@life-cockpit/angular-ui-kit 1.11.4 → 1.11.5

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/README.md CHANGED
@@ -120,7 +120,7 @@ export class MyComponent {}
120
120
  | Skeleton | `lc-skeleton` | Loading placeholder |
121
121
  | Spinner | `lc-spinner` | Loading indicator |
122
122
  | Stepper | `lc-stepper` | Step-by-step progress |
123
- | Table | `lc-table` | Data table |
123
+ | Table | `lc-table` | Data table with sorting, filtering, pagination, formatter callbacks and custom cell templates |
124
124
  | Toggle Group | `lc-toggle-group` | Segmented toggle |
125
125
 
126
126
  ### Feedback
@@ -211,7 +211,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
211
211
 
212
212
  /* eslint-disable @typescript-eslint/member-ordering, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */
213
213
  /**
214
- * Icon component - Tabler Icons wrapper for displaying SVG icons
214
+ * Icon component - Heroicons wrapper for displaying SVG icons
215
215
  *
216
216
  * Features:
217
217
  * - Signal-based reactive API
@@ -219,7 +219,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
219
219
  * - Multiple size options (xs, sm, md, lg, xl)
220
220
  * - Custom color support (CSS colors, variables)
221
221
  * - Accessibility attributes (ARIA labels, decorative icons)
222
- * - Dynamic SVG loading from Tabler Icons
222
+ * - Dynamic SVG loading from Heroicons
223
223
  *
224
224
  * @example
225
225
  * ```html
@@ -246,7 +246,7 @@ class IconComponent {
246
246
  sanitizer = inject(DomSanitizer);
247
247
  http = inject(HttpClient);
248
248
  /**
249
- * Icon name from Tabler Icons library
249
+ * Icon name from Heroicons library
250
250
  * @example "user", "check", "arrow-right"
251
251
  */
252
252
  name = input('', ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
@@ -285,13 +285,13 @@ class IconComponent {
285
285
  */
286
286
  decorative = input(false, ...(ngDevMode ? [{ debugName: "decorative" }] : /* istanbul ignore next */ []));
287
287
  /**
288
- * SVG content loaded from Tabler Icons
288
+ * SVG content loaded from Heroicons
289
289
  * @internal
290
290
  */
291
291
  svgContent = signal('', ...(ngDevMode ? [{ debugName: "svgContent" }] : /* istanbul ignore next */ []));
292
292
  /**
293
- * Alias map for non-Tabler names (e.g. Material Design names)
294
- * Maps alternative names to their Tabler equivalents
293
+ * Alias map for non-Heroicon names (e.g. Material Design names)
294
+ * Maps alternative names to their Heroicon equivalents
295
295
  * @internal
296
296
  */
297
297
  iconAliasMap = {
@@ -478,8 +478,7 @@ class IconComponent {
478
478
  if (!rawName)
479
479
  return '';
480
480
  const iconName = this.iconAliasMap[rawName] ?? rawName;
481
- const tablerVariant = iconVariant === 'solid' ? 'filled' : 'outline';
482
- return `/tabler-icons/${tablerVariant}/${iconName}.svg`;
481
+ return `/heroicons/24/${iconVariant}/${iconName}.svg`;
483
482
  }, ...(ngDevMode ? [{ debugName: "iconPath" }] : /* istanbul ignore next */ []));
484
483
  /**
485
484
  * Computed size in pixels
@@ -519,7 +518,7 @@ class IconComponent {
519
518
  this.svgContent.set('');
520
519
  return;
521
520
  }
522
- // Resolve aliases (Material Design -> Tabler)
521
+ // Resolve aliases (Material Design Heroicons)
523
522
  const iconName = this.iconAliasMap[rawName] ?? rawName;
524
523
  // Try to use inline SVG first (avoids HTTP request)
525
524
  const inlineSvg = this.inlineSvgMap[iconName]?.[iconVariant];
@@ -1304,12 +1303,12 @@ class InputComponent {
1304
1303
  */
1305
1304
  helperText = input(...(ngDevMode ? [undefined, { debugName: "helperText" }] : /* istanbul ignore next */ []));
1306
1305
  /**
1307
- * Icon to display before input text (Tabler icon name)
1306
+ * Icon to display before input text (Heroicons name)
1308
1307
  * @example 'envelope'
1309
1308
  */
1310
1309
  iconBefore = input(...(ngDevMode ? [undefined, { debugName: "iconBefore" }] : /* istanbul ignore next */ []));
1311
1310
  /**
1312
- * Icon to display after input text (Tabler icon name)
1311
+ * Icon to display after input text (Heroicons name)
1313
1312
  * @example 'eye'
1314
1313
  */
1315
1314
  iconAfter = input(...(ngDevMode ? [undefined, { debugName: "iconAfter" }] : /* istanbul ignore next */ []));
@@ -6398,7 +6397,7 @@ class TabComponent {
6398
6397
  */
6399
6398
  disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
6400
6399
  /**
6401
- * Optional icon name (Tabler Icons)
6400
+ * Optional icon name (Heroicons)
6402
6401
  */
6403
6402
  icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
6404
6403
  /**
@@ -6853,7 +6852,7 @@ class ChipComponent {
6853
6852
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
6854
6853
  /** Size of the chip */
6855
6854
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
6856
- /** Icon name from Tabler Icons */
6855
+ /** Icon name from Heroicons */
6857
6856
  icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
6858
6857
  /** Whether the chip can be removed */
6859
6858
  removable = input(false, ...(ngDevMode ? [{ debugName: "removable" }] : /* istanbul ignore next */ []));
@@ -6940,7 +6939,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
6940
6939
  * - Variant styles (default, striped, bordered)
6941
6940
  * - Size presets (sm, md, lg)
6942
6941
  * - Hoverable row highlighting
6942
+ * - Per-column formatter callbacks for display values
6943
6943
  * - Custom cell templates via content projection
6944
+ * - Composed cells (e.g. avatar + badge + actions)
6944
6945
  * - Responsive horizontal scrolling
6945
6946
  * - Empty state text for no data
6946
6947
  * - Accessible with proper table semantics
@@ -6950,6 +6951,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
6950
6951
  * <lc-table [columns]="columns" [data]="data" variant="striped" [hoverable]="true"
6951
6952
  * (sort)="onSort($event)" (rowClick)="onRowClick($event)" />
6952
6953
  * ```
6954
+ *
6955
+ * @example
6956
+ * ```ts
6957
+ * columns: TableColumn[] = [
6958
+ * {
6959
+ * key: 'amount',
6960
+ * label: 'Amount',
6961
+ * formatter: (value) => new Intl.NumberFormat('de-DE', {
6962
+ * style: 'currency',
6963
+ * currency: 'EUR',
6964
+ * }).format(Number(value ?? 0)),
6965
+ * },
6966
+ * ];
6967
+ * ```
6953
6968
  */
6954
6969
  class TableComponent {
6955
6970
  /** Custom cell templates */
@@ -7126,6 +7141,12 @@ class TableComponent {
7126
7141
  getCellValue(row, columnKey) {
7127
7142
  return row[columnKey];
7128
7143
  }
7144
+ getFormattedCellValue(row, column, relativeRowIndex) {
7145
+ const value = this.getCellValue(row, column.key);
7146
+ if (!column.formatter)
7147
+ return value;
7148
+ return column.formatter(value, row, column, this.getAbsoluteIndex(relativeRowIndex));
7149
+ }
7129
7150
  getCellTemplate(columnKey) {
7130
7151
  return this.cellTemplates?.find((template) => template.columnKey() === columnKey);
7131
7152
  }
@@ -7241,11 +7262,11 @@ class TableComponent {
7241
7262
  return event.target.value;
7242
7263
  }
7243
7264
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7244
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", type: TableComponent, isStandalone: true, selector: "lc-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, paginate: { classPropertyName: "paginate", publicName: "paginate", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sort", rowClick: "rowClick", cellEdit: "cellEdit", selectionChange: "selectionChange" }, queries: [{ propertyName: "cellTemplates", predicate: TableCellDirective }], ngImport: i0, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" role=\"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 <input\n type=\"text\"\n class=\"lc-table__filter-input\"\n [placeholder]=\"'Filter ' + column.label\"\n [value]=\"getFilterValue(column.key)\"\n (input)=\"onFilterChange(column.key, $event)\"\n [attr.aria-label]=\"'Filter by ' + column.label\"\n />\n }\n </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 (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayData().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track $index; let i = $index) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(i)\"\n (click)=\"onRowClick(row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected($index)\"\n (change)=\"toggleRowSelect($index)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + ($index + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"column.cssClass || ''\"\n (dblclick)=\"editable() ? startEdit($index, column.key, getCellValue(row, column.key)) : null\"\n >\n @if (isEditing($index, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit($index, column.key)\"\n (keydown)=\"onEditKeydown($event, $index, column.key)\"\n autofocus\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getCellValue(row, column.key) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <select\n class=\"lc-table-pagination__size\"\n [value]=\"internalPageSize()\"\n (change)=\"onPageSizeChange($event)\"\n aria-label=\"Rows per page\"\n >\n @for (opt of pageSizeOptions(); track opt) {\n <option [value]=\"opt\">{{ opt }} / page</option>\n }\n </select>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</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 aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-background);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface);border-bottom:2px solid var(--color-border)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-50)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-100)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}[data-theme=dark] .lc-table,:root[data-theme=dark] .lc-table{background-color:var(--color-neutral-900)}[data-theme=dark] .lc-table thead,:root[data-theme=dark] .lc-table thead{background-color:var(--color-neutral-800);border-bottom-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th,:root[data-theme=dark] .lc-table thead tr th{color:var(--color-text-primary);background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table thead tr th.sortable:hover,:root[data-theme=dark] .lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th.sorted-asc,[data-theme=dark] .lc-table thead tr th.sorted-desc,:root[data-theme=dark] .lc-table thead tr th.sorted-asc,:root[data-theme=dark] .lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n),:root[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover,:root[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-700)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-xs);background-color:var(--color-background);color:var(--color-text-primary);transition:border-color .15s ease}.lc-table__filter-input:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb, 59, 130, 246),.15)}.lc-table__filter-input::placeholder{color:var(--color-text-secondary);opacity:.6}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-primary-50, rgba(59, 130, 246, .08))!important}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-background);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{appearance:none;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);background-color:var(--color-background);color:var(--color-text-primary);font-size:var(--typography-font-size-xs);cursor:pointer}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-100)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}[data-theme=dark] .lc-table__filter-input,:root[data-theme=dark] .lc-table__filter-input{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table__edit-input,:root[data-theme=dark] .lc-table__edit-input{background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table__row--selected,:root[data-theme=dark] .lc-table__row--selected{background-color:#3b82f61f!important}[data-theme=dark] .lc-table-pagination__size,[data-theme=dark] .lc-table-pagination__btn,:root[data-theme=dark] .lc-table-pagination__size,:root[data-theme=dark] .lc-table-pagination__btn{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-700)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7265
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", type: TableComponent, isStandalone: true, selector: "lc-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, paginate: { classPropertyName: "paginate", publicName: "paginate", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, filterable: { classPropertyName: "filterable", publicName: "filterable", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sort: "sort", rowClick: "rowClick", cellEdit: "cellEdit", selectionChange: "selectionChange" }, queries: [{ propertyName: "cellTemplates", predicate: TableCellDirective }], ngImport: i0, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" role=\"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 <input\n type=\"text\"\n class=\"lc-table__filter-input\"\n [placeholder]=\"'Filter ' + column.label\"\n [value]=\"getFilterValue(column.key)\"\n (input)=\"onFilterChange(column.key, $event)\"\n [attr.aria-label]=\"'Filter by ' + column.label\"\n />\n }\n </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 (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayData().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track $index; let i = $index) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(i)\"\n (click)=\"onRowClick(row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected($index)\"\n (change)=\"toggleRowSelect($index)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + ($index + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"column.cssClass || ''\"\n (dblclick)=\"editable() ? startEdit($index, column.key, getCellValue(row, column.key)) : null\"\n >\n @if (isEditing($index, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit($index, column.key)\"\n (keydown)=\"onEditKeydown($event, $index, column.key)\"\n autofocus\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, i) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <select\n class=\"lc-table-pagination__size\"\n [value]=\"internalPageSize()\"\n (change)=\"onPageSizeChange($event)\"\n aria-label=\"Rows per page\"\n >\n @for (opt of pageSizeOptions(); track opt) {\n <option [value]=\"opt\">{{ opt }} / page</option>\n }\n </select>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</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 aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-background);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface);border-bottom:2px solid var(--color-border)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-50)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-100)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}[data-theme=dark] .lc-table,:root[data-theme=dark] .lc-table{background-color:var(--color-neutral-900)}[data-theme=dark] .lc-table thead,:root[data-theme=dark] .lc-table thead{background-color:var(--color-neutral-800);border-bottom-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th,:root[data-theme=dark] .lc-table thead tr th{color:var(--color-text-primary);background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table thead tr th.sortable:hover,:root[data-theme=dark] .lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th.sorted-asc,[data-theme=dark] .lc-table thead tr th.sorted-desc,:root[data-theme=dark] .lc-table thead tr th.sorted-asc,:root[data-theme=dark] .lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n),:root[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover,:root[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-700)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-xs);background-color:var(--color-background);color:var(--color-text-primary);transition:border-color .15s ease}.lc-table__filter-input:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb, 59, 130, 246),.15)}.lc-table__filter-input::placeholder{color:var(--color-text-secondary);opacity:.6}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-primary-50, rgba(59, 130, 246, .08))!important}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-background);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{appearance:none;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);background-color:var(--color-background);color:var(--color-text-primary);font-size:var(--typography-font-size-xs);cursor:pointer}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-100)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}[data-theme=dark] .lc-table__filter-input,:root[data-theme=dark] .lc-table__filter-input{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table__edit-input,:root[data-theme=dark] .lc-table__edit-input{background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table__row--selected,:root[data-theme=dark] .lc-table__row--selected{background-color:#3b82f61f!important}[data-theme=dark] .lc-table-pagination__size,[data-theme=dark] .lc-table-pagination__btn,:root[data-theme=dark] .lc-table-pagination__size,:root[data-theme=dark] .lc-table-pagination__btn{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-700)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7245
7266
  }
7246
7267
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: TableComponent, decorators: [{
7247
7268
  type: Component,
7248
- args: [{ selector: 'lc-table', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" role=\"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 <input\n type=\"text\"\n class=\"lc-table__filter-input\"\n [placeholder]=\"'Filter ' + column.label\"\n [value]=\"getFilterValue(column.key)\"\n (input)=\"onFilterChange(column.key, $event)\"\n [attr.aria-label]=\"'Filter by ' + column.label\"\n />\n }\n </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 (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayData().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track $index; let i = $index) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(i)\"\n (click)=\"onRowClick(row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected($index)\"\n (change)=\"toggleRowSelect($index)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + ($index + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"column.cssClass || ''\"\n (dblclick)=\"editable() ? startEdit($index, column.key, getCellValue(row, column.key)) : null\"\n >\n @if (isEditing($index, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit($index, column.key)\"\n (keydown)=\"onEditKeydown($event, $index, column.key)\"\n autofocus\n />\n } @else if (hasCustomTemplate(column.key)) {\n <ng-container *ngTemplateOutlet=\"getCellTemplate(column.key)!.template; context: { $implicit: row }\"></ng-container>\n } @else {\n {{ getCellValue(row, column.key) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <select\n class=\"lc-table-pagination__size\"\n [value]=\"internalPageSize()\"\n (change)=\"onPageSizeChange($event)\"\n aria-label=\"Rows per page\"\n >\n @for (opt of pageSizeOptions(); track opt) {\n <option [value]=\"opt\">{{ opt }} / page</option>\n }\n </select>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</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 aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-background);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface);border-bottom:2px solid var(--color-border)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-50)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-100)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}[data-theme=dark] .lc-table,:root[data-theme=dark] .lc-table{background-color:var(--color-neutral-900)}[data-theme=dark] .lc-table thead,:root[data-theme=dark] .lc-table thead{background-color:var(--color-neutral-800);border-bottom-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th,:root[data-theme=dark] .lc-table thead tr th{color:var(--color-text-primary);background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table thead tr th.sortable:hover,:root[data-theme=dark] .lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th.sorted-asc,[data-theme=dark] .lc-table thead tr th.sorted-desc,:root[data-theme=dark] .lc-table thead tr th.sorted-asc,:root[data-theme=dark] .lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n),:root[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover,:root[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-700)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-xs);background-color:var(--color-background);color:var(--color-text-primary);transition:border-color .15s ease}.lc-table__filter-input:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb, 59, 130, 246),.15)}.lc-table__filter-input::placeholder{color:var(--color-text-secondary);opacity:.6}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-primary-50, rgba(59, 130, 246, .08))!important}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-background);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{appearance:none;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);background-color:var(--color-background);color:var(--color-text-primary);font-size:var(--typography-font-size-xs);cursor:pointer}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-100)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}[data-theme=dark] .lc-table__filter-input,:root[data-theme=dark] .lc-table__filter-input{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table__edit-input,:root[data-theme=dark] .lc-table__edit-input{background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table__row--selected,:root[data-theme=dark] .lc-table__row--selected{background-color:#3b82f61f!important}[data-theme=dark] .lc-table-pagination__size,[data-theme=dark] .lc-table-pagination__btn,:root[data-theme=dark] .lc-table-pagination__size,:root[data-theme=dark] .lc-table-pagination__btn{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-700)}\n"] }]
7269
+ args: [{ selector: 'lc-table', standalone: true, imports: [NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"wrapperClasses()\">\n <table [class]=\"tableClasses()\" role=\"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 <input\n type=\"text\"\n class=\"lc-table__filter-input\"\n [placeholder]=\"'Filter ' + column.label\"\n [value]=\"getFilterValue(column.key)\"\n (input)=\"onFilterChange(column.key, $event)\"\n [attr.aria-label]=\"'Filter by ' + column.label\"\n />\n }\n </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 (change)=\"toggleSelectAll()\"\n aria-label=\"Select all rows\"\n />\n </th>\n }\n @for (column of columns(); track column.key) {\n <th\n scope=\"col\"\n [class]=\"getHeaderClasses(column) + (column.cssClass ? ' ' + column.cssClass : '')\"\n [attr.aria-sort]=\"getAriaSort(column.key)\"\n [style.width]=\"column.width\"\n [title]=\"column.tooltip || ''\"\n (click)=\"handleSort(column.key)\">\n {{ column.label }}\n @if (column.sortable && getSortState(column.key)) {\n <span class=\"sort-indicator\" [attr.aria-label]=\"getSortState(column.key) === 'asc' ? 'sorted ascending' : 'sorted descending'\">\n @if (getSortState(column.key) === 'asc') {\n \u2191\n } @else {\n \u2193\n }\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (displayData().length === 0) {\n <tr>\n <td [attr.colspan]=\"columns().length + (selectable() ? 1 : 0)\" class=\"lc-table__empty\">\n {{ emptyText() }}\n </td>\n </tr>\n } @else {\n @for (row of displayData(); track $index; let i = $index) {\n <tr\n [class.lc-table__row--selected]=\"selectable() && isRowSelected(i)\"\n (click)=\"onRowClick(row)\"\n >\n @if (selectable()) {\n <td class=\"lc-table__select-cell\">\n <input\n type=\"checkbox\"\n class=\"lc-table__checkbox\"\n [checked]=\"isRowSelected($index)\"\n (change)=\"toggleRowSelect($index)\"\n (click)=\"$event.stopPropagation()\"\n [attr.aria-label]=\"'Select row ' + ($index + 1)\"\n />\n </td>\n }\n @for (column of columns(); track column.key) {\n <td\n [class]=\"column.cssClass || ''\"\n (dblclick)=\"editable() ? startEdit($index, column.key, getCellValue(row, column.key)) : null\"\n >\n @if (isEditing($index, column.key)) {\n <input\n type=\"text\"\n class=\"lc-table__edit-input\"\n [value]=\"editValue()\"\n (input)=\"editValue.set(getInputValue($event))\"\n (blur)=\"commitEdit($index, column.key)\"\n (keydown)=\"onEditKeydown($event, $index, column.key)\"\n autofocus\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, i) }}\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n\n<!-- Pagination -->\n@if (paginate()) {\n <div class=\"lc-table-pagination\">\n <div class=\"lc-table-pagination__info\">\n {{ paginationStart }}\u2013{{ paginationEnd }} of {{ totalRows() }}\n </div>\n <div class=\"lc-table-pagination__controls\">\n <select\n class=\"lc-table-pagination__size\"\n [value]=\"internalPageSize()\"\n (change)=\"onPageSizeChange($event)\"\n aria-label=\"Rows per page\"\n >\n @for (opt of pageSizeOptions(); track opt) {\n <option [value]=\"opt\">{{ opt }} / page</option>\n }\n </select>\n <button\n type=\"button\"\n class=\"lc-table-pagination__btn\"\n [disabled]=\"currentPage() === 0\"\n (click)=\"goToPage(currentPage() - 1)\"\n aria-label=\"Previous page\"\n >\u2039</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 aria-label=\"Next page\"\n >\u203A</button>\n </div>\n </div>\n}\n", styles: [".lc-table-wrapper{width:100%}.lc-table-wrapper--responsive{overflow-x:auto;-webkit-overflow-scrolling:touch}@media(max-width:768px){.lc-table-wrapper--responsive::-webkit-scrollbar{height:8px}.lc-table-wrapper--responsive::-webkit-scrollbar-thumb{background-color:var(--color-border);border-radius:var(--border-radius-sm)}}.lc-table{width:100%;border-collapse:collapse;border-spacing:0;background-color:var(--color-background);color:var(--color-text-primary);font-family:var(--typography-font-family)}.lc-table thead{background-color:var(--color-surface);border-bottom:2px solid var(--color-border)}.lc-table thead tr th{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));text-align:left;font-weight:var(--typography-font-weight-semibold);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.lc-table thead tr th.sortable{cursor:pointer;position:relative;padding-right:var(--spacing-8);transition:background-color .2s ease}.lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table thead tr th.sortable .sort-indicator{position:absolute;right:var(--spacing-3);top:50%;transform:translateY(-50%);font-size:var(--typography-font-size-xs);color:var(--color-primary)}.lc-table thead tr th.sorted-asc,.lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-100);color:var(--color-text-primary)}.lc-table tbody tr{border-bottom:1px solid var(--color-divider)}.lc-table tbody tr:last-child{border-bottom:none}.lc-table tbody tr td{padding:var(--lc-density-padding-sm, var(--spacing-3)) var(--lc-density-padding-md, var(--spacing-4));font-size:var(--typography-font-size-sm);color:var(--color-text-primary)}.lc-table__empty{text-align:center;padding:var(--spacing-8) var(--spacing-4)!important;color:var(--color-text-secondary);font-style:italic}.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-50)}.lc-table--bordered{border:1px solid var(--color-border)}.lc-table--bordered thead tr th,.lc-table--bordered tbody tr td{border-right:1px solid var(--color-divider)}.lc-table--bordered thead tr th:last-child,.lc-table--bordered tbody tr td:last-child{border-right:none}.lc-table--bordered tbody tr{border-bottom:1px solid var(--color-border)}.lc-table--hoverable tbody tr{transition:background-color .15s ease;cursor:pointer}.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-100)}.lc-table--sm thead tr th,.lc-table--sm tbody tr td{padding:var(--lc-density-padding-xs, var(--spacing-2)) var(--lc-density-padding-sm, var(--spacing-3));font-size:var(--typography-font-size-xs)}.lc-table--lg thead tr th,.lc-table--lg tbody tr td{padding:var(--lc-density-padding-md, var(--spacing-4)) var(--spacing-5);font-size:var(--typography-font-size-base)}[data-theme=dark] .lc-table,:root[data-theme=dark] .lc-table{background-color:var(--color-neutral-900)}[data-theme=dark] .lc-table thead,:root[data-theme=dark] .lc-table thead{background-color:var(--color-neutral-800);border-bottom-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th,:root[data-theme=dark] .lc-table thead tr th{color:var(--color-text-primary);background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table thead tr th.sortable:hover,:root[data-theme=dark] .lc-table thead tr th.sortable:hover{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table thead tr th.sorted-asc,[data-theme=dark] .lc-table thead tr th.sorted-desc,:root[data-theme=dark] .lc-table thead tr th.sorted-asc,:root[data-theme=dark] .lc-table thead tr th.sorted-desc{background-color:var(--color-neutral-700)}[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n),:root[data-theme=dark] .lc-table.lc-table--striped tbody tr:nth-child(2n){background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover,:root[data-theme=dark] .lc-table.lc-table--hoverable tbody tr:hover{background-color:var(--color-neutral-700)}.lc-table__filter-row th{padding:var(--spacing-2) var(--spacing-4)!important;background-color:var(--color-background)!important;border-bottom:1px solid var(--color-divider)!important}.lc-table__filter-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-xs);background-color:var(--color-background);color:var(--color-text-primary);transition:border-color .15s ease}.lc-table__filter-input:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 2px rgba(var(--color-primary-rgb, 59, 130, 246),.15)}.lc-table__filter-input::placeholder{color:var(--color-text-secondary);opacity:.6}.lc-table__select-cell{width:40px;text-align:center!important;padding:var(--spacing-2)!important}.lc-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--color-primary)}.lc-table__row--selected{background-color:var(--color-primary-50, rgba(59, 130, 246, .08))!important}.lc-table__edit-input{width:100%;padding:var(--spacing-1) var(--spacing-2);border:2px solid var(--color-primary);border-radius:var(--border-radius-sm);font-size:inherit;background-color:var(--color-background);color:var(--color-text-primary);outline:none}.lc-table-pagination{display:flex;align-items:center;justify-content:space-between;padding:var(--spacing-3) var(--spacing-1);font-size:var(--typography-font-size-sm);color:var(--color-text-secondary)}.lc-table-pagination__info{white-space:nowrap}.lc-table-pagination__controls{display:flex;align-items:center;gap:var(--spacing-2)}.lc-table-pagination__size{appearance:none;padding:var(--spacing-1) var(--spacing-2);border:1px solid var(--color-border);border-radius:var(--border-radius-sm);background-color:var(--color-background);color:var(--color-text-primary);font-size:var(--typography-font-size-xs);cursor:pointer}.lc-table-pagination__btn{appearance:none;border:1px solid var(--color-border);background-color:var(--color-surface);color:var(--color-text-primary);width:28px;height:28px;display:flex;align-items:center;justify-content:center;border-radius:var(--border-radius-sm);font-size:var(--typography-font-size-base);cursor:pointer;transition:background-color .15s ease}.lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-100)}.lc-table-pagination__btn:disabled{opacity:.4;cursor:not-allowed}.lc-table-pagination__page{white-space:nowrap;min-width:60px;text-align:center}@media(max-width:640px){.lc-table-wrapper--stack .lc-table thead{display:none}.lc-table-wrapper--stack .lc-table tbody tr{display:block;margin-bottom:var(--spacing-4);border:1px solid var(--color-border);border-radius:var(--border-radius-md)}.lc-table-wrapper--stack .lc-table tbody tr td{display:block;text-align:right;padding:var(--spacing-2) var(--spacing-4);border-bottom:1px solid var(--color-divider)}.lc-table-wrapper--stack .lc-table tbody tr td:last-child{border-bottom:none}.lc-table-wrapper--stack .lc-table tbody tr td:before{content:attr(data-label);float:left;font-weight:var(--typography-font-weight-semibold);color:var(--color-text-secondary)}}[data-theme=dark] .lc-table__filter-input,:root[data-theme=dark] .lc-table__filter-input{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table__edit-input,:root[data-theme=dark] .lc-table__edit-input{background-color:var(--color-neutral-800)}[data-theme=dark] .lc-table__row--selected,:root[data-theme=dark] .lc-table__row--selected{background-color:#3b82f61f!important}[data-theme=dark] .lc-table-pagination__size,[data-theme=dark] .lc-table-pagination__btn,:root[data-theme=dark] .lc-table-pagination__size,:root[data-theme=dark] .lc-table-pagination__btn{background-color:var(--color-neutral-800);border-color:var(--color-neutral-700)}[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__size:hover:not(:disabled),:root[data-theme=dark] .lc-table-pagination__btn:hover:not(:disabled){background-color:var(--color-neutral-700)}\n"] }]
7249
7270
  }], propDecorators: { cellTemplates: [{
7250
7271
  type: ContentChildren,
7251
7272
  args: [TableCellDirective]
@@ -7256,7 +7277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
7256
7277
  *
7257
7278
  * Features:
7258
7279
  * - Consistent label-value layout for read-only data
7259
- * - Optional leading icon from Tabler Icons
7280
+ * - Optional leading icon from Heroicons
7260
7281
  * - Compact mode for dense layouts
7261
7282
  * - Content projection for custom value rendering
7262
7283
  * - Configurable icon size (xs, sm, md)
@@ -7277,7 +7298,7 @@ class FieldGroupComponent {
7277
7298
  */
7278
7299
  value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : /* istanbul ignore next */ []));
7279
7300
  /**
7280
- * Optional icon name from Tabler Icons
7301
+ * Optional icon name from Heroicons
7281
7302
  */
7282
7303
  icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
7283
7304
  /**
@@ -7578,7 +7599,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImpo
7578
7599
  *
7579
7600
  * Features:
7580
7601
  * - Compact (sm) and page-level (md, lg) size modes
7581
- * - Optional icon from Tabler Icons library
7602
+ * - Optional icon from Heroicons library
7582
7603
  * - Heading and description text
7583
7604
  * - Action slot for projected CTA buttons
7584
7605
  * - Centered layout with visual hierarchy
@@ -7603,7 +7624,7 @@ class EmptyStateComponent {
7603
7624
  */
7604
7625
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
7605
7626
  /**
7606
- * Tabler icon name to display above the heading
7627
+ * Heroicon name to display above the heading
7607
7628
  */
7608
7629
  icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : /* istanbul ignore next */ []));
7609
7630
  /**
@@ -8732,7 +8753,7 @@ class StatTrendComponent {
8732
8753
  sparklineData = input([], ...(ngDevMode ? [{ debugName: "sparklineData" }] : /* istanbul ignore next */ []));
8733
8754
  /** Color of the sparkline. Auto-matched to trend direction if not set. */
8734
8755
  sparklineColor = input(undefined, ...(ngDevMode ? [{ debugName: "sparklineColor" }] : /* istanbul ignore next */ []));
8735
- /** Optional icon name (Tabler icon). */
8756
+ /** Optional icon name (Heroicon). */
8736
8757
  icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
8737
8758
  resolvedDirection = computed(() => {
8738
8759
  const dir = this.direction();