@aquera/ngx-smart-table 0.0.36 → 0.0.38

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.
@@ -3886,15 +3886,21 @@ function injectDropdownStyles() {
3886
3886
  nile-select.st-cell-editor::part(combobox) {
3887
3887
  background-color: transparent !important;
3888
3888
  border: solid 1px transparent !important;
3889
+ /* Suppress nile-select's open-state blue inset ring (box-shadow: 0 0 0 1px
3890
+ border-brand inset) so it does not show a second border inside the table
3891
+ cell's own focus outline. */
3892
+ box-shadow: none !important;
3889
3893
  margin: 0px !important;
3890
3894
  max-height: 28px;
3891
3895
  }
3892
3896
  nile-select.st-cell-editor::part(combobox):hover {
3893
3897
  border: solid 1px transparent !important;
3898
+ box-shadow: none !important;
3894
3899
  }
3895
3900
  .st-cell-editor::part(combobox) {
3896
3901
  background-color: transparent !important;
3897
3902
  border: solid 1px transparent !important;
3903
+ box-shadow: none !important;
3898
3904
  margin: 0px !important;
3899
3905
  max-height: 28px;
3900
3906
  }
@@ -8711,6 +8717,12 @@ class StHeaderComponent {
8711
8717
  * Whether filtering is enabled globally
8712
8718
  */
8713
8719
  this.enableFiltering = true;
8720
+ /**
8721
+ * When keyboard navigation is enabled the column-action button is reached with the
8722
+ * arrow keys (focusHeader) rather than Tab, so it is removed from the tab order
8723
+ * (tabindex -1). Without keyboard nav it stays a normal tab stop.
8724
+ */
8725
+ this.keyboardNavigationEnabled = false;
8714
8726
  /**
8715
8727
  * Emits column sort event when sort is toggled
8716
8728
  */
@@ -8873,11 +8885,11 @@ class StHeaderComponent {
8873
8885
  this.columnMoved.emit(moveEvent);
8874
8886
  }
8875
8887
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8876
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StHeaderComponent, isStandalone: true, selector: "st-header", inputs: { column: "column", columnIndex: "columnIndex", isFirstColumn: "isFirstColumn", isLastColumn: "isLastColumn", tableState: "tableState", enableSorting: "enableSorting", enableFiltering: "enableFiltering" }, outputs: { sortToggle: "sortToggle", filterChange: "filterChange", columnMoved: "columnMoved", menuClick: "menuClick", tabOut: "tabOut", headerNavigate: "headerNavigate", menuKeyboard: "menuKeyboard" }, ngImport: i0, template: "<div class=\"st-header\" [class.sortable]=\"isSortable()\" [class.sorted]=\"isSorted()\"\n tabindex=\"-1\"\n (keydown)=\"onHeaderKeyDown($event)\">\n <div class=\"header-content\">\n <span class=\"header-text\">{{ column.header || column.key }}</span>\n @if (isMenuEnabled()) {\n <button class=\"column-menu-trigger\"\n (click)=\"onMenuClick($event)\"\n (keydown)=\"onMenuTriggerKeyDown($event)\"\n type=\"button\"\n aria-label=\"Column actions\">\n <nile-icon name=\"options\"></nile-icon>\n </button>\n }\n </div>\n</div>\n", styles: [".st-header{position:relative;text-align:left;padding-left:8px}.st-header.sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .2s}.st-header.resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}.st-header.align-center{text-align:center}.st-header.align-center .header-content{justify-content:center}.st-header.align-right{text-align:right}.st-header.align-right .header-content{justify-content:flex-end}.st-header .header-content{display:flex;align-items:center;gap:8px}.st-header .header-text{flex:1;font-size:12px;font-weight:var(--ng-font-weight-medium);letter-spacing:.2px;line-height:14px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.st-header .column-menu-trigger{background:none;border:none;padding:4px;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center}.st-header .column-menu-trigger nile-icon{font-size:16px;pointer-events:none}.st-header .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:10}.st-header .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-header .resize-handle:hover:after,.st-header .resize-handle:active:after{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
8888
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StHeaderComponent, isStandalone: true, selector: "st-header", inputs: { column: "column", columnIndex: "columnIndex", isFirstColumn: "isFirstColumn", isLastColumn: "isLastColumn", tableState: "tableState", enableSorting: "enableSorting", enableFiltering: "enableFiltering", keyboardNavigationEnabled: "keyboardNavigationEnabled" }, outputs: { sortToggle: "sortToggle", filterChange: "filterChange", columnMoved: "columnMoved", menuClick: "menuClick", tabOut: "tabOut", headerNavigate: "headerNavigate", menuKeyboard: "menuKeyboard" }, ngImport: i0, template: "<div class=\"st-header\" [class.sortable]=\"isSortable()\" [class.sorted]=\"isSorted()\"\n tabindex=\"-1\"\n (keydown)=\"onHeaderKeyDown($event)\">\n <div class=\"header-content\">\n <span class=\"header-text\">{{ column.header || column.key }}</span>\n @if (isMenuEnabled()) {\n <button class=\"column-menu-trigger\"\n [attr.tabindex]=\"keyboardNavigationEnabled ? -1 : null\"\n (click)=\"onMenuClick($event)\"\n (keydown)=\"onMenuTriggerKeyDown($event)\"\n type=\"button\"\n aria-label=\"Column actions\">\n <nile-icon name=\"options\"></nile-icon>\n </button>\n }\n </div>\n</div>\n", styles: [".st-header{position:relative;text-align:left;padding-left:8px}.st-header.sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .2s}.st-header.resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}.st-header.align-center{text-align:center}.st-header.align-center .header-content{justify-content:center}.st-header.align-right{text-align:right}.st-header.align-right .header-content{justify-content:flex-end}.st-header .header-content{display:flex;align-items:center;gap:8px}.st-header .header-text{flex:1;font-size:12px;font-weight:var(--ng-font-weight-medium);letter-spacing:.2px;line-height:14px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.st-header .column-menu-trigger{background:none;border:none;padding:4px;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center}.st-header .column-menu-trigger nile-icon{font-size:16px;pointer-events:none}.st-header .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:10}.st-header .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-header .resize-handle:hover:after,.st-header .resize-handle:active:after{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
8877
8889
  }
8878
8890
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StHeaderComponent, decorators: [{
8879
8891
  type: Component,
8880
- args: [{ selector: 'st-header', standalone: true, imports: [CommonModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"st-header\" [class.sortable]=\"isSortable()\" [class.sorted]=\"isSorted()\"\n tabindex=\"-1\"\n (keydown)=\"onHeaderKeyDown($event)\">\n <div class=\"header-content\">\n <span class=\"header-text\">{{ column.header || column.key }}</span>\n @if (isMenuEnabled()) {\n <button class=\"column-menu-trigger\"\n (click)=\"onMenuClick($event)\"\n (keydown)=\"onMenuTriggerKeyDown($event)\"\n type=\"button\"\n aria-label=\"Column actions\">\n <nile-icon name=\"options\"></nile-icon>\n </button>\n }\n </div>\n</div>\n", styles: [".st-header{position:relative;text-align:left;padding-left:8px}.st-header.sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .2s}.st-header.resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}.st-header.align-center{text-align:center}.st-header.align-center .header-content{justify-content:center}.st-header.align-right{text-align:right}.st-header.align-right .header-content{justify-content:flex-end}.st-header .header-content{display:flex;align-items:center;gap:8px}.st-header .header-text{flex:1;font-size:12px;font-weight:var(--ng-font-weight-medium);letter-spacing:.2px;line-height:14px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.st-header .column-menu-trigger{background:none;border:none;padding:4px;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center}.st-header .column-menu-trigger nile-icon{font-size:16px;pointer-events:none}.st-header .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:10}.st-header .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-header .resize-handle:hover:after,.st-header .resize-handle:active:after{opacity:1}\n"] }]
8892
+ args: [{ selector: 'st-header', standalone: true, imports: [CommonModule], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"st-header\" [class.sortable]=\"isSortable()\" [class.sorted]=\"isSorted()\"\n tabindex=\"-1\"\n (keydown)=\"onHeaderKeyDown($event)\">\n <div class=\"header-content\">\n <span class=\"header-text\">{{ column.header || column.key }}</span>\n @if (isMenuEnabled()) {\n <button class=\"column-menu-trigger\"\n [attr.tabindex]=\"keyboardNavigationEnabled ? -1 : null\"\n (click)=\"onMenuClick($event)\"\n (keydown)=\"onMenuTriggerKeyDown($event)\"\n type=\"button\"\n aria-label=\"Column actions\">\n <nile-icon name=\"options\"></nile-icon>\n </button>\n }\n </div>\n</div>\n", styles: [".st-header{position:relative;text-align:left;padding-left:8px}.st-header.sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .2s}.st-header.resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}.st-header.align-center{text-align:center}.st-header.align-center .header-content{justify-content:center}.st-header.align-right{text-align:right}.st-header.align-right .header-content{justify-content:flex-end}.st-header .header-content{display:flex;align-items:center;gap:8px}.st-header .header-text{flex:1;font-size:12px;font-weight:var(--ng-font-weight-medium);letter-spacing:.2px;line-height:14px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.st-header .column-menu-trigger{background:none;border:none;padding:4px;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center}.st-header .column-menu-trigger nile-icon{font-size:16px;pointer-events:none}.st-header .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:10}.st-header .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-header .resize-handle:hover:after,.st-header .resize-handle:active:after{opacity:1}\n"] }]
8881
8893
  }], propDecorators: { column: [{
8882
8894
  type: Input
8883
8895
  }], columnIndex: [{
@@ -8892,6 +8904,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
8892
8904
  type: Input
8893
8905
  }], enableFiltering: [{
8894
8906
  type: Input
8907
+ }], keyboardNavigationEnabled: [{
8908
+ type: Input
8895
8909
  }], sortToggle: [{
8896
8910
  type: Output
8897
8911
  }], filterChange: [{
@@ -9750,15 +9764,27 @@ class StRowActionsDropdownComponent {
9750
9764
  }
9751
9765
  }
9752
9766
  /**
9753
- * Space closes the dropdown (focus is on a menu item after open, so the trigger
9754
- * button's keydown never fires handle it here at the document level instead).
9767
+ * Enter / Space activate the currently focused menu item. The items are
9768
+ * <nile-menu-item> elements, not native <button>s, so a key press never
9769
+ * produces a synthetic click — without this, keyboard users can open the
9770
+ * dropdown and arrow between items but cannot invoke an action. (Focus is on
9771
+ * a menu item after open, so the trigger button's own keydown never fires;
9772
+ * we handle it at the document level instead.)
9755
9773
  */
9756
- onSpaceKey(event) {
9757
- if (this.isOpen) {
9758
- event.preventDefault();
9759
- event.stopPropagation();
9760
- this.closed.emit();
9761
- }
9774
+ onActivateKey(event) {
9775
+ if (!this.isOpen)
9776
+ return;
9777
+ const panel = this.dropdownPanel?.nativeElement;
9778
+ const active = document.activeElement;
9779
+ if (!panel || !active || !panel.contains(active))
9780
+ return;
9781
+ const items = Array.from(panel.querySelectorAll('nile-menu-item'));
9782
+ const index = items.indexOf(active);
9783
+ if (index < 0 || index >= this.visibleActions.length)
9784
+ return;
9785
+ event.preventDefault();
9786
+ event.stopPropagation();
9787
+ this.onActionClick(this.visibleActions[index]);
9762
9788
  }
9763
9789
  /**
9764
9790
  * Tab / Shift+Tab: close the dropdown AND tell the parent to move focus
@@ -9778,7 +9804,7 @@ class StRowActionsDropdownComponent {
9778
9804
  event.stopPropagation();
9779
9805
  }
9780
9806
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StRowActionsDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9781
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StRowActionsDropdownComponent, isStandalone: true, selector: "st-row-actions-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed", tabbed: "tabbed" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)", "document:keydown.space": "onSpaceKey($event)", "document:keydown.tab": "onTabKey($event)", "document:keydown.shift.tab": "onTabKey($event)" } }, viewQueries: [{ propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isOpen && context) {\n <div class=\"dropdown-container\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" role=\"presentation\" (click)=\"closed.emit()\"></div>\n\n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" role=\"dialog\" aria-label=\"Row actions\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n @if (isOpen) {\n <nile-menu>\n @for (action of visibleActions; track action.id) {\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n @if (action.icon) {\n <nile-icon size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n \n @if (visibleActions.length === 0) {\n <nile-menu-item>No actions available</nile-menu-item>\n }\n </nile-menu>\n }\n </div>\n </div>\n}\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:transparent;pointer-events:auto;z-index:9998}.dropdown-menu{position:fixed;background-color:#fff;box-shadow:0 5px 15px #0000004d,0 0 0 1px #0000001a;overflow:hidden;pointer-events:auto;z-index:9999}.action-icon{display:flex;align-items:center;justify-content:center;font-size:16px;width:20px;flex-shrink:0}.action-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-empty{padding:16px;text-align:center;color:#a0aec0;font-size:14px;font-style:italic}nile-menu{height:fit-content}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9807
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StRowActionsDropdownComponent, isStandalone: true, selector: "st-row-actions-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed", tabbed: "tabbed" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)", "document:keydown.enter": "onActivateKey($event)", "document:keydown.space": "onActivateKey($event)", "document:keydown.tab": "onTabKey($event)", "document:keydown.shift.tab": "onTabKey($event)" } }, viewQueries: [{ propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isOpen && context) {\n <div class=\"dropdown-container\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" role=\"presentation\" (click)=\"closed.emit()\"></div>\n\n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" role=\"dialog\" aria-label=\"Row actions\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n @if (isOpen) {\n <nile-menu>\n @for (action of visibleActions; track action.id) {\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n @if (action.icon) {\n <nile-icon size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n \n @if (visibleActions.length === 0) {\n <nile-menu-item>No actions available</nile-menu-item>\n }\n </nile-menu>\n }\n </div>\n </div>\n}\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background-color:transparent;pointer-events:auto;z-index:9998}.dropdown-menu{position:fixed;background-color:#fff;box-shadow:0 5px 15px #0000004d,0 0 0 1px #0000001a;overflow:hidden;pointer-events:auto;z-index:9999}.action-icon{display:flex;align-items:center;justify-content:center;font-size:16px;width:20px;flex-shrink:0}.action-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-empty{padding:16px;text-align:center;color:#a0aec0;font-size:14px;font-style:italic}nile-menu{height:fit-content}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9782
9808
  }
9783
9809
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StRowActionsDropdownComponent, decorators: [{
9784
9810
  type: Component,
@@ -9801,7 +9827,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
9801
9827
  }], onEscapeKey: [{
9802
9828
  type: HostListener,
9803
9829
  args: ['document:keydown.escape', ['$event']]
9804
- }], onSpaceKey: [{
9830
+ }], onActivateKey: [{
9831
+ type: HostListener,
9832
+ args: ['document:keydown.enter', ['$event']]
9833
+ }, {
9805
9834
  type: HostListener,
9806
9835
  args: ['document:keydown.space', ['$event']]
9807
9836
  }], onTabKey: [{
@@ -9825,6 +9854,31 @@ class StKeyboardNavigationDirective {
9825
9854
  }
9826
9855
  onKeyDown(event) {
9827
9856
  if (!this.tableState.isNavigationActive()) {
9857
+ // Only act when the region container ITSELF holds focus — not when the event
9858
+ // bubbled up from a child control (column/row action buttons). Otherwise
9859
+ // Shift+Tab on those buttons would be hijacked and skip the proper order.
9860
+ if (event.target !== this.el.nativeElement) {
9861
+ return;
9862
+ }
9863
+ // Not navigating yet — the grid region is focused (via Tab) but no cell is
9864
+ // active. An arrow key ENTERS cell navigation at the first cell; Shift+Tab
9865
+ // returns to the sheet tabs; a plain Tab is left alone so it moves on to the
9866
+ // next control, keeping the forward/reverse tab order symmetric.
9867
+ const key = event.key;
9868
+ const isArrow = key === NavigationKey.ARROW_UP || key === NavigationKey.ARROW_DOWN ||
9869
+ key === NavigationKey.ARROW_LEFT || key === NavigationKey.ARROW_RIGHT;
9870
+ if (isArrow && !this.tableState.isAnyCellEditing()) {
9871
+ event.preventDefault();
9872
+ this.tableState.focusCell(0, 0);
9873
+ }
9874
+ else if (key === NavigationKey.TAB && event.shiftKey) {
9875
+ // Region focused (not navigating): Shift+Tab returns straight to the sheet
9876
+ // tabs, mirroring the scripted forward jump (sheet-tab → region). Without
9877
+ // this, native Shift+Tab stops on the tab-panel wrapper first, so the
9878
+ // reverse order wouldn't match the forward order.
9879
+ event.preventDefault();
9880
+ this.tableState.requestFocusTabs();
9881
+ }
9828
9882
  return;
9829
9883
  }
9830
9884
  const isEditing = this.tableState.isAnyCellEditing();
@@ -11915,13 +11969,20 @@ class StTableComponent {
11915
11969
  }
11916
11970
  }
11917
11971
  onTableContainerFocus(event) {
11972
+ // The grid is a single tab stop: focusing the region (via Tab from the sheet
11973
+ // tab, or Shift+Tab from the controls after it) lands the user on the first
11974
+ // cell so they can edit/navigate with the arrow keys. The column-action and
11975
+ // row-action buttons are reached with the arrow keys (they're removed from the
11976
+ // tab order, tabindex -1), so a plain Tab out of the grid skips them and moves
11977
+ // to the next control — keeping the forward/reverse tab order symmetric.
11918
11978
  if (!this.isKeyboardNavigationEnabled())
11919
11979
  return;
11920
11980
  const tableState = this.getActiveTableState();
11921
- const currentFocus = tableState.getFocusedPosition();
11981
+ if (tableState.getFocusedPosition())
11982
+ return;
11922
11983
  const grid = this.visibleCellGrid();
11923
11984
  const cols = this.visibleColumns();
11924
- if (!currentFocus && grid.length > 0 && cols.length > 0) {
11985
+ if (grid.length > 0 && cols.length > 0) {
11925
11986
  tableState.focusCell(0, 0);
11926
11987
  }
11927
11988
  }
@@ -11976,7 +12037,7 @@ class StTableComponent {
11976
12037
  this.internalData$.complete();
11977
12038
  }
11978
12039
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
11979
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StTableComponent, isStandalone: true, selector: "st-table", inputs: { tableConfig: { classPropertyName: "tableConfig", publicName: "tableConfig", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, data$: { classPropertyName: "data$", publicName: "data$", isSignal: true, isRequired: false, transformFunction: null }, tableState: { classPropertyName: "tableState", publicName: "tableState", isSignal: true, isRequired: false, transformFunction: null }, enableSorting: { classPropertyName: "enableSorting", publicName: "enableSorting", isSignal: true, isRequired: false, transformFunction: null }, enableFiltering: { classPropertyName: "enableFiltering", publicName: "enableFiltering", isSignal: true, isRequired: false, transformFunction: null }, validateConfig: { classPropertyName: "validateConfig", publicName: "validateConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stateChange: "stateChange", dataChange: "dataChange", cellEdit: "cellEdit", cellSave: "cellSave", cellCancel: "cellCancel", cellChange: "cellChange", columnResized: "columnResized", columnMoved: "columnMoved", configValidationErrors: "configValidationErrors", addColumnClicked: "addColumnClicked", columnAdded: "columnAdded", rowAction: "rowAction", validationStateChange: "validationStateChange", requestAddRow: "requestAddRow", requestFocusTabs: "requestFocusTabs" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<!-- Top pagination controls -->\n@if (showTopPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"top\">\n </st-pagination>\n}\n\n@if (!(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <div class=\"st-table\"\n role=\"region\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [ngClass]=\"{\n 'virtual-scroll-enabled': isVirtualScrollEnabled(),\n 'keyboard-navigation-enabled': isKeyboardNavigationEnabled()\n }\"\n [ngStyle]=\"tableWrapperStyle()\"\n stKeyboardNavigation\n [tableState]=\"getActiveTableState()\"\n [addRowOnNavigatePastEnd]=\"mergedConfig()?.features?.keyboardNavigation?.addRowOnNavigatePastEnd || false\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? 0 : -1\"\n (focus)=\"onTableContainerFocus($event)\">\n <!-- Unified Table Actions Menu -->\n\n <!-- Virtual scroll viewport wrapper -->\n @if (isVirtualScrollEnabled()) {\n <div class=\"st-scroll-viewport\" #scrollViewport\n [ngStyle]=\"{ 'height.px': getVirtualScrollViewportHeight() }\">\n\n <!-- Spacer to create scrollable area -->\n <div class=\"st-scroll-spacer\" [ngStyle]=\"{ 'height.px': virtualScrollTotalHeight() }\">\n </div>\n\n <!-- Table positioner with transform (instead of tbody) -->\n <div class=\"st-table-positioner\" [ngStyle]=\"{ transform: 'translateY(' + virtualScrollOffsetY() + 'px)' }\">\n <!-- Table with only visible rows -->\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'virtual',\n theadStyle: { top: virtualScrollOffsetYNeg() + 'px' }\n }\"></ng-container>\n </div>\n </div>\n }\n \n <!-- Standard table (when virtual scroll disabled) -->\n @if (!isVirtualScrollEnabled()) {\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'standard',\n theadStyle: null\n }\"></ng-container>\n }\n\n <!-- Shared Column Menu Dropdown -->\n <st-column-menu-dropdown\n [isOpen]=\"columnMenuState().isOpen\"\n [position]=\"columnMenuState().position\"\n [context]=\"columnMenuState().context\"\n (actionClicked)=\"onColumnActionClicked($event)\"\n (closed)=\"closeColumnMenu()\">\n </st-column-menu-dropdown>\n\n <!-- Screen reader live region for dynamic announcements (sort, filter, pagination) -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\" aria-relevant=\"text\"></div>\n <!-- Table Actions Menu (outside virtual scroll transform context) -->\n @if (tableActionsMenuIsOpen()) {\n <div class=\"table-actions-menu-container\">\n <div class=\"table-actions-menu-backdrop\" (click)=\"closeTableActionsMenu()\"></div>\n\n @if (tableActionsMenuView() === 'main') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n @if (mergedConfig()?.features?.columnManagement?.allowAdd) {\n <nile-menu-item (click)=\"onTableActionsAddColumn()\">\n <nile-icon slot=\"prefix\" name=\"plus\" size=\"12\"></nile-icon>\n Add Column\n </nile-menu-item>\n }\n <nile-menu-item (click)=\"openTableActionsColumnsView()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"eye\"></nile-icon>\n Show/Hide Columns\n </nile-menu-item>\n </nile-menu>\n </div>\n }\n\n @if (tableActionsMenuView() === 'columns') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n <nile-menu-item (click)=\"backToTableActionsMain()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"chevron-left\"></nile-icon>\n Back\n </nile-menu-item>\n <nile-divider></nile-divider>\n @for (column of getTableActionsColumnsVisibility(); track column.key) {\n <nile-menu-item\n [class.disabled]=\"!column.hideable\"\n (click)=\"onTableActionsToggleColumn(column.key, $event)\">\n <nile-checkbox\n [checked]=\"column.visible\"\n [disabled]=\"!column.hideable\"\n [label]=\"column.header || column.key\">\n </nile-checkbox>\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n }\n </div>\n }\n </div>\n}\n\n@if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container>\n}\n\n<!-- Shared Row Actions Dropdown -->\n<st-row-actions-dropdown [isOpen]=\"dropdownState().isOpen\" [position]=\"dropdownState().position\"\n [context]=\"dropdownState().context\" (actionClicked)=\"onRowActionClicked($event)\"\n (closed)=\"closeRowActionsDropdown()\" (tabbed)=\"onDropdownTabbed($event)\">\n</st-row-actions-dropdown>\n\n\n<!-- Bottom pagination controls -->\n@if (showBottomPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"bottom\">\n</st-pagination>\n}\n\n\n<!-- ========================================== -->\n<!-- REUSABLE TABLE TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #tableTemplate let-mode=\"mode\" let-theadStyle=\"theadStyle\">\n <table class=\"st-table-element\"\n role=\"grid\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [attr.aria-rowcount]=\"visibleCellGrid().length\"\n [attr.aria-colcount]=\"visibleColumns().length\">\n <!-- TABLE HEADER -->\n <thead [ngClass]=\"{ 'sticky': mergedConfig()?.display?.stickyHeader }\" [ngStyle]=\"theadStyle\">\n <tr role=\"row\">\n <!-- Row Number Header -->\n @if (mergedConfig()?.showRowNumber) {\n <th class=\"row-number-header header-cell sticky-left\"\n [class.row-number-header--with-icon]=\"hasRowNumberIcon\"\n scope=\"col\"\n aria-label=\"Row number\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'background-color': rowNumberStickyBackground()\n }\">\n <span class=\"row-number-cell__index\">#</span>\n </th>\n }\n <!-- Column Headers -->\n @for (column of visibleColumns(); track column.key; let colIndex = $index, isFirst = $first, isLast = $last) {\n <th\n scope=\"col\"\n [attr.aria-sort]=\"getColumnAriaSort(column)\"\n [ngClass]=\"{\n 'header-cell': mode === 'standard',\n 'sticky-left': column.sticky === 'left',\n 'sticky-right': column.sticky === 'right',\n 'sticky-right-first': column.sticky === 'right' && isFirstStickyRight(column.key),\n 'resizable': column.resizable !== false\n }\"\n [ngStyle]=\"{\n position: column.sticky ? 'sticky' : null,\n 'left.px': column.sticky === 'left' ? (column.stickyOffset || 0) : null,\n 'right.px': column.sticky === 'right' ? (column.stickyOffset || 0) : null,\n 'z-index': column.sticky ? ZIndex.STICKY_HEADER_CELL : null,\n 'width.px': column.width,\n 'min-width.px': column.minWidth ?? 100,\n 'background-color': stickyColumnBackground(column)\n }\">\n\n <st-header\n [column]=\"column\"\n [columnIndex]=\"colIndex\"\n [isFirstColumn]=\"isFirst\"\n [isLastColumn]=\"isLast\"\n [tableState]=\"getActiveTableState()\"\n [enableSorting]=\"mergedConfig()?.sorting?.enabled ?? enableSorting()\"\n [enableFiltering]=\"mergedConfig()?.filtering?.enabled ?? enableFiltering()\"\n (columnMoved)=\"onColumnMoved($event)\"\n (menuClick)=\"openColumnMenu($event, column, colIndex, isFirst, isLast)\"\n (menuKeyboard)=\"openColumnMenuFromKeyboard(colIndex, isFirst, isLast)\"\n (tabOut)=\"onHeaderTabOut()\"\n (headerNavigate)=\"onHeaderNavigate($event, colIndex)\">\n </st-header>\n\n @if (column.resizable !== false) {\n <div\n class=\"resize-handle\"\n aria-hidden=\"true\"\n stColumnResize\n [column]=\"column\"\n (columnResizing)=\"onColumnResizing($event)\"\n (columnResized)=\"onColumnResized($event)\">\n </div>\n }\n </th>\n }\n\n <!-- Settings Column Header -->\n <th\n scope=\"col\"\n aria-label=\"Actions\"\n class=\"settings-column sticky-right\"\n [ngClass]=\"{ 'header-cell': mode === 'standard' }\"\n [ngStyle]=\"{\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'background-color': rowNumberStickyBackground()\n }\">\n <div [ngClass]=\"{ 'flex-center': mode === 'virtual', 'header-content': mode === 'standard' }\">\n <st-table-actions\n [isMenuOpen]=\"tableActionsMenuIsOpen()\"\n (menuButtonClicked)=\"onTableActionsButtonClick($event)\">\n </st-table-actions>\n </div>\n </th>\n </tr>\n </thead>\n\n <!-- TABLE BODY -->\n <tbody>\n <!-- Virtual Scroll Rows -->\n @if (mode === 'virtual') {\n @for (row of visibleRows(); track trackByRowIndex($index, row); let relativeIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"getAbsoluteRowIndex(relativeIndex)\"\n [attr.aria-rowindex]=\"getAbsoluteRowIndex(relativeIndex) + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (getAbsoluteRowIndex(relativeIndex) + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(getAbsoluteRowIndex(relativeIndex))\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{getAbsoluteRowIndex(relativeIndex) + 1}}</span>\n @if (resolveRowNumberIcon(getAbsoluteRowIndex(relativeIndex)); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: getAbsoluteRowIndex(relativeIndex),\n mode: 'virtual',\n relativeIndex: relativeIndex\n }\"></ng-container>\n </tr>\n }\n }\n\n <!-- Standard Rows -->\n @if (mode === 'standard') {\n @for (row of visibleCellGrid(); track $index; let rowIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"rowIndex\"\n [attr.aria-rowindex]=\"rowIndex + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (rowIndex + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(rowIndex)\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{rowIndex + 1}}</span>\n @if (resolveRowNumberIcon(rowIndex); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: rowIndex,\n mode: 'standard'\n }\"></ng-container>\n </tr>\n }\n }\n </tbody>\n </table>\n</ng-template>\n\n<!-- ========================================== -->\n<!-- REUSABLE BODY CELL TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #bodyCellTemplate let-row=\"row\" let-rowIndex=\"rowIndex\" let-mode=\"mode\" let-relativeIndex=\"relativeIndex\">\n <!-- Data Cells -->\n @for (cell of row; track $index; let colIndex = $index) {\n <td\n role=\"gridcell\"\n [attr.aria-colindex]=\"colIndex + 1\"\n [ngClass]=\"{\n 'sticky-left': visibleColumns()[colIndex]?.sticky === 'left',\n 'sticky-right': visibleColumns()[colIndex]?.sticky === 'right',\n 'sticky-right-first': visibleColumns()[colIndex]?.sticky === 'right' && visibleColumns()[colIndex]?.key && isFirstStickyRight(visibleColumns()[colIndex].key),\n 'align-center': visibleColumns()[colIndex]?.alignment === 'center',\n 'align-right': visibleColumns()[colIndex]?.alignment === 'right',\n 'cell-focused': cell.isFocused()\n }\"\n [ngStyle]=\"{\n position: visibleColumns()[colIndex]?.sticky ? 'sticky' : null,\n 'left.px': visibleColumns()[colIndex]?.sticky === 'left' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'right.px': visibleColumns()[colIndex]?.sticky === 'right' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'z-index': visibleColumns()[colIndex]?.sticky ? ZIndex.STICKY_BODY_CELL : null,\n 'width.px': visibleColumns()[colIndex]?.width,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': bodyCellBackground(visibleColumns()[colIndex], rowIndex)\n }\"\n (click)=\"isKeyboardNavigationEnabled() ? onCellClick(rowIndex, colIndex) : null\">\n \n <!-- Virtual Scroll Cell -->\n @if (mode === 'virtual') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\" \n [editMode]=\"getEditModeForCells()\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellEdit)=\"onCellEdit($event)\" \n (cellSave)=\"onCellSave($event)\"\n (cellSaveAndNavigate)=\"onCellSaveAndNavigate($event)\" \n (cellCancel)=\"onCellCancel($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n\n <!-- Standard Cell -->\n @if (mode === 'standard') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellSave)=\"onCellSave($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n </td>\n }\n \n <!-- Row Actions Cell -->\n <td class=\"settings-column\"\n role=\"gridcell\"\n [attr.aria-colindex]=\"visibleColumns().length + 1\"\n [ngClass]=\"{\n 'has-actions': hasRowActions()\n }\"\n [ngStyle]=\"{\n position: hasRowActions() ? 'sticky' : null,\n 'right.px': hasRowActions() ? 0 : null,\n 'z-index': hasRowActions() ? ZIndex.STICKY_BODY_CELL : null,\n 'background-color': settingsColumnBodyBackground(rowIndex)\n }\">\n @if (hasRowActions()) {\n <button\n class=\"settings-trigger\"\n (click)=\"openRowActionsDropdown($event, getRowData(rowIndex), rowIndex)\"\n (keydown)=\"onSettingsTriggerKeydown($event, getRowData(rowIndex), rowIndex)\"\n type=\"button\"\n aria-label=\"Row actions\">\n <span aria-hidden=\"true\">\u22EF</span>\n </button>\n }\n </td>\n</ng-template>\n\n@if (showColumnModal()) {\n <st-column-editor-modal\n (columnCreated)=\"onColumnCreated($event)\"\n (cancelled)=\"onModalCancelled()\">\n </st-column-editor-modal>\n}\n\n<ng-template #skeletonLoader>\n @if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <div class=\"list-row\">\n @for (i of skeletonColumns; track $index) {\n <div class=\"list-content\">\n @for (j of skeletonRows; track $index) {\n <nile-skeleton-loader variant=\"text\" width=\"90%\" height=\"18\"></nile-skeleton-loader>\n }\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}:host>st-pagination{flex-shrink:0}.st-table{width:100%;overflow:auto;position:relative;flex:1 1 auto;min-height:0;border-radius:4px;border:1px solid #E6E9EB}.st-table st-table-actions{position:sticky;right:0}.st-table.keyboard-navigation-enabled{cursor:pointer}.st-table.keyboard-navigation-enabled:focus{outline:none;box-shadow:0 0 0 2px #3b82f64d}.st-table.keyboard-navigation-enabled td.cell-focused{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;position:relative;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:has(.st-cell.editing){box-shadow:var(--st-focused-cell-editing-box-shadow, 0 0 0 4px rgba(37, 99, 235, .15))}.st-table.virtual-scroll-enabled{overflow-x:visible;margin:0;border:1px solid #E6E9EB;border-collapse:separate;border-spacing:0}.st-table.virtual-scroll-enabled .st-scroll-viewport{position:relative;overflow-y:auto;overflow-x:auto;scroll-behavior:smooth}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-scroll-spacer{position:absolute;top:0;left:0;width:1px;pointer-events:none;z-index:-1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-positioner{position:absolute;top:0;left:0;right:0;will-change:transform}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element{position:relative;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;border:none;background-color:#fff;will-change:top;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr{border-bottom:1px solid #E6E9EB;transition:background-color .15s;height:2rem;box-sizing:border-box}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:last-child{border-bottom:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td{padding:0;vertical-align:middle;box-sizing:border-box;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-center{text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-right{text-align:right}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column{width:2rem;text-align:center;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:2px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table:not(.virtual-scroll-enabled) .st-table-element{width:100%;height:100%;overflow:auto;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table:not(.virtual-scroll-enabled) .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr{height:2rem;box-sizing:border-box}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:last-child{border-bottom:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td{padding:0;vertical-align:middle;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-center{text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-right{text-align:right}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column{position:sticky;right:0;width:2rem;text-align:center;border-right:none;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content{display:flex;height:2rem;align-items:center}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content .table-header-text{flex-grow:1;padding-left:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element .settings-column>.header-content{display:flex;align-items:center;justify-content:center}.table-actions-menu-container{position:fixed;inset:0;z-index:9996;pointer-events:none}.table-actions-menu-backdrop{position:absolute;inset:0;background:transparent;pointer-events:auto}.table-actions-menu-panel{position:fixed;pointer-events:auto;z-index:9997;min-width:15rem}.table-actions-menu-panel nile-menu{max-height:30rem;overflow-y:auto}.table-actions-menu-panel nile-menu::part(base){width:fit-content;min-height:auto}.table-actions-menu-panel nile-menu nile-menu-item::part(base){min-height:2.5rem}.table-actions-menu-panel nile-menu nile-menu-item::part(label){font-size:12px}.table-actions-menu-panel nile-menu nile-menu-item.disabled{opacity:.5;cursor:not-allowed}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(base){display:flex;align-items:center}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(label){font-size:12px;margin-top:0}.flex-center{display:flex;align-items:center;justify-content:center}.list-row .list-content{display:flex;justify-content:space-evenly;gap:4px;margin-bottom:1rem}.list-row{padding:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: StPaginationComponent, selector: "st-pagination", inputs: ["tableState", "tableConfig", "position"] }, { kind: "component", type: StHeaderComponent, selector: "st-header", inputs: ["column", "columnIndex", "isFirstColumn", "isLastColumn", "tableState", "enableSorting", "enableFiltering"], outputs: ["sortToggle", "filterChange", "columnMoved", "menuClick", "tabOut", "headerNavigate", "menuKeyboard"] }, { kind: "component", type: StCellComponent, selector: "st-cell", inputs: ["cell", "editMode", "tableState", "tableConfig", "columnIndex"], outputs: ["cellChange", "cellEdit", "cellSave", "cellCancel", "cellSaveAndNavigate"] }, { kind: "component", type: StTableActionsComponent, selector: "st-table-actions", inputs: ["isMenuOpen"], outputs: ["menuButtonClicked"] }, { kind: "component", type: StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: ["isOpen", "position", "context"], outputs: ["actionClicked", "closed"] }, { kind: "component", type: StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: ["isOpen", "position", "context"], outputs: ["actionClicked", "closed", "tabbed"] }, { kind: "directive", type: StKeyboardNavigationDirective, selector: "[stKeyboardNavigation]", inputs: ["tableState", "addRowOnNavigatePastEnd"] }, { kind: "directive", type: StColumnResizeDirective, selector: "[stColumnResize]", inputs: ["column"], outputs: ["columnResized", "columnResizing"] }, { kind: "component", type: StColumnEditorModalComponent, selector: "st-column-editor-modal", outputs: ["columnCreated", "cancelled"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); }
12040
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StTableComponent, isStandalone: true, selector: "st-table", inputs: { tableConfig: { classPropertyName: "tableConfig", publicName: "tableConfig", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, data$: { classPropertyName: "data$", publicName: "data$", isSignal: true, isRequired: false, transformFunction: null }, tableState: { classPropertyName: "tableState", publicName: "tableState", isSignal: true, isRequired: false, transformFunction: null }, enableSorting: { classPropertyName: "enableSorting", publicName: "enableSorting", isSignal: true, isRequired: false, transformFunction: null }, enableFiltering: { classPropertyName: "enableFiltering", publicName: "enableFiltering", isSignal: true, isRequired: false, transformFunction: null }, validateConfig: { classPropertyName: "validateConfig", publicName: "validateConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stateChange: "stateChange", dataChange: "dataChange", cellEdit: "cellEdit", cellSave: "cellSave", cellCancel: "cellCancel", cellChange: "cellChange", columnResized: "columnResized", columnMoved: "columnMoved", configValidationErrors: "configValidationErrors", addColumnClicked: "addColumnClicked", columnAdded: "columnAdded", rowAction: "rowAction", validationStateChange: "validationStateChange", requestAddRow: "requestAddRow", requestFocusTabs: "requestFocusTabs" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<!-- Top pagination controls -->\n@if (showTopPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"top\">\n </st-pagination>\n}\n\n@if (!(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <div class=\"st-table\"\n role=\"region\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [ngClass]=\"{\n 'virtual-scroll-enabled': isVirtualScrollEnabled(),\n 'keyboard-navigation-enabled': isKeyboardNavigationEnabled()\n }\"\n [ngStyle]=\"tableWrapperStyle()\"\n stKeyboardNavigation\n [tableState]=\"getActiveTableState()\"\n [addRowOnNavigatePastEnd]=\"mergedConfig()?.features?.keyboardNavigation?.addRowOnNavigatePastEnd || false\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? 0 : -1\"\n (focus)=\"onTableContainerFocus($event)\">\n <!-- Unified Table Actions Menu -->\n\n <!-- Virtual scroll viewport wrapper -->\n @if (isVirtualScrollEnabled()) {\n <div class=\"st-scroll-viewport\" #scrollViewport\n [ngStyle]=\"{ 'height.px': getVirtualScrollViewportHeight() }\">\n\n <!-- Spacer to create scrollable area -->\n <div class=\"st-scroll-spacer\" [ngStyle]=\"{ 'height.px': virtualScrollTotalHeight() }\">\n </div>\n\n <!-- Table positioner with transform (instead of tbody) -->\n <div class=\"st-table-positioner\" [ngStyle]=\"{ transform: 'translateY(' + virtualScrollOffsetY() + 'px)' }\">\n <!-- Table with only visible rows -->\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'virtual',\n theadStyle: { top: virtualScrollOffsetYNeg() + 'px' }\n }\"></ng-container>\n </div>\n </div>\n }\n \n <!-- Standard table (when virtual scroll disabled) -->\n @if (!isVirtualScrollEnabled()) {\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'standard',\n theadStyle: null\n }\"></ng-container>\n }\n\n <!-- Shared Column Menu Dropdown -->\n <st-column-menu-dropdown\n [isOpen]=\"columnMenuState().isOpen\"\n [position]=\"columnMenuState().position\"\n [context]=\"columnMenuState().context\"\n (actionClicked)=\"onColumnActionClicked($event)\"\n (closed)=\"closeColumnMenu()\">\n </st-column-menu-dropdown>\n\n <!-- Screen reader live region for dynamic announcements (sort, filter, pagination) -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\" aria-relevant=\"text\"></div>\n <!-- Table Actions Menu (outside virtual scroll transform context) -->\n @if (tableActionsMenuIsOpen()) {\n <div class=\"table-actions-menu-container\">\n <div class=\"table-actions-menu-backdrop\" (click)=\"closeTableActionsMenu()\"></div>\n\n @if (tableActionsMenuView() === 'main') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n @if (mergedConfig()?.features?.columnManagement?.allowAdd) {\n <nile-menu-item (click)=\"onTableActionsAddColumn()\">\n <nile-icon slot=\"prefix\" name=\"plus\" size=\"12\"></nile-icon>\n Add Column\n </nile-menu-item>\n }\n <nile-menu-item (click)=\"openTableActionsColumnsView()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"eye\"></nile-icon>\n Show/Hide Columns\n </nile-menu-item>\n </nile-menu>\n </div>\n }\n\n @if (tableActionsMenuView() === 'columns') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n <nile-menu-item (click)=\"backToTableActionsMain()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"chevron-left\"></nile-icon>\n Back\n </nile-menu-item>\n <nile-divider></nile-divider>\n @for (column of getTableActionsColumnsVisibility(); track column.key) {\n <nile-menu-item\n [class.disabled]=\"!column.hideable\"\n (click)=\"onTableActionsToggleColumn(column.key, $event)\">\n <nile-checkbox\n [checked]=\"column.visible\"\n [disabled]=\"!column.hideable\"\n [label]=\"column.header || column.key\">\n </nile-checkbox>\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n }\n </div>\n }\n </div>\n}\n\n@if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container>\n}\n\n<!-- Shared Row Actions Dropdown -->\n<st-row-actions-dropdown [isOpen]=\"dropdownState().isOpen\" [position]=\"dropdownState().position\"\n [context]=\"dropdownState().context\" (actionClicked)=\"onRowActionClicked($event)\"\n (closed)=\"closeRowActionsDropdown()\" (tabbed)=\"onDropdownTabbed($event)\">\n</st-row-actions-dropdown>\n\n\n<!-- Bottom pagination controls -->\n@if (showBottomPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"bottom\">\n</st-pagination>\n}\n\n\n<!-- ========================================== -->\n<!-- REUSABLE TABLE TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #tableTemplate let-mode=\"mode\" let-theadStyle=\"theadStyle\">\n <table class=\"st-table-element\"\n role=\"grid\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [attr.aria-rowcount]=\"visibleCellGrid().length\"\n [attr.aria-colcount]=\"visibleColumns().length\">\n <!-- TABLE HEADER -->\n <thead [ngClass]=\"{ 'sticky': mergedConfig()?.display?.stickyHeader }\" [ngStyle]=\"theadStyle\">\n <tr role=\"row\">\n <!-- Row Number Header -->\n @if (mergedConfig()?.showRowNumber) {\n <th class=\"row-number-header header-cell sticky-left\"\n [class.row-number-header--with-icon]=\"hasRowNumberIcon\"\n scope=\"col\"\n aria-label=\"Row number\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'background-color': rowNumberStickyBackground()\n }\">\n <span class=\"row-number-cell__index\">#</span>\n </th>\n }\n <!-- Column Headers -->\n @for (column of visibleColumns(); track column.key; let colIndex = $index, isFirst = $first, isLast = $last) {\n <th\n scope=\"col\"\n [attr.aria-sort]=\"getColumnAriaSort(column)\"\n [ngClass]=\"{\n 'header-cell': mode === 'standard',\n 'sticky-left': column.sticky === 'left',\n 'sticky-right': column.sticky === 'right',\n 'sticky-right-first': column.sticky === 'right' && isFirstStickyRight(column.key),\n 'resizable': column.resizable !== false\n }\"\n [ngStyle]=\"{\n position: column.sticky ? 'sticky' : null,\n 'left.px': column.sticky === 'left' ? (column.stickyOffset || 0) : null,\n 'right.px': column.sticky === 'right' ? (column.stickyOffset || 0) : null,\n 'z-index': column.sticky ? ZIndex.STICKY_HEADER_CELL : null,\n 'width.px': column.width,\n 'min-width.px': column.minWidth ?? 100,\n 'background-color': stickyColumnBackground(column)\n }\">\n\n <st-header\n [column]=\"column\"\n [columnIndex]=\"colIndex\"\n [isFirstColumn]=\"isFirst\"\n [isLastColumn]=\"isLast\"\n [tableState]=\"getActiveTableState()\"\n [keyboardNavigationEnabled]=\"isKeyboardNavigationEnabled()\"\n [enableSorting]=\"mergedConfig()?.sorting?.enabled ?? enableSorting()\"\n [enableFiltering]=\"mergedConfig()?.filtering?.enabled ?? enableFiltering()\"\n (columnMoved)=\"onColumnMoved($event)\"\n (menuClick)=\"openColumnMenu($event, column, colIndex, isFirst, isLast)\"\n (menuKeyboard)=\"openColumnMenuFromKeyboard(colIndex, isFirst, isLast)\"\n (tabOut)=\"onHeaderTabOut()\"\n (headerNavigate)=\"onHeaderNavigate($event, colIndex)\">\n </st-header>\n\n @if (column.resizable !== false) {\n <div\n class=\"resize-handle\"\n aria-hidden=\"true\"\n stColumnResize\n [column]=\"column\"\n (columnResizing)=\"onColumnResizing($event)\"\n (columnResized)=\"onColumnResized($event)\">\n </div>\n }\n </th>\n }\n\n <!-- Settings Column Header -->\n <th\n scope=\"col\"\n aria-label=\"Actions\"\n class=\"settings-column sticky-right\"\n [ngClass]=\"{ 'header-cell': mode === 'standard' }\"\n [ngStyle]=\"{\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'background-color': rowNumberStickyBackground()\n }\">\n <div [ngClass]=\"{ 'flex-center': mode === 'virtual', 'header-content': mode === 'standard' }\">\n <st-table-actions\n [isMenuOpen]=\"tableActionsMenuIsOpen()\"\n (menuButtonClicked)=\"onTableActionsButtonClick($event)\">\n </st-table-actions>\n </div>\n </th>\n </tr>\n </thead>\n\n <!-- TABLE BODY -->\n <tbody>\n <!-- Virtual Scroll Rows -->\n @if (mode === 'virtual') {\n @for (row of visibleRows(); track trackByRowIndex($index, row); let relativeIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"getAbsoluteRowIndex(relativeIndex)\"\n [attr.aria-rowindex]=\"getAbsoluteRowIndex(relativeIndex) + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (getAbsoluteRowIndex(relativeIndex) + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(getAbsoluteRowIndex(relativeIndex))\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{getAbsoluteRowIndex(relativeIndex) + 1}}</span>\n @if (resolveRowNumberIcon(getAbsoluteRowIndex(relativeIndex)); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: getAbsoluteRowIndex(relativeIndex),\n mode: 'virtual',\n relativeIndex: relativeIndex\n }\"></ng-container>\n </tr>\n }\n }\n\n <!-- Standard Rows -->\n @if (mode === 'standard') {\n @for (row of visibleCellGrid(); track $index; let rowIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"rowIndex\"\n [attr.aria-rowindex]=\"rowIndex + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (rowIndex + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(rowIndex)\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{rowIndex + 1}}</span>\n @if (resolveRowNumberIcon(rowIndex); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: rowIndex,\n mode: 'standard'\n }\"></ng-container>\n </tr>\n }\n }\n </tbody>\n </table>\n</ng-template>\n\n<!-- ========================================== -->\n<!-- REUSABLE BODY CELL TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #bodyCellTemplate let-row=\"row\" let-rowIndex=\"rowIndex\" let-mode=\"mode\" let-relativeIndex=\"relativeIndex\">\n <!-- Data Cells -->\n @for (cell of row; track $index; let colIndex = $index) {\n <td\n role=\"gridcell\"\n [attr.aria-colindex]=\"colIndex + 1\"\n [ngClass]=\"{\n 'sticky-left': visibleColumns()[colIndex]?.sticky === 'left',\n 'sticky-right': visibleColumns()[colIndex]?.sticky === 'right',\n 'sticky-right-first': visibleColumns()[colIndex]?.sticky === 'right' && visibleColumns()[colIndex]?.key && isFirstStickyRight(visibleColumns()[colIndex].key),\n 'align-center': visibleColumns()[colIndex]?.alignment === 'center',\n 'align-right': visibleColumns()[colIndex]?.alignment === 'right',\n 'cell-focused': cell.isFocused()\n }\"\n [ngStyle]=\"{\n position: visibleColumns()[colIndex]?.sticky ? 'sticky' : null,\n 'left.px': visibleColumns()[colIndex]?.sticky === 'left' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'right.px': visibleColumns()[colIndex]?.sticky === 'right' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'z-index': visibleColumns()[colIndex]?.sticky ? ZIndex.STICKY_BODY_CELL : null,\n 'width.px': visibleColumns()[colIndex]?.width,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': bodyCellBackground(visibleColumns()[colIndex], rowIndex)\n }\"\n (click)=\"isKeyboardNavigationEnabled() ? onCellClick(rowIndex, colIndex) : null\">\n \n <!-- Virtual Scroll Cell -->\n @if (mode === 'virtual') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\" \n [editMode]=\"getEditModeForCells()\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellEdit)=\"onCellEdit($event)\" \n (cellSave)=\"onCellSave($event)\"\n (cellSaveAndNavigate)=\"onCellSaveAndNavigate($event)\" \n (cellCancel)=\"onCellCancel($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n\n <!-- Standard Cell -->\n @if (mode === 'standard') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellSave)=\"onCellSave($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n </td>\n }\n \n <!-- Row Actions Cell -->\n <td class=\"settings-column\"\n role=\"gridcell\"\n [attr.aria-colindex]=\"visibleColumns().length + 1\"\n [ngClass]=\"{\n 'has-actions': hasRowActions()\n }\"\n [ngStyle]=\"{\n position: hasRowActions() ? 'sticky' : null,\n 'right.px': hasRowActions() ? 0 : null,\n 'z-index': hasRowActions() ? ZIndex.STICKY_BODY_CELL : null,\n 'background-color': settingsColumnBodyBackground(rowIndex)\n }\">\n @if (hasRowActions()) {\n <button\n class=\"settings-trigger\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? -1 : null\"\n (click)=\"openRowActionsDropdown($event, getRowData(rowIndex), rowIndex)\"\n (keydown)=\"onSettingsTriggerKeydown($event, getRowData(rowIndex), rowIndex)\"\n type=\"button\"\n aria-label=\"Row actions\">\n <span aria-hidden=\"true\">\u22EF</span>\n </button>\n }\n </td>\n</ng-template>\n\n@if (showColumnModal()) {\n <st-column-editor-modal\n (columnCreated)=\"onColumnCreated($event)\"\n (cancelled)=\"onModalCancelled()\">\n </st-column-editor-modal>\n}\n\n<ng-template #skeletonLoader>\n @if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <div class=\"list-row\">\n @for (i of skeletonColumns; track $index) {\n <div class=\"list-content\">\n @for (j of skeletonRows; track $index) {\n <nile-skeleton-loader variant=\"text\" width=\"90%\" height=\"18\"></nile-skeleton-loader>\n }\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}:host>st-pagination{flex-shrink:0}.st-table{width:100%;overflow:auto;position:relative;flex:1 1 auto;min-height:0;border-radius:4px;border:1px solid #E6E9EB}.st-table st-table-actions{position:sticky;right:0}.st-table.keyboard-navigation-enabled{cursor:pointer}.st-table.keyboard-navigation-enabled:focus{outline:none;box-shadow:0 0 0 2px #3b82f64d}.st-table.keyboard-navigation-enabled td.cell-focused{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;position:relative;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:has(.st-cell.editing){box-shadow:var(--st-focused-cell-editing-box-shadow, 0 0 0 4px rgba(37, 99, 235, .15))}.st-table.virtual-scroll-enabled{overflow-x:visible;margin:0;border:1px solid #E6E9EB;border-collapse:separate;border-spacing:0}.st-table.virtual-scroll-enabled .st-scroll-viewport{position:relative;overflow-y:auto;overflow-x:auto;scroll-behavior:smooth}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-scroll-spacer{position:absolute;top:0;left:0;width:1px;pointer-events:none;z-index:-1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-positioner{position:absolute;top:0;left:0;right:0;will-change:transform}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element{position:relative;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;border:none;background-color:#fff;will-change:top;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr{border-bottom:1px solid #E6E9EB;transition:background-color .15s;height:2rem;box-sizing:border-box}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:last-child{border-bottom:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td{padding:0;vertical-align:middle;box-sizing:border-box;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-center{text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-right{text-align:right}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column{width:2rem;text-align:center;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:2px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table:not(.virtual-scroll-enabled) .st-table-element{width:100%;height:100%;overflow:auto;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table:not(.virtual-scroll-enabled) .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr{height:2rem;box-sizing:border-box}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:last-child{border-bottom:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td{padding:0;vertical-align:middle;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-center{text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-right{text-align:right}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column{position:sticky;right:0;width:2rem;text-align:center;border-right:none;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content{display:flex;height:2rem;align-items:center}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content .table-header-text{flex-grow:1;padding-left:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element .settings-column>.header-content{display:flex;align-items:center;justify-content:center}.table-actions-menu-container{position:fixed;inset:0;z-index:9996;pointer-events:none}.table-actions-menu-backdrop{position:absolute;inset:0;background:transparent;pointer-events:auto}.table-actions-menu-panel{position:fixed;pointer-events:auto;z-index:9997;min-width:15rem}.table-actions-menu-panel nile-menu{max-height:30rem;overflow-y:auto}.table-actions-menu-panel nile-menu::part(base){width:fit-content;min-height:auto}.table-actions-menu-panel nile-menu nile-menu-item::part(base){min-height:2.5rem}.table-actions-menu-panel nile-menu nile-menu-item::part(label){font-size:12px}.table-actions-menu-panel nile-menu nile-menu-item.disabled{opacity:.5;cursor:not-allowed}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(base){display:flex;align-items:center}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(label){font-size:12px;margin-top:0}.flex-center{display:flex;align-items:center;justify-content:center}.list-row .list-content{display:flex;justify-content:space-evenly;gap:4px;margin-bottom:1rem}.list-row{padding:1rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: StPaginationComponent, selector: "st-pagination", inputs: ["tableState", "tableConfig", "position"] }, { kind: "component", type: StHeaderComponent, selector: "st-header", inputs: ["column", "columnIndex", "isFirstColumn", "isLastColumn", "tableState", "enableSorting", "enableFiltering", "keyboardNavigationEnabled"], outputs: ["sortToggle", "filterChange", "columnMoved", "menuClick", "tabOut", "headerNavigate", "menuKeyboard"] }, { kind: "component", type: StCellComponent, selector: "st-cell", inputs: ["cell", "editMode", "tableState", "tableConfig", "columnIndex"], outputs: ["cellChange", "cellEdit", "cellSave", "cellCancel", "cellSaveAndNavigate"] }, { kind: "component", type: StTableActionsComponent, selector: "st-table-actions", inputs: ["isMenuOpen"], outputs: ["menuButtonClicked"] }, { kind: "component", type: StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: ["isOpen", "position", "context"], outputs: ["actionClicked", "closed"] }, { kind: "component", type: StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: ["isOpen", "position", "context"], outputs: ["actionClicked", "closed", "tabbed"] }, { kind: "directive", type: StKeyboardNavigationDirective, selector: "[stKeyboardNavigation]", inputs: ["tableState", "addRowOnNavigatePastEnd"] }, { kind: "directive", type: StColumnResizeDirective, selector: "[stColumnResize]", inputs: ["column"], outputs: ["columnResized", "columnResizing"] }, { kind: "component", type: StColumnEditorModalComponent, selector: "st-column-editor-modal", outputs: ["columnCreated", "cancelled"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); }
11980
12041
  }
11981
12042
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StTableComponent, decorators: [{
11982
12043
  type: Component,
@@ -11991,7 +12052,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11991
12052
  StKeyboardNavigationDirective,
11992
12053
  StColumnResizeDirective,
11993
12054
  StColumnEditorModalComponent
11994
- ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<!-- Top pagination controls -->\n@if (showTopPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"top\">\n </st-pagination>\n}\n\n@if (!(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <div class=\"st-table\"\n role=\"region\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [ngClass]=\"{\n 'virtual-scroll-enabled': isVirtualScrollEnabled(),\n 'keyboard-navigation-enabled': isKeyboardNavigationEnabled()\n }\"\n [ngStyle]=\"tableWrapperStyle()\"\n stKeyboardNavigation\n [tableState]=\"getActiveTableState()\"\n [addRowOnNavigatePastEnd]=\"mergedConfig()?.features?.keyboardNavigation?.addRowOnNavigatePastEnd || false\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? 0 : -1\"\n (focus)=\"onTableContainerFocus($event)\">\n <!-- Unified Table Actions Menu -->\n\n <!-- Virtual scroll viewport wrapper -->\n @if (isVirtualScrollEnabled()) {\n <div class=\"st-scroll-viewport\" #scrollViewport\n [ngStyle]=\"{ 'height.px': getVirtualScrollViewportHeight() }\">\n\n <!-- Spacer to create scrollable area -->\n <div class=\"st-scroll-spacer\" [ngStyle]=\"{ 'height.px': virtualScrollTotalHeight() }\">\n </div>\n\n <!-- Table positioner with transform (instead of tbody) -->\n <div class=\"st-table-positioner\" [ngStyle]=\"{ transform: 'translateY(' + virtualScrollOffsetY() + 'px)' }\">\n <!-- Table with only visible rows -->\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'virtual',\n theadStyle: { top: virtualScrollOffsetYNeg() + 'px' }\n }\"></ng-container>\n </div>\n </div>\n }\n \n <!-- Standard table (when virtual scroll disabled) -->\n @if (!isVirtualScrollEnabled()) {\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'standard',\n theadStyle: null\n }\"></ng-container>\n }\n\n <!-- Shared Column Menu Dropdown -->\n <st-column-menu-dropdown\n [isOpen]=\"columnMenuState().isOpen\"\n [position]=\"columnMenuState().position\"\n [context]=\"columnMenuState().context\"\n (actionClicked)=\"onColumnActionClicked($event)\"\n (closed)=\"closeColumnMenu()\">\n </st-column-menu-dropdown>\n\n <!-- Screen reader live region for dynamic announcements (sort, filter, pagination) -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\" aria-relevant=\"text\"></div>\n <!-- Table Actions Menu (outside virtual scroll transform context) -->\n @if (tableActionsMenuIsOpen()) {\n <div class=\"table-actions-menu-container\">\n <div class=\"table-actions-menu-backdrop\" (click)=\"closeTableActionsMenu()\"></div>\n\n @if (tableActionsMenuView() === 'main') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n @if (mergedConfig()?.features?.columnManagement?.allowAdd) {\n <nile-menu-item (click)=\"onTableActionsAddColumn()\">\n <nile-icon slot=\"prefix\" name=\"plus\" size=\"12\"></nile-icon>\n Add Column\n </nile-menu-item>\n }\n <nile-menu-item (click)=\"openTableActionsColumnsView()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"eye\"></nile-icon>\n Show/Hide Columns\n </nile-menu-item>\n </nile-menu>\n </div>\n }\n\n @if (tableActionsMenuView() === 'columns') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n <nile-menu-item (click)=\"backToTableActionsMain()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"chevron-left\"></nile-icon>\n Back\n </nile-menu-item>\n <nile-divider></nile-divider>\n @for (column of getTableActionsColumnsVisibility(); track column.key) {\n <nile-menu-item\n [class.disabled]=\"!column.hideable\"\n (click)=\"onTableActionsToggleColumn(column.key, $event)\">\n <nile-checkbox\n [checked]=\"column.visible\"\n [disabled]=\"!column.hideable\"\n [label]=\"column.header || column.key\">\n </nile-checkbox>\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n }\n </div>\n }\n </div>\n}\n\n@if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container>\n}\n\n<!-- Shared Row Actions Dropdown -->\n<st-row-actions-dropdown [isOpen]=\"dropdownState().isOpen\" [position]=\"dropdownState().position\"\n [context]=\"dropdownState().context\" (actionClicked)=\"onRowActionClicked($event)\"\n (closed)=\"closeRowActionsDropdown()\" (tabbed)=\"onDropdownTabbed($event)\">\n</st-row-actions-dropdown>\n\n\n<!-- Bottom pagination controls -->\n@if (showBottomPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"bottom\">\n</st-pagination>\n}\n\n\n<!-- ========================================== -->\n<!-- REUSABLE TABLE TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #tableTemplate let-mode=\"mode\" let-theadStyle=\"theadStyle\">\n <table class=\"st-table-element\"\n role=\"grid\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [attr.aria-rowcount]=\"visibleCellGrid().length\"\n [attr.aria-colcount]=\"visibleColumns().length\">\n <!-- TABLE HEADER -->\n <thead [ngClass]=\"{ 'sticky': mergedConfig()?.display?.stickyHeader }\" [ngStyle]=\"theadStyle\">\n <tr role=\"row\">\n <!-- Row Number Header -->\n @if (mergedConfig()?.showRowNumber) {\n <th class=\"row-number-header header-cell sticky-left\"\n [class.row-number-header--with-icon]=\"hasRowNumberIcon\"\n scope=\"col\"\n aria-label=\"Row number\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'background-color': rowNumberStickyBackground()\n }\">\n <span class=\"row-number-cell__index\">#</span>\n </th>\n }\n <!-- Column Headers -->\n @for (column of visibleColumns(); track column.key; let colIndex = $index, isFirst = $first, isLast = $last) {\n <th\n scope=\"col\"\n [attr.aria-sort]=\"getColumnAriaSort(column)\"\n [ngClass]=\"{\n 'header-cell': mode === 'standard',\n 'sticky-left': column.sticky === 'left',\n 'sticky-right': column.sticky === 'right',\n 'sticky-right-first': column.sticky === 'right' && isFirstStickyRight(column.key),\n 'resizable': column.resizable !== false\n }\"\n [ngStyle]=\"{\n position: column.sticky ? 'sticky' : null,\n 'left.px': column.sticky === 'left' ? (column.stickyOffset || 0) : null,\n 'right.px': column.sticky === 'right' ? (column.stickyOffset || 0) : null,\n 'z-index': column.sticky ? ZIndex.STICKY_HEADER_CELL : null,\n 'width.px': column.width,\n 'min-width.px': column.minWidth ?? 100,\n 'background-color': stickyColumnBackground(column)\n }\">\n\n <st-header\n [column]=\"column\"\n [columnIndex]=\"colIndex\"\n [isFirstColumn]=\"isFirst\"\n [isLastColumn]=\"isLast\"\n [tableState]=\"getActiveTableState()\"\n [enableSorting]=\"mergedConfig()?.sorting?.enabled ?? enableSorting()\"\n [enableFiltering]=\"mergedConfig()?.filtering?.enabled ?? enableFiltering()\"\n (columnMoved)=\"onColumnMoved($event)\"\n (menuClick)=\"openColumnMenu($event, column, colIndex, isFirst, isLast)\"\n (menuKeyboard)=\"openColumnMenuFromKeyboard(colIndex, isFirst, isLast)\"\n (tabOut)=\"onHeaderTabOut()\"\n (headerNavigate)=\"onHeaderNavigate($event, colIndex)\">\n </st-header>\n\n @if (column.resizable !== false) {\n <div\n class=\"resize-handle\"\n aria-hidden=\"true\"\n stColumnResize\n [column]=\"column\"\n (columnResizing)=\"onColumnResizing($event)\"\n (columnResized)=\"onColumnResized($event)\">\n </div>\n }\n </th>\n }\n\n <!-- Settings Column Header -->\n <th\n scope=\"col\"\n aria-label=\"Actions\"\n class=\"settings-column sticky-right\"\n [ngClass]=\"{ 'header-cell': mode === 'standard' }\"\n [ngStyle]=\"{\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'background-color': rowNumberStickyBackground()\n }\">\n <div [ngClass]=\"{ 'flex-center': mode === 'virtual', 'header-content': mode === 'standard' }\">\n <st-table-actions\n [isMenuOpen]=\"tableActionsMenuIsOpen()\"\n (menuButtonClicked)=\"onTableActionsButtonClick($event)\">\n </st-table-actions>\n </div>\n </th>\n </tr>\n </thead>\n\n <!-- TABLE BODY -->\n <tbody>\n <!-- Virtual Scroll Rows -->\n @if (mode === 'virtual') {\n @for (row of visibleRows(); track trackByRowIndex($index, row); let relativeIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"getAbsoluteRowIndex(relativeIndex)\"\n [attr.aria-rowindex]=\"getAbsoluteRowIndex(relativeIndex) + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (getAbsoluteRowIndex(relativeIndex) + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(getAbsoluteRowIndex(relativeIndex))\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{getAbsoluteRowIndex(relativeIndex) + 1}}</span>\n @if (resolveRowNumberIcon(getAbsoluteRowIndex(relativeIndex)); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: getAbsoluteRowIndex(relativeIndex),\n mode: 'virtual',\n relativeIndex: relativeIndex\n }\"></ng-container>\n </tr>\n }\n }\n\n <!-- Standard Rows -->\n @if (mode === 'standard') {\n @for (row of visibleCellGrid(); track $index; let rowIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"rowIndex\"\n [attr.aria-rowindex]=\"rowIndex + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (rowIndex + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(rowIndex)\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{rowIndex + 1}}</span>\n @if (resolveRowNumberIcon(rowIndex); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: rowIndex,\n mode: 'standard'\n }\"></ng-container>\n </tr>\n }\n }\n </tbody>\n </table>\n</ng-template>\n\n<!-- ========================================== -->\n<!-- REUSABLE BODY CELL TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #bodyCellTemplate let-row=\"row\" let-rowIndex=\"rowIndex\" let-mode=\"mode\" let-relativeIndex=\"relativeIndex\">\n <!-- Data Cells -->\n @for (cell of row; track $index; let colIndex = $index) {\n <td\n role=\"gridcell\"\n [attr.aria-colindex]=\"colIndex + 1\"\n [ngClass]=\"{\n 'sticky-left': visibleColumns()[colIndex]?.sticky === 'left',\n 'sticky-right': visibleColumns()[colIndex]?.sticky === 'right',\n 'sticky-right-first': visibleColumns()[colIndex]?.sticky === 'right' && visibleColumns()[colIndex]?.key && isFirstStickyRight(visibleColumns()[colIndex].key),\n 'align-center': visibleColumns()[colIndex]?.alignment === 'center',\n 'align-right': visibleColumns()[colIndex]?.alignment === 'right',\n 'cell-focused': cell.isFocused()\n }\"\n [ngStyle]=\"{\n position: visibleColumns()[colIndex]?.sticky ? 'sticky' : null,\n 'left.px': visibleColumns()[colIndex]?.sticky === 'left' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'right.px': visibleColumns()[colIndex]?.sticky === 'right' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'z-index': visibleColumns()[colIndex]?.sticky ? ZIndex.STICKY_BODY_CELL : null,\n 'width.px': visibleColumns()[colIndex]?.width,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': bodyCellBackground(visibleColumns()[colIndex], rowIndex)\n }\"\n (click)=\"isKeyboardNavigationEnabled() ? onCellClick(rowIndex, colIndex) : null\">\n \n <!-- Virtual Scroll Cell -->\n @if (mode === 'virtual') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\" \n [editMode]=\"getEditModeForCells()\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellEdit)=\"onCellEdit($event)\" \n (cellSave)=\"onCellSave($event)\"\n (cellSaveAndNavigate)=\"onCellSaveAndNavigate($event)\" \n (cellCancel)=\"onCellCancel($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n\n <!-- Standard Cell -->\n @if (mode === 'standard') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellSave)=\"onCellSave($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n </td>\n }\n \n <!-- Row Actions Cell -->\n <td class=\"settings-column\"\n role=\"gridcell\"\n [attr.aria-colindex]=\"visibleColumns().length + 1\"\n [ngClass]=\"{\n 'has-actions': hasRowActions()\n }\"\n [ngStyle]=\"{\n position: hasRowActions() ? 'sticky' : null,\n 'right.px': hasRowActions() ? 0 : null,\n 'z-index': hasRowActions() ? ZIndex.STICKY_BODY_CELL : null,\n 'background-color': settingsColumnBodyBackground(rowIndex)\n }\">\n @if (hasRowActions()) {\n <button\n class=\"settings-trigger\"\n (click)=\"openRowActionsDropdown($event, getRowData(rowIndex), rowIndex)\"\n (keydown)=\"onSettingsTriggerKeydown($event, getRowData(rowIndex), rowIndex)\"\n type=\"button\"\n aria-label=\"Row actions\">\n <span aria-hidden=\"true\">\u22EF</span>\n </button>\n }\n </td>\n</ng-template>\n\n@if (showColumnModal()) {\n <st-column-editor-modal\n (columnCreated)=\"onColumnCreated($event)\"\n (cancelled)=\"onModalCancelled()\">\n </st-column-editor-modal>\n}\n\n<ng-template #skeletonLoader>\n @if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <div class=\"list-row\">\n @for (i of skeletonColumns; track $index) {\n <div class=\"list-content\">\n @for (j of skeletonRows; track $index) {\n <nile-skeleton-loader variant=\"text\" width=\"90%\" height=\"18\"></nile-skeleton-loader>\n }\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}:host>st-pagination{flex-shrink:0}.st-table{width:100%;overflow:auto;position:relative;flex:1 1 auto;min-height:0;border-radius:4px;border:1px solid #E6E9EB}.st-table st-table-actions{position:sticky;right:0}.st-table.keyboard-navigation-enabled{cursor:pointer}.st-table.keyboard-navigation-enabled:focus{outline:none;box-shadow:0 0 0 2px #3b82f64d}.st-table.keyboard-navigation-enabled td.cell-focused{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;position:relative;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:has(.st-cell.editing){box-shadow:var(--st-focused-cell-editing-box-shadow, 0 0 0 4px rgba(37, 99, 235, .15))}.st-table.virtual-scroll-enabled{overflow-x:visible;margin:0;border:1px solid #E6E9EB;border-collapse:separate;border-spacing:0}.st-table.virtual-scroll-enabled .st-scroll-viewport{position:relative;overflow-y:auto;overflow-x:auto;scroll-behavior:smooth}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-scroll-spacer{position:absolute;top:0;left:0;width:1px;pointer-events:none;z-index:-1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-positioner{position:absolute;top:0;left:0;right:0;will-change:transform}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element{position:relative;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;border:none;background-color:#fff;will-change:top;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr{border-bottom:1px solid #E6E9EB;transition:background-color .15s;height:2rem;box-sizing:border-box}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:last-child{border-bottom:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td{padding:0;vertical-align:middle;box-sizing:border-box;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-center{text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-right{text-align:right}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column{width:2rem;text-align:center;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:2px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table:not(.virtual-scroll-enabled) .st-table-element{width:100%;height:100%;overflow:auto;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table:not(.virtual-scroll-enabled) .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr{height:2rem;box-sizing:border-box}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:last-child{border-bottom:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td{padding:0;vertical-align:middle;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-center{text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-right{text-align:right}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column{position:sticky;right:0;width:2rem;text-align:center;border-right:none;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content{display:flex;height:2rem;align-items:center}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content .table-header-text{flex-grow:1;padding-left:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element .settings-column>.header-content{display:flex;align-items:center;justify-content:center}.table-actions-menu-container{position:fixed;inset:0;z-index:9996;pointer-events:none}.table-actions-menu-backdrop{position:absolute;inset:0;background:transparent;pointer-events:auto}.table-actions-menu-panel{position:fixed;pointer-events:auto;z-index:9997;min-width:15rem}.table-actions-menu-panel nile-menu{max-height:30rem;overflow-y:auto}.table-actions-menu-panel nile-menu::part(base){width:fit-content;min-height:auto}.table-actions-menu-panel nile-menu nile-menu-item::part(base){min-height:2.5rem}.table-actions-menu-panel nile-menu nile-menu-item::part(label){font-size:12px}.table-actions-menu-panel nile-menu nile-menu-item.disabled{opacity:.5;cursor:not-allowed}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(base){display:flex;align-items:center}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(label){font-size:12px;margin-top:0}.flex-center{display:flex;align-items:center;justify-content:center}.list-row .list-content{display:flex;justify-content:space-evenly;gap:4px;margin-bottom:1rem}.list-row{padding:1rem}\n"] }]
12055
+ ], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<!-- Top pagination controls -->\n@if (showTopPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"top\">\n </st-pagination>\n}\n\n@if (!(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <div class=\"st-table\"\n role=\"region\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [ngClass]=\"{\n 'virtual-scroll-enabled': isVirtualScrollEnabled(),\n 'keyboard-navigation-enabled': isKeyboardNavigationEnabled()\n }\"\n [ngStyle]=\"tableWrapperStyle()\"\n stKeyboardNavigation\n [tableState]=\"getActiveTableState()\"\n [addRowOnNavigatePastEnd]=\"mergedConfig()?.features?.keyboardNavigation?.addRowOnNavigatePastEnd || false\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? 0 : -1\"\n (focus)=\"onTableContainerFocus($event)\">\n <!-- Unified Table Actions Menu -->\n\n <!-- Virtual scroll viewport wrapper -->\n @if (isVirtualScrollEnabled()) {\n <div class=\"st-scroll-viewport\" #scrollViewport\n [ngStyle]=\"{ 'height.px': getVirtualScrollViewportHeight() }\">\n\n <!-- Spacer to create scrollable area -->\n <div class=\"st-scroll-spacer\" [ngStyle]=\"{ 'height.px': virtualScrollTotalHeight() }\">\n </div>\n\n <!-- Table positioner with transform (instead of tbody) -->\n <div class=\"st-table-positioner\" [ngStyle]=\"{ transform: 'translateY(' + virtualScrollOffsetY() + 'px)' }\">\n <!-- Table with only visible rows -->\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'virtual',\n theadStyle: { top: virtualScrollOffsetYNeg() + 'px' }\n }\"></ng-container>\n </div>\n </div>\n }\n \n <!-- Standard table (when virtual scroll disabled) -->\n @if (!isVirtualScrollEnabled()) {\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'standard',\n theadStyle: null\n }\"></ng-container>\n }\n\n <!-- Shared Column Menu Dropdown -->\n <st-column-menu-dropdown\n [isOpen]=\"columnMenuState().isOpen\"\n [position]=\"columnMenuState().position\"\n [context]=\"columnMenuState().context\"\n (actionClicked)=\"onColumnActionClicked($event)\"\n (closed)=\"closeColumnMenu()\">\n </st-column-menu-dropdown>\n\n <!-- Screen reader live region for dynamic announcements (sort, filter, pagination) -->\n <div class=\"sr-only\" aria-live=\"polite\" aria-atomic=\"true\" aria-relevant=\"text\"></div>\n <!-- Table Actions Menu (outside virtual scroll transform context) -->\n @if (tableActionsMenuIsOpen()) {\n <div class=\"table-actions-menu-container\">\n <div class=\"table-actions-menu-backdrop\" (click)=\"closeTableActionsMenu()\"></div>\n\n @if (tableActionsMenuView() === 'main') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n @if (mergedConfig()?.features?.columnManagement?.allowAdd) {\n <nile-menu-item (click)=\"onTableActionsAddColumn()\">\n <nile-icon slot=\"prefix\" name=\"plus\" size=\"12\"></nile-icon>\n Add Column\n </nile-menu-item>\n }\n <nile-menu-item (click)=\"openTableActionsColumnsView()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"eye\"></nile-icon>\n Show/Hide Columns\n </nile-menu-item>\n </nile-menu>\n </div>\n }\n\n @if (tableActionsMenuView() === 'columns') {\n <div class=\"table-actions-menu-panel\" [ngStyle]=\"tableActionsDropdownStyle()\">\n <nile-menu>\n <nile-menu-item (click)=\"backToTableActionsMain()\">\n <nile-icon size=\"12\" slot=\"prefix\" name=\"chevron-left\"></nile-icon>\n Back\n </nile-menu-item>\n <nile-divider></nile-divider>\n @for (column of getTableActionsColumnsVisibility(); track column.key) {\n <nile-menu-item\n [class.disabled]=\"!column.hideable\"\n (click)=\"onTableActionsToggleColumn(column.key, $event)\">\n <nile-checkbox\n [checked]=\"column.visible\"\n [disabled]=\"!column.hideable\"\n [label]=\"column.header || column.key\">\n </nile-checkbox>\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n }\n </div>\n }\n </div>\n}\n\n@if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container>\n}\n\n<!-- Shared Row Actions Dropdown -->\n<st-row-actions-dropdown [isOpen]=\"dropdownState().isOpen\" [position]=\"dropdownState().position\"\n [context]=\"dropdownState().context\" (actionClicked)=\"onRowActionClicked($event)\"\n (closed)=\"closeRowActionsDropdown()\" (tabbed)=\"onDropdownTabbed($event)\">\n</st-row-actions-dropdown>\n\n\n<!-- Bottom pagination controls -->\n@if (showBottomPagination() && !(mergedConfig()?.tableSkeleton?.enabled | async)) {\n <st-pagination \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n position=\"bottom\">\n</st-pagination>\n}\n\n\n<!-- ========================================== -->\n<!-- REUSABLE TABLE TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #tableTemplate let-mode=\"mode\" let-theadStyle=\"theadStyle\">\n <table class=\"st-table-element\"\n role=\"grid\"\n [attr.aria-label]=\"mergedConfig()?.display?.ariaLabel || 'Data table'\"\n [attr.aria-rowcount]=\"visibleCellGrid().length\"\n [attr.aria-colcount]=\"visibleColumns().length\">\n <!-- TABLE HEADER -->\n <thead [ngClass]=\"{ 'sticky': mergedConfig()?.display?.stickyHeader }\" [ngStyle]=\"theadStyle\">\n <tr role=\"row\">\n <!-- Row Number Header -->\n @if (mergedConfig()?.showRowNumber) {\n <th class=\"row-number-header header-cell sticky-left\"\n [class.row-number-header--with-icon]=\"hasRowNumberIcon\"\n scope=\"col\"\n aria-label=\"Row number\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'background-color': rowNumberStickyBackground()\n }\">\n <span class=\"row-number-cell__index\">#</span>\n </th>\n }\n <!-- Column Headers -->\n @for (column of visibleColumns(); track column.key; let colIndex = $index, isFirst = $first, isLast = $last) {\n <th\n scope=\"col\"\n [attr.aria-sort]=\"getColumnAriaSort(column)\"\n [ngClass]=\"{\n 'header-cell': mode === 'standard',\n 'sticky-left': column.sticky === 'left',\n 'sticky-right': column.sticky === 'right',\n 'sticky-right-first': column.sticky === 'right' && isFirstStickyRight(column.key),\n 'resizable': column.resizable !== false\n }\"\n [ngStyle]=\"{\n position: column.sticky ? 'sticky' : null,\n 'left.px': column.sticky === 'left' ? (column.stickyOffset || 0) : null,\n 'right.px': column.sticky === 'right' ? (column.stickyOffset || 0) : null,\n 'z-index': column.sticky ? ZIndex.STICKY_HEADER_CELL : null,\n 'width.px': column.width,\n 'min-width.px': column.minWidth ?? 100,\n 'background-color': stickyColumnBackground(column)\n }\">\n\n <st-header\n [column]=\"column\"\n [columnIndex]=\"colIndex\"\n [isFirstColumn]=\"isFirst\"\n [isLastColumn]=\"isLast\"\n [tableState]=\"getActiveTableState()\"\n [keyboardNavigationEnabled]=\"isKeyboardNavigationEnabled()\"\n [enableSorting]=\"mergedConfig()?.sorting?.enabled ?? enableSorting()\"\n [enableFiltering]=\"mergedConfig()?.filtering?.enabled ?? enableFiltering()\"\n (columnMoved)=\"onColumnMoved($event)\"\n (menuClick)=\"openColumnMenu($event, column, colIndex, isFirst, isLast)\"\n (menuKeyboard)=\"openColumnMenuFromKeyboard(colIndex, isFirst, isLast)\"\n (tabOut)=\"onHeaderTabOut()\"\n (headerNavigate)=\"onHeaderNavigate($event, colIndex)\">\n </st-header>\n\n @if (column.resizable !== false) {\n <div\n class=\"resize-handle\"\n aria-hidden=\"true\"\n stColumnResize\n [column]=\"column\"\n (columnResizing)=\"onColumnResizing($event)\"\n (columnResized)=\"onColumnResized($event)\">\n </div>\n }\n </th>\n }\n\n <!-- Settings Column Header -->\n <th\n scope=\"col\"\n aria-label=\"Actions\"\n class=\"settings-column sticky-right\"\n [ngClass]=\"{ 'header-cell': mode === 'standard' }\"\n [ngStyle]=\"{\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'background-color': rowNumberStickyBackground()\n }\">\n <div [ngClass]=\"{ 'flex-center': mode === 'virtual', 'header-content': mode === 'standard' }\">\n <st-table-actions\n [isMenuOpen]=\"tableActionsMenuIsOpen()\"\n (menuButtonClicked)=\"onTableActionsButtonClick($event)\">\n </st-table-actions>\n </div>\n </th>\n </tr>\n </thead>\n\n <!-- TABLE BODY -->\n <tbody>\n <!-- Virtual Scroll Rows -->\n @if (mode === 'virtual') {\n @for (row of visibleRows(); track trackByRowIndex($index, row); let relativeIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"getAbsoluteRowIndex(relativeIndex)\"\n [attr.aria-rowindex]=\"getAbsoluteRowIndex(relativeIndex) + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (getAbsoluteRowIndex(relativeIndex) + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(getAbsoluteRowIndex(relativeIndex))\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{getAbsoluteRowIndex(relativeIndex) + 1}}</span>\n @if (resolveRowNumberIcon(getAbsoluteRowIndex(relativeIndex)); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: getAbsoluteRowIndex(relativeIndex),\n mode: 'virtual',\n relativeIndex: relativeIndex\n }\"></ng-container>\n </tr>\n }\n }\n\n <!-- Standard Rows -->\n @if (mode === 'standard') {\n @for (row of visibleCellGrid(); track $index; let rowIndex = $index) {\n <tr role=\"row\"\n [attr.data-row-index]=\"rowIndex\"\n [attr.aria-rowindex]=\"rowIndex + 1\">\n <!-- Row Number Cell -->\n @if (mergedConfig()?.showRowNumber) {\n <td class=\"row-number-cell\"\n role=\"rowheader\"\n [class.row-number-cell--with-icon]=\"hasRowNumberIcon\"\n [attr.aria-label]=\"'Row ' + (rowIndex + 1)\"\n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'width.px': rowNumberColumnWidth,\n 'min-width.px': rowNumberColumnWidth,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': rowNumberCellBackground(rowIndex)\n }\">\n <span class=\"row-number-cell__inner\">\n <span class=\"row-number-cell__index\">{{rowIndex + 1}}</span>\n @if (resolveRowNumberIcon(rowIndex); as icon) {\n @if (icon.tooltip) {\n <nile-tooltip class=\"row-number-cell__icon-wrap\" [content]=\"icon.tooltip\" placement=\"top\" [hoist]=\"true\">\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" [attr.aria-label]=\"icon.tooltip\"></nile-icon>\n </nile-tooltip>\n } @else {\n <nile-icon [name]=\"icon.name\" size=\"14\" class=\"row-number-cell__icon\" aria-hidden=\"true\"></nile-icon>\n }\n }\n </span>\n </td>\n }\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: rowIndex,\n mode: 'standard'\n }\"></ng-container>\n </tr>\n }\n }\n </tbody>\n </table>\n</ng-template>\n\n<!-- ========================================== -->\n<!-- REUSABLE BODY CELL TEMPLATE -->\n<!-- ========================================== -->\n<ng-template #bodyCellTemplate let-row=\"row\" let-rowIndex=\"rowIndex\" let-mode=\"mode\" let-relativeIndex=\"relativeIndex\">\n <!-- Data Cells -->\n @for (cell of row; track $index; let colIndex = $index) {\n <td\n role=\"gridcell\"\n [attr.aria-colindex]=\"colIndex + 1\"\n [ngClass]=\"{\n 'sticky-left': visibleColumns()[colIndex]?.sticky === 'left',\n 'sticky-right': visibleColumns()[colIndex]?.sticky === 'right',\n 'sticky-right-first': visibleColumns()[colIndex]?.sticky === 'right' && visibleColumns()[colIndex]?.key && isFirstStickyRight(visibleColumns()[colIndex].key),\n 'align-center': visibleColumns()[colIndex]?.alignment === 'center',\n 'align-right': visibleColumns()[colIndex]?.alignment === 'right',\n 'cell-focused': cell.isFocused()\n }\"\n [ngStyle]=\"{\n position: visibleColumns()[colIndex]?.sticky ? 'sticky' : null,\n 'left.px': visibleColumns()[colIndex]?.sticky === 'left' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'right.px': visibleColumns()[colIndex]?.sticky === 'right' ? (visibleColumns()[colIndex]?.stickyOffset || 0) : null,\n 'z-index': visibleColumns()[colIndex]?.sticky ? ZIndex.STICKY_BODY_CELL : null,\n 'width.px': visibleColumns()[colIndex]?.width,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null,\n 'background-color': bodyCellBackground(visibleColumns()[colIndex], rowIndex)\n }\"\n (click)=\"isKeyboardNavigationEnabled() ? onCellClick(rowIndex, colIndex) : null\">\n \n <!-- Virtual Scroll Cell -->\n @if (mode === 'virtual') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\" \n [editMode]=\"getEditModeForCells()\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellEdit)=\"onCellEdit($event)\" \n (cellSave)=\"onCellSave($event)\"\n (cellSaveAndNavigate)=\"onCellSaveAndNavigate($event)\" \n (cellCancel)=\"onCellCancel($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n\n <!-- Standard Cell -->\n @if (mode === 'standard') {\n <st-cell \n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig()!\"\n [columnIndex]=\"colIndex\"\n (cellSave)=\"onCellSave($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n }\n </td>\n }\n \n <!-- Row Actions Cell -->\n <td class=\"settings-column\"\n role=\"gridcell\"\n [attr.aria-colindex]=\"visibleColumns().length + 1\"\n [ngClass]=\"{\n 'has-actions': hasRowActions()\n }\"\n [ngStyle]=\"{\n position: hasRowActions() ? 'sticky' : null,\n 'right.px': hasRowActions() ? 0 : null,\n 'z-index': hasRowActions() ? ZIndex.STICKY_BODY_CELL : null,\n 'background-color': settingsColumnBodyBackground(rowIndex)\n }\">\n @if (hasRowActions()) {\n <button\n class=\"settings-trigger\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? -1 : null\"\n (click)=\"openRowActionsDropdown($event, getRowData(rowIndex), rowIndex)\"\n (keydown)=\"onSettingsTriggerKeydown($event, getRowData(rowIndex), rowIndex)\"\n type=\"button\"\n aria-label=\"Row actions\">\n <span aria-hidden=\"true\">\u22EF</span>\n </button>\n }\n </td>\n</ng-template>\n\n@if (showColumnModal()) {\n <st-column-editor-modal\n (columnCreated)=\"onColumnCreated($event)\"\n (cancelled)=\"onModalCancelled()\">\n </st-column-editor-modal>\n}\n\n<ng-template #skeletonLoader>\n @if (mergedConfig()?.tableSkeleton?.enabled | async) {\n <div class=\"list-row\">\n @for (i of skeletonColumns; track $index) {\n <div class=\"list-content\">\n @for (j of skeletonRows; track $index) {\n <nile-skeleton-loader variant=\"text\" width=\"90%\" height=\"18\"></nile-skeleton-loader>\n }\n </div>\n }\n </div>\n }\n</ng-template>\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}:host>st-pagination{flex-shrink:0}.st-table{width:100%;overflow:auto;position:relative;flex:1 1 auto;min-height:0;border-radius:4px;border:1px solid #E6E9EB}.st-table st-table-actions{position:sticky;right:0}.st-table.keyboard-navigation-enabled{cursor:pointer}.st-table.keyboard-navigation-enabled:focus{outline:none;box-shadow:0 0 0 2px #3b82f64d}.st-table.keyboard-navigation-enabled td.cell-focused{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;position:relative;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:-1px;box-shadow:var(--st-focused-cell-box-shadow, 0 0 0 3px rgba(49, 130, 206, .1))}.st-table.keyboard-navigation-enabled td.cell-focused:has(.st-cell.editing){box-shadow:var(--st-focused-cell-editing-box-shadow, 0 0 0 4px rgba(37, 99, 235, .15))}.st-table.virtual-scroll-enabled{overflow-x:visible;margin:0;border:1px solid #E6E9EB;border-collapse:separate;border-spacing:0}.st-table.virtual-scroll-enabled .st-scroll-viewport{position:relative;overflow-y:auto;overflow-x:auto;scroll-behavior:smooth}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-scroll-spacer{position:absolute;top:0;left:0;width:1px;pointer-events:none;z-index:-1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-positioner{position:absolute;top:0;left:0;right:0;will-change:transform}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element{position:relative;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;border:none;background-color:#fff;will-change:top;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr{border-bottom:1px solid #E6E9EB;transition:background-color .15s;height:2rem;box-sizing:border-box}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:last-child{border-bottom:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td{padding:0;vertical-align:middle;box-sizing:border-box;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-center{text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-right{text-align:right}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column{width:2rem;text-align:center;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger:focus{outline:var(--st-focused-cell-outline-width, 2px) solid var(--st-focused-cell-outline-color, #4299e1);outline-offset:2px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,#00000014,#0000)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,#0000,#00000014)}.st-table:not(.virtual-scroll-enabled) .st-table-element{width:100%;height:100%;overflow:auto;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table:not(.virtual-scroll-enabled) .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:var(--ng-font-weight-bold);font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header{font-weight:300;font-size:12px;background-color:#f8f8f8;text-align:center;padding:0 6px}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header.row-number-header--with-icon>*{display:inline-block;min-width:22px;text-align:right;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr{height:2rem;box-sizing:border-box}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:has(.st-cell.editing){position:relative;z-index:20}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:last-child{border-bottom:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td{padding:0;vertical-align:middle;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td:has(.st-cell.editing){overflow:visible}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell{font-weight:300;font-size:12px;background-color:#f8f8f8;min-width:30px;padding:0 6px;white-space:nowrap;text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__inner{display:inline-flex;align-items:center;justify-content:center;gap:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__index{display:inline-block;font-variant-numeric:tabular-nums}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon-wrap{display:inline-flex;align-items:center;flex:0 0 auto}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell .row-number-cell__icon{display:inline-flex;color:var(--st-row-number-icon-color, var(--nile-colors-dark-500, #636363));line-height:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon{text-align:left}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__inner{justify-content:flex-start;width:100%}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell.row-number-cell--with-icon .row-number-cell__index{text-align:right;min-width:22px}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-center{text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-right{text-align:right}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column{position:sticky;right:0;width:2rem;text-align:center;border-right:none;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content{display:flex;height:2rem;align-items:center}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content .table-header-text{flex-grow:1;padding-left:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element .settings-column>.header-content{display:flex;align-items:center;justify-content:center}.table-actions-menu-container{position:fixed;inset:0;z-index:9996;pointer-events:none}.table-actions-menu-backdrop{position:absolute;inset:0;background:transparent;pointer-events:auto}.table-actions-menu-panel{position:fixed;pointer-events:auto;z-index:9997;min-width:15rem}.table-actions-menu-panel nile-menu{max-height:30rem;overflow-y:auto}.table-actions-menu-panel nile-menu::part(base){width:fit-content;min-height:auto}.table-actions-menu-panel nile-menu nile-menu-item::part(base){min-height:2.5rem}.table-actions-menu-panel nile-menu nile-menu-item::part(label){font-size:12px}.table-actions-menu-panel nile-menu nile-menu-item.disabled{opacity:.5;cursor:not-allowed}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(base){display:flex;align-items:center}.table-actions-menu-panel nile-menu nile-menu-item nile-checkbox::part(label){font-size:12px;margin-top:0}.flex-center{display:flex;align-items:center;justify-content:center}.list-row .list-content{display:flex;justify-content:space-evenly;gap:4px;margin-bottom:1rem}.list-row{padding:1rem}\n"] }]
11995
12056
  }], ctorParameters: () => [], propDecorators: { tableConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableConfig", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], data$: [{ type: i0.Input, args: [{ isSignal: true, alias: "data$", required: false }] }], tableState: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableState", required: false }] }], enableSorting: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSorting", required: false }] }], enableFiltering: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableFiltering", required: false }] }], validateConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "validateConfig", required: false }] }], stateChange: [{ type: i0.Output, args: ["stateChange"] }], dataChange: [{ type: i0.Output, args: ["dataChange"] }], cellEdit: [{ type: i0.Output, args: ["cellEdit"] }], cellSave: [{ type: i0.Output, args: ["cellSave"] }], cellCancel: [{ type: i0.Output, args: ["cellCancel"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], columnResized: [{ type: i0.Output, args: ["columnResized"] }], columnMoved: [{ type: i0.Output, args: ["columnMoved"] }], configValidationErrors: [{ type: i0.Output, args: ["configValidationErrors"] }], addColumnClicked: [{ type: i0.Output, args: ["addColumnClicked"] }], columnAdded: [{ type: i0.Output, args: ["columnAdded"] }], rowAction: [{ type: i0.Output, args: ["rowAction"] }], validationStateChange: [{ type: i0.Output, args: ["validationStateChange"] }], requestAddRow: [{ type: i0.Output, args: ["requestAddRow"] }], requestFocusTabs: [{ type: i0.Output, args: ["requestFocusTabs"] }], scrollViewport: [{
11996
12057
  type: ViewChild,
11997
12058
  args: ['scrollViewport', { read: ElementRef }]
@@ -14060,11 +14121,18 @@ class StWorkbookComponent {
14060
14121
  target?.focus();
14061
14122
  return;
14062
14123
  }
14063
- // Table sheets: land on the first column-action button. Headers without
14064
- // an action button are skipped only column actions are focusable in
14065
- // the header row.
14066
- const firstMenuBtn = host.querySelector('thead .st-header .column-menu-trigger');
14067
- firstMenuBtn?.focus();
14124
+ // Table sheets: land on the grid region (the keyboard-nav container). This
14125
+ // makes the FORWARD tab order (sheet-tab region column-menu row-actions
14126
+ // → …) mirror the REVERSE native order, which already passes through the
14127
+ // region. Cell navigation is entered from here with the arrow keys (see
14128
+ // StKeyboardNavigationDirective); a plain Tab continues to the next control.
14129
+ const region = host.querySelector('.st-table[role="region"]');
14130
+ if (region) {
14131
+ region.focus();
14132
+ }
14133
+ else {
14134
+ host.querySelector('thead .st-header .column-menu-trigger')?.focus();
14135
+ }
14068
14136
  });
14069
14137
  }
14070
14138
  updateActiveSheet() {
@@ -14467,11 +14535,11 @@ class StWorkbookComponent {
14467
14535
  }
14468
14536
  }
14469
14537
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StWorkbookComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14470
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StWorkbookComponent, isStandalone: true, selector: "st-workbook", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, sheetsData: { classPropertyName: "sheetsData", publicName: "sheetsData", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sheetChanged: "sheetChanged", addSheet: "addSheet", sheetTabAction: "sheetTabAction", workbookAction: "workbookAction", cellChange: "cellChange", cellSave: "cellSave", tableStateChange: "tableStateChange", fullscreenToggle: "fullscreenToggle", requestAddRow: "requestAddRow", conditionBuilderValueChange: "conditionBuilderValueChange", conditionBuilderValidityChange: "conditionBuilderValidityChange" }, viewQueries: [{ propertyName: "tableComponent", first: true, predicate: StTableComponent, descendants: true }, { propertyName: "workbookTabGroup", first: true, predicate: ["workbookTabGroup"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen()\">\n <nile-tab-group #workbookTabGroup [activeIndex]=\"activeSheetIndex()\">\n \n <!-- Sheet Tabs (one per sheet) -->\n @for (sheet of sheets(); track sheet.id; let i = $index) {\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-sheet-tab\"\n [class.active]=\"i === activeSheetIndex()\"\n role=\"tab\"\n [attr.aria-selected]=\"i === activeSheetIndex()\"\n [attr.aria-label]=\"sheet.name\"\n [attr.tabindex]=\"i === activeSheetIndex() ? 0 : -1\"\n (click)=\"onTabChange(i)\"\n (keydown)=\"onSheetTabKeydown($event, i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n\n <!-- Tab actions dropdown button -->\n @if (hasTabActions(sheet)) {\n <button class=\"tab-actions-button\"\n type=\"button\"\n [attr.aria-label]=\"'Actions for ' + sheet.name\"\n (click)=\"openTabActions($event, sheet, i)\">\n <nile-icon name=\"arrowdown\" size=\"14\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n </div>\n </nile-tab>\n }\n \n <!-- Toolbar Tab (for workbook controls) -->\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\" role=\"toolbar\" aria-label=\"Workbook toolbar\"\n (keydown)=\"onToolbarKeydown($event)\">\n\n <!-- Autosave Indicator \u2014 hidden unless `autosave.showIndicator: true` -->\n @if (autosaveIndicatorVisible()) {\n <div class=\"autosave-indicator\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (!isSaving() && lastSaveTime()) {\n <nile-icon\n name=\"save\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saved at {{ lastSaveTime() | date:'HH:mm:ss' }}</span>\n }\n @if (isSaving()) {\n <nile-icon\n name=\"loader\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saving\u2026</span>\n }\n </div>\n }\n\n <!-- Toolbar Workbook Actions (shown as individual buttons) -->\n @for (action of toolbarWorkbookActions(); track action.id) {\n <button class=\"toolbar-action-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n @if (!action.icon) {\n <span>{{ action.label }}</span>\n }\n </button>\n }\n\n <!-- Workbook Actions Dropdown -->\n @if (visibleWorkbookActions().length > 0) {\n <button class=\"workbook-actions-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Workbook actions\"\n [attr.aria-expanded]=\"workbookActionsOpen()\"\n aria-haspopup=\"true\"\n (click)=\"toggleWorkbookActions($event)\">\n <nile-icon name=\"settings\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Add Sheet Button -->\n @if (canAddSheet) {\n <button class=\"add-sheet-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Add sheet\"\n (click)=\"onAddSheet()\">\n <nile-icon name=\"plus\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Fullscreen Button -->\n @if (config().display?.allowFullscreen !== false) {\n <button class=\"fullscreen-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n [attr.aria-pressed]=\"isFullscreen()\"\n (click)=\"toggleFullscreen()\">\n <nile-icon [name]=\"isFullscreen() ? 'collapse' : 'expand-06'\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: content is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using @for with track to force complete reinitialization when tableComponentKey changes -->\n @for (key of [tableComponentKey()]; track key) {\n @switch (activeSheetContentType) {\n @case ('condition-builder') {\n @if (activeSheet()?.conditionBuilder) {\n <st-condition-builder\n [attr.data-sheet-key]=\"key\"\n [config]=\"activeSheet()!.conditionBuilder!.config\"\n [value]=\"activeSheet()!.conditionBuilder!.value\"\n (valueChange)=\"onConditionBuilderValueChange($event)\"\n (validityChange)=\"onConditionBuilderValidityChange($event)\">\n </st-condition-builder>\n }\n }\n @default {\n @if (currentTableConfig() && currentTableState()) {\n <st-table\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig()!\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState()!\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\"\n (requestFocusTabs)=\"onRequestFocusTabs()\">\n </st-table>\n }\n }\n }\n }\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n@if (tabActionsOpen()) {\n <div class=\"tab-actions-dropdown\" [ngStyle]=\"tabActionsPosition()\" (keydown)=\"onTabActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" [attr.aria-label]=\"(selectedSheet()?.name || 'Sheet') + ' actions'\">\n <nile-menu>\n @for (action of selectedSheet()?.tabActions; track action.id) {\n <nile-menu-item tabindex=\"-1\" (click)=\"onTabActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Workbook Actions Dropdown -->\n@if (workbookActionsOpen()) {\n <div class=\"workbook-actions-dropdown\" [ngStyle]=\"workbookActionsPosition()\" (keydown)=\"onWorkbookActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" aria-label=\"Workbook actions\">\n <nile-menu>\n @for (action of visibleWorkbookActions(); track action.id) {\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Fullscreen Backdrop -->\n@if (isFullscreen()) {\n <div class=\"fullscreen-backdrop\" (click)=\"toggleFullscreen()\">\n </div>\n}\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:#fff;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:var(--ng-font-weight-medium);font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200);flex-shrink:0;position:sticky;right:0;z-index:3;align-self:stretch;background-color:#fafafa;box-shadow:-8px 0 12px -8px #0000001f}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.workbook-toolbar-tab button.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:#00000080;z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0;flex-wrap:nowrap;width:max-content;min-width:100%;box-sizing:border-box}nile-tab-group nile-tab.workbook-sheet-tab{flex-shrink:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:var(--ng-font-weight-bold)}nile-tab-group nile-tab-panel::part(base){padding:0;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: StTableComponent, selector: "st-table", inputs: ["tableConfig", "data", "data$", "tableState", "enableSorting", "enableFiltering", "validateConfig"], outputs: ["stateChange", "dataChange", "cellEdit", "cellSave", "cellCancel", "cellChange", "columnResized", "columnMoved", "configValidationErrors", "addColumnClicked", "columnAdded", "rowAction", "validationStateChange", "requestAddRow", "requestFocusTabs"] }, { kind: "component", type: StConditionBuilderComponent, selector: "st-condition-builder", inputs: ["config", "value", "disabled"], outputs: ["valueChange", "validityChange"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] }); }
14538
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: StWorkbookComponent, isStandalone: true, selector: "st-workbook", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, sheetsData: { classPropertyName: "sheetsData", publicName: "sheetsData", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sheetChanged: "sheetChanged", addSheet: "addSheet", sheetTabAction: "sheetTabAction", workbookAction: "workbookAction", cellChange: "cellChange", cellSave: "cellSave", tableStateChange: "tableStateChange", fullscreenToggle: "fullscreenToggle", requestAddRow: "requestAddRow", conditionBuilderValueChange: "conditionBuilderValueChange", conditionBuilderValidityChange: "conditionBuilderValidityChange" }, viewQueries: [{ propertyName: "tableComponent", first: true, predicate: StTableComponent, descendants: true }, { propertyName: "workbookTabGroup", first: true, predicate: ["workbookTabGroup"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen()\">\n <nile-tab-group #workbookTabGroup [activeIndex]=\"activeSheetIndex()\">\n \n <!-- Sheet Tabs (one per sheet) -->\n @for (sheet of sheets(); track sheet.id; let i = $index) {\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-sheet-tab\"\n [class.active]=\"i === activeSheetIndex()\"\n role=\"tab\"\n [attr.aria-selected]=\"i === activeSheetIndex()\"\n [attr.aria-label]=\"sheet.name\"\n [attr.tabindex]=\"i === activeSheetIndex() ? 0 : -1\"\n (click)=\"onTabChange(i)\"\n (keydown)=\"onSheetTabKeydown($event, i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n\n <!-- Tab actions affordance. Rendered as a non-interactive, aria-hidden\n <span> (not a <button>) so it is NOT a nested interactive control\n inside the role=\"tab\" element \u2014 that nesting fails WCAG 4.1.2 /\n axe \"nested-interactive\" and confuses screen readers & keyboard\n focus order. Mouse users still click it; keyboard users open the\n same menu via Space on the focused tab (see onSheetTabKeydown),\n which is why the Tab handler already skips this element. -->\n @if (hasTabActions(sheet)) {\n <span class=\"tab-actions-button\"\n aria-hidden=\"true\"\n (click)=\"openTabActions($event, sheet, i)\">\n <nile-icon name=\"arrowdown\" size=\"14\" aria-hidden=\"true\"></nile-icon>\n </span>\n }\n </div>\n </nile-tab>\n }\n \n <!-- Toolbar \"Tab\" (for workbook controls). This is NOT a real tab \u2014 it's a\n disabled layout slot that hosts the workbook toolbar. NOTE: nile-tab force-sets\n role=\"tab\" on itself (setAttribute in its update cycle), so a role override here\n does NOT stick \u2014 the inner interactive buttons remain nested inside role=\"tab\"\n (axe \"nested-interactive\"). Fixing that requires a nile-elements (nile-tab)\n change or not using nile-tab for the toolbar. Tracked separately. -->\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\" role=\"toolbar\" aria-label=\"Workbook toolbar\"\n (keydown)=\"onToolbarKeydown($event)\">\n\n <!-- Autosave Indicator \u2014 hidden unless `autosave.showIndicator: true` -->\n @if (autosaveIndicatorVisible()) {\n <div class=\"autosave-indicator\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (!isSaving() && lastSaveTime()) {\n <nile-icon\n name=\"save\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saved at {{ lastSaveTime() | date:'HH:mm:ss' }}</span>\n }\n @if (isSaving()) {\n <nile-icon\n name=\"loader\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saving\u2026</span>\n }\n </div>\n }\n\n <!-- Toolbar Workbook Actions (shown as individual buttons) -->\n @for (action of toolbarWorkbookActions(); track action.id) {\n <button class=\"toolbar-action-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n @if (!action.icon) {\n <span>{{ action.label }}</span>\n }\n </button>\n }\n\n <!-- Workbook Actions Dropdown -->\n @if (visibleWorkbookActions().length > 0) {\n <button class=\"workbook-actions-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Workbook actions\"\n [attr.aria-expanded]=\"workbookActionsOpen()\"\n aria-haspopup=\"true\"\n (click)=\"toggleWorkbookActions($event)\">\n <nile-icon name=\"settings\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Add Sheet Button -->\n @if (canAddSheet) {\n <button class=\"add-sheet-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Add sheet\"\n (click)=\"onAddSheet()\">\n <nile-icon name=\"plus\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Fullscreen Button -->\n @if (config().display?.allowFullscreen !== false) {\n <button class=\"fullscreen-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n [attr.aria-pressed]=\"isFullscreen()\"\n (click)=\"toggleFullscreen()\">\n <nile-icon [name]=\"isFullscreen() ? 'collapse' : 'expand-06'\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: content is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using @for with track to force complete reinitialization when tableComponentKey changes -->\n @for (key of [tableComponentKey()]; track key) {\n @switch (activeSheetContentType) {\n @case ('condition-builder') {\n @if (activeSheet()?.conditionBuilder) {\n <st-condition-builder\n [attr.data-sheet-key]=\"key\"\n [config]=\"activeSheet()!.conditionBuilder!.config\"\n [value]=\"activeSheet()!.conditionBuilder!.value\"\n (valueChange)=\"onConditionBuilderValueChange($event)\"\n (validityChange)=\"onConditionBuilderValidityChange($event)\">\n </st-condition-builder>\n }\n }\n @default {\n @if (currentTableConfig() && currentTableState()) {\n <st-table\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig()!\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState()!\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\"\n (requestFocusTabs)=\"onRequestFocusTabs()\">\n </st-table>\n }\n }\n }\n }\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n@if (tabActionsOpen()) {\n <div class=\"tab-actions-dropdown\" [ngStyle]=\"tabActionsPosition()\" (keydown)=\"onTabActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" [attr.aria-label]=\"(selectedSheet()?.name || 'Sheet') + ' actions'\">\n <nile-menu>\n @for (action of selectedSheet()?.tabActions; track action.id) {\n <nile-menu-item tabindex=\"-1\" (click)=\"onTabActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Workbook Actions Dropdown -->\n@if (workbookActionsOpen()) {\n <div class=\"workbook-actions-dropdown\" [ngStyle]=\"workbookActionsPosition()\" (keydown)=\"onWorkbookActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" aria-label=\"Workbook actions\">\n <nile-menu>\n @for (action of visibleWorkbookActions(); track action.id) {\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Fullscreen Backdrop -->\n@if (isFullscreen()) {\n <div class=\"fullscreen-backdrop\" (click)=\"toggleFullscreen()\">\n </div>\n}\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:#fff;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:var(--ng-font-weight-medium);font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200);flex-shrink:0;position:sticky;right:0;z-index:3;align-self:stretch;background-color:#fafafa;box-shadow:-8px 0 12px -8px #0000001f}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.workbook-toolbar-tab button.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:#00000080;z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0;flex-wrap:nowrap;width:max-content;min-width:100%;box-sizing:border-box}nile-tab-group nile-tab.workbook-sheet-tab{flex-shrink:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:var(--ng-font-weight-bold)}nile-tab-group nile-tab-panel::part(base){padding:0;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow:hidden}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: StTableComponent, selector: "st-table", inputs: ["tableConfig", "data", "data$", "tableState", "enableSorting", "enableFiltering", "validateConfig"], outputs: ["stateChange", "dataChange", "cellEdit", "cellSave", "cellCancel", "cellChange", "columnResized", "columnMoved", "configValidationErrors", "addColumnClicked", "columnAdded", "rowAction", "validationStateChange", "requestAddRow", "requestFocusTabs"] }, { kind: "component", type: StConditionBuilderComponent, selector: "st-condition-builder", inputs: ["config", "value", "disabled"], outputs: ["valueChange", "validityChange"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] }); }
14471
14539
  }
14472
14540
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: StWorkbookComponent, decorators: [{
14473
14541
  type: Component,
14474
- args: [{ selector: 'st-workbook', standalone: true, imports: [CommonModule, StTableComponent, StConditionBuilderComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen()\">\n <nile-tab-group #workbookTabGroup [activeIndex]=\"activeSheetIndex()\">\n \n <!-- Sheet Tabs (one per sheet) -->\n @for (sheet of sheets(); track sheet.id; let i = $index) {\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-sheet-tab\"\n [class.active]=\"i === activeSheetIndex()\"\n role=\"tab\"\n [attr.aria-selected]=\"i === activeSheetIndex()\"\n [attr.aria-label]=\"sheet.name\"\n [attr.tabindex]=\"i === activeSheetIndex() ? 0 : -1\"\n (click)=\"onTabChange(i)\"\n (keydown)=\"onSheetTabKeydown($event, i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n\n <!-- Tab actions dropdown button -->\n @if (hasTabActions(sheet)) {\n <button class=\"tab-actions-button\"\n type=\"button\"\n [attr.aria-label]=\"'Actions for ' + sheet.name\"\n (click)=\"openTabActions($event, sheet, i)\">\n <nile-icon name=\"arrowdown\" size=\"14\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n </div>\n </nile-tab>\n }\n \n <!-- Toolbar Tab (for workbook controls) -->\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\" role=\"toolbar\" aria-label=\"Workbook toolbar\"\n (keydown)=\"onToolbarKeydown($event)\">\n\n <!-- Autosave Indicator \u2014 hidden unless `autosave.showIndicator: true` -->\n @if (autosaveIndicatorVisible()) {\n <div class=\"autosave-indicator\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (!isSaving() && lastSaveTime()) {\n <nile-icon\n name=\"save\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saved at {{ lastSaveTime() | date:'HH:mm:ss' }}</span>\n }\n @if (isSaving()) {\n <nile-icon\n name=\"loader\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saving\u2026</span>\n }\n </div>\n }\n\n <!-- Toolbar Workbook Actions (shown as individual buttons) -->\n @for (action of toolbarWorkbookActions(); track action.id) {\n <button class=\"toolbar-action-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n @if (!action.icon) {\n <span>{{ action.label }}</span>\n }\n </button>\n }\n\n <!-- Workbook Actions Dropdown -->\n @if (visibleWorkbookActions().length > 0) {\n <button class=\"workbook-actions-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Workbook actions\"\n [attr.aria-expanded]=\"workbookActionsOpen()\"\n aria-haspopup=\"true\"\n (click)=\"toggleWorkbookActions($event)\">\n <nile-icon name=\"settings\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Add Sheet Button -->\n @if (canAddSheet) {\n <button class=\"add-sheet-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Add sheet\"\n (click)=\"onAddSheet()\">\n <nile-icon name=\"plus\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Fullscreen Button -->\n @if (config().display?.allowFullscreen !== false) {\n <button class=\"fullscreen-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n [attr.aria-pressed]=\"isFullscreen()\"\n (click)=\"toggleFullscreen()\">\n <nile-icon [name]=\"isFullscreen() ? 'collapse' : 'expand-06'\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: content is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using @for with track to force complete reinitialization when tableComponentKey changes -->\n @for (key of [tableComponentKey()]; track key) {\n @switch (activeSheetContentType) {\n @case ('condition-builder') {\n @if (activeSheet()?.conditionBuilder) {\n <st-condition-builder\n [attr.data-sheet-key]=\"key\"\n [config]=\"activeSheet()!.conditionBuilder!.config\"\n [value]=\"activeSheet()!.conditionBuilder!.value\"\n (valueChange)=\"onConditionBuilderValueChange($event)\"\n (validityChange)=\"onConditionBuilderValidityChange($event)\">\n </st-condition-builder>\n }\n }\n @default {\n @if (currentTableConfig() && currentTableState()) {\n <st-table\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig()!\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState()!\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\"\n (requestFocusTabs)=\"onRequestFocusTabs()\">\n </st-table>\n }\n }\n }\n }\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n@if (tabActionsOpen()) {\n <div class=\"tab-actions-dropdown\" [ngStyle]=\"tabActionsPosition()\" (keydown)=\"onTabActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" [attr.aria-label]=\"(selectedSheet()?.name || 'Sheet') + ' actions'\">\n <nile-menu>\n @for (action of selectedSheet()?.tabActions; track action.id) {\n <nile-menu-item tabindex=\"-1\" (click)=\"onTabActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Workbook Actions Dropdown -->\n@if (workbookActionsOpen()) {\n <div class=\"workbook-actions-dropdown\" [ngStyle]=\"workbookActionsPosition()\" (keydown)=\"onWorkbookActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" aria-label=\"Workbook actions\">\n <nile-menu>\n @for (action of visibleWorkbookActions(); track action.id) {\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Fullscreen Backdrop -->\n@if (isFullscreen()) {\n <div class=\"fullscreen-backdrop\" (click)=\"toggleFullscreen()\">\n </div>\n}\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:#fff;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:var(--ng-font-weight-medium);font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200);flex-shrink:0;position:sticky;right:0;z-index:3;align-self:stretch;background-color:#fafafa;box-shadow:-8px 0 12px -8px #0000001f}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.workbook-toolbar-tab button.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:#00000080;z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0;flex-wrap:nowrap;width:max-content;min-width:100%;box-sizing:border-box}nile-tab-group nile-tab.workbook-sheet-tab{flex-shrink:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:var(--ng-font-weight-bold)}nile-tab-group nile-tab-panel::part(base){padding:0;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow:hidden}\n"] }]
14542
+ args: [{ selector: 'st-workbook', standalone: true, imports: [CommonModule, StTableComponent, StConditionBuilderComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA], template: "<div class=\"workbook-container\" [class.fullscreen]=\"isFullscreen()\">\n <nile-tab-group #workbookTabGroup [activeIndex]=\"activeSheetIndex()\">\n \n <!-- Sheet Tabs (one per sheet) -->\n @for (sheet of sheets(); track sheet.id; let i = $index) {\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-sheet-tab\"\n [class.active]=\"i === activeSheetIndex()\"\n role=\"tab\"\n [attr.aria-selected]=\"i === activeSheetIndex()\"\n [attr.aria-label]=\"sheet.name\"\n [attr.tabindex]=\"i === activeSheetIndex() ? 0 : -1\"\n (click)=\"onTabChange(i)\"\n (keydown)=\"onSheetTabKeydown($event, i)\">\n <div class=\"sheet-tab-content\">\n <span class=\"sheet-name\">{{ sheet.name }}</span>\n\n <!-- Tab actions affordance. Rendered as a non-interactive, aria-hidden\n <span> (not a <button>) so it is NOT a nested interactive control\n inside the role=\"tab\" element \u2014 that nesting fails WCAG 4.1.2 /\n axe \"nested-interactive\" and confuses screen readers & keyboard\n focus order. Mouse users still click it; keyboard users open the\n same menu via Space on the focused tab (see onSheetTabKeydown),\n which is why the Tab handler already skips this element. -->\n @if (hasTabActions(sheet)) {\n <span class=\"tab-actions-button\"\n aria-hidden=\"true\"\n (click)=\"openTabActions($event, sheet, i)\">\n <nile-icon name=\"arrowdown\" size=\"14\" aria-hidden=\"true\"></nile-icon>\n </span>\n }\n </div>\n </nile-tab>\n }\n \n <!-- Toolbar \"Tab\" (for workbook controls). This is NOT a real tab \u2014 it's a\n disabled layout slot that hosts the workbook toolbar. NOTE: nile-tab force-sets\n role=\"tab\" on itself (setAttribute in its update cycle), so a role override here\n does NOT stick \u2014 the inner interactive buttons remain nested inside role=\"tab\"\n (axe \"nested-interactive\"). Fixing that requires a nile-elements (nile-tab)\n change or not using nile-tab for the toolbar. Tracked separately. -->\n <nile-tab slot=\"nav\"\n panel=\"shared-panel\"\n class=\"workbook-toolbar-tab\"\n [disabled]=\"true\">\n <div class=\"workbook-toolbar-content\" role=\"toolbar\" aria-label=\"Workbook toolbar\"\n (keydown)=\"onToolbarKeydown($event)\">\n\n <!-- Autosave Indicator \u2014 hidden unless `autosave.showIndicator: true` -->\n @if (autosaveIndicatorVisible()) {\n <div class=\"autosave-indicator\" aria-live=\"polite\" aria-atomic=\"true\">\n @if (!isSaving() && lastSaveTime()) {\n <nile-icon\n name=\"save\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saved at {{ lastSaveTime() | date:'HH:mm:ss' }}</span>\n }\n @if (isSaving()) {\n <nile-icon\n name=\"loader\"\n size=\"14\"\n aria-hidden=\"true\">\n </nile-icon>\n <span class=\"sr-only\">Saving\u2026</span>\n }\n </div>\n }\n\n <!-- Toolbar Workbook Actions (shown as individual buttons) -->\n @for (action of toolbarWorkbookActions(); track action.id) {\n <button class=\"toolbar-action-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n @if (!action.icon) {\n <span>{{ action.label }}</span>\n }\n </button>\n }\n\n <!-- Workbook Actions Dropdown -->\n @if (visibleWorkbookActions().length > 0) {\n <button class=\"workbook-actions-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Workbook actions\"\n [attr.aria-expanded]=\"workbookActionsOpen()\"\n aria-haspopup=\"true\"\n (click)=\"toggleWorkbookActions($event)\">\n <nile-icon name=\"settings\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Add Sheet Button -->\n @if (canAddSheet) {\n <button class=\"add-sheet-button\"\n type=\"button\"\n tabindex=\"-1\"\n aria-label=\"Add sheet\"\n (click)=\"onAddSheet()\">\n <nile-icon name=\"plus\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n\n <!-- Fullscreen Button -->\n @if (config().display?.allowFullscreen !== false) {\n <button class=\"fullscreen-button\"\n type=\"button\"\n tabindex=\"-1\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n [attr.aria-pressed]=\"isFullscreen()\"\n (click)=\"toggleFullscreen()\">\n <nile-icon [name]=\"isFullscreen() ? 'collapse' : 'expand-06'\" aria-hidden=\"true\"></nile-icon>\n </button>\n }\n </div>\n </nile-tab>\n \n <!-- Single Shared Tab Panel -->\n <nile-tab-panel name=\"shared-panel\">\n <!-- Lazy loading strategy: content is destroyed and recreated with new config/state when sheet changes -->\n <!-- Using @for with track to force complete reinitialization when tableComponentKey changes -->\n @for (key of [tableComponentKey()]; track key) {\n @switch (activeSheetContentType) {\n @case ('condition-builder') {\n @if (activeSheet()?.conditionBuilder) {\n <st-condition-builder\n [attr.data-sheet-key]=\"key\"\n [config]=\"activeSheet()!.conditionBuilder!.config\"\n [value]=\"activeSheet()!.conditionBuilder!.value\"\n (valueChange)=\"onConditionBuilderValueChange($event)\"\n (validityChange)=\"onConditionBuilderValidityChange($event)\">\n </st-condition-builder>\n }\n }\n @default {\n @if (currentTableConfig() && currentTableState()) {\n <st-table\n [attr.data-sheet-key]=\"key\"\n [tableConfig]=\"currentTableConfig()!\"\n [data$]=\"currentTableData$\"\n [tableState]=\"currentTableState()!\"\n (cellChange)=\"onCellChange($event)\"\n (cellSave)=\"onCellSave($event)\"\n (stateChange)=\"onTableStateChange($event)\"\n (requestAddRow)=\"onRequestAddRow($event)\"\n (requestFocusTabs)=\"onRequestFocusTabs()\">\n </st-table>\n }\n }\n }\n }\n </nile-tab-panel>\n \n </nile-tab-group>\n</div>\n\n<!-- Tab Actions Dropdown -->\n@if (tabActionsOpen()) {\n <div class=\"tab-actions-dropdown\" [ngStyle]=\"tabActionsPosition()\" (keydown)=\"onTabActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeTabActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" [attr.aria-label]=\"(selectedSheet()?.name || 'Sheet') + ' actions'\">\n <nile-menu>\n @for (action of selectedSheet()?.tabActions; track action.id) {\n <nile-menu-item tabindex=\"-1\" (click)=\"onTabActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Workbook Actions Dropdown -->\n@if (workbookActionsOpen()) {\n <div class=\"workbook-actions-dropdown\" [ngStyle]=\"workbookActionsPosition()\" (keydown)=\"onWorkbookActionsKeydown($event)\">\n <div class=\"dropdown-backdrop\" role=\"presentation\" (click)=\"closeWorkbookActions()\"></div>\n <div class=\"dropdown-menu\" role=\"dialog\" aria-label=\"Workbook actions\">\n <nile-menu>\n @for (action of visibleWorkbookActions(); track action.id) {\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\"\n [attr.aria-disabled]=\"isActionDisabled(action)\"\n (click)=\"onWorkbookActionClick(action, $event)\">\n @if (action.icon) {\n <nile-icon slot=\"prefix\" size=\"14\" [name]=\"action.icon\" aria-hidden=\"true\"></nile-icon>\n }\n {{ action.label }}\n </nile-menu-item>\n }\n </nile-menu>\n </div>\n </div>\n}\n\n<!-- Fullscreen Backdrop -->\n@if (isFullscreen()) {\n <div class=\"fullscreen-backdrop\" (click)=\"toggleFullscreen()\">\n </div>\n}\n", styles: [".sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}:host{display:block;width:100%;height:100%}.workbook-container{display:flex;flex-direction:column;height:100%;background:#fff;border:1px solid var(--nile-color-neutral-200);border-radius:4px;overflow:hidden}.workbook-container.fullscreen{position:fixed;inset:0;z-index:2000;border:none;border-radius:0}.workbook-container nile-tab-group{height:100%;display:flex;flex-direction:column}.sheet-tab-content{display:flex;align-items:center;gap:8px;padding:0 4px}.sheet-tab-content .sheet-name{font-size:12px;font-weight:var(--ng-font-weight-medium);font-family:var(--nile-font-family-sans-serif);color:#000}.sheet-tab-content .tab-actions-button{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;background:transparent;border:none;cursor:pointer}.workbook-toolbar-tab{margin-left:auto!important;pointer-events:auto!important;border-left:1px solid var(--nile-color-neutral-200);flex-shrink:0;position:sticky;right:0;z-index:3;align-self:stretch;background-color:#fafafa;box-shadow:-8px 0 12px -8px #0000001f}.workbook-toolbar-tab .workbook-toolbar-content{display:flex;gap:4px;align-items:center;padding:0 8px}.workbook-toolbar-tab .workbook-toolbar-content .autosave-indicator{display:flex;align-items:center;margin-right:8px;color:var(--nile-color-success-500)}.workbook-toolbar-tab button{display:flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;background:transparent;border:none;border-radius:4px;cursor:pointer;transition:background-color .2s;color:var(--nile-color-neutral-600)}.workbook-toolbar-tab button:hover{background-color:var(--nile-color-neutral-100);color:var(--nile-color-neutral-900)}.workbook-toolbar-tab button:active{background-color:var(--nile-color-neutral-200)}.workbook-toolbar-tab button nile-icon{font-size:16px}.workbook-toolbar-tab button.disabled{opacity:.5;cursor:not-allowed;pointer-events:none}.tab-actions-dropdown{position:fixed;z-index:1001}.tab-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.tab-actions-dropdown .dropdown-menu{position:relative;min-width:180px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.tab-actions-dropdown .dropdown-menu nile-menu{display:block}.workbook-actions-dropdown{position:fixed;z-index:1001}.workbook-actions-dropdown .dropdown-backdrop{position:fixed;top:0;left:0;width:100%;height:100%;background:transparent;z-index:1000}.workbook-actions-dropdown .dropdown-menu{position:relative;min-width:200px;background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;z-index:1001;overflow:hidden}.workbook-actions-dropdown .dropdown-menu nile-menu{display:block}.fullscreen-backdrop{position:fixed;inset:0;background:#00000080;z-index:1999;cursor:pointer}nile-tab-group::part(nav){background-color:#fafafa}nile-tab-group::part(active-tab-indicator-path){background:none}nile-tab-group::part(active-tab-indicator){border-bottom:none}nile-tab-group::part(tabs){gap:0;flex-wrap:nowrap;width:max-content;min-width:100%;box-sizing:border-box}nile-tab-group nile-tab.workbook-sheet-tab{flex-shrink:0}nile-tab-group nile-tab{border:1px solid #e0e0e0;border-top-left-radius:6px;border-top-right-radius:6px}nile-tab-group nile-tab::part(base){padding-left:.5rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom-left-radius:0;border-bottom-right-radius:0}nile-tab-group nile-tab.active{background-color:#fff;color:#000}nile-tab-group nile-tab.active .sheet-name{font-weight:var(--ng-font-weight-bold)}nile-tab-group nile-tab-panel::part(base){padding:0;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow:hidden}\n"] }]
14475
14543
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], sheetsData: [{ type: i0.Input, args: [{ isSignal: true, alias: "sheetsData", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], sheetChanged: [{ type: i0.Output, args: ["sheetChanged"] }], addSheet: [{ type: i0.Output, args: ["addSheet"] }], sheetTabAction: [{ type: i0.Output, args: ["sheetTabAction"] }], workbookAction: [{ type: i0.Output, args: ["workbookAction"] }], cellChange: [{ type: i0.Output, args: ["cellChange"] }], cellSave: [{ type: i0.Output, args: ["cellSave"] }], tableStateChange: [{ type: i0.Output, args: ["tableStateChange"] }], fullscreenToggle: [{ type: i0.Output, args: ["fullscreenToggle"] }], requestAddRow: [{ type: i0.Output, args: ["requestAddRow"] }], conditionBuilderValueChange: [{ type: i0.Output, args: ["conditionBuilderValueChange"] }], conditionBuilderValidityChange: [{ type: i0.Output, args: ["conditionBuilderValidityChange"] }], tableComponent: [{
14476
14544
  type: ViewChild,
14477
14545
  args: [StTableComponent]