@aquera/ngx-smart-table 0.0.17-patch-0.5 → 0.0.17-patch-0.7

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.
@@ -4843,6 +4843,308 @@ class NileDatePickerEditor {
4843
4843
  }
4844
4844
  }
4845
4845
 
4846
+ /**
4847
+ * Custom editor using NileChip from @aquera/nile-elements
4848
+ * Renders the chip input in a floating popover below the cell to avoid row height mismatch.
4849
+ *
4850
+ * @see https://nile.aqueralabs.com/1.6.3/chip?theme=enterprise
4851
+ */
4852
+ let chipStylesInjected = false;
4853
+ function injectChipStyles() {
4854
+ if (chipStylesInjected)
4855
+ return;
4856
+ chipStylesInjected = true;
4857
+ const styleId = 'nile-chip-editor-styles';
4858
+ if (document.getElementById(styleId))
4859
+ return;
4860
+ const style = document.createElement('style');
4861
+ style.id = styleId;
4862
+ style.textContent = `
4863
+ .st-chip-popover {
4864
+ position: fixed;
4865
+ z-index: 10000;
4866
+ background: var(--nile-colors-white-base, #fff);
4867
+ border: 1px solid var(--nile-colors-neutral-200, #e2e8f0);
4868
+ border-radius: 6px;
4869
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
4870
+ padding: 8px;
4871
+ box-sizing: border-box;
4872
+ max-height: 200px;
4873
+ overflow-y: auto;
4874
+ }
4875
+ .st-chip-popover nile-chip {
4876
+ width: 100%;
4877
+ }
4878
+ .st-chip-popover nile-chip::part(base) {
4879
+ border: none !important;
4880
+ box-shadow: none !important;
4881
+ min-height: 32px;
4882
+ }
4883
+ .st-chip-popover nile-chip::part(input) {
4884
+ font-size: var(--nile-font-size-small, 13px);
4885
+ }
4886
+ `;
4887
+ document.head.appendChild(style);
4888
+ }
4889
+ /**
4890
+ * Custom editor that uses NileChip (tag input) component.
4891
+ * Renders in a floating popover below the cell to avoid expanding row height.
4892
+ *
4893
+ * Cell value is expected to be `string[]` (array of tag strings).
4894
+ */
4895
+ class NileChipEditor {
4896
+ constructor(options) {
4897
+ this.options = options;
4898
+ this.acceptsInitialKeypress = false;
4899
+ this.eventListeners = [];
4900
+ this.trackedValues = [];
4901
+ this.hasChangeOccurred = false;
4902
+ }
4903
+ edit(context) {
4904
+ var _a, _b;
4905
+ if (!context.container) {
4906
+ console.warn('NileChipEditor requires a container element');
4907
+ return;
4908
+ }
4909
+ injectChipStyles();
4910
+ this.cellContainer = context.container;
4911
+ // Create the floating popover
4912
+ this.popover = document.createElement('div');
4913
+ this.popover.className = 'st-chip-popover';
4914
+ // Create nile-chip inside the popover
4915
+ this.chip = document.createElement('nile-chip');
4916
+ this.chip.className = 'st-cell-editor st-nile-chip-editor';
4917
+ this.setInitialValue(context.value);
4918
+ this.applyOptions();
4919
+ this.popover.appendChild(this.chip);
4920
+ // Apply custom max-height if provided
4921
+ if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.popoverMaxHeight) {
4922
+ this.popover.style.maxHeight = `${this.options.popoverMaxHeight}px`;
4923
+ }
4924
+ // Append popover to body and position it
4925
+ document.body.appendChild(this.popover);
4926
+ this.positionPopover();
4927
+ this.setupEventListeners(context);
4928
+ if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.autoFocus) !== false) {
4929
+ setTimeout(() => {
4930
+ var _a;
4931
+ try {
4932
+ (_a = this.chip) === null || _a === void 0 ? void 0 : _a.focus();
4933
+ }
4934
+ catch ( /* ignore */_b) { /* ignore */ }
4935
+ }, 0);
4936
+ }
4937
+ }
4938
+ positionPopover() {
4939
+ var _a, _b;
4940
+ if (!this.popover || !this.cellContainer)
4941
+ return;
4942
+ const rect = this.cellContainer.getBoundingClientRect();
4943
+ const minWidth = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.popoverMinWidth) !== null && _b !== void 0 ? _b : rect.width;
4944
+ const popoverWidth = Math.max(minWidth, rect.width);
4945
+ this.popover.style.top = `${rect.bottom + 2}px`;
4946
+ this.popover.style.left = `${rect.left}px`;
4947
+ this.popover.style.width = `${popoverWidth}px`;
4948
+ // After rendering, check if it goes off-screen bottom and flip above if needed
4949
+ requestAnimationFrame(() => {
4950
+ if (!this.popover)
4951
+ return;
4952
+ const popRect = this.popover.getBoundingClientRect();
4953
+ if (popRect.bottom > window.innerHeight) {
4954
+ this.popover.style.top = `${rect.top - popRect.height - 2}px`;
4955
+ }
4956
+ });
4957
+ }
4958
+ setInitialValue(value) {
4959
+ if (!this.chip)
4960
+ return;
4961
+ if (Array.isArray(value)) {
4962
+ this.trackedValues = [...value];
4963
+ this.chip.value = this.trackedValues;
4964
+ }
4965
+ else if (typeof value === 'string' && value) {
4966
+ this.trackedValues = [value];
4967
+ this.chip.value = this.trackedValues;
4968
+ }
4969
+ else {
4970
+ this.trackedValues = [];
4971
+ this.chip.value = [];
4972
+ }
4973
+ }
4974
+ applyOptions() {
4975
+ if (!this.chip || !this.options)
4976
+ return;
4977
+ if (this.options.placeholder) {
4978
+ this.chip.placeholder = this.options.placeholder;
4979
+ }
4980
+ if (this.options.label) {
4981
+ this.chip.label = this.options.label;
4982
+ }
4983
+ if (this.options.helpText) {
4984
+ this.chip.helpText = this.options.helpText;
4985
+ }
4986
+ if (this.options.disabled !== undefined) {
4987
+ this.chip.disabled = this.options.disabled;
4988
+ }
4989
+ if (this.options.readonly !== undefined) {
4990
+ this.chip.readonly = this.options.readonly;
4991
+ }
4992
+ if (this.options.acceptUserInput !== undefined) {
4993
+ this.chip.acceptUserInput = this.options.acceptUserInput;
4994
+ }
4995
+ if (this.options.noDuplicates !== undefined) {
4996
+ this.chip.noDuplicates = this.options.noDuplicates;
4997
+ }
4998
+ if (this.options.clearable !== undefined) {
4999
+ this.chip.clearable = this.options.clearable;
5000
+ }
5001
+ if (this.options.noWrap !== undefined) {
5002
+ this.chip.noWrap = this.options.noWrap;
5003
+ }
5004
+ if (this.options.noAutoComplete !== undefined) {
5005
+ this.chip.noAutoComplete = this.options.noAutoComplete;
5006
+ }
5007
+ if (this.options.enableVirtualScroll !== undefined) {
5008
+ this.chip.enableVirtualScroll = this.options.enableVirtualScroll;
5009
+ }
5010
+ if (this.options.openDropdownOnFocus !== undefined) {
5011
+ this.chip.openDropdownOnFocus = this.options.openDropdownOnFocus;
5012
+ }
5013
+ if (this.options.loading !== undefined) {
5014
+ this.chip.loading = this.options.loading;
5015
+ }
5016
+ // Visual states
5017
+ if (this.options.warning !== undefined) {
5018
+ this.chip.warning = this.options.warning;
5019
+ }
5020
+ if (this.options.error !== undefined) {
5021
+ this.chip.error = this.options.error;
5022
+ }
5023
+ if (this.options.success !== undefined) {
5024
+ this.chip.success = this.options.success;
5025
+ }
5026
+ if (this.options.errorMessage) {
5027
+ this.chip.errorMessage = this.options.errorMessage;
5028
+ }
5029
+ if (this.options.errorIndexes) {
5030
+ this.chip.errorIndexes = this.options.errorIndexes;
5031
+ }
5032
+ // Autocomplete options
5033
+ if (this.options.autoCompleteOptions) {
5034
+ const opts = this.options.autoCompleteOptions;
5035
+ const stringOpts = opts.map(o => { var _a; return typeof o === 'string' ? o : ((_a = o.label) !== null && _a !== void 0 ? _a : o.value); });
5036
+ this.chip.autoCompleteOptions = stringOpts;
5037
+ }
5038
+ if (this.options.filterFunction) {
5039
+ this.chip.filterFunction = this.options.filterFunction;
5040
+ }
5041
+ if (this.options.renderItemFunction) {
5042
+ this.chip.renderItemFunction = this.options.renderItemFunction;
5043
+ }
5044
+ }
5045
+ addListener(element, event, handler, capture) {
5046
+ element.addEventListener(event, handler, capture);
5047
+ this.eventListeners.push({ element, event, handler, capture });
5048
+ }
5049
+ setupEventListeners(context) {
5050
+ if (!this.chip)
5051
+ return;
5052
+ // Track chip changes
5053
+ this.addListener(this.chip, 'nile-chip-change', (e) => {
5054
+ var _a;
5055
+ const detail = e.detail;
5056
+ const newValue = Array.isArray(detail === null || detail === void 0 ? void 0 : detail.value) ? [...detail.value] : (((_a = this.chip) === null || _a === void 0 ? void 0 : _a.value) ? [...this.chip.value] : []);
5057
+ this.trackedValues = newValue;
5058
+ this.hasChangeOccurred = true;
5059
+ context.onChange(newValue);
5060
+ });
5061
+ // Keyboard handling on the chip element
5062
+ this.addListener(this.chip, 'keydown', (e) => {
5063
+ const keyEvent = e;
5064
+ if (keyEvent.key === 'Enter') {
5065
+ keyEvent.stopPropagation();
5066
+ }
5067
+ else if (keyEvent.key === 'Escape') {
5068
+ keyEvent.preventDefault();
5069
+ keyEvent.stopPropagation();
5070
+ context.onCancel();
5071
+ }
5072
+ else if (keyEvent.key === 'Tab') {
5073
+ keyEvent.preventDefault();
5074
+ keyEvent.stopPropagation();
5075
+ context.onSave(this.getCurrentValue());
5076
+ }
5077
+ });
5078
+ // Click-outside: save when clicking anywhere outside the popover
5079
+ let saveTriggered = false;
5080
+ const mousedownHandler = (e) => {
5081
+ var _a;
5082
+ if (saveTriggered)
5083
+ return;
5084
+ if (!this.popover)
5085
+ return;
5086
+ const path = e.composedPath();
5087
+ for (const el of path) {
5088
+ if (el === this.popover)
5089
+ return;
5090
+ if (el === this.chip)
5091
+ return;
5092
+ if (el instanceof HTMLElement) {
5093
+ if (((_a = el.tagName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === 'nile-chip')
5094
+ return;
5095
+ if (el.className && typeof el.className === 'string' && el.className.includes('nile-chip'))
5096
+ return;
5097
+ }
5098
+ }
5099
+ saveTriggered = true;
5100
+ context.onSave(this.getCurrentValue());
5101
+ };
5102
+ document.addEventListener('mousedown', mousedownHandler, true);
5103
+ this._documentMousedownHandler = mousedownHandler;
5104
+ // Reposition on scroll/resize so popover stays aligned with the cell
5105
+ const reposition = () => this.positionPopover();
5106
+ this.addListener(window, 'resize', reposition);
5107
+ this.addListener(window, 'scroll', reposition, true);
5108
+ }
5109
+ destroy() {
5110
+ // Remove document mousedown handler
5111
+ if (this._documentMousedownHandler) {
5112
+ document.removeEventListener('mousedown', this._documentMousedownHandler, true);
5113
+ delete this._documentMousedownHandler;
5114
+ }
5115
+ // Remove all tracked listeners
5116
+ for (const { element, event, handler, capture } of this.eventListeners) {
5117
+ element.removeEventListener(event, handler, capture);
5118
+ }
5119
+ this.eventListeners = [];
5120
+ // Remove the popover from the DOM
5121
+ if (this.popover) {
5122
+ this.popover.remove();
5123
+ this.popover = undefined;
5124
+ }
5125
+ this.chip = undefined;
5126
+ this.cellContainer = undefined;
5127
+ this.trackedValues = [];
5128
+ this.hasChangeOccurred = false;
5129
+ }
5130
+ focus() {
5131
+ var _a;
5132
+ try {
5133
+ (_a = this.chip) === null || _a === void 0 ? void 0 : _a.focus();
5134
+ }
5135
+ catch ( /* ignore */_b) { /* ignore */ }
5136
+ }
5137
+ getCurrentValue() {
5138
+ if (this.hasChangeOccurred) {
5139
+ return [...this.trackedValues];
5140
+ }
5141
+ if (!this.chip)
5142
+ return [];
5143
+ const val = this.chip.value;
5144
+ return Array.isArray(val) ? [...val] : [];
5145
+ }
5146
+ }
5147
+
4846
5148
  /**
4847
5149
  * Custom editor using NileCodeEditor from @aquera/nile-elements
4848
5150
  * This provides code editing capabilities with syntax highlighting for table cells
@@ -4984,7 +5286,7 @@ class NileCodeEditor {
4984
5286
  this.syncingFromDialog = false; // Flag to prevent inline editor from overwriting multiline content
4985
5287
  this.userEditedInline = false; // Flag to track if user has typed in inline editor
4986
5288
  this.dialogOriginalValue = ''; // Store original value when dialog opens
4987
- this.dialogCurrentValue = ''; // Track current value in dialog
5289
+ this.dialogCurrentValue = null; // Track current value in dialog
4988
5290
  }
4989
5291
  edit(context) {
4990
5292
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
@@ -5266,7 +5568,7 @@ class NileCodeEditor {
5266
5568
  getDialogEditorValue() {
5267
5569
  var _a;
5268
5570
  // Use tracked value from change events (most reliable)
5269
- if (this.dialogCurrentValue) {
5571
+ if (this.dialogCurrentValue !== null && this.dialogCurrentValue !== undefined) {
5270
5572
  return this.dialogCurrentValue.replace(/\n+$/, '');
5271
5573
  }
5272
5574
  if (!this.dialogEditor)
@@ -5296,10 +5598,9 @@ class NileCodeEditor {
5296
5598
  var _a, _b;
5297
5599
  if (!this.dialogOpen)
5298
5600
  return;
5299
- // Get the value from dialog editor - try multiple sources
5601
+ // Always read live dialog editor state to avoid stale tracked values from debounced updates
5300
5602
  let dialogValue = this.dialogCurrentValue;
5301
- // If no tracked value, try reading directly from dialog editor
5302
- if (!dialogValue && this.dialogEditor) {
5603
+ if (this.dialogEditor) {
5303
5604
  try {
5304
5605
  const shadowRoot = this.dialogEditor.shadowRoot;
5305
5606
  if (shadowRoot) {
@@ -5313,12 +5614,12 @@ class NileCodeEditor {
5313
5614
  // Fall through
5314
5615
  }
5315
5616
  // Fallback to value property
5316
- if (!dialogValue) {
5617
+ if (dialogValue === null || dialogValue === undefined) {
5317
5618
  dialogValue = (_b = this.dialogEditor.value) !== null && _b !== void 0 ? _b : '';
5318
5619
  }
5319
5620
  }
5320
5621
  // Strip trailing newlines
5321
- dialogValue = (dialogValue || '').replace(/\n+$/, '');
5622
+ dialogValue = (dialogValue !== null && dialogValue !== void 0 ? dialogValue : '').replace(/\n+$/, '');
5322
5623
  // Update tracked value and inline editor
5323
5624
  this.trackedValue = dialogValue;
5324
5625
  this.userEditedInline = false;
@@ -5360,7 +5661,7 @@ class NileCodeEditor {
5360
5661
  */
5361
5662
  closeDialogUI() {
5362
5663
  this.dialogOpen = false;
5363
- this.dialogCurrentValue = '';
5664
+ this.dialogCurrentValue = null;
5364
5665
  if (this.dialog) {
5365
5666
  this.dialog.open = false;
5366
5667
  const dialogRef = this.dialog;
@@ -5612,7 +5913,7 @@ class NileCodeEditor {
5612
5913
  this.trackedValue = null;
5613
5914
  this.userEditedInline = false;
5614
5915
  this.dialogOriginalValue = '';
5615
- this.dialogCurrentValue = '';
5916
+ this.dialogCurrentValue = null;
5616
5917
  }
5617
5918
  focus() {
5618
5919
  var _a;
@@ -7758,7 +8059,7 @@ class StColumnMenuDropdownComponent {
7758
8059
  */
7759
8060
  this.isOpen = false;
7760
8061
  /**
7761
- * Position of the dropdown (x, y coordinates)
8062
+ * Position of the dropdown (x, y coordinates, triggerTop for flip positioning)
7762
8063
  */
7763
8064
  this.position = { x: 0, y: 0 };
7764
8065
  /**
@@ -7872,25 +8173,42 @@ class StColumnMenuDropdownComponent {
7872
8173
  this.dropdownStyle = {};
7873
8174
  return;
7874
8175
  }
7875
- const viewportWidth = window.innerWidth;
7876
- const viewportHeight = window.innerHeight;
7877
- const dropdownWidth = 280; // Approximate dropdown width
7878
- const dropdownHeight = 300; // Approximate max dropdown height
7879
8176
  let { x, y } = this.position;
7880
- // Adjust horizontal position if dropdown would overflow
7881
- if (x + dropdownWidth > viewportWidth) {
7882
- x = Math.max(10, viewportWidth - dropdownWidth - 10);
7883
- }
7884
- // Adjust vertical position if dropdown would overflow
7885
- if (y + dropdownHeight > viewportHeight) {
7886
- y = Math.max(10, viewportHeight - dropdownHeight - 10);
7887
- }
8177
+ // Render at initial position first
7888
8178
  this.dropdownStyle = {
7889
8179
  position: 'fixed',
7890
8180
  left: `${x}px`,
7891
8181
  top: `${y}px`,
7892
- 'z-index': 9999
8182
+ 'z-index': 9999,
8183
+ visibility: 'hidden'
7893
8184
  };
8185
+ // After rendering, measure actual size and adjust if needed
8186
+ requestAnimationFrame(() => {
8187
+ var _a, _b;
8188
+ const viewportWidth = window.innerWidth;
8189
+ const viewportHeight = window.innerHeight;
8190
+ const el = (_a = this.dropdownPanel) === null || _a === void 0 ? void 0 : _a.nativeElement;
8191
+ const dropdownWidth = (el === null || el === void 0 ? void 0 : el.offsetWidth) || 280;
8192
+ const dropdownHeight = (el === null || el === void 0 ? void 0 : el.offsetHeight) || 200;
8193
+ // Adjust horizontal position if dropdown would overflow
8194
+ if (x + dropdownWidth > viewportWidth) {
8195
+ x = Math.max(10, viewportWidth - dropdownWidth - 10);
8196
+ }
8197
+ // Adjust vertical position — flip above the trigger if it overflows bottom
8198
+ if (y + dropdownHeight > viewportHeight) {
8199
+ const triggerTop = (_b = this.position.triggerTop) !== null && _b !== void 0 ? _b : this.position.y;
8200
+ y = triggerTop - dropdownHeight - 4;
8201
+ }
8202
+ // Clamp to viewport edges
8203
+ x = Math.max(10, x);
8204
+ y = Math.max(10, y);
8205
+ this.dropdownStyle = {
8206
+ position: 'fixed',
8207
+ left: `${x}px`,
8208
+ top: `${y}px`,
8209
+ 'z-index': 9999
8210
+ };
8211
+ });
7894
8212
  }
7895
8213
  /**
7896
8214
  * Check if an action is disabled
@@ -7958,10 +8276,10 @@ class StColumnMenuDropdownComponent {
7958
8276
  }
7959
8277
  }
7960
8278
  StColumnMenuDropdownComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StColumnMenuDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7961
- StColumnMenuDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "click": "onBackdropClick($event)" } }, viewQueries: [{ propertyName: "filterPopup", first: true, predicate: ["filterPopup"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"], components: [{ type: StColumnFilterComponent, selector: "st-column-filter", inputs: ["column", "tableState", "columnIndex", "isFirstColumn", "isLastColumn", "isOpen", "filterContext"], outputs: ["closed", "filterApplied", "filterCleared"] }], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
8279
+ StColumnMenuDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "click": "onBackdropClick($event)" } }, viewQueries: [{ propertyName: "filterPopup", first: true, predicate: ["filterPopup"], descendants: true }, { propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"], components: [{ type: StColumnFilterComponent, selector: "st-column-filter", inputs: ["column", "tableState", "columnIndex", "isFirstColumn", "isLastColumn", "isOpen", "filterContext"], outputs: ["closed", "filterApplied", "filterCleared"] }], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
7962
8280
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StColumnMenuDropdownComponent, decorators: [{
7963
8281
  type: Component,
7964
- args: [{ selector: 'st-column-menu-dropdown', template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"] }]
8282
+ args: [{ selector: 'st-column-menu-dropdown', template: "<!-- Dropdown container with backdrop -->\n<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-backdrop\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"column-menu-dropdown\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <!-- Main menu with actions -->\n <nile-menu *ngIf=\"!isFilterOpen\">\n <!-- Dynamically render all visible actions -->\n <ng-container *ngFor=\"let action of visibleActions; let i = index; let last = last\">\n <nile-menu-item \n (click)=\"onActionClick(action)\"\n [class.disabled]=\"isActionDisabled(action)\"\n [class.active]=\"isActionActive(action)\">\n <span class=\"checkmark\" *ngIf=\"isActionActive(action)\">\u2713</span>\n <nile-icon slot=\"prefix\" *ngIf=\"action.icon && !isActionActive(action)\" [name]=\"action.icon\"></nile-icon>\n <span class=\"action-label\">{{ action.label }}</span>\n </nile-menu-item>\n \n <!-- Add divider after action groups -->\n <nile-divider *ngIf=\"shouldShowDividerAfter(action, i, last)\"></nile-divider>\n </ng-container>\n \n <!-- Fallback if no actions -->\n <nile-menu-item *ngIf=\"visibleActions.length === 0\">\n No actions available\n </nile-menu-item>\n </nile-menu>\n \n <!-- Filter popup (conditionally rendered) -->\n <st-column-filter\n #filterPopup\n *ngIf=\"isFilterOpen && context\"\n [column]=\"context.column\"\n [tableState]=\"context.tableState\"\n [columnIndex]=\"context.columnIndex\"\n [isFirstColumn]=\"context.isFirstColumn\"\n [isLastColumn]=\"context.isLastColumn\"\n [isOpen]=\"isFilterOpen\"\n (filterApplied)=\"onFilterApplied($event)\"\n (filterCleared)=\"onFilterCleared()\"\n (closed)=\"onFilterClosed()\">\n </st-column-filter>\n </div>\n</div>\n", styles: [".dropdown-container{position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998}.dropdown-backdrop{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:auto;z-index:9998}.column-menu-dropdown{min-width:200px;max-width:300px;background-color:#fff;border-radius:8px;box-shadow:0 10px 25px #00000026;overflow:hidden;pointer-events:auto;z-index:9999}nile-menu nile-divider::part(divider){margin:0}nile-menu nile-menu-item::part(base){height:2.5rem;min-height:auto}nile-menu nile-menu-item .checkmark{margin-right:8px;color:#4299e1;font-weight:700}\n"] }]
7965
8283
  }], propDecorators: { isOpen: [{
7966
8284
  type: Input
7967
8285
  }], position: [{
@@ -7975,6 +8293,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
7975
8293
  }], filterPopup: [{
7976
8294
  type: ViewChild,
7977
8295
  args: ['filterPopup']
8296
+ }], dropdownPanel: [{
8297
+ type: ViewChild,
8298
+ args: ['dropdownPanel']
7978
8299
  }], onBackdropClick: [{
7979
8300
  type: HostListener,
7980
8301
  args: ['click', ['$event']]
@@ -7987,7 +8308,7 @@ class StRowActionsDropdownComponent {
7987
8308
  */
7988
8309
  this.isOpen = false;
7989
8310
  /**
7990
- * Position of the dropdown (x, y coordinates)
8311
+ * Position of the dropdown (x, y coordinates, triggerTop for flip positioning)
7991
8312
  */
7992
8313
  this.position = { x: 0, y: 0 };
7993
8314
  /**
@@ -8042,35 +8363,40 @@ class StRowActionsDropdownComponent {
8042
8363
  this.dropdownStyle = {};
8043
8364
  return;
8044
8365
  }
8045
- const DROPDOWN_WIDTH = 200; // Approximate width
8046
- const DROPDOWN_HEIGHT = this.visibleActions.length * 40 + 16; // Approximate height
8047
- const viewportWidth = window.innerWidth;
8048
- const viewportHeight = window.innerHeight;
8049
8366
  let left = this.position.x;
8050
8367
  let top = this.position.y;
8051
- // Check if dropdown would overflow right edge
8052
- if (left + DROPDOWN_WIDTH > viewportWidth) {
8053
- left = viewportWidth - DROPDOWN_WIDTH - 10;
8054
- }
8055
- // Check if dropdown would overflow bottom edge
8056
- if (top + DROPDOWN_HEIGHT > viewportHeight) {
8057
- // Position above the trigger
8058
- top = this.position.y - DROPDOWN_HEIGHT;
8059
- }
8060
- // Ensure dropdown doesn't go off-screen on the left
8061
- if (left < 10) {
8062
- left = 10;
8063
- }
8064
- // Ensure dropdown doesn't go off-screen on the top
8065
- if (top < 10) {
8066
- top = 10;
8067
- }
8368
+ // Render at initial position first (hidden until measured)
8068
8369
  this.dropdownStyle = {
8069
8370
  position: 'fixed',
8070
8371
  left: `${left}px`,
8071
8372
  top: `${top}px`,
8072
- zIndex: TableZIndex.ROW_ACTIONS_DROPDOWN
8373
+ zIndex: TableZIndex.ROW_ACTIONS_DROPDOWN,
8374
+ visibility: 'hidden'
8073
8375
  };
8376
+ // After rendering, measure actual size and adjust position directly on the DOM
8377
+ // (OnPush change detection won't pick up property changes inside requestAnimationFrame)
8378
+ requestAnimationFrame(() => {
8379
+ var _a, _b;
8380
+ const el = (_a = this.dropdownPanel) === null || _a === void 0 ? void 0 : _a.nativeElement;
8381
+ if (!el)
8382
+ return;
8383
+ const viewportWidth = window.innerWidth;
8384
+ const viewportHeight = window.innerHeight;
8385
+ const dropdownWidth = el.offsetWidth || 200;
8386
+ const dropdownHeight = el.offsetHeight || (this.visibleActions.length * 40 + 16);
8387
+ if (left + dropdownWidth > viewportWidth) {
8388
+ left = viewportWidth - dropdownWidth - 10;
8389
+ }
8390
+ if (top + dropdownHeight > viewportHeight) {
8391
+ const triggerTop = (_b = this.position.triggerTop) !== null && _b !== void 0 ? _b : this.position.y;
8392
+ top = triggerTop - dropdownHeight - 4;
8393
+ }
8394
+ left = Math.max(10, left);
8395
+ top = Math.max(10, top);
8396
+ el.style.left = `${left}px`;
8397
+ el.style.top = `${top}px`;
8398
+ el.style.visibility = 'visible';
8399
+ });
8074
8400
  }
8075
8401
  /**
8076
8402
  * Handle action click
@@ -8124,10 +8450,10 @@ class StRowActionsDropdownComponent {
8124
8450
  }
8125
8451
  }
8126
8452
  StRowActionsDropdownComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StRowActionsDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
8127
- StRowActionsDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\" class=\"dropdown-menu\" [style.left.px]=\"dropdownStyle.left\" [style.top.px]=\"dropdownStyle.top\">\n <ng-container *ngFor=\"let action of visibleActions\">\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n <nile-icon *ngIf=\"action.icon\" size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </ng-container>\n \n <nile-menu-item *ngIf=\"visibleActions.length === 0\">No actions available</nile-menu-item>\n </nile-menu>\n </div>\n\n </div>\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"], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8453
+ StRowActionsDropdownComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: { isOpen: "isOpen", position: "position", context: "context" }, outputs: { actionClicked: "actionClicked", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscapeKey($event)" } }, viewQueries: [{ propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\">\n <ng-container *ngFor=\"let action of visibleActions\">\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n <nile-icon *ngIf=\"action.icon\" size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </ng-container>\n \n <nile-menu-item *ngIf=\"visibleActions.length === 0\">No actions available</nile-menu-item>\n </nile-menu>\n </div>\n</div>\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"], directives: [{ type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8128
8454
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StRowActionsDropdownComponent, decorators: [{
8129
8455
  type: Component,
8130
- args: [{ selector: 'st-row-actions-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\" class=\"dropdown-menu\" [style.left.px]=\"dropdownStyle.left\" [style.top.px]=\"dropdownStyle.top\">\n <ng-container *ngFor=\"let action of visibleActions\">\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n <nile-icon *ngIf=\"action.icon\" size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </ng-container>\n \n <nile-menu-item *ngIf=\"visibleActions.length === 0\">No actions available</nile-menu-item>\n </nile-menu>\n </div>\n\n </div>\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"] }]
8456
+ args: [{ selector: 'st-row-actions-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dropdown-container\" *ngIf=\"isOpen && context\">\n <!-- Backdrop -->\n <div class=\"dropdown-overlay\" (click)=\"closed.emit()\"></div>\n \n <!-- Dropdown menu -->\n <div class=\"dropdown-menu\" #dropdownPanel [ngStyle]=\"dropdownStyle\">\n <nile-menu *ngIf=\"isOpen\">\n <ng-container *ngFor=\"let action of visibleActions\">\n <nile-menu-item [class.disabled]=\"isActionDisabled(action)\" (click)=\"onActionClick(action)\" class=\"action-label\">\n <nile-icon *ngIf=\"action.icon\" size=\"14\" slot=\"prefix\" [name]=\"action.icon\"></nile-icon>\n {{ action.label }}\n </nile-menu-item>\n </ng-container>\n \n <nile-menu-item *ngIf=\"visibleActions.length === 0\">No actions available</nile-menu-item>\n </nile-menu>\n </div>\n</div>\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"] }]
8131
8457
  }], propDecorators: { isOpen: [{
8132
8458
  type: Input
8133
8459
  }], position: [{
@@ -8138,6 +8464,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
8138
8464
  type: Output
8139
8465
  }], closed: [{
8140
8466
  type: Output
8467
+ }], dropdownPanel: [{
8468
+ type: ViewChild,
8469
+ args: ['dropdownPanel']
8141
8470
  }], onEscapeKey: [{
8142
8471
  type: HostListener,
8143
8472
  args: ['document:keydown.escape', ['$event']]
@@ -9432,10 +9761,10 @@ class StTableComponent {
9432
9761
  event.stopPropagation();
9433
9762
  const target = event.currentTarget;
9434
9763
  const rect = target.getBoundingClientRect();
9435
- // Calculate position (below the button by default)
9436
9764
  const position = {
9437
9765
  x: rect.left,
9438
- y: rect.bottom + 4 // 4px gap
9766
+ y: rect.bottom + 4,
9767
+ triggerTop: rect.top
9439
9768
  };
9440
9769
  // Create context
9441
9770
  const context = {
@@ -9497,10 +9826,10 @@ class StTableComponent {
9497
9826
  event.stopPropagation();
9498
9827
  const target = event.currentTarget;
9499
9828
  const rect = target.getBoundingClientRect();
9500
- // Calculate position (below the button by default)
9501
9829
  const position = {
9502
9830
  x: rect.left,
9503
- y: rect.bottom + 4 // 4px gap
9831
+ y: rect.bottom + 4,
9832
+ triggerTop: rect.top
9504
9833
  };
9505
9834
  // Create context
9506
9835
  const context = {
@@ -13340,5 +13669,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
13340
13669
  * Generated bundle index. Do not edit.
13341
13670
  */
13342
13671
 
13343
- export { ArrayFormatter, AutosaveService, BaseColumnConfig, BooleanEditor, BooleanFormatter, BuilderPreviewComponent, BuilderToolbarComponent, Cell, CellAlignment, CellDataType, CellLifecycleState, CellVerticalAlignment, ChainValidator, ClickOutsideDirective, ColumnConfigFactory, ColumnEditorComponent, ColumnListComponent, Columns, CurrencyFormatter, DEFAULT_AUTOSAVE_CONFIG, DEFAULT_COLUMN_CONFIG, DEFAULT_TABLE_CONFIG, DateEditor, DateFormatter, DateRangeValidator, DefaultFormatter, DefinitionBuilderComponent, DefinitionBuilderModule, DefinitionBuilderService, DefinitionExportService, DefinitionImportService, EditMode, EmailValidator, FilterOperator, FunctionFormatter, FunctionValidator, JsonSchemaValidatorService, LengthValidator, NavigationDirection, NavigationKey, NileAutoCompleteEditor, NileCalendarEditor, NileCodeEditor, NileDatePickerEditor, NileInputEditor, NileSelectEditor, NumberEditor, NumberFormatter, OUFormatter, PatternValidators, PercentageFormatter, RangeValidator, RegexValidator, RequiredValidator, RowValidationService, SampleDataGeneratorService, SelectEditor, SharedTableComponentsModule, SheetState, SimpleColumnConfig, SmartTableModule, SortDirection, StAddColumnButtonComponent, StCellComponent, StColumnEditorModalComponent, StColumnFilterComponent, StColumnMenuDropdownComponent, StColumnResizeDirective, StColumnVisibilityComponent, StHeaderComponent, StKeyboardNavigationDirective, StPaginationComponent, StRowActionsDropdownComponent, StSheetActionsComponent, StSheetComponent, StTableActionsComponent, StTableComponent, StWorkbookComponent, StringFormatter, TableConfigEditorComponent, TableState, TableZIndex, TemplateFormatter, TextAreaEditor, TextEditor, UrlValidator, ValidationLoggerService, VirtualScrollService, WorkbookState, canEdit, createCellState, createMemento, dnToHumanReadable, isCellValid, isDisplayMode, isNullOrUndefined, isValidDate, isValidationSuccess, mergeTableConfig, registerFormatter, resolveFormatter, restoreFromMemento };
13672
+ export { ArrayFormatter, AutosaveService, BaseColumnConfig, BooleanEditor, BooleanFormatter, BuilderPreviewComponent, BuilderToolbarComponent, Cell, CellAlignment, CellDataType, CellLifecycleState, CellVerticalAlignment, ChainValidator, ClickOutsideDirective, ColumnConfigFactory, ColumnEditorComponent, ColumnListComponent, Columns, CurrencyFormatter, DEFAULT_AUTOSAVE_CONFIG, DEFAULT_COLUMN_CONFIG, DEFAULT_TABLE_CONFIG, DateEditor, DateFormatter, DateRangeValidator, DefaultFormatter, DefinitionBuilderComponent, DefinitionBuilderModule, DefinitionBuilderService, DefinitionExportService, DefinitionImportService, EditMode, EmailValidator, FilterOperator, FunctionFormatter, FunctionValidator, JsonSchemaValidatorService, LengthValidator, NavigationDirection, NavigationKey, NileAutoCompleteEditor, NileCalendarEditor, NileChipEditor, NileCodeEditor, NileDatePickerEditor, NileInputEditor, NileSelectEditor, NumberEditor, NumberFormatter, OUFormatter, PatternValidators, PercentageFormatter, RangeValidator, RegexValidator, RequiredValidator, RowValidationService, SampleDataGeneratorService, SelectEditor, SharedTableComponentsModule, SheetState, SimpleColumnConfig, SmartTableModule, SortDirection, StAddColumnButtonComponent, StCellComponent, StColumnEditorModalComponent, StColumnFilterComponent, StColumnMenuDropdownComponent, StColumnResizeDirective, StColumnVisibilityComponent, StHeaderComponent, StKeyboardNavigationDirective, StPaginationComponent, StRowActionsDropdownComponent, StSheetActionsComponent, StSheetComponent, StTableActionsComponent, StTableComponent, StWorkbookComponent, StringFormatter, TableConfigEditorComponent, TableState, TableZIndex, TemplateFormatter, TextAreaEditor, TextEditor, UrlValidator, ValidationLoggerService, VirtualScrollService, WorkbookState, canEdit, createCellState, createMemento, dnToHumanReadable, isCellValid, isDisplayMode, isNullOrUndefined, isValidDate, isValidationSuccess, mergeTableConfig, registerFormatter, resolveFormatter, restoreFromMemento };
13344
13673
  //# sourceMappingURL=aquera-ngx-smart-table.mjs.map