@lifecorner/angular-ui-kit 3.13.1 → 3.15.0

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.
Files changed (43) hide show
  1. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +64 -11
  2. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -1
  3. package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +2 -1
  4. package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -1
  5. package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +23 -5
  6. package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -1
  7. package/fesm2022/lifecorner-angular-ui-kit-button.mjs +39 -6
  8. package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
  9. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +1 -0
  10. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
  11. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +1 -0
  12. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
  13. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +1 -0
  14. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
  15. package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs +42 -5
  16. package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs.map +1 -1
  17. package/fesm2022/lifecorner-angular-ui-kit-header.mjs +21 -3
  18. package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
  19. package/fesm2022/lifecorner-angular-ui-kit-list.mjs +1 -0
  20. package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
  21. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +1 -0
  22. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
  23. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +20 -3
  24. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -1
  25. package/fesm2022/lifecorner-angular-ui-kit-sidenav-placeholder.mjs +9 -3
  26. package/fesm2022/lifecorner-angular-ui-kit-sidenav-placeholder.mjs.map +1 -1
  27. package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +115 -6
  28. package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
  29. package/fesm2022/lifecorner-angular-ui-kit-stat-trend.mjs +62 -4
  30. package/fesm2022/lifecorner-angular-ui-kit-stat-trend.mjs.map +1 -1
  31. package/fesm2022/lifecorner-angular-ui-kit-table.mjs +1 -0
  32. package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
  33. package/package.json +1 -1
  34. package/src/styles/theme-contrast.spec.ts +52 -0
  35. package/types/lifecorner-angular-ui-kit-app-shell.d.ts +100 -0
  36. package/types/lifecorner-angular-ui-kit-avatar.d.ts +24 -0
  37. package/types/lifecorner-angular-ui-kit-button.d.ts +31 -0
  38. package/types/lifecorner-angular-ui-kit-empty-state.d.ts +38 -0
  39. package/types/lifecorner-angular-ui-kit-header.d.ts +15 -2
  40. package/types/lifecorner-angular-ui-kit-page-header.d.ts +20 -0
  41. package/types/lifecorner-angular-ui-kit-sidenav-placeholder.d.ts +4 -2
  42. package/types/lifecorner-angular-ui-kit-sidenav.d.ts +100 -2
  43. package/types/lifecorner-angular-ui-kit-stat-trend.d.ts +46 -0
@@ -1 +1 @@
1
- {"version":3,"file":"lifecorner-angular-ui-kit-table.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/table/table-cell.directive.ts","../../../../libs/angular-ui-kit/src/lib/table/table.component.ts","../../../../libs/angular-ui-kit/src/lib/table/table.component.html"],"sourcesContent":["import { Directive, input, TemplateRef, inject } from '@angular/core';\n\n/**\n * Directive for defining custom cell templates in the Table component.\n *\n * @example\n * ```html\n * <lc-table [columns]=\"columns\" [data]=\"data\">\n * <ng-template lcTableCell=\"status\" let-row>\n * <lc-badge [variant]=\"row.status\">{{ row.status }}</lc-badge>\n * </ng-template>\n * </lc-table>\n * ```\n */\n@Directive({\n selector: '[lcTableCell]',\n standalone: true,\n})\nexport class TableCellDirective {\n /** The column key this template applies to */\n readonly columnKey = input('', { alias: 'lcTableCell' });\n\n public template = inject(TemplateRef<{ $implicit: Record<string, unknown> }>);\n}\n","import {\n Component,\n ChangeDetectionStrategy,\n ElementRef,\n input,\n output,\n computed,\n signal,\n linkedSignal,\n viewChild,\n viewChildren,\n afterRenderEffect,\n ContentChildren,\n QueryList,\n} from '@angular/core';\nimport { NgStyle, NgTemplateOutlet } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { TableCellDirective } from './table-cell.directive';\nimport { InputComponent } from '@lifecorner/angular-ui-kit/input';\nimport { SelectComponent } from '@lifecorner/angular-ui-kit/select';\nimport { ButtonComponent, ButtonVariant } from '@lifecorner/angular-ui-kit/button';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHEVRON_RIGHT } from '@lifecorner/angular-ui-kit/icons';\n\ntype TableCellClass = string | ((\n value: unknown,\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n) => string);\n\ntype TableCellStyle = Record<string, string> | ((\n value: unknown,\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n) => Record<string, string>);\n\nexport interface TableColumn {\n key: string;\n label: string;\n sortable?: boolean;\n filterable?: boolean;\n editable?: boolean;\n width?: string;\n /** Optional CSS class(es) applied to both th and td cells */\n cssClass?: string;\n /** Optional CSS class(es) for td cells only (string or resolver callback) */\n cellClass?: TableCellClass;\n /** Optional inline styles for td cells only (object or resolver callback) */\n cellStyle?: TableCellStyle;\n /** Optional tooltip shown on hover over the column header */\n tooltip?: string;\n /** Optional formatter for cell output when no custom template is used */\n formatter?: (\n value: unknown,\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ) => unknown;\n /** Input type for inline editing (default: text) */\n editType?: 'text' | 'number' | 'select';\n /** Options for select edit type */\n editOptions?: string[];\n}\n\n/**\n * A row-level action rendered in the table's actions column (e.g. Freigeben, Ablehnen).\n * Action button clicks never trigger the row's `rowClick` output.\n */\nexport interface TableAction {\n /** Unique identifier emitted with the {@link ActionClickEvent} */\n key: string;\n /** Visible button label (omit for icon-only buttons when an `icon` is set) */\n label?: string;\n /** Optional icon name rendered before the label */\n icon?: string;\n /** Button variant (default: 'ghost') */\n variant?: ButtonVariant;\n /** Optional tooltip / aria-label, useful for icon-only actions */\n tooltip?: string;\n /** Hide this action for specific rows */\n hidden?: (row: Record<string, unknown>, rowIndex: number) => boolean;\n /** Disable this action for specific rows */\n disabled?: (row: Record<string, unknown>, rowIndex: number) => boolean;\n}\n\nexport type TableActionsAlign = 'start' | 'center' | 'end';\n\nexport interface ActionClickEvent {\n action: string;\n row: Record<string, unknown>;\n rowIndex: number;\n}\n\nexport interface SortEvent {\n column: string;\n direction: 'asc' | 'desc';\n}\n\nexport interface CellEditEvent {\n row: Record<string, unknown>;\n column: string;\n oldValue: unknown;\n newValue: unknown;\n /** Index of `row` in the `data` input (not its position on screen). */\n rowIndex: number;\n}\n\nexport interface SelectionChangeEvent {\n selected: Record<string, unknown>[];\n allSelected: boolean;\n}\n\n/** Emitted when a parent (group) row is expanded or collapsed in tree mode. */\nexport interface RowToggleEvent {\n id: string;\n expanded: boolean;\n row: Record<string, unknown>;\n}\n\n/**\n * Configuration that enables hierarchical (tree / grouped) rows. Mirrors the\n * discrete `idKey` / `parentKey` / `treeColumn` inputs and is exported for\n * consumers that prefer to pass a single config object around.\n */\nexport interface TableTreeConfig {\n idKey: string;\n parentKey: string;\n treeColumn?: string;\n}\n\nexport type TableVariant = 'default' | 'striped' | 'bordered';\nexport type TableSize = 'sm' | 'md' | 'lg';\n\n/**\n * Internal, render-ready view-model for a single visible table row. In flat\n * mode every row is depth 0 with no tree adornments; in tree mode it carries\n * the disclosure / indentation / aria metadata for the row.\n */\ninterface DisplayRow {\n /** The underlying data object. */\n row: Record<string, unknown>;\n /**\n * The row's index into `data()` — in both modes. It is what action, class,\n * style and formatter callbacks receive as `rowIndex`, and what identifies\n * the row in `CellEditEvent`. (It used to be the *positional* index in flat\n * mode — page offset plus row position — which, once a sort or filter was\n * active, pointed at a different row of `data()` than the one on screen.)\n */\n absIndex: number;\n /**\n * What selection and inline editing are keyed by: the row's `idKey` value\n * when the table has one, otherwise the row object itself. Either survives a\n * re-sort, a filter and a page change; an id also survives the parent\n * replacing its data array with fresh objects.\n */\n key: unknown;\n /** Row id (tree mode only; `null` in flat mode). */\n id: string | null;\n /** Tree depth — 0 for roots and for every row in flat mode. */\n depth: number;\n /** 1-based depth, surfaced as `aria-level` in tree mode. */\n level: number;\n /** Whether this row has visible children (renders a chevron). */\n hasChildren: boolean;\n /** Whether this parent row is currently expanded. */\n expanded: boolean;\n /** 1-based position within its sibling group (`aria-posinset`). */\n posInSet: number;\n /** Size of its sibling group (`aria-setsize`). */\n setSize: number;\n}\n\n/**\n * Table component for displaying structured data in rows and columns.\n *\n * Features:\n * - Column-based sorting with sort direction indicators\n * - Variant styles (default, striped, bordered)\n * - Size presets (sm, md, lg)\n * - Hoverable row highlighting\n * - Per-column formatter callbacks for display values\n * - Per-cell class/style callbacks for conditional styling\n * - Custom cell templates via content projection\n * - Composed cells (e.g. avatar + badge + actions)\n * - Hierarchical \"tree\" rows (grouped / expandable) via `idKey` + `parentKey`\n * - Responsive horizontal scrolling\n * - Empty state text for no data\n * - Accessible with proper table semantics\n *\n * @example\n * ```html\n * <lc-table [columns]=\"columns\" [data]=\"data\" variant=\"striped\" [hoverable]=\"true\"\n * (sort)=\"onSort($event)\" (rowClick)=\"onRowClick($event)\" />\n * ```\n *\n * @example\n * ```ts\n * columns: TableColumn[] = [\n * {\n * key: 'amount',\n * label: 'Amount',\n * formatter: (value) => new Intl.NumberFormat('de-DE', {\n * style: 'currency',\n * currency: 'EUR',\n * }).format(Number(value ?? 0)),\n * },\n * ];\n * ```\n */\n@Component({\n selector: 'lc-table',\n standalone: true,\n imports: [NgTemplateOutlet, NgStyle, FormsModule, SelectComponent, InputComponent, ButtonComponent, IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_RIGHT])],\n templateUrl: './table.component.html',\n styleUrl: './table.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TableComponent {\n /** Custom cell templates */\n @ContentChildren(TableCellDirective) cellTemplates!: QueryList<TableCellDirective>;\n\n /** Array of column definitions */\n columns = input<TableColumn[]>([]);\n\n /** Array of data objects to display */\n data = input<Record<string, unknown>[]>([]);\n\n /** Visual variant of the table */\n variant = input<TableVariant>('default');\n\n /** Size of the table */\n size = input<TableSize>('md');\n\n /** Whether rows should highlight on hover */\n hoverable = input<boolean>(false);\n\n /** Whether table should be responsive (horizontal scroll on mobile) */\n responsive = input<boolean>(true);\n\n /** Text shown when data is empty */\n emptyText = input<string>('No data available');\n\n /** Placeholder prefix of the column filters, followed by the column label (`filterable`). */\n filterPlaceholderLabel = input('Filter');\n\n /** Accessible name of the select-all checkbox (`selectable`). */\n selectAllAriaLabel = input('Select all rows');\n\n /** Accessible name of a row checkbox, followed by the row number. */\n selectRowAriaLabel = input('Select row');\n\n /** Screen-reader state of a column sorted ascending. */\n sortedAscendingLabel = input('sorted ascending');\n\n /** Screen-reader state of a column sorted descending. */\n sortedDescendingLabel = input('sorted descending');\n\n /** Tree mode: accessible name prefix of the expand toggle, followed by the row label. */\n expandRowAriaLabel = input('Aufklappen:');\n\n /** Tree mode: accessible name prefix of the collapse toggle, followed by the row label. */\n collapseRowAriaLabel = input('Einklappen:');\n\n /** Pagination: word between the shown range and the total (`1–10 of 42`). */\n rangeOfLabel = input('of');\n\n /** Accessible name of the page-size select. */\n rowsPerPageAriaLabel = input('Rows per page');\n\n /** Accessible name of the previous-page button. */\n previousPageAriaLabel = input('Previous page');\n\n /** Accessible name of the next-page button. */\n nextPageAriaLabel = input('Next page');\n\n // -- Pagination --\n /** Enable pagination */\n paginate = input<boolean>(false);\n\n /** Rows per page */\n pageSize = input<number>(10);\n\n /** Available page size options */\n pageSizeOptions = input<number[]>([5, 10, 25, 50]);\n\n // -- Selection --\n /** Enable row selection checkboxes */\n selectable = input<boolean>(false);\n\n // -- Column Filters --\n /** Enable per-column text filters */\n filterable = input<boolean>(false);\n\n // -- Inline Editing --\n /** Enable inline cell editing on double-click */\n editable = input<boolean>(false);\n\n // -- Row Actions --\n /**\n * Row-level actions rendered in a trailing actions column (e.g. Freigeben / Ablehnen).\n * Clicking an action button does NOT trigger the row's `rowClick` output.\n */\n actions = input<TableAction[]>([]);\n\n /** Header label for the actions column */\n actionsLabel = input<string>('');\n\n /** Width of the actions column (e.g. '120px') */\n actionsWidth = input<string | undefined>(undefined);\n\n /** Horizontal alignment of the action buttons (and header label) within the cell */\n actionsAlign = input<TableActionsAlign>('start');\n\n // -- Tree / grouped rows --\n /**\n * Row field holding the unique id. Required (together with {@link parentKey})\n * to enable hierarchical \"tree mode\". Absent ⇒ today's flat table.\n */\n idKey = input<string | undefined>(undefined);\n\n /**\n * Row field referencing the parent row's id. Presence of both `idKey` and\n * `parentKey` enables tree mode. Rows with an absent/empty or unknown parent\n * id are treated as roots.\n */\n parentKey = input<string | undefined>(undefined);\n\n /** Column key the chevron + indentation attach to. Default: first column. */\n treeColumn = input<string | undefined>(undefined);\n\n /** Initial expand state for all parent rows when uncontrolled. Default: true. */\n defaultExpanded = input<boolean>(true);\n\n /**\n * Controlled set of expanded parent ids. When provided, the table renders\n * exactly these as expanded; combine with {@link expandedIdsChange} for\n * `[(expandedIds)]`. When omitted, expansion is uncontrolled and seeded by\n * {@link defaultExpanded}.\n */\n expandedIds = input<string[] | undefined>(undefined);\n\n /** Indentation per depth level, in px. Default: 20. */\n indentSize = input<number>(20);\n\n /** Accessible name prefix of a column filter, followed by the column label. */\n filterAriaLabel = input('Filter by');\n\n /** Emitted when a sortable column header is clicked */\n readonly sort = output<SortEvent>();\n\n /** Emitted when a row is clicked */\n readonly rowClick = output<Record<string, unknown>>();\n\n /** Emitted when a cell is edited */\n readonly cellEdit = output<CellEditEvent>();\n\n /** Emitted when row selection changes */\n readonly selectionChange = output<SelectionChangeEvent>();\n\n /** Emitted when a row action button is clicked */\n readonly actionClick = output<ActionClickEvent>();\n\n /** Emitted when a parent row is expanded/collapsed (tree mode). */\n readonly rowToggle = output<RowToggleEvent>();\n\n /** Emitted with the full list of expanded parent ids; enables `[(expandedIds)]`. */\n readonly expandedIdsChange = output<string[]>();\n\n // -- Internal state --\n protected currentSort = signal<{ column: string; direction: 'asc' | 'desc' } | null>(null);\n /**\n * Effective page size. Seeded from the `pageSize` input (resetting if it\n * changes) and overridable by the user via the page-size dropdown.\n */\n protected internalPageSize = linkedSignal(() => this.pageSize());\n /**\n * Current page, kept within range: when the data shrinks or the page size\n * grows so that the page no longer exists, it moves back to the last one\n * (rather than showing an empty page captioned \"31–30 of 30\").\n */\n protected currentPage = linkedSignal<number, number>({\n source: () => this.totalPages(),\n computation: (total, previous) => Math.min(previous?.value ?? 0, total - 1),\n });\n /**\n * Selected row keys (see `DisplayRow.key`). Pruned when `data` changes, so\n * a key whose row is gone doesn't linger and count towards \"all selected\".\n */\n protected selectedRows = linkedSignal<Set<unknown>, Set<unknown>>({\n source: () => this.rowKeys(),\n computation: (keys, previous) => {\n if (!previous) return new Set<unknown>();\n const kept = new Set([...previous.value].filter((k) => keys.has(k)));\n return kept.size === previous.value.size ? previous.value : kept;\n },\n });\n protected columnFilters = signal<Record<string, string>>({});\n protected editingCell = signal<{ key: unknown; column: string } | null>(null);\n protected editValue = signal<string>('');\n\n /** The inline-edit input while a cell is being edited. */\n private readonly editInput = viewChild<ElementRef<HTMLInputElement>>('editInput');\n private focusedEditInput: HTMLInputElement | null = null;\n\n constructor() {\n // The edit input is inserted on double-click. `autofocus` is only honoured\n // for elements present when the page loads, so the input never received\n // focus (and Enter/Escape/blur never reached it); focus it once it renders.\n afterRenderEffect(() => {\n const el = this.editInput()?.nativeElement ?? null;\n if (el && el !== this.focusedEditInput) {\n el.focus();\n }\n this.focusedEditInput = el;\n });\n }\n\n /** The key of every row currently in `data()`. */\n private readonly rowKeys = computed(() => new Set(this.data().map((row) => this.rowKey(row))));\n\n /** See `DisplayRow.key`. */\n private rowKey(row: Record<string, unknown>): unknown {\n const idKey = this.idKey();\n return idKey ? String(row[idKey] ?? '') : row;\n }\n /** User expand/collapse overrides keyed by row id (uncontrolled mode). */\n private readonly expandOverrides = signal<Map<string, boolean>>(new Map());\n\n /**\n * Filtered data (applies column filters)\n */\n protected readonly filteredData = computed(() => {\n let items = this.data();\n const filters = this.columnFilters();\n\n if (this.filterable()) {\n for (const [key, value] of Object.entries(filters)) {\n if (value.trim()) {\n items = items.filter(row =>\n String(row[key] ?? '').toLowerCase().includes(value.toLowerCase())\n );\n }\n }\n }\n\n return items;\n });\n\n /** Comparator for the active sort, shared by flat sorting and tree sibling sorting. */\n private rowComparator(sortState: { column: string; direction: 'asc' | 'desc' }) {\n return (a: Record<string, unknown>, b: Record<string, unknown>): number => {\n const aVal = a[sortState.column];\n const bVal = b[sortState.column];\n let cmp = 0;\n if (aVal == null && bVal == null) cmp = 0;\n else if (aVal == null) cmp = -1;\n else if (bVal == null) cmp = 1;\n else if (typeof aVal === 'number' && typeof bVal === 'number') cmp = aVal - bVal;\n else cmp = String(aVal).localeCompare(String(bVal));\n return sortState.direction === 'asc' ? cmp : -cmp;\n };\n }\n\n /**\n * Sorted data\n */\n protected readonly sortedData = computed(() => {\n const items = [...this.filteredData()];\n const sortState = this.currentSort();\n if (!sortState) return items;\n return items.sort(this.rowComparator(sortState));\n });\n\n /**\n * Paginated data (or all if pagination disabled). Flat mode only.\n */\n protected readonly displayData = computed(() => {\n const items = this.sortedData();\n if (!this.paginate()) return items;\n const ps = this.internalPageSize();\n const start = this.currentPage() * ps;\n return items.slice(start, start + ps);\n });\n\n // -- Tree / grouped rows -----------------------------------------------------\n\n /** Whether hierarchical tree mode is active. */\n protected readonly treeMode = computed(() => !!this.idKey() && !!this.parentKey());\n\n /** Column the chevron + indentation attach to (defaults to the first column). */\n protected readonly effectiveTreeColumn = computed(\n () => this.treeColumn() || this.columns()[0]?.key\n );\n\n /** Stable map of row object → its index in `data()` (row identity for tree mode). */\n private readonly dataIndexMap = computed(() => {\n const map = new Map<Record<string, unknown>, number>();\n this.data().forEach((row, i) => map.set(row, i));\n return map;\n });\n\n /** Parent → ordered children index built from `idKey`/`parentKey`. */\n private readonly treeBuild = computed(() => {\n const idKey = this.idKey();\n const parentKey = this.parentKey();\n const byId = new Map<string, Record<string, unknown>>();\n const childrenOf = new Map<string, Record<string, unknown>[]>();\n const roots: Record<string, unknown>[] = [];\n if (!idKey || !parentKey) return { byId, childrenOf, roots };\n\n const rows = this.data();\n for (const row of rows) {\n const id = String(row[idKey] ?? '');\n if (id) byId.set(id, row);\n }\n for (const row of rows) {\n const parentRaw = row[parentKey];\n const parentId = parentRaw == null ? '' : String(parentRaw);\n if (parentId && byId.has(parentId)) {\n const siblings = childrenOf.get(parentId) ?? [];\n siblings.push(row);\n childrenOf.set(parentId, siblings);\n } else {\n // No parent, empty parent, or orphaned (unknown parent) ⇒ root.\n roots.push(row);\n }\n }\n return { byId, childrenOf, roots };\n });\n\n /**\n * Tree restricted to rows that match the active filters together with their\n * ancestor chain (so the path to a match stays visible).\n */\n private readonly treeFiltered = computed(() => {\n const { byId, childrenOf, roots } = this.treeBuild();\n const parentKey = this.parentKey();\n const filters = this.columnFilters();\n const active =\n this.filterable() && parentKey && Object.values(filters).some((v) => v.trim());\n if (!active) return { childrenOf, roots };\n\n const matches = (row: Record<string, unknown>): boolean =>\n Object.entries(filters).every(\n ([key, value]) =>\n !value.trim() ||\n String(row[key] ?? '').toLowerCase().includes(value.toLowerCase())\n );\n\n // Visible = every matching row plus all of its ancestors.\n const visible = new Set<Record<string, unknown>>();\n for (const row of this.data()) {\n if (!matches(row)) continue;\n let current: Record<string, unknown> | undefined = row;\n while (current && !visible.has(current)) {\n visible.add(current);\n const parentRaw: unknown = current[parentKey];\n const parentId = parentRaw == null ? '' : String(parentRaw);\n current = parentId ? byId.get(parentId) : undefined;\n }\n }\n\n const visibleChildrenOf = new Map<string, Record<string, unknown>[]>();\n const visibleRoots: Record<string, unknown>[] = [];\n for (const row of this.data()) {\n if (!visible.has(row)) continue;\n const parentRaw = row[parentKey];\n const parentId = parentRaw == null ? '' : String(parentRaw);\n const parent = parentId ? byId.get(parentId) : undefined;\n if (parent && visible.has(parent)) {\n const siblings = visibleChildrenOf.get(parentId) ?? [];\n siblings.push(row);\n visibleChildrenOf.set(parentId, siblings);\n } else {\n visibleRoots.push(row);\n }\n }\n return { childrenOf: visibleChildrenOf, roots: visibleRoots };\n });\n\n /** Tree with each sibling group sorted by the active sort (structure kept intact). */\n private readonly treeSorted = computed(() => {\n const { childrenOf, roots } = this.treeFiltered();\n const sortState = this.currentSort();\n if (!sortState) return { childrenOf, roots };\n const cmp = this.rowComparator(sortState);\n const sortedChildrenOf = new Map<string, Record<string, unknown>[]>();\n for (const [parentId, siblings] of childrenOf) {\n sortedChildrenOf.set(parentId, [...siblings].sort(cmp));\n }\n return { childrenOf: sortedChildrenOf, roots: [...roots].sort(cmp) };\n });\n\n /** Root rows after filter/sort — the unit of pagination in tree mode. */\n private readonly treeRoots = computed(() => this.treeSorted().roots);\n\n /**\n * Render-ready rows. In flat mode this wraps the existing paginated data; in\n * tree mode it paginates roots and flattens each visible (expanded) subtree.\n */\n protected readonly displayRows = computed<DisplayRow[]>(() => {\n const dataIndex = this.dataIndexMap();\n if (!this.treeMode()) {\n return this.displayData().map((row) => ({\n row,\n absIndex: dataIndex.get(row) ?? -1,\n key: this.rowKey(row),\n id: null,\n depth: 0,\n level: 0,\n hasChildren: false,\n expanded: false,\n posInSet: 0,\n setSize: 0,\n }));\n }\n\n const idKey = this.idKey() as string;\n const { childrenOf } = this.treeSorted();\n let roots = this.treeRoots();\n if (this.paginate()) {\n const ps = this.internalPageSize();\n const start = this.currentPage() * ps;\n roots = roots.slice(start, start + ps);\n }\n\n const out: DisplayRow[] = [];\n const walk = (group: Record<string, unknown>[], depth: number): void => {\n group.forEach((row, idx) => {\n const id = String(row[idKey] ?? '');\n const children = childrenOf.get(id) ?? [];\n const hasChildren = children.length > 0;\n const expanded = hasChildren && this.isExpanded(id);\n out.push({\n row,\n absIndex: dataIndex.get(row) ?? -1,\n key: this.rowKey(row),\n id,\n depth,\n level: depth + 1,\n hasChildren,\n expanded,\n posInSet: idx + 1,\n setSize: group.length,\n });\n if (expanded) walk(children, depth + 1);\n });\n };\n walk(roots, 0);\n return out;\n });\n\n /** Total pages */\n protected readonly totalPages = computed(() => {\n if (!this.paginate()) return 1;\n const total = this.treeMode() ? this.treeRoots().length : this.filteredData().length;\n return Math.max(1, Math.ceil(total / this.internalPageSize()));\n });\n\n /**\n * Pagination row count. Tree mode counts root rows (the paginated unit); flat\n * mode counts filtered rows.\n */\n protected readonly totalRows = computed(() =>\n this.treeMode() ? this.treeRoots().length : this.filteredData().length\n );\n\n /** Whether all visible rows are selected */\n protected readonly allSelected = computed(() => {\n const rows = this.displayRows();\n if (rows.length === 0) return false;\n const selected = this.selectedRows();\n return rows.every((r) => selected.has(r.key));\n });\n\n /** Whether some, but not all, visible rows are selected — the header box's mixed state. */\n protected readonly someSelected = computed(() => {\n const selected = this.selectedRows();\n return !this.allSelected() && this.displayRows().some((r) => selected.has(r.key));\n });\n\n protected readonly pageSizeSelectOptions = computed(() =>\n this.pageSizeOptions().map((opt) => ({\n value: opt,\n label: `${opt} / page`,\n }))\n );\n\n /**\n * Computed CSS classes for the table element\n */\n tableClasses = computed(() => {\n const classes = ['lc-table'];\n classes.push(`lc-table--${this.variant()}`);\n classes.push(`lc-table--${this.size()}`);\n if (this.hoverable()) classes.push('lc-table--hoverable');\n return classes.join(' ');\n });\n\n /**\n * Computed CSS classes for the wrapper element\n */\n wrapperClasses = computed(() => {\n const classes = ['lc-table-wrapper'];\n if (this.responsive()) classes.push('lc-table-wrapper--responsive');\n return classes.join(' ');\n });\n\n // -- Sort --\n handleSort(columnKey: string): void {\n const column = this.columns().find((col) => col.key === columnKey);\n if (!column || !column.sortable) return;\n\n const current = this.currentSort();\n let direction: 'asc' | 'desc' = 'asc';\n if (current && current.column === columnKey) {\n direction = current.direction === 'asc' ? 'desc' : 'asc';\n }\n\n this.currentSort.set({ column: columnKey, direction });\n this.sort.emit({ column: columnKey, direction });\n }\n\n getSortState(columnKey: string): 'asc' | 'desc' | null {\n const current = this.currentSort();\n if (current && current.column === columnKey) return current.direction;\n return null;\n }\n\n getAriaSort(columnKey: string): string | null {\n const sortState = this.getSortState(columnKey);\n if (sortState === 'asc') return 'ascending';\n if (sortState === 'desc') return 'descending';\n return null;\n }\n\n getHeaderClasses(column: TableColumn): string {\n const classes: string[] = [];\n if (column.sortable) classes.push('sortable');\n const sortState = this.getSortState(column.key);\n if (sortState) classes.push(`sorted-${sortState}`);\n return classes.join(' ');\n }\n\n getCellValue(row: Record<string, unknown>, columnKey: string): unknown {\n return row[columnKey];\n }\n\n getFormattedCellValue(\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ): unknown {\n const value = this.getCellValue(row, column.key);\n if (!column.formatter) return value;\n\n return column.formatter(value, row, column, rowIndex);\n }\n\n getCellClasses(\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ): string {\n const classes: string[] = [];\n if (column.cssClass) classes.push(column.cssClass);\n\n if (typeof column.cellClass === 'string') {\n classes.push(column.cellClass);\n } else if (typeof column.cellClass === 'function') {\n const resolved = column.cellClass(\n this.getCellValue(row, column.key),\n row,\n column,\n rowIndex\n );\n if (resolved) classes.push(resolved);\n }\n\n return classes.join(' ').trim();\n }\n\n getCellStyles(\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ): Record<string, string> | null {\n if (!column.cellStyle) return null;\n\n if (typeof column.cellStyle === 'function') {\n return column.cellStyle(\n this.getCellValue(row, column.key),\n row,\n column,\n rowIndex\n );\n }\n\n return column.cellStyle;\n }\n\n /** Whether the given column is the disclosure/indent column in tree mode. */\n protected isTreeColumn(columnKey: string): boolean {\n return this.treeMode() && columnKey === this.effectiveTreeColumn();\n }\n\n /** Indent levels to render before a row's chevron (one guide per ancestor depth). */\n protected indentLevels(depth: number): number[] {\n return Array.from({ length: depth }, (_, i) => i);\n }\n\n /** Accessible name for a row's disclosure button (the tree column's value). */\n protected treeCellLabel(row: Record<string, unknown>): string {\n const col = this.effectiveTreeColumn();\n return col ? String(row[col] ?? '') : '';\n }\n\n getCellTemplate(columnKey: string): TableCellDirective | undefined {\n return this.cellTemplates?.find((template) => template.columnKey() === columnKey);\n }\n\n hasCustomTemplate(columnKey: string): boolean {\n return !!this.getCellTemplate(columnKey);\n }\n\n onRowClick(row: Record<string, unknown>): void {\n this.rowClick.emit(row);\n }\n\n // -- Row Actions --\n /** Whether the trailing actions column should be rendered */\n protected readonly hasActions = computed(() => this.actions().length > 0);\n\n protected isActionHidden(\n action: TableAction,\n row: Record<string, unknown>,\n rowIndex: number\n ): boolean {\n return action.hidden ? action.hidden(row, rowIndex) : false;\n }\n\n protected isActionDisabled(\n action: TableAction,\n row: Record<string, unknown>,\n rowIndex: number\n ): boolean {\n return action.disabled ? action.disabled(row, rowIndex) : false;\n }\n\n /**\n * Handles an action button click. The DOM click is stopped from propagating\n * (see template `$event.stopPropagation()`), so the row's `rowClick` never fires.\n */\n protected onActionClick(\n action: TableAction,\n row: Record<string, unknown>,\n rowIndex: number\n ): void {\n this.actionClick.emit({\n action: action.key,\n row,\n rowIndex,\n });\n }\n\n // -- Tree keyboard model -----------------------------------------------------\n // `role=\"treegrid\"` promises a composite widget: one tab stop, arrows to move\n // between rows, Right/Left to open/close a group or step into/out of it. The\n // rows carry a roving tabindex; the focused row is remembered by key so it\n // survives re-renders, and falls back to the first row when it is gone.\n\n private readonly rowEls = viewChildren<ElementRef<HTMLTableRowElement>>('dataRow');\n private readonly focusedRowKey = signal<unknown>(null);\n\n /** Key of the row that holds the tab stop. */\n private readonly effectiveFocusedKey = computed(() => {\n const rows = this.displayRows();\n const key = this.focusedRowKey();\n return rows.some((r) => r.key === key) ? key : rows[0]?.key;\n });\n\n protected rowTabindex(dr: DisplayRow): number | null {\n if (!this.treeMode()) return null;\n return dr.key === this.effectiveFocusedKey() ? 0 : -1;\n }\n\n protected onRowFocus(dr: DisplayRow): void {\n if (this.treeMode()) this.focusedRowKey.set(dr.key);\n }\n\n protected onRowKeydown(event: KeyboardEvent, dr: DisplayRow): void {\n if (!this.treeMode()) return;\n // Keys typed into an inline editor or the row's own controls are theirs.\n if ((event.target as HTMLElement).tagName === 'INPUT') return;\n const rows = this.displayRows();\n const index = rows.findIndex((r) => r.key === dr.key);\n if (index < 0) return;\n\n switch (event.key) {\n case 'ArrowDown':\n this.focusRow(index + 1);\n break;\n case 'ArrowUp':\n this.focusRow(index - 1);\n break;\n case 'Home':\n this.focusRow(0);\n break;\n case 'End':\n this.focusRow(rows.length - 1);\n break;\n case 'ArrowRight':\n if (!dr.hasChildren) return;\n if (dr.expanded) this.focusRow(index + 1); // first child\n else if (dr.id) this.toggleRow(dr.id, dr.row);\n break;\n case 'ArrowLeft':\n if (dr.hasChildren && dr.expanded && dr.id) {\n this.toggleRow(dr.id, dr.row);\n } else if (dr.depth > 0) {\n // Step out to the parent: the nearest row above with a smaller depth.\n for (let i = index - 1; i >= 0; i--) {\n if (rows[i].depth < dr.depth) {\n this.focusRow(i);\n break;\n }\n }\n } else {\n return;\n }\n break;\n case 'Enter':\n this.rowClick.emit(dr.row);\n break;\n case ' ':\n if (!this.selectable()) return;\n this.toggleRowSelect(dr.row);\n break;\n default:\n return;\n }\n event.preventDefault();\n }\n\n private focusRow(index: number): void {\n const rows = this.displayRows();\n if (index < 0 || index >= rows.length) return;\n this.focusedRowKey.set(rows[index].key);\n this.rowEls()[index]?.nativeElement.focus();\n }\n\n // -- Tree expand / collapse --------------------------------------------------\n\n /** Whether the parent row with the given id is currently expanded. */\n protected isExpanded(id: string): boolean {\n const controlled = this.expandedIds();\n if (controlled !== undefined) return controlled.includes(id);\n const override = this.expandOverrides().get(id);\n if (override !== undefined) return override;\n return this.defaultExpanded();\n }\n\n /** Chevron click: toggle expand state without triggering the row click. */\n protected onChevronClick(displayRow: DisplayRow, event: Event): void {\n event.stopPropagation();\n if (displayRow.id) this.toggleRow(displayRow.id, displayRow.row);\n }\n\n private toggleRow(id: string, row: Record<string, unknown>): void {\n const expanded = !this.isExpanded(id);\n this.expandOverrides.update((map) => {\n const next = new Map(map);\n next.set(id, expanded);\n return next;\n });\n this.rowToggle.emit({ id, expanded, row });\n this.expandedIdsChange.emit(this.nextExpandedIds(id, expanded));\n }\n\n /** The full list of expanded parent ids after applying a single toggle. */\n private nextExpandedIds(changedId: string, changedExpanded: boolean): string[] {\n const controlled = this.expandedIds();\n const overrides = this.expandOverrides();\n const parentIds = Array.from(this.treeBuild().childrenOf.keys());\n return parentIds.filter((pid) => {\n if (pid === changedId) return changedExpanded;\n if (controlled !== undefined) return controlled.includes(pid);\n const override = overrides.get(pid);\n return override !== undefined ? override : this.defaultExpanded();\n });\n }\n\n // -- Pagination --\n protected goToPage(page: number): void {\n if (page >= 0 && page < this.totalPages()) {\n this.currentPage.set(page);\n }\n }\n\n protected onPageSizeChange(event: Event): void {\n const newSize = Number((event.target as HTMLSelectElement).value);\n this.internalPageSize.set(newSize);\n this.currentPage.set(0);\n }\n\n protected onPageSizeModelChange(value: string | number | null): void {\n if (value == null) {\n return;\n }\n const parsed = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(parsed)) {\n return;\n }\n this.internalPageSize.set(parsed);\n this.currentPage.set(0);\n }\n\n protected get paginationStart(): number {\n if (this.totalRows() === 0) return 0;\n return this.currentPage() * this.internalPageSize() + 1;\n }\n\n protected get paginationEnd(): number {\n return Math.min((this.currentPage() + 1) * this.internalPageSize(), this.totalRows());\n }\n\n // -- Selection --\n // Keyed by row identity (see `DisplayRow.key`), never by position: a sort or\n // filter changes where a row is shown, not which row it is.\n protected toggleSelectAll(): void {\n const selected = new Set(this.selectedRows());\n const rows = this.displayRows();\n const allSelected = this.allSelected();\n\n rows.forEach((r) => {\n if (allSelected) selected.delete(r.key);\n else selected.add(r.key);\n });\n\n this.selectedRows.set(selected);\n this.emitSelectionChange();\n }\n\n protected toggleRowSelect(row: Record<string, unknown>): void {\n const key = this.rowKey(row);\n const selected = new Set(this.selectedRows());\n if (selected.has(key)) selected.delete(key);\n else selected.add(key);\n this.selectedRows.set(selected);\n this.emitSelectionChange();\n }\n\n protected isRowSelected(row: Record<string, unknown>): boolean {\n return this.selectedRows().has(this.rowKey(row));\n }\n\n private emitSelectionChange(): void {\n const keys = this.selectedRows();\n // In data order, so the consumer gets a stable list whatever the sort.\n const selected = this.data().filter((row) => keys.has(this.rowKey(row)));\n this.selectionChange.emit({ selected, allSelected: this.allSelected() });\n }\n\n // -- Column Filters --\n protected onFilterChange(columnKey: string, value: string): void {\n const filters = { ...this.columnFilters(), [columnKey]: value };\n this.columnFilters.set(filters);\n this.currentPage.set(0);\n }\n\n protected getFilterValue(columnKey: string): string {\n return this.columnFilters()[columnKey] || '';\n }\n\n // -- Inline Editing --\n // Keyed by row identity too — the edited cell is the one the user clicked,\n // whichever position sorting put it in.\n protected startEdit(row: Record<string, unknown>, column: string, currentValue: unknown): void {\n if (!this.editable()) return;\n const col = this.columns().find(c => c.key === column);\n if (col && col.editable === false) return;\n this.editingCell.set({ key: this.rowKey(row), column });\n this.editValue.set(String(currentValue ?? ''));\n }\n\n protected isEditing(row: Record<string, unknown>, column: string): boolean {\n const cell = this.editingCell();\n return cell !== null && cell.key === this.rowKey(row) && cell.column === column;\n }\n\n protected commitEdit(row: Record<string, unknown>, column: string): void {\n // Only the cell being edited commits: the input's blur arrives after Enter\n // or Escape already ended the edit, and must not commit (or re-commit).\n if (!this.isEditing(row, column)) return;\n const oldValue = row[column];\n const newValue = this.editValue();\n this.editingCell.set(null);\n this.editValue.set('');\n if (String(oldValue ?? '') !== newValue) {\n const rowIndex = this.dataIndexMap().get(row) ?? -1;\n this.cellEdit.emit({ row, column, oldValue, newValue, rowIndex });\n }\n }\n\n protected cancelEdit(): void {\n this.editingCell.set(null);\n this.editValue.set('');\n }\n\n protected onEditKeydown(event: KeyboardEvent, row: Record<string, unknown>, column: string): void {\n if (event.key === 'Enter') {\n this.commitEdit(row, column);\n } else if (event.key === 'Escape') {\n this.cancelEdit();\n }\n }\n\n /** Enter/Space on a focused sortable header sorts, like a click does. */\n protected onHeaderKeydown(event: KeyboardEvent, columnKey: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.handleSort(columnKey);\n }\n }\n\n protected getInputValue(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n}\n","<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"filterPlaceholderLabel() + ' ' + column.label\"\n [ariaLabel]=\"filterAriaLabel() + ' ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (change)=\"toggleSelectAll()\"\n [attr.aria-label]=\"selectAllAriaLabel()\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <!-- A sortable header is a keyboard stop too: Enter/Space sort like a click. -->\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [attr.tabindex]=\"column.sortable ? 0 : null\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\"\n (keydown)=\"column.sortable ? onHeaderKeydown($event, column.key) : null\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.key) {\n <!-- In tree mode the rows form the treegrid's keyboard model: a roving\n tab stop plus Arrow/Home/End/Enter/Space handling (see the\n component). Flat mode keeps plain table rows. -->\n <tr\n #dataRow\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.row)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.tabindex]=\"rowTabindex(dr)\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n [attr.aria-selected]=\"treeMode() && selectable() ? isRowSelected(dr.row) : null\"\n (click)=\"onRowClick(dr.row)\"\n (focus)=\"onRowFocus(dr)\"\n (keydown)=\"onRowKeydown($event, dr)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.row)\"\n (change)=\"toggleRowSelect(dr.row)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"selectRowAriaLabel() + ' ' + (dr.absIndex + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.row, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? collapseRowAriaLabel() : expandRowAriaLabel()) + ' ' + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"action.tooltip ?? action.label ?? action.key\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(row, column.key)) {\n <input\n #editInput\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(row, column.key)\"\n (keydown)=\"onEditKeydown($event, row, column.key)\"\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}–{{ paginationEnd }} {{ rangeOfLabel() }} {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"size() === 'sm' ? 'sm' : size() === 'lg' ? 'lg' : 'md'\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"rowsPerPageAriaLabel()\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n [attr.aria-label]=\"previousPageAriaLabel()\"\n >‹</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n [attr.aria-label]=\"nextPageAriaLabel()\"\n >›</button>\n </div>\n </div>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lifecorner-angular-ui-kit-table.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/table/table-cell.directive.ts","../../../../libs/angular-ui-kit/src/lib/table/table.component.ts","../../../../libs/angular-ui-kit/src/lib/table/table.component.html"],"sourcesContent":["import { Directive, input, TemplateRef, inject } from '@angular/core';\n\n/**\n * Directive for defining custom cell templates in the Table component.\n *\n * @example\n * ```html\n * <lc-table [columns]=\"columns\" [data]=\"data\">\n * <ng-template lcTableCell=\"status\" let-row>\n * <lc-badge [variant]=\"row.status\">{{ row.status }}</lc-badge>\n * </ng-template>\n * </lc-table>\n * ```\n */\n@Directive({\n selector: '[lcTableCell]',\n standalone: true,\n})\nexport class TableCellDirective {\n /** The column key this template applies to */\n readonly columnKey = input('', { alias: 'lcTableCell' });\n\n public template = inject(TemplateRef<{ $implicit: Record<string, unknown> }>);\n}\n","import {\n Component,\n ChangeDetectionStrategy,\n ElementRef,\n input,\n output,\n computed,\n signal,\n linkedSignal,\n viewChild,\n viewChildren,\n afterRenderEffect,\n ContentChildren,\n QueryList,\n} from '@angular/core';\nimport { NgStyle, NgTemplateOutlet } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { TableCellDirective } from './table-cell.directive';\nimport { InputComponent } from '@lifecorner/angular-ui-kit/input';\nimport { SelectComponent } from '@lifecorner/angular-ui-kit/select';\nimport { ButtonComponent, ButtonVariant } from '@lifecorner/angular-ui-kit/button';\nimport { IconComponent, ɵprovideKitIcons } from '@lifecorner/angular-ui-kit/icon';\nimport { ICON_CHEVRON_RIGHT } from '@lifecorner/angular-ui-kit/icons';\n\ntype TableCellClass = string | ((\n value: unknown,\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n) => string);\n\ntype TableCellStyle = Record<string, string> | ((\n value: unknown,\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n) => Record<string, string>);\n\nexport interface TableColumn {\n key: string;\n label: string;\n sortable?: boolean;\n filterable?: boolean;\n editable?: boolean;\n width?: string;\n /** Optional CSS class(es) applied to both th and td cells */\n cssClass?: string;\n /** Optional CSS class(es) for td cells only (string or resolver callback) */\n cellClass?: TableCellClass;\n /** Optional inline styles for td cells only (object or resolver callback) */\n cellStyle?: TableCellStyle;\n /** Optional tooltip shown on hover over the column header */\n tooltip?: string;\n /** Optional formatter for cell output when no custom template is used */\n formatter?: (\n value: unknown,\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ) => unknown;\n /** Input type for inline editing (default: text) */\n editType?: 'text' | 'number' | 'select';\n /** Options for select edit type */\n editOptions?: string[];\n}\n\n/**\n * A row-level action rendered in the table's actions column (e.g. Freigeben, Ablehnen).\n * Action button clicks never trigger the row's `rowClick` output.\n */\nexport interface TableAction {\n /** Unique identifier emitted with the {@link ActionClickEvent} */\n key: string;\n /** Visible button label (omit for icon-only buttons when an `icon` is set) */\n label?: string;\n /** Optional icon name rendered before the label */\n icon?: string;\n /** Button variant (default: 'ghost') */\n variant?: ButtonVariant;\n /** Optional tooltip / aria-label, useful for icon-only actions */\n tooltip?: string;\n /** Hide this action for specific rows */\n hidden?: (row: Record<string, unknown>, rowIndex: number) => boolean;\n /** Disable this action for specific rows */\n disabled?: (row: Record<string, unknown>, rowIndex: number) => boolean;\n}\n\nexport type TableActionsAlign = 'start' | 'center' | 'end';\n\nexport interface ActionClickEvent {\n action: string;\n row: Record<string, unknown>;\n rowIndex: number;\n}\n\nexport interface SortEvent {\n column: string;\n direction: 'asc' | 'desc';\n}\n\nexport interface CellEditEvent {\n row: Record<string, unknown>;\n column: string;\n oldValue: unknown;\n newValue: unknown;\n /** Index of `row` in the `data` input (not its position on screen). */\n rowIndex: number;\n}\n\nexport interface SelectionChangeEvent {\n selected: Record<string, unknown>[];\n allSelected: boolean;\n}\n\n/** Emitted when a parent (group) row is expanded or collapsed in tree mode. */\nexport interface RowToggleEvent {\n id: string;\n expanded: boolean;\n row: Record<string, unknown>;\n}\n\n/**\n * Configuration that enables hierarchical (tree / grouped) rows. Mirrors the\n * discrete `idKey` / `parentKey` / `treeColumn` inputs and is exported for\n * consumers that prefer to pass a single config object around.\n */\nexport interface TableTreeConfig {\n idKey: string;\n parentKey: string;\n treeColumn?: string;\n}\n\nexport type TableVariant = 'default' | 'striped' | 'bordered';\nexport type TableSize = 'sm' | 'md' | 'lg';\n\n/**\n * Internal, render-ready view-model for a single visible table row. In flat\n * mode every row is depth 0 with no tree adornments; in tree mode it carries\n * the disclosure / indentation / aria metadata for the row.\n */\ninterface DisplayRow {\n /** The underlying data object. */\n row: Record<string, unknown>;\n /**\n * The row's index into `data()` — in both modes. It is what action, class,\n * style and formatter callbacks receive as `rowIndex`, and what identifies\n * the row in `CellEditEvent`. (It used to be the *positional* index in flat\n * mode — page offset plus row position — which, once a sort or filter was\n * active, pointed at a different row of `data()` than the one on screen.)\n */\n absIndex: number;\n /**\n * What selection and inline editing are keyed by: the row's `idKey` value\n * when the table has one, otherwise the row object itself. Either survives a\n * re-sort, a filter and a page change; an id also survives the parent\n * replacing its data array with fresh objects.\n */\n key: unknown;\n /** Row id (tree mode only; `null` in flat mode). */\n id: string | null;\n /** Tree depth — 0 for roots and for every row in flat mode. */\n depth: number;\n /** 1-based depth, surfaced as `aria-level` in tree mode. */\n level: number;\n /** Whether this row has visible children (renders a chevron). */\n hasChildren: boolean;\n /** Whether this parent row is currently expanded. */\n expanded: boolean;\n /** 1-based position within its sibling group (`aria-posinset`). */\n posInSet: number;\n /** Size of its sibling group (`aria-setsize`). */\n setSize: number;\n}\n\n/**\n * Table component for displaying structured data in rows and columns.\n *\n * Features:\n * - Column-based sorting with sort direction indicators\n * - Variant styles (default, striped, bordered)\n * - Size presets (sm, md, lg)\n * - Hoverable row highlighting\n * - Per-column formatter callbacks for display values\n * - Per-cell class/style callbacks for conditional styling\n * - Custom cell templates via content projection\n * - Composed cells (e.g. avatar + badge + actions)\n * - Hierarchical \"tree\" rows (grouped / expandable) via `idKey` + `parentKey`\n * - Responsive horizontal scrolling\n * - Empty state text for no data\n * - Accessible with proper table semantics\n *\n * @example\n * ```html\n * <lc-table [columns]=\"columns\" [data]=\"data\" variant=\"striped\" [hoverable]=\"true\"\n * (sort)=\"onSort($event)\" (rowClick)=\"onRowClick($event)\" />\n * ```\n *\n * @example\n * ```ts\n * columns: TableColumn[] = [\n * {\n * key: 'amount',\n * label: 'Amount',\n * formatter: (value) => new Intl.NumberFormat('de-DE', {\n * style: 'currency',\n * currency: 'EUR',\n * }).format(Number(value ?? 0)),\n * },\n * ];\n * ```\n */\n@Component({\n selector: 'lc-table',\n standalone: true,\n imports: [NgTemplateOutlet, NgStyle, FormsModule, SelectComponent, InputComponent, ButtonComponent, IconComponent],\n viewProviders: [ɵprovideKitIcons([ICON_CHEVRON_RIGHT])],\n templateUrl: './table.component.html',\n styleUrl: './table.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class TableComponent {\n /** Custom cell templates */\n @ContentChildren(TableCellDirective) cellTemplates!: QueryList<TableCellDirective>;\n\n /** Array of column definitions */\n columns = input<TableColumn[]>([]);\n\n /** Array of data objects to display */\n data = input<Record<string, unknown>[]>([]);\n\n /** Visual variant of the table */\n variant = input<TableVariant>('default');\n\n /** Size of the table */\n size = input<TableSize>('md');\n\n /** Whether rows should highlight on hover */\n hoverable = input<boolean>(false);\n\n /** Whether table should be responsive (horizontal scroll on mobile) */\n responsive = input<boolean>(true);\n\n /** Text shown when data is empty */\n emptyText = input<string>('No data available');\n\n /** Placeholder prefix of the column filters, followed by the column label (`filterable`). */\n filterPlaceholderLabel = input('Filter');\n\n /** Accessible name of the select-all checkbox (`selectable`). */\n selectAllAriaLabel = input('Select all rows');\n\n /** Accessible name of a row checkbox, followed by the row number. */\n selectRowAriaLabel = input('Select row');\n\n /** Screen-reader state of a column sorted ascending. */\n sortedAscendingLabel = input('sorted ascending');\n\n /** Screen-reader state of a column sorted descending. */\n sortedDescendingLabel = input('sorted descending');\n\n /** Tree mode: accessible name prefix of the expand toggle, followed by the row label. */\n expandRowAriaLabel = input('Aufklappen:');\n\n /** Tree mode: accessible name prefix of the collapse toggle, followed by the row label. */\n collapseRowAriaLabel = input('Einklappen:');\n\n /** Pagination: word between the shown range and the total (`1–10 of 42`). */\n rangeOfLabel = input('of');\n\n /** Accessible name of the page-size select. */\n rowsPerPageAriaLabel = input('Rows per page');\n\n /** Accessible name of the previous-page button. */\n previousPageAriaLabel = input('Previous page');\n\n /** Accessible name of the next-page button. */\n nextPageAriaLabel = input('Next page');\n\n // -- Pagination --\n /** Enable pagination */\n paginate = input<boolean>(false);\n\n /** Rows per page */\n pageSize = input<number>(10);\n\n /** Available page size options */\n pageSizeOptions = input<number[]>([5, 10, 25, 50]);\n\n // -- Selection --\n /** Enable row selection checkboxes */\n selectable = input<boolean>(false);\n\n // -- Column Filters --\n /** Enable per-column text filters */\n filterable = input<boolean>(false);\n\n // -- Inline Editing --\n /** Enable inline cell editing on double-click */\n editable = input<boolean>(false);\n\n // -- Row Actions --\n /**\n * Row-level actions rendered in a trailing actions column (e.g. Freigeben / Ablehnen).\n * Clicking an action button does NOT trigger the row's `rowClick` output.\n */\n actions = input<TableAction[]>([]);\n\n /** Header label for the actions column */\n actionsLabel = input<string>('');\n\n /** Width of the actions column (e.g. '120px') */\n actionsWidth = input<string | undefined>(undefined);\n\n /** Horizontal alignment of the action buttons (and header label) within the cell */\n actionsAlign = input<TableActionsAlign>('start');\n\n // -- Tree / grouped rows --\n /**\n * Row field holding the unique id. Required (together with {@link parentKey})\n * to enable hierarchical \"tree mode\". Absent ⇒ today's flat table.\n */\n idKey = input<string | undefined>(undefined);\n\n /**\n * Row field referencing the parent row's id. Presence of both `idKey` and\n * `parentKey` enables tree mode. Rows with an absent/empty or unknown parent\n * id are treated as roots.\n */\n parentKey = input<string | undefined>(undefined);\n\n /** Column key the chevron + indentation attach to. Default: first column. */\n treeColumn = input<string | undefined>(undefined);\n\n /** Initial expand state for all parent rows when uncontrolled. Default: true. */\n defaultExpanded = input<boolean>(true);\n\n /**\n * Controlled set of expanded parent ids. When provided, the table renders\n * exactly these as expanded; combine with {@link expandedIdsChange} for\n * `[(expandedIds)]`. When omitted, expansion is uncontrolled and seeded by\n * {@link defaultExpanded}.\n */\n expandedIds = input<string[] | undefined>(undefined);\n\n /** Indentation per depth level, in px. Default: 20. */\n indentSize = input<number>(20);\n\n /** Accessible name prefix of a column filter, followed by the column label. */\n filterAriaLabel = input('Filter by');\n\n /** Emitted when a sortable column header is clicked */\n readonly sort = output<SortEvent>();\n\n /** Emitted when a row is clicked */\n readonly rowClick = output<Record<string, unknown>>();\n\n /** Emitted when a cell is edited */\n readonly cellEdit = output<CellEditEvent>();\n\n /** Emitted when row selection changes */\n readonly selectionChange = output<SelectionChangeEvent>();\n\n /** Emitted when a row action button is clicked */\n readonly actionClick = output<ActionClickEvent>();\n\n /** Emitted when a parent row is expanded/collapsed (tree mode). */\n readonly rowToggle = output<RowToggleEvent>();\n\n /** Emitted with the full list of expanded parent ids; enables `[(expandedIds)]`. */\n readonly expandedIdsChange = output<string[]>();\n\n // -- Internal state --\n protected currentSort = signal<{ column: string; direction: 'asc' | 'desc' } | null>(null);\n /**\n * Effective page size. Seeded from the `pageSize` input (resetting if it\n * changes) and overridable by the user via the page-size dropdown.\n */\n protected internalPageSize = linkedSignal(() => this.pageSize());\n /**\n * Current page, kept within range: when the data shrinks or the page size\n * grows so that the page no longer exists, it moves back to the last one\n * (rather than showing an empty page captioned \"31–30 of 30\").\n */\n protected currentPage = linkedSignal<number, number>({\n source: () => this.totalPages(),\n computation: (total, previous) => Math.min(previous?.value ?? 0, total - 1),\n });\n /**\n * Selected row keys (see `DisplayRow.key`). Pruned when `data` changes, so\n * a key whose row is gone doesn't linger and count towards \"all selected\".\n */\n protected selectedRows = linkedSignal<Set<unknown>, Set<unknown>>({\n source: () => this.rowKeys(),\n computation: (keys, previous) => {\n if (!previous) return new Set<unknown>();\n const kept = new Set([...previous.value].filter((k) => keys.has(k)));\n return kept.size === previous.value.size ? previous.value : kept;\n },\n });\n protected columnFilters = signal<Record<string, string>>({});\n protected editingCell = signal<{ key: unknown; column: string } | null>(null);\n protected editValue = signal<string>('');\n\n /** The inline-edit input while a cell is being edited. */\n private readonly editInput = viewChild<ElementRef<HTMLInputElement>>('editInput');\n private focusedEditInput: HTMLInputElement | null = null;\n\n constructor() {\n // The edit input is inserted on double-click. `autofocus` is only honoured\n // for elements present when the page loads, so the input never received\n // focus (and Enter/Escape/blur never reached it); focus it once it renders.\n afterRenderEffect(() => {\n const el = this.editInput()?.nativeElement ?? null;\n if (el && el !== this.focusedEditInput) {\n el.focus();\n }\n this.focusedEditInput = el;\n });\n }\n\n /** The key of every row currently in `data()`. */\n private readonly rowKeys = computed(() => new Set(this.data().map((row) => this.rowKey(row))));\n\n /** See `DisplayRow.key`. */\n private rowKey(row: Record<string, unknown>): unknown {\n const idKey = this.idKey();\n return idKey ? String(row[idKey] ?? '') : row;\n }\n /** User expand/collapse overrides keyed by row id (uncontrolled mode). */\n private readonly expandOverrides = signal<Map<string, boolean>>(new Map());\n\n /**\n * Filtered data (applies column filters)\n */\n protected readonly filteredData = computed(() => {\n let items = this.data();\n const filters = this.columnFilters();\n\n if (this.filterable()) {\n for (const [key, value] of Object.entries(filters)) {\n if (value.trim()) {\n items = items.filter(row =>\n String(row[key] ?? '').toLowerCase().includes(value.toLowerCase())\n );\n }\n }\n }\n\n return items;\n });\n\n /** Comparator for the active sort, shared by flat sorting and tree sibling sorting. */\n private rowComparator(sortState: { column: string; direction: 'asc' | 'desc' }) {\n return (a: Record<string, unknown>, b: Record<string, unknown>): number => {\n const aVal = a[sortState.column];\n const bVal = b[sortState.column];\n let cmp = 0;\n if (aVal == null && bVal == null) cmp = 0;\n else if (aVal == null) cmp = -1;\n else if (bVal == null) cmp = 1;\n else if (typeof aVal === 'number' && typeof bVal === 'number') cmp = aVal - bVal;\n else cmp = String(aVal).localeCompare(String(bVal));\n return sortState.direction === 'asc' ? cmp : -cmp;\n };\n }\n\n /**\n * Sorted data\n */\n protected readonly sortedData = computed(() => {\n const items = [...this.filteredData()];\n const sortState = this.currentSort();\n if (!sortState) return items;\n return items.sort(this.rowComparator(sortState));\n });\n\n /**\n * Paginated data (or all if pagination disabled). Flat mode only.\n */\n protected readonly displayData = computed(() => {\n const items = this.sortedData();\n if (!this.paginate()) return items;\n const ps = this.internalPageSize();\n const start = this.currentPage() * ps;\n return items.slice(start, start + ps);\n });\n\n // -- Tree / grouped rows -----------------------------------------------------\n\n /** Whether hierarchical tree mode is active. */\n protected readonly treeMode = computed(() => !!this.idKey() && !!this.parentKey());\n\n /** Column the chevron + indentation attach to (defaults to the first column). */\n protected readonly effectiveTreeColumn = computed(\n () => this.treeColumn() || this.columns()[0]?.key\n );\n\n /** Stable map of row object → its index in `data()` (row identity for tree mode). */\n private readonly dataIndexMap = computed(() => {\n const map = new Map<Record<string, unknown>, number>();\n this.data().forEach((row, i) => map.set(row, i));\n return map;\n });\n\n /** Parent → ordered children index built from `idKey`/`parentKey`. */\n private readonly treeBuild = computed(() => {\n const idKey = this.idKey();\n const parentKey = this.parentKey();\n const byId = new Map<string, Record<string, unknown>>();\n const childrenOf = new Map<string, Record<string, unknown>[]>();\n const roots: Record<string, unknown>[] = [];\n if (!idKey || !parentKey) return { byId, childrenOf, roots };\n\n const rows = this.data();\n for (const row of rows) {\n const id = String(row[idKey] ?? '');\n if (id) byId.set(id, row);\n }\n for (const row of rows) {\n const parentRaw = row[parentKey];\n const parentId = parentRaw == null ? '' : String(parentRaw);\n if (parentId && byId.has(parentId)) {\n const siblings = childrenOf.get(parentId) ?? [];\n siblings.push(row);\n childrenOf.set(parentId, siblings);\n } else {\n // No parent, empty parent, or orphaned (unknown parent) ⇒ root.\n roots.push(row);\n }\n }\n return { byId, childrenOf, roots };\n });\n\n /**\n * Tree restricted to rows that match the active filters together with their\n * ancestor chain (so the path to a match stays visible).\n */\n private readonly treeFiltered = computed(() => {\n const { byId, childrenOf, roots } = this.treeBuild();\n const parentKey = this.parentKey();\n const filters = this.columnFilters();\n const active =\n this.filterable() && parentKey && Object.values(filters).some((v) => v.trim());\n if (!active) return { childrenOf, roots };\n\n const matches = (row: Record<string, unknown>): boolean =>\n Object.entries(filters).every(\n ([key, value]) =>\n !value.trim() ||\n String(row[key] ?? '').toLowerCase().includes(value.toLowerCase())\n );\n\n // Visible = every matching row plus all of its ancestors.\n const visible = new Set<Record<string, unknown>>();\n for (const row of this.data()) {\n if (!matches(row)) continue;\n let current: Record<string, unknown> | undefined = row;\n while (current && !visible.has(current)) {\n visible.add(current);\n const parentRaw: unknown = current[parentKey];\n const parentId = parentRaw == null ? '' : String(parentRaw);\n current = parentId ? byId.get(parentId) : undefined;\n }\n }\n\n const visibleChildrenOf = new Map<string, Record<string, unknown>[]>();\n const visibleRoots: Record<string, unknown>[] = [];\n for (const row of this.data()) {\n if (!visible.has(row)) continue;\n const parentRaw = row[parentKey];\n const parentId = parentRaw == null ? '' : String(parentRaw);\n const parent = parentId ? byId.get(parentId) : undefined;\n if (parent && visible.has(parent)) {\n const siblings = visibleChildrenOf.get(parentId) ?? [];\n siblings.push(row);\n visibleChildrenOf.set(parentId, siblings);\n } else {\n visibleRoots.push(row);\n }\n }\n return { childrenOf: visibleChildrenOf, roots: visibleRoots };\n });\n\n /** Tree with each sibling group sorted by the active sort (structure kept intact). */\n private readonly treeSorted = computed(() => {\n const { childrenOf, roots } = this.treeFiltered();\n const sortState = this.currentSort();\n if (!sortState) return { childrenOf, roots };\n const cmp = this.rowComparator(sortState);\n const sortedChildrenOf = new Map<string, Record<string, unknown>[]>();\n for (const [parentId, siblings] of childrenOf) {\n sortedChildrenOf.set(parentId, [...siblings].sort(cmp));\n }\n return { childrenOf: sortedChildrenOf, roots: [...roots].sort(cmp) };\n });\n\n /** Root rows after filter/sort — the unit of pagination in tree mode. */\n private readonly treeRoots = computed(() => this.treeSorted().roots);\n\n /**\n * Render-ready rows. In flat mode this wraps the existing paginated data; in\n * tree mode it paginates roots and flattens each visible (expanded) subtree.\n */\n protected readonly displayRows = computed<DisplayRow[]>(() => {\n const dataIndex = this.dataIndexMap();\n if (!this.treeMode()) {\n return this.displayData().map((row) => ({\n row,\n absIndex: dataIndex.get(row) ?? -1,\n key: this.rowKey(row),\n id: null,\n depth: 0,\n level: 0,\n hasChildren: false,\n expanded: false,\n posInSet: 0,\n setSize: 0,\n }));\n }\n\n const idKey = this.idKey() as string;\n const { childrenOf } = this.treeSorted();\n let roots = this.treeRoots();\n if (this.paginate()) {\n const ps = this.internalPageSize();\n const start = this.currentPage() * ps;\n roots = roots.slice(start, start + ps);\n }\n\n const out: DisplayRow[] = [];\n const walk = (group: Record<string, unknown>[], depth: number): void => {\n group.forEach((row, idx) => {\n const id = String(row[idKey] ?? '');\n const children = childrenOf.get(id) ?? [];\n const hasChildren = children.length > 0;\n const expanded = hasChildren && this.isExpanded(id);\n out.push({\n row,\n absIndex: dataIndex.get(row) ?? -1,\n key: this.rowKey(row),\n id,\n depth,\n level: depth + 1,\n hasChildren,\n expanded,\n posInSet: idx + 1,\n setSize: group.length,\n });\n if (expanded) walk(children, depth + 1);\n });\n };\n walk(roots, 0);\n return out;\n });\n\n /** Total pages */\n protected readonly totalPages = computed(() => {\n if (!this.paginate()) return 1;\n const total = this.treeMode() ? this.treeRoots().length : this.filteredData().length;\n return Math.max(1, Math.ceil(total / this.internalPageSize()));\n });\n\n /**\n * Pagination row count. Tree mode counts root rows (the paginated unit); flat\n * mode counts filtered rows.\n */\n protected readonly totalRows = computed(() =>\n this.treeMode() ? this.treeRoots().length : this.filteredData().length\n );\n\n /** Whether all visible rows are selected */\n protected readonly allSelected = computed(() => {\n const rows = this.displayRows();\n if (rows.length === 0) return false;\n const selected = this.selectedRows();\n return rows.every((r) => selected.has(r.key));\n });\n\n /** Whether some, but not all, visible rows are selected — the header box's mixed state. */\n protected readonly someSelected = computed(() => {\n const selected = this.selectedRows();\n return !this.allSelected() && this.displayRows().some((r) => selected.has(r.key));\n });\n\n protected readonly pageSizeSelectOptions = computed(() =>\n this.pageSizeOptions().map((opt) => ({\n value: opt,\n label: `${opt} / page`,\n }))\n );\n\n /**\n * Computed CSS classes for the table element\n */\n tableClasses = computed(() => {\n const classes = ['lc-table'];\n classes.push(`lc-table--${this.variant()}`);\n classes.push(`lc-table--${this.size()}`);\n if (this.hoverable()) classes.push('lc-table--hoverable');\n return classes.join(' ');\n });\n\n /**\n * Computed CSS classes for the wrapper element\n */\n wrapperClasses = computed(() => {\n const classes = ['lc-table-wrapper'];\n if (this.responsive()) classes.push('lc-table-wrapper--responsive');\n return classes.join(' ');\n });\n\n // -- Sort --\n handleSort(columnKey: string): void {\n const column = this.columns().find((col) => col.key === columnKey);\n if (!column || !column.sortable) return;\n\n const current = this.currentSort();\n let direction: 'asc' | 'desc' = 'asc';\n if (current && current.column === columnKey) {\n direction = current.direction === 'asc' ? 'desc' : 'asc';\n }\n\n this.currentSort.set({ column: columnKey, direction });\n this.sort.emit({ column: columnKey, direction });\n }\n\n getSortState(columnKey: string): 'asc' | 'desc' | null {\n const current = this.currentSort();\n if (current && current.column === columnKey) return current.direction;\n return null;\n }\n\n getAriaSort(columnKey: string): string | null {\n const sortState = this.getSortState(columnKey);\n if (sortState === 'asc') return 'ascending';\n if (sortState === 'desc') return 'descending';\n return null;\n }\n\n getHeaderClasses(column: TableColumn): string {\n const classes: string[] = [];\n if (column.sortable) classes.push('sortable');\n const sortState = this.getSortState(column.key);\n if (sortState) classes.push(`sorted-${sortState}`);\n return classes.join(' ');\n }\n\n getCellValue(row: Record<string, unknown>, columnKey: string): unknown {\n return row[columnKey];\n }\n\n getFormattedCellValue(\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ): unknown {\n const value = this.getCellValue(row, column.key);\n if (!column.formatter) return value;\n\n return column.formatter(value, row, column, rowIndex);\n }\n\n getCellClasses(\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ): string {\n const classes: string[] = [];\n if (column.cssClass) classes.push(column.cssClass);\n\n if (typeof column.cellClass === 'string') {\n classes.push(column.cellClass);\n } else if (typeof column.cellClass === 'function') {\n const resolved = column.cellClass(\n this.getCellValue(row, column.key),\n row,\n column,\n rowIndex\n );\n if (resolved) classes.push(resolved);\n }\n\n return classes.join(' ').trim();\n }\n\n getCellStyles(\n row: Record<string, unknown>,\n column: TableColumn,\n rowIndex: number\n ): Record<string, string> | null {\n if (!column.cellStyle) return null;\n\n if (typeof column.cellStyle === 'function') {\n return column.cellStyle(\n this.getCellValue(row, column.key),\n row,\n column,\n rowIndex\n );\n }\n\n return column.cellStyle;\n }\n\n /** Whether the given column is the disclosure/indent column in tree mode. */\n protected isTreeColumn(columnKey: string): boolean {\n return this.treeMode() && columnKey === this.effectiveTreeColumn();\n }\n\n /** Indent levels to render before a row's chevron (one guide per ancestor depth). */\n protected indentLevels(depth: number): number[] {\n return Array.from({ length: depth }, (_, i) => i);\n }\n\n /** Accessible name for a row's disclosure button (the tree column's value). */\n protected treeCellLabel(row: Record<string, unknown>): string {\n const col = this.effectiveTreeColumn();\n return col ? String(row[col] ?? '') : '';\n }\n\n getCellTemplate(columnKey: string): TableCellDirective | undefined {\n return this.cellTemplates?.find((template) => template.columnKey() === columnKey);\n }\n\n hasCustomTemplate(columnKey: string): boolean {\n return !!this.getCellTemplate(columnKey);\n }\n\n onRowClick(row: Record<string, unknown>): void {\n this.rowClick.emit(row);\n }\n\n // -- Row Actions --\n /** Whether the trailing actions column should be rendered */\n protected readonly hasActions = computed(() => this.actions().length > 0);\n\n protected isActionHidden(\n action: TableAction,\n row: Record<string, unknown>,\n rowIndex: number\n ): boolean {\n return action.hidden ? action.hidden(row, rowIndex) : false;\n }\n\n protected isActionDisabled(\n action: TableAction,\n row: Record<string, unknown>,\n rowIndex: number\n ): boolean {\n return action.disabled ? action.disabled(row, rowIndex) : false;\n }\n\n /**\n * Handles an action button click. The DOM click is stopped from propagating\n * (see template `$event.stopPropagation()`), so the row's `rowClick` never fires.\n */\n protected onActionClick(\n action: TableAction,\n row: Record<string, unknown>,\n rowIndex: number\n ): void {\n this.actionClick.emit({\n action: action.key,\n row,\n rowIndex,\n });\n }\n\n // -- Tree keyboard model -----------------------------------------------------\n // `role=\"treegrid\"` promises a composite widget: one tab stop, arrows to move\n // between rows, Right/Left to open/close a group or step into/out of it. The\n // rows carry a roving tabindex; the focused row is remembered by key so it\n // survives re-renders, and falls back to the first row when it is gone.\n\n private readonly rowEls = viewChildren<ElementRef<HTMLTableRowElement>>('dataRow');\n private readonly focusedRowKey = signal<unknown>(null);\n\n /** Key of the row that holds the tab stop. */\n private readonly effectiveFocusedKey = computed(() => {\n const rows = this.displayRows();\n const key = this.focusedRowKey();\n return rows.some((r) => r.key === key) ? key : rows[0]?.key;\n });\n\n protected rowTabindex(dr: DisplayRow): number | null {\n if (!this.treeMode()) return null;\n return dr.key === this.effectiveFocusedKey() ? 0 : -1;\n }\n\n protected onRowFocus(dr: DisplayRow): void {\n if (this.treeMode()) this.focusedRowKey.set(dr.key);\n }\n\n protected onRowKeydown(event: KeyboardEvent, dr: DisplayRow): void {\n if (!this.treeMode()) return;\n // Keys typed into an inline editor or the row's own controls are theirs.\n if ((event.target as HTMLElement).tagName === 'INPUT') return;\n const rows = this.displayRows();\n const index = rows.findIndex((r) => r.key === dr.key);\n if (index < 0) return;\n\n switch (event.key) {\n case 'ArrowDown':\n this.focusRow(index + 1);\n break;\n case 'ArrowUp':\n this.focusRow(index - 1);\n break;\n case 'Home':\n this.focusRow(0);\n break;\n case 'End':\n this.focusRow(rows.length - 1);\n break;\n case 'ArrowRight':\n if (!dr.hasChildren) return;\n if (dr.expanded) this.focusRow(index + 1); // first child\n else if (dr.id) this.toggleRow(dr.id, dr.row);\n break;\n case 'ArrowLeft':\n if (dr.hasChildren && dr.expanded && dr.id) {\n this.toggleRow(dr.id, dr.row);\n } else if (dr.depth > 0) {\n // Step out to the parent: the nearest row above with a smaller depth.\n for (let i = index - 1; i >= 0; i--) {\n if (rows[i].depth < dr.depth) {\n this.focusRow(i);\n break;\n }\n }\n } else {\n return;\n }\n break;\n case 'Enter':\n this.rowClick.emit(dr.row);\n break;\n case ' ':\n if (!this.selectable()) return;\n this.toggleRowSelect(dr.row);\n break;\n default:\n return;\n }\n event.preventDefault();\n }\n\n private focusRow(index: number): void {\n const rows = this.displayRows();\n if (index < 0 || index >= rows.length) return;\n this.focusedRowKey.set(rows[index].key);\n this.rowEls()[index]?.nativeElement.focus();\n }\n\n // -- Tree expand / collapse --------------------------------------------------\n\n /** Whether the parent row with the given id is currently expanded. */\n protected isExpanded(id: string): boolean {\n const controlled = this.expandedIds();\n if (controlled !== undefined) return controlled.includes(id);\n const override = this.expandOverrides().get(id);\n if (override !== undefined) return override;\n return this.defaultExpanded();\n }\n\n /** Chevron click: toggle expand state without triggering the row click. */\n protected onChevronClick(displayRow: DisplayRow, event: Event): void {\n event.stopPropagation();\n if (displayRow.id) this.toggleRow(displayRow.id, displayRow.row);\n }\n\n private toggleRow(id: string, row: Record<string, unknown>): void {\n const expanded = !this.isExpanded(id);\n this.expandOverrides.update((map) => {\n const next = new Map(map);\n next.set(id, expanded);\n return next;\n });\n this.rowToggle.emit({ id, expanded, row });\n this.expandedIdsChange.emit(this.nextExpandedIds(id, expanded));\n }\n\n /** The full list of expanded parent ids after applying a single toggle. */\n private nextExpandedIds(changedId: string, changedExpanded: boolean): string[] {\n const controlled = this.expandedIds();\n const overrides = this.expandOverrides();\n const parentIds = Array.from(this.treeBuild().childrenOf.keys());\n return parentIds.filter((pid) => {\n if (pid === changedId) return changedExpanded;\n if (controlled !== undefined) return controlled.includes(pid);\n const override = overrides.get(pid);\n return override !== undefined ? override : this.defaultExpanded();\n });\n }\n\n // -- Pagination --\n protected goToPage(page: number): void {\n if (page >= 0 && page < this.totalPages()) {\n this.currentPage.set(page);\n }\n }\n\n protected onPageSizeChange(event: Event): void {\n const newSize = Number((event.target as HTMLSelectElement).value);\n this.internalPageSize.set(newSize);\n this.currentPage.set(0);\n }\n\n protected onPageSizeModelChange(value: string | number | null): void {\n if (value == null) {\n return;\n }\n const parsed = typeof value === 'number' ? value : Number(value);\n if (!Number.isFinite(parsed)) {\n return;\n }\n this.internalPageSize.set(parsed);\n this.currentPage.set(0);\n }\n\n protected get paginationStart(): number {\n if (this.totalRows() === 0) return 0;\n return this.currentPage() * this.internalPageSize() + 1;\n }\n\n protected get paginationEnd(): number {\n return Math.min((this.currentPage() + 1) * this.internalPageSize(), this.totalRows());\n }\n\n // -- Selection --\n // Keyed by row identity (see `DisplayRow.key`), never by position: a sort or\n // filter changes where a row is shown, not which row it is.\n protected toggleSelectAll(): void {\n const selected = new Set(this.selectedRows());\n const rows = this.displayRows();\n const allSelected = this.allSelected();\n\n rows.forEach((r) => {\n if (allSelected) selected.delete(r.key);\n else selected.add(r.key);\n });\n\n this.selectedRows.set(selected);\n this.emitSelectionChange();\n }\n\n protected toggleRowSelect(row: Record<string, unknown>): void {\n const key = this.rowKey(row);\n const selected = new Set(this.selectedRows());\n if (selected.has(key)) selected.delete(key);\n else selected.add(key);\n this.selectedRows.set(selected);\n this.emitSelectionChange();\n }\n\n protected isRowSelected(row: Record<string, unknown>): boolean {\n return this.selectedRows().has(this.rowKey(row));\n }\n\n private emitSelectionChange(): void {\n const keys = this.selectedRows();\n // In data order, so the consumer gets a stable list whatever the sort.\n const selected = this.data().filter((row) => keys.has(this.rowKey(row)));\n this.selectionChange.emit({ selected, allSelected: this.allSelected() });\n }\n\n // -- Column Filters --\n protected onFilterChange(columnKey: string, value: string): void {\n const filters = { ...this.columnFilters(), [columnKey]: value };\n this.columnFilters.set(filters);\n this.currentPage.set(0);\n }\n\n protected getFilterValue(columnKey: string): string {\n return this.columnFilters()[columnKey] || '';\n }\n\n // -- Inline Editing --\n // Keyed by row identity too — the edited cell is the one the user clicked,\n // whichever position sorting put it in.\n protected startEdit(row: Record<string, unknown>, column: string, currentValue: unknown): void {\n if (!this.editable()) return;\n const col = this.columns().find(c => c.key === column);\n if (col && col.editable === false) return;\n this.editingCell.set({ key: this.rowKey(row), column });\n this.editValue.set(String(currentValue ?? ''));\n }\n\n protected isEditing(row: Record<string, unknown>, column: string): boolean {\n const cell = this.editingCell();\n return cell !== null && cell.key === this.rowKey(row) && cell.column === column;\n }\n\n protected commitEdit(row: Record<string, unknown>, column: string): void {\n // Only the cell being edited commits: the input's blur arrives after Enter\n // or Escape already ended the edit, and must not commit (or re-commit).\n if (!this.isEditing(row, column)) return;\n const oldValue = row[column];\n const newValue = this.editValue();\n this.editingCell.set(null);\n this.editValue.set('');\n if (String(oldValue ?? '') !== newValue) {\n const rowIndex = this.dataIndexMap().get(row) ?? -1;\n this.cellEdit.emit({ row, column, oldValue, newValue, rowIndex });\n }\n }\n\n protected cancelEdit(): void {\n this.editingCell.set(null);\n this.editValue.set('');\n }\n\n protected onEditKeydown(event: KeyboardEvent, row: Record<string, unknown>, column: string): void {\n if (event.key === 'Enter') {\n this.commitEdit(row, column);\n } else if (event.key === 'Escape') {\n this.cancelEdit();\n }\n }\n\n /** Enter/Space on a focused sortable header sorts, like a click does. */\n protected onHeaderKeydown(event: KeyboardEvent, columnKey: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.handleSort(columnKey);\n }\n }\n\n protected getInputValue(event: Event): string {\n return (event.target as HTMLInputElement).value;\n }\n}\n","<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" [attr.role]=\"treeMode() ? 'treegrid' : 'table'\">\n <thead>\n <!-- Filter row -->\n @if (filterable()) {\n <tr class=\"lc-table__filter-row\">\n @if (selectable()) {\n <th class=\"lc-table__select-cell\"></th>\n }\n @for (column of columns(); track column.key) {\n <th>\n @if (column.filterable !== false) {\n <lc-input\n class=\"lc-table__filter-input\"\n size=\"xs\"\n [placeholder]=\"filterPlaceholderLabel() + ' ' + column.label\"\n [ariaLabel]=\"filterAriaLabel() + ' ' + column.label\"\n [ngModel]=\"getFilterValue(column.key)\"\n (ngModelChange)=\"onFilterChange(column.key, $event)\"\n />\n }\n </th>\n }\n @if (hasActions()) {\n <th class=\"lc-table__actions-cell\"></th>\n }\n </tr>\n }\n <!-- Header row -->\n <tr>\n @if (selectable()) {\n <th class=\"lc-table__select-cell\" scope=\"col\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"allSelected()\"\n [indeterminate]=\"someSelected()\"\n (change)=\"toggleSelectAll()\"\n [attr.aria-label]=\"selectAllAriaLabel()\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <!-- A sortable header is a keyboard stop too: Enter/Space sort like a click. -->\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [attr.tabindex]=\"column.sortable ? 0 : null\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\"\n (keydown)=\"column.sortable ? onHeaderKeydown($event, column.key) : null\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? sortedAscendingLabel() : sortedDescendingLabel()\">\n @if (getSortState(column.key) === 'asc') {\n ↑\n } @else {\n ↓\n }\n </span>\n }\n </th>\n }\n @if (hasActions()) {\n <th\n scope=\"col\"\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [style.width]=\"actionsWidth()\"\n >\n {{ actionsLabel() }}\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayRows().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0) + (hasActions() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (dr of displayRows(); track dr.key) {\n <!-- In tree mode the rows form the treegrid's keyboard model: a roving\n tab stop plus Arrow/Home/End/Enter/Space handling (see the\n component). Flat mode keeps plain table rows. -->\n <tr\n #dataRow\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(dr.row)\"\n [class.lc-table__row--group]=\"dr.hasChildren\"\n [attr.role]=\"treeMode() ? 'row' : null\"\n [attr.tabindex]=\"rowTabindex(dr)\"\n [attr.aria-level]=\"treeMode() ? dr.level : null\"\n [attr.aria-expanded]=\"treeMode() && dr.hasChildren ? dr.expanded : null\"\n [attr.aria-posinset]=\"treeMode() ? dr.posInSet : null\"\n [attr.aria-setsize]=\"treeMode() ? dr.setSize : null\"\n [attr.aria-selected]=\"treeMode() && selectable() ? isRowSelected(dr.row) : null\"\n (click)=\"onRowClick(dr.row)\"\n (focus)=\"onRowFocus(dr)\"\n (keydown)=\"onRowKeydown($event, dr)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\" [attr.role]=\"treeMode() ? 'gridcell' : null\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected(dr.row)\"\n (change)=\"toggleRowSelect(dr.row)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"selectRowAriaLabel() + ' ' + (dr.absIndex + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"getCellClasses(dr.row, column, dr.absIndex)\"\n [ngStyle]=\"getCellStyles(dr.row, column, dr.absIndex)\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (dblclick)=\"editable() ? startEdit(dr.row, column.key, getCellValue(dr.row, column.key)) : null\"\n >\n @if (isTreeColumn(column.key)) {\n <span class=\"lc-table__tree-cell\">\n @for (lvl of indentLevels(dr.depth); track lvl) {\n <span class=\"lc-table__tree-indent\" [style.width.px]=\"indentSize()\"></span>\n }\n <span class=\"lc-table__tree-chevron\" [style.width.px]=\"indentSize()\">\n @if (dr.hasChildren) {\n <button\n type=\"button\"\n class=\"lc-table__chevron-btn\"\n [class.lc-table__chevron-btn--expanded]=\"dr.expanded\"\n [attr.aria-label]=\"(dr.expanded ? collapseRowAriaLabel() : expandRowAriaLabel()) + ' ' + treeCellLabel(dr.row)\"\n [attr.aria-expanded]=\"dr.expanded\"\n (click)=\"onChevronClick(dr, $event)\"\n >\n <lc-icon name=\"chevron-right\" size=\"xs\" [decorative]=\"true\" />\n </button>\n }\n </span>\n <span class=\"lc-table__tree-content\">\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n </span>\n </span>\n } @else {\n <ng-container\n *ngTemplateOutlet=\"cellContent; context: { row: dr.row, column: column, absIndex: dr.absIndex }\"\n ></ng-container>\n }\n </td>\n }\n @if (hasActions()) {\n <td\n class=\"lc-table__actions-cell\"\n [class]=\"'lc-table__actions-cell--' + actionsAlign()\"\n [attr.role]=\"treeMode() ? 'gridcell' : null\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"lc-table__actions\">\n @for (action of actions(); track action.key) {\n @if (!isActionHidden(action, dr.row, dr.absIndex)) {\n <lc-button\n [variant]=\"action.variant ?? 'ghost'\"\n size=\"xs\"\n [iconOnly]=\"!action.label\"\n [disabled]=\"isActionDisabled(action, dr.row, dr.absIndex)\"\n [ariaLabel]=\"action.tooltip ?? action.label ?? action.key\"\n (clicked)=\"onActionClick(action, dr.row, dr.absIndex)\"\n >\n @if (action.icon) {\n <lc-icon [name]=\"action.icon\" size=\"sm\" [decorative]=\"true\" />\n }\n @if (action.label) {\n {{ action.label }}\n }\n </lc-button>\n }\n }\n </div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Shared cell content (edit input / custom template / formatted value) -->\n<ng-template #cellContent let-row=\"row\" let-column=\"column\" let-absIndex=\"absIndex\">\n @if (isEditing(row, column.key)) {\n <input\n #editInput\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit(row, column.key)\"\n (keydown)=\"onEditKeydown($event, row, column.key)\"\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getFormattedCellValue(row, column, absIndex) }}\n }\n</ng-template>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}–{{ paginationEnd }} {{ rangeOfLabel() }} {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <lc-select\n class=\"lc-table-pagination__size\"\n [size]=\"size() === 'sm' ? 'sm' : size() === 'lg' ? 'lg' : 'md'\"\n [options]=\"pageSizeSelectOptions()\"\n [ngModel]=\"internalPageSize()\"\n [ariaLabel]=\"rowsPerPageAriaLabel()\"\n (ngModelChange)=\"onPageSizeModelChange($event)\"\n />\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n [attr.aria-label]=\"previousPageAriaLabel()\"\n >‹</button>\n <span class=\"lc-table-pagination__page\">\n {{ currentPage() + 1 }} / {{ totalPages() }}\n </span>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() >= totalPages() - 1\"\n (click)=\"goToPage(currentPage() + 1)\"\n [attr.aria-label]=\"nextPageAriaLabel()\"\n >›</button>\n </div>\n </div>\n}\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.13.1",
3
+ "version": "3.15.0",
4
4
  "description": "LifeCorner Design System – Angular UI component library",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -228,3 +228,55 @@ describe('Theme contrast (WCAG 2.2 AA)', () => {
228
228
  }
229
229
  });
230
230
  });
231
+
232
+ // Request 020: the pairings the new component options read, computed from the
233
+ // theme tokens (no new token). The outline tint is the button stylesheet's own.
234
+ describe('Component pairings of 3.15 (request 020)', () => {
235
+ const buttonCss = compile(resolve(__dirname, '../lib/button/button.component.scss')).css;
236
+ const tint = parse(buttonCss.match(/\n\.btn-outline \{[^}]*background-color: (rgba\([^)]+\))/)?.[1] ?? '');
237
+ const pages = ['--color-background', '--color-land-1', '--color-land-3', '--color-surface'];
238
+
239
+ /** Design 020 §5, per palette: [light, dark]. */
240
+ const expected = {
241
+ emptyStateIcon: [7.85, 9.68],
242
+ avatarGlyph: [7.0, 6.1],
243
+ outlineActiveText: [6.71, 6.71],
244
+ };
245
+
246
+ describe.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('%s palette', (_palette, tokens, i) => {
247
+ /** A token's colour, translucent ones composited over `base`. */
248
+ const solid = (name: string, base = '--color-background') => over(color(tokens, name), color(tokens, base));
249
+
250
+ it('AC-8: the primary empty-state icon on its circle (--color-primary-700 on -100)', () => {
251
+ const r = ratio(solid('--color-primary-700'), solid('--color-primary-100'));
252
+ expect(r).toBeCloseTo(expected.emptyStateIcon[i], 2);
253
+ expect(r).toBeGreaterThanOrEqual(3);
254
+ });
255
+
256
+ it('AC-12: the avatar person glyph on its disc (--color-neutral-700 on -300)', () => {
257
+ const r = ratio(solid('--color-neutral-700'), solid('--color-neutral-300'));
258
+ expect(r).toBeCloseTo(expected.avatarGlyph[i], 2);
259
+ expect(r).toBeGreaterThanOrEqual(3);
260
+ });
261
+
262
+ it.each(pages)('AC-13: outline primary at rest on %s: text 4.5:1 on the tint, border 3:1', (page) => {
263
+ const ground = solid(page);
264
+ expect(ratio(solid('--color-primary-700'), over(tint, ground))).toBeGreaterThanOrEqual(4.5);
265
+ expect(ratio(solid('--color-primary-600'), ground)).toBeGreaterThanOrEqual(3);
266
+ });
267
+
268
+ it.each(pages)('AC-13: outline primary on hover over %s: text 4.5:1 on --color-surface-selected, border 3:1', (page) => {
269
+ const fill = solid('--color-surface-selected', page);
270
+ expect(ratio(solid('--color-primary-700'), fill)).toBeGreaterThanOrEqual(4.5);
271
+ expect(ratio(solid('--color-primary-600'), solid(page))).toBeGreaterThanOrEqual(3);
272
+ });
273
+
274
+ it('AC-13: outline primary active: text on --color-primary-200 and the border beside it', () => {
275
+ const fill = solid('--color-primary-200');
276
+ const text = ratio(solid('--color-primary-700'), fill);
277
+ expect(text).toBeCloseTo(expected.outlineActiveText[i], 2);
278
+ expect(text).toBeGreaterThanOrEqual(4.5);
279
+ expect(ratio(solid('--color-primary-600'), fill)).toBeGreaterThanOrEqual(3);
280
+ });
281
+ });
282
+ });
@@ -1,4 +1,10 @@
1
1
  import * as i0 from "@angular/core";
2
+ /**
3
+ * Where the side navigation sits from 1024 px: `'below-header'` (the header
4
+ * spans the full width, the nav starts below it) or `'full-height'` (the nav
5
+ * runs from the top to the bottom of the viewport, the header beside it).
6
+ */
7
+ export type AppShellNavPlacement = 'below-header' | 'full-height';
2
8
  /**
3
9
  * App shell: the frame around every page of an app — header, side navigation,
4
10
  * page, bottom navigation bar, footer and the horizon — laid out for phones
@@ -38,6 +44,27 @@ import * as i0 from "@angular/core";
38
44
  * kit's styles): full-bleed, below the side navigation and the page, filling
39
45
  * the rest of the screen — on Today, the sign-in pages and the shell pages.
40
46
  *
47
+ * `navPlacement="full-height"` (3.14) runs the nav column from the top to the
48
+ * bottom of the viewport (sticky, 100dvh) with the header beside it, from
49
+ * 1024 px; below 1024 px it renders like the default. The DOM and tab order
50
+ * stay header → nav → page → footer, so in full-height the header's controls
51
+ * come before a brand at the top of the nav (banner, then navigation, then
52
+ * content). The land and the footer run under the nav; the footer's content
53
+ * starts at the nav width.
54
+ *
55
+ * CSS hooks (set them on `lc-app-shell` or any ancestor):
56
+ * - `--lc-app-shell-nav-width` — the nav column from 1024 px. Default
57
+ * `240px` (`248px` from 1440, `280px` from 1920).
58
+ * - `--lc-app-shell-bottom-clearance` — the space kept free for the bottom
59
+ * bar below 1024 px. Default: the bar's height + 40 px + the inset, at
60
+ * least `112px` + the inset.
61
+ * - `--lc-app-shell-bg` — the page colour behind everything (the sky).
62
+ * Default `var(--color-background)`.
63
+ * - `--lc-app-shell-bg-image` — a layer over the page colour. Default
64
+ * `var(--app-background-image, none)`. A tint, for example:
65
+ * `linear-gradient(to bottom, var(--color-land-1), var(--color-land-2), var(--color-land-3))`.
66
+ * The horizon's land still paints over it.
67
+ *
41
68
  * Needs `<meta name="viewport" content="width=device-width, initial-scale=1,
42
69
  * viewport-fit=cover">` for the safe-area insets. Breakpoints are fixed
43
70
  * (1024 px side navigation, 1440 / 1920 px widths), so the layout works
@@ -63,6 +90,18 @@ export declare class AppShellComponent {
63
90
  * @default false
64
91
  */
65
92
  readonly horizon: import("@angular/core").InputSignal<boolean>;
93
+ /**
94
+ * Where the side navigation sits from 1024 px. `'below-header'`: the header
95
+ * spans the full width and the nav starts below it. `'full-height'`: the nav
96
+ * runs from the top to the bottom of the viewport, with the header beside
97
+ * it. Below 1024 px both render the same. The DOM and tab order don't change
98
+ * (header, nav, page). CSS only, so it holds before JavaScript runs.
99
+ * `'full-height'` expects a brand block at the top of the rail
100
+ * (`lc-sidenav brandName` or `showLogo`, with a `logoSize` that matches the
101
+ * header's `size`, e.g. both `md`: 64 px) and the header's `showLogo` off.
102
+ * @default 'below-header'
103
+ */
104
+ readonly navPlacement: import("@angular/core").InputSignal<AppShellNavPlacement>;
66
105
  protected readonly shellClasses: import("@angular/core").Signal<string>;
67
106
  private readonly shell;
68
107
  private readonly barSlot;
@@ -74,8 +113,26 @@ export declare class AppShellComponent {
74
113
  "required": false;
75
114
  "isSignal": true;
76
115
  };
116
+ "navPlacement": {
117
+ "alias": "navPlacement";
118
+ "required": false;
119
+ "isSignal": true;
120
+ };
77
121
  }, {}, never, ["[shell-header]", "[shell-nav]", "*", "[shell-horizon-figure]", "[shell-footer]", "[shell-bottom-nav]"], true, never>;
78
122
  }
123
+ /**
124
+ * Horizontal padding of `lc-app-page` (3.15).
125
+ * - `default`: 24 · 32 · 48 · 56 · 72 · 96 px from 0 · 640 · 1024 · 1280 · 1440 · 1920 px.
126
+ * - `header`: `lc-header`'s padding (16 px up to 768 px, 24 px above), so the
127
+ * content lines up with the header title and the user menu.
128
+ */
129
+ export type AppPagePaddingX = 'default' | 'header';
130
+ /**
131
+ * Space above `lc-app-page`'s content (3.15).
132
+ * - `default`: 24 · 32 · 48 · 56 · 72 · 112 px by width.
133
+ * - `none` 0, `sm` 8 px, `md` 16 px at every width.
134
+ */
135
+ export type AppPagePaddingTop = 'default' | 'none' | 'sm' | 'md';
79
136
  /**
80
137
  * A page inside `lc-app-shell`: the `<main>` landmark with the page's content
81
138
  * centred at a reading width, and an optional right column docked to the
@@ -95,6 +152,22 @@ export declare class AppShellComponent {
95
152
  * `asideAriaLabel`.
96
153
  * - `busy` marks the page as loading: `aria-busy="true"` on `<main>` while a
97
154
  * skeleton stands in for the content (AS-12). No visual change.
155
+ * - `paddingX="header"` lines the content up with `lc-header` (3.15): its
156
+ * title and its user menu. Combine it with `contentMaxWidth="none"` (or a
157
+ * page narrower than the cap); centred content doesn't align.
158
+ * `paddingTop` sets the space above the content (`none`, `sm` 8 px, `md`
159
+ * 16 px), e.g. `md` with `lc-page-header paddingTop="none"` puts the `h1`
160
+ * 16 px below the header.
161
+ *
162
+ * CSS hooks (set them on `lc-app-page` or any ancestor; each wins over the
163
+ * inputs and holds one value at every width):
164
+ * - `--lc-app-page-padding-x`: the side padding (default: `paddingX`).
165
+ * Per breakpoint, set it inside your own media query:
166
+ * `lc-app-page { --lc-app-page-padding-x: 16px }` and
167
+ * `@media (min-width: 1024px) { lc-app-page { --lc-app-page-padding-x: 32px } }`.
168
+ * - `--lc-app-page-padding-top`: the space above the content (default: `paddingTop`).
169
+ * - `--lc-app-page-gap`: the space between the content's children (24 px, 40 px from 1024 px).
170
+ * - `--lc-app-page-aside-width`: the right column (360 px, 400 from 1440, 460 from 1920).
98
171
  *
99
172
  * @example
100
173
  * ```html
@@ -130,6 +203,23 @@ export declare class AppPageComponent {
130
203
  * @default false
131
204
  */
132
205
  readonly busy: import("@angular/core").InputSignal<boolean>;
206
+ /**
207
+ * Horizontal page padding. `'default'`: 24/32/48/56/72/96 px from
208
+ * 0/640/1024/1280/1440/1920 px. `'header'`: the same padding as `lc-header`
209
+ * (16 px up to 768 px, 24 px above, from `--lc-density-padding-md`/`-lg`),
210
+ * so the content lines up with the header title and the user menu. Combine
211
+ * it with `contentMaxWidth="none"` (or a page narrower than the cap).
212
+ * `--lc-app-page-padding-x` wins over both.
213
+ * @default 'default'
214
+ */
215
+ readonly paddingX: import("@angular/core").InputSignal<AppPagePaddingX>;
216
+ /**
217
+ * Space above the page content. `'default'`: 24/32/48/56/72/112 px by
218
+ * width. `'none'` 0, `'sm'` 8 px, `'md'` 16 px at every width.
219
+ * `--lc-app-page-padding-top` wins.
220
+ * @default 'default'
221
+ */
222
+ readonly paddingTop: import("@angular/core").InputSignal<AppPagePaddingTop>;
133
223
  /** The right column renders only when it has an accessible name. */
134
224
  protected readonly hasAside: import("@angular/core").Signal<boolean>;
135
225
  protected readonly pageClasses: import("@angular/core").Signal<string>;
@@ -160,5 +250,15 @@ export declare class AppPageComponent {
160
250
  "required": false;
161
251
  "isSignal": true;
162
252
  };
253
+ "paddingX": {
254
+ "alias": "paddingX";
255
+ "required": false;
256
+ "isSignal": true;
257
+ };
258
+ "paddingTop": {
259
+ "alias": "paddingTop";
260
+ "required": false;
261
+ "isSignal": true;
262
+ };
163
263
  }, {}, never, ["*", "[page-aside]"], true, never>;
164
264
  }