@lifecorner/angular-ui-kit 3.8.0 → 3.9.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 (30) hide show
  1. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +4 -4
  2. package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -1
  3. package/fesm2022/lifecorner-angular-ui-kit-button.mjs +39 -6
  4. package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
  5. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +2 -1
  6. package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
  7. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +2 -1
  8. package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
  9. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +2 -1
  10. package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
  11. package/fesm2022/lifecorner-angular-ui-kit-header.mjs +2 -1
  12. package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
  13. package/fesm2022/lifecorner-angular-ui-kit-list.mjs +2 -1
  14. package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
  15. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +2 -1
  16. package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
  17. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +2 -2
  18. package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -1
  19. package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs +2 -2
  20. package/fesm2022/lifecorner-angular-ui-kit-skeleton.mjs.map +1 -1
  21. package/fesm2022/lifecorner-angular-ui-kit-table.mjs +2 -1
  22. package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
  23. package/package.json +1 -1
  24. package/src/styles/_horizon.scss +46 -12
  25. package/src/styles/horizon.shell.spec.ts +67 -0
  26. package/src/styles/horizon.spec.ts +6 -4
  27. package/types/lifecorner-angular-ui-kit-app-shell.d.ts +15 -4
  28. package/types/lifecorner-angular-ui-kit-button.d.ts +30 -0
  29. package/types/lifecorner-angular-ui-kit-page-header.d.ts +6 -1
  30. package/types/lifecorner-angular-ui-kit-skeleton.d.ts +7 -1
@@ -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.8.0",
3
+ "version": "3.9.0",
4
4
  "description": "LifeCorner Design System – Angular UI component library",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,9 +26,11 @@
26
26
  *
27
27
  * Inputs (custom properties, set on the block or any ancestor):
28
28
  * --lc-horizon-land height of the land below the line
29
- * (default Today's: 112 px phone, 100 · 120 · 140 · 184 px
30
- * from 1024 · 1280 · 1440 · 1920; with the compact footer
31
- * on the land add its height, e.g. 136 px on the phone)
29
+ * (default Today's: 112 px phone, 72 · 80 · 96 · 128 px
30
+ * from 1024 · 1280 · 1440 · 1920 (3.9, LK-12); with the
31
+ * compact footer on the land add its height, e.g. 136 px
32
+ * on the phone. Inside lc-app-shell with a [shell-footer]
33
+ * the footer's height is added below it by the shell.)
32
34
  * --lc-horizon-sun-radius the sun's radius (58 px phone, 70 · 90 · 120 · 166 px)
33
35
  * --lc-horizon-sun-x the sun's centre from the block's left edge (72%)
34
36
  * --lc-horizon-figure-size the figure's size in .lc-horizon__figure
@@ -45,6 +47,9 @@
45
47
  * <lc-character class="lc-horizon__figure" pose="comforts" />
46
48
  * </div>
47
49
  *
50
+ * In lc-app-shell (3.9, AS-29) the attribute `shell-horizon-figure` alone does
51
+ * the same: the shell projects the element as a direct child of its horizon.
52
+ *
48
53
  * Colours: --color-background-low, --color-horizon-line, --color-land-1…3,
49
54
  * --color-sun-1…3, --color-sun-ring, --color-sun-halo (theme tokens).
50
55
  */
@@ -94,27 +99,28 @@
94
99
  linear-gradient(180deg, transparent, var(--color-background-low))
95
100
  0 0 / 100% calc(100% - var(--_lc-horizon-land)) no-repeat;
96
101
 
97
- // Desktop steps of Today's horizon (app-shell 12.2). A page sets its own
98
- // geometry through --lc-horizon-land / --lc-horizon-sun-radius.
102
+ // Desktop steps of Today's horizon (app-shell 12.2; the land 72 · 80 · 96 ·
103
+ // 128 px since 3.9, LK-12). A page sets its own geometry through
104
+ // --lc-horizon-land / --lc-horizon-sun-radius.
99
105
  @media (min-width: 1024px) {
100
- --_lc-horizon-land: var(--lc-horizon-land, 100px);
106
+ --_lc-horizon-land: var(--lc-horizon-land, 72px);
101
107
  --_lc-horizon-r: var(--lc-horizon-sun-radius, 70px);
102
108
  --_lc-horizon-fig: var(--lc-horizon-figure-size, 96px);
103
109
  --_lc-horizon-fig-gap: var(--lc-horizon-figure-gap, 24px);
104
110
  }
105
111
 
106
112
  @media (min-width: 1280px) {
107
- --_lc-horizon-land: var(--lc-horizon-land, 120px);
113
+ --_lc-horizon-land: var(--lc-horizon-land, 80px);
108
114
  --_lc-horizon-r: var(--lc-horizon-sun-radius, 90px);
109
115
  }
110
116
 
111
117
  @media (min-width: 1440px) {
112
- --_lc-horizon-land: var(--lc-horizon-land, 140px);
118
+ --_lc-horizon-land: var(--lc-horizon-land, 96px);
113
119
  --_lc-horizon-r: var(--lc-horizon-sun-radius, 120px);
114
120
  }
115
121
 
116
122
  @media (min-width: 1920px) {
117
- --_lc-horizon-land: var(--lc-horizon-land, 184px);
123
+ --_lc-horizon-land: var(--lc-horizon-land, 128px);
118
124
  --_lc-horizon-r: var(--lc-horizon-sun-radius, 166px);
119
125
  --_lc-horizon-fig: var(--lc-horizon-figure-size, 128px);
120
126
  }
@@ -135,7 +141,7 @@
135
141
  // Edu on the horizon line (3.8, G-4): left of the sun, the feet on the line.
136
142
  // Only a block WITH the figure gets the taller minimum; without it the block
137
143
  // renders exactly as before.
138
- .lc-horizon:has(> .lc-horizon__figure) {
144
+ @mixin figure-min-height {
139
145
  min-height: calc(var(--_lc-horizon-land) + max(var(--_lc-horizon-r) + 22px, var(--_lc-horizon-fig) + 8px));
140
146
  }
141
147
 
@@ -143,7 +149,7 @@
143
149
  // Its right edge sits the gap left of the sun's left edge; the box bottom lies
144
150
  // 12.5 % of its size below the line, where the standing poses' feet end
145
151
  // (y 87.5 of 100). Px, not rem: at 200 % text the figure keeps its size.
146
- .lc-horizon__figure {
152
+ @mixin figure {
147
153
  --lc-character-size: var(--_lc-horizon-fig);
148
154
 
149
155
  position: absolute;
@@ -160,8 +166,36 @@
160
166
  }
161
167
 
162
168
  // A <picture> or an element holding an inline <svg>.
163
- .lc-horizon__figure > :is(img, svg) {
169
+ @mixin figure-fill {
164
170
  display: block;
165
171
  width: 100%;
166
172
  height: 100%;
167
173
  }
174
+
175
+ .lc-horizon:has(> .lc-horizon__figure) {
176
+ @include figure-min-height;
177
+ }
178
+
179
+ .lc-horizon__figure {
180
+ @include figure;
181
+ }
182
+
183
+ .lc-horizon__figure > :is(img, svg) {
184
+ @include figure-fill;
185
+ }
186
+
187
+ // lc-app-shell's figure slot (3.9, AS-29): the attribute alone places the
188
+ // figure, with the same rules and the same specificity as .lc-horizon__figure
189
+ // (`:where` adds none). Here, not in the shell's own stylesheet: the slot's
190
+ // element belongs to the page's view, and `:has()` must see it.
191
+ .lc-horizon:has(> [shell-horizon-figure]) {
192
+ @include figure-min-height;
193
+ }
194
+
195
+ .lc-horizon > :where([shell-horizon-figure]) {
196
+ @include figure;
197
+ }
198
+
199
+ .lc-horizon > :where([shell-horizon-figure]) > :is(img, svg) {
200
+ @include figure-fill;
201
+ }
@@ -0,0 +1,67 @@
1
+ import { compile } from 'sass';
2
+ import { resolve } from 'path';
3
+
4
+ /**
5
+ * The horizon in 3.9 (request 006): the slimmer land defaults (LK-12, AC-1,
6
+ * AC-3, AC-8) and lc-app-shell's figure slot `[shell-horizon-figure]` (AS-29,
7
+ * AC-6, AC-7), read from the compiled CSS. The 3.8 figure rules are pinned by
8
+ * horizon.figure.spec.ts.
9
+ */
10
+ const css = '\n' + compile(resolve(__dirname, '_horizon.scss')).css;
11
+
12
+ /** The declarations of the top-level rule whose selector is exactly `selector` (compiled rules start a line). */
13
+ function rule(selector: string): string {
14
+ const start = css.indexOf(`\n${selector} {`);
15
+ expect(start).toBeGreaterThan(-1);
16
+ return css.slice(start + selector.length + 3, css.indexOf('}', start)).trim();
17
+ }
18
+
19
+ /** The declarations of `selector` inside `@media (forced-colors: active)`. */
20
+ function forcedColors(selector: string): string {
21
+ const match = new RegExp(`@media \\(forced-colors: active\\) \\{\\s*${selector.replace(/[.*+?^${}()|[\]\\>]/g, '\\$&')} \\{([^}]*)\\}`).exec(css);
22
+ expect(match).not.toBeNull();
23
+ return (match?.[1] ?? '').trim();
24
+ }
25
+
26
+ describe('.lc-horizon land defaults (LK-12)', () => {
27
+ it('AC-1: 112 px on the phone, 72 · 80 · 96 · 128 px from 1024 · 1280 · 1440 · 1920', () => {
28
+ const lands = [...css.matchAll(/--_lc-horizon-land: var\(--lc-horizon-land, (\d+)px\)/g)].map((m) => Number(m[1]));
29
+ expect(lands).toEqual([112, 72, 80, 96, 128]);
30
+ });
31
+
32
+ it('AC-3, AC-8: --lc-horizon-land wins at every width (every step is only its fallback)', () => {
33
+ const steps = [...css.matchAll(/--_lc-horizon-land:\s*([^;]+);/g)].map((m) => m[1]);
34
+ expect(steps).toHaveLength(5);
35
+ for (const step of steps) expect(step).toMatch(/^var\(--lc-horizon-land, \d+px\)$/);
36
+ });
37
+ });
38
+
39
+ describe('[shell-horizon-figure] (AS-29)', () => {
40
+ it('places the shell figure with exactly the rules of .lc-horizon__figure', () => {
41
+ expect(rule('.lc-horizon > :where([shell-horizon-figure])')).toBe(rule('.lc-horizon__figure'));
42
+ expect(rule('.lc-horizon > :where([shell-horizon-figure]) > :is(img, svg)')).toBe(rule('.lc-horizon__figure > :is(img, svg)'));
43
+ });
44
+
45
+ it('raises the minimum above the line with a figure child, as .lc-horizon__figure does', () => {
46
+ expect(rule('.lc-horizon:has(> [shell-horizon-figure])')).toBe(rule('.lc-horizon:has(> .lc-horizon__figure)'));
47
+ });
48
+
49
+ it('AC-7: sizes and places the figure, never a pointer target, hidden in forced colours', () => {
50
+ const figure = rule('.lc-horizon > :where([shell-horizon-figure])');
51
+ expect(figure).toMatch(/position:\s*absolute/);
52
+ expect(figure).toMatch(/--lc-character-size:\s*var\(--_lc-horizon-fig\)/);
53
+ expect(figure).toMatch(/pointer-events:\s*none/);
54
+ expect(forcedColors('.lc-horizon > :where([shell-horizon-figure])')).toBe(forcedColors('.lc-horizon__figure'));
55
+ });
56
+
57
+ it('keeps the specificity of .lc-horizon__figure: :where() adds none to the attribute', () => {
58
+ // (0,1,0) like `.lc-horizon__figure`, (0,2,0) for the :has() rule: every
59
+ // selector that names the attribute, in order (the third is in forced colours).
60
+ expect(css.match(/^[^{}\n]*shell-horizon-figure[^{}\n]*(?= \{)/gm)).toEqual([
61
+ '.lc-horizon:has(> [shell-horizon-figure])',
62
+ '.lc-horizon > :where([shell-horizon-figure])',
63
+ ' .lc-horizon > :where([shell-horizon-figure])',
64
+ '.lc-horizon > :where([shell-horizon-figure]) > :is(img, svg)',
65
+ ]);
66
+ });
67
+ });
@@ -49,11 +49,13 @@ describe('.lc-horizon (LK-1)', () => {
49
49
  expect(base).toMatch(/--_lc-horizon-x:\s*var\(--lc-horizon-sun-x, 72%\)/);
50
50
  });
51
51
 
52
+ // The land steps changed in 3.9 (LK-12, request 006): 100 · 120 · 140 · 184 px
53
+ // became 72 · 80 · 96 · 128 px; the sun radii are unchanged.
52
54
  it.each([
53
- [1024, '100px', '70px'],
54
- [1280, '120px', '90px'],
55
- [1440, '140px', '120px'],
56
- [1920, '184px', '166px'],
55
+ [1024, '72px', '70px'],
56
+ [1280, '80px', '90px'],
57
+ [1440, '96px', '120px'],
58
+ [1920, '128px', '166px'],
57
59
  ])('uses Today’s desktop geometry from %s px', (width, land, radius) => {
58
60
  const step = block(`@media (min-width: ${width}px) {\n .lc-horizon {`);
59
61
  expect(step).toContain(`var(--lc-horizon-land, ${land})`);