@lifecorner/angular-ui-kit 3.14.0 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs +36 -2
- package/fesm2022/lifecorner-angular-ui-kit-app-shell.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +2 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +23 -5
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs +39 -6
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-choice-prompt.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-confirm-dialog.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-copy-field.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs +42 -5
- package/fesm2022/lifecorner-angular-ui-kit-empty-state.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +21 -3
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-list.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-next-step-card.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs +20 -3
- package/fesm2022/lifecorner-angular-ui-kit-page-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav-placeholder.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-sidenav-placeholder.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-table.mjs.map +1 -1
- package/package.json +1 -1
- package/src/styles/theme-contrast.spec.ts +52 -0
- package/types/lifecorner-angular-ui-kit-app-shell.d.ts +56 -0
- package/types/lifecorner-angular-ui-kit-avatar.d.ts +24 -0
- package/types/lifecorner-angular-ui-kit-button.d.ts +31 -0
- package/types/lifecorner-angular-ui-kit-empty-state.d.ts +38 -0
- package/types/lifecorner-angular-ui-kit-header.d.ts +15 -2
- package/types/lifecorner-angular-ui-kit-page-header.d.ts +20 -0
- package/types/lifecorner-angular-ui-kit-sidenav-placeholder.d.ts +4 -2
- package/types/lifecorner-angular-ui-kit-sidenav.d.ts +5 -2
|
@@ -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
|
@@ -228,3 +228,55 @@ describe('Theme contrast (WCAG 2.2 AA)', () => {
|
|
|
228
228
|
}
|
|
229
229
|
});
|
|
230
230
|
});
|
|
231
|
+
|
|
232
|
+
// Request 020: the pairings the new component options read, computed from the
|
|
233
|
+
// theme tokens (no new token). The outline tint is the button stylesheet's own.
|
|
234
|
+
describe('Component pairings of 3.15 (request 020)', () => {
|
|
235
|
+
const buttonCss = compile(resolve(__dirname, '../lib/button/button.component.scss')).css;
|
|
236
|
+
const tint = parse(buttonCss.match(/\n\.btn-outline \{[^}]*background-color: (rgba\([^)]+\))/)?.[1] ?? '');
|
|
237
|
+
const pages = ['--color-background', '--color-land-1', '--color-land-3', '--color-surface'];
|
|
238
|
+
|
|
239
|
+
/** Design 020 §5, per palette: [light, dark]. */
|
|
240
|
+
const expected = {
|
|
241
|
+
emptyStateIcon: [7.85, 9.68],
|
|
242
|
+
avatarGlyph: [7.0, 6.1],
|
|
243
|
+
outlineActiveText: [6.71, 6.71],
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
describe.each(palettes.map(([name, tokens], i) => [name, tokens, i] as const))('%s palette', (_palette, tokens, i) => {
|
|
247
|
+
/** A token's colour, translucent ones composited over `base`. */
|
|
248
|
+
const solid = (name: string, base = '--color-background') => over(color(tokens, name), color(tokens, base));
|
|
249
|
+
|
|
250
|
+
it('AC-8: the primary empty-state icon on its circle (--color-primary-700 on -100)', () => {
|
|
251
|
+
const r = ratio(solid('--color-primary-700'), solid('--color-primary-100'));
|
|
252
|
+
expect(r).toBeCloseTo(expected.emptyStateIcon[i], 2);
|
|
253
|
+
expect(r).toBeGreaterThanOrEqual(3);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
it('AC-12: the avatar person glyph on its disc (--color-neutral-700 on -300)', () => {
|
|
257
|
+
const r = ratio(solid('--color-neutral-700'), solid('--color-neutral-300'));
|
|
258
|
+
expect(r).toBeCloseTo(expected.avatarGlyph[i], 2);
|
|
259
|
+
expect(r).toBeGreaterThanOrEqual(3);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it.each(pages)('AC-13: outline primary at rest on %s: text 4.5:1 on the tint, border 3:1', (page) => {
|
|
263
|
+
const ground = solid(page);
|
|
264
|
+
expect(ratio(solid('--color-primary-700'), over(tint, ground))).toBeGreaterThanOrEqual(4.5);
|
|
265
|
+
expect(ratio(solid('--color-primary-600'), ground)).toBeGreaterThanOrEqual(3);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it.each(pages)('AC-13: outline primary on hover over %s: text 4.5:1 on --color-surface-selected, border 3:1', (page) => {
|
|
269
|
+
const fill = solid('--color-surface-selected', page);
|
|
270
|
+
expect(ratio(solid('--color-primary-700'), fill)).toBeGreaterThanOrEqual(4.5);
|
|
271
|
+
expect(ratio(solid('--color-primary-600'), solid(page))).toBeGreaterThanOrEqual(3);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
it('AC-13: outline primary active: text on --color-primary-200 and the border beside it', () => {
|
|
275
|
+
const fill = solid('--color-primary-200');
|
|
276
|
+
const text = ratio(solid('--color-primary-700'), fill);
|
|
277
|
+
expect(text).toBeCloseTo(expected.outlineActiveText[i], 2);
|
|
278
|
+
expect(text).toBeGreaterThanOrEqual(4.5);
|
|
279
|
+
expect(ratio(solid('--color-primary-600'), fill)).toBeGreaterThanOrEqual(3);
|
|
280
|
+
});
|
|
281
|
+
});
|
|
282
|
+
});
|
|
@@ -120,6 +120,19 @@ export declare class AppShellComponent {
|
|
|
120
120
|
};
|
|
121
121
|
}, {}, never, ["[shell-header]", "[shell-nav]", "*", "[shell-horizon-figure]", "[shell-footer]", "[shell-bottom-nav]"], true, never>;
|
|
122
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Horizontal padding of `lc-app-page` (3.15).
|
|
125
|
+
* - `default`: 24 · 32 · 48 · 56 · 72 · 96 px from 0 · 640 · 1024 · 1280 · 1440 · 1920 px.
|
|
126
|
+
* - `header`: `lc-header`'s padding (16 px up to 768 px, 24 px above), so the
|
|
127
|
+
* content lines up with the header title and the user menu.
|
|
128
|
+
*/
|
|
129
|
+
export type AppPagePaddingX = 'default' | 'header';
|
|
130
|
+
/**
|
|
131
|
+
* Space above `lc-app-page`'s content (3.15).
|
|
132
|
+
* - `default`: 24 · 32 · 48 · 56 · 72 · 112 px by width.
|
|
133
|
+
* - `none` 0, `sm` 8 px, `md` 16 px at every width.
|
|
134
|
+
*/
|
|
135
|
+
export type AppPagePaddingTop = 'default' | 'none' | 'sm' | 'md';
|
|
123
136
|
/**
|
|
124
137
|
* A page inside `lc-app-shell`: the `<main>` landmark with the page's content
|
|
125
138
|
* centred at a reading width, and an optional right column docked to the
|
|
@@ -139,6 +152,22 @@ export declare class AppShellComponent {
|
|
|
139
152
|
* `asideAriaLabel`.
|
|
140
153
|
* - `busy` marks the page as loading: `aria-busy="true"` on `<main>` while a
|
|
141
154
|
* skeleton stands in for the content (AS-12). No visual change.
|
|
155
|
+
* - `paddingX="header"` lines the content up with `lc-header` (3.15): its
|
|
156
|
+
* title and its user menu. Combine it with `contentMaxWidth="none"` (or a
|
|
157
|
+
* page narrower than the cap); centred content doesn't align.
|
|
158
|
+
* `paddingTop` sets the space above the content (`none`, `sm` 8 px, `md`
|
|
159
|
+
* 16 px), e.g. `md` with `lc-page-header paddingTop="none"` puts the `h1`
|
|
160
|
+
* 16 px below the header.
|
|
161
|
+
*
|
|
162
|
+
* CSS hooks (set them on `lc-app-page` or any ancestor; each wins over the
|
|
163
|
+
* inputs and holds one value at every width):
|
|
164
|
+
* - `--lc-app-page-padding-x`: the side padding (default: `paddingX`).
|
|
165
|
+
* Per breakpoint, set it inside your own media query:
|
|
166
|
+
* `lc-app-page { --lc-app-page-padding-x: 16px }` and
|
|
167
|
+
* `@media (min-width: 1024px) { lc-app-page { --lc-app-page-padding-x: 32px } }`.
|
|
168
|
+
* - `--lc-app-page-padding-top`: the space above the content (default: `paddingTop`).
|
|
169
|
+
* - `--lc-app-page-gap`: the space between the content's children (24 px, 40 px from 1024 px).
|
|
170
|
+
* - `--lc-app-page-aside-width`: the right column (360 px, 400 from 1440, 460 from 1920).
|
|
142
171
|
*
|
|
143
172
|
* @example
|
|
144
173
|
* ```html
|
|
@@ -174,6 +203,23 @@ export declare class AppPageComponent {
|
|
|
174
203
|
* @default false
|
|
175
204
|
*/
|
|
176
205
|
readonly busy: import("@angular/core").InputSignal<boolean>;
|
|
206
|
+
/**
|
|
207
|
+
* Horizontal page padding. `'default'`: 24/32/48/56/72/96 px from
|
|
208
|
+
* 0/640/1024/1280/1440/1920 px. `'header'`: the same padding as `lc-header`
|
|
209
|
+
* (16 px up to 768 px, 24 px above, from `--lc-density-padding-md`/`-lg`),
|
|
210
|
+
* so the content lines up with the header title and the user menu. Combine
|
|
211
|
+
* it with `contentMaxWidth="none"` (or a page narrower than the cap).
|
|
212
|
+
* `--lc-app-page-padding-x` wins over both.
|
|
213
|
+
* @default 'default'
|
|
214
|
+
*/
|
|
215
|
+
readonly paddingX: import("@angular/core").InputSignal<AppPagePaddingX>;
|
|
216
|
+
/**
|
|
217
|
+
* Space above the page content. `'default'`: 24/32/48/56/72/112 px by
|
|
218
|
+
* width. `'none'` 0, `'sm'` 8 px, `'md'` 16 px at every width.
|
|
219
|
+
* `--lc-app-page-padding-top` wins.
|
|
220
|
+
* @default 'default'
|
|
221
|
+
*/
|
|
222
|
+
readonly paddingTop: import("@angular/core").InputSignal<AppPagePaddingTop>;
|
|
177
223
|
/** The right column renders only when it has an accessible name. */
|
|
178
224
|
protected readonly hasAside: import("@angular/core").Signal<boolean>;
|
|
179
225
|
protected readonly pageClasses: import("@angular/core").Signal<string>;
|
|
@@ -204,5 +250,15 @@ export declare class AppPageComponent {
|
|
|
204
250
|
"required": false;
|
|
205
251
|
"isSignal": true;
|
|
206
252
|
};
|
|
253
|
+
"paddingX": {
|
|
254
|
+
"alias": "paddingX";
|
|
255
|
+
"required": false;
|
|
256
|
+
"isSignal": true;
|
|
257
|
+
};
|
|
258
|
+
"paddingTop": {
|
|
259
|
+
"alias": "paddingTop";
|
|
260
|
+
"required": false;
|
|
261
|
+
"isSignal": true;
|
|
262
|
+
};
|
|
207
263
|
}, {}, never, ["*", "[page-aside]"], true, never>;
|
|
208
264
|
}
|
|
@@ -16,6 +16,13 @@ export type AvatarLoading = 'eager' | 'lazy';
|
|
|
16
16
|
* the name or initials beside the colour — colour is never the only cue.
|
|
17
17
|
*/
|
|
18
18
|
export type AvatarColor = 'default' | 'member-1' | 'member-2' | 'member-3' | 'member-4' | 'member-5' | 'member-6';
|
|
19
|
+
/**
|
|
20
|
+
* What `lc-avatar` shows with no image and no name (3.15).
|
|
21
|
+
* - `initials`: "?"
|
|
22
|
+
* - `person`: a person symbol on a neutral disc (`--color-neutral-300`, glyph
|
|
23
|
+
* `--color-neutral-700`; `color` is ignored while it shows)
|
|
24
|
+
*/
|
|
25
|
+
export type AvatarFallback = 'initials' | 'person';
|
|
19
26
|
/** The six member colours in their order (`AvatarColor` without `default`). */
|
|
20
27
|
export declare const AVATAR_MEMBER_COLORS: readonly AvatarColor[];
|
|
21
28
|
/**
|
|
@@ -37,6 +44,8 @@ export declare function ɵavatarInitials(name: string | undefined): string;
|
|
|
37
44
|
* - `ring`: a gap in the page colour around the avatar, for stacks and for
|
|
38
45
|
* avatars on images or tints
|
|
39
46
|
* - Accessible with alt text support
|
|
47
|
+
* - `fallback="person"`: a person symbol on a neutral disc instead of "?"
|
|
48
|
+
* when there is no name (3.15)
|
|
40
49
|
*
|
|
41
50
|
* @example
|
|
42
51
|
* ```html
|
|
@@ -86,10 +95,20 @@ export declare class AvatarComponent {
|
|
|
86
95
|
* button labelled "Menu for Tom Ek".
|
|
87
96
|
*/
|
|
88
97
|
decorative: import("@angular/core").InputSignal<boolean>;
|
|
98
|
+
/**
|
|
99
|
+
* What shows with no image and no name: `'initials'` shows "?"; `'person'`
|
|
100
|
+
* shows a person symbol on a neutral disc (`color` is ignored while it
|
|
101
|
+
* shows). With a `name`, both show the initials. The accessible name stays
|
|
102
|
+
* `alt`, then `name`, then "Avatar".
|
|
103
|
+
* @default 'initials'
|
|
104
|
+
*/
|
|
105
|
+
fallback: import("@angular/core").InputSignal<AvatarFallback>;
|
|
89
106
|
/**
|
|
90
107
|
* Computed initials from name
|
|
91
108
|
*/
|
|
92
109
|
initials: import("@angular/core").Signal<string>;
|
|
110
|
+
/** The person symbol: `fallback="person"`, no image (or a broken one) and no name. */
|
|
111
|
+
protected readonly showPerson: import("@angular/core").Signal<boolean>;
|
|
93
112
|
/**
|
|
94
113
|
* Computed CSS classes for the avatar
|
|
95
114
|
*/
|
|
@@ -160,5 +179,10 @@ export declare class AvatarComponent {
|
|
|
160
179
|
"required": false;
|
|
161
180
|
"isSignal": true;
|
|
162
181
|
};
|
|
182
|
+
"fallback": {
|
|
183
|
+
"alias": "fallback";
|
|
184
|
+
"required": false;
|
|
185
|
+
"isSignal": true;
|
|
186
|
+
};
|
|
163
187
|
}, {}, never, never, true, never>;
|
|
164
188
|
}
|