6 Commits

63 changed files with 3065 additions and 559 deletions

View File

@@ -1,7 +1,9 @@
import js from "@eslint/js"; import js from "@eslint/js";
import tseslint from "typescript-eslint";
export default [ export default [
js.configs.recommended, js.configs.recommended,
...tseslint.configs.recommended,
{ {
files: ["**/*.ts", "**/*.tsx"], files: ["**/*.ts", "**/*.tsx"],
languageOptions: { languageOptions: {
@@ -9,7 +11,8 @@ export default [
sourceType: "module", sourceType: "module",
}, },
rules: { rules: {
"no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }], "no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
}, },
}, },
{ {

View File

@@ -21,6 +21,7 @@
"prettier": "^3.6.2", "prettier": "^3.6.2",
"storybook": "8.6.14", "storybook": "8.6.14",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.57.0",
"vitest": "^3.2.4" "vitest": "^3.2.4"
} }
} }

View File

@@ -77,12 +77,40 @@ By default, tags are rendered as plain styled text (not links).
## Angular usage ## Angular usage
Tokenization helper:
```ts ```ts
import { createAngularContentTokens } from "@hublib-web/content-suggestions/angular"; import { createAngularContentTokens } from "@hublib-web/content-suggestions/angular";
const tokens = createAngularContentTokens(text); const tokens = createAngularContentTokens(text);
``` ```
Ready-to-use UI renderer (React-like props API):
```ts
import { AngularContentTextWithSuggestionsRenderer } from "@hublib-web/content-suggestions/angular";
const renderer = new AngularContentTextWithSuggestionsRenderer();
renderer.attach(containerElement, {
text,
weight: "normal",
ellipsis: { count: 180, expandable: true },
blur: false,
onView: () => {
// analytics
},
});
```
Title variant with defaults (`weight: "bold"`, `ellipsis: { rows: 2 }`):
```ts
import { AngularContentTitleWithSuggestionsRenderer } from "@hublib-web/content-suggestions/angular";
const titleRenderer = new AngularContentTitleWithSuggestionsRenderer();
titleRenderer.attach(titleContainer, { text: title });
```
## Storybook (dev/design system) ## Storybook (dev/design system)
Run from repository root: Run from repository root:

View File

@@ -76,6 +76,41 @@ var findAllEntities = (content) => {
}; };
// src/angular/index.ts // src/angular/index.ts
var LINK_COLOR = "#1677ff";
var READ_MORE_TEXT = "\u0427\u0438\u0442\u0430\u0442\u044C \u043F\u043E\u043B\u043D\u043E\u0441\u0442\u044C\u044E";
var toKebabCase = (value) => value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
var applyStyleObject = (element, styles) => {
if (!styles) {
return;
}
for (const [key, rawValue] of Object.entries(styles)) {
if (rawValue === null || rawValue === void 0) {
continue;
}
const styleValue = typeof rawValue === "number" ? `${rawValue}px` : String(rawValue);
if (key.startsWith("--")) {
element.style.setProperty(key, styleValue);
continue;
}
const cssKey = key.includes("-") ? key : toKebabCase(key);
element.style.setProperty(cssKey, styleValue);
}
};
var toNode = (value) => {
if (value === null || value === void 0) {
return null;
}
if (value instanceof Node) {
return value;
}
return document.createTextNode(String(value));
};
var resolveEllipsisSymbol = (symbol, expanded) => {
if (typeof symbol === "function") {
return symbol(expanded);
}
return symbol ?? READ_MORE_TEXT;
};
var buildAngularTagHref = (entity) => { var buildAngularTagHref = (entity) => {
return `/search/?query=${encodeURIComponent(entity.tag.toLowerCase())}`; return `/search/?query=${encodeURIComponent(entity.tag.toLowerCase())}`;
}; };
@@ -133,9 +168,328 @@ var AngularContentSuggestionsAdapter = class {
}; };
} }
}; };
var AngularContentTextRenderer = class {
host = null;
props = {};
expanded = false;
viewed = false;
hostInsideView = false;
observer = null;
attach(host, props = {}) {
this.destroy();
this.host = host;
this.props = { ...props };
this.expanded = false;
this.viewed = false;
this.hostInsideView = false;
this.initObserver();
this.render();
return this.getState();
}
update(nextProps) {
this.props = {
...this.props,
...nextProps
};
this.render();
return this.getState();
}
destroy() {
if (this.observer && this.host) {
this.observer.unobserve(this.host);
this.observer.disconnect();
}
this.observer = null;
if (this.host) {
this.host.innerHTML = "";
}
this.host = null;
this.props = {};
this.expanded = false;
this.viewed = false;
this.hostInsideView = false;
}
getState() {
return {
props: { ...this.props },
snapshot: this.createSnapshot(),
expanded: this.getMergedExpanded(this.resolveEllipsisConfig(), this.getText())
};
}
getText() {
return this.props.text ?? "";
}
createSnapshot() {
const text = this.getText();
const entities = findAllEntities(text);
const tokens = createAngularContentTokens(text);
return {
text,
entities,
tokens
};
}
resolveEllipsisConfig() {
const ellipsis = this.props.ellipsis;
if (!ellipsis || typeof ellipsis !== "object") {
return null;
}
return ellipsis;
}
getMergedExpanded(ellipsisConfig, text) {
const controlledExpanded = ellipsisConfig && typeof ellipsisConfig.expanded === "boolean" ? ellipsisConfig.expanded : void 0;
if (controlledExpanded !== void 0) {
return controlledExpanded;
}
if (ellipsisConfig && "count" in ellipsisConfig) {
const count = ellipsisConfig.count ?? 0;
if (count <= 0 || text.length <= count) {
return true;
}
}
return this.expanded;
}
createDefaultMentionNode(entity) {
const span = document.createElement("span");
span.style.color = LINK_COLOR;
span.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
span.textContent = entity.displayText;
return span;
}
createDefaultTagNode(entity) {
const span = document.createElement("span");
span.style.color = LINK_COLOR;
span.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
span.textContent = entity.text;
return span;
}
createDefaultLinkNode(entity) {
const anchor = document.createElement("a");
anchor.href = entity.url;
anchor.target = "_blank";
anchor.referrerPolicy = "no-referrer";
anchor.style.color = LINK_COLOR;
anchor.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
anchor.textContent = entity.text;
return anchor;
}
renderEntity(entity, index) {
if (entity.type === "mention") {
const customNode2 = this.props.renderMention?.(entity, index);
return toNode(customNode2) ?? this.createDefaultMentionNode(entity);
}
if (entity.type === "tag") {
const customNode2 = this.props.renderTag?.(entity, index);
return toNode(customNode2) ?? this.createDefaultTagNode(entity);
}
const customNode = this.props.renderLink?.(entity, index);
return toNode(customNode) ?? this.createDefaultLinkNode(entity);
}
buildTextNodes(text, entities, upto = null) {
let lastIndex = 0;
const nodes = [];
for (const [index, entity] of entities.entries()) {
if (upto !== null && entity.start >= upto) {
break;
}
const textEnd = upto !== null ? Math.min(entity.start, upto) : entity.start;
if (entity.start > lastIndex && lastIndex < textEnd) {
nodes.push(document.createTextNode(text.slice(lastIndex, textEnd)));
}
if (upto === null || entity.end <= upto) {
const entityNode = this.renderEntity(entity, index);
if (entityNode) {
nodes.push(entityNode);
}
}
lastIndex = entity.end;
}
if (upto === null) {
if (lastIndex < text.length) {
nodes.push(document.createTextNode(text.slice(lastIndex)));
}
} else if (lastIndex < upto) {
nodes.push(document.createTextNode(text.slice(lastIndex, upto)));
}
return nodes;
}
applyBaseParagraphStyle(element) {
element.style.whiteSpace = "pre-wrap";
element.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
element.style.setProperty("-webkit-touch-callout", "default");
element.style.setProperty("-webkit-user-select", "text");
element.style.setProperty("-khtml-user-select", "text");
element.style.setProperty("-moz-user-select", "text");
element.style.setProperty("-ms-user-select", "text");
element.style.setProperty("user-select", "text");
if (this.props.blur) {
element.style.filter = "blur(3px)";
element.style.setProperty("-webkit-user-select", "none");
element.style.setProperty("-khtml-user-select", "none");
element.style.setProperty("-moz-user-select", "none");
element.style.setProperty("-ms-user-select", "none");
element.style.setProperty("user-select", "none");
element.style.pointerEvents = "none";
}
applyStyleObject(element, this.props.style);
}
buildReadMoreButton(symbol) {
const button = document.createElement("button");
button.type = "button";
button.textContent = resolveEllipsisSymbol(symbol, this.expanded);
button.style.border = "0";
button.style.background = "none";
button.style.padding = "0";
button.style.marginLeft = "6px";
button.style.cursor = "pointer";
button.style.color = LINK_COLOR;
button.style.fontWeight = "700";
button.onclick = (event) => {
event.preventDefault();
event.stopPropagation();
this.handleExpand();
};
return button;
}
handleExpand() {
const ellipsisConfig = this.resolveEllipsisConfig();
if (!ellipsisConfig) {
return;
}
this.expanded = true;
ellipsisConfig.onExpand?.(true);
this.render();
}
computeEntitySafeCutoff(count, entities) {
let cutoff = count;
let extended = true;
while (extended) {
extended = false;
for (const entity of entities) {
if (entity.start < cutoff && entity.end > cutoff) {
cutoff = entity.end;
extended = true;
}
}
}
return cutoff;
}
hasVerticalOverflow(element) {
return element.scrollHeight - element.clientHeight > 1;
}
render() {
if (!this.host) {
return;
}
const text = this.getText();
const entities = findAllEntities(text);
const ellipsisConfig = this.resolveEllipsisConfig();
const mergedExpanded = this.getMergedExpanded(ellipsisConfig, text);
const wrapper = document.createElement("div");
const paragraph = document.createElement("div");
if (this.props.className) {
paragraph.className = this.props.className;
}
this.applyBaseParagraphStyle(paragraph);
if (ellipsisConfig && "count" in ellipsisConfig) {
const count = ellipsisConfig.count ?? 0;
const shouldTruncate = !mergedExpanded && count > 0 && text.length > count;
if (shouldTruncate) {
const cutoff = this.computeEntitySafeCutoff(count, entities);
const nodes = this.buildTextNodes(text, entities, cutoff);
paragraph.append(...nodes);
paragraph.append(document.createTextNode("\u2026"));
if (ellipsisConfig.expandable) {
paragraph.append(this.buildReadMoreButton(ellipsisConfig.symbol));
}
} else {
paragraph.append(...this.buildTextNodes(text, entities));
}
} else {
paragraph.append(...this.buildTextNodes(text, entities));
if (ellipsisConfig && "rows" in ellipsisConfig && !mergedExpanded) {
paragraph.style.display = "-webkit-box";
paragraph.style.setProperty("-webkit-box-orient", "vertical");
paragraph.style.setProperty("-webkit-line-clamp", String(ellipsisConfig.rows));
paragraph.style.overflow = "hidden";
wrapper.append(paragraph);
this.host.replaceChildren(wrapper);
if (ellipsisConfig.expandable && this.hasVerticalOverflow(paragraph)) {
wrapper.append(this.buildReadMoreButton(ellipsisConfig.symbol));
}
this.emitOnViewIfNeeded(mergedExpanded);
return;
}
}
wrapper.append(paragraph);
this.host.replaceChildren(wrapper);
this.emitOnViewIfNeeded(mergedExpanded);
}
initObserver() {
if (!this.host) {
return;
}
if (typeof IntersectionObserver === "undefined") {
this.hostInsideView = true;
return;
}
this.observer = new IntersectionObserver(
(entries) => {
const entry = entries[0];
if (!entry) {
return;
}
if (entry.isIntersecting && !this.hostInsideView) {
this.hostInsideView = true;
const ellipsisConfig = this.resolveEllipsisConfig();
const mergedExpanded = this.getMergedExpanded(ellipsisConfig, this.getText());
this.emitOnViewIfNeeded(mergedExpanded);
}
},
{ threshold: 0.5 }
);
this.observer.observe(this.host);
}
emitOnViewIfNeeded(mergedExpanded) {
if (!mergedExpanded || this.viewed || !this.hostInsideView) {
return;
}
this.viewed = true;
this.props.onView?.();
}
};
var AngularContentTextWithSuggestionsRenderer = class extends AngularContentTextRenderer {
};
var AngularContentTitleWithSuggestionsRenderer = class {
renderer = new AngularContentTextWithSuggestionsRenderer();
attach(host, props = {}) {
return this.renderer.attach(host, this.normalizeProps(props));
}
update(props) {
return this.renderer.update(this.normalizeProps(props));
}
destroy() {
this.renderer.destroy();
}
getState() {
return this.renderer.getState();
}
normalizeProps(props) {
return {
...props,
weight: "bold",
blur: props.blur ?? false,
ellipsis: props.ellipsis === void 0 ? { rows: 2 } : props.ellipsis
};
}
};
exports.AngularContentSuggestionsAdapter = AngularContentSuggestionsAdapter; exports.AngularContentSuggestionsAdapter = AngularContentSuggestionsAdapter;
exports.AngularContentTextRenderer = AngularContentTextRenderer;
exports.AngularContentTextWithSuggestionsRenderer = AngularContentTextWithSuggestionsRenderer;
exports.AngularContentTitleWithSuggestionsRenderer = AngularContentTitleWithSuggestionsRenderer;
exports.buildAngularTagHref = buildAngularTagHref; exports.buildAngularTagHref = buildAngularTagHref;
exports.createAngularContentTokens = createAngularContentTokens; exports.createAngularContentTokens = createAngularContentTokens;
exports.toKebabCase = toKebabCase;
//# sourceMappingURL=index.cjs.map //# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map //# sourceMappingURL=index.cjs.map

File diff suppressed because one or more lines are too long

View File

@@ -24,10 +24,95 @@ interface AngularContentSnapshot {
entities: ContentEntity[]; entities: ContentEntity[];
tokens: AngularContentToken[]; tokens: AngularContentToken[];
} }
type AngularEllipsisSymbol = string | ((expanded: boolean) => string);
type AngularCountEllipsisConfig = {
count: number;
rows?: never;
expandable?: boolean;
expanded?: boolean;
symbol?: AngularEllipsisSymbol;
onExpand?: (expanded: boolean) => void;
};
type AngularRowsEllipsisConfig = {
rows: number;
count?: never;
expandable?: boolean;
expanded?: boolean;
symbol?: AngularEllipsisSymbol;
onExpand?: (expanded: boolean) => void;
};
type AngularContentEllipsisConfig = AngularCountEllipsisConfig | AngularRowsEllipsisConfig | false;
type AngularRenderResult = Node | string | number | null | undefined;
type AngularMentionRenderer = (entity: MentionEntity, index: number) => AngularRenderResult;
type AngularTagRenderer = (entity: TagEntity, index: number) => AngularRenderResult;
type AngularLinkRenderer = (entity: LinkEntity, index: number) => AngularRenderResult;
interface AngularContentTextProps {
className?: string;
weight?: "normal" | "bold";
text?: string | null;
ellipsis?: AngularContentEllipsisConfig;
blur?: boolean;
style?: Record<string, string | number> | null;
onView?: () => void;
renderMention?: AngularMentionRenderer;
renderTag?: AngularTagRenderer;
renderLink?: AngularLinkRenderer;
}
type AngularContentTextWithSuggestionsProps = Omit<AngularContentTextProps, "renderMention" | "renderTag"> & {
renderMention?: AngularMentionRenderer;
renderTag?: AngularTagRenderer;
};
type AngularContentTitleWithSuggestionsProps = Omit<AngularContentTextWithSuggestionsProps, "weight">;
interface AngularContentTextRendererState {
props: AngularContentTextProps;
snapshot: AngularContentSnapshot;
expanded: boolean;
}
declare const toKebabCase: (value: string) => string;
declare const buildAngularTagHref: (entity: TagEntity) => string; declare const buildAngularTagHref: (entity: TagEntity) => string;
declare const createAngularContentTokens: (inputText: string | null | undefined) => AngularContentToken[]; declare const createAngularContentTokens: (inputText: string | null | undefined) => AngularContentToken[];
declare class AngularContentSuggestionsAdapter { declare class AngularContentSuggestionsAdapter {
snapshot(inputText: string | null | undefined): AngularContentSnapshot; snapshot(inputText: string | null | undefined): AngularContentSnapshot;
} }
declare class AngularContentTextRenderer {
private host;
private props;
private expanded;
private viewed;
private hostInsideView;
private observer;
attach(host: HTMLElement, props?: AngularContentTextProps): AngularContentTextRendererState;
update(nextProps: AngularContentTextProps): AngularContentTextRendererState;
destroy(): void;
getState(): AngularContentTextRendererState;
private getText;
private createSnapshot;
private resolveEllipsisConfig;
private getMergedExpanded;
private createDefaultMentionNode;
private createDefaultTagNode;
private createDefaultLinkNode;
private renderEntity;
private buildTextNodes;
private applyBaseParagraphStyle;
private buildReadMoreButton;
private handleExpand;
private computeEntitySafeCutoff;
private hasVerticalOverflow;
private render;
private initObserver;
private emitOnViewIfNeeded;
}
declare class AngularContentTextWithSuggestionsRenderer extends AngularContentTextRenderer {
}
declare class AngularContentTitleWithSuggestionsRenderer {
private readonly renderer;
attach(host: HTMLElement, props?: AngularContentTitleWithSuggestionsProps): AngularContentTextRendererState;
update(props: AngularContentTitleWithSuggestionsProps): AngularContentTextRendererState;
destroy(): void;
getState(): AngularContentTextRendererState;
private normalizeProps;
}
export { type AngularContentSnapshot, AngularContentSuggestionsAdapter, type AngularContentToken, type AngularLinkToken, type AngularMentionToken, type AngularTagToken, type AngularTextToken, buildAngularTagHref, createAngularContentTokens }; export { type AngularContentEllipsisConfig, type AngularContentSnapshot, AngularContentSuggestionsAdapter, type AngularContentTextProps, AngularContentTextRenderer, type AngularContentTextRendererState, type AngularContentTextWithSuggestionsProps, AngularContentTextWithSuggestionsRenderer, type AngularContentTitleWithSuggestionsProps, AngularContentTitleWithSuggestionsRenderer, type AngularContentToken, type AngularCountEllipsisConfig, type AngularEllipsisSymbol, type AngularLinkRenderer, type AngularLinkToken, type AngularMentionRenderer, type AngularMentionToken, type AngularRenderResult, type AngularRowsEllipsisConfig, type AngularTagRenderer, type AngularTagToken, type AngularTextToken, buildAngularTagHref, createAngularContentTokens, toKebabCase };

View File

@@ -24,10 +24,95 @@ interface AngularContentSnapshot {
entities: ContentEntity[]; entities: ContentEntity[];
tokens: AngularContentToken[]; tokens: AngularContentToken[];
} }
type AngularEllipsisSymbol = string | ((expanded: boolean) => string);
type AngularCountEllipsisConfig = {
count: number;
rows?: never;
expandable?: boolean;
expanded?: boolean;
symbol?: AngularEllipsisSymbol;
onExpand?: (expanded: boolean) => void;
};
type AngularRowsEllipsisConfig = {
rows: number;
count?: never;
expandable?: boolean;
expanded?: boolean;
symbol?: AngularEllipsisSymbol;
onExpand?: (expanded: boolean) => void;
};
type AngularContentEllipsisConfig = AngularCountEllipsisConfig | AngularRowsEllipsisConfig | false;
type AngularRenderResult = Node | string | number | null | undefined;
type AngularMentionRenderer = (entity: MentionEntity, index: number) => AngularRenderResult;
type AngularTagRenderer = (entity: TagEntity, index: number) => AngularRenderResult;
type AngularLinkRenderer = (entity: LinkEntity, index: number) => AngularRenderResult;
interface AngularContentTextProps {
className?: string;
weight?: "normal" | "bold";
text?: string | null;
ellipsis?: AngularContentEllipsisConfig;
blur?: boolean;
style?: Record<string, string | number> | null;
onView?: () => void;
renderMention?: AngularMentionRenderer;
renderTag?: AngularTagRenderer;
renderLink?: AngularLinkRenderer;
}
type AngularContentTextWithSuggestionsProps = Omit<AngularContentTextProps, "renderMention" | "renderTag"> & {
renderMention?: AngularMentionRenderer;
renderTag?: AngularTagRenderer;
};
type AngularContentTitleWithSuggestionsProps = Omit<AngularContentTextWithSuggestionsProps, "weight">;
interface AngularContentTextRendererState {
props: AngularContentTextProps;
snapshot: AngularContentSnapshot;
expanded: boolean;
}
declare const toKebabCase: (value: string) => string;
declare const buildAngularTagHref: (entity: TagEntity) => string; declare const buildAngularTagHref: (entity: TagEntity) => string;
declare const createAngularContentTokens: (inputText: string | null | undefined) => AngularContentToken[]; declare const createAngularContentTokens: (inputText: string | null | undefined) => AngularContentToken[];
declare class AngularContentSuggestionsAdapter { declare class AngularContentSuggestionsAdapter {
snapshot(inputText: string | null | undefined): AngularContentSnapshot; snapshot(inputText: string | null | undefined): AngularContentSnapshot;
} }
declare class AngularContentTextRenderer {
private host;
private props;
private expanded;
private viewed;
private hostInsideView;
private observer;
attach(host: HTMLElement, props?: AngularContentTextProps): AngularContentTextRendererState;
update(nextProps: AngularContentTextProps): AngularContentTextRendererState;
destroy(): void;
getState(): AngularContentTextRendererState;
private getText;
private createSnapshot;
private resolveEllipsisConfig;
private getMergedExpanded;
private createDefaultMentionNode;
private createDefaultTagNode;
private createDefaultLinkNode;
private renderEntity;
private buildTextNodes;
private applyBaseParagraphStyle;
private buildReadMoreButton;
private handleExpand;
private computeEntitySafeCutoff;
private hasVerticalOverflow;
private render;
private initObserver;
private emitOnViewIfNeeded;
}
declare class AngularContentTextWithSuggestionsRenderer extends AngularContentTextRenderer {
}
declare class AngularContentTitleWithSuggestionsRenderer {
private readonly renderer;
attach(host: HTMLElement, props?: AngularContentTitleWithSuggestionsProps): AngularContentTextRendererState;
update(props: AngularContentTitleWithSuggestionsProps): AngularContentTextRendererState;
destroy(): void;
getState(): AngularContentTextRendererState;
private normalizeProps;
}
export { type AngularContentSnapshot, AngularContentSuggestionsAdapter, type AngularContentToken, type AngularLinkToken, type AngularMentionToken, type AngularTagToken, type AngularTextToken, buildAngularTagHref, createAngularContentTokens }; export { type AngularContentEllipsisConfig, type AngularContentSnapshot, AngularContentSuggestionsAdapter, type AngularContentTextProps, AngularContentTextRenderer, type AngularContentTextRendererState, type AngularContentTextWithSuggestionsProps, AngularContentTextWithSuggestionsRenderer, type AngularContentTitleWithSuggestionsProps, AngularContentTitleWithSuggestionsRenderer, type AngularContentToken, type AngularCountEllipsisConfig, type AngularEllipsisSymbol, type AngularLinkRenderer, type AngularLinkToken, type AngularMentionRenderer, type AngularMentionToken, type AngularRenderResult, type AngularRowsEllipsisConfig, type AngularTagRenderer, type AngularTagToken, type AngularTextToken, buildAngularTagHref, createAngularContentTokens, toKebabCase };

View File

@@ -74,6 +74,41 @@ var findAllEntities = (content) => {
}; };
// src/angular/index.ts // src/angular/index.ts
var LINK_COLOR = "#1677ff";
var READ_MORE_TEXT = "\u0427\u0438\u0442\u0430\u0442\u044C \u043F\u043E\u043B\u043D\u043E\u0441\u0442\u044C\u044E";
var toKebabCase = (value) => value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
var applyStyleObject = (element, styles) => {
if (!styles) {
return;
}
for (const [key, rawValue] of Object.entries(styles)) {
if (rawValue === null || rawValue === void 0) {
continue;
}
const styleValue = typeof rawValue === "number" ? `${rawValue}px` : String(rawValue);
if (key.startsWith("--")) {
element.style.setProperty(key, styleValue);
continue;
}
const cssKey = key.includes("-") ? key : toKebabCase(key);
element.style.setProperty(cssKey, styleValue);
}
};
var toNode = (value) => {
if (value === null || value === void 0) {
return null;
}
if (value instanceof Node) {
return value;
}
return document.createTextNode(String(value));
};
var resolveEllipsisSymbol = (symbol, expanded) => {
if (typeof symbol === "function") {
return symbol(expanded);
}
return symbol ?? READ_MORE_TEXT;
};
var buildAngularTagHref = (entity) => { var buildAngularTagHref = (entity) => {
return `/search/?query=${encodeURIComponent(entity.tag.toLowerCase())}`; return `/search/?query=${encodeURIComponent(entity.tag.toLowerCase())}`;
}; };
@@ -131,7 +166,322 @@ var AngularContentSuggestionsAdapter = class {
}; };
} }
}; };
var AngularContentTextRenderer = class {
host = null;
props = {};
expanded = false;
viewed = false;
hostInsideView = false;
observer = null;
attach(host, props = {}) {
this.destroy();
this.host = host;
this.props = { ...props };
this.expanded = false;
this.viewed = false;
this.hostInsideView = false;
this.initObserver();
this.render();
return this.getState();
}
update(nextProps) {
this.props = {
...this.props,
...nextProps
};
this.render();
return this.getState();
}
destroy() {
if (this.observer && this.host) {
this.observer.unobserve(this.host);
this.observer.disconnect();
}
this.observer = null;
if (this.host) {
this.host.innerHTML = "";
}
this.host = null;
this.props = {};
this.expanded = false;
this.viewed = false;
this.hostInsideView = false;
}
getState() {
return {
props: { ...this.props },
snapshot: this.createSnapshot(),
expanded: this.getMergedExpanded(this.resolveEllipsisConfig(), this.getText())
};
}
getText() {
return this.props.text ?? "";
}
createSnapshot() {
const text = this.getText();
const entities = findAllEntities(text);
const tokens = createAngularContentTokens(text);
return {
text,
entities,
tokens
};
}
resolveEllipsisConfig() {
const ellipsis = this.props.ellipsis;
if (!ellipsis || typeof ellipsis !== "object") {
return null;
}
return ellipsis;
}
getMergedExpanded(ellipsisConfig, text) {
const controlledExpanded = ellipsisConfig && typeof ellipsisConfig.expanded === "boolean" ? ellipsisConfig.expanded : void 0;
if (controlledExpanded !== void 0) {
return controlledExpanded;
}
if (ellipsisConfig && "count" in ellipsisConfig) {
const count = ellipsisConfig.count ?? 0;
if (count <= 0 || text.length <= count) {
return true;
}
}
return this.expanded;
}
createDefaultMentionNode(entity) {
const span = document.createElement("span");
span.style.color = LINK_COLOR;
span.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
span.textContent = entity.displayText;
return span;
}
createDefaultTagNode(entity) {
const span = document.createElement("span");
span.style.color = LINK_COLOR;
span.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
span.textContent = entity.text;
return span;
}
createDefaultLinkNode(entity) {
const anchor = document.createElement("a");
anchor.href = entity.url;
anchor.target = "_blank";
anchor.referrerPolicy = "no-referrer";
anchor.style.color = LINK_COLOR;
anchor.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
anchor.textContent = entity.text;
return anchor;
}
renderEntity(entity, index) {
if (entity.type === "mention") {
const customNode2 = this.props.renderMention?.(entity, index);
return toNode(customNode2) ?? this.createDefaultMentionNode(entity);
}
if (entity.type === "tag") {
const customNode2 = this.props.renderTag?.(entity, index);
return toNode(customNode2) ?? this.createDefaultTagNode(entity);
}
const customNode = this.props.renderLink?.(entity, index);
return toNode(customNode) ?? this.createDefaultLinkNode(entity);
}
buildTextNodes(text, entities, upto = null) {
let lastIndex = 0;
const nodes = [];
for (const [index, entity] of entities.entries()) {
if (upto !== null && entity.start >= upto) {
break;
}
const textEnd = upto !== null ? Math.min(entity.start, upto) : entity.start;
if (entity.start > lastIndex && lastIndex < textEnd) {
nodes.push(document.createTextNode(text.slice(lastIndex, textEnd)));
}
if (upto === null || entity.end <= upto) {
const entityNode = this.renderEntity(entity, index);
if (entityNode) {
nodes.push(entityNode);
}
}
lastIndex = entity.end;
}
if (upto === null) {
if (lastIndex < text.length) {
nodes.push(document.createTextNode(text.slice(lastIndex)));
}
} else if (lastIndex < upto) {
nodes.push(document.createTextNode(text.slice(lastIndex, upto)));
}
return nodes;
}
applyBaseParagraphStyle(element) {
element.style.whiteSpace = "pre-wrap";
element.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
element.style.setProperty("-webkit-touch-callout", "default");
element.style.setProperty("-webkit-user-select", "text");
element.style.setProperty("-khtml-user-select", "text");
element.style.setProperty("-moz-user-select", "text");
element.style.setProperty("-ms-user-select", "text");
element.style.setProperty("user-select", "text");
if (this.props.blur) {
element.style.filter = "blur(3px)";
element.style.setProperty("-webkit-user-select", "none");
element.style.setProperty("-khtml-user-select", "none");
element.style.setProperty("-moz-user-select", "none");
element.style.setProperty("-ms-user-select", "none");
element.style.setProperty("user-select", "none");
element.style.pointerEvents = "none";
}
applyStyleObject(element, this.props.style);
}
buildReadMoreButton(symbol) {
const button = document.createElement("button");
button.type = "button";
button.textContent = resolveEllipsisSymbol(symbol, this.expanded);
button.style.border = "0";
button.style.background = "none";
button.style.padding = "0";
button.style.marginLeft = "6px";
button.style.cursor = "pointer";
button.style.color = LINK_COLOR;
button.style.fontWeight = "700";
button.onclick = (event) => {
event.preventDefault();
event.stopPropagation();
this.handleExpand();
};
return button;
}
handleExpand() {
const ellipsisConfig = this.resolveEllipsisConfig();
if (!ellipsisConfig) {
return;
}
this.expanded = true;
ellipsisConfig.onExpand?.(true);
this.render();
}
computeEntitySafeCutoff(count, entities) {
let cutoff = count;
let extended = true;
while (extended) {
extended = false;
for (const entity of entities) {
if (entity.start < cutoff && entity.end > cutoff) {
cutoff = entity.end;
extended = true;
}
}
}
return cutoff;
}
hasVerticalOverflow(element) {
return element.scrollHeight - element.clientHeight > 1;
}
render() {
if (!this.host) {
return;
}
const text = this.getText();
const entities = findAllEntities(text);
const ellipsisConfig = this.resolveEllipsisConfig();
const mergedExpanded = this.getMergedExpanded(ellipsisConfig, text);
const wrapper = document.createElement("div");
const paragraph = document.createElement("div");
if (this.props.className) {
paragraph.className = this.props.className;
}
this.applyBaseParagraphStyle(paragraph);
if (ellipsisConfig && "count" in ellipsisConfig) {
const count = ellipsisConfig.count ?? 0;
const shouldTruncate = !mergedExpanded && count > 0 && text.length > count;
if (shouldTruncate) {
const cutoff = this.computeEntitySafeCutoff(count, entities);
const nodes = this.buildTextNodes(text, entities, cutoff);
paragraph.append(...nodes);
paragraph.append(document.createTextNode("\u2026"));
if (ellipsisConfig.expandable) {
paragraph.append(this.buildReadMoreButton(ellipsisConfig.symbol));
}
} else {
paragraph.append(...this.buildTextNodes(text, entities));
}
} else {
paragraph.append(...this.buildTextNodes(text, entities));
if (ellipsisConfig && "rows" in ellipsisConfig && !mergedExpanded) {
paragraph.style.display = "-webkit-box";
paragraph.style.setProperty("-webkit-box-orient", "vertical");
paragraph.style.setProperty("-webkit-line-clamp", String(ellipsisConfig.rows));
paragraph.style.overflow = "hidden";
wrapper.append(paragraph);
this.host.replaceChildren(wrapper);
if (ellipsisConfig.expandable && this.hasVerticalOverflow(paragraph)) {
wrapper.append(this.buildReadMoreButton(ellipsisConfig.symbol));
}
this.emitOnViewIfNeeded(mergedExpanded);
return;
}
}
wrapper.append(paragraph);
this.host.replaceChildren(wrapper);
this.emitOnViewIfNeeded(mergedExpanded);
}
initObserver() {
if (!this.host) {
return;
}
if (typeof IntersectionObserver === "undefined") {
this.hostInsideView = true;
return;
}
this.observer = new IntersectionObserver(
(entries) => {
const entry = entries[0];
if (!entry) {
return;
}
if (entry.isIntersecting && !this.hostInsideView) {
this.hostInsideView = true;
const ellipsisConfig = this.resolveEllipsisConfig();
const mergedExpanded = this.getMergedExpanded(ellipsisConfig, this.getText());
this.emitOnViewIfNeeded(mergedExpanded);
}
},
{ threshold: 0.5 }
);
this.observer.observe(this.host);
}
emitOnViewIfNeeded(mergedExpanded) {
if (!mergedExpanded || this.viewed || !this.hostInsideView) {
return;
}
this.viewed = true;
this.props.onView?.();
}
};
var AngularContentTextWithSuggestionsRenderer = class extends AngularContentTextRenderer {
};
var AngularContentTitleWithSuggestionsRenderer = class {
renderer = new AngularContentTextWithSuggestionsRenderer();
attach(host, props = {}) {
return this.renderer.attach(host, this.normalizeProps(props));
}
update(props) {
return this.renderer.update(this.normalizeProps(props));
}
destroy() {
this.renderer.destroy();
}
getState() {
return this.renderer.getState();
}
normalizeProps(props) {
return {
...props,
weight: "bold",
blur: props.blur ?? false,
ellipsis: props.ellipsis === void 0 ? { rows: 2 } : props.ellipsis
};
}
};
export { AngularContentSuggestionsAdapter, buildAngularTagHref, createAngularContentTokens }; export { AngularContentSuggestionsAdapter, AngularContentTextRenderer, AngularContentTextWithSuggestionsRenderer, AngularContentTitleWithSuggestionsRenderer, buildAngularTagHref, createAngularContentTokens, toKebabCase };
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{ {
"name": "@hublib-web/content-suggestions", "name": "@hublib-web/content-suggestions",
"version": "0.1.0", "version": "0.1.2",
"description": "Content text/title with mentions, tags and links for React and Angular", "description": "Content text/title with mentions, tags and links for React and Angular",
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",

View File

@@ -36,10 +36,140 @@ export interface AngularContentSnapshot {
tokens: AngularContentToken[]; tokens: AngularContentToken[];
} }
export const buildAngularTagHref = (entity: TagEntity): string => { export type AngularEllipsisSymbol = string | ((expanded: boolean) => string);
export type AngularCountEllipsisConfig = {
count: number;
rows?: never;
expandable?: boolean;
expanded?: boolean;
symbol?: AngularEllipsisSymbol;
onExpand?: (expanded: boolean) => void;
};
export type AngularRowsEllipsisConfig = {
rows: number;
count?: never;
expandable?: boolean;
expanded?: boolean;
symbol?: AngularEllipsisSymbol;
onExpand?: (expanded: boolean) => void;
};
export type AngularContentEllipsisConfig =
| AngularCountEllipsisConfig
| AngularRowsEllipsisConfig
| false;
export type AngularRenderResult = Node | string | number | null | undefined;
export type AngularMentionRenderer = (
entity: MentionEntity,
index: number,
) => AngularRenderResult;
export type AngularTagRenderer = (
entity: TagEntity,
index: number,
) => AngularRenderResult;
export type AngularLinkRenderer = (
entity: LinkEntity,
index: number,
) => AngularRenderResult;
export interface AngularContentTextProps {
className?: string;
weight?: "normal" | "bold";
text?: string | null;
ellipsis?: AngularContentEllipsisConfig;
blur?: boolean;
style?: Record<string, string | number> | null;
onView?: () => void;
renderMention?: AngularMentionRenderer;
renderTag?: AngularTagRenderer;
renderLink?: AngularLinkRenderer;
}
export type AngularContentTextWithSuggestionsProps = Omit<
AngularContentTextProps,
"renderMention" | "renderTag"
> & {
renderMention?: AngularMentionRenderer;
renderTag?: AngularTagRenderer;
};
export type AngularContentTitleWithSuggestionsProps = Omit<
AngularContentTextWithSuggestionsProps,
"weight"
>;
export interface AngularContentTextRendererState {
props: AngularContentTextProps;
snapshot: AngularContentSnapshot;
expanded: boolean;
}
const LINK_COLOR = "#1677ff";
const READ_MORE_TEXT = "Читать полностью";
const toKebabCase = (value: string) => value.replace(/[A-Z]/g, char => `-${char.toLowerCase()}`);
const applyStyleObject = (
element: HTMLElement,
styles?: Record<string, string | number> | null,
) => {
if (!styles) {
return;
}
for (const [key, rawValue] of Object.entries(styles)) {
if (rawValue === null || rawValue === undefined) {
continue;
}
const styleValue =
typeof rawValue === "number" ? `${rawValue}px` : String(rawValue);
if (key.startsWith("--")) {
element.style.setProperty(key, styleValue);
continue;
}
const cssKey = key.includes("-") ? key : toKebabCase(key);
element.style.setProperty(cssKey, styleValue);
}
};
const toNode = (value: AngularRenderResult): Node | null => {
if (value === null || value === undefined) {
return null;
}
if (value instanceof Node) {
return value;
}
return document.createTextNode(String(value));
};
const resolveEllipsisSymbol = (
symbol: AngularEllipsisSymbol | undefined,
expanded: boolean,
): string => {
if (typeof symbol === "function") {
return symbol(expanded);
}
return symbol ?? READ_MORE_TEXT;
};
const buildAngularTagHref = (entity: TagEntity): string => {
return `/search/?query=${encodeURIComponent(entity.tag.toLowerCase())}`; return `/search/?query=${encodeURIComponent(entity.tag.toLowerCase())}`;
}; };
export { buildAngularTagHref };
export const createAngularContentTokens = ( export const createAngularContentTokens = (
inputText: string | null | undefined, inputText: string | null | undefined,
): AngularContentToken[] => { ): AngularContentToken[] => {
@@ -104,3 +234,417 @@ export class AngularContentSuggestionsAdapter {
}; };
} }
} }
export class AngularContentTextRenderer {
private host: HTMLElement | null = null;
private props: AngularContentTextProps = {};
private expanded = false;
private viewed = false;
private hostInsideView = false;
private observer: IntersectionObserver | null = null;
attach(host: HTMLElement, props: AngularContentTextProps = {}): AngularContentTextRendererState {
this.destroy();
this.host = host;
this.props = { ...props };
this.expanded = false;
this.viewed = false;
this.hostInsideView = false;
this.initObserver();
this.render();
return this.getState();
}
update(nextProps: AngularContentTextProps): AngularContentTextRendererState {
this.props = {
...this.props,
...nextProps,
};
this.render();
return this.getState();
}
destroy(): void {
if (this.observer && this.host) {
this.observer.unobserve(this.host);
this.observer.disconnect();
}
this.observer = null;
if (this.host) {
this.host.innerHTML = "";
}
this.host = null;
this.props = {};
this.expanded = false;
this.viewed = false;
this.hostInsideView = false;
}
getState(): AngularContentTextRendererState {
return {
props: { ...this.props },
snapshot: this.createSnapshot(),
expanded: this.getMergedExpanded(this.resolveEllipsisConfig(), this.getText()),
};
}
private getText(): string {
return this.props.text ?? "";
}
private createSnapshot(): AngularContentSnapshot {
const text = this.getText();
const entities = findAllEntities(text);
const tokens = createAngularContentTokens(text);
return {
text,
entities,
tokens,
};
}
private resolveEllipsisConfig():
| AngularCountEllipsisConfig
| AngularRowsEllipsisConfig
| null {
const ellipsis = this.props.ellipsis;
if (!ellipsis || typeof ellipsis !== "object") {
return null;
}
return ellipsis;
}
private getMergedExpanded(
ellipsisConfig: AngularCountEllipsisConfig | AngularRowsEllipsisConfig | null,
text: string,
): boolean {
const controlledExpanded =
ellipsisConfig && typeof ellipsisConfig.expanded === "boolean"
? ellipsisConfig.expanded
: undefined;
if (controlledExpanded !== undefined) {
return controlledExpanded;
}
if (ellipsisConfig && "count" in ellipsisConfig) {
const count = ellipsisConfig.count ?? 0;
if (count <= 0 || text.length <= count) {
return true;
}
}
return this.expanded;
}
private createDefaultMentionNode(entity: MentionEntity): Node {
const span = document.createElement("span");
span.style.color = LINK_COLOR;
span.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
span.textContent = entity.displayText;
return span;
}
private createDefaultTagNode(entity: TagEntity): Node {
const span = document.createElement("span");
span.style.color = LINK_COLOR;
span.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
span.textContent = entity.text;
return span;
}
private createDefaultLinkNode(entity: LinkEntity): Node {
const anchor = document.createElement("a");
anchor.href = entity.url;
anchor.target = "_blank";
anchor.referrerPolicy = "no-referrer";
anchor.style.color = LINK_COLOR;
anchor.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
anchor.textContent = entity.text;
return anchor;
}
private renderEntity(entity: ContentEntity, index: number): Node | null {
if (entity.type === "mention") {
const customNode = this.props.renderMention?.(entity, index);
return toNode(customNode) ?? this.createDefaultMentionNode(entity);
}
if (entity.type === "tag") {
const customNode = this.props.renderTag?.(entity, index);
return toNode(customNode) ?? this.createDefaultTagNode(entity);
}
const customNode = this.props.renderLink?.(entity, index);
return toNode(customNode) ?? this.createDefaultLinkNode(entity);
}
private buildTextNodes(
text: string,
entities: ContentEntity[],
upto: number | null = null,
): Node[] {
let lastIndex = 0;
const nodes: Node[] = [];
for (const [index, entity] of entities.entries()) {
if (upto !== null && entity.start >= upto) {
break;
}
const textEnd = upto !== null ? Math.min(entity.start, upto) : entity.start;
if (entity.start > lastIndex && lastIndex < textEnd) {
nodes.push(document.createTextNode(text.slice(lastIndex, textEnd)));
}
if (upto === null || entity.end <= upto) {
const entityNode = this.renderEntity(entity, index);
if (entityNode) {
nodes.push(entityNode);
}
}
lastIndex = entity.end;
}
if (upto === null) {
if (lastIndex < text.length) {
nodes.push(document.createTextNode(text.slice(lastIndex)));
}
} else if (lastIndex < upto) {
nodes.push(document.createTextNode(text.slice(lastIndex, upto)));
}
return nodes;
}
private applyBaseParagraphStyle(element: HTMLElement): void {
element.style.whiteSpace = "pre-wrap";
element.style.fontWeight = this.props.weight === "bold" ? "700" : "400";
element.style.setProperty("-webkit-touch-callout", "default");
element.style.setProperty("-webkit-user-select", "text");
element.style.setProperty("-khtml-user-select", "text");
element.style.setProperty("-moz-user-select", "text");
element.style.setProperty("-ms-user-select", "text");
element.style.setProperty("user-select", "text");
if (this.props.blur) {
element.style.filter = "blur(3px)";
element.style.setProperty("-webkit-user-select", "none");
element.style.setProperty("-khtml-user-select", "none");
element.style.setProperty("-moz-user-select", "none");
element.style.setProperty("-ms-user-select", "none");
element.style.setProperty("user-select", "none");
element.style.pointerEvents = "none";
}
applyStyleObject(element, this.props.style);
}
private buildReadMoreButton(symbol: AngularEllipsisSymbol | undefined): HTMLButtonElement {
const button = document.createElement("button");
button.type = "button";
button.textContent = resolveEllipsisSymbol(symbol, this.expanded);
button.style.border = "0";
button.style.background = "none";
button.style.padding = "0";
button.style.marginLeft = "6px";
button.style.cursor = "pointer";
button.style.color = LINK_COLOR;
button.style.fontWeight = "700";
button.onclick = event => {
event.preventDefault();
event.stopPropagation();
this.handleExpand();
};
return button;
}
private handleExpand(): void {
const ellipsisConfig = this.resolveEllipsisConfig();
if (!ellipsisConfig) {
return;
}
this.expanded = true;
ellipsisConfig.onExpand?.(true);
this.render();
}
private computeEntitySafeCutoff(
count: number,
entities: ContentEntity[],
): number {
let cutoff = count;
let extended = true;
while (extended) {
extended = false;
for (const entity of entities) {
if (entity.start < cutoff && entity.end > cutoff) {
cutoff = entity.end;
extended = true;
}
}
}
return cutoff;
}
private hasVerticalOverflow(element: HTMLElement): boolean {
return element.scrollHeight - element.clientHeight > 1;
}
private render(): void {
if (!this.host) {
return;
}
const text = this.getText();
const entities = findAllEntities(text);
const ellipsisConfig = this.resolveEllipsisConfig();
const mergedExpanded = this.getMergedExpanded(ellipsisConfig, text);
const wrapper = document.createElement("div");
const paragraph = document.createElement("div");
if (this.props.className) {
paragraph.className = this.props.className;
}
this.applyBaseParagraphStyle(paragraph);
if (ellipsisConfig && "count" in ellipsisConfig) {
const count = ellipsisConfig.count ?? 0;
const shouldTruncate = !mergedExpanded && count > 0 && text.length > count;
if (shouldTruncate) {
const cutoff = this.computeEntitySafeCutoff(count, entities);
const nodes = this.buildTextNodes(text, entities, cutoff);
paragraph.append(...nodes);
paragraph.append(document.createTextNode("…"));
if (ellipsisConfig.expandable) {
paragraph.append(this.buildReadMoreButton(ellipsisConfig.symbol));
}
} else {
paragraph.append(...this.buildTextNodes(text, entities));
}
} else {
paragraph.append(...this.buildTextNodes(text, entities));
if (ellipsisConfig && "rows" in ellipsisConfig && !mergedExpanded) {
paragraph.style.display = "-webkit-box";
paragraph.style.setProperty("-webkit-box-orient", "vertical");
paragraph.style.setProperty("-webkit-line-clamp", String(ellipsisConfig.rows));
paragraph.style.overflow = "hidden";
// Важно: сначала рендерим paragraph в DOM, потом меряем реальный overflow.
wrapper.append(paragraph);
this.host.replaceChildren(wrapper);
if (ellipsisConfig.expandable && this.hasVerticalOverflow(paragraph)) {
wrapper.append(this.buildReadMoreButton(ellipsisConfig.symbol));
}
this.emitOnViewIfNeeded(mergedExpanded);
return;
}
}
wrapper.append(paragraph);
this.host.replaceChildren(wrapper);
this.emitOnViewIfNeeded(mergedExpanded);
}
private initObserver(): void {
if (!this.host) {
return;
}
if (typeof IntersectionObserver === "undefined") {
this.hostInsideView = true;
return;
}
this.observer = new IntersectionObserver(
entries => {
const entry = entries[0];
if (!entry) {
return;
}
if (entry.isIntersecting && !this.hostInsideView) {
this.hostInsideView = true;
const ellipsisConfig = this.resolveEllipsisConfig();
const mergedExpanded = this.getMergedExpanded(ellipsisConfig, this.getText());
this.emitOnViewIfNeeded(mergedExpanded);
}
},
{ threshold: 0.5 },
);
this.observer.observe(this.host);
}
private emitOnViewIfNeeded(mergedExpanded: boolean): void {
if (!mergedExpanded || this.viewed || !this.hostInsideView) {
return;
}
this.viewed = true;
this.props.onView?.();
}
}
export class AngularContentTextWithSuggestionsRenderer extends AngularContentTextRenderer {}
export class AngularContentTitleWithSuggestionsRenderer {
private readonly renderer = new AngularContentTextWithSuggestionsRenderer();
attach(
host: HTMLElement,
props: AngularContentTitleWithSuggestionsProps = {},
): AngularContentTextRendererState {
return this.renderer.attach(host, this.normalizeProps(props));
}
update(props: AngularContentTitleWithSuggestionsProps): AngularContentTextRendererState {
return this.renderer.update(this.normalizeProps(props));
}
destroy(): void {
this.renderer.destroy();
}
getState(): AngularContentTextRendererState {
return this.renderer.getState();
}
private normalizeProps(
props: AngularContentTitleWithSuggestionsProps,
): AngularContentTextWithSuggestionsProps {
return {
...props,
weight: "bold",
blur: props.blur ?? false,
ellipsis: props.ellipsis === undefined ? { rows: 2 } : props.ellipsis,
};
}
}
export { toKebabCase };

View File

@@ -8,7 +8,7 @@ Typography package with shared tokens and framework adapters:
## Install from Git (SSH tag) ## Install from Git (SSH tag)
```bash ```bash
yarn add "@hublib-web/tach-typography@git+ssh://git@github.com/ORG/REPO.git#workspace=@hublib-web/tach-typography&tag=tach-typography-v0.1.0" yarn add "@hublib-web/tach-typography@git+ssh://git@github.com/ORG/REPO.git#workspace=@hublib-web/tach-typography&tag=tach-typography-v0.2.0"
``` ```
## Install inside this monorepo ## Install inside this monorepo
@@ -30,13 +30,13 @@ yarn workspace @hublib-web/tach-typography build
```bash ```bash
git add packages/tach-typography/package.json packages/tach-typography/dist git add packages/tach-typography/package.json packages/tach-typography/dist
git commit -m "release(tach-typography): v0.1.0" git commit -m "release(tach-typography): v0.2.0"
``` ```
4. Create and push tag: 4. Create and push tag:
```bash ```bash
git tag -a tach-typography-v0.1.0 -m "@hublib-web/tach-typography v0.1.0" git tag -a tach-typography-v0.2.0 -m "@hublib-web/tach-typography v0.2.0"
git push origin main --follow-tags git push origin main --follow-tags
``` ```
@@ -62,22 +62,31 @@ export const Example = () => (
```ts ```ts
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { TachTypographyDirective, TachTypographyNzModule } from "@hublib-web/tach-typography/angular"; import { TachTypographyComponent } from "@hublib-web/tach-typography/angular";
@Component({ @Component({
selector: "app-example", selector: "app-example",
standalone: true, standalone: true,
imports: [TachTypographyNzModule, TachTypographyDirective], imports: [TachTypographyComponent],
template: ` template: `
<span <tach-typography
nz-typography variant="Body"
tachTypography color="link"
tachTypography="Body" weight="bold"
tachTypographyColor="link" [nzProps]="{ nzCopyable: true, nzType: 'secondary' }"
tachTypographyWeight="bold"
> >
Hello from Angular + NG-ZORRO Hello from Angular + NG-ZORRO
</span> </tach-typography>
<tach-typography
as="a"
variant="Body"
color="link"
[hostProps]="{ href: '/docs', target: '_blank', rel: 'noopener noreferrer' }"
[nzProps]="{ nzType: 'secondary' }"
>
Open docs
</tach-typography>
`, `,
}) })
export class ExampleComponent {} export class ExampleComponent {}

View File

@@ -0,0 +1,81 @@
import { ElementRef, EventEmitter, OnChanges, Renderer2, SimpleChanges } from "@angular/core";
import { NzTypographyComponent } from "ng-zorro-antd/typography";
import { type EllipsisOptions, type TypographyClassOptions, type TypographyColor, type TypographyRenderOptions, type TypographyVariant, type TypographyWeight } from "../core";
import * as i0 from "@angular/core";
import * as i1 from "ng-zorro-antd/typography";
export type AngularTypographyClassInput = TypographyClassOptions;
export interface AngularTypographyRenderOptions extends TypographyRenderOptions {
preserveStyle?: Record<string, string | number>;
}
export type TachTypographyHostTag = "span" | "p" | "a" | "h1" | "h2" | "h3" | "h4";
type NonFunctionNonEmitterKeys<T> = {
[K in keyof T]-?: T[K] extends (...args: never[]) => unknown ? never : T[K] extends EventEmitter<unknown> ? never : K;
}[keyof T];
type NzTypographyInputKey = Extract<NonFunctionNonEmitterKeys<NzTypographyComponent>, `nz${string}`>;
export type TachTypographyNzProps = Partial<Pick<NzTypographyComponent, NzTypographyInputKey>>;
export type TachTypographyHostProps = Record<string, unknown>;
export declare const tachAngularTypographyClassName: (options?: AngularTypographyClassInput) => string;
export declare const tachAngularTypographyClassList: (options?: AngularTypographyClassInput) => string[];
export declare const tachAngularTypographyStyles: (ellipsis?: EllipsisOptions, preserveStyle?: Record<string, string | number>) => Record<string, string | number>;
export declare class TachTypographyDirective implements OnChanges {
private readonly elementRef;
private readonly renderer;
tachTypography: TypographyVariant | "" | undefined;
tachTypographyVariant: TypographyVariant;
tachTypographyColor: TypographyColor;
tachTypographyWeight: TypographyWeight;
tachTypographyClickable: boolean;
tachTypographyClassName: string | undefined;
tachTypographyEllipsis: EllipsisOptions | undefined;
private readonly appliedClasses;
private readonly appliedStyleProperties;
constructor(elementRef: ElementRef<HTMLElement>, renderer: Renderer2);
ngOnChanges(_changes: SimpleChanges): void;
private syncClasses;
private syncEllipsisStyles;
static ɵfac: i0.ɵɵFactoryDeclaration<TachTypographyDirective, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<TachTypographyDirective, "[tachTypography]", never, { "tachTypography": { "alias": "tachTypography"; "required": false; }; "tachTypographyVariant": { "alias": "tachTypographyVariant"; "required": false; }; "tachTypographyColor": { "alias": "tachTypographyColor"; "required": false; }; "tachTypographyWeight": { "alias": "tachTypographyWeight"; "required": false; }; "tachTypographyClickable": { "alias": "tachTypographyClickable"; "required": false; }; "tachTypographyClassName": { "alias": "tachTypographyClassName"; "required": false; }; "tachTypographyEllipsis": { "alias": "tachTypographyEllipsis"; "required": false; }; }, {}, never, never, true, never>;
}
export declare class TachTypographyNzPropsDirective implements OnChanges {
tachTypographyNzProps: TachTypographyNzProps | null | undefined;
private readonly appliedNzKeys;
private readonly nzTypography;
ngOnChanges(): void;
static ɵfac: i0.ɵɵFactoryDeclaration<TachTypographyNzPropsDirective, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<TachTypographyNzPropsDirective, "[tachTypographyNzProps]", never, { "tachTypographyNzProps": { "alias": "tachTypographyNzProps"; "required": false; }; }, {}, never, never, true, never>;
}
export declare class TachTypographyHostPropsDirective implements OnChanges {
private readonly elementRef;
private readonly renderer;
tachTypographyHostProps: TachTypographyHostProps | null | undefined;
private readonly appliedHostProps;
constructor(elementRef: ElementRef<HTMLElement>, renderer: Renderer2);
ngOnChanges(): void;
private shouldApplyAsAttribute;
private hasPropertyOnElement;
static ɵfac: i0.ɵɵFactoryDeclaration<TachTypographyHostPropsDirective, never>;
static ɵdir: i0.ɵɵDirectiveDeclaration<TachTypographyHostPropsDirective, "[tachTypographyHostProps]", never, { "tachTypographyHostProps": { "alias": "tachTypographyHostProps"; "required": false; }; }, {}, never, never, true, never>;
}
export declare class TachTypographyComponent {
hostTag: TachTypographyHostTag;
variant: TypographyVariant;
color: TypographyColor;
weight: TypographyWeight;
clickable: boolean;
className: string | undefined;
ellipsis: EllipsisOptions | undefined;
nzProps: TachTypographyNzProps | undefined;
hostProps: TachTypographyHostProps | undefined;
preserveStyle: Record<string, string | number> | undefined;
readonly tachClick: EventEmitter<MouseEvent>;
handleClick(event: MouseEvent): void;
static ɵfac: i0.ɵɵFactoryDeclaration<TachTypographyComponent, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<TachTypographyComponent, "tach-typography", never, { "hostTag": { "alias": "as"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "color": { "alias": "color"; "required": false; }; "weight": { "alias": "weight"; "required": false; }; "clickable": { "alias": "clickable"; "required": false; }; "className": { "alias": "className"; "required": false; }; "ellipsis": { "alias": "ellipsis"; "required": false; }; "nzProps": { "alias": "nzProps"; "required": false; }; "hostProps": { "alias": "hostProps"; "required": false; }; "preserveStyle": { "alias": "preserveStyle"; "required": false; }; }, { "tachClick": "tachClick"; }, never, ["*", "*", "*", "*", "*", "*", "*"], true, never>;
}
export declare class TachTypographyNzModule {
static ɵfac: i0.ɵɵFactoryDeclaration<TachTypographyNzModule, never>;
static ɵmod: i0.ɵɵNgModuleDeclaration<TachTypographyNzModule, never, [typeof i1.NzTypographyModule, typeof TachTypographyDirective, typeof TachTypographyNzPropsDirective, typeof TachTypographyHostPropsDirective, typeof TachTypographyComponent], [typeof i1.NzTypographyModule, typeof TachTypographyDirective, typeof TachTypographyNzPropsDirective, typeof TachTypographyHostPropsDirective, typeof TachTypographyComponent]>;
static ɵinj: i0.ɵɵInjectorDeclaration<TachTypographyNzModule>;
}
export {};
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/angular/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,545 @@
import { NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault } from "@angular/common";
import { ChangeDetectionStrategy, Component, Directive, EventEmitter, inject, Input, NgModule, Output, } from "@angular/core";
import { NzTypographyComponent, NzTypographyModule } from "ng-zorro-antd/typography";
import { tachTypographyClassList, tachTypographyClassName, tachTypographyEllipsisStyle, } from "../core";
import * as i0 from "@angular/core";
import * as i1 from "ng-zorro-antd/typography";
const camelToKebab = (value) => value.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
const toCssProperty = (styleKey) => {
if (styleKey.startsWith("Webkit")) {
return `-webkit-${camelToKebab(styleKey.slice(6))}`;
}
return camelToKebab(styleKey);
};
export const tachAngularTypographyClassName = (options = {}) => {
return tachTypographyClassName(options);
};
export const tachAngularTypographyClassList = (options = {}) => {
return tachTypographyClassList(options);
};
export const tachAngularTypographyStyles = (ellipsis, preserveStyle = {}) => {
const ellipsisStyle = tachTypographyEllipsisStyle(ellipsis);
if (!ellipsisStyle) {
return preserveStyle;
}
return {
...ellipsisStyle,
...preserveStyle,
};
};
export class TachTypographyDirective {
elementRef;
renderer;
tachTypography;
tachTypographyVariant = "Body";
tachTypographyColor = "primary";
tachTypographyWeight = "normal";
tachTypographyClickable = false;
tachTypographyClassName;
tachTypographyEllipsis;
appliedClasses = new Set();
appliedStyleProperties = new Set();
constructor(elementRef, renderer) {
this.elementRef = elementRef;
this.renderer = renderer;
}
ngOnChanges(_changes) {
this.syncClasses();
this.syncEllipsisStyles();
}
syncClasses() {
const nextClassList = tachTypographyClassList({
variant: this.tachTypography || this.tachTypographyVariant,
color: this.tachTypographyColor,
weight: this.tachTypographyWeight,
clickable: this.tachTypographyClickable,
className: this.tachTypographyClassName,
});
const nextSet = new Set(nextClassList);
for (const className of this.appliedClasses) {
if (!nextSet.has(className)) {
this.renderer.removeClass(this.elementRef.nativeElement, className);
}
}
for (const className of nextSet) {
this.renderer.addClass(this.elementRef.nativeElement, className);
}
this.appliedClasses.clear();
for (const className of nextSet) {
this.appliedClasses.add(className);
}
}
syncEllipsisStyles() {
const nextStyles = tachTypographyEllipsisStyle(this.tachTypographyEllipsis) || {};
const nextStyleKeys = new Set(Object.keys(nextStyles));
for (const styleKey of this.appliedStyleProperties) {
if (!nextStyleKeys.has(styleKey)) {
this.renderer.removeStyle(this.elementRef.nativeElement, toCssProperty(styleKey));
}
}
for (const [styleKey, styleValue] of Object.entries(nextStyles)) {
this.renderer.setStyle(this.elementRef.nativeElement, toCssProperty(styleKey), styleValue);
}
this.appliedStyleProperties.clear();
for (const styleKey of nextStyleKeys) {
this.appliedStyleProperties.add(styleKey);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: TachTypographyDirective, isStandalone: true, selector: "[tachTypography]", inputs: { tachTypography: "tachTypography", tachTypographyVariant: "tachTypographyVariant", tachTypographyColor: "tachTypographyColor", tachTypographyWeight: "tachTypographyWeight", tachTypographyClickable: "tachTypographyClickable", tachTypographyClassName: "tachTypographyClassName", tachTypographyEllipsis: "tachTypographyEllipsis" }, usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyDirective, decorators: [{
type: Directive,
args: [{
selector: "[tachTypography]",
standalone: true,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { tachTypography: [{
type: Input
}], tachTypographyVariant: [{
type: Input
}], tachTypographyColor: [{
type: Input
}], tachTypographyWeight: [{
type: Input
}], tachTypographyClickable: [{
type: Input
}], tachTypographyClassName: [{
type: Input
}], tachTypographyEllipsis: [{
type: Input
}] } });
export class TachTypographyNzPropsDirective {
tachTypographyNzProps;
appliedNzKeys = new Set();
nzTypography = inject(NzTypographyComponent, { self: true, optional: true });
ngOnChanges() {
if (!this.nzTypography) {
return;
}
const nzTypography = this.nzTypography;
const nextProps = this.tachTypographyNzProps ?? {};
const nextKeys = new Set();
for (const [key, value] of Object.entries(nextProps)) {
if (!key.startsWith("nz")) {
continue;
}
nzTypography[key] = value;
nextKeys.add(key);
}
for (const key of this.appliedNzKeys) {
if (!nextKeys.has(key)) {
nzTypography[key] = undefined;
}
}
this.appliedNzKeys.clear();
for (const key of nextKeys) {
this.appliedNzKeys.add(key);
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyNzPropsDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: TachTypographyNzPropsDirective, isStandalone: true, selector: "[tachTypographyNzProps]", inputs: { tachTypographyNzProps: "tachTypographyNzProps" }, usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyNzPropsDirective, decorators: [{
type: Directive,
args: [{
selector: "[tachTypographyNzProps]",
standalone: true,
}]
}], propDecorators: { tachTypographyNzProps: [{
type: Input
}] } });
export class TachTypographyHostPropsDirective {
elementRef;
renderer;
tachTypographyHostProps;
appliedHostProps = new Map();
constructor(elementRef, renderer) {
this.elementRef = elementRef;
this.renderer = renderer;
}
ngOnChanges() {
const nextProps = this.tachTypographyHostProps ?? {};
const nextAppliedProps = new Map();
for (const [key, value] of Object.entries(nextProps)) {
if (key === "class" || key === "className" || key === "style") {
continue;
}
if (value === undefined || value === null) {
continue;
}
const applyAsAttr = this.shouldApplyAsAttribute(key, value);
if (applyAsAttr) {
if (typeof value === "boolean") {
if (value) {
this.renderer.setAttribute(this.elementRef.nativeElement, key, "");
}
else {
this.renderer.removeAttribute(this.elementRef.nativeElement, key);
}
}
else {
this.renderer.setAttribute(this.elementRef.nativeElement, key, String(value));
}
nextAppliedProps.set(key, "attr");
continue;
}
this.renderer.setProperty(this.elementRef.nativeElement, key, value);
nextAppliedProps.set(key, "prop");
}
for (const [key, kind] of this.appliedHostProps.entries()) {
if (nextAppliedProps.has(key)) {
continue;
}
if (kind === "attr") {
this.renderer.removeAttribute(this.elementRef.nativeElement, key);
}
else {
this.renderer.setProperty(this.elementRef.nativeElement, key, undefined);
}
}
this.appliedHostProps.clear();
for (const [key, kind] of nextAppliedProps.entries()) {
this.appliedHostProps.set(key, kind);
}
}
shouldApplyAsAttribute(key, value) {
if (key.startsWith("data-") || key.startsWith("aria-")) {
return true;
}
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
return !this.hasPropertyOnElement(key);
}
return false;
}
hasPropertyOnElement(key) {
return key in this.elementRef.nativeElement;
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyHostPropsDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: TachTypographyHostPropsDirective, isStandalone: true, selector: "[tachTypographyHostProps]", inputs: { tachTypographyHostProps: "tachTypographyHostProps" }, usesOnChanges: true, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyHostPropsDirective, decorators: [{
type: Directive,
args: [{
selector: "[tachTypographyHostProps]",
standalone: true,
}]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { tachTypographyHostProps: [{
type: Input
}] } });
export class TachTypographyComponent {
hostTag = "span";
variant = "Body";
color = "primary";
weight = "normal";
clickable = false;
className;
ellipsis;
nzProps;
hostProps;
preserveStyle;
tachClick = new EventEmitter();
handleClick(event) {
this.tachClick.emit(event);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: TachTypographyComponent, isStandalone: true, selector: "tach-typography", inputs: { hostTag: ["as", "hostTag"], variant: "variant", color: "color", weight: "weight", clickable: "clickable", className: "className", ellipsis: "ellipsis", nzProps: "nzProps", hostProps: "hostProps", preserveStyle: "preserveStyle" }, outputs: { tachClick: "tachClick" }, ngImport: i0, template: `
<ng-container [ngSwitch]="hostTag">
<p
*ngSwitchCase="'p'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</p>
<a
*ngSwitchCase="'a'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</a>
<h1
*ngSwitchCase="'h1'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h1>
<h2
*ngSwitchCase="'h2'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h2>
<h3
*ngSwitchCase="'h3'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h3>
<h4
*ngSwitchCase="'h4'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h4>
<span
*ngSwitchDefault
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</span>
</ng-container>
`, isInline: true, dependencies: [{ kind: "ngmodule", type: NzTypographyModule }, { kind: "component", type: i1.NzTypographyComponent, selector: " nz-typography, [nz-typography], p[nz-paragraph], span[nz-text], h1[nz-title], h2[nz-title], h3[nz-title], h4[nz-title] ", inputs: ["nzCopyable", "nzEditable", "nzDisabled", "nzExpandable", "nzEllipsis", "nzCopyTooltips", "nzCopyIcons", "nzEditTooltip", "nzEditIcon", "nzContent", "nzEllipsisRows", "nzType", "nzCopyText", "nzSuffix"], outputs: ["nzContentChange", "nzCopy", "nzExpandChange", "nzOnEllipsis"], exportAs: ["nzTypography"] }, { kind: "directive", type: TachTypographyDirective, selector: "[tachTypography]", inputs: ["tachTypography", "tachTypographyVariant", "tachTypographyColor", "tachTypographyWeight", "tachTypographyClickable", "tachTypographyClassName", "tachTypographyEllipsis"] }, { kind: "directive", type: TachTypographyNzPropsDirective, selector: "[tachTypographyNzProps]", inputs: ["tachTypographyNzProps"] }, { kind: "directive", type: TachTypographyHostPropsDirective, selector: "[tachTypographyHostProps]", inputs: ["tachTypographyHostProps"] }, { kind: "directive", type: NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyComponent, decorators: [{
type: Component,
args: [{
selector: "tach-typography",
standalone: true,
imports: [
NzTypographyModule,
TachTypographyDirective,
TachTypographyNzPropsDirective,
TachTypographyHostPropsDirective,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgStyle,
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<ng-container [ngSwitch]="hostTag">
<p
*ngSwitchCase="'p'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</p>
<a
*ngSwitchCase="'a'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</a>
<h1
*ngSwitchCase="'h1'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h1>
<h2
*ngSwitchCase="'h2'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h2>
<h3
*ngSwitchCase="'h3'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h3>
<h4
*ngSwitchCase="'h4'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h4>
<span
*ngSwitchDefault
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</span>
</ng-container>
`,
}]
}], propDecorators: { hostTag: [{
type: Input,
args: ["as"]
}], variant: [{
type: Input
}], color: [{
type: Input
}], weight: [{
type: Input
}], clickable: [{
type: Input
}], className: [{
type: Input
}], ellipsis: [{
type: Input
}], nzProps: [{
type: Input
}], hostProps: [{
type: Input
}], preserveStyle: [{
type: Input
}], tachClick: [{
type: Output
}] } });
export class TachTypographyNzModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyNzModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyNzModule, imports: [NzTypographyModule, TachTypographyDirective, TachTypographyNzPropsDirective, TachTypographyHostPropsDirective, TachTypographyComponent], exports: [NzTypographyModule, TachTypographyDirective, TachTypographyNzPropsDirective, TachTypographyHostPropsDirective, TachTypographyComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyNzModule, imports: [NzTypographyModule,
TachTypographyComponent, NzTypographyModule] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: TachTypographyNzModule, decorators: [{
type: NgModule,
args: [{
imports: [
NzTypographyModule,
TachTypographyDirective,
TachTypographyNzPropsDirective,
TachTypographyHostPropsDirective,
TachTypographyComponent,
],
exports: [
NzTypographyModule,
TachTypographyDirective,
TachTypographyNzPropsDirective,
TachTypographyHostPropsDirective,
TachTypographyComponent,
],
}]
}] });
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export * from "./index";
//# sourceMappingURL=public-api.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../../../src/angular/public-api.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}

View File

@@ -0,0 +1,2 @@
export * from "./index";
//# sourceMappingURL=public-api.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../../../src/angular/public-api.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}

View File

@@ -0,0 +1,4 @@
import type { TypographyClassOptions } from "./types";
export declare const tachTypographyClassName: ({ variant, color, weight, clickable, className, }?: TypographyClassOptions) => string;
export declare const tachTypographyClassList: (options?: TypographyClassOptions) => string[];
//# sourceMappingURL=classnames.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"classnames.d.ts","sourceRoot":"","sources":["../../../src/core/classnames.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAOtD,eAAO,MAAM,uBAAuB,GAAI,oDAMrC,sBAA2B,KAAG,MAShC,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,UAAS,sBAA2B,KAAG,MAAM,EAIpF,CAAC"}

View File

@@ -0,0 +1,11 @@
const BASE_CLASS = "tach-typography";
const join = (...parts) => parts.filter(Boolean).join(" ");
export const tachTypographyClassName = ({ variant = "Body", color = "primary", weight = "normal", clickable = false, className, } = {}) => {
return join(BASE_CLASS, `${BASE_CLASS}--${variant}`, `${BASE_CLASS}--color-${color}`, weight === "bold" && `${BASE_CLASS}--bold`, clickable && `${BASE_CLASS}--pointer`, className);
};
export const tachTypographyClassList = (options = {}) => {
return tachTypographyClassName(options)
.split(" ")
.filter(Boolean);
};
//# sourceMappingURL=classnames.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"classnames.js","sourceRoot":"","sources":["../../../src/core/classnames.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,iBAAiB,CAAC;AAErC,MAAM,IAAI,GAAG,CAAC,GAAG,KAA+C,EAAU,EAAE,CAC1E,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,EACtC,OAAO,GAAG,MAAM,EAChB,KAAK,GAAG,SAAS,EACjB,MAAM,GAAG,QAAQ,EACjB,SAAS,GAAG,KAAK,EACjB,SAAS,MACiB,EAAE,EAAU,EAAE;IACxC,OAAO,IAAI,CACT,UAAU,EACV,GAAG,UAAU,KAAK,OAAO,EAAE,EAC3B,GAAG,UAAU,WAAW,KAAK,EAAE,EAC/B,MAAM,KAAK,MAAM,IAAI,GAAG,UAAU,QAAQ,EAC1C,SAAS,IAAI,GAAG,UAAU,WAAW,EACrC,SAAS,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,UAAkC,EAAE,EAAY,EAAE;IACxF,OAAO,uBAAuB,CAAC,OAAO,CAAC;SACpC,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC,CAAC"}

View File

@@ -0,0 +1,5 @@
import type { EllipsisOptions } from "./types";
type StyleRecord = Record<string, string | number>;
export declare const tachTypographyEllipsisStyle: (ellipsis?: EllipsisOptions) => StyleRecord | undefined;
export {};
//# sourceMappingURL=ellipsis.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ellipsis.d.ts","sourceRoot":"","sources":["../../../src/core/ellipsis.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;AAEnD,eAAO,MAAM,2BAA2B,GACtC,WAAW,eAAe,KACzB,WAAW,GAAG,SAchB,CAAC"}

View File

@@ -0,0 +1,14 @@
export const tachTypographyEllipsisStyle = (ellipsis) => {
if (!ellipsis) {
return undefined;
}
const rows = typeof ellipsis === "object" ? ellipsis.rows ?? 1 : 1;
return {
overflow: "hidden",
textOverflow: "ellipsis",
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: rows,
};
};
//# sourceMappingURL=ellipsis.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ellipsis.js","sourceRoot":"","sources":["../../../src/core/ellipsis.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,QAA0B,EACD,EAAE;IAC3B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnE,OAAO;QACL,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,UAAU;QACxB,OAAO,EAAE,aAAa;QACtB,eAAe,EAAE,UAAU;QAC3B,eAAe,EAAE,IAAI;KACtB,CAAC;AACJ,CAAC,CAAC"}

View File

@@ -0,0 +1,4 @@
export * from "./types";
export * from "./classnames";
export * from "./ellipsis";
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}

View File

@@ -0,0 +1,4 @@
export * from "./types";
export * from "./classnames";
export * from "./ellipsis";
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC"}

View File

@@ -0,0 +1,19 @@
export declare const TYPOGRAPHY_VARIANTS: readonly ["LargeTitle", "Title1", "Title2", "Title3", "Headline", "Body", "Inputs", "Subheadline", "FootnoteUnderline", "Footnote", "Caption", "Caption2", "AccentH1", "AccentH2", "AccentSubttl", "AccentSubttl2", "AccentCaption", "AccentCaption2", "AccentRegularM", "AccentRegularS", "AccentLargeTtl", "AppMediumBody", "AppMediumSubtext", "AppMediumSubtextUnderline"];
export declare const TYPOGRAPHY_COLORS: readonly ["primary", "secondary", "tertiary", "quaternary", "link", "white", "dark", "alert", "malahit", "attantion"];
export type TypographyVariant = (typeof TYPOGRAPHY_VARIANTS)[number];
export type TypographyColor = (typeof TYPOGRAPHY_COLORS)[number];
export type TypographyWeight = "normal" | "bold";
export interface TypographyClassOptions {
variant?: TypographyVariant;
color?: TypographyColor;
weight?: TypographyWeight;
clickable?: boolean;
className?: string | undefined;
}
export type EllipsisOptions = boolean | {
rows?: number;
};
export interface TypographyRenderOptions extends TypographyClassOptions {
ellipsis?: EllipsisOptions;
}
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,gXAyBtB,CAAC;AAEX,eAAO,MAAM,iBAAiB,uHAWpB,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AACjE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,MAAM,eAAe,GACvB,OAAO,GACP;IACE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,MAAM,WAAW,uBAAwB,SAAQ,sBAAsB;IACrE,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B"}

View File

@@ -0,0 +1,39 @@
export const TYPOGRAPHY_VARIANTS = [
"LargeTitle",
"Title1",
"Title2",
"Title3",
"Headline",
"Body",
"Inputs",
"Subheadline",
"FootnoteUnderline",
"Footnote",
"Caption",
"Caption2",
"AccentH1",
"AccentH2",
"AccentSubttl",
"AccentSubttl2",
"AccentCaption",
"AccentCaption2",
"AccentRegularM",
"AccentRegularS",
"AccentLargeTtl",
"AppMediumBody",
"AppMediumSubtext",
"AppMediumSubtextUnderline",
];
export const TYPOGRAPHY_COLORS = [
"primary",
"secondary",
"tertiary",
"quaternary",
"link",
"white",
"dark",
"alert",
"malahit",
"attantion",
];
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,YAAY;IACZ,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,MAAM;IACN,QAAQ;IACR,aAAa;IACb,mBAAmB;IACnB,UAAU;IACV,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,cAAc;IACd,eAAe;IACf,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,kBAAkB;IAClB,2BAA2B;CACnB,CAAC;AAEX,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,SAAS;IACT,WAAW;IACX,UAAU;IACV,YAAY;IACZ,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,SAAS;IACT,WAAW;CACH,CAAC"}

View File

@@ -1,204 +0,0 @@
'use strict';
var core = require('@angular/core');
var typography = require('ng-zorro-antd/typography');
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
var __typeError = (msg) => {
throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __decoratorStart = (base) => [, , , __create(null)];
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
var __runInitializers = (array, flags, self, value) => {
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
return value;
};
var __decorateElement = (array, flags, name, decorators, target, extra) => {
var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
return __privateGet(this, extra);
}, set [name](x) {
return __privateSet(this, extra, x);
} }, name));
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
for (var i = decorators.length - 1; i >= 0; i--) {
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
if (k) {
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
}
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
else if (typeof it !== "object" || it === null) __typeError("Object expected");
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
}
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
// src/core/classnames.ts
var BASE_CLASS = "tach-typography";
var join = (...parts) => parts.filter(Boolean).join(" ");
var tachTypographyClassName = ({
variant = "Body",
color = "primary",
weight = "normal",
clickable = false,
className
} = {}) => {
return join(
BASE_CLASS,
`${BASE_CLASS}--${variant}`,
`${BASE_CLASS}--color-${color}`,
weight === "bold" && `${BASE_CLASS}--bold`,
clickable && `${BASE_CLASS}--pointer`,
className
);
};
var tachTypographyClassList = (options = {}) => {
return tachTypographyClassName(options).split(" ").filter(Boolean);
};
// src/core/ellipsis.ts
var tachTypographyEllipsisStyle = (ellipsis) => {
if (!ellipsis) {
return void 0;
}
const rows = typeof ellipsis === "object" ? ellipsis.rows ?? 1 : 1;
return {
overflow: "hidden",
textOverflow: "ellipsis",
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: rows
};
};
// src/angular/index.ts
var camelToKebab = (value) => value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
var toCssProperty = (styleKey) => {
if (styleKey.startsWith("Webkit")) {
return `-webkit-${camelToKebab(styleKey.slice(6))}`;
}
return camelToKebab(styleKey);
};
var tachAngularTypographyClassName = (options = {}) => {
return tachTypographyClassName(options);
};
var tachAngularTypographyClassList = (options = {}) => {
return tachTypographyClassList(options);
};
var tachAngularTypographyStyles = (ellipsis, preserveStyle = {}) => {
const ellipsisStyle = tachTypographyEllipsisStyle(ellipsis);
if (!ellipsisStyle) {
return preserveStyle;
}
return {
...ellipsisStyle,
...preserveStyle
};
};
var _tachTypographyEllipsis_dec, _tachTypographyClassName_dec, _tachTypographyClickable_dec, _tachTypographyWeight_dec, _tachTypographyColor_dec, _tachTypographyVariant_dec, _tachTypography_dec, _TachTypographyDirective_decorators, _init;
_TachTypographyDirective_decorators = [core.Directive({
selector: "[tachTypography]",
standalone: true
})], _tachTypography_dec = [core.Input()], _tachTypographyVariant_dec = [core.Input()], _tachTypographyColor_dec = [core.Input()], _tachTypographyWeight_dec = [core.Input()], _tachTypographyClickable_dec = [core.Input()], _tachTypographyClassName_dec = [core.Input()], _tachTypographyEllipsis_dec = [core.Input()];
exports.TachTypographyDirective = class TachTypographyDirective {
constructor(elementRef, renderer) {
this.elementRef = elementRef;
this.renderer = renderer;
__publicField(this, "tachTypography", __runInitializers(_init, 8, this)), __runInitializers(_init, 11, this);
__publicField(this, "tachTypographyVariant", __runInitializers(_init, 12, this, "Body")), __runInitializers(_init, 15, this);
__publicField(this, "tachTypographyColor", __runInitializers(_init, 16, this, "primary")), __runInitializers(_init, 19, this);
__publicField(this, "tachTypographyWeight", __runInitializers(_init, 20, this, "normal")), __runInitializers(_init, 23, this);
__publicField(this, "tachTypographyClickable", __runInitializers(_init, 24, this, false)), __runInitializers(_init, 27, this);
__publicField(this, "tachTypographyClassName", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
__publicField(this, "tachTypographyEllipsis", __runInitializers(_init, 32, this)), __runInitializers(_init, 35, this);
__publicField(this, "appliedClasses", /* @__PURE__ */ new Set());
__publicField(this, "appliedStyleProperties", /* @__PURE__ */ new Set());
}
ngOnChanges(_changes) {
this.syncClasses();
this.syncEllipsisStyles();
}
syncClasses() {
const nextClassList = tachTypographyClassList({
variant: this.tachTypography || this.tachTypographyVariant,
color: this.tachTypographyColor,
weight: this.tachTypographyWeight,
clickable: this.tachTypographyClickable,
className: this.tachTypographyClassName
});
const nextSet = new Set(nextClassList);
for (const className of this.appliedClasses) {
if (!nextSet.has(className)) {
this.renderer.removeClass(this.elementRef.nativeElement, className);
}
}
for (const className of nextSet) {
this.renderer.addClass(this.elementRef.nativeElement, className);
}
this.appliedClasses.clear();
for (const className of nextSet) {
this.appliedClasses.add(className);
}
}
syncEllipsisStyles() {
const nextStyles = tachTypographyEllipsisStyle(this.tachTypographyEllipsis) || {};
const nextStyleKeys = new Set(Object.keys(nextStyles));
for (const styleKey of this.appliedStyleProperties) {
if (!nextStyleKeys.has(styleKey)) {
this.renderer.removeStyle(this.elementRef.nativeElement, toCssProperty(styleKey));
}
}
for (const [styleKey, styleValue] of Object.entries(nextStyles)) {
this.renderer.setStyle(this.elementRef.nativeElement, toCssProperty(styleKey), styleValue);
}
this.appliedStyleProperties.clear();
for (const styleKey of nextStyleKeys) {
this.appliedStyleProperties.add(styleKey);
}
}
};
_init = __decoratorStart();
__decorateElement(_init, 5, "tachTypography", _tachTypography_dec, exports.TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyVariant", _tachTypographyVariant_dec, exports.TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyColor", _tachTypographyColor_dec, exports.TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyWeight", _tachTypographyWeight_dec, exports.TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyClickable", _tachTypographyClickable_dec, exports.TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyClassName", _tachTypographyClassName_dec, exports.TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyEllipsis", _tachTypographyEllipsis_dec, exports.TachTypographyDirective);
exports.TachTypographyDirective = __decorateElement(_init, 0, "TachTypographyDirective", _TachTypographyDirective_decorators, exports.TachTypographyDirective);
__runInitializers(_init, 1, exports.TachTypographyDirective);
var _TachTypographyNzModule_decorators, _init2;
_TachTypographyNzModule_decorators = [core.NgModule({
imports: [typography.NzTypographyModule, exports.TachTypographyDirective],
exports: [typography.NzTypographyModule, exports.TachTypographyDirective]
})];
exports.TachTypographyNzModule = class TachTypographyNzModule {
};
_init2 = __decoratorStart();
exports.TachTypographyNzModule = __decorateElement(_init2, 0, "TachTypographyNzModule", _TachTypographyNzModule_decorators, exports.TachTypographyNzModule);
__runInitializers(_init2, 1, exports.TachTypographyNzModule);
exports.tachAngularTypographyClassList = tachAngularTypographyClassList;
exports.tachAngularTypographyClassName = tachAngularTypographyClassName;
exports.tachAngularTypographyStyles = tachAngularTypographyStyles;
//# sourceMappingURL=index.cjs.map
//# sourceMappingURL=index.cjs.map

File diff suppressed because one or more lines are too long

View File

@@ -1,31 +0,0 @@
import { OnChanges, ElementRef, Renderer2, SimpleChanges } from '@angular/core';
import { T as TypographyClassOptions, d as TypographyRenderOptions, e as TypographyVariant, c as TypographyColor, f as TypographyWeight, E as EllipsisOptions } from '../types-CQyFuLqp.cjs';
type AngularTypographyClassInput = TypographyClassOptions;
interface AngularTypographyRenderOptions extends TypographyRenderOptions {
preserveStyle?: Record<string, string | number>;
}
declare const tachAngularTypographyClassName: (options?: AngularTypographyClassInput) => string;
declare const tachAngularTypographyClassList: (options?: AngularTypographyClassInput) => string[];
declare const tachAngularTypographyStyles: (ellipsis?: EllipsisOptions, preserveStyle?: Record<string, string | number>) => Record<string, string | number>;
declare class TachTypographyDirective implements OnChanges {
private readonly elementRef;
private readonly renderer;
tachTypography: TypographyVariant | "" | undefined;
tachTypographyVariant: TypographyVariant;
tachTypographyColor: TypographyColor;
tachTypographyWeight: TypographyWeight;
tachTypographyClickable: boolean;
tachTypographyClassName: string | undefined;
tachTypographyEllipsis: EllipsisOptions | undefined;
private readonly appliedClasses;
private readonly appliedStyleProperties;
constructor(elementRef: ElementRef<HTMLElement>, renderer: Renderer2);
ngOnChanges(_changes: SimpleChanges): void;
private syncClasses;
private syncEllipsisStyles;
}
declare class TachTypographyNzModule {
}
export { type AngularTypographyClassInput, type AngularTypographyRenderOptions, TachTypographyDirective, TachTypographyNzModule, tachAngularTypographyClassList, tachAngularTypographyClassName, tachAngularTypographyStyles };

View File

@@ -1,31 +1 @@
import { OnChanges, ElementRef, Renderer2, SimpleChanges } from '@angular/core'; export * from "./angular/index";
import { T as TypographyClassOptions, d as TypographyRenderOptions, e as TypographyVariant, c as TypographyColor, f as TypographyWeight, E as EllipsisOptions } from '../types-CQyFuLqp.js';
type AngularTypographyClassInput = TypographyClassOptions;
interface AngularTypographyRenderOptions extends TypographyRenderOptions {
preserveStyle?: Record<string, string | number>;
}
declare const tachAngularTypographyClassName: (options?: AngularTypographyClassInput) => string;
declare const tachAngularTypographyClassList: (options?: AngularTypographyClassInput) => string[];
declare const tachAngularTypographyStyles: (ellipsis?: EllipsisOptions, preserveStyle?: Record<string, string | number>) => Record<string, string | number>;
declare class TachTypographyDirective implements OnChanges {
private readonly elementRef;
private readonly renderer;
tachTypography: TypographyVariant | "" | undefined;
tachTypographyVariant: TypographyVariant;
tachTypographyColor: TypographyColor;
tachTypographyWeight: TypographyWeight;
tachTypographyClickable: boolean;
tachTypographyClassName: string | undefined;
tachTypographyEllipsis: EllipsisOptions | undefined;
private readonly appliedClasses;
private readonly appliedStyleProperties;
constructor(elementRef: ElementRef<HTMLElement>, renderer: Renderer2);
ngOnChanges(_changes: SimpleChanges): void;
private syncClasses;
private syncEllipsisStyles;
}
declare class TachTypographyNzModule {
}
export { type AngularTypographyClassInput, type AngularTypographyRenderOptions, TachTypographyDirective, TachTypographyNzModule, tachAngularTypographyClassList, tachAngularTypographyClassName, tachAngularTypographyStyles };

View File

@@ -1,200 +1 @@
import { Directive, Input, NgModule } from '@angular/core'; export * from "./angular/index.js";
import { NzTypographyModule } from 'ng-zorro-antd/typography';
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
var __typeError = (msg) => {
throw TypeError(msg);
};
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __decoratorStart = (base) => [, , , __create(null)];
var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
var __runInitializers = (array, flags, self, value) => {
for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
return value;
};
var __decorateElement = (array, flags, name, decorators, target, extra) => {
var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
return __privateGet(this, extra);
}, set [name](x) {
return __privateSet(this, extra, x);
} }, name));
k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
for (var i = decorators.length - 1; i >= 0; i--) {
ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
if (k) {
ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
}
it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
else if (typeof it !== "object" || it === null) __typeError("Object expected");
else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
}
return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
};
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
// src/core/classnames.ts
var BASE_CLASS = "tach-typography";
var join = (...parts) => parts.filter(Boolean).join(" ");
var tachTypographyClassName = ({
variant = "Body",
color = "primary",
weight = "normal",
clickable = false,
className
} = {}) => {
return join(
BASE_CLASS,
`${BASE_CLASS}--${variant}`,
`${BASE_CLASS}--color-${color}`,
weight === "bold" && `${BASE_CLASS}--bold`,
clickable && `${BASE_CLASS}--pointer`,
className
);
};
var tachTypographyClassList = (options = {}) => {
return tachTypographyClassName(options).split(" ").filter(Boolean);
};
// src/core/ellipsis.ts
var tachTypographyEllipsisStyle = (ellipsis) => {
if (!ellipsis) {
return void 0;
}
const rows = typeof ellipsis === "object" ? ellipsis.rows ?? 1 : 1;
return {
overflow: "hidden",
textOverflow: "ellipsis",
display: "-webkit-box",
WebkitBoxOrient: "vertical",
WebkitLineClamp: rows
};
};
// src/angular/index.ts
var camelToKebab = (value) => value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
var toCssProperty = (styleKey) => {
if (styleKey.startsWith("Webkit")) {
return `-webkit-${camelToKebab(styleKey.slice(6))}`;
}
return camelToKebab(styleKey);
};
var tachAngularTypographyClassName = (options = {}) => {
return tachTypographyClassName(options);
};
var tachAngularTypographyClassList = (options = {}) => {
return tachTypographyClassList(options);
};
var tachAngularTypographyStyles = (ellipsis, preserveStyle = {}) => {
const ellipsisStyle = tachTypographyEllipsisStyle(ellipsis);
if (!ellipsisStyle) {
return preserveStyle;
}
return {
...ellipsisStyle,
...preserveStyle
};
};
var _tachTypographyEllipsis_dec, _tachTypographyClassName_dec, _tachTypographyClickable_dec, _tachTypographyWeight_dec, _tachTypographyColor_dec, _tachTypographyVariant_dec, _tachTypography_dec, _TachTypographyDirective_decorators, _init;
_TachTypographyDirective_decorators = [Directive({
selector: "[tachTypography]",
standalone: true
})], _tachTypography_dec = [Input()], _tachTypographyVariant_dec = [Input()], _tachTypographyColor_dec = [Input()], _tachTypographyWeight_dec = [Input()], _tachTypographyClickable_dec = [Input()], _tachTypographyClassName_dec = [Input()], _tachTypographyEllipsis_dec = [Input()];
var TachTypographyDirective = class {
constructor(elementRef, renderer) {
this.elementRef = elementRef;
this.renderer = renderer;
__publicField(this, "tachTypography", __runInitializers(_init, 8, this)), __runInitializers(_init, 11, this);
__publicField(this, "tachTypographyVariant", __runInitializers(_init, 12, this, "Body")), __runInitializers(_init, 15, this);
__publicField(this, "tachTypographyColor", __runInitializers(_init, 16, this, "primary")), __runInitializers(_init, 19, this);
__publicField(this, "tachTypographyWeight", __runInitializers(_init, 20, this, "normal")), __runInitializers(_init, 23, this);
__publicField(this, "tachTypographyClickable", __runInitializers(_init, 24, this, false)), __runInitializers(_init, 27, this);
__publicField(this, "tachTypographyClassName", __runInitializers(_init, 28, this)), __runInitializers(_init, 31, this);
__publicField(this, "tachTypographyEllipsis", __runInitializers(_init, 32, this)), __runInitializers(_init, 35, this);
__publicField(this, "appliedClasses", /* @__PURE__ */ new Set());
__publicField(this, "appliedStyleProperties", /* @__PURE__ */ new Set());
}
ngOnChanges(_changes) {
this.syncClasses();
this.syncEllipsisStyles();
}
syncClasses() {
const nextClassList = tachTypographyClassList({
variant: this.tachTypography || this.tachTypographyVariant,
color: this.tachTypographyColor,
weight: this.tachTypographyWeight,
clickable: this.tachTypographyClickable,
className: this.tachTypographyClassName
});
const nextSet = new Set(nextClassList);
for (const className of this.appliedClasses) {
if (!nextSet.has(className)) {
this.renderer.removeClass(this.elementRef.nativeElement, className);
}
}
for (const className of nextSet) {
this.renderer.addClass(this.elementRef.nativeElement, className);
}
this.appliedClasses.clear();
for (const className of nextSet) {
this.appliedClasses.add(className);
}
}
syncEllipsisStyles() {
const nextStyles = tachTypographyEllipsisStyle(this.tachTypographyEllipsis) || {};
const nextStyleKeys = new Set(Object.keys(nextStyles));
for (const styleKey of this.appliedStyleProperties) {
if (!nextStyleKeys.has(styleKey)) {
this.renderer.removeStyle(this.elementRef.nativeElement, toCssProperty(styleKey));
}
}
for (const [styleKey, styleValue] of Object.entries(nextStyles)) {
this.renderer.setStyle(this.elementRef.nativeElement, toCssProperty(styleKey), styleValue);
}
this.appliedStyleProperties.clear();
for (const styleKey of nextStyleKeys) {
this.appliedStyleProperties.add(styleKey);
}
}
};
_init = __decoratorStart();
__decorateElement(_init, 5, "tachTypography", _tachTypography_dec, TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyVariant", _tachTypographyVariant_dec, TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyColor", _tachTypographyColor_dec, TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyWeight", _tachTypographyWeight_dec, TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyClickable", _tachTypographyClickable_dec, TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyClassName", _tachTypographyClassName_dec, TachTypographyDirective);
__decorateElement(_init, 5, "tachTypographyEllipsis", _tachTypographyEllipsis_dec, TachTypographyDirective);
TachTypographyDirective = __decorateElement(_init, 0, "TachTypographyDirective", _TachTypographyDirective_decorators, TachTypographyDirective);
__runInitializers(_init, 1, TachTypographyDirective);
var _TachTypographyNzModule_decorators, _init2;
_TachTypographyNzModule_decorators = [NgModule({
imports: [NzTypographyModule, TachTypographyDirective],
exports: [NzTypographyModule, TachTypographyDirective]
})];
var TachTypographyNzModule = class {
};
_init2 = __decoratorStart();
TachTypographyNzModule = __decorateElement(_init2, 0, "TachTypographyNzModule", _TachTypographyNzModule_decorators, TachTypographyNzModule);
__runInitializers(_init2, 1, TachTypographyNzModule);
export { TachTypographyDirective, TachTypographyNzModule, tachAngularTypographyClassList, tachAngularTypographyClassName, tachAngularTypographyStyles };
//# sourceMappingURL=index.js.map
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{ {
"name": "@hublib-web/tach-typography", "name": "@hublib-web/tach-typography",
"version": "0.1.0", "version": "0.2.0",
"description": "Cross-framework typography package for React and Angular", "description": "Cross-framework typography package for React and Angular",
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",
@@ -46,14 +46,14 @@
}, },
"./angular": { "./angular": {
"types": "./dist/angular/index.d.ts", "types": "./dist/angular/index.d.ts",
"import": "./dist/angular/index.js", "import": "./dist/angular/index.js"
"require": "./dist/angular/index.cjs"
}, },
"./styles.css": "./dist/styles.css", "./styles.css": "./dist/styles.css",
"./styles/typography-vars.scss": "./styles/typography-vars.scss" "./styles/typography-vars.scss": "./styles/typography-vars.scss"
}, },
"scripts": { "scripts": {
"build": "yarn clean && tsup && node ./scripts/copy-styles.mjs", "build": "yarn clean && tsup && yarn build:angular && node ./scripts/copy-styles.mjs",
"build:angular": "ngc -p tsconfig.angular.json && node ./scripts/fix-angular-entry.mjs",
"clean": "rm -rf dist", "clean": "rm -rf dist",
"typecheck": "tsc -p tsconfig.json --noEmit", "typecheck": "tsc -p tsconfig.json --noEmit",
"test": "vitest run", "test": "vitest run",
@@ -61,6 +61,9 @@
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"storybook:build": "storybook build" "storybook:build": "storybook build"
}, },
"dependencies": {
"tslib": "^2.8.1"
},
"peerDependencies": { "peerDependencies": {
"@angular/animations": ">=17.0.0", "@angular/animations": ">=17.0.0",
"@angular/common": ">=17.0.0", "@angular/common": ">=17.0.0",
@@ -112,6 +115,8 @@
"devDependencies": { "devDependencies": {
"@angular/animations": "^20.3.17", "@angular/animations": "^20.3.17",
"@angular/common": "^20.3.17", "@angular/common": "^20.3.17",
"@angular/compiler": "^20.3.17",
"@angular/compiler-cli": "^20.3.17",
"@angular/core": "^20.3.17", "@angular/core": "^20.3.17",
"@angular/forms": "^20.3.17", "@angular/forms": "^20.3.17",
"@angular/platform-browser": "^20.3.17", "@angular/platform-browser": "^20.3.17",

View File

@@ -0,0 +1,12 @@
import { access, writeFile } from "node:fs/promises";
import path from "node:path";
const distAngularDir = path.resolve("dist/angular");
await access(path.join(distAngularDir, "angular/index.js"));
await access(path.join(distAngularDir, "angular/index.d.ts"));
await writeFile(
path.join(distAngularDir, "index.js"),
'export * from "./angular/index.js";\n',
);
await writeFile(path.join(distAngularDir, "index.d.ts"), 'export * from "./angular/index";\n');

View File

@@ -1,6 +1,19 @@
import { NgModule } from "@angular/core"; import { NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault } from "@angular/common";
import { Directive, ElementRef, Input, OnChanges, Renderer2, SimpleChanges } from "@angular/core"; import {
import { NzTypographyModule } from "ng-zorro-antd/typography"; ChangeDetectionStrategy,
Component,
Directive,
ElementRef,
EventEmitter,
inject,
Input,
NgModule,
OnChanges,
Output,
Renderer2,
SimpleChanges,
} from "@angular/core";
import { NzTypographyComponent, NzTypographyModule } from "ng-zorro-antd/typography";
import { import {
tachTypographyClassList, tachTypographyClassList,
@@ -20,6 +33,18 @@ export interface AngularTypographyRenderOptions extends TypographyRenderOptions
preserveStyle?: Record<string, string | number>; preserveStyle?: Record<string, string | number>;
} }
export type TachTypographyHostTag = "span" | "p" | "a" | "h1" | "h2" | "h3" | "h4";
type NonFunctionNonEmitterKeys<T> = {
[K in keyof T]-?: T[K] extends (...args: never[]) => unknown
? never
: T[K] extends EventEmitter<unknown>
? never
: K;
}[keyof T];
type NzTypographyInputKey = Extract<NonFunctionNonEmitterKeys<NzTypographyComponent>, `nz${string}`>;
export type TachTypographyNzProps = Partial<Pick<NzTypographyComponent, NzTypographyInputKey>>;
export type TachTypographyHostProps = Record<string, unknown>;
const camelToKebab = (value: string): string => const camelToKebab = (value: string): string =>
value.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`); value.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
@@ -133,8 +158,292 @@ export class TachTypographyDirective implements OnChanges {
} }
} }
@Directive({
selector: "[tachTypographyNzProps]",
standalone: true,
})
export class TachTypographyNzPropsDirective implements OnChanges {
@Input() tachTypographyNzProps: TachTypographyNzProps | null | undefined;
private readonly appliedNzKeys = new Set<string>();
private readonly nzTypography = inject(NzTypographyComponent, { self: true, optional: true });
ngOnChanges(): void {
if (!this.nzTypography) {
return;
}
const nzTypography = this.nzTypography as unknown as Record<string, unknown>;
const nextProps = this.tachTypographyNzProps ?? {};
const nextKeys = new Set<string>();
for (const [key, value] of Object.entries(nextProps)) {
if (!key.startsWith("nz")) {
continue;
}
nzTypography[key] = value;
nextKeys.add(key);
}
for (const key of this.appliedNzKeys) {
if (!nextKeys.has(key)) {
nzTypography[key] = undefined;
}
}
this.appliedNzKeys.clear();
for (const key of nextKeys) {
this.appliedNzKeys.add(key);
}
}
}
@Directive({
selector: "[tachTypographyHostProps]",
standalone: true,
})
export class TachTypographyHostPropsDirective implements OnChanges {
@Input() tachTypographyHostProps: TachTypographyHostProps | null | undefined;
private readonly appliedHostProps = new Map<string, "attr" | "prop">();
constructor(
private readonly elementRef: ElementRef<HTMLElement>,
private readonly renderer: Renderer2,
) {}
ngOnChanges(): void {
const nextProps = this.tachTypographyHostProps ?? {};
const nextAppliedProps = new Map<string, "attr" | "prop">();
for (const [key, value] of Object.entries(nextProps)) {
if (key === "class" || key === "className" || key === "style") {
continue;
}
if (value === undefined || value === null) {
continue;
}
const applyAsAttr = this.shouldApplyAsAttribute(key, value);
if (applyAsAttr) {
if (typeof value === "boolean") {
if (value) {
this.renderer.setAttribute(this.elementRef.nativeElement, key, "");
} else {
this.renderer.removeAttribute(this.elementRef.nativeElement, key);
}
} else {
this.renderer.setAttribute(this.elementRef.nativeElement, key, String(value));
}
nextAppliedProps.set(key, "attr");
continue;
}
this.renderer.setProperty(this.elementRef.nativeElement, key, value);
nextAppliedProps.set(key, "prop");
}
for (const [key, kind] of this.appliedHostProps.entries()) {
if (nextAppliedProps.has(key)) {
continue;
}
if (kind === "attr") {
this.renderer.removeAttribute(this.elementRef.nativeElement, key);
} else {
this.renderer.setProperty(this.elementRef.nativeElement, key, undefined);
}
}
this.appliedHostProps.clear();
for (const [key, kind] of nextAppliedProps.entries()) {
this.appliedHostProps.set(key, kind);
}
}
private shouldApplyAsAttribute(key: string, value: unknown): boolean {
if (key.startsWith("data-") || key.startsWith("aria-")) {
return true;
}
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
return !this.hasPropertyOnElement(key);
}
return false;
}
private hasPropertyOnElement(key: string): boolean {
return key in this.elementRef.nativeElement;
}
}
@Component({
selector: "tach-typography",
standalone: true,
imports: [
NzTypographyModule,
TachTypographyDirective,
TachTypographyNzPropsDirective,
TachTypographyHostPropsDirective,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
NgStyle,
],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<ng-container [ngSwitch]="hostTag">
<p
*ngSwitchCase="'p'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</p>
<a
*ngSwitchCase="'a'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</a>
<h1
*ngSwitchCase="'h1'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h1>
<h2
*ngSwitchCase="'h2'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h2>
<h3
*ngSwitchCase="'h3'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h3>
<h4
*ngSwitchCase="'h4'"
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</h4>
<span
*ngSwitchDefault
nz-typography
[tachTypography]="variant"
[tachTypographyColor]="color"
[tachTypographyWeight]="weight"
[tachTypographyClickable]="clickable"
[tachTypographyClassName]="className"
[tachTypographyEllipsis]="ellipsis"
[tachTypographyNzProps]="nzProps"
[tachTypographyHostProps]="hostProps"
[ngStyle]="preserveStyle"
(click)="handleClick($event)"
>
<ng-content />
</span>
</ng-container>
`,
})
export class TachTypographyComponent {
@Input("as") hostTag: TachTypographyHostTag = "span";
@Input() variant: TypographyVariant = "Body";
@Input() color: TypographyColor = "primary";
@Input() weight: TypographyWeight = "normal";
@Input() clickable = false;
@Input() className: string | undefined;
@Input() ellipsis: EllipsisOptions | undefined;
@Input() nzProps: TachTypographyNzProps | undefined;
@Input() hostProps: TachTypographyHostProps | undefined;
@Input() preserveStyle: Record<string, string | number> | undefined;
@Output() readonly tachClick = new EventEmitter<MouseEvent>();
handleClick(event: MouseEvent): void {
this.tachClick.emit(event);
}
}
@NgModule({ @NgModule({
imports: [NzTypographyModule, TachTypographyDirective], imports: [
exports: [NzTypographyModule, TachTypographyDirective], NzTypographyModule,
TachTypographyDirective,
TachTypographyNzPropsDirective,
TachTypographyHostPropsDirective,
TachTypographyComponent,
],
exports: [
NzTypographyModule,
TachTypographyDirective,
TachTypographyNzPropsDirective,
TachTypographyHostPropsDirective,
TachTypographyComponent,
],
}) })
export class TachTypographyNzModule {} export class TachTypographyNzModule {}

View File

@@ -0,0 +1 @@
export * from "./index";

View File

@@ -0,0 +1,20 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist/angular",
"types": ["node"],
"module": "ES2022",
"target": "ES2022",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"importHelpers": true
},
"angularCompilerOptions": {
"compilationMode": "partial"
},
"files": ["src/angular/public-api.ts"],
"include": ["src/angular/**/*.ts", "src/core/**/*.ts"],
"exclude": ["dist", "src/**/*.test.ts", "src/react", "src/stories"]
}

View File

@@ -4,7 +4,6 @@ export default defineConfig({
entry: { entry: {
"core/index": "src/core/index.ts", "core/index": "src/core/index.ts",
"react/index": "src/react/index.tsx", "react/index": "src/react/index.tsx",
"angular/index": "src/angular/index.ts",
}, },
format: ["esm", "cjs"], format: ["esm", "cjs"],
dts: true, dts: true,

View File

@@ -1 +1 @@
{"version":3,"file":"format-time.d.ts","sourceRoot":"","sources":["../../src/core/format-time.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,WAWzC,CAAC"} {"version":3,"file":"format-time.d.ts","sourceRoot":"","sources":["../../src/core/format-time.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,WAazC,CAAC"}

View File

@@ -1,9 +1,10 @@
export const formatTime = (seconds) => { export const formatTime = (seconds) => {
const safeSeconds = Number.isFinite(seconds) && seconds > 0 ? seconds : 0;
const pad = (num) => String(num).padStart(2, "0"); const pad = (num) => String(num).padStart(2, "0");
const hrs = Math.floor(seconds / 3600); const hrs = Math.floor(safeSeconds / 3600);
const mins = Math.floor((seconds % 3600) / 60); const mins = Math.floor((safeSeconds % 3600) / 60);
const secs = Math.floor(seconds % 60); const secs = Math.floor(safeSeconds % 60);
if (seconds < 3600) { if (safeSeconds < 3600) {
return `${pad(mins)}:${pad(secs)}`; return `${pad(mins)}:${pad(secs)}`;
} }
return `${pad(hrs)}:${pad(mins)}:${pad(secs)}`; return `${pad(hrs)}:${pad(mins)}:${pad(secs)}`;

View File

@@ -1 +1 @@
{"version":3,"file":"format-time.js","sourceRoot":"","sources":["../../src/core/format-time.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IAC7C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IAEtC,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;QACpB,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;IACpC,CAAC;IAED,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAChD,CAAC,CAAC"} {"version":3,"file":"format-time.js","sourceRoot":"","sources":["../../src/core/format-time.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IAC7C,MAAM,WAAW,GAChB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;IAE1C,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QACxB,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;IACpC,CAAC;IAED,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAChD,CAAC,CAAC"}

View File

@@ -131,6 +131,7 @@ export declare class VideoPlayerRuntime {
private attachDurationAndPlayStartHooks; private attachDurationAndPlayStartHooks;
private loadCurrentSource; private loadCurrentSource;
private buildHlsConfig; private buildHlsConfig;
private syncLiveUi;
private loadHlsSource; private loadHlsSource;
private loadVideoJsSource; private loadVideoJsSource;
private resetDeferredHlsLoading; private resetDeferredHlsLoading;

View File

@@ -1 +1 @@
{"version":3,"file":"player-runtime.d.ts","sourceRoot":"","sources":["../../src/core/player-runtime.ts"],"names":[],"mappings":"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"} {"version":3,"file":"player-runtime.d.ts","sourceRoot":"","sources":["../../src/core/player-runtime.ts"],"names":[],"mappings":"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"}

View File

@@ -465,6 +465,24 @@ export class VideoPlayerRuntime {
pLoader: playlistLoader, pLoader: playlistLoader,
}; };
} }
syncLiveUi(player, video, isLive) {
const wrapper = video.parentElement;
if (isLive) {
wrapper?.classList.add("vjs-hls-live", "vjs-live");
player.duration(Infinity);
if (player.liveTracker) {
player.liveTracker.isLive_ = true;
player.liveTracker.startTracking();
player.liveTracker.trigger("durationchange");
}
return;
}
wrapper?.classList.remove("vjs-hls-live", "vjs-live");
if (player.liveTracker) {
player.liveTracker.isLive_ = false;
player.liveTracker.trigger("durationchange");
}
}
async loadHlsSource() { async loadHlsSource() {
const options = this.options; const options = this.options;
const player = this.playerRef; const player = this.playerRef;
@@ -508,19 +526,27 @@ export class VideoPlayerRuntime {
duration: details?.totalduration, duration: details?.totalduration,
live: details?.live, live: details?.live,
}); });
if (details?.live) { if (typeof details?.live === "boolean") {
video.parentElement?.classList.add("vjs-hls-live", "vjs-live"); this.syncLiveUi(player, video, details.live);
player.duration(Infinity);
if (player.liveTracker) {
player.liveTracker.isLive_ = true;
player.liveTracker.startTracking();
player.liveTracker.trigger("durationchange");
}
} }
if (options.initialTime > 0) { if (options.initialTime > 0) {
hls.startLoad(options.initialTime); hls.startLoad(options.initialTime);
} }
}); });
hls.on(Hls.Events.LEVEL_LOADED, (_event, data) => {
const details = data?.details;
if (!details) {
return;
}
this.emit("manifestloaded", {
engine: "hls",
duration: details.totalduration,
live: details.live,
});
if (typeof details.live === "boolean") {
this.syncLiveUi(player, video, details.live);
}
});
hls.on(Hls.Events.FRAG_CHANGED, () => { hls.on(Hls.Events.FRAG_CHANGED, () => {
if (player.liveTracker) { if (player.liveTracker) {
player.liveTracker.atLiveEdge = isAtLiveEdge; player.liveTracker.atLiveEdge = isAtLiveEdge;
@@ -722,10 +748,8 @@ export class VideoPlayerRuntime {
const videoElement = this.playerRef const videoElement = this.playerRef
.el() .el()
?.querySelector("video"); ?.querySelector("video");
videoElement?.parentElement?.classList.remove("vjs-hls-live", "vjs-live"); if (videoElement) {
if (this.playerRef.liveTracker) { this.syncLiveUi(this.playerRef, videoElement, false);
this.playerRef.liveTracker.isLive_ = false;
this.playerRef.liveTracker.trigger("durationchange");
} }
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/react/video-player/components/video-js/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,WASzC,CAAC"} {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/react/video-player/components/video-js/utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,WAWzC,CAAC"}

View File

@@ -1,9 +1,10 @@
export const formatTime = (seconds) => { export const formatTime = (seconds) => {
const safeSeconds = Number.isFinite(seconds) && seconds > 0 ? seconds : 0;
const pad = (num) => String(num).padStart(2, "0"); const pad = (num) => String(num).padStart(2, "0");
const hrs = Math.floor(seconds / 3600); const hrs = Math.floor(safeSeconds / 3600);
const mins = Math.floor((seconds % 3600) / 60); const mins = Math.floor((safeSeconds % 3600) / 60);
const secs = Math.floor(seconds % 60); const secs = Math.floor(safeSeconds % 60);
if (seconds < 3600) { if (safeSeconds < 3600) {
return `${pad(mins)}:${pad(secs)}`; return `${pad(mins)}:${pad(secs)}`;
} }
return `${pad(hrs)}:${pad(mins)}:${pad(secs)}`; return `${pad(hrs)}:${pad(mins)}:${pad(secs)}`;

View File

@@ -1 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/react/video-player/components/video-js/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IAC7C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;QACpB,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAChD,CAAC,CAAC"} {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../src/react/video-player/components/video-js/utils.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,EAAE;IAC7C,MAAM,WAAW,GAChB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;IAC1C,IAAI,WAAW,GAAG,IAAI,EAAE,CAAC;QACxB,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAChD,CAAC,CAAC"}

View File

@@ -1,6 +1,6 @@
{ {
"name": "@hublib-web/video-player", "name": "@hublib-web/video-player",
"version": "0.1.2", "version": "0.1.3",
"description": "Cross-framework video player package for React and Angular", "description": "Cross-framework video player package for React and Angular",
"license": "MIT", "license": "MIT",
"type": "module", "type": "module",

View File

@@ -1,10 +1,12 @@
export const formatTime = (seconds: number) => { export const formatTime = (seconds: number) => {
const safeSeconds =
Number.isFinite(seconds) && seconds > 0 ? seconds : 0;
const pad = (num: number) => String(num).padStart(2, "0"); const pad = (num: number) => String(num).padStart(2, "0");
const hrs = Math.floor(seconds / 3600); const hrs = Math.floor(safeSeconds / 3600);
const mins = Math.floor((seconds % 3600) / 60); const mins = Math.floor((safeSeconds % 3600) / 60);
const secs = Math.floor(seconds % 60); const secs = Math.floor(safeSeconds % 60);
if (seconds < 3600) { if (safeSeconds < 3600) {
return `${pad(mins)}:${pad(secs)}`; return `${pad(mins)}:${pad(secs)}`;
} }

View File

@@ -718,6 +718,31 @@ export class VideoPlayerRuntime {
}; };
} }
private syncLiveUi(
player: VideoPlayerRuntimePlayer,
video: HTMLVideoElement,
isLive: boolean,
) {
const wrapper = video.parentElement;
if (isLive) {
wrapper?.classList.add("vjs-hls-live", "vjs-live");
player.duration(Infinity);
if (player.liveTracker) {
player.liveTracker.isLive_ = true;
player.liveTracker.startTracking();
player.liveTracker.trigger("durationchange");
}
return;
}
wrapper?.classList.remove("vjs-hls-live", "vjs-live");
if (player.liveTracker) {
player.liveTracker.isLive_ = false;
player.liveTracker.trigger("durationchange");
}
}
private async loadHlsSource() { private async loadHlsSource() {
const options = this.options; const options = this.options;
const player = this.playerRef; const player = this.playerRef;
@@ -769,14 +794,8 @@ export class VideoPlayerRuntime {
live: details?.live, live: details?.live,
}); });
if (details?.live) { if (typeof details?.live === "boolean") {
video.parentElement?.classList.add("vjs-hls-live", "vjs-live"); this.syncLiveUi(player, video, details.live);
player.duration(Infinity);
if (player.liveTracker) {
player.liveTracker.isLive_ = true;
player.liveTracker.startTracking();
player.liveTracker.trigger("durationchange");
}
} }
if (options.initialTime > 0) { if (options.initialTime > 0) {
@@ -784,6 +803,22 @@ export class VideoPlayerRuntime {
} }
}); });
hls.on(Hls.Events.LEVEL_LOADED, (_event, data) => {
const details = data?.details;
if (!details) {
return;
}
this.emit("manifestloaded", {
engine: "hls",
duration: details.totalduration,
live: details.live,
});
if (typeof details.live === "boolean") {
this.syncLiveUi(player, video, details.live);
}
});
hls.on(Hls.Events.FRAG_CHANGED, () => { hls.on(Hls.Events.FRAG_CHANGED, () => {
if (player.liveTracker) { if (player.liveTracker) {
player.liveTracker.atLiveEdge = isAtLiveEdge; player.liveTracker.atLiveEdge = isAtLiveEdge;
@@ -1034,10 +1069,8 @@ export class VideoPlayerRuntime {
const videoElement = this.playerRef const videoElement = this.playerRef
.el() .el()
?.querySelector("video") as HTMLVideoElement | null; ?.querySelector("video") as HTMLVideoElement | null;
videoElement?.parentElement?.classList.remove("vjs-hls-live", "vjs-live"); if (videoElement) {
if (this.playerRef.liveTracker) { this.syncLiveUi(this.playerRef, videoElement, false);
this.playerRef.liveTracker.isLive_ = false;
this.playerRef.liveTracker.trigger("durationchange");
} }
} }
} }

View File

@@ -1,9 +1,11 @@
export const formatTime = (seconds: number) => { export const formatTime = (seconds: number) => {
const safeSeconds =
Number.isFinite(seconds) && seconds > 0 ? seconds : 0;
const pad = (num: number) => String(num).padStart(2, "0"); const pad = (num: number) => String(num).padStart(2, "0");
const hrs = Math.floor(seconds / 3600); const hrs = Math.floor(safeSeconds / 3600);
const mins = Math.floor((seconds % 3600) / 60); const mins = Math.floor((safeSeconds % 3600) / 60);
const secs = Math.floor(seconds % 60); const secs = Math.floor(safeSeconds % 60);
if (seconds < 3600) { if (safeSeconds < 3600) {
return `${pad(mins)}:${pad(secs)}`; return `${pad(mins)}:${pad(secs)}`;
} }
return `${pad(hrs)}:${pad(mins)}:${pad(secs)}`; return `${pad(hrs)}:${pad(mins)}:${pad(secs)}`;

389
yarn.lock
View File

@@ -12,6 +12,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ampproject/remapping@npm:^2.2.0":
version: 2.3.0
resolution: "@ampproject/remapping@npm:2.3.0"
dependencies:
"@jridgewell/gen-mapping": "npm:^0.3.5"
"@jridgewell/trace-mapping": "npm:^0.3.24"
checksum: 10c0/81d63cca5443e0f0c72ae18b544cc28c7c0ec2cea46e7cb888bb0e0f411a1191d0d6b7af798d54e30777d8d1488b2ec0732aac2be342d3d7d3ffd271c6f489ed
languageName: node
linkType: hard
"@angular/animations@npm:^20.3.17": "@angular/animations@npm:^20.3.17":
version: 20.3.17 version: 20.3.17
resolution: "@angular/animations@npm:20.3.17" resolution: "@angular/animations@npm:20.3.17"
@@ -49,6 +59,40 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@angular/compiler-cli@npm:^20.3.17":
version: 20.3.18
resolution: "@angular/compiler-cli@npm:20.3.18"
dependencies:
"@babel/core": "npm:7.28.3"
"@jridgewell/sourcemap-codec": "npm:^1.4.14"
chokidar: "npm:^4.0.0"
convert-source-map: "npm:^1.5.1"
reflect-metadata: "npm:^0.2.0"
semver: "npm:^7.0.0"
tslib: "npm:^2.3.0"
yargs: "npm:^18.0.0"
peerDependencies:
"@angular/compiler": 20.3.18
typescript: ">=5.8 <6.0"
peerDependenciesMeta:
typescript:
optional: true
bin:
ng-xi18n: bundles/src/bin/ng_xi18n.js
ngc: bundles/src/bin/ngc.js
checksum: 10c0/db6ed45caea752782dc5c35c4f2152435f78a43ca0610f74a0ed098f67bac8dea97ded7a37b108e6f333ce3e086f21dc76ea2e76f1464e91723d17bb1bca3de3
languageName: node
linkType: hard
"@angular/compiler@npm:^20.3.17":
version: 20.3.18
resolution: "@angular/compiler@npm:20.3.18"
dependencies:
tslib: "npm:^2.3.0"
checksum: 10c0/b8149a45e007eb5fc056f9b39b0e0eebb22e2e816027c7aed03ac884a08b5030c51e4b698865580bf253eb1e06c072da797ac318376979dd8cb98a65da535961
languageName: node
linkType: hard
"@angular/core@npm:^20.3.17": "@angular/core@npm:^20.3.17":
version: 20.3.17 version: 20.3.17
resolution: "@angular/core@npm:20.3.17" resolution: "@angular/core@npm:20.3.17"
@@ -230,7 +274,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": "@babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.27.1, @babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0":
version: 7.29.0 version: 7.29.0
resolution: "@babel/code-frame@npm:7.29.0" resolution: "@babel/code-frame@npm:7.29.0"
dependencies: dependencies:
@@ -248,6 +292,29 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/core@npm:7.28.3":
version: 7.28.3
resolution: "@babel/core@npm:7.28.3"
dependencies:
"@ampproject/remapping": "npm:^2.2.0"
"@babel/code-frame": "npm:^7.27.1"
"@babel/generator": "npm:^7.28.3"
"@babel/helper-compilation-targets": "npm:^7.27.2"
"@babel/helper-module-transforms": "npm:^7.28.3"
"@babel/helpers": "npm:^7.28.3"
"@babel/parser": "npm:^7.28.3"
"@babel/template": "npm:^7.27.2"
"@babel/traverse": "npm:^7.28.3"
"@babel/types": "npm:^7.28.2"
convert-source-map: "npm:^2.0.0"
debug: "npm:^4.1.0"
gensync: "npm:^1.0.0-beta.2"
json5: "npm:^2.2.3"
semver: "npm:^6.3.1"
checksum: 10c0/e6b3eb830c4b93f5a442b305776df1cd2bb4fafa4612355366f67c764f3e54a69d45b84def77fb2d4fd83439102667b0a92c3ea2838f678733245b748c602a7b
languageName: node
linkType: hard
"@babel/core@npm:^7.18.9": "@babel/core@npm:^7.18.9":
version: 7.29.0 version: 7.29.0
resolution: "@babel/core@npm:7.29.0" resolution: "@babel/core@npm:7.29.0"
@@ -271,7 +338,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/generator@npm:^7.29.0": "@babel/generator@npm:^7.28.3, @babel/generator@npm:^7.29.0":
version: 7.29.1 version: 7.29.1
resolution: "@babel/generator@npm:7.29.1" resolution: "@babel/generator@npm:7.29.1"
dependencies: dependencies:
@@ -284,7 +351,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-compilation-targets@npm:^7.28.6": "@babel/helper-compilation-targets@npm:^7.27.2, @babel/helper-compilation-targets@npm:^7.28.6":
version: 7.28.6 version: 7.28.6
resolution: "@babel/helper-compilation-targets@npm:7.28.6" resolution: "@babel/helper-compilation-targets@npm:7.28.6"
dependencies: dependencies:
@@ -314,7 +381,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-module-transforms@npm:^7.28.6": "@babel/helper-module-transforms@npm:^7.28.3, @babel/helper-module-transforms@npm:^7.28.6":
version: 7.28.6 version: 7.28.6
resolution: "@babel/helper-module-transforms@npm:7.28.6" resolution: "@babel/helper-module-transforms@npm:7.28.6"
dependencies: dependencies:
@@ -348,6 +415,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helpers@npm:^7.28.3":
version: 7.29.2
resolution: "@babel/helpers@npm:7.29.2"
dependencies:
"@babel/template": "npm:^7.28.6"
"@babel/types": "npm:^7.29.0"
checksum: 10c0/dab0e65b9318b2502a62c58bc0913572318595eec0482c31f0ad416b72636e6698a1d7c57cd2791d4528eb8c548bca88d338dc4d2a55a108dc1f6702f9bc5512
languageName: node
linkType: hard
"@babel/helpers@npm:^7.28.6": "@babel/helpers@npm:^7.28.6":
version: 7.28.6 version: 7.28.6
resolution: "@babel/helpers@npm:7.28.6" resolution: "@babel/helpers@npm:7.28.6"
@@ -369,6 +446,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/parser@npm:^7.28.3":
version: 7.29.2
resolution: "@babel/parser@npm:7.29.2"
dependencies:
"@babel/types": "npm:^7.29.0"
bin:
parser: ./bin/babel-parser.js
checksum: 10c0/e5a4e69e3ac7acdde995f37cf299a68458cfe7009dff66bd0962fd04920bef287201169006af365af479c08ff216bfefbb595e331f87f6ae7283858aebbc3317
languageName: node
linkType: hard
"@babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.4, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.7, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.6, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.28.4, @babel/runtime@npm:^7.5.5": "@babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.4, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.7, @babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.6, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.28.4, @babel/runtime@npm:^7.5.5":
version: 7.28.6 version: 7.28.6
resolution: "@babel/runtime@npm:7.28.6" resolution: "@babel/runtime@npm:7.28.6"
@@ -376,7 +464,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/template@npm:^7.28.6": "@babel/template@npm:^7.27.2, @babel/template@npm:^7.28.6":
version: 7.28.6 version: 7.28.6
resolution: "@babel/template@npm:7.28.6" resolution: "@babel/template@npm:7.28.6"
dependencies: dependencies:
@@ -387,7 +475,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": "@babel/traverse@npm:^7.18.9, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0":
version: 7.29.0 version: 7.29.0
resolution: "@babel/traverse@npm:7.29.0" resolution: "@babel/traverse@npm:7.29.0"
dependencies: dependencies:
@@ -797,7 +885,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@eslint-community/eslint-utils@npm:^4.8.0": "@eslint-community/eslint-utils@npm:^4.8.0, @eslint-community/eslint-utils@npm:^4.9.1":
version: 4.9.1 version: 4.9.1
resolution: "@eslint-community/eslint-utils@npm:4.9.1" resolution: "@eslint-community/eslint-utils@npm:4.9.1"
dependencies: dependencies:
@@ -808,7 +896,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@eslint-community/regexpp@npm:^4.12.1": "@eslint-community/regexpp@npm:^4.12.1, @eslint-community/regexpp@npm:^4.12.2":
version: 4.12.2 version: 4.12.2
resolution: "@eslint-community/regexpp@npm:4.12.2" resolution: "@eslint-community/regexpp@npm:4.12.2"
checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d
@@ -949,6 +1037,7 @@ __metadata:
prettier: "npm:^3.6.2" prettier: "npm:^3.6.2"
storybook: "npm:8.6.14" storybook: "npm:8.6.14"
typescript: "npm:^5.9.3" typescript: "npm:^5.9.3"
typescript-eslint: "npm:^8.57.0"
vitest: "npm:^3.2.4" vitest: "npm:^3.2.4"
languageName: unknown languageName: unknown
linkType: soft linkType: soft
@@ -959,6 +1048,8 @@ __metadata:
dependencies: dependencies:
"@angular/animations": "npm:^20.3.17" "@angular/animations": "npm:^20.3.17"
"@angular/common": "npm:^20.3.17" "@angular/common": "npm:^20.3.17"
"@angular/compiler": "npm:^20.3.17"
"@angular/compiler-cli": "npm:^20.3.17"
"@angular/core": "npm:^20.3.17" "@angular/core": "npm:^20.3.17"
"@angular/forms": "npm:^20.3.17" "@angular/forms": "npm:^20.3.17"
"@angular/platform-browser": "npm:^20.3.17" "@angular/platform-browser": "npm:^20.3.17"
@@ -976,6 +1067,7 @@ __metadata:
react-dom: "npm:^19.2.0" react-dom: "npm:^19.2.0"
rxjs: "npm:^7.8.2" rxjs: "npm:^7.8.2"
storybook: "npm:8.6.14" storybook: "npm:8.6.14"
tslib: "npm:^2.8.1"
tsup: "npm:^8.5.0" tsup: "npm:^8.5.0"
typescript: "npm:^5.9.3" typescript: "npm:^5.9.3"
vite: "npm:6.4.1" vite: "npm:6.4.1"
@@ -2299,6 +2391,141 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/eslint-plugin@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/eslint-plugin@npm:8.57.0"
dependencies:
"@eslint-community/regexpp": "npm:^4.12.2"
"@typescript-eslint/scope-manager": "npm:8.57.0"
"@typescript-eslint/type-utils": "npm:8.57.0"
"@typescript-eslint/utils": "npm:8.57.0"
"@typescript-eslint/visitor-keys": "npm:8.57.0"
ignore: "npm:^7.0.5"
natural-compare: "npm:^1.4.0"
ts-api-utils: "npm:^2.4.0"
peerDependencies:
"@typescript-eslint/parser": ^8.57.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/600033b98dd96e11bb0e22ff77dcaa0f9e9135b60046267059296ce8c8870dfabcddf40d5c8b62415eb3e2133e77a1fb1ac08dca42b859533dd85fbba1f220f7
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/parser@npm:8.57.0"
dependencies:
"@typescript-eslint/scope-manager": "npm:8.57.0"
"@typescript-eslint/types": "npm:8.57.0"
"@typescript-eslint/typescript-estree": "npm:8.57.0"
"@typescript-eslint/visitor-keys": "npm:8.57.0"
debug: "npm:^4.4.3"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/c224e0802cdc42ad7c79553018d6572370eff6539b3cb92220e44da3931dfe7e94a11fcea7d30d9c9366e76d50488c8c9d59002ba52dd6818fdc598280f7990c
languageName: node
linkType: hard
"@typescript-eslint/project-service@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/project-service@npm:8.57.0"
dependencies:
"@typescript-eslint/tsconfig-utils": "npm:^8.57.0"
"@typescript-eslint/types": "npm:^8.57.0"
debug: "npm:^4.4.3"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/f97c25ad9c39957fc58fba21dbc8ce928d3889f95b0ecc93b477da3ce9bb6057bf866cac8114c0c93c455f68d0fb5b0042dc4771e436f07cd9c975bc61f3221f
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/scope-manager@npm:8.57.0"
dependencies:
"@typescript-eslint/types": "npm:8.57.0"
"@typescript-eslint/visitor-keys": "npm:8.57.0"
checksum: 10c0/a3e1243044f4634a36308f0d027db97ef686ed88cb93183feee1ba0a6de4eaa8824bb63b79075241c0a275d989d5f2641a6341cc785a6c688ee6f0d05c07d723
languageName: node
linkType: hard
"@typescript-eslint/tsconfig-utils@npm:8.57.0, @typescript-eslint/tsconfig-utils@npm:^8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/tsconfig-utils@npm:8.57.0"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/d63f4de1a9d39c208b05a93df838318ff48af0a6ae561395d1860a8fd1fc552d47cc08065c445e084fb67bfac1c5a477183213477ed2bca688b9409cbeda3965
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/type-utils@npm:8.57.0"
dependencies:
"@typescript-eslint/types": "npm:8.57.0"
"@typescript-eslint/typescript-estree": "npm:8.57.0"
"@typescript-eslint/utils": "npm:8.57.0"
debug: "npm:^4.4.3"
ts-api-utils: "npm:^2.4.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/55fd3b6b71d76602cead51fe3ea246eb908e2614bbe092fae26d9320f73c2f107e82d28e2cf509b61ea5f29d5b1fa32046bef0823cea63105bc35c15319e95ec
languageName: node
linkType: hard
"@typescript-eslint/types@npm:8.57.0, @typescript-eslint/types@npm:^8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/types@npm:8.57.0"
checksum: 10c0/69eb21a9a550f17ce9445b7bfab9099d6a43fa33f79506df966793077d73423dad7612f33a7efb1e09f4403a889ba6b7a44987cf3e6fea0e63a373022226bc68
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/typescript-estree@npm:8.57.0"
dependencies:
"@typescript-eslint/project-service": "npm:8.57.0"
"@typescript-eslint/tsconfig-utils": "npm:8.57.0"
"@typescript-eslint/types": "npm:8.57.0"
"@typescript-eslint/visitor-keys": "npm:8.57.0"
debug: "npm:^4.4.3"
minimatch: "npm:^10.2.2"
semver: "npm:^7.7.3"
tinyglobby: "npm:^0.2.15"
ts-api-utils: "npm:^2.4.0"
peerDependencies:
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/2b72ff255b6711d529496bcae38869e3809b15761252809743d80d01e3efa5a62ebaafc24b96b16a245a8d0bd307958a3e9ab31434d03a87acedbdd5e01c18be
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/utils@npm:8.57.0"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.9.1"
"@typescript-eslint/scope-manager": "npm:8.57.0"
"@typescript-eslint/types": "npm:8.57.0"
"@typescript-eslint/typescript-estree": "npm:8.57.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/d2c5803a7eaae71ce4cf1435fdc0ab0243e8924647b39bc823e42bc7604f6e01cdcb101eaf9c0eec91fe1bd272e5533041b8a40017679b164be11f32242f292b
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:8.57.0":
version: 8.57.0
resolution: "@typescript-eslint/visitor-keys@npm:8.57.0"
dependencies:
"@typescript-eslint/types": "npm:8.57.0"
eslint-visitor-keys: "npm:^5.0.0"
checksum: 10c0/4e585126b7b10f04c8d52166a473b715038793c87c7b7a1dbd0f577b017896db8545d6ea13bd191c12cf951dfdac23884b3e9bf0bb6f44afea38ae9eae5d7a6a
languageName: node
linkType: hard
"@videojs/http-streaming@npm:^3.17.2, @videojs/http-streaming@npm:^3.17.4": "@videojs/http-streaming@npm:^3.17.2, @videojs/http-streaming@npm:^3.17.4":
version: 3.17.4 version: 3.17.4
resolution: "@videojs/http-streaming@npm:3.17.4" resolution: "@videojs/http-streaming@npm:3.17.4"
@@ -2592,7 +2819,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ansi-styles@npm:^6.1.0": "ansi-styles@npm:^6.1.0, ansi-styles@npm:^6.2.1":
version: 6.2.3 version: 6.2.3
resolution: "ansi-styles@npm:6.2.3" resolution: "ansi-styles@npm:6.2.3"
checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868 checksum: 10c0/23b8a4ce14e18fb854693b95351e286b771d23d8844057ed2e7d083cd3e708376c3323707ec6a24365f7d7eda3ca00327fe04092e29e551499ec4c8b7bfac868
@@ -2970,6 +3197,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"cliui@npm:^9.0.1":
version: 9.0.1
resolution: "cliui@npm:9.0.1"
dependencies:
string-width: "npm:^7.2.0"
strip-ansi: "npm:^7.1.0"
wrap-ansi: "npm:^9.0.0"
checksum: 10c0/13441832e9efe7c7a76bd2b8e683555c478d461a9f249dc5db9b17fe8d4b47fa9277b503914b90bd00e4a151abb6b9b02b2288972ffe2e5e3ca40bcb1c2330d3
languageName: node
linkType: hard
"color-convert@npm:^2.0.1": "color-convert@npm:^2.0.1":
version: 2.0.1 version: 2.0.1
resolution: "color-convert@npm:2.0.1" resolution: "color-convert@npm:2.0.1"
@@ -3030,6 +3268,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"convert-source-map@npm:^1.5.1":
version: 1.9.0
resolution: "convert-source-map@npm:1.9.0"
checksum: 10c0/281da55454bf8126cbc6625385928c43479f2060984180c42f3a86c8b8c12720a24eac260624a7d1e090004028d2dee78602330578ceec1a08e27cb8bb0a8a5b
languageName: node
linkType: hard
"convert-source-map@npm:^2.0.0": "convert-source-map@npm:^2.0.0":
version: 2.0.0 version: 2.0.0
resolution: "convert-source-map@npm:2.0.0" resolution: "convert-source-map@npm:2.0.0"
@@ -3107,7 +3352,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1": "debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1, debug@npm:^4.4.3":
version: 4.4.3 version: 4.4.3
resolution: "debug@npm:4.4.3" resolution: "debug@npm:4.4.3"
dependencies: dependencies:
@@ -3243,6 +3488,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"emoji-regex@npm:^10.3.0":
version: 10.6.0
resolution: "emoji-regex@npm:10.6.0"
checksum: 10c0/1e4aa097bb007301c3b4b1913879ae27327fdc48e93eeefefe3b87e495eb33c5af155300be951b4349ff6ac084f4403dc9eff970acba7c1c572d89396a9a32d7
languageName: node
linkType: hard
"emoji-regex@npm:^8.0.0": "emoji-regex@npm:^8.0.0":
version: 8.0.0 version: 8.0.0
resolution: "emoji-regex@npm:8.0.0" resolution: "emoji-regex@npm:8.0.0"
@@ -3502,7 +3754,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"escalade@npm:^3.2.0": "escalade@npm:^3.1.1, escalade@npm:^3.2.0":
version: 3.2.0 version: 3.2.0
resolution: "escalade@npm:3.2.0" resolution: "escalade@npm:3.2.0"
checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65
@@ -3540,6 +3792,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-visitor-keys@npm:^5.0.0":
version: 5.0.1
resolution: "eslint-visitor-keys@npm:5.0.1"
checksum: 10c0/16190bdf2cbae40a1109384c94450c526a79b0b9c3cb21e544256ed85ac48a4b84db66b74a6561d20fe6ab77447f150d711c2ad5ad74df4fcc133736bce99678
languageName: node
linkType: hard
"eslint@npm:^9.37.0": "eslint@npm:^9.37.0":
version: 9.39.3 version: 9.39.3
resolution: "eslint@npm:9.39.3" resolution: "eslint@npm:9.39.3"
@@ -3833,6 +4092,20 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"get-caller-file@npm:^2.0.5":
version: 2.0.5
resolution: "get-caller-file@npm:2.0.5"
checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde
languageName: node
linkType: hard
"get-east-asian-width@npm:^1.0.0":
version: 1.5.0
resolution: "get-east-asian-width@npm:1.5.0"
checksum: 10c0/bff8bbc8d81790b9477f7aa55b1806b9f082a8dc1359fff7bd8b96939622c86b729685afc2bfeb22def1fc6ef1e5228e4d87dd4e6da60bc43a5edfb03c4ee167
languageName: node
linkType: hard
"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0": "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.3.0":
version: 1.3.1 version: 1.3.1
resolution: "get-intrinsic@npm:1.3.1" resolution: "get-intrinsic@npm:1.3.1"
@@ -4061,6 +4334,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ignore@npm:^7.0.5":
version: 7.0.5
resolution: "ignore@npm:7.0.5"
checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d
languageName: node
linkType: hard
"immutable@npm:^5.0.2": "immutable@npm:^5.0.2":
version: 5.1.5 version: 5.1.5
resolution: "immutable@npm:5.1.5" resolution: "immutable@npm:5.1.5"
@@ -5802,6 +6082,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"reflect-metadata@npm:^0.2.0":
version: 0.2.2
resolution: "reflect-metadata@npm:0.2.2"
checksum: 10c0/1cd93a15ea291e420204955544637c264c216e7aac527470e393d54b4bb075f10a17e60d8168ec96600c7e0b9fcc0cb0bb6e91c3fbf5b0d8c9056f04e6ac1ec2
languageName: node
linkType: hard
"requires-port@npm:^1.0.0": "requires-port@npm:^1.0.0":
version: 1.0.0 version: 1.0.0
resolution: "requires-port@npm:1.0.0" resolution: "requires-port@npm:1.0.0"
@@ -6045,7 +6332,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"semver@npm:^7.3.5, semver@npm:^7.6.2": "semver@npm:^7.0.0, semver@npm:^7.3.5, semver@npm:^7.6.2, semver@npm:^7.7.3":
version: 7.7.4 version: 7.7.4
resolution: "semver@npm:7.7.4" resolution: "semver@npm:7.7.4"
bin: bin:
@@ -6217,6 +6504,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"string-width@npm:^7.0.0, string-width@npm:^7.2.0":
version: 7.2.0
resolution: "string-width@npm:7.2.0"
dependencies:
emoji-regex: "npm:^10.3.0"
get-east-asian-width: "npm:^1.0.0"
strip-ansi: "npm:^7.1.0"
checksum: 10c0/eb0430dd43f3199c7a46dcbf7a0b34539c76fe3aa62763d0b0655acdcbdf360b3f66f3d58ca25ba0205f42ea3491fa00f09426d3b7d3040e506878fc7664c9b9
languageName: node
linkType: hard
"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
version: 6.0.1 version: 6.0.1
resolution: "strip-ansi@npm:6.0.1" resolution: "strip-ansi@npm:6.0.1"
@@ -6226,7 +6524,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"strip-ansi@npm:^7.0.1": "strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0":
version: 7.2.0 version: 7.2.0
resolution: "strip-ansi@npm:7.2.0" resolution: "strip-ansi@npm:7.2.0"
dependencies: dependencies:
@@ -6463,6 +6761,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"ts-api-utils@npm:^2.4.0":
version: 2.4.0
resolution: "ts-api-utils@npm:2.4.0"
peerDependencies:
typescript: ">=4.8.4"
checksum: 10c0/ed185861aef4e7124366a3f6561113557a57504267d4d452a51e0ba516a9b6e713b56b4aeaab9fa13de9db9ab755c65c8c13a777dba9133c214632cb7b65c083
languageName: node
linkType: hard
"ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0": "ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0":
version: 2.2.0 version: 2.2.0
resolution: "ts-dedent@npm:2.2.0" resolution: "ts-dedent@npm:2.2.0"
@@ -6488,7 +6795,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.3.0": "tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.8.1":
version: 2.8.1 version: 2.8.1
resolution: "tslib@npm:2.8.1" resolution: "tslib@npm:2.8.1"
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
@@ -6546,6 +6853,21 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"typescript-eslint@npm:^8.57.0":
version: 8.57.0
resolution: "typescript-eslint@npm:8.57.0"
dependencies:
"@typescript-eslint/eslint-plugin": "npm:8.57.0"
"@typescript-eslint/parser": "npm:8.57.0"
"@typescript-eslint/typescript-estree": "npm:8.57.0"
"@typescript-eslint/utils": "npm:8.57.0"
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: ">=4.8.4 <6.0.0"
checksum: 10c0/5491c6dff2bc3f2914d60326490316b3f92e022756017da8b36cbb9d4d94fc781b642a3a033ca3add2ff26ee7a95798baedc5f55598cd21ce706bae5b7731632
languageName: node
linkType: hard
"typescript@npm:5.9.3, typescript@npm:^5.9.3": "typescript@npm:5.9.3, typescript@npm:^5.9.3":
version: 5.9.3 version: 5.9.3
resolution: "typescript@npm:5.9.3" resolution: "typescript@npm:5.9.3"
@@ -7061,6 +7383,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"wrap-ansi@npm:^9.0.0":
version: 9.0.2
resolution: "wrap-ansi@npm:9.0.2"
dependencies:
ansi-styles: "npm:^6.2.1"
string-width: "npm:^7.0.0"
strip-ansi: "npm:^7.1.0"
checksum: 10c0/3305839b9a0d6fb930cb63a52f34d3936013d8b0682ff3ec133c9826512620f213800ffa19ea22904876d5b7e9a3c1f40682f03597d986a4ca881fa7b033688c
languageName: node
linkType: hard
"ws@npm:^8.13.0, ws@npm:^8.2.3": "ws@npm:^8.13.0, ws@npm:^8.2.3":
version: 8.19.0 version: 8.19.0
resolution: "ws@npm:8.19.0" resolution: "ws@npm:8.19.0"
@@ -7090,6 +7423,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"y18n@npm:^5.0.5":
version: 5.0.8
resolution: "y18n@npm:5.0.8"
checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249
languageName: node
linkType: hard
"yallist@npm:^3.0.2": "yallist@npm:^3.0.2":
version: 3.1.1 version: 3.1.1
resolution: "yallist@npm:3.1.1" resolution: "yallist@npm:3.1.1"
@@ -7111,6 +7451,27 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"yargs-parser@npm:^22.0.0":
version: 22.0.0
resolution: "yargs-parser@npm:22.0.0"
checksum: 10c0/cb7ef81759c4271cb1d96b9351dbbc9a9ce35d3e1122d2b739bf6c432603824fa02c67cc12dcef6ea80283379d63495686e8f41cc7b06c6576e792aba4d33e1c
languageName: node
linkType: hard
"yargs@npm:^18.0.0":
version: 18.0.0
resolution: "yargs@npm:18.0.0"
dependencies:
cliui: "npm:^9.0.1"
escalade: "npm:^3.1.1"
get-caller-file: "npm:^2.0.5"
string-width: "npm:^7.2.0"
y18n: "npm:^5.0.5"
yargs-parser: "npm:^22.0.0"
checksum: 10c0/bf290e4723876ea9c638c786a5c42ac28e03c9ca2325e1424bf43b94e5876456292d3ed905b853ebbba6daf43ed29e772ac2a6b3c5fb1b16533245d6211778f3
languageName: node
linkType: hard
"yocto-queue@npm:^0.1.0": "yocto-queue@npm:^0.1.0":
version: 0.1.0 version: 0.1.0
resolution: "yocto-queue@npm:0.1.0" resolution: "yocto-queue@npm:0.1.0"