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

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.
@@ -4890,6 +4890,299 @@ class NileDatePickerEditor {
4890
4890
  }
4891
4891
  }
4892
4892
 
4893
+ /**
4894
+ * Custom editor using NileChip from @aquera/nile-elements
4895
+ * Renders the chip input in a floating popover below the cell to avoid row height mismatch.
4896
+ *
4897
+ * @see https://nile.aqueralabs.com/1.6.3/chip?theme=enterprise
4898
+ */
4899
+ let chipStylesInjected = false;
4900
+ function injectChipStyles() {
4901
+ if (chipStylesInjected)
4902
+ return;
4903
+ chipStylesInjected = true;
4904
+ const styleId = 'nile-chip-editor-styles';
4905
+ if (document.getElementById(styleId))
4906
+ return;
4907
+ const style = document.createElement('style');
4908
+ style.id = styleId;
4909
+ style.textContent = `
4910
+ .st-chip-popover {
4911
+ position: fixed;
4912
+ z-index: 10000;
4913
+ background: var(--nile-colors-white-base, #fff);
4914
+ border: 1px solid var(--nile-colors-neutral-200, #e2e8f0);
4915
+ border-radius: 6px;
4916
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
4917
+ padding: 8px;
4918
+ box-sizing: border-box;
4919
+ max-height: 200px;
4920
+ overflow-y: auto;
4921
+ }
4922
+ .st-chip-popover nile-chip {
4923
+ width: 100%;
4924
+ }
4925
+ .st-chip-popover nile-chip::part(base) {
4926
+ border: none !important;
4927
+ box-shadow: none !important;
4928
+ min-height: 32px;
4929
+ }
4930
+ .st-chip-popover nile-chip::part(input) {
4931
+ font-size: var(--nile-font-size-small, 13px);
4932
+ }
4933
+ `;
4934
+ document.head.appendChild(style);
4935
+ }
4936
+ /**
4937
+ * Custom editor that uses NileChip (tag input) component.
4938
+ * Renders in a floating popover below the cell to avoid expanding row height.
4939
+ *
4940
+ * Cell value is expected to be `string[]` (array of tag strings).
4941
+ */
4942
+ class NileChipEditor {
4943
+ constructor(options) {
4944
+ this.options = options;
4945
+ this.acceptsInitialKeypress = false;
4946
+ this.eventListeners = [];
4947
+ this.trackedValues = [];
4948
+ }
4949
+ edit(context) {
4950
+ if (!context.container) {
4951
+ console.warn('NileChipEditor requires a container element');
4952
+ return;
4953
+ }
4954
+ injectChipStyles();
4955
+ this.cellContainer = context.container;
4956
+ // Create the floating popover
4957
+ this.popover = document.createElement('div');
4958
+ this.popover.className = 'st-chip-popover';
4959
+ // Create nile-chip inside the popover
4960
+ this.chip = document.createElement('nile-chip');
4961
+ this.chip.className = 'st-cell-editor st-nile-chip-editor';
4962
+ this.setInitialValue(context.value);
4963
+ this.applyOptions();
4964
+ this.popover.appendChild(this.chip);
4965
+ // Apply custom max-height if provided
4966
+ if (this.options?.popoverMaxHeight) {
4967
+ this.popover.style.maxHeight = `${this.options.popoverMaxHeight}px`;
4968
+ }
4969
+ // Append popover to body and position it
4970
+ document.body.appendChild(this.popover);
4971
+ this.positionPopover();
4972
+ this.setupEventListeners(context);
4973
+ if (this.options?.autoFocus !== false) {
4974
+ setTimeout(() => {
4975
+ try {
4976
+ this.chip?.focus();
4977
+ }
4978
+ catch { /* ignore */ }
4979
+ }, 0);
4980
+ }
4981
+ }
4982
+ positionPopover() {
4983
+ if (!this.popover || !this.cellContainer)
4984
+ return;
4985
+ const rect = this.cellContainer.getBoundingClientRect();
4986
+ const minWidth = this.options?.popoverMinWidth ?? rect.width;
4987
+ const popoverWidth = Math.max(minWidth, rect.width);
4988
+ this.popover.style.top = `${rect.bottom + 2}px`;
4989
+ this.popover.style.left = `${rect.left}px`;
4990
+ this.popover.style.width = `${popoverWidth}px`;
4991
+ // After rendering, check if it goes off-screen bottom and flip above if needed
4992
+ requestAnimationFrame(() => {
4993
+ if (!this.popover)
4994
+ return;
4995
+ const popRect = this.popover.getBoundingClientRect();
4996
+ if (popRect.bottom > window.innerHeight) {
4997
+ this.popover.style.top = `${rect.top - popRect.height - 2}px`;
4998
+ }
4999
+ });
5000
+ }
5001
+ setInitialValue(value) {
5002
+ if (!this.chip)
5003
+ return;
5004
+ if (Array.isArray(value)) {
5005
+ this.trackedValues = [...value];
5006
+ this.chip.value = this.trackedValues;
5007
+ }
5008
+ else if (typeof value === 'string' && value) {
5009
+ this.trackedValues = [value];
5010
+ this.chip.value = this.trackedValues;
5011
+ }
5012
+ else {
5013
+ this.trackedValues = [];
5014
+ this.chip.value = [];
5015
+ }
5016
+ }
5017
+ applyOptions() {
5018
+ if (!this.chip || !this.options)
5019
+ return;
5020
+ if (this.options.placeholder) {
5021
+ this.chip.placeholder = this.options.placeholder;
5022
+ }
5023
+ if (this.options.label) {
5024
+ this.chip.label = this.options.label;
5025
+ }
5026
+ if (this.options.helpText) {
5027
+ this.chip.helpText = this.options.helpText;
5028
+ }
5029
+ if (this.options.disabled !== undefined) {
5030
+ this.chip.disabled = this.options.disabled;
5031
+ }
5032
+ if (this.options.readonly !== undefined) {
5033
+ this.chip.readonly = this.options.readonly;
5034
+ }
5035
+ if (this.options.acceptUserInput !== undefined) {
5036
+ this.chip.acceptUserInput = this.options.acceptUserInput;
5037
+ }
5038
+ if (this.options.noDuplicates !== undefined) {
5039
+ this.chip.noDuplicates = this.options.noDuplicates;
5040
+ }
5041
+ if (this.options.clearable !== undefined) {
5042
+ this.chip.clearable = this.options.clearable;
5043
+ }
5044
+ if (this.options.noWrap !== undefined) {
5045
+ this.chip.noWrap = this.options.noWrap;
5046
+ }
5047
+ if (this.options.noAutoComplete !== undefined) {
5048
+ this.chip.noAutoComplete = this.options.noAutoComplete;
5049
+ }
5050
+ if (this.options.enableVirtualScroll !== undefined) {
5051
+ this.chip.enableVirtualScroll = this.options.enableVirtualScroll;
5052
+ }
5053
+ if (this.options.openDropdownOnFocus !== undefined) {
5054
+ this.chip.openDropdownOnFocus = this.options.openDropdownOnFocus;
5055
+ }
5056
+ if (this.options.loading !== undefined) {
5057
+ this.chip.loading = this.options.loading;
5058
+ }
5059
+ // Visual states
5060
+ if (this.options.warning !== undefined) {
5061
+ this.chip.warning = this.options.warning;
5062
+ }
5063
+ if (this.options.error !== undefined) {
5064
+ this.chip.error = this.options.error;
5065
+ }
5066
+ if (this.options.success !== undefined) {
5067
+ this.chip.success = this.options.success;
5068
+ }
5069
+ if (this.options.errorMessage) {
5070
+ this.chip.errorMessage = this.options.errorMessage;
5071
+ }
5072
+ if (this.options.errorIndexes) {
5073
+ this.chip.errorIndexes = this.options.errorIndexes;
5074
+ }
5075
+ // Autocomplete options
5076
+ if (this.options.autoCompleteOptions) {
5077
+ const opts = this.options.autoCompleteOptions;
5078
+ const stringOpts = opts.map(o => typeof o === 'string' ? o : (o.label ?? o.value));
5079
+ this.chip.autoCompleteOptions = stringOpts;
5080
+ }
5081
+ if (this.options.filterFunction) {
5082
+ this.chip.filterFunction = this.options.filterFunction;
5083
+ }
5084
+ if (this.options.renderItemFunction) {
5085
+ this.chip.renderItemFunction = this.options.renderItemFunction;
5086
+ }
5087
+ }
5088
+ addListener(element, event, handler, capture) {
5089
+ element.addEventListener(event, handler, capture);
5090
+ this.eventListeners.push({ element, event, handler, capture });
5091
+ }
5092
+ setupEventListeners(context) {
5093
+ if (!this.chip)
5094
+ return;
5095
+ // Track chip changes
5096
+ this.addListener(this.chip, 'nile-chip-change', (e) => {
5097
+ const detail = e.detail;
5098
+ const newValue = Array.isArray(detail?.value) ? [...detail.value] : (this.chip?.value ? [...this.chip.value] : []);
5099
+ this.trackedValues = newValue;
5100
+ context.onChange(newValue);
5101
+ });
5102
+ // Keyboard handling on the chip element
5103
+ this.addListener(this.chip, 'keydown', (e) => {
5104
+ const keyEvent = e;
5105
+ if (keyEvent.key === 'Enter') {
5106
+ keyEvent.stopPropagation();
5107
+ }
5108
+ else if (keyEvent.key === 'Escape') {
5109
+ keyEvent.preventDefault();
5110
+ keyEvent.stopPropagation();
5111
+ context.onCancel();
5112
+ }
5113
+ else if (keyEvent.key === 'Tab') {
5114
+ keyEvent.preventDefault();
5115
+ keyEvent.stopPropagation();
5116
+ context.onSave(this.getCurrentValue());
5117
+ }
5118
+ });
5119
+ // Click-outside: save when clicking anywhere outside the popover
5120
+ let saveTriggered = false;
5121
+ const mousedownHandler = (e) => {
5122
+ if (saveTriggered)
5123
+ return;
5124
+ if (!this.popover)
5125
+ return;
5126
+ const path = e.composedPath();
5127
+ for (const el of path) {
5128
+ if (el === this.popover)
5129
+ return;
5130
+ if (el === this.chip)
5131
+ return;
5132
+ if (el instanceof HTMLElement) {
5133
+ if (el.tagName?.toLowerCase() === 'nile-chip')
5134
+ return;
5135
+ if (el.className && typeof el.className === 'string' && el.className.includes('nile-chip'))
5136
+ return;
5137
+ }
5138
+ }
5139
+ saveTriggered = true;
5140
+ context.onSave(this.getCurrentValue());
5141
+ };
5142
+ document.addEventListener('mousedown', mousedownHandler, true);
5143
+ this._documentMousedownHandler = mousedownHandler;
5144
+ // Reposition on scroll/resize so popover stays aligned with the cell
5145
+ const reposition = () => this.positionPopover();
5146
+ this.addListener(window, 'resize', reposition);
5147
+ this.addListener(window, 'scroll', reposition, true);
5148
+ }
5149
+ destroy() {
5150
+ // Remove document mousedown handler
5151
+ if (this._documentMousedownHandler) {
5152
+ document.removeEventListener('mousedown', this._documentMousedownHandler, true);
5153
+ delete this._documentMousedownHandler;
5154
+ }
5155
+ // Remove all tracked listeners
5156
+ for (const { element, event, handler, capture } of this.eventListeners) {
5157
+ element.removeEventListener(event, handler, capture);
5158
+ }
5159
+ this.eventListeners = [];
5160
+ // Remove the popover from the DOM
5161
+ if (this.popover) {
5162
+ this.popover.remove();
5163
+ this.popover = undefined;
5164
+ }
5165
+ this.chip = undefined;
5166
+ this.cellContainer = undefined;
5167
+ this.trackedValues = [];
5168
+ }
5169
+ focus() {
5170
+ try {
5171
+ this.chip?.focus();
5172
+ }
5173
+ catch { /* ignore */ }
5174
+ }
5175
+ getCurrentValue() {
5176
+ if (this.trackedValues.length > 0) {
5177
+ return [...this.trackedValues];
5178
+ }
5179
+ if (!this.chip)
5180
+ return [];
5181
+ const val = this.chip.value;
5182
+ return Array.isArray(val) ? [...val] : [];
5183
+ }
5184
+ }
5185
+
4893
5186
  /**
4894
5187
  * Custom editor using NileCodeEditor from @aquera/nile-elements
4895
5188
  * This provides code editing capabilities with syntax highlighting for table cells
@@ -5031,7 +5324,7 @@ class NileCodeEditor {
5031
5324
  this.syncingFromDialog = false; // Flag to prevent inline editor from overwriting multiline content
5032
5325
  this.userEditedInline = false; // Flag to track if user has typed in inline editor
5033
5326
  this.dialogOriginalValue = ''; // Store original value when dialog opens
5034
- this.dialogCurrentValue = ''; // Track current value in dialog
5327
+ this.dialogCurrentValue = null; // Track current value in dialog
5035
5328
  }
5036
5329
  edit(context) {
5037
5330
  if (!context.container) {
@@ -5306,7 +5599,7 @@ class NileCodeEditor {
5306
5599
  */
5307
5600
  getDialogEditorValue() {
5308
5601
  // Use tracked value from change events (most reliable)
5309
- if (this.dialogCurrentValue) {
5602
+ if (this.dialogCurrentValue !== null && this.dialogCurrentValue !== undefined) {
5310
5603
  return this.dialogCurrentValue.replace(/\n+$/, '');
5311
5604
  }
5312
5605
  if (!this.dialogEditor)
@@ -5335,10 +5628,9 @@ class NileCodeEditor {
5335
5628
  applyDialogChanges() {
5336
5629
  if (!this.dialogOpen)
5337
5630
  return;
5338
- // Get the value from dialog editor - try multiple sources
5631
+ // Always read live dialog editor state to avoid stale tracked values from debounced updates
5339
5632
  let dialogValue = this.dialogCurrentValue;
5340
- // If no tracked value, try reading directly from dialog editor
5341
- if (!dialogValue && this.dialogEditor) {
5633
+ if (this.dialogEditor) {
5342
5634
  try {
5343
5635
  const shadowRoot = this.dialogEditor.shadowRoot;
5344
5636
  if (shadowRoot) {
@@ -5352,12 +5644,12 @@ class NileCodeEditor {
5352
5644
  // Fall through
5353
5645
  }
5354
5646
  // Fallback to value property
5355
- if (!dialogValue) {
5647
+ if (dialogValue === null || dialogValue === undefined) {
5356
5648
  dialogValue = this.dialogEditor.value ?? '';
5357
5649
  }
5358
5650
  }
5359
5651
  // Strip trailing newlines
5360
- dialogValue = (dialogValue || '').replace(/\n+$/, '');
5652
+ dialogValue = (dialogValue ?? '').replace(/\n+$/, '');
5361
5653
  // Update tracked value and inline editor
5362
5654
  this.trackedValue = dialogValue;
5363
5655
  this.userEditedInline = false;
@@ -5399,7 +5691,7 @@ class NileCodeEditor {
5399
5691
  */
5400
5692
  closeDialogUI() {
5401
5693
  this.dialogOpen = false;
5402
- this.dialogCurrentValue = '';
5694
+ this.dialogCurrentValue = null;
5403
5695
  if (this.dialog) {
5404
5696
  this.dialog.open = false;
5405
5697
  const dialogRef = this.dialog;
@@ -5644,7 +5936,7 @@ class NileCodeEditor {
5644
5936
  this.trackedValue = null;
5645
5937
  this.userEditedInline = false;
5646
5938
  this.dialogOriginalValue = '';
5647
- this.dialogCurrentValue = '';
5939
+ this.dialogCurrentValue = null;
5648
5940
  }
5649
5941
  focus() {
5650
5942
  this.editor?.focus();
@@ -13350,5 +13642,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
13350
13642
  * Generated bundle index. Do not edit.
13351
13643
  */
13352
13644
 
13353
- 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 };
13645
+ 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 };
13354
13646
  //# sourceMappingURL=aquera-ngx-smart-table.mjs.map