@lifecorner/angular-ui-kit 3.21.1 → 3.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-tree-view.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/tree-view/file-icons.ts","../../../../libs/angular-ui-kit/src/lib/tree-view/tree-view.component.ts","../../../../libs/angular-ui-kit/src/lib/tree-view/tree-view.component.html"],"sourcesContent":["/**\n * File-type → icon mapping for the TreeView component.\n *\n * Icon names refer to Tabler Icons (the design system's icon source).\n * Resolution order for a file node:\n * 1. explicit `node.icon`\n * 2. exact file name match (e.g. `package.json`, `Dockerfile`)\n * 3. file extension match (e.g. `.ts`, `.png`)\n * 4. generic file fallback\n */\n\n/** Icon used for collapsed folders. */\nexport const FOLDER_ICON = 'folder';\n/** Icon used for expanded (open) folders. */\nexport const FOLDER_OPEN_ICON = 'folder-open';\n/** Generic fallback icon for files with no specific match. */\nexport const FILE_FALLBACK_ICON = 'file';\n\n/** Map of well-known file names (lower-cased) to icons. */\nconst FILE_NAME_ICONS: Record<string, string> = {\n 'package.json': 'brand-npm',\n 'package-lock.json': 'brand-npm',\n 'yarn.lock': 'brand-yarn',\n 'pnpm-lock.yaml': 'brand-pnpm',\n 'dockerfile': 'brand-docker',\n 'docker-compose.yml': 'brand-docker',\n 'docker-compose.yaml': 'brand-docker',\n '.gitignore': 'brand-git',\n '.gitattributes': 'brand-git',\n '.gitmodules': 'brand-git',\n 'readme.md': 'book',\n 'license': 'license',\n 'license.md': 'license',\n '.env': 'key',\n '.env.local': 'key',\n '.editorconfig': 'settings',\n '.prettierrc': 'settings',\n '.eslintrc': 'settings',\n 'tsconfig.json': 'brand-typescript',\n 'angular.json': 'brand-angular',\n 'nx.json': 'settings',\n 'makefile': 'terminal',\n};\n\n/** Map of file extensions (without dot, lower-cased) to icons. */\nconst FILE_EXT_ICONS: Record<string, string> = {\n // Languages\n ts: 'brand-typescript',\n tsx: 'brand-typescript',\n js: 'brand-javascript',\n jsx: 'brand-javascript',\n mjs: 'brand-javascript',\n cjs: 'brand-javascript',\n html: 'brand-html5',\n htm: 'brand-html5',\n css: 'brand-css3',\n scss: 'brand-sass',\n sass: 'brand-sass',\n less: 'brand-css3',\n py: 'brand-python',\n rb: 'diamond',\n go: 'brand-golang',\n rs: 'brand-rust',\n java: 'coffee',\n kt: 'brand-kotlin',\n swift: 'brand-swift',\n c: 'file-code',\n h: 'file-code',\n cpp: 'brand-cpp',\n cs: 'brand-c-sharp',\n php: 'brand-php',\n dart: 'brand-flutter',\n sh: 'terminal-2',\n bash: 'terminal-2',\n zsh: 'terminal-2',\n sql: 'database',\n // Data / config\n json: 'braces',\n jsonc: 'braces',\n yml: 'file-code',\n yaml: 'file-code',\n toml: 'file-code',\n xml: 'file-code',\n ini: 'settings',\n env: 'key',\n // Docs\n md: 'markdown',\n mdx: 'markdown',\n txt: 'file-text',\n pdf: 'file-type-pdf',\n doc: 'file-text',\n docx: 'file-text',\n csv: 'file-spreadsheet',\n xls: 'file-spreadsheet',\n xlsx: 'file-spreadsheet',\n // Images\n png: 'photo',\n jpg: 'photo',\n jpeg: 'photo',\n gif: 'photo',\n webp: 'photo',\n svg: 'file-vector',\n ico: 'photo',\n bmp: 'photo',\n // Media\n mp3: 'music',\n wav: 'music',\n mp4: 'video',\n mov: 'video',\n webm: 'video',\n // Archives\n zip: 'file-zip',\n tar: 'file-zip',\n gz: 'file-zip',\n rar: 'file-zip',\n '7z': 'file-zip',\n // Fonts\n woff: 'typography',\n woff2: 'typography',\n ttf: 'typography',\n otf: 'typography',\n // Misc\n lock: 'lock',\n};\n\n/**\n * Resolve the icon name for a file based on its name.\n * Performs exact-name then extension lookup, falling back to a generic file icon.\n */\nexport function resolveFileIcon(fileName: string): string {\n const lower = fileName.toLowerCase();\n\n const byName = FILE_NAME_ICONS[lower];\n if (byName) return byName;\n\n const dotIndex = lower.lastIndexOf('.');\n if (dotIndex > 0 && dotIndex < lower.length - 1) {\n const ext = lower.slice(dotIndex + 1);\n const byExt = FILE_EXT_ICONS[ext];\n if (byExt) return byExt;\n }\n\n return FILE_FALLBACK_ICON;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport {\n ICON_CHECK,\n ICON_CHEVRON_RIGHT,\n ICON_FILE,\n ICON_FILE_TEXT,\n ICON_KEY,\n ICON_SETTINGS,\n} from '@lifecorner/angular-ui-kit/icons';\nimport {\n FILE_FALLBACK_ICON,\n FOLDER_ICON,\n FOLDER_OPEN_ICON,\n resolveFileIcon,\n} from './file-icons';\n\n// ── Public types ─────────────────────────────────────────────────────────────\n\n/**\n * Node type. `'file'` and `'folder'` get the built-in file-tree treatment\n * (extension icons, folder open/close icons). Any other string marks a custom\n * domain type: such nodes render a colored type dot (or an explicit `icon`)\n * instead of file icons.\n */\nexport type TreeNodeType = 'file' | 'folder' | (string & {});\n\nexport type TreeNodeStatus =\n | 'default'\n | 'added'\n | 'modified'\n | 'removed'\n | 'muted'\n | 'success'\n | 'busy';\n\n/**\n * A node in the tree. Any node carrying `children` can expand — this covers\n * file trees (folders) as well as arbitrary domain hierarchies.\n */\nexport interface TreeNode {\n /** Display name, e.g. `app.component.ts` or `src`. */\n name: string;\n /**\n * Node type. Optional — inferred as `folder` when `children` is present,\n * otherwise `file`. May be any string for domain hierarchies.\n */\n type?: TreeNodeType;\n /**\n * Stable identifier. Optional — when omitted, the full path is used,\n * which is stable as long as names are unique among siblings.\n */\n id?: string;\n /** Child nodes. Any node with children can expand / collapse. */\n children?: TreeNode[];\n /**\n * Explicit Tabler icon name. Overrides automatic file-type / folder\n * icon resolution and the custom-type dot.\n */\n icon?: string;\n /**\n * Accent color for the node's icon / type dot. Any CSS color, including\n * `var(--…)` token references.\n */\n color?: string;\n /** Optional badge text shown to the right of the node (e.g. git status, count). */\n badge?: string;\n /**\n * Tone of the badge / node accent. `success` additionally renders a ✓\n * indicator, `busy` a pulsing dot (static under `prefers-reduced-motion`).\n */\n status?: TreeNodeStatus;\n /** Whether this node starts expanded. Ignored for nodes without children. */\n expanded?: boolean;\n /** Disable selection / interaction for this node. */\n disabled?: boolean;\n}\n\n// ── Internal flattened representation ─────────────────────────────────────────\n\ninterface FlatNode {\n id: string;\n name: string;\n type: TreeNodeType;\n depth: number;\n hasChildren: boolean;\n expanded: boolean;\n /** Resolved icon, or `null` for custom-type nodes that render a type dot. */\n icon: string | null;\n color?: string;\n badge?: string;\n status: TreeNodeStatus;\n disabled: boolean;\n /** Whether each ancestor level still has following siblings (for guide lines). */\n ancestorHasSibling: boolean[];\n /** Whether this node is the last among its siblings. */\n isLast: boolean;\n /** 1-based position among its siblings (aria-posinset). */\n posInSet: number;\n /** Number of siblings including itself (aria-setsize). */\n setSize: number;\n /** Id of the parent node, `null` for root nodes. */\n parentId: string | null;\n}\n\nconst BADGE_STATUS_COLOR: Record<TreeNodeStatus, string> = {\n default: 'var(--color-text-tertiary)',\n added: 'var(--color-success-default, #16a34a)',\n modified: 'var(--color-warning-default, #d97706)',\n removed: 'var(--color-error-default, #dc2626)',\n muted: 'var(--color-text-disabled)',\n success: 'var(--color-success-default, #16a34a)',\n busy: 'var(--color-primary-500, #6366f1)',\n};\n\nfunction nodeType(node: TreeNode): TreeNodeType {\n return node.type ?? (node.children ? 'folder' : 'file');\n}\n\nfunction isExpandable(node: TreeNode): boolean {\n return !!node.children?.length;\n}\n\n/**\n * Tree view component for visualizing hierarchies — file / folder trees as\n * well as arbitrary domain object trees with custom node types.\n *\n * Features:\n * - Recursive rendering from a single `nodes` input; any node with children\n * can expand / collapse\n * - Automatic file-type icons by extension and well-known file name,\n * with open / closed folder icons (for `file` / `folder` nodes)\n * - Custom node types: colored type dots or explicit icons via `type`,\n * `color`, `icon`\n * - Expand / collapse, with expand-all / collapse-all helpers\n * - Two-way bound selection and a `nodeClick` event\n * - Indentation guide lines for readability\n * - Optional per-node status badges (added / modified / removed) and status\n * indicators (`success` ✓, `busy` pulse)\n * - Keyboard accessible: roving tabindex (one tab stop), Arrow keys / Home /\n * End move focus, Enter / Space toggle or select, Left / Right collapse /\n * expand or move to parent / first child\n * - Dark / light theme support via design tokens\n *\n * @example\n * ```html\n * <lc-tree-view [nodes]=\"projectTree\" [(selectedId)]=\"selected\" />\n * ```\n */\n@Component({\n selector: 'lc-tree-view',\n standalone: true,\n imports: [IconComponent],\n // Its own glyphs and the inline ones of the built-in file-type map (file-icons.ts).\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_RIGHT, ICON_CHECK, ICON_FILE, ICON_FILE_TEXT, ICON_KEY, ICON_SETTINGS])],\n templateUrl: './tree-view.component.html',\n styleUrls: ['./tree-view.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'lc-tree-view' },\n})\nexport class TreeViewComponent {\n /** The root-level nodes of the tree. */\n readonly nodes = input.required<TreeNode[]>();\n\n /** Id (or path) of the currently selected node (two-way bindable). */\n readonly selectedId = model<string | null>(null);\n\n /** Show indentation guide lines. */\n readonly showGuides = input(true);\n\n /** Show the expand-all / collapse-all toolbar. */\n readonly showToolbar = input(true);\n\n /** Label of the toolbar's expand-all button. */\n readonly expandAllLabel = input('Expand all');\n\n /** Label of the toolbar's collapse-all button. */\n readonly collapseAllLabel = input('Collapse all');\n\n /** Icon size for node icons. */\n readonly iconSize = input<'xs' | 'sm' | 'md'>('sm');\n\n /** Accessible name of a folder's expand toggle. */\n readonly expandAriaLabel = input('Expand');\n\n /** Accessible name of a folder's collapse toggle. */\n readonly collapseAriaLabel = input('Collapse');\n\n /** Emitted when a node is clicked / activated. */\n readonly nodeClick = output<TreeNode>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** Set of node ids the user has explicitly expanded / collapsed. */\n private readonly expandOverrides = signal<Map<string, boolean>>(new Map());\n\n /** Id of the node that last had keyboard focus (roving tabindex). */\n private readonly focusedId = signal<string | null>(null);\n\n /** Flattened, render-ready list of visible nodes. */\n protected readonly visibleNodes = computed<FlatNode[]>(() => {\n const out: FlatNode[] = [];\n const overrides = this.expandOverrides();\n this.flatten(this.nodes(), 0, '', [], overrides, out, null);\n return out;\n });\n\n /**\n * The single tab stop of the tree: the last focused node if it is still\n * visible, else the selected node, else the first enabled node.\n */\n protected readonly tabStopId = computed<string | null>(() => {\n const nodes = this.visibleNodes();\n const focusable = (id: string | null) =>\n id !== null && nodes.some((n) => n.id === id && !n.disabled);\n const focused = this.focusedId();\n if (focusable(focused)) return focused;\n const selected = this.selectedId();\n if (focusable(selected)) return selected;\n return nodes.find((n) => !n.disabled)?.id ?? null;\n });\n\n protected badgeColor(status: TreeNodeStatus): string {\n return BADGE_STATUS_COLOR[status];\n }\n\n protected onNodeClick(flat: FlatNode): void {\n if (flat.disabled) return;\n if (flat.hasChildren) {\n this.toggle(flat);\n }\n this.selectedId.set(flat.id);\n const original = this.findNode(this.nodes(), '', flat.id);\n if (original) this.nodeClick.emit(original);\n }\n\n protected onToggleClick(flat: FlatNode, event: Event): void {\n event.stopPropagation();\n if (!flat.disabled) this.toggle(flat);\n }\n\n protected onFocus(flat: FlatNode): void {\n this.focusedId.set(flat.id);\n }\n\n protected onKeydown(flat: FlatNode, event: KeyboardEvent): void {\n if (flat.disabled) return;\n const nodes = this.visibleNodes();\n const index = nodes.findIndex((n) => n.id === flat.id);\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.onNodeClick(flat);\n break;\n case 'ArrowRight':\n event.preventDefault();\n if (!flat.hasChildren) return;\n if (!flat.expanded) {\n this.setExpanded(flat.id, true);\n } else {\n // Expanded: move to the first child.\n this.focusIndex(index + 1);\n }\n break;\n case 'ArrowLeft':\n event.preventDefault();\n if (flat.hasChildren && flat.expanded) {\n this.setExpanded(flat.id, false);\n } else if (flat.parentId !== null) {\n // Leaf or collapsed node: move to the parent.\n this.focusIndex(nodes.findIndex((n) => n.id === flat.parentId));\n }\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, index, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, index, -1));\n break;\n case 'Home':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, -1, 1));\n break;\n case 'End':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, nodes.length, -1));\n break;\n }\n }\n\n /** Expand every folder in the tree. */\n expandAll(): void {\n this.setAll(true);\n }\n\n /** Collapse every folder in the tree. */\n collapseAll(): void {\n this.setAll(false);\n }\n\n protected trackById = (_: number, n: FlatNode): string => n.id;\n\n // ── internals ──────────────────────────────────────────────────────────────\n\n /** Index of the next enabled node from `from` in direction `dir`, or -1. */\n private nextEnabled(nodes: FlatNode[], from: number, dir: 1 | -1): number {\n for (let i = from + dir; i >= 0 && i < nodes.length; i += dir) {\n if (!nodes[i].disabled) return i;\n }\n return -1;\n }\n\n /**\n * Moves keyboard focus to the visible node at `index`. The rows are\n * rendered in `visibleNodes()` order, so the index maps 1:1 to the DOM.\n */\n private focusIndex(index: number): void {\n const nodes = this.visibleNodes();\n if (index < 0 || index >= nodes.length || nodes[index].disabled) return;\n this.focusedId.set(nodes[index].id);\n const items = this.host.nativeElement.querySelectorAll<HTMLElement>('.lc-tree-view__item');\n items[index]?.focus();\n }\n\n private toggle(flat: FlatNode): void {\n this.setExpanded(flat.id, !flat.expanded);\n }\n\n private setExpanded(id: string, value: boolean): void {\n this.expandOverrides.update((map) => {\n const next = new Map(map);\n next.set(id, value);\n return next;\n });\n }\n\n private setAll(value: boolean): void {\n const next = new Map<string, boolean>();\n const walk = (nodes: TreeNode[], parentPath: string): void => {\n for (const node of nodes) {\n const id = node.id ?? `${parentPath}/${node.name}`;\n if (node.children?.length) {\n next.set(id, value);\n walk(node.children, id);\n }\n }\n };\n walk(this.nodes(), '');\n this.expandOverrides.set(next);\n }\n\n private isExpanded(\n id: string,\n node: TreeNode,\n overrides: Map<string, boolean>,\n ): boolean {\n const override = overrides.get(id);\n if (override !== undefined) return override;\n return node.expanded ?? false;\n }\n\n private flatten(\n nodes: TreeNode[],\n depth: number,\n parentPath: string,\n ancestorHasSibling: boolean[],\n overrides: Map<string, boolean>,\n out: FlatNode[],\n parentId: string | null,\n ): void {\n nodes.forEach((node, index) => {\n const id = node.id ?? `${parentPath}/${node.name}`;\n const type = nodeType(node);\n const hasChildren = isExpandable(node);\n const expanded = hasChildren && this.isExpanded(id, node, overrides);\n const isLast = index === nodes.length - 1;\n\n out.push({\n id,\n name: node.name,\n type,\n depth,\n hasChildren,\n expanded,\n icon: this.resolveIcon(node, type, expanded),\n color: node.color,\n badge: node.badge,\n status: node.status ?? 'default',\n disabled: node.disabled ?? false,\n ancestorHasSibling,\n isLast,\n posInSet: index + 1,\n setSize: nodes.length,\n parentId,\n });\n\n if (expanded && node.children) {\n this.flatten(\n node.children,\n depth + 1,\n id,\n [...ancestorHasSibling, !isLast],\n overrides,\n out,\n id,\n );\n }\n });\n }\n\n private resolveIcon(\n node: TreeNode,\n type: TreeNodeType,\n expanded: boolean,\n ): string | null {\n if (node.icon) return node.icon;\n if (type === 'folder') return expanded ? FOLDER_OPEN_ICON : FOLDER_ICON;\n if (type === 'file') {\n return node.name ? resolveFileIcon(node.name) : FILE_FALLBACK_ICON;\n }\n // Custom domain type without explicit icon: render a colored type dot.\n return null;\n }\n\n private findNode(\n nodes: TreeNode[],\n parentPath: string,\n targetId: string,\n ): TreeNode | null {\n for (const node of nodes) {\n const id = node.id ?? `${parentPath}/${node.name}`;\n if (id === targetId) return node;\n if (node.children) {\n const found = this.findNode(node.children, id, targetId);\n if (found) return found;\n }\n }\n return null;\n }\n}\n","@if (showToolbar()) {\n <div class=\"lc-tree-view__toolbar\">\n <button type=\"button\" class=\"lc-tree-view__tool-btn\" (click)=\"expandAll()\" [attr.title]=\"expandAllLabel()\">\n <lc-icon name=\"fold-down\" size=\"xs\" [decorative]=\"true\" />\n <span>{{ expandAllLabel() }}</span>\n </button>\n <button type=\"button\" class=\"lc-tree-view__tool-btn\" (click)=\"collapseAll()\" [attr.title]=\"collapseAllLabel()\">\n <lc-icon name=\"fold-up\" size=\"xs\" [decorative]=\"true\" />\n <span>{{ collapseAllLabel() }}</span>\n </button>\n </div>\n}\n\n<ul class=\"lc-tree-view__list\" role=\"tree\">\n @for (node of visibleNodes(); track trackById($index, node)) {\n <li\n class=\"lc-tree-view__item\"\n [class.lc-tree-view__item--selected]=\"node.id === selectedId()\"\n [class.lc-tree-view__item--disabled]=\"node.disabled\"\n [class.lc-tree-view__item--folder]=\"node.type === 'folder'\"\n role=\"treeitem\"\n [attr.aria-level]=\"node.depth + 1\"\n [attr.aria-posinset]=\"node.posInSet\"\n [attr.aria-setsize]=\"node.setSize\"\n [attr.aria-expanded]=\"node.hasChildren ? node.expanded : null\"\n [attr.aria-selected]=\"node.id === selectedId()\"\n [attr.aria-disabled]=\"node.disabled ? true : null\"\n [attr.aria-busy]=\"node.status === 'busy' ? true : null\"\n [tabindex]=\"node.id === tabStopId() ? 0 : -1\"\n (focus)=\"onFocus(node)\"\n (click)=\"onNodeClick(node)\"\n (keydown)=\"onKeydown(node, $event)\"\n >\n <!-- indentation + guide lines -->\n @for (hasSibling of node.ancestorHasSibling; track $index) {\n <span\n class=\"lc-tree-view__indent\"\n [class.lc-tree-view__indent--guide]=\"showGuides() && hasSibling\"\n ></span>\n }\n\n <!-- expand / collapse chevron -->\n <span class=\"lc-tree-view__chevron\">\n @if (node.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-tree-view__chevron-btn\"\n [class.lc-tree-view__chevron-btn--expanded]=\"node.expanded\"\n (click)=\"onToggleClick(node, $event)\"\n [attr.aria-label]=\"node.expanded ? collapseAriaLabel() : expandAriaLabel()\"\n tabindex=\"-1\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n\n <!-- type / file icon, or type dot for custom node types -->\n <span\n class=\"lc-tree-view__icon\"\n [style.color]=\"\n node.color ?? (node.status === 'default' ? null : badgeColor(node.status))\n \"\n >\n @if (node.icon; as icon) {\n <lc-icon [name]=\"icon\" [size]=\"iconSize()\" [decorative]=\"true\" />\n } @else {\n <span\n class=\"lc-tree-view__type-dot\"\n [style.background-color]=\"node.color ?? null\"\n ></span>\n }\n </span>\n\n <!-- label -->\n <span class=\"lc-tree-view__label\">{{ node.name }}</span>\n\n <!-- badge -->\n @if (node.badge) {\n <span\n class=\"lc-tree-view__badge\"\n [style.color]=\"badgeColor(node.status)\"\n [style.border-color]=\"badgeColor(node.status)\"\n >{{ node.badge }}</span\n >\n }\n\n <!-- status indicator -->\n @if (node.status === 'success') {\n <span class=\"lc-tree-view__status lc-tree-view__status--success\">\n <lc-icon name=\"check\" size=\"xs\" [decorative]=\"true\" />\n </span>\n } @else if (node.status === 'busy') {\n <span class=\"lc-tree-view__status lc-tree-view__status--busy\"></span>\n }\n </li>\n }\n</ul>\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-tree-view.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/tree-view/file-icons.ts","../../../../libs/angular-ui-kit/src/lib/tree-view/tree-view.component.ts","../../../../libs/angular-ui-kit/src/lib/tree-view/tree-view.component.html"],"sourcesContent":["/**\n * File-type → icon mapping for the TreeView component.\n *\n * Icon names refer to Tabler Icons (the design system's icon source).\n * Resolution order for a file node:\n * 1. explicit `node.icon`\n * 2. exact file name match (e.g. `package.json`, `Dockerfile`)\n * 3. file extension match (e.g. `.ts`, `.png`)\n * 4. generic file fallback\n */\n\n/** Icon used for collapsed folders. */\nexport const FOLDER_ICON = 'folder';\n/** Icon used for expanded (open) folders. */\nexport const FOLDER_OPEN_ICON = 'folder-open';\n/** Generic fallback icon for files with no specific match. */\nexport const FILE_FALLBACK_ICON = 'file';\n\n/** Map of well-known file names (lower-cased) to icons. */\nconst FILE_NAME_ICONS: Record<string, string> = {\n 'package.json': 'brand-npm',\n 'package-lock.json': 'brand-npm',\n 'yarn.lock': 'brand-yarn',\n 'pnpm-lock.yaml': 'brand-pnpm',\n 'dockerfile': 'brand-docker',\n 'docker-compose.yml': 'brand-docker',\n 'docker-compose.yaml': 'brand-docker',\n '.gitignore': 'brand-git',\n '.gitattributes': 'brand-git',\n '.gitmodules': 'brand-git',\n 'readme.md': 'book',\n 'license': 'license',\n 'license.md': 'license',\n '.env': 'key',\n '.env.local': 'key',\n '.editorconfig': 'settings',\n '.prettierrc': 'settings',\n '.eslintrc': 'settings',\n 'tsconfig.json': 'brand-typescript',\n 'angular.json': 'brand-angular',\n 'nx.json': 'settings',\n 'makefile': 'terminal',\n};\n\n/** Map of file extensions (without dot, lower-cased) to icons. */\nconst FILE_EXT_ICONS: Record<string, string> = {\n // Languages\n ts: 'brand-typescript',\n tsx: 'brand-typescript',\n js: 'brand-javascript',\n jsx: 'brand-javascript',\n mjs: 'brand-javascript',\n cjs: 'brand-javascript',\n html: 'brand-html5',\n htm: 'brand-html5',\n css: 'brand-css3',\n scss: 'brand-sass',\n sass: 'brand-sass',\n less: 'brand-css3',\n py: 'brand-python',\n rb: 'diamond',\n go: 'brand-golang',\n rs: 'brand-rust',\n java: 'coffee',\n kt: 'brand-kotlin',\n swift: 'brand-swift',\n c: 'file-code',\n h: 'file-code',\n cpp: 'brand-cpp',\n cs: 'brand-c-sharp',\n php: 'brand-php',\n dart: 'brand-flutter',\n sh: 'terminal-2',\n bash: 'terminal-2',\n zsh: 'terminal-2',\n sql: 'database',\n // Data / config\n json: 'braces',\n jsonc: 'braces',\n yml: 'file-code',\n yaml: 'file-code',\n toml: 'file-code',\n xml: 'file-code',\n ini: 'settings',\n env: 'key',\n // Docs\n md: 'markdown',\n mdx: 'markdown',\n txt: 'file-text',\n pdf: 'file-type-pdf',\n doc: 'file-text',\n docx: 'file-text',\n csv: 'file-spreadsheet',\n xls: 'file-spreadsheet',\n xlsx: 'file-spreadsheet',\n // Images\n png: 'photo',\n jpg: 'photo',\n jpeg: 'photo',\n gif: 'photo',\n webp: 'photo',\n svg: 'file-vector',\n ico: 'photo',\n bmp: 'photo',\n // Media\n mp3: 'music',\n wav: 'music',\n mp4: 'video',\n mov: 'video',\n webm: 'video',\n // Archives\n zip: 'file-zip',\n tar: 'file-zip',\n gz: 'file-zip',\n rar: 'file-zip',\n '7z': 'file-zip',\n // Fonts\n woff: 'typography',\n woff2: 'typography',\n ttf: 'typography',\n otf: 'typography',\n // Misc\n lock: 'lock',\n};\n\n/**\n * Resolve the icon name for a file based on its name.\n * Performs exact-name then extension lookup, falling back to a generic file icon.\n */\nexport function resolveFileIcon(fileName: string): string {\n const lower = fileName.toLowerCase();\n\n const byName = FILE_NAME_ICONS[lower];\n if (byName) return byName;\n\n const dotIndex = lower.lastIndexOf('.');\n if (dotIndex > 0 && dotIndex < lower.length - 1) {\n const ext = lower.slice(dotIndex + 1);\n const byExt = FILE_EXT_ICONS[ext];\n if (byExt) return byExt;\n }\n\n return FILE_FALLBACK_ICON;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport {\n ICON_CHECK,\n ICON_CHEVRON_RIGHT,\n ICON_FILE,\n ICON_FILE_TEXT,\n ICON_KEY,\n ICON_LOCK,\n ICON_SETTINGS,\n} from '@lifecorner/angular-ui-kit/icons';\nimport {\n FILE_FALLBACK_ICON,\n FOLDER_ICON,\n FOLDER_OPEN_ICON,\n resolveFileIcon,\n} from './file-icons';\n\n// ── Public types ─────────────────────────────────────────────────────────────\n\n/**\n * Node type. `'file'` and `'folder'` get the built-in file-tree treatment\n * (extension icons, folder open/close icons). Any other string marks a custom\n * domain type: such nodes render a colored type dot (or an explicit `icon`)\n * instead of file icons.\n */\nexport type TreeNodeType = 'file' | 'folder' | (string & {});\n\nexport type TreeNodeStatus =\n | 'default'\n | 'added'\n | 'modified'\n | 'removed'\n | 'muted'\n | 'success'\n | 'busy';\n\n/**\n * A node in the tree. Any node carrying `children` can expand — this covers\n * file trees (folders) as well as arbitrary domain hierarchies.\n */\nexport interface TreeNode {\n /** Display name, e.g. `app.component.ts` or `src`. */\n name: string;\n /**\n * Node type. Optional — inferred as `folder` when `children` is present,\n * otherwise `file`. May be any string for domain hierarchies.\n */\n type?: TreeNodeType;\n /**\n * Stable identifier. Optional — when omitted, the full path is used,\n * which is stable as long as names are unique among siblings.\n */\n id?: string;\n /** Child nodes. Any node with children can expand / collapse. */\n children?: TreeNode[];\n /**\n * Explicit Tabler icon name. Overrides automatic file-type / folder\n * icon resolution and the custom-type dot.\n */\n icon?: string;\n /**\n * Accent color for the node's icon / type dot. Any CSS color, including\n * `var(--…)` token references.\n */\n color?: string;\n /** Optional badge text shown to the right of the node (e.g. git status, count). */\n badge?: string;\n /**\n * Tone of the badge / node accent. `success` additionally renders a ✓\n * indicator, `busy` a pulsing dot (static under `prefers-reduced-motion`).\n */\n status?: TreeNodeStatus;\n /** Whether this node starts expanded. Ignored for nodes without children. */\n expanded?: boolean;\n /** Disable selection / interaction for this node. */\n disabled?: boolean;\n}\n\n// ── Internal flattened representation ─────────────────────────────────────────\n\ninterface FlatNode {\n id: string;\n name: string;\n type: TreeNodeType;\n depth: number;\n hasChildren: boolean;\n expanded: boolean;\n /** Resolved icon, or `null` for custom-type nodes that render a type dot. */\n icon: string | null;\n color?: string;\n badge?: string;\n status: TreeNodeStatus;\n disabled: boolean;\n /** Whether each ancestor level still has following siblings (for guide lines). */\n ancestorHasSibling: boolean[];\n /** Whether this node is the last among its siblings. */\n isLast: boolean;\n /** 1-based position among its siblings (aria-posinset). */\n posInSet: number;\n /** Number of siblings including itself (aria-setsize). */\n setSize: number;\n /** Id of the parent node, `null` for root nodes. */\n parentId: string | null;\n}\n\nconst BADGE_STATUS_COLOR: Record<TreeNodeStatus, string> = {\n default: 'var(--color-text-tertiary)',\n added: 'var(--color-success-default, #16a34a)',\n modified: 'var(--color-warning-default, #d97706)',\n removed: 'var(--color-error-default, #dc2626)',\n muted: 'var(--color-text-disabled)',\n success: 'var(--color-success-default, #16a34a)',\n busy: 'var(--color-primary-500, #6366f1)',\n};\n\nfunction nodeType(node: TreeNode): TreeNodeType {\n return node.type ?? (node.children ? 'folder' : 'file');\n}\n\nfunction isExpandable(node: TreeNode): boolean {\n return !!node.children?.length;\n}\n\n/**\n * Tree view component for visualizing hierarchies — file / folder trees as\n * well as arbitrary domain object trees with custom node types.\n *\n * Features:\n * - Recursive rendering from a single `nodes` input; any node with children\n * can expand / collapse\n * - Automatic file-type icons by extension and well-known file name,\n * with open / closed folder icons (for `file` / `folder` nodes)\n * - Custom node types: colored type dots or explicit icons via `type`,\n * `color`, `icon`\n * - Expand / collapse, with expand-all / collapse-all helpers\n * - Two-way bound selection and a `nodeClick` event\n * - Indentation guide lines for readability\n * - Optional per-node status badges (added / modified / removed) and status\n * indicators (`success` ✓, `busy` pulse)\n * - Keyboard accessible: roving tabindex (one tab stop), Arrow keys / Home /\n * End move focus, Enter / Space toggle or select, Left / Right collapse /\n * expand or move to parent / first child\n * - Dark / light theme support via design tokens\n *\n * @example\n * ```html\n * <lc-tree-view [nodes]=\"projectTree\" [(selectedId)]=\"selected\" />\n * ```\n */\n@Component({\n selector: 'lc-tree-view',\n standalone: true,\n imports: [IconComponent],\n // Its own glyphs and the inline ones of the built-in file-type map (file-icons.ts).\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_RIGHT, ICON_CHECK, ICON_FILE, ICON_FILE_TEXT, ICON_KEY, ICON_LOCK, ICON_SETTINGS])],\n templateUrl: './tree-view.component.html',\n styleUrls: ['./tree-view.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'lc-tree-view' },\n})\nexport class TreeViewComponent {\n /** The root-level nodes of the tree. */\n readonly nodes = input.required<TreeNode[]>();\n\n /** Id (or path) of the currently selected node (two-way bindable). */\n readonly selectedId = model<string | null>(null);\n\n /** Show indentation guide lines. */\n readonly showGuides = input(true);\n\n /** Show the expand-all / collapse-all toolbar. */\n readonly showToolbar = input(true);\n\n /** Label of the toolbar's expand-all button. */\n readonly expandAllLabel = input('Expand all');\n\n /** Label of the toolbar's collapse-all button. */\n readonly collapseAllLabel = input('Collapse all');\n\n /** Icon size for node icons. */\n readonly iconSize = input<'xs' | 'sm' | 'md'>('sm');\n\n /** Accessible name of a folder's expand toggle. */\n readonly expandAriaLabel = input('Expand');\n\n /** Accessible name of a folder's collapse toggle. */\n readonly collapseAriaLabel = input('Collapse');\n\n /** Emitted when a node is clicked / activated. */\n readonly nodeClick = output<TreeNode>();\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** Set of node ids the user has explicitly expanded / collapsed. */\n private readonly expandOverrides = signal<Map<string, boolean>>(new Map());\n\n /** Id of the node that last had keyboard focus (roving tabindex). */\n private readonly focusedId = signal<string | null>(null);\n\n /** Flattened, render-ready list of visible nodes. */\n protected readonly visibleNodes = computed<FlatNode[]>(() => {\n const out: FlatNode[] = [];\n const overrides = this.expandOverrides();\n this.flatten(this.nodes(), 0, '', [], overrides, out, null);\n return out;\n });\n\n /**\n * The single tab stop of the tree: the last focused node if it is still\n * visible, else the selected node, else the first enabled node.\n */\n protected readonly tabStopId = computed<string | null>(() => {\n const nodes = this.visibleNodes();\n const focusable = (id: string | null) =>\n id !== null && nodes.some((n) => n.id === id && !n.disabled);\n const focused = this.focusedId();\n if (focusable(focused)) return focused;\n const selected = this.selectedId();\n if (focusable(selected)) return selected;\n return nodes.find((n) => !n.disabled)?.id ?? null;\n });\n\n protected badgeColor(status: TreeNodeStatus): string {\n return BADGE_STATUS_COLOR[status];\n }\n\n protected onNodeClick(flat: FlatNode): void {\n if (flat.disabled) return;\n if (flat.hasChildren) {\n this.toggle(flat);\n }\n this.selectedId.set(flat.id);\n const original = this.findNode(this.nodes(), '', flat.id);\n if (original) this.nodeClick.emit(original);\n }\n\n protected onToggleClick(flat: FlatNode, event: Event): void {\n event.stopPropagation();\n if (!flat.disabled) this.toggle(flat);\n }\n\n protected onFocus(flat: FlatNode): void {\n this.focusedId.set(flat.id);\n }\n\n protected onKeydown(flat: FlatNode, event: KeyboardEvent): void {\n if (flat.disabled) return;\n const nodes = this.visibleNodes();\n const index = nodes.findIndex((n) => n.id === flat.id);\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n event.preventDefault();\n this.onNodeClick(flat);\n break;\n case 'ArrowRight':\n event.preventDefault();\n if (!flat.hasChildren) return;\n if (!flat.expanded) {\n this.setExpanded(flat.id, true);\n } else {\n // Expanded: move to the first child.\n this.focusIndex(index + 1);\n }\n break;\n case 'ArrowLeft':\n event.preventDefault();\n if (flat.hasChildren && flat.expanded) {\n this.setExpanded(flat.id, false);\n } else if (flat.parentId !== null) {\n // Leaf or collapsed node: move to the parent.\n this.focusIndex(nodes.findIndex((n) => n.id === flat.parentId));\n }\n break;\n case 'ArrowDown':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, index, 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, index, -1));\n break;\n case 'Home':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, -1, 1));\n break;\n case 'End':\n event.preventDefault();\n this.focusIndex(this.nextEnabled(nodes, nodes.length, -1));\n break;\n }\n }\n\n /** Expand every folder in the tree. */\n expandAll(): void {\n this.setAll(true);\n }\n\n /** Collapse every folder in the tree. */\n collapseAll(): void {\n this.setAll(false);\n }\n\n protected trackById = (_: number, n: FlatNode): string => n.id;\n\n // ── internals ──────────────────────────────────────────────────────────────\n\n /** Index of the next enabled node from `from` in direction `dir`, or -1. */\n private nextEnabled(nodes: FlatNode[], from: number, dir: 1 | -1): number {\n for (let i = from + dir; i >= 0 && i < nodes.length; i += dir) {\n if (!nodes[i].disabled) return i;\n }\n return -1;\n }\n\n /**\n * Moves keyboard focus to the visible node at `index`. The rows are\n * rendered in `visibleNodes()` order, so the index maps 1:1 to the DOM.\n */\n private focusIndex(index: number): void {\n const nodes = this.visibleNodes();\n if (index < 0 || index >= nodes.length || nodes[index].disabled) return;\n this.focusedId.set(nodes[index].id);\n const items = this.host.nativeElement.querySelectorAll<HTMLElement>('.lc-tree-view__item');\n items[index]?.focus();\n }\n\n private toggle(flat: FlatNode): void {\n this.setExpanded(flat.id, !flat.expanded);\n }\n\n private setExpanded(id: string, value: boolean): void {\n this.expandOverrides.update((map) => {\n const next = new Map(map);\n next.set(id, value);\n return next;\n });\n }\n\n private setAll(value: boolean): void {\n const next = new Map<string, boolean>();\n const walk = (nodes: TreeNode[], parentPath: string): void => {\n for (const node of nodes) {\n const id = node.id ?? `${parentPath}/${node.name}`;\n if (node.children?.length) {\n next.set(id, value);\n walk(node.children, id);\n }\n }\n };\n walk(this.nodes(), '');\n this.expandOverrides.set(next);\n }\n\n private isExpanded(\n id: string,\n node: TreeNode,\n overrides: Map<string, boolean>,\n ): boolean {\n const override = overrides.get(id);\n if (override !== undefined) return override;\n return node.expanded ?? false;\n }\n\n private flatten(\n nodes: TreeNode[],\n depth: number,\n parentPath: string,\n ancestorHasSibling: boolean[],\n overrides: Map<string, boolean>,\n out: FlatNode[],\n parentId: string | null,\n ): void {\n nodes.forEach((node, index) => {\n const id = node.id ?? `${parentPath}/${node.name}`;\n const type = nodeType(node);\n const hasChildren = isExpandable(node);\n const expanded = hasChildren && this.isExpanded(id, node, overrides);\n const isLast = index === nodes.length - 1;\n\n out.push({\n id,\n name: node.name,\n type,\n depth,\n hasChildren,\n expanded,\n icon: this.resolveIcon(node, type, expanded),\n color: node.color,\n badge: node.badge,\n status: node.status ?? 'default',\n disabled: node.disabled ?? false,\n ancestorHasSibling,\n isLast,\n posInSet: index + 1,\n setSize: nodes.length,\n parentId,\n });\n\n if (expanded && node.children) {\n this.flatten(\n node.children,\n depth + 1,\n id,\n [...ancestorHasSibling, !isLast],\n overrides,\n out,\n id,\n );\n }\n });\n }\n\n private resolveIcon(\n node: TreeNode,\n type: TreeNodeType,\n expanded: boolean,\n ): string | null {\n if (node.icon) return node.icon;\n if (type === 'folder') return expanded ? FOLDER_OPEN_ICON : FOLDER_ICON;\n if (type === 'file') {\n return node.name ? resolveFileIcon(node.name) : FILE_FALLBACK_ICON;\n }\n // Custom domain type without explicit icon: render a colored type dot.\n return null;\n }\n\n private findNode(\n nodes: TreeNode[],\n parentPath: string,\n targetId: string,\n ): TreeNode | null {\n for (const node of nodes) {\n const id = node.id ?? `${parentPath}/${node.name}`;\n if (id === targetId) return node;\n if (node.children) {\n const found = this.findNode(node.children, id, targetId);\n if (found) return found;\n }\n }\n return null;\n }\n}\n","@if (showToolbar()) {\n <div class=\"lc-tree-view__toolbar\">\n <button type=\"button\" class=\"lc-tree-view__tool-btn\" (click)=\"expandAll()\" [attr.title]=\"expandAllLabel()\">\n <lc-icon name=\"fold-down\" size=\"xs\" [decorative]=\"true\" />\n <span>{{ expandAllLabel() }}</span>\n </button>\n <button type=\"button\" class=\"lc-tree-view__tool-btn\" (click)=\"collapseAll()\" [attr.title]=\"collapseAllLabel()\">\n <lc-icon name=\"fold-up\" size=\"xs\" [decorative]=\"true\" />\n <span>{{ collapseAllLabel() }}</span>\n </button>\n </div>\n}\n\n<ul class=\"lc-tree-view__list\" role=\"tree\">\n @for (node of visibleNodes(); track trackById($index, node)) {\n <li\n class=\"lc-tree-view__item\"\n [class.lc-tree-view__item--selected]=\"node.id === selectedId()\"\n [class.lc-tree-view__item--disabled]=\"node.disabled\"\n [class.lc-tree-view__item--folder]=\"node.type === 'folder'\"\n role=\"treeitem\"\n [attr.aria-level]=\"node.depth + 1\"\n [attr.aria-posinset]=\"node.posInSet\"\n [attr.aria-setsize]=\"node.setSize\"\n [attr.aria-expanded]=\"node.hasChildren ? node.expanded : null\"\n [attr.aria-selected]=\"node.id === selectedId()\"\n [attr.aria-disabled]=\"node.disabled ? true : null\"\n [attr.aria-busy]=\"node.status === 'busy' ? true : null\"\n [tabindex]=\"node.id === tabStopId() ? 0 : -1\"\n (focus)=\"onFocus(node)\"\n (click)=\"onNodeClick(node)\"\n (keydown)=\"onKeydown(node, $event)\"\n >\n <!-- indentation + guide lines -->\n @for (hasSibling of node.ancestorHasSibling; track $index) {\n <span\n class=\"lc-tree-view__indent\"\n [class.lc-tree-view__indent--guide]=\"showGuides() && hasSibling\"\n ></span>\n }\n\n <!-- expand / collapse chevron -->\n <span class=\"lc-tree-view__chevron\">\n @if (node.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-tree-view__chevron-btn\"\n [class.lc-tree-view__chevron-btn--expanded]=\"node.expanded\"\n (click)=\"onToggleClick(node, $event)\"\n [attr.aria-label]=\"node.expanded ? collapseAriaLabel() : expandAriaLabel()\"\n tabindex=\"-1\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n\n <!-- type / file icon, or type dot for custom node types -->\n <span\n class=\"lc-tree-view__icon\"\n [style.color]=\"\n node.color ?? (node.status === 'default' ? null : badgeColor(node.status))\n \"\n >\n @if (node.icon; as icon) {\n <lc-icon [name]=\"icon\" [size]=\"iconSize()\" [decorative]=\"true\" />\n } @else {\n <span\n class=\"lc-tree-view__type-dot\"\n [style.background-color]=\"node.color ?? null\"\n ></span>\n }\n </span>\n\n <!-- label -->\n <span class=\"lc-tree-view__label\">{{ node.name }}</span>\n\n <!-- badge -->\n @if (node.badge) {\n <span\n class=\"lc-tree-view__badge\"\n [style.color]=\"badgeColor(node.status)\"\n [style.border-color]=\"badgeColor(node.status)\"\n >{{ node.badge }}</span\n >\n }\n\n <!-- status indicator -->\n @if (node.status === 'success') {\n <span class=\"lc-tree-view__status lc-tree-view__status--success\">\n <lc-icon name=\"check\" size=\"xs\" [decorative]=\"true\" />\n </span>\n } @else if (node.status === 'busy') {\n <span class=\"lc-tree-view__status lc-tree-view__status--busy\"></span>\n }\n </li>\n }\n</ul>\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifecorner/angular-ui-kit",
3
- "version": "3.21.1",
3
+ "version": "3.22.1",
4
4
  "description": "LifeCorner Design System – Angular UI component library",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -136,8 +136,21 @@ export declare const ICON_WALLET: LcIconDefinition;
136
136
  export declare const ICON_BUILDING_BANK: LcIconDefinition;
137
137
  export declare const ICON_SHIELD_LOCK: LcIconDefinition;
138
138
  export declare const ICON_SHIELD_LOCK_SOLID: LcIconDefinition;
139
+ export declare const ICON_SEARCH: LcIconDefinition;
140
+ export declare const ICON_SEARCH_SOLID: LcIconDefinition;
141
+ export declare const ICON_LOCK: LcIconDefinition;
142
+ export declare const ICON_LOCK_SOLID: LcIconDefinition;
143
+ export declare const ICON_DEVICE_TABLET: LcIconDefinition;
144
+ export declare const ICON_DEVICE_TABLET_SOLID: LcIconDefinition;
145
+ export declare const ICON_PLAYER_PLAY: LcIconDefinition;
146
+ export declare const ICON_PLAYER_PLAY_SOLID: LcIconDefinition;
147
+ export declare const ICON_PLAYER_PAUSE: LcIconDefinition;
148
+ export declare const ICON_PLAYER_PAUSE_SOLID: LcIconDefinition;
149
+ export declare const ICON_CLIPBOARD: LcIconDefinition;
150
+ export declare const ICON_CLIPBOARD_SOLID: LcIconDefinition;
151
+ export declare const ICON_ARROW_DOWN: LcIconDefinition;
139
152
  /**
140
- * Every glyph above (137): `provideLcIcons(BUNDLED_ICONS)` restores the
153
+ * Every glyph above (150): `provideLcIcons(BUNDLED_ICONS)` restores the
141
154
  * synchronous rendering of 3.5.1 for every inline name, e.g. in tests or
142
155
  * Storybook. An app that imports it bundles all of them.
143
156
  */