@neural-ui/core 1.7.1 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/bottom-sheet/package.json +4 -0
  2. package/confirm-popup/package.json +4 -0
  3. package/data-view/package.json +4 -0
  4. package/fesm2022/neural-ui-core-alert.mjs +48 -21
  5. package/fesm2022/neural-ui-core-alert.mjs.map +1 -1
  6. package/fesm2022/neural-ui-core-autocomplete.mjs +153 -71
  7. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -1
  8. package/fesm2022/neural-ui-core-block-ui.mjs +2 -2
  9. package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -1
  10. package/fesm2022/neural-ui-core-bottom-sheet.mjs +121 -0
  11. package/fesm2022/neural-ui-core-bottom-sheet.mjs.map +1 -0
  12. package/fesm2022/neural-ui-core-breadcrumb.mjs +2 -2
  13. package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -1
  14. package/fesm2022/neural-ui-core-button.mjs +2 -2
  15. package/fesm2022/neural-ui-core-button.mjs.map +1 -1
  16. package/fesm2022/neural-ui-core-calendar.mjs +2 -2
  17. package/fesm2022/neural-ui-core-calendar.mjs.map +1 -1
  18. package/fesm2022/neural-ui-core-checkbox.mjs +69 -39
  19. package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -1
  20. package/fesm2022/neural-ui-core-chip.mjs +2 -2
  21. package/fesm2022/neural-ui-core-chip.mjs.map +1 -1
  22. package/fesm2022/neural-ui-core-code-block.mjs +2 -2
  23. package/fesm2022/neural-ui-core-code-block.mjs.map +1 -1
  24. package/fesm2022/neural-ui-core-confirm-popup.mjs +105 -0
  25. package/fesm2022/neural-ui-core-confirm-popup.mjs.map +1 -0
  26. package/fesm2022/neural-ui-core-dashboard-grid.mjs +9 -3
  27. package/fesm2022/neural-ui-core-dashboard-grid.mjs.map +1 -1
  28. package/fesm2022/neural-ui-core-data-view.mjs +386 -0
  29. package/fesm2022/neural-ui-core-data-view.mjs.map +1 -0
  30. package/fesm2022/neural-ui-core-date-input.mjs +185 -10
  31. package/fesm2022/neural-ui-core-date-input.mjs.map +1 -1
  32. package/fesm2022/neural-ui-core-empty-state.mjs +19 -5
  33. package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -1
  34. package/fesm2022/neural-ui-core-form-field.mjs +81 -0
  35. package/fesm2022/neural-ui-core-form-field.mjs.map +1 -0
  36. package/fesm2022/neural-ui-core-inline-editor.mjs +428 -0
  37. package/fesm2022/neural-ui-core-inline-editor.mjs.map +1 -0
  38. package/fesm2022/neural-ui-core-input-mask.mjs +110 -0
  39. package/fesm2022/neural-ui-core-input-mask.mjs.map +1 -0
  40. package/fesm2022/neural-ui-core-input.mjs +2 -2
  41. package/fesm2022/neural-ui-core-input.mjs.map +1 -1
  42. package/fesm2022/neural-ui-core-listbox.mjs +219 -0
  43. package/fesm2022/neural-ui-core-listbox.mjs.map +1 -0
  44. package/fesm2022/neural-ui-core-menu.mjs +229 -0
  45. package/fesm2022/neural-ui-core-menu.mjs.map +1 -0
  46. package/fesm2022/neural-ui-core-modal.mjs +34 -10
  47. package/fesm2022/neural-ui-core-modal.mjs.map +1 -1
  48. package/fesm2022/neural-ui-core-multiselect.mjs +170 -179
  49. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -1
  50. package/fesm2022/neural-ui-core-number-input.mjs +2 -2
  51. package/fesm2022/neural-ui-core-number-input.mjs.map +1 -1
  52. package/fesm2022/neural-ui-core-panel.mjs +92 -0
  53. package/fesm2022/neural-ui-core-panel.mjs.map +1 -0
  54. package/fesm2022/neural-ui-core-password.mjs +106 -0
  55. package/fesm2022/neural-ui-core-password.mjs.map +1 -0
  56. package/fesm2022/neural-ui-core-pick-list.mjs +133 -0
  57. package/fesm2022/neural-ui-core-pick-list.mjs.map +1 -0
  58. package/fesm2022/neural-ui-core-select.mjs +128 -166
  59. package/fesm2022/neural-ui-core-select.mjs.map +1 -1
  60. package/fesm2022/neural-ui-core-sidebar.mjs +14 -3
  61. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -1
  62. package/fesm2022/neural-ui-core-slider.mjs +2 -2
  63. package/fesm2022/neural-ui-core-slider.mjs.map +1 -1
  64. package/fesm2022/neural-ui-core-spinner.mjs +19 -9
  65. package/fesm2022/neural-ui-core-spinner.mjs.map +1 -1
  66. package/fesm2022/neural-ui-core-split-button.mjs +2 -2
  67. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -1
  68. package/fesm2022/neural-ui-core-table.mjs +503 -62
  69. package/fesm2022/neural-ui-core-table.mjs.map +1 -1
  70. package/fesm2022/neural-ui-core-tabs.mjs +11 -4
  71. package/fesm2022/neural-ui-core-tabs.mjs.map +1 -1
  72. package/fesm2022/neural-ui-core-tags.mjs +134 -0
  73. package/fesm2022/neural-ui-core-tags.mjs.map +1 -0
  74. package/fesm2022/neural-ui-core-textarea.mjs +2 -2
  75. package/fesm2022/neural-ui-core-textarea.mjs.map +1 -1
  76. package/fesm2022/neural-ui-core-toggle-button-group.mjs +2 -2
  77. package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -1
  78. package/fesm2022/neural-ui-core-toolbar.mjs +16 -4
  79. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -1
  80. package/fesm2022/neural-ui-core-tree-select.mjs +259 -0
  81. package/fesm2022/neural-ui-core-tree-select.mjs.map +1 -0
  82. package/fesm2022/neural-ui-core-tree-table.mjs +267 -8
  83. package/fesm2022/neural-ui-core-tree-table.mjs.map +1 -1
  84. package/fesm2022/neural-ui-core-tree.mjs +15 -14
  85. package/fesm2022/neural-ui-core-tree.mjs.map +1 -1
  86. package/fesm2022/neural-ui-core-uploader.mjs +103 -12
  87. package/fesm2022/neural-ui-core-uploader.mjs.map +1 -1
  88. package/form-field/package.json +4 -0
  89. package/inline-editor/package.json +4 -0
  90. package/input-mask/package.json +4 -0
  91. package/listbox/package.json +4 -0
  92. package/menu/package.json +4 -0
  93. package/package.json +53 -1
  94. package/panel/package.json +4 -0
  95. package/password/package.json +4 -0
  96. package/pick-list/package.json +4 -0
  97. package/styles/_tokens.scss +33 -17
  98. package/tags/package.json +4 -0
  99. package/tree-select/package.json +4 -0
  100. package/types/neural-ui-core-alert.d.ts +2 -1
  101. package/types/neural-ui-core-autocomplete.d.ts +22 -2
  102. package/types/neural-ui-core-bottom-sheet.d.ts +20 -0
  103. package/types/neural-ui-core-checkbox.d.ts +6 -1
  104. package/types/neural-ui-core-confirm-popup.d.ts +38 -0
  105. package/types/neural-ui-core-dashboard-grid.d.ts +1 -0
  106. package/types/neural-ui-core-data-view.d.ts +95 -0
  107. package/types/neural-ui-core-date-input.d.ts +35 -5
  108. package/types/neural-ui-core-empty-state.d.ts +11 -1
  109. package/types/neural-ui-core-form-field.d.ts +33 -0
  110. package/types/neural-ui-core-inline-editor.d.ts +66 -0
  111. package/types/neural-ui-core-input-mask.d.ts +26 -0
  112. package/types/neural-ui-core-listbox.d.ts +54 -0
  113. package/types/neural-ui-core-menu.d.ts +49 -0
  114. package/types/neural-ui-core-modal.d.ts +10 -2
  115. package/types/neural-ui-core-multiselect.d.ts +10 -1
  116. package/types/neural-ui-core-panel.d.ts +25 -0
  117. package/types/neural-ui-core-password.d.ts +29 -0
  118. package/types/neural-ui-core-pick-list.d.ts +40 -0
  119. package/types/neural-ui-core-select.d.ts +7 -1
  120. package/types/neural-ui-core-sidebar.d.ts +5 -1
  121. package/types/neural-ui-core-spinner.d.ts +4 -2
  122. package/types/neural-ui-core-table.d.ts +89 -5
  123. package/types/neural-ui-core-tabs.d.ts +2 -0
  124. package/types/neural-ui-core-tags.d.ts +32 -0
  125. package/types/neural-ui-core-toolbar.d.ts +8 -2
  126. package/types/neural-ui-core-tree-select.d.ts +57 -0
  127. package/types/neural-ui-core-tree-table.d.ts +111 -4
  128. package/types/neural-ui-core-tree.d.ts +1 -1
  129. package/types/neural-ui-core-uploader.d.ts +26 -3
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, TemplateRef, Directive, DestroyRef, PLATFORM_ID, viewChild, contentChild, input, output, signal, computed, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
2
+ import { inject, TemplateRef, Directive, DestroyRef, PLATFORM_ID, viewChild, input, contentChild, computed, output, signal, effect, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
3
  import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { FormControl, ReactiveFormsModule } from '@angular/forms';
@@ -9,6 +9,8 @@ import { NeuInputComponent } from '@neural-ui/core/input';
9
9
  import { NeuSelectComponent } from '@neural-ui/core/select';
10
10
  import { NeuDateInputComponent } from '@neural-ui/core/date-input';
11
11
  import { NeuIconComponent } from '@neural-ui/core/icon';
12
+ import { NeuCheckboxComponent } from '@neural-ui/core/checkbox';
13
+ import { NeuInlineEditorComponent } from '@neural-ui/core/inline-editor';
12
14
 
13
15
  /**
14
16
  * Directiva para definir el template de expansión de fila en NeuTable.
@@ -35,6 +37,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
35
37
  }]
36
38
  }] });
37
39
 
40
+ /**
41
+ * Declarative slot for custom NeuTable toolbar content.
42
+ *
43
+ * Use it for actions owned by the application, such as PDF export,
44
+ * bulk workflows, sync buttons or custom filters.
45
+ */
46
+ class NeuTableToolbarDirective {
47
+ templateRef = inject(TemplateRef);
48
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuTableToolbarDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
49
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.17", type: NeuTableToolbarDirective, isStandalone: true, selector: "ng-template[neuTableToolbar]", ngImport: i0 });
50
+ }
51
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuTableToolbarDirective, decorators: [{
52
+ type: Directive,
53
+ args: [{
54
+ selector: 'ng-template[neuTableToolbar]',
55
+ standalone: true,
56
+ }]
57
+ }] });
58
+
38
59
  // Conversor interno — el input acepta object[] para compatibilidad con
39
60
  // interfaces de usuario concretas (User, Product…). Internamente casteamos a Row.
40
61
  function asRows(data) {
@@ -63,7 +84,6 @@ class NeuTableComponent {
63
84
  _platformId = inject(PLATFORM_ID);
64
85
  _scrollContainer = viewChild('scrollContainer', ...(ngDevMode ? [{ debugName: "_scrollContainer" }] : /* istanbul ignore next */ []));
65
86
  _virtualOverscan = 3;
66
- expandTemplate = contentChild(NeuTableExpandDirective, ...(ngDevMode ? [{ debugName: "expandTemplate" }] : /* istanbul ignore next */ []));
67
87
  // ── Inputs de datos ─────────────────────────────────────────────────
68
88
  columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
69
89
  data = input([], ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
@@ -75,6 +95,9 @@ class NeuTableComponent {
75
95
  toolbarExtraRef = input(null, ...(ngDevMode ? [{ debugName: "toolbarExtraRef" }] : /* istanbul ignore next */ []));
76
96
  emptyMessage = input('No results found', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
77
97
  skeletonRows = input([1, 2, 3, 4, 5], ...(ngDevMode ? [{ debugName: "skeletonRows" }] : /* istanbul ignore next */ []));
98
+ expandTemplate = contentChild(NeuTableExpandDirective, ...(ngDevMode ? [{ debugName: "expandTemplate" }] : /* istanbul ignore next */ []));
99
+ toolbarTemplate = contentChild(NeuTableToolbarDirective, ...(ngDevMode ? [{ debugName: "toolbarTemplate" }] : /* istanbul ignore next */ []));
100
+ _toolbarTemplateRef = computed(() => this.toolbarExtraRef() ?? this.toolbarTemplate()?.templateRef ?? null, ...(ngDevMode ? [{ debugName: "_toolbarTemplateRef" }] : /* istanbul ignore next */ []));
78
101
  // ── Inputs de funcionalidad ──────────────────────────────────────────
79
102
  searchable = input(true, ...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
80
103
  searchPlaceholder = input('Search...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
@@ -90,6 +113,7 @@ class NeuTableComponent {
90
113
  paginationAriaLabel = input('Pagination', ...(ngDevMode ? [{ debugName: "paginationAriaLabel" }] : /* istanbul ignore next */ []));
91
114
  exportCsvTitle = input('Export CSV', ...(ngDevMode ? [{ debugName: "exportCsvTitle" }] : /* istanbul ignore next */ []));
92
115
  exportJsonTitle = input('Export JSON', ...(ngDevMode ? [{ debugName: "exportJsonTitle" }] : /* istanbul ignore next */ []));
116
+ exportXlsxTitle = input('Export XLSX', ...(ngDevMode ? [{ debugName: "exportXlsxTitle" }] : /* istanbul ignore next */ []));
93
117
  clearSelectionLabel = input('Clear selection', ...(ngDevMode ? [{ debugName: "clearSelectionLabel" }] : /* istanbul ignore next */ []));
94
118
  selectionSummaryLabel = input('selected', ...(ngDevMode ? [{ debugName: "selectionSummaryLabel" }] : /* istanbul ignore next */ []));
95
119
  tableAriaLabel = input('Data table', ...(ngDevMode ? [{ debugName: "tableAriaLabel" }] : /* istanbul ignore next */ []));
@@ -113,6 +137,16 @@ class NeuTableComponent {
113
137
  virtualScroll = input(false, ...(ngDevMode ? [{ debugName: "virtualScroll" }] : /* istanbul ignore next */ []));
114
138
  virtualScrollVisibleItems = input(8, ...(ngDevMode ? [{ debugName: "virtualScrollVisibleItems" }] : /* istanbul ignore next */ []));
115
139
  resizableColumns = input(false, ...(ngDevMode ? [{ debugName: "resizableColumns" }] : /* istanbul ignore next */ []));
140
+ reorderableColumns = input(false, ...(ngDevMode ? [{ debugName: "reorderableColumns" }] : /* istanbul ignore next */ []));
141
+ columnChooser = input(false, ...(ngDevMode ? [{ debugName: "columnChooser" }] : /* istanbul ignore next */ []));
142
+ columnChooserLabel = input('Columns', ...(ngDevMode ? [{ debugName: "columnChooserLabel" }] : /* istanbul ignore next */ []));
143
+ groupBy = input('', ...(ngDevMode ? [{ debugName: "groupBy" }] : /* istanbul ignore next */ []));
144
+ groupHeaderLabel = input('Group:', ...(ngDevMode ? [{ debugName: "groupHeaderLabel" }] : /* istanbul ignore next */ []));
145
+ inlineEdit = input(false, ...(ngDevMode ? [{ debugName: "inlineEdit" }] : /* istanbul ignore next */ []));
146
+ inlineEditLabel = input('Edit cell', ...(ngDevMode ? [{ debugName: "inlineEditLabel" }] : /* istanbul ignore next */ []));
147
+ saveInlineEditLabel = input('Save cell', ...(ngDevMode ? [{ debugName: "saveInlineEditLabel" }] : /* istanbul ignore next */ []));
148
+ cancelInlineEditLabel = input('Cancel cell edit', ...(ngDevMode ? [{ debugName: "cancelInlineEditLabel" }] : /* istanbul ignore next */ []));
149
+ initialLayout = input(null, ...(ngDevMode ? [{ debugName: "initialLayout" }] : /* istanbul ignore next */ []));
116
150
  rowKey = input('id', ...(ngDevMode ? [{ debugName: "rowKey" }] : /* istanbul ignore next */ []));
117
151
  bordered = input(true, ...(ngDevMode ? [{ debugName: "bordered" }] : /* istanbul ignore next */ []));
118
152
  roundedBorders = input(true, ...(ngDevMode ? [{ debugName: "roundedBorders" }] : /* istanbul ignore next */ []));
@@ -156,6 +190,9 @@ class NeuTableComponent {
156
190
  serverStateChange = output();
157
191
  searchChange = output();
158
192
  columnResize = output();
193
+ columnReorder = output();
194
+ layoutChange = output();
195
+ cellEditCommit = output();
159
196
  // ── Estado interno (usado cuando useUrlState = false) ─────────────────
160
197
  // Internal state signals (used when useUrlState = false)
161
198
  _internalPage = signal(1, ...(ngDevMode ? [{ debugName: "_internalPage" }] : /* istanbul ignore next */ []));
@@ -164,6 +201,10 @@ class NeuTableComponent {
164
201
  _internalSortDir = signal('asc', ...(ngDevMode ? [{ debugName: "_internalSortDir" }] : /* istanbul ignore next */ []));
165
202
  _internalMultiSort = signal('', ...(ngDevMode ? [{ debugName: "_internalMultiSort" }] : /* istanbul ignore next */ []));
166
203
  _columnWidths = signal({}, ...(ngDevMode ? [{ debugName: "_columnWidths" }] : /* istanbul ignore next */ []));
204
+ _columnOrder = signal([], ...(ngDevMode ? [{ debugName: "_columnOrder" }] : /* istanbul ignore next */ []));
205
+ _hiddenColumns = signal(new Set(), ...(ngDevMode ? [{ debugName: "_hiddenColumns" }] : /* istanbul ignore next */ []));
206
+ columnChooserOpen = signal(false, ...(ngDevMode ? [{ debugName: "columnChooserOpen" }] : /* istanbul ignore next */ []));
207
+ _editingCell = signal(null, ...(ngDevMode ? [{ debugName: "_editingCell" }] : /* istanbul ignore next */ []));
167
208
  _resizeCleanup = null;
168
209
  // ── URL State ─────────────────────────────────────────────────────────
169
210
  _urlParamSignals = new Map();
@@ -229,7 +270,26 @@ class NeuTableComponent {
229
270
  _pageSizeControl = new FormControl('', { nonNullable: true });
230
271
  _columnFilterControls = new Map();
231
272
  /** True when at least one column has filterable:true / True si alguna columna tiene filterable:true */
232
- _hasFilterableCol = computed(() => this.columns().some((c) => c.filterable), ...(ngDevMode ? [{ debugName: "_hasFilterableCol" }] : /* istanbul ignore next */ []));
273
+ _hasFilterableCol = computed(() => this.visibleColumns().some((c) => c.filterable), ...(ngDevMode ? [{ debugName: "_hasFilterableCol" }] : /* istanbul ignore next */ []));
274
+ orderedColumns = computed(() => {
275
+ const columns = this.columns();
276
+ const order = this._columnOrder();
277
+ if (order.length === 0) {
278
+ return columns;
279
+ }
280
+ const byKey = new Map(columns.map((col) => [col.key, col]));
281
+ return [
282
+ ...order.flatMap((key) => {
283
+ const col = byKey.get(key);
284
+ return col ? [col] : [];
285
+ }),
286
+ ...columns.filter((col) => !order.includes(col.key)),
287
+ ];
288
+ }, ...(ngDevMode ? [{ debugName: "orderedColumns" }] : /* istanbul ignore next */ []));
289
+ visibleColumns = computed(() => {
290
+ const hidden = this._hiddenColumns();
291
+ return this.orderedColumns().filter((col) => !hidden.has(col.key));
292
+ }, ...(ngDevMode ? [{ debugName: "visibleColumns" }] : /* istanbul ignore next */ []));
233
293
  /** Convierte filterOptions de string[] a NeuSelectOption[] con opción "Todos" al inicio.
234
294
  * Converts filterOptions from string[] to NeuSelectOption[] with a leading "All" option. */
235
295
  _filterOpts(col) {
@@ -263,6 +323,22 @@ class NeuTableComponent {
263
323
  }
264
324
  }
265
325
  });
326
+ effect(() => {
327
+ const keys = this.columns().map((col) => col.key);
328
+ const layout = this.initialLayout();
329
+ const rawOrder = layout?.columnOrder?.length ? layout.columnOrder : this._columnOrder();
330
+ const nextOrder = [
331
+ ...rawOrder.filter((key) => keys.includes(key)),
332
+ ...keys.filter((key) => !rawOrder.includes(key)),
333
+ ];
334
+ if (nextOrder.join('|') !== this._columnOrder().join('|')) {
335
+ this._columnOrder.set(nextOrder);
336
+ }
337
+ if (layout) {
338
+ this._hiddenColumns.set(new Set(layout.hiddenColumns.filter((key) => keys.includes(key))));
339
+ this._columnWidths.set(layout.columnWidths ?? {});
340
+ }
341
+ });
266
342
  effect(() => {
267
343
  if (!this.virtualScroll()) {
268
344
  return;
@@ -398,6 +474,44 @@ class NeuTableComponent {
398
474
  }
399
475
  return rows.slice(this._virtualStartIndex(), this._virtualEndIndex());
400
476
  }, ...(ngDevMode ? [{ debugName: "visiblePageRows" }] : /* istanbul ignore next */ []));
477
+ visiblePageEntries = computed(() => {
478
+ const rows = this.visiblePageRows();
479
+ const groupKey = this.groupBy();
480
+ if (!groupKey) {
481
+ return rows.map((row, rowIndex) => ({
482
+ kind: 'row',
483
+ key: this.getRowKey(row),
484
+ row,
485
+ rowIndex,
486
+ }));
487
+ }
488
+ const counts = new Map();
489
+ for (const row of rows) {
490
+ const label = String(row[groupKey] ?? '—');
491
+ counts.set(label, (counts.get(label) ?? 0) + 1);
492
+ }
493
+ const seen = new Set();
494
+ const entries = [];
495
+ rows.forEach((row, rowIndex) => {
496
+ const label = String(row[groupKey] ?? '—');
497
+ if (!seen.has(label)) {
498
+ seen.add(label);
499
+ entries.push({
500
+ kind: 'group',
501
+ key: `group:${label}:${entries.length}`,
502
+ label,
503
+ count: counts.get(label) ?? 0,
504
+ });
505
+ }
506
+ entries.push({
507
+ kind: 'row',
508
+ key: this.getRowKey(row),
509
+ row,
510
+ rowIndex,
511
+ });
512
+ });
513
+ return entries;
514
+ }, ...(ngDevMode ? [{ debugName: "visiblePageEntries" }] : /* istanbul ignore next */ []));
401
515
  _virtualTopSpacerHeight = computed(() => {
402
516
  if (!this._virtualScrollActive()) {
403
517
  return 0;
@@ -429,7 +543,7 @@ class NeuTableComponent {
429
543
  return `${from}-${to} ${this.ofLabel()} ${total} ${total === 1 ? this.resultLabelSingular() : this.resultLabelPlural()}`;
430
544
  }, ...(ngDevMode ? [{ debugName: "paginationInfo" }] : /* istanbul ignore next */ []));
431
545
  totalColspan = computed(() => {
432
- let cols = this.columns().length;
546
+ let cols = this.visibleColumns().length;
433
547
  if (this.selectable())
434
548
  cols++;
435
549
  if (this.expandable())
@@ -442,7 +556,7 @@ class NeuTableComponent {
442
556
  this._columnWidths();
443
557
  const offsets = new Map();
444
558
  let leftPx = 0;
445
- for (const col of this.columns()) {
559
+ for (const col of this.visibleColumns()) {
446
560
  if (col.frozen === 'left') {
447
561
  offsets.set(col.key, leftPx);
448
562
  leftPx += this._columnWidthPx(col) ?? 0;
@@ -451,11 +565,11 @@ class NeuTableComponent {
451
565
  return offsets;
452
566
  }, ...(ngDevMode ? [{ debugName: "_frozenLeftOffsets" }] : /* istanbul ignore next */ []));
453
567
  _lastFrozenLeftKey = computed(() => {
454
- const frozenLeft = this.columns().filter((col) => col.frozen === 'left');
568
+ const frozenLeft = this.visibleColumns().filter((col) => col.frozen === 'left');
455
569
  return frozenLeft.at(-1)?.key ?? null;
456
570
  }, ...(ngDevMode ? [{ debugName: "_lastFrozenLeftKey" }] : /* istanbul ignore next */ []));
457
571
  _firstFrozenRightKey = computed(() => {
458
- const frozenRight = this.columns().filter((col) => col.frozen === 'right');
572
+ const frozenRight = this.visibleColumns().filter((col) => col.frozen === 'right');
459
573
  return frozenRight[0]?.key ?? null;
460
574
  }, ...(ngDevMode ? [{ debugName: "_firstFrozenRightKey" }] : /* istanbul ignore next */ []));
461
575
  isLastFrozenLeftColumn(key) {
@@ -464,6 +578,64 @@ class NeuTableComponent {
464
578
  isFirstFrozenRightColumn(key) {
465
579
  return this._firstFrozenRightKey() === key;
466
580
  }
581
+ toggleColumnChooser() {
582
+ this.columnChooserOpen.update((value) => !value);
583
+ }
584
+ isColumnVisible(key) {
585
+ return !this._hiddenColumns().has(key);
586
+ }
587
+ toggleColumnVisibility(key) {
588
+ const next = new Set(this._hiddenColumns());
589
+ if (next.has(key)) {
590
+ next.delete(key);
591
+ }
592
+ else if (this.visibleColumns().length > 1) {
593
+ next.add(key);
594
+ }
595
+ this._hiddenColumns.set(next);
596
+ this._emitLayoutChange();
597
+ }
598
+ isFirstVisibleColumn(key) {
599
+ return this.visibleColumns()[0]?.key === key;
600
+ }
601
+ isLastVisibleColumn(key) {
602
+ return this.visibleColumns().at(-1)?.key === key;
603
+ }
604
+ moveColumn(key, direction) {
605
+ const order = this.orderedColumns().map((col) => col.key);
606
+ const previousIndex = order.indexOf(key);
607
+ const targetIndex = previousIndex + direction;
608
+ if (previousIndex < 0 || targetIndex < 0 || targetIndex >= order.length) {
609
+ return;
610
+ }
611
+ const next = [...order];
612
+ const [moved] = next.splice(previousIndex, 1);
613
+ next.splice(targetIndex, 0, moved);
614
+ this._columnOrder.set(next);
615
+ this.columnReorder.emit({
616
+ previousIndex,
617
+ currentIndex: targetIndex,
618
+ columns: next,
619
+ });
620
+ this._emitLayoutChange();
621
+ }
622
+ applyLayout(layout) {
623
+ const keys = this.columns().map((col) => col.key);
624
+ this._columnOrder.set([
625
+ ...layout.columnOrder.filter((key) => keys.includes(key)),
626
+ ...keys.filter((key) => !layout.columnOrder.includes(key)),
627
+ ]);
628
+ this._hiddenColumns.set(new Set(layout.hiddenColumns.filter((key) => keys.includes(key))));
629
+ this._columnWidths.set(layout.columnWidths ?? {});
630
+ this._emitLayoutChange();
631
+ }
632
+ currentLayout() {
633
+ return {
634
+ columnOrder: this.orderedColumns().map((col) => col.key),
635
+ hiddenColumns: [...this._hiddenColumns()],
636
+ columnWidths: this._columnWidths(),
637
+ };
638
+ }
467
639
  isColumnResizable(col) {
468
640
  return this.resizableColumns() && col.resizable !== false;
469
641
  }
@@ -518,6 +690,7 @@ class NeuTableComponent {
518
690
  delete next[key];
519
691
  return next;
520
692
  });
693
+ this._emitLayoutChange();
521
694
  }
522
695
  // ── Expansión de filas ────────────────────────────────────────────────
523
696
  _expandedKeys = signal(new Set(), ...(ngDevMode ? [{ debugName: "_expandedKeys" }] : /* istanbul ignore next */ []));
@@ -789,6 +962,27 @@ class NeuTableComponent {
789
962
  });
790
963
  this._downloadBlob(new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }), `${this.exportFileName()}.json`);
791
964
  }
965
+ exportXlsx() {
966
+ if (!isPlatformBrowser(this._platformId))
967
+ return;
968
+ const cols = this._getExportColumns();
969
+ const rows = this._getExportRows();
970
+ const escape = (value) => value
971
+ .replace(/&/g, '&amp;')
972
+ .replace(/</g, '&lt;')
973
+ .replace(/>/g, '&gt;')
974
+ .replace(/"/g, '&quot;');
975
+ const table = [
976
+ '<table>',
977
+ `<tr>${cols.map((col) => `<th>${escape(col.header)}</th>`).join('')}</tr>`,
978
+ ...rows.map((row) => `<tr>${cols.map((col) => `<td>${escape(this.getCellValue(row, col))}</td>`).join('')}</tr>`),
979
+ '</table>',
980
+ ].join('');
981
+ const html = `<!doctype html><html><head><meta charset="utf-8"></head><body>${table}</body></html>`;
982
+ this._downloadBlob(new Blob([html], {
983
+ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8;',
984
+ }), `${this.exportFileName()}.xlsx`);
985
+ }
792
986
  _getExportColumns() {
793
987
  const keys = this.exportColumns();
794
988
  const all = this.columns().filter((c) => c.type !== 'actions');
@@ -830,6 +1024,8 @@ class NeuTableComponent {
830
1024
  }
831
1025
  resetVirtualScrollPosition() {
832
1026
  this._virtualScrollTop.set(0);
1027
+ if (!isPlatformBrowser(this._platformId))
1028
+ return;
833
1029
  requestAnimationFrame(() => {
834
1030
  this._scrollContainer()?.nativeElement.scrollTo({ top: 0 });
835
1031
  });
@@ -850,6 +1046,7 @@ class NeuTableComponent {
850
1046
  }
851
1047
  _setColumnWidth(key, width) {
852
1048
  this._columnWidths.update((current) => ({ ...current, [key]: width }));
1049
+ this._emitLayoutChange();
853
1050
  }
854
1051
  _stopColumnResize() {
855
1052
  this._resizeCleanup?.();
@@ -880,6 +1077,55 @@ class NeuTableComponent {
880
1077
  return String(val);
881
1078
  }
882
1079
  }
1080
+ isEditingCell(row, col) {
1081
+ const editing = this._editingCell();
1082
+ return (editing !== null &&
1083
+ editing.rowKey === this.getRowKey(row) &&
1084
+ editing.columnKey === col.key);
1085
+ }
1086
+ editingValue() {
1087
+ return this._editingCell()?.value ?? '';
1088
+ }
1089
+ inlineEditorType(col) {
1090
+ return col.editor ?? 'text';
1091
+ }
1092
+ inlineEditorOptions(col) {
1093
+ return (col.editOptions ?? []).map((option) => ({ label: option, value: option }));
1094
+ }
1095
+ setEditingValue(value) {
1096
+ this._editingCell.update((editing) => (editing ? { ...editing, value } : editing));
1097
+ }
1098
+ startCellEdit(row, col, event) {
1099
+ if (!this.inlineEdit() || !col.editable) {
1100
+ return;
1101
+ }
1102
+ event?.stopPropagation();
1103
+ const previousValue = row[col.key];
1104
+ this._editingCell.set({
1105
+ rowKey: this.getRowKey(row),
1106
+ columnKey: col.key,
1107
+ value: previousValue ?? '',
1108
+ previousValue,
1109
+ });
1110
+ }
1111
+ commitCellEdit(row, col) {
1112
+ const editing = this._editingCell();
1113
+ if (!editing || editing.rowKey !== this.getRowKey(row) || editing.columnKey !== col.key) {
1114
+ return;
1115
+ }
1116
+ this._editingCell.set(null);
1117
+ this.cellEditCommit.emit({
1118
+ row,
1119
+ column: col,
1120
+ value: editing.value,
1121
+ previousValue: editing.previousValue,
1122
+ });
1123
+ }
1124
+ cancelCellEdit(event) {
1125
+ event?.stopPropagation();
1126
+ event?.preventDefault();
1127
+ this._editingCell.set(null);
1128
+ }
883
1129
  getSortPriority(key) {
884
1130
  if (!this.multiSort())
885
1131
  return -1;
@@ -913,8 +1159,11 @@ class NeuTableComponent {
913
1159
  };
914
1160
  this.serverStateChange.emit({ ...current, ...patch });
915
1161
  }
1162
+ _emitLayoutChange() {
1163
+ this.layoutChange.emit(this.currentLayout());
1164
+ }
916
1165
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
917
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuTableComponent, isStandalone: true, selector: "neu-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, toolbarExtraRef: { classPropertyName: "toolbarExtraRef", publicName: "toolbarExtraRef", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, skeletonRows: { classPropertyName: "skeletonRows", publicName: "skeletonRows", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, exactMatchable: { classPropertyName: "exactMatchable", publicName: "exactMatchable", isSignal: true, isRequired: false, transformFunction: null }, exactMatchLabel: { classPropertyName: "exactMatchLabel", publicName: "exactMatchLabel", isSignal: true, isRequired: false, transformFunction: null }, searchAriaLabel: { classPropertyName: "searchAriaLabel", publicName: "searchAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, clearSearchAriaLabel: { classPropertyName: "clearSearchAriaLabel", publicName: "clearSearchAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, clearFilterLabel: { classPropertyName: "clearFilterLabel", publicName: "clearFilterLabel", isSignal: true, isRequired: false, transformFunction: null }, previousPageAriaLabel: { classPropertyName: "previousPageAriaLabel", publicName: "previousPageAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, nextPageAriaLabel: { classPropertyName: "nextPageAriaLabel", publicName: "nextPageAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, pageSizeLabel: { classPropertyName: "pageSizeLabel", publicName: "pageSizeLabel", isSignal: true, isRequired: false, transformFunction: null }, pageSizeAriaLabel: { classPropertyName: "pageSizeAriaLabel", publicName: "pageSizeAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationAriaLabel: { classPropertyName: "paginationAriaLabel", publicName: "paginationAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, exportCsvTitle: { classPropertyName: "exportCsvTitle", publicName: "exportCsvTitle", isSignal: true, isRequired: false, transformFunction: null }, exportJsonTitle: { classPropertyName: "exportJsonTitle", publicName: "exportJsonTitle", isSignal: true, isRequired: false, transformFunction: null }, clearSelectionLabel: { classPropertyName: "clearSelectionLabel", publicName: "clearSelectionLabel", isSignal: true, isRequired: false, transformFunction: null }, selectionSummaryLabel: { classPropertyName: "selectionSummaryLabel", publicName: "selectionSummaryLabel", isSignal: true, isRequired: false, transformFunction: null }, tableAriaLabel: { classPropertyName: "tableAriaLabel", publicName: "tableAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, selectAllAriaLabel: { classPropertyName: "selectAllAriaLabel", publicName: "selectAllAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, selectRowAriaLabel: { classPropertyName: "selectRowAriaLabel", publicName: "selectRowAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, expandRowAriaLabel: { classPropertyName: "expandRowAriaLabel", publicName: "expandRowAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, filterAriaPrefix: { classPropertyName: "filterAriaPrefix", publicName: "filterAriaPrefix", isSignal: true, isRequired: false, transformFunction: null }, allFilterOptionLabel: { classPropertyName: "allFilterOptionLabel", publicName: "allFilterOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, ofLabel: { classPropertyName: "ofLabel", publicName: "ofLabel", isSignal: true, isRequired: false, transformFunction: null }, resultLabelSingular: { classPropertyName: "resultLabelSingular", publicName: "resultLabelSingular", isSignal: true, isRequired: false, transformFunction: null }, resultLabelPlural: { classPropertyName: "resultLabelPlural", publicName: "resultLabelPlural", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, expandMode: { classPropertyName: "expandMode", publicName: "expandMode", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, exportFileName: { classPropertyName: "exportFileName", publicName: "exportFileName", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, roundedBorders: { classPropertyName: "roundedBorders", publicName: "roundedBorders", isSignal: true, isRequired: false, transformFunction: null }, stripedRows: { classPropertyName: "stripedRows", publicName: "stripedRows", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, showRowNumbers: { classPropertyName: "showRowNumbers", publicName: "showRowNumbers", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, footerRow: { classPropertyName: "footerRow", publicName: "footerRow", isSignal: true, isRequired: false, transformFunction: null }, emptyStateTemplate: { classPropertyName: "emptyStateTemplate", publicName: "emptyStateTemplate", isSignal: true, isRequired: false, transformFunction: null }, serverSide: { classPropertyName: "serverSide", publicName: "serverSide", isSignal: true, isRequired: false, transformFunction: null }, totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: false, transformFunction: null }, multiSort: { classPropertyName: "multiSort", publicName: "multiSort", isSignal: true, isRequired: false, transformFunction: null }, exportFormats: { classPropertyName: "exportFormats", publicName: "exportFormats", isSignal: true, isRequired: false, transformFunction: null }, exportColumns: { classPropertyName: "exportColumns", publicName: "exportColumns", isSignal: true, isRequired: false, transformFunction: null }, exportScope: { classPropertyName: "exportScope", publicName: "exportScope", isSignal: true, isRequired: false, transformFunction: null }, selectionActions: { classPropertyName: "selectionActions", publicName: "selectionActions", isSignal: true, isRequired: false, transformFunction: null }, pageParam: { classPropertyName: "pageParam", publicName: "pageParam", isSignal: true, isRequired: false, transformFunction: null }, searchParam: { classPropertyName: "searchParam", publicName: "searchParam", isSignal: true, isRequired: false, transformFunction: null }, sortParam: { classPropertyName: "sortParam", publicName: "sortParam", isSignal: true, isRequired: false, transformFunction: null }, sortDirParam: { classPropertyName: "sortDirParam", publicName: "sortDirParam", isSignal: true, isRequired: false, transformFunction: null }, multiSortParam: { classPropertyName: "multiSortParam", publicName: "multiSortParam", isSignal: true, isRequired: false, transformFunction: null }, useUrlState: { classPropertyName: "useUrlState", publicName: "useUrlState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", rowClick: "rowClick", rowDblClick: "rowDblClick", actionClick: "actionClick", selectionActionClick: "selectionActionClick", serverStateChange: "serverStateChange", searchChange: "searchChange", columnResize: "columnResize" }, host: { properties: { "class.neu-table__host": "true", "class.neu-table__host--compact": "density() === \"compact\"", "class.neu-table__host--relaxed": "density() === \"relaxed\"" } }, queries: [{ propertyName: "expandTemplate", first: true, predicate: NeuTableExpandDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
1166
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuTableComponent, isStandalone: true, selector: "neu-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, pageSize: { classPropertyName: "pageSize", publicName: "pageSize", isSignal: true, isRequired: false, transformFunction: null }, pagination: { classPropertyName: "pagination", publicName: "pagination", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, toolbarExtraRef: { classPropertyName: "toolbarExtraRef", publicName: "toolbarExtraRef", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, skeletonRows: { classPropertyName: "skeletonRows", publicName: "skeletonRows", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, exactMatchable: { classPropertyName: "exactMatchable", publicName: "exactMatchable", isSignal: true, isRequired: false, transformFunction: null }, exactMatchLabel: { classPropertyName: "exactMatchLabel", publicName: "exactMatchLabel", isSignal: true, isRequired: false, transformFunction: null }, searchAriaLabel: { classPropertyName: "searchAriaLabel", publicName: "searchAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, clearSearchAriaLabel: { classPropertyName: "clearSearchAriaLabel", publicName: "clearSearchAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, clearFilterLabel: { classPropertyName: "clearFilterLabel", publicName: "clearFilterLabel", isSignal: true, isRequired: false, transformFunction: null }, previousPageAriaLabel: { classPropertyName: "previousPageAriaLabel", publicName: "previousPageAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, nextPageAriaLabel: { classPropertyName: "nextPageAriaLabel", publicName: "nextPageAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, pageSizeLabel: { classPropertyName: "pageSizeLabel", publicName: "pageSizeLabel", isSignal: true, isRequired: false, transformFunction: null }, pageSizeAriaLabel: { classPropertyName: "pageSizeAriaLabel", publicName: "pageSizeAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, paginationAriaLabel: { classPropertyName: "paginationAriaLabel", publicName: "paginationAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, exportCsvTitle: { classPropertyName: "exportCsvTitle", publicName: "exportCsvTitle", isSignal: true, isRequired: false, transformFunction: null }, exportJsonTitle: { classPropertyName: "exportJsonTitle", publicName: "exportJsonTitle", isSignal: true, isRequired: false, transformFunction: null }, exportXlsxTitle: { classPropertyName: "exportXlsxTitle", publicName: "exportXlsxTitle", isSignal: true, isRequired: false, transformFunction: null }, clearSelectionLabel: { classPropertyName: "clearSelectionLabel", publicName: "clearSelectionLabel", isSignal: true, isRequired: false, transformFunction: null }, selectionSummaryLabel: { classPropertyName: "selectionSummaryLabel", publicName: "selectionSummaryLabel", isSignal: true, isRequired: false, transformFunction: null }, tableAriaLabel: { classPropertyName: "tableAriaLabel", publicName: "tableAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, selectAllAriaLabel: { classPropertyName: "selectAllAriaLabel", publicName: "selectAllAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, selectRowAriaLabel: { classPropertyName: "selectRowAriaLabel", publicName: "selectRowAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, expandRowAriaLabel: { classPropertyName: "expandRowAriaLabel", publicName: "expandRowAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceholder: { classPropertyName: "filterPlaceholder", publicName: "filterPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, filterAriaPrefix: { classPropertyName: "filterAriaPrefix", publicName: "filterAriaPrefix", isSignal: true, isRequired: false, transformFunction: null }, allFilterOptionLabel: { classPropertyName: "allFilterOptionLabel", publicName: "allFilterOptionLabel", isSignal: true, isRequired: false, transformFunction: null }, ofLabel: { classPropertyName: "ofLabel", publicName: "ofLabel", isSignal: true, isRequired: false, transformFunction: null }, resultLabelSingular: { classPropertyName: "resultLabelSingular", publicName: "resultLabelSingular", isSignal: true, isRequired: false, transformFunction: null }, resultLabelPlural: { classPropertyName: "resultLabelPlural", publicName: "resultLabelPlural", isSignal: true, isRequired: false, transformFunction: null }, sortable: { classPropertyName: "sortable", publicName: "sortable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, expandable: { classPropertyName: "expandable", publicName: "expandable", isSignal: true, isRequired: false, transformFunction: null }, expandMode: { classPropertyName: "expandMode", publicName: "expandMode", isSignal: true, isRequired: false, transformFunction: null }, exportable: { classPropertyName: "exportable", publicName: "exportable", isSignal: true, isRequired: false, transformFunction: null }, exportFileName: { classPropertyName: "exportFileName", publicName: "exportFileName", isSignal: true, isRequired: false, transformFunction: null }, pageSizeOptions: { classPropertyName: "pageSizeOptions", publicName: "pageSizeOptions", isSignal: true, isRequired: false, transformFunction: null }, stickyHeader: { classPropertyName: "stickyHeader", publicName: "stickyHeader", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, resizableColumns: { classPropertyName: "resizableColumns", publicName: "resizableColumns", isSignal: true, isRequired: false, transformFunction: null }, reorderableColumns: { classPropertyName: "reorderableColumns", publicName: "reorderableColumns", isSignal: true, isRequired: false, transformFunction: null }, columnChooser: { classPropertyName: "columnChooser", publicName: "columnChooser", isSignal: true, isRequired: false, transformFunction: null }, columnChooserLabel: { classPropertyName: "columnChooserLabel", publicName: "columnChooserLabel", isSignal: true, isRequired: false, transformFunction: null }, groupBy: { classPropertyName: "groupBy", publicName: "groupBy", isSignal: true, isRequired: false, transformFunction: null }, groupHeaderLabel: { classPropertyName: "groupHeaderLabel", publicName: "groupHeaderLabel", isSignal: true, isRequired: false, transformFunction: null }, inlineEdit: { classPropertyName: "inlineEdit", publicName: "inlineEdit", isSignal: true, isRequired: false, transformFunction: null }, inlineEditLabel: { classPropertyName: "inlineEditLabel", publicName: "inlineEditLabel", isSignal: true, isRequired: false, transformFunction: null }, saveInlineEditLabel: { classPropertyName: "saveInlineEditLabel", publicName: "saveInlineEditLabel", isSignal: true, isRequired: false, transformFunction: null }, cancelInlineEditLabel: { classPropertyName: "cancelInlineEditLabel", publicName: "cancelInlineEditLabel", isSignal: true, isRequired: false, transformFunction: null }, initialLayout: { classPropertyName: "initialLayout", publicName: "initialLayout", isSignal: true, isRequired: false, transformFunction: null }, rowKey: { classPropertyName: "rowKey", publicName: "rowKey", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, roundedBorders: { classPropertyName: "roundedBorders", publicName: "roundedBorders", isSignal: true, isRequired: false, transformFunction: null }, stripedRows: { classPropertyName: "stripedRows", publicName: "stripedRows", isSignal: true, isRequired: false, transformFunction: null }, density: { classPropertyName: "density", publicName: "density", isSignal: true, isRequired: false, transformFunction: null }, showRowNumbers: { classPropertyName: "showRowNumbers", publicName: "showRowNumbers", isSignal: true, isRequired: false, transformFunction: null }, rowClass: { classPropertyName: "rowClass", publicName: "rowClass", isSignal: true, isRequired: false, transformFunction: null }, footerRow: { classPropertyName: "footerRow", publicName: "footerRow", isSignal: true, isRequired: false, transformFunction: null }, emptyStateTemplate: { classPropertyName: "emptyStateTemplate", publicName: "emptyStateTemplate", isSignal: true, isRequired: false, transformFunction: null }, serverSide: { classPropertyName: "serverSide", publicName: "serverSide", isSignal: true, isRequired: false, transformFunction: null }, totalItems: { classPropertyName: "totalItems", publicName: "totalItems", isSignal: true, isRequired: false, transformFunction: null }, multiSort: { classPropertyName: "multiSort", publicName: "multiSort", isSignal: true, isRequired: false, transformFunction: null }, exportFormats: { classPropertyName: "exportFormats", publicName: "exportFormats", isSignal: true, isRequired: false, transformFunction: null }, exportColumns: { classPropertyName: "exportColumns", publicName: "exportColumns", isSignal: true, isRequired: false, transformFunction: null }, exportScope: { classPropertyName: "exportScope", publicName: "exportScope", isSignal: true, isRequired: false, transformFunction: null }, selectionActions: { classPropertyName: "selectionActions", publicName: "selectionActions", isSignal: true, isRequired: false, transformFunction: null }, pageParam: { classPropertyName: "pageParam", publicName: "pageParam", isSignal: true, isRequired: false, transformFunction: null }, searchParam: { classPropertyName: "searchParam", publicName: "searchParam", isSignal: true, isRequired: false, transformFunction: null }, sortParam: { classPropertyName: "sortParam", publicName: "sortParam", isSignal: true, isRequired: false, transformFunction: null }, sortDirParam: { classPropertyName: "sortDirParam", publicName: "sortDirParam", isSignal: true, isRequired: false, transformFunction: null }, multiSortParam: { classPropertyName: "multiSortParam", publicName: "multiSortParam", isSignal: true, isRequired: false, transformFunction: null }, useUrlState: { classPropertyName: "useUrlState", publicName: "useUrlState", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange", rowClick: "rowClick", rowDblClick: "rowDblClick", actionClick: "actionClick", selectionActionClick: "selectionActionClick", serverStateChange: "serverStateChange", searchChange: "searchChange", columnResize: "columnResize", columnReorder: "columnReorder", layoutChange: "layoutChange", cellEditCommit: "cellEditCommit" }, host: { properties: { "class.neu-table__host": "true", "class.neu-table__host--compact": "density() === \"compact\"", "class.neu-table__host--relaxed": "density() === \"relaxed\"" } }, queries: [{ propertyName: "expandTemplate", first: true, predicate: NeuTableExpandDirective, descendants: true, isSignal: true }, { propertyName: "toolbarTemplate", first: true, predicate: NeuTableToolbarDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, isSignal: true }], ngImport: i0, template: `
918
1167
  <div
919
1168
  class="neu-table-container"
920
1169
  [class.neu-table--sticky-header]="stickyHeader()"
@@ -923,14 +1172,14 @@ class NeuTableComponent {
923
1172
  [class.neu-table-container--striped]="stripedRows()"
924
1173
  >
925
1174
  <!-- ---- Toolbar ---- -->
926
- @if (searchable() || title() || exportable() || toolbarExtraRef()) {
1175
+ @if (searchable() || title() || exportable() || _toolbarTemplateRef()) {
927
1176
  <div class="neu-table__toolbar">
928
1177
  @if (title()) {
929
1178
  <h3 class="neu-table__title">{{ title() }}</h3>
930
1179
  }
931
- @if (toolbarExtraRef()) {
1180
+ @if (_toolbarTemplateRef(); as toolbarTpl) {
932
1181
  <div class="neu-table__toolbar-extra">
933
- <ng-container [ngTemplateOutlet]="toolbarExtraRef()!" />
1182
+ <ng-container [ngTemplateOutlet]="toolbarTpl" />
934
1183
  </div>
935
1184
  }
936
1185
  @if (searchable()) {
@@ -979,15 +1228,38 @@ class NeuTableComponent {
979
1228
  }
980
1229
  </div>
981
1230
  @if (exactMatchable()) {
982
- <label class="neu-table__exact-label">
983
- <input
1231
+ <neu-checkbox
984
1232
  class="neu-table__exact-checkbox"
985
- type="checkbox"
986
1233
  [checked]="exactMatch()"
987
- (change)="setExactMatch($any($event.target).checked)"
1234
+ [label]="exactMatchLabel()"
1235
+ (checkedChange)="setExactMatch($event)"
988
1236
  />
989
- {{ exactMatchLabel() }}
990
- </label>
1237
+ }
1238
+ </div>
1239
+ }
1240
+ @if (columnChooser()) {
1241
+ <div class="neu-table__column-chooser">
1242
+ <button
1243
+ class="neu-table__export-btn"
1244
+ type="button"
1245
+ [attr.aria-expanded]="columnChooserOpen()"
1246
+ (click)="toggleColumnChooser()"
1247
+ >
1248
+ {{ columnChooserLabel() }}
1249
+ </button>
1250
+ @if (columnChooserOpen()) {
1251
+ <div class="neu-table__column-chooser-panel" role="menu">
1252
+ @for (col of orderedColumns(); track col.key) {
1253
+ <div class="neu-table__column-chooser-item">
1254
+ <neu-checkbox
1255
+ class="neu-table__column-chooser-checkbox"
1256
+ [checked]="isColumnVisible(col.key)"
1257
+ [label]="col.header"
1258
+ (checkedChange)="toggleColumnVisibility(col.key)"
1259
+ />
1260
+ </div>
1261
+ }
1262
+ </div>
991
1263
  }
992
1264
  </div>
993
1265
  }
@@ -1043,6 +1315,31 @@ class NeuTableComponent {
1043
1315
  JSON
1044
1316
  </button>
1045
1317
  }
1318
+ @if (exportFormats().includes('xlsx')) {
1319
+ <button
1320
+ class="neu-table__export-btn"
1321
+ type="button"
1322
+ (click)="exportXlsx()"
1323
+ [title]="exportXlsxTitle()"
1324
+ >
1325
+ <svg
1326
+ viewBox="0 0 24 24"
1327
+ fill="none"
1328
+ stroke="currentColor"
1329
+ stroke-width="2"
1330
+ stroke-linecap="round"
1331
+ stroke-linejoin="round"
1332
+ aria-hidden="true"
1333
+ width="15"
1334
+ height="15"
1335
+ >
1336
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
1337
+ <polyline points="7 10 12 15 17 10" />
1338
+ <line x1="12" y1="15" x2="12" y2="3" />
1339
+ </svg>
1340
+ XLSX
1341
+ </button>
1342
+ }
1046
1343
  </div>
1047
1344
  }
1048
1345
  </div>
@@ -1123,20 +1420,19 @@ class NeuTableComponent {
1123
1420
  }
1124
1421
  @if (selectable()) {
1125
1422
  <th class="neu-table__th neu-table__th--check" scope="col">
1126
- <input
1127
- type="checkbox"
1423
+ <neu-checkbox
1128
1424
  class="neu-table__checkbox"
1129
1425
  [checked]="isAllFilteredSelected()"
1130
1426
  [indeterminate]="isSomeFilteredSelected()"
1131
- (change)="toggleAll()"
1132
- [attr.aria-label]="selectAllAriaLabel()"
1427
+ [ariaLabel]="selectAllAriaLabel()"
1428
+ (checkedChange)="toggleAll()"
1133
1429
  />
1134
1430
  </th>
1135
1431
  }
1136
1432
  @if (showRowNumbers()) {
1137
1433
  <th class="neu-table__th neu-table__th--rn" scope="col">#</th>
1138
1434
  }
1139
- @for (col of columns(); track col.key) {
1435
+ @for (col of visibleColumns(); track col.key) {
1140
1436
  <th
1141
1437
  class="neu-table__th"
1142
1438
  [class.neu-table__th--sortable]="sortable() && col.sortable !== false"
@@ -1161,6 +1457,28 @@ class NeuTableComponent {
1161
1457
  scope="col"
1162
1458
  (click)="sortable() && col.sortable !== false ? sortBy(col.key, $event) : null"
1163
1459
  >
1460
+ @if (reorderableColumns()) {
1461
+ <span class="neu-table__reorder-controls" (click)="$event.stopPropagation()">
1462
+ <button
1463
+ type="button"
1464
+ class="neu-table__reorder-btn"
1465
+ [disabled]="isFirstVisibleColumn(col.key)"
1466
+ [attr.aria-label]="'Move ' + col.header + ' left'"
1467
+ (click)="moveColumn(col.key, -1)"
1468
+ >
1469
+
1470
+ </button>
1471
+ <button
1472
+ type="button"
1473
+ class="neu-table__reorder-btn"
1474
+ [disabled]="isLastVisibleColumn(col.key)"
1475
+ [attr.aria-label]="'Move ' + col.header + ' right'"
1476
+ (click)="moveColumn(col.key, 1)"
1477
+ >
1478
+
1479
+ </button>
1480
+ </span>
1481
+ }
1164
1482
  @if (col.headerTemplate) {
1165
1483
  <ng-container
1166
1484
  [ngTemplateOutlet]="col.headerTemplate"
@@ -1212,7 +1530,7 @@ class NeuTableComponent {
1212
1530
  @if (showRowNumbers()) {
1213
1531
  <th class="neu-table__th neu-table__th--filter-placeholder" scope="col"></th>
1214
1532
  }
1215
- @for (col of columns(); track col.key) {
1533
+ @for (col of visibleColumns(); track col.key) {
1216
1534
  <th
1217
1535
  class="neu-table__th neu-table__th--filter"
1218
1536
  scope="col"
@@ -1231,6 +1549,7 @@ class NeuTableComponent {
1231
1549
  } @else if (col.filterType === 'date') {
1232
1550
  <neu-date-input
1233
1551
  [formControl]="columnFilterControl(col.key)"
1552
+ [placeholder]="filterPlaceholder()"
1234
1553
  [attr.aria-label]="filterAriaPrefix() + ' ' + col.header"
1235
1554
  />
1236
1555
  } @else {
@@ -1255,7 +1574,7 @@ class NeuTableComponent {
1255
1574
  <div class="neu-table__skeleton-rows">
1256
1575
  @for (_ of skeletonRows(); track $index) {
1257
1576
  <div class="neu-table__skeleton-row">
1258
- @for (__ of columns(); track $index) {
1577
+ @for (__ of visibleColumns(); track $index) {
1259
1578
  <div class="neu-table__skeleton-cell"></div>
1260
1579
  }
1261
1580
  </div>
@@ -1305,7 +1624,16 @@ class NeuTableComponent {
1305
1624
  ></td>
1306
1625
  </tr>
1307
1626
  }
1308
- @for (row of visiblePageRows(); track getRowKey(row); let rowIdx = $index) {
1627
+ @for (entry of visiblePageEntries(); track entry.key; let entryIdx = $index) {
1628
+ @if (entry.kind === 'group') {
1629
+ <tr class="neu-table__group-row">
1630
+ <td [attr.colspan]="totalColspan()" class="neu-table__td neu-table__td--group">
1631
+ {{ groupHeaderLabel() }} {{ entry.label }}
1632
+ <span class="neu-table__group-count">({{ entry.count }})</span>
1633
+ </td>
1634
+ </tr>
1635
+ } @else {
1636
+ @let row = entry.row;
1309
1637
  <tr
1310
1638
  class="neu-table__row"
1311
1639
  [class]="getRowClass(row)"
@@ -1345,21 +1673,20 @@ class NeuTableComponent {
1345
1673
  class="neu-table__td neu-table__th--check"
1346
1674
  (click)="$event.stopPropagation()"
1347
1675
  >
1348
- <input
1349
- type="checkbox"
1676
+ <neu-checkbox
1350
1677
  class="neu-table__checkbox"
1351
1678
  [checked]="isRowSelected(row)"
1352
- (change)="toggleRow(row)"
1353
- [attr.aria-label]="selectRowAriaLabel()"
1679
+ [ariaLabel]="selectRowAriaLabel()"
1680
+ (checkedChange)="toggleRow(row)"
1354
1681
  />
1355
1682
  </td>
1356
1683
  }
1357
1684
  @if (showRowNumbers()) {
1358
1685
  <td class="neu-table__td neu-table__td--rn">
1359
- {{ visibleRowNumber(rowIdx) }}
1686
+ {{ visibleRowNumber(entry.rowIndex) }}
1360
1687
  </td>
1361
1688
  }
1362
- @for (col of columns(); track col.key) {
1689
+ @for (col of visibleColumns(); track col.key) {
1363
1690
  <td
1364
1691
  class="neu-table__td"
1365
1692
  [class]="col.cellClass ?? ''"
@@ -1378,8 +1705,24 @@ class NeuTableComponent {
1378
1705
  [style.min-width]="columnWidth(col)"
1379
1706
  [style.max-width]="columnWidth(col)"
1380
1707
  [style.text-align]="col.align ?? 'left'"
1708
+ (dblclick)="startCellEdit(row, col, $event)"
1381
1709
  >
1382
- @if (col.cellTemplate) {
1710
+ @if (isEditingCell(row, col)) {
1711
+ <neu-inline-editor
1712
+ class="neu-table__edit-control"
1713
+ [type]="inlineEditorType(col)"
1714
+ [value]="$any(editingValue())"
1715
+ [options]="inlineEditorOptions(col)"
1716
+ [startInEdit]="true"
1717
+ [saveOnBlur]="true"
1718
+ [editLabel]="inlineEditLabel()"
1719
+ [saveLabel]="saveInlineEditLabel()"
1720
+ [cancelLabel]="cancelInlineEditLabel()"
1721
+ (valueChange)="setEditingValue($event)"
1722
+ (editCommit)="commitCellEdit(row, col)"
1723
+ (editCancel)="cancelCellEdit()"
1724
+ />
1725
+ } @else if (col.cellTemplate) {
1383
1726
  <ng-container
1384
1727
  [ngTemplateOutlet]="col.cellTemplate"
1385
1728
  [ngTemplateOutletContext]="{ $implicit: row, row: row, column: col }"
@@ -1472,6 +1815,7 @@ class NeuTableComponent {
1472
1815
  </td>
1473
1816
  </tr>
1474
1817
  }
1818
+ }
1475
1819
  }
1476
1820
  @if (_virtualScrollActive() && _virtualBottomSpacerHeight() > 0) {
1477
1821
  <tr class="neu-table__spacer-row" aria-hidden="true">
@@ -1496,7 +1840,7 @@ class NeuTableComponent {
1496
1840
  @if (showRowNumbers()) {
1497
1841
  <td class="neu-table__td"></td>
1498
1842
  }
1499
- @for (col of columns(); track col.key) {
1843
+ @for (col of visibleColumns(); track col.key) {
1500
1844
  <td
1501
1845
  class="neu-table__td neu-table__td--footer"
1502
1846
  [style.width]="columnWidth(col)"
@@ -1586,7 +1930,7 @@ class NeuTableComponent {
1586
1930
  </div>
1587
1931
  }
1588
1932
  </div>
1589
- `, isInline: true, styles: [".neu-table-container{background:var(--neu-surface);overflow:hidden;box-shadow:var(--neu-shadow-sm)}.neu-table-container--bordered{border:1px solid var(--neu-border)}.neu-table-container--rounded{border-radius:var(--neu-radius-lg)}.neu-table-container--striped .neu-table__row:not(.neu-table__row--selected):nth-child(2n){background:color-mix(in srgb,var(--neu-surface-2) 70%,transparent)}.neu-table__toolbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);background:var(--neu-surface)}.neu-table__toolbar-extra{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__title{font-size:var(--neu-text-base);font-weight:600;color:var(--neu-text);margin:0;letter-spacing:-.01em}.neu-table__search-group{display:flex;align-items:center;gap:var(--neu-space-3);flex:1;max-width:420px;min-width:0}.neu-table__search-wrapper{position:relative;display:flex;align-items:center;flex:1;min-width:0}.neu-table__search-icon{position:absolute;left:var(--neu-space-3);width:15px;height:15px;color:var(--neu-text-muted);pointer-events:none;flex-shrink:0}.neu-table__search{width:100%;height:36px;padding:0 var(--neu-space-3) 0 36px;border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface-2);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__search::placeholder{color:var(--neu-text-muted)}.neu-table__search:focus{border-color:var(--neu-primary);box-shadow:var(--neu-focus-ring);background:var(--neu-surface)}.neu-table__search::-webkit-search-cancel-button{display:none}.neu-table__search-clear{position:absolute;right:var(--neu-space-2);display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:color var(--neu-transition),background-color var(--neu-transition)}.neu-table__search-clear svg{width:13px;height:13px}.neu-table__search-clear:hover{color:var(--neu-error);background:var(--neu-error-bg)}.neu-table__exact-label{display:inline-flex;align-items:center;gap:6px;font-size:var(--neu-text-sm);color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none}.neu-table__exact-label:hover{color:var(--neu-text)}.neu-table__exact-checkbox{width:14px;height:14px;accent-color:var(--neu-primary);cursor:pointer}.neu-table__scroll-container{position:relative;isolation:isolate;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--neu-surface-3) transparent}.neu-table__scroll-container::-webkit-scrollbar{height:4px}.neu-table__scroll-container::-webkit-scrollbar-track{background:transparent}.neu-table__scroll-container::-webkit-scrollbar-thumb{background:var(--neu-surface-3);border-radius:99px}@media(max-width:399px){.neu-table__scroll-container{background-image:linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,rgba(15,23,42,.08),transparent),linear-gradient(to left,rgba(15,23,42,.08),transparent);background-position:left center,right center,left center,right center;background-repeat:no-repeat;background-color:var(--neu-surface);background-size:20px 100%,20px 100%,10px 100%,10px 100%;background-attachment:local,local,scroll,scroll}}.neu-table__scroll-container--virtual{overflow-y:auto}.neu-table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--neu-text-sm);min-width:400px}.neu-table--sticky-header .neu-table__scroll-container{overflow-y:auto;max-height:var(--neu-table-max-height, 480px)}.neu-table--sticky-header .neu-table__head tr:first-child .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:inset 0 -1px 0 var(--neu-border)}.neu-table--sticky-header .neu-table__th--filter,.neu-table--sticky-header .neu-table__th--filter-placeholder{position:sticky;top:var(--neu-table-header-height, 44px);z-index:1;background:var(--neu-surface-2)}.neu-table--scrollable .neu-table__scroll-container{max-height:480px;overflow-y:auto}.neu-table--scrollable .neu-table__head .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:0 1px 0 var(--neu-border)}.neu-table__head{background:var(--neu-surface-2)}.neu-table__th{position:relative;padding:var(--neu-space-3) var(--neu-space-4);font-size:var(--neu-text-xs);font-weight:600;color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%);text-transform:uppercase;letter-spacing:.06em;border-bottom:1px solid var(--neu-border);white-space:nowrap;-webkit-user-select:none;user-select:none;background-clip:padding-box}.neu-table__th--check{width:40px;text-align:center!important;padding:var(--neu-space-3) var(--neu-space-3)}.neu-table__th--sortable{cursor:pointer;transition:color var(--neu-transition)}.neu-table__th--sortable:hover{color:var(--neu-text)}.neu-table__th--sorted-asc,.neu-table__th--sorted-desc{color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__resize-handle{position:absolute;top:0;right:-4px;width:12px;height:100%;padding:0;border:0;background:transparent;cursor:col-resize;touch-action:none;opacity:1}.neu-table__resize-handle:after{content:\"\";position:absolute;top:10px;bottom:10px;left:50%;width:2px;border-radius:999px;transform:translate(-50%);background:color-mix(in srgb,var(--neu-primary) 26%,var(--neu-border) 74%);box-shadow:0 0 0 1px color-mix(in srgb,var(--neu-surface) 55%,transparent 45%);opacity:1;transition:background var(--neu-transition)}.neu-table__resize-handle:focus-visible{outline:none}.neu-table__resize-handle:focus-visible:after,.neu-table__resize-handle:hover:after{background:color-mix(in srgb,var(--neu-primary) 62%,var(--neu-border) 38%)}.neu-table__sort-icon{margin-left:4px;font-style:normal;font-size:10px;opacity:.5}.neu-table__th--sorted-asc .neu-table__sort-icon,.neu-table__th--sorted-desc .neu-table__sort-icon{opacity:1}.neu-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--neu-primary)}.neu-table__selection-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--neu-space-3);flex-wrap:wrap;padding:var(--neu-space-2) var(--neu-space-5);background:var(--neu-primary-50);border-bottom:1px solid var(--neu-primary-100);font-size:var(--neu-text-sm);color:var(--neu-primary);font-weight:500;animation:neu-tab-fade .15s ease}.neu-table__selection-main{display:flex;align-items:center;gap:var(--neu-space-3);flex-wrap:wrap}.neu-table__selection-actions{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__selection-clear{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;text-decoration:underline;text-underline-offset:2px;padding:0;font-family:var(--neu-font-sans)}.neu-table__row{transition:background-color var(--neu-transition)}.neu-table__row:hover{background:var(--neu-surface-2)}.neu-table__row:not(:last-child) .neu-table__td{border-bottom:1px solid var(--neu-border)}.neu-table__row--selected{background:var(--neu-primary-50)!important}.neu-table__row--selected .neu-table__td{color:var(--neu-primary)}.neu-table__row--clickable{cursor:pointer}.neu-table__td{padding:var(--neu-space-3) var(--neu-space-4);color:var(--neu-text);line-height:1.5;vertical-align:middle;background-clip:padding-box}.neu-table__td--center{text-align:center}.neu-table__td--empty{padding:var(--neu-space-8) 0}.neu-table__spacer-row{pointer-events:none}.neu-table__spacer-cell{padding:0!important;border:0!important;line-height:0}.neu-table__skeleton-rows{display:flex;flex-direction:column;gap:1px}.neu-table__skeleton-row{display:flex;align-items:center;padding:var(--neu-space-3) var(--neu-space-4);gap:var(--neu-space-4);border-bottom:1px solid var(--neu-border)}.neu-table__skeleton-cell{height:14px;flex:1;border-radius:var(--neu-radius-sm);background:linear-gradient(90deg,var(--neu-surface-2) 0%,var(--neu-surface-3) 50%,var(--neu-surface-2) 100%);background-size:200% 100%;animation:neu-skeleton 1.4s ease infinite}.neu-table__skeleton-cell:first-child{max-width:60px}.neu-table__skeleton-cell:nth-child(2){max-width:160px}.neu-table__skeleton-cell:last-child{max-width:80px}@keyframes neu-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}.neu-table__empty{display:flex;flex-direction:column;align-items:center;gap:var(--neu-space-3);padding:var(--neu-space-8) var(--neu-space-4);color:var(--neu-text-muted)}.neu-table__empty svg{width:40px;height:40px;opacity:.4}.neu-table__empty p{font-size:var(--neu-text-sm);margin:0}.neu-table__clear-filter{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:2px}.neu-table__clear-filter:hover{color:var(--neu-primary-dark)}.neu-table__footer{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-3) var(--neu-space-5);border-top:1px solid var(--neu-border);background:var(--neu-surface-2)}.neu-table__info{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__pagination{display:flex;align-items:center;gap:2px}.neu-table__page-btn{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 var(--neu-space-2);border:1px solid transparent;border-radius:var(--neu-radius);background:transparent;font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);font-weight:500;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition)}.neu-table__page-btn svg{width:14px;height:14px}.neu-table__page-btn:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text);border-color:var(--neu-border)}.neu-table__page-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__page-btn--active{background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));border-color:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)))}.neu-table__page-btn--active:hover{background:var(--neu-primary-solid-hover, var(--neu-primary-dark));border-color:var(--neu-primary-solid-hover, var(--neu-primary-dark))}.neu-table__export-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--neu-transition);flex-shrink:0}.neu-table__export-btn svg{flex-shrink:0}.neu-table__export-btn:hover{color:var(--neu-primary);border-color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__export-btn:disabled{opacity:.45;cursor:not-allowed}.neu-table__export-btn--selection{height:30px;font-size:var(--neu-text-xs);padding:0 var(--neu-space-2)}.neu-table__export-btn--primary{color:var(--neu-primary);border-color:var(--neu-primary-200);background:var(--neu-surface)}.neu-table__export-btn--danger{color:var(--neu-error);border-color:color-mix(in srgb,var(--neu-error) 24%,var(--neu-border) 76%)}.neu-table__export-btn--danger:hover:not(:disabled){background:var(--neu-error-bg);border-color:color-mix(in srgb,var(--neu-error) 40%,var(--neu-border) 60%);color:var(--neu-error)}.neu-table__page-size{display:flex;align-items:center;gap:var(--neu-space-2);min-width:0}.neu-table__page-size-label{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__page-size-select{display:block;min-width:78px}.neu-table__page-size-select .neu-select__trigger{min-width:78px}@supports selector(:has(*)){.neu-table-container:has(.neu-table__page-size .neu-select--open){overflow:visible}.neu-table__footer:has(.neu-table__page-size .neu-select--open){position:relative;z-index:4}}.neu-table__th--expand-col,.neu-table__td--expand-col{width:36px;padding:var(--neu-space-2) var(--neu-space-2);text-align:center}.neu-table__expand-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:all var(--neu-transition);padding:0}.neu-table__expand-btn svg{width:14px;height:14px;transition:transform .2s ease}.neu-table__expand-btn:hover{color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__expand-btn--open svg{transform:rotate(90deg)}.neu-table__row-expand-detail{background:var(--neu-surface-2)}.neu-table__td--expand-panel{padding:0}.neu-table__expand-content{padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);animation:neu-tab-fade .18s ease}.neu-table__cell-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:var(--neu-radius-full);font-size:var(--neu-text-xs);font-weight:600;letter-spacing:.02em;white-space:nowrap}.neu-table__cell-badge--primary{background:var(--neu-primary-100);color:var(--neu-primary-dark)}.neu-table__cell-badge--success{background:var(--neu-table-badge-success-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-success) 22%)}.neu-table__cell-badge--warning{background:var(--neu-table-badge-warning-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-warning) 22%)}.neu-table__cell-badge--danger{background:var(--neu-table-badge-danger-bg);color:color-mix(in srgb,var(--neu-text) 74%,var(--neu-error) 26%)}.neu-table__cell-badge--info{background:var(--neu-primary-50);color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__cell-badge--default{background:var(--neu-surface-3);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}@keyframes neu-tab-fade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-table__host--compact .neu-table__th,.neu-table__host--compact .neu-table__td{padding:var(--neu-table-density-compact-padding, 4px 8px)}.neu-table__host--relaxed .neu-table__th,.neu-table__host--relaxed .neu-table__td{padding:var(--neu-table-density-relaxed-padding, 16px 20px)}.neu-table__th--rn,.neu-table__td--rn{width:44px;text-align:right;padding-right:var(--neu-space-4);color:var(--neu-text-muted);font-variant-numeric:tabular-nums;font-size:var(--neu-text-xs)}.neu-table__th--frozen-left,.neu-table__th--frozen-right{position:sticky;z-index:3;background:var(--neu-surface-2);background-clip:border-box}.neu-table__th--frozen-left{left:0}.neu-table__th--frozen-right{right:0}.neu-table__th--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__th--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__td--frozen-left,.neu-table__td--frozen-right{position:sticky;z-index:2;background:var(--neu-surface);background-clip:border-box}.neu-table__td--frozen-left{left:0}.neu-table__td--frozen-right{right:0}.neu-table__td--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__td--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__foot{background:var(--neu-surface-2)}.neu-table__footer-row .neu-table__td--footer{padding:var(--neu-space-3) var(--neu-space-4);font-weight:600;font-size:var(--neu-text-sm);border-top:2px solid var(--neu-border);color:var(--neu-text)}.neu-table__sort-priority{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));font-size:9px;font-weight:700;margin-right:2px}.neu-table__cell-link{color:var(--neu-primary);text-decoration:none;text-underline-offset:2px}.neu-table__cell-link:hover{text-decoration:underline}.neu-table__actions{display:flex;align-items:center;gap:var(--neu-space-1);flex-wrap:nowrap}.neu-table__action-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:var(--neu-radius-sm);background:transparent;font-size:14px;cursor:pointer;transition:all var(--neu-transition);color:var(--neu-text-muted)}.neu-table__action-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__action-btn--ghost:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text)}.neu-table__action-btn--primary{background:var(--neu-primary-50);color:var(--neu-primary)}.neu-table__action-btn--primary:hover:not(:disabled){background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg))}.neu-table__action-btn--danger{color:var(--neu-error)}.neu-table__action-btn--danger:hover:not(:disabled){background:var(--neu-error-bg)}.neu-table__action-icon{line-height:1}.neu-table__action-confirm{display:inline-flex;align-items:center;gap:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);white-space:nowrap}.neu-table__action-confirm .neu-table__action-btn{width:auto;padding:0 var(--neu-space-2);font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);font-weight:500;border:1px solid var(--neu-border)}.neu-table__export-group{display:flex;align-items:center;gap:var(--neu-space-2);flex-shrink:0}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.neu-table__filter-row .neu-table__th--filter,.neu-table__filter-row .neu-table__th--filter-placeholder{padding:var(--neu-space-2) var(--neu-space-3);background:var(--neu-surface-2);border-bottom:2px solid var(--neu-border);font-weight:400;text-transform:none;letter-spacing:0;vertical-align:middle}.neu-table__col-filter-input,.neu-table__col-filter-select{display:block;width:100%;height:28px;padding:0 var(--neu-space-2);border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);color:var(--neu-text);font-weight:400;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__col-filter-input::placeholder,.neu-table__col-filter-select::placeholder{color:var(--neu-text-muted)}.neu-table__col-filter-input:focus,.neu-table__col-filter-select:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1a;background:var(--neu-surface)}.neu-table__col-filter-select{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: NeuInputComponent, selector: "neu-input", inputs: ["type", "label", "placeholder", "floatingLabel", "size", "hint", "errorMessage", "disabled", "autocomplete", "startIcon", "endIcon", "icon", "iconPosition", "inputId", "name", "required", "readonly", "maxlength", "minlength", "min", "max", "pattern"] }, { kind: "component", type: NeuSelectComponent, selector: "neu-select", inputs: ["options", "label", "placeholder", "errorMessage", "hint", "disabled", "floatingLabel", "size", "searchable", "searchPlaceholder", "clearable", "virtualScroll", "virtualScrollVisibleItems", "noResultsMessage", "clearAriaLabel", "urlParam"], outputs: ["selectionChange"] }, { kind: "component", type: NeuDateInputComponent, selector: "neu-date-input", inputs: ["type", "label", "hint", "errorMessage", "disabled", "size", "readonly", "name", "inputId", "required", "min", "max", "step", "locale", "placeholder", "dateFormat", "floatingLabel"], outputs: ["rangeChange"] }, { kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1933
+ `, isInline: true, styles: [".neu-table-container{background:var(--neu-surface);overflow:hidden;box-shadow:var(--neu-shadow-sm)}.neu-table-container--bordered{border:1px solid var(--neu-border)}.neu-table-container--rounded{border-radius:var(--neu-radius-lg)}.neu-table-container--striped .neu-table__row:not(.neu-table__row--selected):nth-child(2n){background:color-mix(in srgb,var(--neu-surface-2) 70%,transparent)}.neu-table__toolbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);background:var(--neu-surface)}.neu-table__toolbar-extra{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__title{font-size:var(--neu-text-base);font-weight:600;color:var(--neu-text);margin:0;letter-spacing:-.01em}.neu-table__search-group{display:flex;align-items:center;gap:var(--neu-space-3);flex:1;max-width:420px;min-width:min(100%,240px)}.neu-table__search-wrapper{position:relative;display:flex;align-items:center;flex:1;min-width:0}.neu-table__search-icon{position:absolute;left:var(--neu-space-3);width:15px;height:15px;color:var(--neu-text-muted);pointer-events:none;flex-shrink:0}.neu-table__search{width:100%;height:36px;padding:0 var(--neu-space-3) 0 36px;border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface-2);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__search::placeholder{color:var(--neu-text-muted)}.neu-table__search:focus{border-color:var(--neu-primary);box-shadow:var(--neu-focus-ring);background:var(--neu-surface)}.neu-table__search::-webkit-search-cancel-button{display:none}.neu-table__search-clear{position:absolute;right:var(--neu-space-2);display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:color var(--neu-transition),background-color var(--neu-transition)}.neu-table__search-clear svg{width:13px;height:13px}.neu-table__search-clear:hover{color:var(--neu-error);background:var(--neu-error-bg)}.neu-table__exact-label{display:inline-flex;align-items:center;gap:6px;font-size:var(--neu-text-sm);color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none}.neu-table__exact-label:hover{color:var(--neu-text)}.neu-table__exact-checkbox .neu-checkbox{gap:6px}.neu-table__exact-checkbox .neu-checkbox__box{width:14px;height:14px}.neu-table__exact-checkbox .neu-checkbox__label{color:var(--neu-text-muted);line-height:1}.neu-table__scroll-container{position:relative;isolation:isolate;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--neu-surface-3) transparent}.neu-table__scroll-container::-webkit-scrollbar{height:6px}.neu-table__scroll-container::-webkit-scrollbar-track{background:transparent}.neu-table__scroll-container::-webkit-scrollbar-thumb{background:var(--neu-surface-3);border-radius:99px}@media(max-width:399px){.neu-table__scroll-container{background-image:linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,rgba(15,23,42,.08),transparent),linear-gradient(to left,rgba(15,23,42,.08),transparent);background-position:left center,right center,left center,right center;background-repeat:no-repeat;background-color:var(--neu-surface);background-size:20px 100%,20px 100%,10px 100%,10px 100%;background-attachment:local,local,scroll,scroll}}.neu-table__scroll-container--virtual{overflow-y:auto}.neu-table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--neu-text-sm);min-width:400px}.neu-table--sticky-header .neu-table__scroll-container{overflow-y:auto;max-height:var(--neu-table-max-height, 480px)}.neu-table--sticky-header .neu-table__head tr:first-child .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:inset 0 -1px 0 var(--neu-border)}.neu-table--sticky-header .neu-table__th--filter,.neu-table--sticky-header .neu-table__th--filter-placeholder{position:sticky;top:var(--neu-table-header-height, 44px);z-index:1;background:var(--neu-surface-2)}.neu-table--scrollable .neu-table__scroll-container{max-height:480px;overflow-y:auto}.neu-table--scrollable .neu-table__head .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:0 1px 0 var(--neu-border)}.neu-table__head{background:var(--neu-surface-2)}.neu-table__th{position:relative;padding:.7rem var(--neu-space-4);font-size:var(--neu-text-xs);font-weight:600;color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%);text-transform:uppercase;letter-spacing:.06em;border-bottom:1px solid var(--neu-border);white-space:nowrap;-webkit-user-select:none;user-select:none;background-clip:padding-box}.neu-table__th--check{width:40px;text-align:center!important;padding:var(--neu-space-3) var(--neu-space-3)}.neu-table__th--sortable{cursor:pointer;transition:color var(--neu-transition)}.neu-table__th--sortable:hover{color:var(--neu-text)}.neu-table__th--sorted-asc,.neu-table__th--sorted-desc{color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__resize-handle{position:absolute;top:0;right:-4px;width:12px;height:100%;padding:0;border:0;background:transparent;cursor:col-resize;touch-action:none;opacity:1}.neu-table__resize-handle:after{content:\"\";position:absolute;top:10px;bottom:10px;left:50%;width:2px;border-radius:999px;transform:translate(-50%);background:color-mix(in srgb,var(--neu-primary) 26%,var(--neu-border) 74%);box-shadow:0 0 0 1px color-mix(in srgb,var(--neu-surface) 55%,transparent 45%);opacity:1;transition:background var(--neu-transition)}.neu-table__resize-handle:focus-visible{outline:none}.neu-table__resize-handle:focus-visible:after,.neu-table__resize-handle:hover:after{background:color-mix(in srgb,var(--neu-primary) 62%,var(--neu-border) 38%)}.neu-table__sort-icon{margin-left:4px;font-style:normal;font-size:10px;opacity:.5}.neu-table__th--sorted-asc .neu-table__sort-icon,.neu-table__th--sorted-desc .neu-table__sort-icon{opacity:1}.neu-table__checkbox{display:inline-flex;align-items:center;justify-content:center}.neu-table__checkbox .neu-checkbox{gap:0}.neu-table__checkbox .neu-checkbox__box{width:16px;height:16px}.neu-table__selection-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--neu-space-3);flex-wrap:wrap;padding:var(--neu-space-2) var(--neu-space-5);background:var(--neu-primary-50);border-bottom:1px solid var(--neu-primary-100);font-size:var(--neu-text-sm);color:var(--neu-primary);font-weight:500;animation:neu-tab-fade .15s ease}.neu-table__selection-main{display:flex;align-items:center;gap:var(--neu-space-3);flex-wrap:wrap}.neu-table__selection-actions{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__selection-clear{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;text-decoration:underline;text-underline-offset:2px;padding:0;font-family:var(--neu-font-sans)}.neu-table__row{transition:background-color var(--neu-transition)}.neu-table__row:hover{background:var(--neu-surface-2)}.neu-table__row:not(:last-child) .neu-table__td{border-bottom:1px solid var(--neu-border)}.neu-table__row--selected{background:var(--neu-primary-50)!important}.neu-table__row--selected .neu-table__td{color:var(--neu-primary)}.neu-table__row--clickable{cursor:pointer}.neu-table__td{padding:.75rem var(--neu-space-4);color:var(--neu-text);line-height:1.5;vertical-align:middle;background-clip:padding-box}.neu-table__td--center{text-align:center}.neu-table__td--empty{padding:var(--neu-space-8) 0}.neu-table__spacer-row{pointer-events:none}.neu-table__spacer-cell{padding:0!important;border:0!important;line-height:0}.neu-table__skeleton-rows{display:flex;flex-direction:column;gap:1px}.neu-table__skeleton-row{display:flex;align-items:center;padding:var(--neu-space-3) var(--neu-space-4);gap:var(--neu-space-4);border-bottom:1px solid var(--neu-border)}.neu-table__skeleton-cell{height:14px;flex:1;border-radius:var(--neu-radius-sm);background:linear-gradient(90deg,var(--neu-surface-2) 0%,var(--neu-surface-3) 50%,var(--neu-surface-2) 100%);background-size:200% 100%;animation:neu-skeleton 1.4s ease infinite}.neu-table__skeleton-cell:first-child{max-width:60px}.neu-table__skeleton-cell:nth-child(2){max-width:160px}.neu-table__skeleton-cell:last-child{max-width:80px}@keyframes neu-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}.neu-table__empty{display:flex;flex-direction:column;align-items:center;gap:var(--neu-space-3);padding:var(--neu-space-8) var(--neu-space-4);color:var(--neu-text-muted)}.neu-table__empty svg{width:40px;height:40px;opacity:.4}.neu-table__empty p{font-size:var(--neu-text-sm);margin:0}.neu-table__clear-filter{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:2px}.neu-table__clear-filter:hover{color:var(--neu-primary-dark)}.neu-table__footer{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-3) var(--neu-space-5);border-top:1px solid var(--neu-border);background:var(--neu-surface-2)}.neu-table__info{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__pagination{display:flex;align-items:center;gap:2px}.neu-table__page-btn{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 var(--neu-space-2);border:1px solid transparent;border-radius:var(--neu-radius);background:transparent;font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);font-weight:500;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition)}.neu-table__page-btn svg{width:14px;height:14px}.neu-table__page-btn:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text);border-color:var(--neu-border)}.neu-table__page-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__page-btn--active{background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));border-color:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)))}.neu-table__page-btn--active:hover{background:var(--neu-primary-solid-hover, var(--neu-primary-dark));border-color:var(--neu-primary-solid-hover, var(--neu-primary-dark))}.neu-table__export-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--neu-transition);flex-shrink:0}.neu-table__export-btn svg{flex-shrink:0}.neu-table__export-btn:hover{color:var(--neu-primary);border-color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__export-btn:disabled{opacity:.45;cursor:not-allowed}.neu-table__export-btn--selection{height:30px;font-size:var(--neu-text-xs);padding:0 var(--neu-space-2)}.neu-table__export-btn--primary{color:var(--neu-primary);border-color:var(--neu-primary-200);background:var(--neu-surface)}.neu-table__export-btn--danger{color:var(--neu-error);border-color:color-mix(in srgb,var(--neu-error) 24%,var(--neu-border) 76%)}.neu-table__export-btn--danger:hover:not(:disabled){background:var(--neu-error-bg);border-color:color-mix(in srgb,var(--neu-error) 40%,var(--neu-border) 60%);color:var(--neu-error)}[data-theme=dark] .neu-table__th{color:#c8d1da}[data-theme=dark] .neu-table__th--sorted-asc,[data-theme=dark] .neu-table__th--sorted-desc{color:#9ecbff}[data-theme=dark] .neu-table__export-btn{background:var(--neu-surface);border-color:var(--neu-border-hover);color:#c8d1da}[data-theme=dark] .neu-table__export-btn--primary{color:#9ecbff}.neu-table__page-size{display:flex;align-items:center;gap:var(--neu-space-2);min-width:0}.neu-table__page-size-label{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__page-size-select{display:block;min-width:78px}.neu-table__page-size-select .neu-select__trigger{min-width:78px}@supports selector(:has(*)){.neu-table-container:has(.neu-table__page-size .neu-select--open){overflow:visible}.neu-table__footer:has(.neu-table__page-size .neu-select--open){position:relative;z-index:4}}.neu-table__th--expand-col,.neu-table__td--expand-col{width:36px;padding:var(--neu-space-2) var(--neu-space-2);text-align:center}.neu-table__expand-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:all var(--neu-transition);padding:0}.neu-table__expand-btn svg{width:14px;height:14px;transition:transform .2s ease}.neu-table__expand-btn:hover{color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__expand-btn--open svg{transform:rotate(90deg)}.neu-table__row-expand-detail{background:var(--neu-surface-2)}.neu-table__td--expand-panel{padding:0}.neu-table__expand-content{padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);animation:neu-tab-fade .18s ease}.neu-table__cell-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:var(--neu-radius-full);font-size:var(--neu-text-xs);font-weight:600;letter-spacing:.02em;white-space:nowrap}.neu-table__cell-badge--primary{background:var(--neu-primary-100);color:var(--neu-primary-dark)}.neu-table__cell-badge--success{background:var(--neu-table-badge-success-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-success) 22%)}.neu-table__cell-badge--warning{background:var(--neu-table-badge-warning-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-warning) 22%)}.neu-table__cell-badge--danger{background:var(--neu-table-badge-danger-bg);color:color-mix(in srgb,var(--neu-text) 74%,var(--neu-error) 26%)}.neu-table__cell-badge--info{background:var(--neu-primary-50);color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__cell-badge--default{background:var(--neu-surface-3);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}@keyframes neu-tab-fade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-table__host--compact .neu-table__th,.neu-table__host--compact .neu-table__td{padding:var(--neu-table-density-compact-padding, 4px 8px)}.neu-table__host--relaxed .neu-table__th,.neu-table__host--relaxed .neu-table__td{padding:var(--neu-table-density-relaxed-padding, 16px 20px)}.neu-table__th--rn,.neu-table__td--rn{width:44px;text-align:right;padding-right:var(--neu-space-4);color:var(--neu-text-muted);font-variant-numeric:tabular-nums;font-size:var(--neu-text-xs)}.neu-table__th--frozen-left,.neu-table__th--frozen-right{position:sticky;z-index:3;background:var(--neu-surface-2);background-clip:border-box}.neu-table__th--frozen-left{left:0}.neu-table__th--frozen-right{right:0}.neu-table__th--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__th--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__td--frozen-left,.neu-table__td--frozen-right{position:sticky;z-index:2;background:var(--neu-surface);background-clip:border-box}.neu-table__td--frozen-left{left:0}.neu-table__td--frozen-right{right:0}.neu-table__td--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__td--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__foot{background:var(--neu-surface-2)}.neu-table__footer-row .neu-table__td--footer{padding:var(--neu-space-3) var(--neu-space-4);font-weight:600;font-size:var(--neu-text-sm);border-top:2px solid var(--neu-border);color:var(--neu-text)}.neu-table__sort-priority{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));font-size:9px;font-weight:700;margin-right:2px}.neu-table__cell-link{color:var(--neu-primary);text-decoration:none;text-underline-offset:2px}.neu-table__cell-link:hover{text-decoration:underline}.neu-table__actions{display:flex;align-items:center;justify-content:center;gap:var(--neu-space-1);flex-wrap:nowrap}.neu-table__action-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:var(--neu-radius-sm);background:transparent;font-size:14px;cursor:pointer;transition:all var(--neu-transition);color:var(--neu-text-muted)}.neu-table__action-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__action-btn--ghost:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text)}.neu-table__action-btn--primary{background:var(--neu-primary-50);color:var(--neu-primary)}.neu-table__action-btn--primary:hover:not(:disabled){background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg))}.neu-table__action-btn--danger{color:var(--neu-error)}.neu-table__action-btn--danger:hover:not(:disabled){background:var(--neu-error-bg)}.neu-table__action-icon{line-height:1}.neu-table__action-confirm{display:inline-flex;align-items:center;gap:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);white-space:nowrap}.neu-table__action-confirm .neu-table__action-btn{width:auto;padding:0 var(--neu-space-2);font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);font-weight:500;border:1px solid var(--neu-border)}.neu-table__export-group{display:flex;align-items:center;gap:var(--neu-space-2);flex-shrink:0}.neu-table__column-chooser{position:relative;flex-shrink:0}.neu-table__column-chooser-panel{position:absolute;top:calc(100% + var(--neu-space-2));right:0;z-index:20;display:grid;gap:var(--neu-space-2);min-width:180px;padding:var(--neu-space-3);border:1px solid var(--neu-border);border-radius:var(--neu-radius-md);background:var(--neu-surface);box-shadow:var(--neu-shadow-lg)}.neu-table__column-chooser-item{display:flex;align-items:center;gap:var(--neu-space-2);font-size:var(--neu-text-sm);color:var(--neu-text);cursor:pointer}.neu-table__column-chooser-item .neu-checkbox__label{font-size:var(--neu-text-sm);color:var(--neu-text);line-height:1.25}.neu-table__reorder-controls{display:inline-flex;align-items:center;gap:2px;margin-right:var(--neu-space-2);vertical-align:middle}.neu-table__reorder-btn{width:20px;height:20px;border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-surface);color:var(--neu-text-muted);cursor:pointer}.neu-table__reorder-btn:disabled{cursor:not-allowed;opacity:.45}.neu-table__group-row .neu-table__td--group{background:var(--neu-surface-2);color:var(--neu-text);font-weight:700}.neu-table__group-count{color:var(--neu-text-muted);font-weight:500}.neu-table__edit-control{width:100%;min-width:96px;height:30px;padding:0 var(--neu-space-2);border:1px solid var(--neu-primary);border-radius:var(--neu-radius-sm);background:var(--neu-surface);color:var(--neu-text);font:inherit;outline:none;box-shadow:0 0 0 2px #007aff1f}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.neu-table__filter-row .neu-table__th--filter,.neu-table__filter-row .neu-table__th--filter-placeholder{height:42px;padding:.35rem var(--neu-space-3);background:var(--neu-surface-2);border-bottom:1px solid var(--neu-border);font-weight:400;text-transform:none;letter-spacing:0;vertical-align:middle}.neu-table__filter-row .neu-table__th--filter-placeholder{padding-block:0}.neu-table__filter-row .neu-select,.neu-table__filter-row .neu-date-input-host,.neu-table__filter-row .neu-input-host{display:block;width:100%}.neu-table__filter-row .neu-select__trigger,.neu-table__filter-row .neu-date-input__trigger,.neu-table__filter-row .neu-input__field{min-height:30px;height:30px;border-radius:var(--neu-radius-sm);font-size:var(--neu-text-xs)}.neu-table__filter-row .neu-select__trigger,.neu-table__filter-row .neu-date-input__trigger{padding-inline:var(--neu-space-2)}.neu-table__filter-row .neu-date-input__icon{width:14px;height:14px}.neu-table__col-filter-input,.neu-table__col-filter-select{display:block;width:100%;height:28px;padding:0 var(--neu-space-2);border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);color:var(--neu-text);font-weight:400;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__col-filter-input::placeholder,.neu-table__col-filter-select::placeholder{color:var(--neu-text-muted)}.neu-table__col-filter-input:focus,.neu-table__col-filter-select:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1a;background:var(--neu-surface)}.neu-table__col-filter-select{cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: NeuInputComponent, selector: "neu-input", inputs: ["type", "label", "placeholder", "floatingLabel", "size", "hint", "errorMessage", "disabled", "autocomplete", "startIcon", "endIcon", "icon", "iconPosition", "inputId", "name", "required", "readonly", "maxlength", "minlength", "min", "max", "pattern"] }, { kind: "component", type: NeuSelectComponent, selector: "neu-select", inputs: ["options", "label", "placeholder", "errorMessage", "hint", "disabled", "floatingLabel", "size", "searchable", "searchPlaceholder", "loading", "loadingLabel", "clearable", "virtualScroll", "virtualScrollVisibleItems", "noResultsMessage", "clearAriaLabel", "urlParam"], outputs: ["selectionChange"] }, { kind: "component", type: NeuDateInputComponent, selector: "neu-date-input", inputs: ["type", "label", "hint", "errorMessage", "disabled", "size", "readonly", "name", "inputId", "required", "min", "max", "step", "locale", "disabledDates", "multiple", "showMonthYearPicker", "yearRange", "placeholder", "dateFormat", "floatingLabel", "presets"], outputs: ["rangeChange"] }, { kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }, { kind: "component", type: NeuCheckboxComponent, selector: "neu-checkbox", inputs: ["label", "name", "disabled", "checked", "indeterminate", "ariaLabel"], outputs: ["checkedChange"] }, { kind: "component", type: NeuInlineEditorComponent, selector: "neu-inline-editor", inputs: ["value", "type", "size", "options", "placeholder", "emptyLabel", "editLabel", "saveLabel", "cancelLabel", "disabled", "readonly", "startInEdit", "saveOnBlur", "min", "max", "step", "rows"], outputs: ["valueChange", "editStart", "editCancel", "editCommit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1590
1934
  }
1591
1935
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuTableComponent, decorators: [{
1592
1936
  type: Component,
@@ -1597,6 +1941,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1597
1941
  NeuSelectComponent,
1598
1942
  NeuDateInputComponent,
1599
1943
  NeuIconComponent,
1944
+ NeuCheckboxComponent,
1945
+ NeuInlineEditorComponent,
1600
1946
  ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
1601
1947
  '[class.neu-table__host]': 'true',
1602
1948
  '[class.neu-table__host--compact]': 'density() === "compact"',
@@ -1610,14 +1956,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1610
1956
  [class.neu-table-container--striped]="stripedRows()"
1611
1957
  >
1612
1958
  <!-- ---- Toolbar ---- -->
1613
- @if (searchable() || title() || exportable() || toolbarExtraRef()) {
1959
+ @if (searchable() || title() || exportable() || _toolbarTemplateRef()) {
1614
1960
  <div class="neu-table__toolbar">
1615
1961
  @if (title()) {
1616
1962
  <h3 class="neu-table__title">{{ title() }}</h3>
1617
1963
  }
1618
- @if (toolbarExtraRef()) {
1964
+ @if (_toolbarTemplateRef(); as toolbarTpl) {
1619
1965
  <div class="neu-table__toolbar-extra">
1620
- <ng-container [ngTemplateOutlet]="toolbarExtraRef()!" />
1966
+ <ng-container [ngTemplateOutlet]="toolbarTpl" />
1621
1967
  </div>
1622
1968
  }
1623
1969
  @if (searchable()) {
@@ -1666,15 +2012,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1666
2012
  }
1667
2013
  </div>
1668
2014
  @if (exactMatchable()) {
1669
- <label class="neu-table__exact-label">
1670
- <input
2015
+ <neu-checkbox
1671
2016
  class="neu-table__exact-checkbox"
1672
- type="checkbox"
1673
2017
  [checked]="exactMatch()"
1674
- (change)="setExactMatch($any($event.target).checked)"
2018
+ [label]="exactMatchLabel()"
2019
+ (checkedChange)="setExactMatch($event)"
1675
2020
  />
1676
- {{ exactMatchLabel() }}
1677
- </label>
2021
+ }
2022
+ </div>
2023
+ }
2024
+ @if (columnChooser()) {
2025
+ <div class="neu-table__column-chooser">
2026
+ <button
2027
+ class="neu-table__export-btn"
2028
+ type="button"
2029
+ [attr.aria-expanded]="columnChooserOpen()"
2030
+ (click)="toggleColumnChooser()"
2031
+ >
2032
+ {{ columnChooserLabel() }}
2033
+ </button>
2034
+ @if (columnChooserOpen()) {
2035
+ <div class="neu-table__column-chooser-panel" role="menu">
2036
+ @for (col of orderedColumns(); track col.key) {
2037
+ <div class="neu-table__column-chooser-item">
2038
+ <neu-checkbox
2039
+ class="neu-table__column-chooser-checkbox"
2040
+ [checked]="isColumnVisible(col.key)"
2041
+ [label]="col.header"
2042
+ (checkedChange)="toggleColumnVisibility(col.key)"
2043
+ />
2044
+ </div>
2045
+ }
2046
+ </div>
1678
2047
  }
1679
2048
  </div>
1680
2049
  }
@@ -1730,6 +2099,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1730
2099
  JSON
1731
2100
  </button>
1732
2101
  }
2102
+ @if (exportFormats().includes('xlsx')) {
2103
+ <button
2104
+ class="neu-table__export-btn"
2105
+ type="button"
2106
+ (click)="exportXlsx()"
2107
+ [title]="exportXlsxTitle()"
2108
+ >
2109
+ <svg
2110
+ viewBox="0 0 24 24"
2111
+ fill="none"
2112
+ stroke="currentColor"
2113
+ stroke-width="2"
2114
+ stroke-linecap="round"
2115
+ stroke-linejoin="round"
2116
+ aria-hidden="true"
2117
+ width="15"
2118
+ height="15"
2119
+ >
2120
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
2121
+ <polyline points="7 10 12 15 17 10" />
2122
+ <line x1="12" y1="15" x2="12" y2="3" />
2123
+ </svg>
2124
+ XLSX
2125
+ </button>
2126
+ }
1733
2127
  </div>
1734
2128
  }
1735
2129
  </div>
@@ -1810,20 +2204,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1810
2204
  }
1811
2205
  @if (selectable()) {
1812
2206
  <th class="neu-table__th neu-table__th--check" scope="col">
1813
- <input
1814
- type="checkbox"
2207
+ <neu-checkbox
1815
2208
  class="neu-table__checkbox"
1816
2209
  [checked]="isAllFilteredSelected()"
1817
2210
  [indeterminate]="isSomeFilteredSelected()"
1818
- (change)="toggleAll()"
1819
- [attr.aria-label]="selectAllAriaLabel()"
2211
+ [ariaLabel]="selectAllAriaLabel()"
2212
+ (checkedChange)="toggleAll()"
1820
2213
  />
1821
2214
  </th>
1822
2215
  }
1823
2216
  @if (showRowNumbers()) {
1824
2217
  <th class="neu-table__th neu-table__th--rn" scope="col">#</th>
1825
2218
  }
1826
- @for (col of columns(); track col.key) {
2219
+ @for (col of visibleColumns(); track col.key) {
1827
2220
  <th
1828
2221
  class="neu-table__th"
1829
2222
  [class.neu-table__th--sortable]="sortable() && col.sortable !== false"
@@ -1848,6 +2241,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1848
2241
  scope="col"
1849
2242
  (click)="sortable() && col.sortable !== false ? sortBy(col.key, $event) : null"
1850
2243
  >
2244
+ @if (reorderableColumns()) {
2245
+ <span class="neu-table__reorder-controls" (click)="$event.stopPropagation()">
2246
+ <button
2247
+ type="button"
2248
+ class="neu-table__reorder-btn"
2249
+ [disabled]="isFirstVisibleColumn(col.key)"
2250
+ [attr.aria-label]="'Move ' + col.header + ' left'"
2251
+ (click)="moveColumn(col.key, -1)"
2252
+ >
2253
+
2254
+ </button>
2255
+ <button
2256
+ type="button"
2257
+ class="neu-table__reorder-btn"
2258
+ [disabled]="isLastVisibleColumn(col.key)"
2259
+ [attr.aria-label]="'Move ' + col.header + ' right'"
2260
+ (click)="moveColumn(col.key, 1)"
2261
+ >
2262
+
2263
+ </button>
2264
+ </span>
2265
+ }
1851
2266
  @if (col.headerTemplate) {
1852
2267
  <ng-container
1853
2268
  [ngTemplateOutlet]="col.headerTemplate"
@@ -1899,7 +2314,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1899
2314
  @if (showRowNumbers()) {
1900
2315
  <th class="neu-table__th neu-table__th--filter-placeholder" scope="col"></th>
1901
2316
  }
1902
- @for (col of columns(); track col.key) {
2317
+ @for (col of visibleColumns(); track col.key) {
1903
2318
  <th
1904
2319
  class="neu-table__th neu-table__th--filter"
1905
2320
  scope="col"
@@ -1918,6 +2333,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1918
2333
  } @else if (col.filterType === 'date') {
1919
2334
  <neu-date-input
1920
2335
  [formControl]="columnFilterControl(col.key)"
2336
+ [placeholder]="filterPlaceholder()"
1921
2337
  [attr.aria-label]="filterAriaPrefix() + ' ' + col.header"
1922
2338
  />
1923
2339
  } @else {
@@ -1942,7 +2358,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1942
2358
  <div class="neu-table__skeleton-rows">
1943
2359
  @for (_ of skeletonRows(); track $index) {
1944
2360
  <div class="neu-table__skeleton-row">
1945
- @for (__ of columns(); track $index) {
2361
+ @for (__ of visibleColumns(); track $index) {
1946
2362
  <div class="neu-table__skeleton-cell"></div>
1947
2363
  }
1948
2364
  </div>
@@ -1992,7 +2408,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
1992
2408
  ></td>
1993
2409
  </tr>
1994
2410
  }
1995
- @for (row of visiblePageRows(); track getRowKey(row); let rowIdx = $index) {
2411
+ @for (entry of visiblePageEntries(); track entry.key; let entryIdx = $index) {
2412
+ @if (entry.kind === 'group') {
2413
+ <tr class="neu-table__group-row">
2414
+ <td [attr.colspan]="totalColspan()" class="neu-table__td neu-table__td--group">
2415
+ {{ groupHeaderLabel() }} {{ entry.label }}
2416
+ <span class="neu-table__group-count">({{ entry.count }})</span>
2417
+ </td>
2418
+ </tr>
2419
+ } @else {
2420
+ @let row = entry.row;
1996
2421
  <tr
1997
2422
  class="neu-table__row"
1998
2423
  [class]="getRowClass(row)"
@@ -2032,21 +2457,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2032
2457
  class="neu-table__td neu-table__th--check"
2033
2458
  (click)="$event.stopPropagation()"
2034
2459
  >
2035
- <input
2036
- type="checkbox"
2460
+ <neu-checkbox
2037
2461
  class="neu-table__checkbox"
2038
2462
  [checked]="isRowSelected(row)"
2039
- (change)="toggleRow(row)"
2040
- [attr.aria-label]="selectRowAriaLabel()"
2463
+ [ariaLabel]="selectRowAriaLabel()"
2464
+ (checkedChange)="toggleRow(row)"
2041
2465
  />
2042
2466
  </td>
2043
2467
  }
2044
2468
  @if (showRowNumbers()) {
2045
2469
  <td class="neu-table__td neu-table__td--rn">
2046
- {{ visibleRowNumber(rowIdx) }}
2470
+ {{ visibleRowNumber(entry.rowIndex) }}
2047
2471
  </td>
2048
2472
  }
2049
- @for (col of columns(); track col.key) {
2473
+ @for (col of visibleColumns(); track col.key) {
2050
2474
  <td
2051
2475
  class="neu-table__td"
2052
2476
  [class]="col.cellClass ?? ''"
@@ -2065,8 +2489,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2065
2489
  [style.min-width]="columnWidth(col)"
2066
2490
  [style.max-width]="columnWidth(col)"
2067
2491
  [style.text-align]="col.align ?? 'left'"
2492
+ (dblclick)="startCellEdit(row, col, $event)"
2068
2493
  >
2069
- @if (col.cellTemplate) {
2494
+ @if (isEditingCell(row, col)) {
2495
+ <neu-inline-editor
2496
+ class="neu-table__edit-control"
2497
+ [type]="inlineEditorType(col)"
2498
+ [value]="$any(editingValue())"
2499
+ [options]="inlineEditorOptions(col)"
2500
+ [startInEdit]="true"
2501
+ [saveOnBlur]="true"
2502
+ [editLabel]="inlineEditLabel()"
2503
+ [saveLabel]="saveInlineEditLabel()"
2504
+ [cancelLabel]="cancelInlineEditLabel()"
2505
+ (valueChange)="setEditingValue($event)"
2506
+ (editCommit)="commitCellEdit(row, col)"
2507
+ (editCancel)="cancelCellEdit()"
2508
+ />
2509
+ } @else if (col.cellTemplate) {
2070
2510
  <ng-container
2071
2511
  [ngTemplateOutlet]="col.cellTemplate"
2072
2512
  [ngTemplateOutletContext]="{ $implicit: row, row: row, column: col }"
@@ -2159,6 +2599,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2159
2599
  </td>
2160
2600
  </tr>
2161
2601
  }
2602
+ }
2162
2603
  }
2163
2604
  @if (_virtualScrollActive() && _virtualBottomSpacerHeight() > 0) {
2164
2605
  <tr class="neu-table__spacer-row" aria-hidden="true">
@@ -2183,7 +2624,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2183
2624
  @if (showRowNumbers()) {
2184
2625
  <td class="neu-table__td"></td>
2185
2626
  }
2186
- @for (col of columns(); track col.key) {
2627
+ @for (col of visibleColumns(); track col.key) {
2187
2628
  <td
2188
2629
  class="neu-table__td neu-table__td--footer"
2189
2630
  [style.width]="columnWidth(col)"
@@ -2273,12 +2714,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
2273
2714
  </div>
2274
2715
  }
2275
2716
  </div>
2276
- `, styles: [".neu-table-container{background:var(--neu-surface);overflow:hidden;box-shadow:var(--neu-shadow-sm)}.neu-table-container--bordered{border:1px solid var(--neu-border)}.neu-table-container--rounded{border-radius:var(--neu-radius-lg)}.neu-table-container--striped .neu-table__row:not(.neu-table__row--selected):nth-child(2n){background:color-mix(in srgb,var(--neu-surface-2) 70%,transparent)}.neu-table__toolbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);background:var(--neu-surface)}.neu-table__toolbar-extra{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__title{font-size:var(--neu-text-base);font-weight:600;color:var(--neu-text);margin:0;letter-spacing:-.01em}.neu-table__search-group{display:flex;align-items:center;gap:var(--neu-space-3);flex:1;max-width:420px;min-width:0}.neu-table__search-wrapper{position:relative;display:flex;align-items:center;flex:1;min-width:0}.neu-table__search-icon{position:absolute;left:var(--neu-space-3);width:15px;height:15px;color:var(--neu-text-muted);pointer-events:none;flex-shrink:0}.neu-table__search{width:100%;height:36px;padding:0 var(--neu-space-3) 0 36px;border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface-2);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__search::placeholder{color:var(--neu-text-muted)}.neu-table__search:focus{border-color:var(--neu-primary);box-shadow:var(--neu-focus-ring);background:var(--neu-surface)}.neu-table__search::-webkit-search-cancel-button{display:none}.neu-table__search-clear{position:absolute;right:var(--neu-space-2);display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:color var(--neu-transition),background-color var(--neu-transition)}.neu-table__search-clear svg{width:13px;height:13px}.neu-table__search-clear:hover{color:var(--neu-error);background:var(--neu-error-bg)}.neu-table__exact-label{display:inline-flex;align-items:center;gap:6px;font-size:var(--neu-text-sm);color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none}.neu-table__exact-label:hover{color:var(--neu-text)}.neu-table__exact-checkbox{width:14px;height:14px;accent-color:var(--neu-primary);cursor:pointer}.neu-table__scroll-container{position:relative;isolation:isolate;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--neu-surface-3) transparent}.neu-table__scroll-container::-webkit-scrollbar{height:4px}.neu-table__scroll-container::-webkit-scrollbar-track{background:transparent}.neu-table__scroll-container::-webkit-scrollbar-thumb{background:var(--neu-surface-3);border-radius:99px}@media(max-width:399px){.neu-table__scroll-container{background-image:linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,rgba(15,23,42,.08),transparent),linear-gradient(to left,rgba(15,23,42,.08),transparent);background-position:left center,right center,left center,right center;background-repeat:no-repeat;background-color:var(--neu-surface);background-size:20px 100%,20px 100%,10px 100%,10px 100%;background-attachment:local,local,scroll,scroll}}.neu-table__scroll-container--virtual{overflow-y:auto}.neu-table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--neu-text-sm);min-width:400px}.neu-table--sticky-header .neu-table__scroll-container{overflow-y:auto;max-height:var(--neu-table-max-height, 480px)}.neu-table--sticky-header .neu-table__head tr:first-child .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:inset 0 -1px 0 var(--neu-border)}.neu-table--sticky-header .neu-table__th--filter,.neu-table--sticky-header .neu-table__th--filter-placeholder{position:sticky;top:var(--neu-table-header-height, 44px);z-index:1;background:var(--neu-surface-2)}.neu-table--scrollable .neu-table__scroll-container{max-height:480px;overflow-y:auto}.neu-table--scrollable .neu-table__head .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:0 1px 0 var(--neu-border)}.neu-table__head{background:var(--neu-surface-2)}.neu-table__th{position:relative;padding:var(--neu-space-3) var(--neu-space-4);font-size:var(--neu-text-xs);font-weight:600;color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%);text-transform:uppercase;letter-spacing:.06em;border-bottom:1px solid var(--neu-border);white-space:nowrap;-webkit-user-select:none;user-select:none;background-clip:padding-box}.neu-table__th--check{width:40px;text-align:center!important;padding:var(--neu-space-3) var(--neu-space-3)}.neu-table__th--sortable{cursor:pointer;transition:color var(--neu-transition)}.neu-table__th--sortable:hover{color:var(--neu-text)}.neu-table__th--sorted-asc,.neu-table__th--sorted-desc{color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__resize-handle{position:absolute;top:0;right:-4px;width:12px;height:100%;padding:0;border:0;background:transparent;cursor:col-resize;touch-action:none;opacity:1}.neu-table__resize-handle:after{content:\"\";position:absolute;top:10px;bottom:10px;left:50%;width:2px;border-radius:999px;transform:translate(-50%);background:color-mix(in srgb,var(--neu-primary) 26%,var(--neu-border) 74%);box-shadow:0 0 0 1px color-mix(in srgb,var(--neu-surface) 55%,transparent 45%);opacity:1;transition:background var(--neu-transition)}.neu-table__resize-handle:focus-visible{outline:none}.neu-table__resize-handle:focus-visible:after,.neu-table__resize-handle:hover:after{background:color-mix(in srgb,var(--neu-primary) 62%,var(--neu-border) 38%)}.neu-table__sort-icon{margin-left:4px;font-style:normal;font-size:10px;opacity:.5}.neu-table__th--sorted-asc .neu-table__sort-icon,.neu-table__th--sorted-desc .neu-table__sort-icon{opacity:1}.neu-table__checkbox{width:16px;height:16px;cursor:pointer;accent-color:var(--neu-primary)}.neu-table__selection-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--neu-space-3);flex-wrap:wrap;padding:var(--neu-space-2) var(--neu-space-5);background:var(--neu-primary-50);border-bottom:1px solid var(--neu-primary-100);font-size:var(--neu-text-sm);color:var(--neu-primary);font-weight:500;animation:neu-tab-fade .15s ease}.neu-table__selection-main{display:flex;align-items:center;gap:var(--neu-space-3);flex-wrap:wrap}.neu-table__selection-actions{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__selection-clear{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;text-decoration:underline;text-underline-offset:2px;padding:0;font-family:var(--neu-font-sans)}.neu-table__row{transition:background-color var(--neu-transition)}.neu-table__row:hover{background:var(--neu-surface-2)}.neu-table__row:not(:last-child) .neu-table__td{border-bottom:1px solid var(--neu-border)}.neu-table__row--selected{background:var(--neu-primary-50)!important}.neu-table__row--selected .neu-table__td{color:var(--neu-primary)}.neu-table__row--clickable{cursor:pointer}.neu-table__td{padding:var(--neu-space-3) var(--neu-space-4);color:var(--neu-text);line-height:1.5;vertical-align:middle;background-clip:padding-box}.neu-table__td--center{text-align:center}.neu-table__td--empty{padding:var(--neu-space-8) 0}.neu-table__spacer-row{pointer-events:none}.neu-table__spacer-cell{padding:0!important;border:0!important;line-height:0}.neu-table__skeleton-rows{display:flex;flex-direction:column;gap:1px}.neu-table__skeleton-row{display:flex;align-items:center;padding:var(--neu-space-3) var(--neu-space-4);gap:var(--neu-space-4);border-bottom:1px solid var(--neu-border)}.neu-table__skeleton-cell{height:14px;flex:1;border-radius:var(--neu-radius-sm);background:linear-gradient(90deg,var(--neu-surface-2) 0%,var(--neu-surface-3) 50%,var(--neu-surface-2) 100%);background-size:200% 100%;animation:neu-skeleton 1.4s ease infinite}.neu-table__skeleton-cell:first-child{max-width:60px}.neu-table__skeleton-cell:nth-child(2){max-width:160px}.neu-table__skeleton-cell:last-child{max-width:80px}@keyframes neu-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}.neu-table__empty{display:flex;flex-direction:column;align-items:center;gap:var(--neu-space-3);padding:var(--neu-space-8) var(--neu-space-4);color:var(--neu-text-muted)}.neu-table__empty svg{width:40px;height:40px;opacity:.4}.neu-table__empty p{font-size:var(--neu-text-sm);margin:0}.neu-table__clear-filter{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:2px}.neu-table__clear-filter:hover{color:var(--neu-primary-dark)}.neu-table__footer{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-3) var(--neu-space-5);border-top:1px solid var(--neu-border);background:var(--neu-surface-2)}.neu-table__info{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__pagination{display:flex;align-items:center;gap:2px}.neu-table__page-btn{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 var(--neu-space-2);border:1px solid transparent;border-radius:var(--neu-radius);background:transparent;font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);font-weight:500;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition)}.neu-table__page-btn svg{width:14px;height:14px}.neu-table__page-btn:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text);border-color:var(--neu-border)}.neu-table__page-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__page-btn--active{background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));border-color:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)))}.neu-table__page-btn--active:hover{background:var(--neu-primary-solid-hover, var(--neu-primary-dark));border-color:var(--neu-primary-solid-hover, var(--neu-primary-dark))}.neu-table__export-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--neu-transition);flex-shrink:0}.neu-table__export-btn svg{flex-shrink:0}.neu-table__export-btn:hover{color:var(--neu-primary);border-color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__export-btn:disabled{opacity:.45;cursor:not-allowed}.neu-table__export-btn--selection{height:30px;font-size:var(--neu-text-xs);padding:0 var(--neu-space-2)}.neu-table__export-btn--primary{color:var(--neu-primary);border-color:var(--neu-primary-200);background:var(--neu-surface)}.neu-table__export-btn--danger{color:var(--neu-error);border-color:color-mix(in srgb,var(--neu-error) 24%,var(--neu-border) 76%)}.neu-table__export-btn--danger:hover:not(:disabled){background:var(--neu-error-bg);border-color:color-mix(in srgb,var(--neu-error) 40%,var(--neu-border) 60%);color:var(--neu-error)}.neu-table__page-size{display:flex;align-items:center;gap:var(--neu-space-2);min-width:0}.neu-table__page-size-label{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__page-size-select{display:block;min-width:78px}.neu-table__page-size-select .neu-select__trigger{min-width:78px}@supports selector(:has(*)){.neu-table-container:has(.neu-table__page-size .neu-select--open){overflow:visible}.neu-table__footer:has(.neu-table__page-size .neu-select--open){position:relative;z-index:4}}.neu-table__th--expand-col,.neu-table__td--expand-col{width:36px;padding:var(--neu-space-2) var(--neu-space-2);text-align:center}.neu-table__expand-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:all var(--neu-transition);padding:0}.neu-table__expand-btn svg{width:14px;height:14px;transition:transform .2s ease}.neu-table__expand-btn:hover{color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__expand-btn--open svg{transform:rotate(90deg)}.neu-table__row-expand-detail{background:var(--neu-surface-2)}.neu-table__td--expand-panel{padding:0}.neu-table__expand-content{padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);animation:neu-tab-fade .18s ease}.neu-table__cell-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:var(--neu-radius-full);font-size:var(--neu-text-xs);font-weight:600;letter-spacing:.02em;white-space:nowrap}.neu-table__cell-badge--primary{background:var(--neu-primary-100);color:var(--neu-primary-dark)}.neu-table__cell-badge--success{background:var(--neu-table-badge-success-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-success) 22%)}.neu-table__cell-badge--warning{background:var(--neu-table-badge-warning-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-warning) 22%)}.neu-table__cell-badge--danger{background:var(--neu-table-badge-danger-bg);color:color-mix(in srgb,var(--neu-text) 74%,var(--neu-error) 26%)}.neu-table__cell-badge--info{background:var(--neu-primary-50);color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__cell-badge--default{background:var(--neu-surface-3);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}@keyframes neu-tab-fade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-table__host--compact .neu-table__th,.neu-table__host--compact .neu-table__td{padding:var(--neu-table-density-compact-padding, 4px 8px)}.neu-table__host--relaxed .neu-table__th,.neu-table__host--relaxed .neu-table__td{padding:var(--neu-table-density-relaxed-padding, 16px 20px)}.neu-table__th--rn,.neu-table__td--rn{width:44px;text-align:right;padding-right:var(--neu-space-4);color:var(--neu-text-muted);font-variant-numeric:tabular-nums;font-size:var(--neu-text-xs)}.neu-table__th--frozen-left,.neu-table__th--frozen-right{position:sticky;z-index:3;background:var(--neu-surface-2);background-clip:border-box}.neu-table__th--frozen-left{left:0}.neu-table__th--frozen-right{right:0}.neu-table__th--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__th--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__td--frozen-left,.neu-table__td--frozen-right{position:sticky;z-index:2;background:var(--neu-surface);background-clip:border-box}.neu-table__td--frozen-left{left:0}.neu-table__td--frozen-right{right:0}.neu-table__td--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__td--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__foot{background:var(--neu-surface-2)}.neu-table__footer-row .neu-table__td--footer{padding:var(--neu-space-3) var(--neu-space-4);font-weight:600;font-size:var(--neu-text-sm);border-top:2px solid var(--neu-border);color:var(--neu-text)}.neu-table__sort-priority{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));font-size:9px;font-weight:700;margin-right:2px}.neu-table__cell-link{color:var(--neu-primary);text-decoration:none;text-underline-offset:2px}.neu-table__cell-link:hover{text-decoration:underline}.neu-table__actions{display:flex;align-items:center;gap:var(--neu-space-1);flex-wrap:nowrap}.neu-table__action-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:var(--neu-radius-sm);background:transparent;font-size:14px;cursor:pointer;transition:all var(--neu-transition);color:var(--neu-text-muted)}.neu-table__action-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__action-btn--ghost:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text)}.neu-table__action-btn--primary{background:var(--neu-primary-50);color:var(--neu-primary)}.neu-table__action-btn--primary:hover:not(:disabled){background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg))}.neu-table__action-btn--danger{color:var(--neu-error)}.neu-table__action-btn--danger:hover:not(:disabled){background:var(--neu-error-bg)}.neu-table__action-icon{line-height:1}.neu-table__action-confirm{display:inline-flex;align-items:center;gap:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);white-space:nowrap}.neu-table__action-confirm .neu-table__action-btn{width:auto;padding:0 var(--neu-space-2);font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);font-weight:500;border:1px solid var(--neu-border)}.neu-table__export-group{display:flex;align-items:center;gap:var(--neu-space-2);flex-shrink:0}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.neu-table__filter-row .neu-table__th--filter,.neu-table__filter-row .neu-table__th--filter-placeholder{padding:var(--neu-space-2) var(--neu-space-3);background:var(--neu-surface-2);border-bottom:2px solid var(--neu-border);font-weight:400;text-transform:none;letter-spacing:0;vertical-align:middle}.neu-table__col-filter-input,.neu-table__col-filter-select{display:block;width:100%;height:28px;padding:0 var(--neu-space-2);border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);color:var(--neu-text);font-weight:400;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__col-filter-input::placeholder,.neu-table__col-filter-select::placeholder{color:var(--neu-text-muted)}.neu-table__col-filter-input:focus,.neu-table__col-filter-select:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1a;background:var(--neu-surface)}.neu-table__col-filter-select{cursor:pointer}\n"] }]
2277
- }], ctorParameters: () => [], propDecorators: { _scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }], expandTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuTableExpandDirective), { isSignal: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], toolbarExtraRef: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarExtraRef", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], skeletonRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRows", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], exactMatchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exactMatchable", required: false }] }], exactMatchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "exactMatchLabel", required: false }] }], searchAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchAriaLabel", required: false }] }], clearSearchAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearSearchAriaLabel", required: false }] }], clearFilterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearFilterLabel", required: false }] }], previousPageAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousPageAriaLabel", required: false }] }], nextPageAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPageAriaLabel", required: false }] }], pageSizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeLabel", required: false }] }], pageSizeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeAriaLabel", required: false }] }], paginationAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationAriaLabel", required: false }] }], exportCsvTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportCsvTitle", required: false }] }], exportJsonTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportJsonTitle", required: false }] }], clearSelectionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearSelectionLabel", required: false }] }], selectionSummaryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionSummaryLabel", required: false }] }], tableAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableAriaLabel", required: false }] }], selectAllAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllAriaLabel", required: false }] }], selectRowAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectRowAriaLabel", required: false }] }], expandRowAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandRowAriaLabel", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], filterAriaPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterAriaPrefix", required: false }] }], allFilterOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "allFilterOptionLabel", required: false }] }], ofLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ofLabel", required: false }] }], resultLabelSingular: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultLabelSingular", required: false }] }], resultLabelPlural: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultLabelPlural", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], expandMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandMode", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], exportFileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFileName", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], roundedBorders: [{ type: i0.Input, args: [{ isSignal: true, alias: "roundedBorders", required: false }] }], stripedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "stripedRows", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], showRowNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRowNumbers", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], footerRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerRow", required: false }] }], emptyStateTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateTemplate", required: false }] }], serverSide: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSide", required: false }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: false }] }], multiSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSort", required: false }] }], exportFormats: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFormats", required: false }] }], exportColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportColumns", required: false }] }], exportScope: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportScope", required: false }] }], selectionActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionActions", required: false }] }], pageParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageParam", required: false }] }], searchParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchParam", required: false }] }], sortParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortParam", required: false }] }], sortDirParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDirParam", required: false }] }], multiSortParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSortParam", required: false }] }], useUrlState: [{ type: i0.Input, args: [{ isSignal: true, alias: "useUrlState", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowDblClick: [{ type: i0.Output, args: ["rowDblClick"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], selectionActionClick: [{ type: i0.Output, args: ["selectionActionClick"] }], serverStateChange: [{ type: i0.Output, args: ["serverStateChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }] } });
2717
+ `, styles: [".neu-table-container{background:var(--neu-surface);overflow:hidden;box-shadow:var(--neu-shadow-sm)}.neu-table-container--bordered{border:1px solid var(--neu-border)}.neu-table-container--rounded{border-radius:var(--neu-radius-lg)}.neu-table-container--striped .neu-table__row:not(.neu-table__row--selected):nth-child(2n){background:color-mix(in srgb,var(--neu-surface-2) 70%,transparent)}.neu-table__toolbar{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);background:var(--neu-surface)}.neu-table__toolbar-extra{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__title{font-size:var(--neu-text-base);font-weight:600;color:var(--neu-text);margin:0;letter-spacing:-.01em}.neu-table__search-group{display:flex;align-items:center;gap:var(--neu-space-3);flex:1;max-width:420px;min-width:min(100%,240px)}.neu-table__search-wrapper{position:relative;display:flex;align-items:center;flex:1;min-width:0}.neu-table__search-icon{position:absolute;left:var(--neu-space-3);width:15px;height:15px;color:var(--neu-text-muted);pointer-events:none;flex-shrink:0}.neu-table__search{width:100%;height:36px;padding:0 var(--neu-space-3) 0 36px;border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface-2);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__search::placeholder{color:var(--neu-text-muted)}.neu-table__search:focus{border-color:var(--neu-primary);box-shadow:var(--neu-focus-ring);background:var(--neu-surface)}.neu-table__search::-webkit-search-cancel-button{display:none}.neu-table__search-clear{position:absolute;right:var(--neu-space-2);display:flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:color var(--neu-transition),background-color var(--neu-transition)}.neu-table__search-clear svg{width:13px;height:13px}.neu-table__search-clear:hover{color:var(--neu-error);background:var(--neu-error-bg)}.neu-table__exact-label{display:inline-flex;align-items:center;gap:6px;font-size:var(--neu-text-sm);color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none}.neu-table__exact-label:hover{color:var(--neu-text)}.neu-table__exact-checkbox .neu-checkbox{gap:6px}.neu-table__exact-checkbox .neu-checkbox__box{width:14px;height:14px}.neu-table__exact-checkbox .neu-checkbox__label{color:var(--neu-text-muted);line-height:1}.neu-table__scroll-container{position:relative;isolation:isolate;width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:var(--neu-surface-3) transparent}.neu-table__scroll-container::-webkit-scrollbar{height:6px}.neu-table__scroll-container::-webkit-scrollbar-track{background:transparent}.neu-table__scroll-container::-webkit-scrollbar-thumb{background:var(--neu-surface-3);border-radius:99px}@media(max-width:399px){.neu-table__scroll-container{background-image:linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,var(--neu-surface),var(--neu-surface)),linear-gradient(to right,rgba(15,23,42,.08),transparent),linear-gradient(to left,rgba(15,23,42,.08),transparent);background-position:left center,right center,left center,right center;background-repeat:no-repeat;background-color:var(--neu-surface);background-size:20px 100%,20px 100%,10px 100%,10px 100%;background-attachment:local,local,scroll,scroll}}.neu-table__scroll-container--virtual{overflow-y:auto}.neu-table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--neu-text-sm);min-width:400px}.neu-table--sticky-header .neu-table__scroll-container{overflow-y:auto;max-height:var(--neu-table-max-height, 480px)}.neu-table--sticky-header .neu-table__head tr:first-child .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:inset 0 -1px 0 var(--neu-border)}.neu-table--sticky-header .neu-table__th--filter,.neu-table--sticky-header .neu-table__th--filter-placeholder{position:sticky;top:var(--neu-table-header-height, 44px);z-index:1;background:var(--neu-surface-2)}.neu-table--scrollable .neu-table__scroll-container{max-height:480px;overflow-y:auto}.neu-table--scrollable .neu-table__head .neu-table__th{position:sticky;top:0;z-index:2;background:var(--neu-surface-2);box-shadow:0 1px 0 var(--neu-border)}.neu-table__head{background:var(--neu-surface-2)}.neu-table__th{position:relative;padding:.7rem var(--neu-space-4);font-size:var(--neu-text-xs);font-weight:600;color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%);text-transform:uppercase;letter-spacing:.06em;border-bottom:1px solid var(--neu-border);white-space:nowrap;-webkit-user-select:none;user-select:none;background-clip:padding-box}.neu-table__th--check{width:40px;text-align:center!important;padding:var(--neu-space-3) var(--neu-space-3)}.neu-table__th--sortable{cursor:pointer;transition:color var(--neu-transition)}.neu-table__th--sortable:hover{color:var(--neu-text)}.neu-table__th--sorted-asc,.neu-table__th--sorted-desc{color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__resize-handle{position:absolute;top:0;right:-4px;width:12px;height:100%;padding:0;border:0;background:transparent;cursor:col-resize;touch-action:none;opacity:1}.neu-table__resize-handle:after{content:\"\";position:absolute;top:10px;bottom:10px;left:50%;width:2px;border-radius:999px;transform:translate(-50%);background:color-mix(in srgb,var(--neu-primary) 26%,var(--neu-border) 74%);box-shadow:0 0 0 1px color-mix(in srgb,var(--neu-surface) 55%,transparent 45%);opacity:1;transition:background var(--neu-transition)}.neu-table__resize-handle:focus-visible{outline:none}.neu-table__resize-handle:focus-visible:after,.neu-table__resize-handle:hover:after{background:color-mix(in srgb,var(--neu-primary) 62%,var(--neu-border) 38%)}.neu-table__sort-icon{margin-left:4px;font-style:normal;font-size:10px;opacity:.5}.neu-table__th--sorted-asc .neu-table__sort-icon,.neu-table__th--sorted-desc .neu-table__sort-icon{opacity:1}.neu-table__checkbox{display:inline-flex;align-items:center;justify-content:center}.neu-table__checkbox .neu-checkbox{gap:0}.neu-table__checkbox .neu-checkbox__box{width:16px;height:16px}.neu-table__selection-bar{display:flex;align-items:center;justify-content:space-between;gap:var(--neu-space-3);flex-wrap:wrap;padding:var(--neu-space-2) var(--neu-space-5);background:var(--neu-primary-50);border-bottom:1px solid var(--neu-primary-100);font-size:var(--neu-text-sm);color:var(--neu-primary);font-weight:500;animation:neu-tab-fade .15s ease}.neu-table__selection-main{display:flex;align-items:center;gap:var(--neu-space-3);flex-wrap:wrap}.neu-table__selection-actions{display:flex;align-items:center;gap:var(--neu-space-2);flex-wrap:wrap}.neu-table__selection-clear{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;text-decoration:underline;text-underline-offset:2px;padding:0;font-family:var(--neu-font-sans)}.neu-table__row{transition:background-color var(--neu-transition)}.neu-table__row:hover{background:var(--neu-surface-2)}.neu-table__row:not(:last-child) .neu-table__td{border-bottom:1px solid var(--neu-border)}.neu-table__row--selected{background:var(--neu-primary-50)!important}.neu-table__row--selected .neu-table__td{color:var(--neu-primary)}.neu-table__row--clickable{cursor:pointer}.neu-table__td{padding:.75rem var(--neu-space-4);color:var(--neu-text);line-height:1.5;vertical-align:middle;background-clip:padding-box}.neu-table__td--center{text-align:center}.neu-table__td--empty{padding:var(--neu-space-8) 0}.neu-table__spacer-row{pointer-events:none}.neu-table__spacer-cell{padding:0!important;border:0!important;line-height:0}.neu-table__skeleton-rows{display:flex;flex-direction:column;gap:1px}.neu-table__skeleton-row{display:flex;align-items:center;padding:var(--neu-space-3) var(--neu-space-4);gap:var(--neu-space-4);border-bottom:1px solid var(--neu-border)}.neu-table__skeleton-cell{height:14px;flex:1;border-radius:var(--neu-radius-sm);background:linear-gradient(90deg,var(--neu-surface-2) 0%,var(--neu-surface-3) 50%,var(--neu-surface-2) 100%);background-size:200% 100%;animation:neu-skeleton 1.4s ease infinite}.neu-table__skeleton-cell:first-child{max-width:60px}.neu-table__skeleton-cell:nth-child(2){max-width:160px}.neu-table__skeleton-cell:last-child{max-width:80px}@keyframes neu-skeleton{0%{background-position:200% 0}to{background-position:-200% 0}}.neu-table__empty{display:flex;flex-direction:column;align-items:center;gap:var(--neu-space-3);padding:var(--neu-space-8) var(--neu-space-4);color:var(--neu-text-muted)}.neu-table__empty svg{width:40px;height:40px;opacity:.4}.neu-table__empty p{font-size:var(--neu-text-sm);margin:0}.neu-table__clear-filter{background:none;border:none;color:var(--neu-primary);font-size:var(--neu-text-xs);font-weight:500;cursor:pointer;padding:0;text-decoration:underline;text-underline-offset:2px}.neu-table__clear-filter:hover{color:var(--neu-primary-dark)}.neu-table__footer{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:var(--neu-space-3);padding:var(--neu-space-3) var(--neu-space-5);border-top:1px solid var(--neu-border);background:var(--neu-surface-2)}.neu-table__info{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__pagination{display:flex;align-items:center;gap:2px}.neu-table__page-btn{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 var(--neu-space-2);border:1px solid transparent;border-radius:var(--neu-radius);background:transparent;font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);font-weight:500;color:var(--neu-text-muted);cursor:pointer;transition:all var(--neu-transition)}.neu-table__page-btn svg{width:14px;height:14px}.neu-table__page-btn:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text);border-color:var(--neu-border)}.neu-table__page-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__page-btn--active{background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));border-color:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)))}.neu-table__page-btn--active:hover{background:var(--neu-primary-solid-hover, var(--neu-primary-dark));border-color:var(--neu-primary-solid-hover, var(--neu-primary-dark))}.neu-table__export-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;height:36px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);cursor:pointer;white-space:nowrap;transition:all var(--neu-transition);flex-shrink:0}.neu-table__export-btn svg{flex-shrink:0}.neu-table__export-btn:hover{color:var(--neu-primary);border-color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__export-btn:disabled{opacity:.45;cursor:not-allowed}.neu-table__export-btn--selection{height:30px;font-size:var(--neu-text-xs);padding:0 var(--neu-space-2)}.neu-table__export-btn--primary{color:var(--neu-primary);border-color:var(--neu-primary-200);background:var(--neu-surface)}.neu-table__export-btn--danger{color:var(--neu-error);border-color:color-mix(in srgb,var(--neu-error) 24%,var(--neu-border) 76%)}.neu-table__export-btn--danger:hover:not(:disabled){background:var(--neu-error-bg);border-color:color-mix(in srgb,var(--neu-error) 40%,var(--neu-border) 60%);color:var(--neu-error)}[data-theme=dark] .neu-table__th{color:#c8d1da}[data-theme=dark] .neu-table__th--sorted-asc,[data-theme=dark] .neu-table__th--sorted-desc{color:#9ecbff}[data-theme=dark] .neu-table__export-btn{background:var(--neu-surface);border-color:var(--neu-border-hover);color:#c8d1da}[data-theme=dark] .neu-table__export-btn--primary{color:#9ecbff}.neu-table__page-size{display:flex;align-items:center;gap:var(--neu-space-2);min-width:0}.neu-table__page-size-label{font-size:var(--neu-text-xs);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}.neu-table__page-size-select{display:block;min-width:78px}.neu-table__page-size-select .neu-select__trigger{min-width:78px}@supports selector(:has(*)){.neu-table-container:has(.neu-table__page-size .neu-select--open){overflow:visible}.neu-table__footer:has(.neu-table__page-size .neu-select--open){position:relative;z-index:4}}.neu-table__th--expand-col,.neu-table__td--expand-col{width:36px;padding:var(--neu-space-2) var(--neu-space-2);text-align:center}.neu-table__expand-btn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);transition:all var(--neu-transition);padding:0}.neu-table__expand-btn svg{width:14px;height:14px;transition:transform .2s ease}.neu-table__expand-btn:hover{color:var(--neu-primary);background:var(--neu-primary-50)}.neu-table__expand-btn--open svg{transform:rotate(90deg)}.neu-table__row-expand-detail{background:var(--neu-surface-2)}.neu-table__td--expand-panel{padding:0}.neu-table__expand-content{padding:var(--neu-space-4) var(--neu-space-5);border-bottom:1px solid var(--neu-border);animation:neu-tab-fade .18s ease}.neu-table__cell-badge{display:inline-flex;align-items:center;padding:2px 8px;border-radius:var(--neu-radius-full);font-size:var(--neu-text-xs);font-weight:600;letter-spacing:.02em;white-space:nowrap}.neu-table__cell-badge--primary{background:var(--neu-primary-100);color:var(--neu-primary-dark)}.neu-table__cell-badge--success{background:var(--neu-table-badge-success-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-success) 22%)}.neu-table__cell-badge--warning{background:var(--neu-table-badge-warning-bg);color:color-mix(in srgb,var(--neu-text) 78%,var(--neu-warning) 22%)}.neu-table__cell-badge--danger{background:var(--neu-table-badge-danger-bg);color:color-mix(in srgb,var(--neu-text) 74%,var(--neu-error) 26%)}.neu-table__cell-badge--info{background:var(--neu-primary-50);color:var(--neu-primary-dark, var(--neu-primary))}.neu-table__cell-badge--default{background:var(--neu-surface-3);color:color-mix(in srgb,var(--neu-text) 72%,var(--neu-surface) 28%)}@keyframes neu-tab-fade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-table__host--compact .neu-table__th,.neu-table__host--compact .neu-table__td{padding:var(--neu-table-density-compact-padding, 4px 8px)}.neu-table__host--relaxed .neu-table__th,.neu-table__host--relaxed .neu-table__td{padding:var(--neu-table-density-relaxed-padding, 16px 20px)}.neu-table__th--rn,.neu-table__td--rn{width:44px;text-align:right;padding-right:var(--neu-space-4);color:var(--neu-text-muted);font-variant-numeric:tabular-nums;font-size:var(--neu-text-xs)}.neu-table__th--frozen-left,.neu-table__th--frozen-right{position:sticky;z-index:3;background:var(--neu-surface-2);background-clip:border-box}.neu-table__th--frozen-left{left:0}.neu-table__th--frozen-right{right:0}.neu-table__th--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__th--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__td--frozen-left,.neu-table__td--frozen-right{position:sticky;z-index:2;background:var(--neu-surface);background-clip:border-box}.neu-table__td--frozen-left{left:0}.neu-table__td--frozen-right{right:0}.neu-table__td--frozen-left-boundary{box-shadow:inset -1px 0 0 var(--neu-border),6px 0 8px -8px #0f172a29}.neu-table__td--frozen-right-boundary{box-shadow:inset 1px 0 0 var(--neu-border),-6px 0 8px -8px #0f172a29}.neu-table__foot{background:var(--neu-surface-2)}.neu-table__footer-row .neu-table__td--footer{padding:var(--neu-space-3) var(--neu-space-4);font-weight:600;font-size:var(--neu-text-sm);border-top:2px solid var(--neu-border);color:var(--neu-text)}.neu-table__sort-priority{display:inline-flex;align-items:center;justify-content:center;width:14px;height:14px;border-radius:50%;background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg));font-size:9px;font-weight:700;margin-right:2px}.neu-table__cell-link{color:var(--neu-primary);text-decoration:none;text-underline-offset:2px}.neu-table__cell-link:hover{text-decoration:underline}.neu-table__actions{display:flex;align-items:center;justify-content:center;gap:var(--neu-space-1);flex-wrap:nowrap}.neu-table__action-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:var(--neu-radius-sm);background:transparent;font-size:14px;cursor:pointer;transition:all var(--neu-transition);color:var(--neu-text-muted)}.neu-table__action-btn:disabled{opacity:.35;cursor:not-allowed}.neu-table__action-btn--ghost:hover:not(:disabled){background:var(--neu-surface-3);color:var(--neu-text)}.neu-table__action-btn--primary{background:var(--neu-primary-50);color:var(--neu-primary)}.neu-table__action-btn--primary:hover:not(:disabled){background:var(--neu-primary-solid, var(--neu-primary-dark, var(--neu-primary)));color:var(--neu-primary-solid-fg, var(--neu-primary-fg))}.neu-table__action-btn--danger{color:var(--neu-error)}.neu-table__action-btn--danger:hover:not(:disabled){background:var(--neu-error-bg)}.neu-table__action-icon{line-height:1}.neu-table__action-confirm{display:inline-flex;align-items:center;gap:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);white-space:nowrap}.neu-table__action-confirm .neu-table__action-btn{width:auto;padding:0 var(--neu-space-2);font-size:var(--neu-text-xs);font-family:var(--neu-font-sans);font-weight:500;border:1px solid var(--neu-border)}.neu-table__export-group{display:flex;align-items:center;gap:var(--neu-space-2);flex-shrink:0}.neu-table__column-chooser{position:relative;flex-shrink:0}.neu-table__column-chooser-panel{position:absolute;top:calc(100% + var(--neu-space-2));right:0;z-index:20;display:grid;gap:var(--neu-space-2);min-width:180px;padding:var(--neu-space-3);border:1px solid var(--neu-border);border-radius:var(--neu-radius-md);background:var(--neu-surface);box-shadow:var(--neu-shadow-lg)}.neu-table__column-chooser-item{display:flex;align-items:center;gap:var(--neu-space-2);font-size:var(--neu-text-sm);color:var(--neu-text);cursor:pointer}.neu-table__column-chooser-item .neu-checkbox__label{font-size:var(--neu-text-sm);color:var(--neu-text);line-height:1.25}.neu-table__reorder-controls{display:inline-flex;align-items:center;gap:2px;margin-right:var(--neu-space-2);vertical-align:middle}.neu-table__reorder-btn{width:20px;height:20px;border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-surface);color:var(--neu-text-muted);cursor:pointer}.neu-table__reorder-btn:disabled{cursor:not-allowed;opacity:.45}.neu-table__group-row .neu-table__td--group{background:var(--neu-surface-2);color:var(--neu-text);font-weight:700}.neu-table__group-count{color:var(--neu-text-muted);font-weight:500}.neu-table__edit-control{width:100%;min-width:96px;height:30px;padding:0 var(--neu-space-2);border:1px solid var(--neu-primary);border-radius:var(--neu-radius-sm);background:var(--neu-surface);color:var(--neu-text);font:inherit;outline:none;box-shadow:0 0 0 2px #007aff1f}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.neu-table__filter-row .neu-table__th--filter,.neu-table__filter-row .neu-table__th--filter-placeholder{height:42px;padding:.35rem var(--neu-space-3);background:var(--neu-surface-2);border-bottom:1px solid var(--neu-border);font-weight:400;text-transform:none;letter-spacing:0;vertical-align:middle}.neu-table__filter-row .neu-table__th--filter-placeholder{padding-block:0}.neu-table__filter-row .neu-select,.neu-table__filter-row .neu-date-input-host,.neu-table__filter-row .neu-input-host{display:block;width:100%}.neu-table__filter-row .neu-select__trigger,.neu-table__filter-row .neu-date-input__trigger,.neu-table__filter-row .neu-input__field{min-height:30px;height:30px;border-radius:var(--neu-radius-sm);font-size:var(--neu-text-xs)}.neu-table__filter-row .neu-select__trigger,.neu-table__filter-row .neu-date-input__trigger{padding-inline:var(--neu-space-2)}.neu-table__filter-row .neu-date-input__icon{width:14px;height:14px}.neu-table__col-filter-input,.neu-table__col-filter-select{display:block;width:100%;height:28px;padding:0 var(--neu-space-2);border:1px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-surface);font-family:var(--neu-font-sans);font-size:var(--neu-text-xs);color:var(--neu-text);font-weight:400;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-table__col-filter-input::placeholder,.neu-table__col-filter-select::placeholder{color:var(--neu-text-muted)}.neu-table__col-filter-input:focus,.neu-table__col-filter-select:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1a;background:var(--neu-surface)}.neu-table__col-filter-select{cursor:pointer}\n"] }]
2718
+ }], ctorParameters: () => [], propDecorators: { _scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { isSignal: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }], pagination: [{ type: i0.Input, args: [{ isSignal: true, alias: "pagination", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], toolbarExtraRef: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarExtraRef", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], skeletonRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "skeletonRows", required: false }] }], expandTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuTableExpandDirective), { isSignal: true }] }], toolbarTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuTableToolbarDirective), { isSignal: true }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], exactMatchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exactMatchable", required: false }] }], exactMatchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "exactMatchLabel", required: false }] }], searchAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchAriaLabel", required: false }] }], clearSearchAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearSearchAriaLabel", required: false }] }], clearFilterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearFilterLabel", required: false }] }], previousPageAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousPageAriaLabel", required: false }] }], nextPageAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPageAriaLabel", required: false }] }], pageSizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeLabel", required: false }] }], pageSizeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeAriaLabel", required: false }] }], paginationAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "paginationAriaLabel", required: false }] }], exportCsvTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportCsvTitle", required: false }] }], exportJsonTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportJsonTitle", required: false }] }], exportXlsxTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportXlsxTitle", required: false }] }], clearSelectionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearSelectionLabel", required: false }] }], selectionSummaryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionSummaryLabel", required: false }] }], tableAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableAriaLabel", required: false }] }], selectAllAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectAllAriaLabel", required: false }] }], selectRowAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectRowAriaLabel", required: false }] }], expandRowAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandRowAriaLabel", required: false }] }], filterPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceholder", required: false }] }], filterAriaPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterAriaPrefix", required: false }] }], allFilterOptionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "allFilterOptionLabel", required: false }] }], ofLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ofLabel", required: false }] }], resultLabelSingular: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultLabelSingular", required: false }] }], resultLabelPlural: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultLabelPlural", required: false }] }], sortable: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], expandable: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandable", required: false }] }], expandMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandMode", required: false }] }], exportable: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportable", required: false }] }], exportFileName: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFileName", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], stickyHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "stickyHeader", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], resizableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "resizableColumns", required: false }] }], reorderableColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "reorderableColumns", required: false }] }], columnChooser: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnChooser", required: false }] }], columnChooserLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnChooserLabel", required: false }] }], groupBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupBy", required: false }] }], groupHeaderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "groupHeaderLabel", required: false }] }], inlineEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineEdit", required: false }] }], inlineEditLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineEditLabel", required: false }] }], saveInlineEditLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveInlineEditLabel", required: false }] }], cancelInlineEditLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelInlineEditLabel", required: false }] }], initialLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialLayout", required: false }] }], rowKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowKey", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], roundedBorders: [{ type: i0.Input, args: [{ isSignal: true, alias: "roundedBorders", required: false }] }], stripedRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "stripedRows", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], showRowNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "showRowNumbers", required: false }] }], rowClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowClass", required: false }] }], footerRow: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerRow", required: false }] }], emptyStateTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateTemplate", required: false }] }], serverSide: [{ type: i0.Input, args: [{ isSignal: true, alias: "serverSide", required: false }] }], totalItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalItems", required: false }] }], multiSort: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSort", required: false }] }], exportFormats: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportFormats", required: false }] }], exportColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportColumns", required: false }] }], exportScope: [{ type: i0.Input, args: [{ isSignal: true, alias: "exportScope", required: false }] }], selectionActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionActions", required: false }] }], pageParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageParam", required: false }] }], searchParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchParam", required: false }] }], sortParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortParam", required: false }] }], sortDirParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortDirParam", required: false }] }], multiSortParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiSortParam", required: false }] }], useUrlState: [{ type: i0.Input, args: [{ isSignal: true, alias: "useUrlState", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], rowClick: [{ type: i0.Output, args: ["rowClick"] }], rowDblClick: [{ type: i0.Output, args: ["rowDblClick"] }], actionClick: [{ type: i0.Output, args: ["actionClick"] }], selectionActionClick: [{ type: i0.Output, args: ["selectionActionClick"] }], serverStateChange: [{ type: i0.Output, args: ["serverStateChange"] }], searchChange: [{ type: i0.Output, args: ["searchChange"] }], columnResize: [{ type: i0.Output, args: ["columnResize"] }], columnReorder: [{ type: i0.Output, args: ["columnReorder"] }], layoutChange: [{ type: i0.Output, args: ["layoutChange"] }], cellEditCommit: [{ type: i0.Output, args: ["cellEditCommit"] }] } });
2278
2719
 
2279
2720
  /**
2280
2721
  * Generated bundle index. Do not edit.
2281
2722
  */
2282
2723
 
2283
- export { NeuTableComponent, NeuTableExpandDirective };
2724
+ export { NeuTableComponent, NeuTableExpandDirective, NeuTableToolbarDirective };
2284
2725
  //# sourceMappingURL=neural-ui-core-table.mjs.map