@aquera/ngx-smart-table 0.0.17-patch-0.1 → 0.0.17-patch-0.2

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.
@@ -2573,10 +2573,38 @@ class Cell {
2573
2573
  return this.rowIndex;
2574
2574
  }
2575
2575
  /**
2576
- * Set loading state
2576
+ * Link this cell to its replacement so future state mutations forward.
2577
+ */
2578
+ setReplacement(replacement) {
2579
+ this.replacementCell = replacement;
2580
+ }
2581
+ onStateChange(callback) {
2582
+ this.stateChangeCallback = callback;
2583
+ }
2584
+ /**
2585
+ * Set loading state. Forwards to replacement cell if this cell was replaced.
2577
2586
  */
2578
2587
  setLoading(isLoading) {
2588
+ if (this.replacementCell) {
2589
+ this.replacementCell.setLoading(isLoading);
2590
+ return;
2591
+ }
2579
2592
  this.state.isLoading = isLoading;
2593
+ try {
2594
+ this.stateChangeCallback?.();
2595
+ }
2596
+ catch {
2597
+ this.stateChangeCallback = undefined;
2598
+ }
2599
+ }
2600
+ /**
2601
+ * Set cell value (public API, forwards to replacement if replaced).
2602
+ */
2603
+ setValueExternal(value) {
2604
+ if (this.replacementCell) {
2605
+ return this.replacementCell.setValueExternal(value);
2606
+ }
2607
+ return this.setValue(value, true);
2580
2608
  }
2581
2609
  /**
2582
2610
  * Set disabled state
@@ -3649,17 +3677,28 @@ function injectDropdownStyles() {
3649
3677
  }
3650
3678
  /* Combobox styling using ::part() selector */
3651
3679
  nile-select.st-cell-editor::part(combobox) {
3652
- background-color: var(--nile-colors-white-base, var(--ng-colors-bg-primary)) !important;
3680
+ background-color: transparent !important;
3653
3681
  border: solid 1px transparent !important;
3654
- margin: 1px 4px !important;
3682
+ margin: 0px !important;
3683
+ max-height: 28px;
3655
3684
  }
3656
3685
  nile-select.st-cell-editor::part(combobox):hover {
3657
3686
  border: solid 1px transparent !important;
3658
3687
  }
3659
3688
  .st-cell-editor::part(combobox) {
3660
- background-color: var(--nile-colors-white-base, var(--ng-colors-bg-primary)) !important;
3689
+ background-color: transparent !important;
3661
3690
  border: solid 1px transparent !important;
3662
- margin: 1px 4px !important;
3691
+ margin: 0px !important;
3692
+ max-height: 28px;
3693
+ }
3694
+ /* Tag spacing */
3695
+ nile-select.st-cell-editor::part(tag) {
3696
+ margin-right: 0px;
3697
+ padding: 1px 2px;
3698
+ }
3699
+ .st-cell-editor::part(tag) {
3700
+ margin-right: 0px;
3701
+ padding: 1px 2px;
3663
3702
  }
3664
3703
  /* Search input full width */
3665
3704
  .nile-select-portal-append .select__search {
@@ -4724,6 +4763,625 @@ class NileDatePickerEditor {
4724
4763
  }
4725
4764
  }
4726
4765
 
4766
+ /**
4767
+ * Custom editor using NileCodeEditor from @aquera/nile-elements
4768
+ * This provides code editing capabilities with syntax highlighting for table cells
4769
+ */
4770
+ /**
4771
+ * Inject global styles for nile-code-editor in table cells
4772
+ */
4773
+ let codeEditorStylesInjected = false;
4774
+ function injectCodeEditorStyles() {
4775
+ if (codeEditorStylesInjected)
4776
+ return;
4777
+ codeEditorStylesInjected = true;
4778
+ const styleId = 'nile-code-editor-cell-styles';
4779
+ if (document.getElementById(styleId))
4780
+ return;
4781
+ const style = document.createElement('style');
4782
+ style.id = styleId;
4783
+ style.textContent = `
4784
+ /* Nile Code Editor cell styling */
4785
+ nile-code-editor.st-cell-editor {
4786
+ display: block;
4787
+ width: 100%;
4788
+ height: 100%;
4789
+ font-size: inherit !important;
4790
+ font-family: inherit !important;
4791
+ line-height: inherit !important;
4792
+ }
4793
+ nile-code-editor.st-cell-editor::part(code-editor-base) {
4794
+ border: none !important;
4795
+ min-height: 100% !important;
4796
+ background: transparent !important;
4797
+ font-size: inherit !important;
4798
+ font-family: inherit !important;
4799
+ line-height: inherit !important;
4800
+ }
4801
+ /* Ensure proper sizing within table cell */
4802
+ .st-nile-code-editor {
4803
+ width: 100%;
4804
+ height: 100%;
4805
+ min-height: 28px;
4806
+ font-size: inherit !important;
4807
+ }
4808
+ /* CodeMirror content should inherit font size */
4809
+ nile-code-editor.st-cell-editor .cm-content,
4810
+ nile-code-editor.st-cell-editor .cm-line {
4811
+ font-size: inherit !important;
4812
+ font-family: inherit !important;
4813
+ line-height: inherit !important;
4814
+ }
4815
+ /* Container wrapper for editor + expand button */
4816
+ .st-code-editor-wrapper {
4817
+ display: flex;
4818
+ align-items: center;
4819
+ width: 100%;
4820
+ height: 100%;
4821
+ gap: 4px;
4822
+ }
4823
+ .st-code-editor-wrapper .st-code-editor-input {
4824
+ flex: 1;
4825
+ min-width: 0;
4826
+ height: 100%;
4827
+ }
4828
+ .st-code-editor-wrapper .st-expand-button {
4829
+ display: flex;
4830
+ align-items: center;
4831
+ justify-content: center;
4832
+ width: 24px;
4833
+ height: 24px;
4834
+ min-width: 24px;
4835
+ padding: 0;
4836
+ border: none;
4837
+ background: transparent;
4838
+ cursor: pointer;
4839
+ color: var(--nile-color-neutral-500, #6b7280);
4840
+ border-radius: 4px;
4841
+ transition: all 0.2s;
4842
+ }
4843
+ .st-code-editor-wrapper .st-expand-button:hover {
4844
+ background: var(--nile-color-neutral-100, #f3f4f6);
4845
+ color: var(--nile-color-neutral-700, #374151);
4846
+ }
4847
+ /* Dialog code editor styling */
4848
+ .st-code-editor-dialog::part(panel) {
4849
+ max-height: var(--max-height, 80vh) !important;
4850
+ overflow: hidden !important;
4851
+ }
4852
+ .st-code-editor-dialog::part(body) {
4853
+ overflow: auto !important;
4854
+ }
4855
+ .st-code-editor-dialog nile-code-editor {
4856
+ width: 100%;
4857
+ display: block;
4858
+ }
4859
+ .st-code-editor-dialog nile-code-editor::part(code-editor-base) {
4860
+ border: 1px solid var(--nile-color-neutral-200, #e5e7eb) !important;
4861
+ border-radius: 4px !important;
4862
+ overflow: auto !important;
4863
+ min-height: var(--dialog-editor-min-height, 300px) !important;
4864
+ }
4865
+ .st-code-editor-dialog nile-code-editor .cm-editor {
4866
+ min-height: var(--dialog-editor-min-height, 300px) !important;
4867
+ }
4868
+ .st-code-editor-dialog nile-code-editor .cm-content {
4869
+ min-height: var(--dialog-editor-min-height, 300px) !important;
4870
+ }
4871
+ `;
4872
+ document.head.appendChild(style);
4873
+ }
4874
+ /**
4875
+ * Custom editor that uses NileCodeEditor component
4876
+ * Provides code editing with syntax highlighting for table cells
4877
+ * @template T The value type (typically string)
4878
+ */
4879
+ class NileCodeEditor {
4880
+ constructor(options) {
4881
+ this.options = options;
4882
+ this.eventListeners = [];
4883
+ this.dialogOpen = false;
4884
+ this.expandButtonClicked = false;
4885
+ this.trackedValue = null;
4886
+ }
4887
+ edit(context) {
4888
+ if (!context.container) {
4889
+ console.warn('NileCodeEditor requires a container element');
4890
+ return;
4891
+ }
4892
+ this.context = context;
4893
+ this.trackedValue = null;
4894
+ // Inject global styles once
4895
+ injectCodeEditorStyles();
4896
+ // Check if we should show expand button (default: true)
4897
+ const showExpandButton = this.options?.showExpandButton !== false;
4898
+ if (showExpandButton) {
4899
+ // Create wrapper for editor + expand button
4900
+ this.wrapper = document.createElement('div');
4901
+ this.wrapper.className = 'st-code-editor-wrapper';
4902
+ // Create the editor container
4903
+ const editorContainer = document.createElement('div');
4904
+ editorContainer.className = 'st-code-editor-input';
4905
+ // Create NileCodeEditor custom element
4906
+ this.editor = document.createElement('nile-code-editor');
4907
+ this.editor.value = String(context.value ?? '');
4908
+ this.editor.className = 'st-cell-editor st-nile-code-editor';
4909
+ this.editor.style.width = '100%';
4910
+ this.editor.style.height = '100%';
4911
+ this.editor.style.boxSizing = 'border-box';
4912
+ this.editor.noborder = this.options?.noborder !== false;
4913
+ editorContainer.appendChild(this.editor);
4914
+ this.wrapper.appendChild(editorContainer);
4915
+ // Create expand button
4916
+ this.expandButton = document.createElement('button');
4917
+ this.expandButton.className = 'st-expand-button';
4918
+ this.expandButton.type = 'button';
4919
+ this.expandButton.title = 'Expand editor';
4920
+ this.expandButton.innerHTML = '<nile-icon name="expand-06" size="16"></nile-icon>';
4921
+ // Use mousedown to set flag BEFORE blur event fires
4922
+ this.expandButton.addEventListener('mousedown', (e) => {
4923
+ e.preventDefault();
4924
+ e.stopPropagation();
4925
+ this.expandButtonClicked = true;
4926
+ });
4927
+ this.expandButton.addEventListener('click', (e) => {
4928
+ e.preventDefault();
4929
+ e.stopPropagation();
4930
+ this.openDialog();
4931
+ });
4932
+ this.wrapper.appendChild(this.expandButton);
4933
+ // Clear container and append wrapper
4934
+ context.container.innerHTML = '';
4935
+ context.container.appendChild(this.wrapper);
4936
+ }
4937
+ else {
4938
+ // Create NileCodeEditor custom element without wrapper
4939
+ this.editor = document.createElement('nile-code-editor');
4940
+ this.editor.value = String(context.value ?? '');
4941
+ this.editor.className = 'st-cell-editor st-nile-code-editor';
4942
+ this.editor.style.width = '100%';
4943
+ this.editor.style.height = '100%';
4944
+ this.editor.style.boxSizing = 'border-box';
4945
+ this.editor.noborder = this.options?.noborder !== false;
4946
+ // Clear container and append editor
4947
+ context.container.innerHTML = '';
4948
+ context.container.appendChild(this.editor);
4949
+ }
4950
+ // Apply all configuration options
4951
+ this.applyOptions();
4952
+ // Set up event listeners
4953
+ this.setupEventListeners(context);
4954
+ // Auto focus - need a slight delay for nile-code-editor to fully initialize
4955
+ if (this.options?.autoFocus !== false) {
4956
+ // Listen for the nile-after-init event which fires when editor is ready
4957
+ const initHandler = () => {
4958
+ this.editor?.removeEventListener('nile-after-init', initHandler);
4959
+ this.focusEditor();
4960
+ };
4961
+ this.editor.addEventListener('nile-after-init', initHandler);
4962
+ // Fallback: also try after a delay in case the event already fired
4963
+ setTimeout(() => {
4964
+ this.focusEditor();
4965
+ }, 100);
4966
+ }
4967
+ }
4968
+ /**
4969
+ * Focus the editor and place cursor
4970
+ */
4971
+ focusEditor() {
4972
+ if (!this.editor)
4973
+ return;
4974
+ try {
4975
+ // Call the component's focus method
4976
+ this.editor.focus();
4977
+ // Try to directly focus the CodeMirror content area
4978
+ const shadowRoot = this.editor.shadowRoot;
4979
+ if (shadowRoot) {
4980
+ const cmContent = shadowRoot.querySelector('.cm-content');
4981
+ if (cmContent) {
4982
+ cmContent.focus();
4983
+ // Dispatch a click event to ensure cursor placement
4984
+ cmContent.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
4985
+ cmContent.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
4986
+ }
4987
+ }
4988
+ }
4989
+ catch (e) {
4990
+ // Silently handle any errors
4991
+ }
4992
+ }
4993
+ /**
4994
+ * Open the full editor dialog
4995
+ */
4996
+ openDialog() {
4997
+ if (this.dialogOpen)
4998
+ return;
4999
+ this.dialogOpen = true;
5000
+ this.expandButtonClicked = false; // Reset flag now that dialog is opening
5001
+ // Create dialog with configurable dimensions
5002
+ const dialogWidth = this.options?.dialogWidth || '600px';
5003
+ const dialogMaxHeight = this.options?.dialogMaxHeight || '80vh';
5004
+ const dialogEditorHeight = this.options?.dialogEditorHeight || '300px';
5005
+ const dialogTitle = this.options?.dialogTitle || 'Edit Code';
5006
+ this.dialog = document.createElement('nile-dialog');
5007
+ this.dialog.className = 'st-code-editor-dialog';
5008
+ this.dialog.label = dialogTitle;
5009
+ this.dialog.style.setProperty('--width', dialogWidth);
5010
+ this.dialog.style.setProperty('--max-height', dialogMaxHeight);
5011
+ // Create dialog content
5012
+ const content = document.createElement('div');
5013
+ content.style.padding = '16px';
5014
+ content.style.maxHeight = `calc(${dialogMaxHeight} - 80px)`;
5015
+ content.style.overflow = 'auto';
5016
+ // Create full editor
5017
+ this.dialogEditor = document.createElement('nile-code-editor');
5018
+ const minLines = this.options?.dialogMinLines ?? 20;
5019
+ const currentValue = this.editor?.value || '';
5020
+ const currentLineCount = (currentValue.match(/\n/g) || []).length + 1;
5021
+ const paddingLines = Math.max(0, minLines - currentLineCount);
5022
+ this.dialogEditor.value = currentValue + '\n'.repeat(paddingLines);
5023
+ this.dialogEditor.multiline = true;
5024
+ this.dialogEditor.lineNumbersMultiline = true;
5025
+ this.dialogEditor.hasScroller = true;
5026
+ const lineHeightPx = 20;
5027
+ const minHeightFromLines = `${minLines * lineHeightPx}px`;
5028
+ this.dialogEditor.style.minHeight = `max(${dialogEditorHeight}, ${minHeightFromLines})`;
5029
+ this.dialogEditor.style.maxHeight = `calc(${dialogMaxHeight} - 120px)`;
5030
+ content.style.setProperty('--dialog-editor-min-height', `max(${dialogEditorHeight}, ${minHeightFromLines})`);
5031
+ // Apply same options to dialog editor
5032
+ if (this.options?.language) {
5033
+ this.dialogEditor.language = this.options.language;
5034
+ }
5035
+ if (this.options?.placeholder) {
5036
+ this.dialogEditor.placeholder = this.options.placeholder;
5037
+ }
5038
+ if (this.options?.tabCompletion !== undefined) {
5039
+ this.dialogEditor.tabCompletion = this.options.tabCompletion;
5040
+ }
5041
+ if (this.options?.enableSearch !== undefined) {
5042
+ this.dialogEditor.enableSearch = this.options.enableSearch;
5043
+ }
5044
+ if (this.options?.enableFoldGutters !== undefined) {
5045
+ this.dialogEditor.enableFoldGutters = this.options.enableFoldGutters;
5046
+ }
5047
+ if (this.options?.customAutoCompletions) {
5048
+ this.dialogEditor.customAutoCompletions = this.options.customAutoCompletions;
5049
+ }
5050
+ if (this.options?.customCompletionsPaths) {
5051
+ this.dialogEditor.customCompletionsPaths = this.options.customCompletionsPaths;
5052
+ }
5053
+ if (this.options?.customThemeCSS) {
5054
+ this.dialogEditor.customThemeCSS = this.options.customThemeCSS;
5055
+ }
5056
+ this.dialogEditor.expandable = false;
5057
+ // Real-time sync: Update cell editor whenever dialog editor changes
5058
+ this.dialogEditor.addEventListener('nile-change', (e) => {
5059
+ const dialogValue = e.detail?.value || '';
5060
+ this.trackedValue = dialogValue;
5061
+ if (this.editor) {
5062
+ this.editor.value = dialogValue;
5063
+ }
5064
+ if (this.context) {
5065
+ this.context.onChange(dialogValue);
5066
+ }
5067
+ });
5068
+ content.appendChild(this.dialogEditor);
5069
+ this.dialog.appendChild(content);
5070
+ // Handle dialog close events (clicking X button - stay in edit mode)
5071
+ this.dialog.addEventListener('nile-request-close', (e) => {
5072
+ const customEvent = e;
5073
+ // Check if close was triggered by overlay click (clicking outside)
5074
+ if (customEvent.detail?.source === 'overlay') {
5075
+ // Clicking outside the dialog - save and exit edit mode
5076
+ this.closeDialog(true);
5077
+ }
5078
+ else {
5079
+ // Clicking X button - stay in edit mode
5080
+ this.closeDialog(false);
5081
+ }
5082
+ });
5083
+ // Handle Escape key in dialog - stay in edit mode
5084
+ this.dialog.addEventListener('keydown', (e) => {
5085
+ if (e.key === 'Escape') {
5086
+ e.preventDefault();
5087
+ e.stopPropagation();
5088
+ this.closeDialog(false);
5089
+ }
5090
+ });
5091
+ // Append to body and show
5092
+ document.body.appendChild(this.dialog);
5093
+ // Open dialog after a tick to ensure it's in the DOM
5094
+ setTimeout(() => {
5095
+ if (this.dialog) {
5096
+ this.dialog.open = true;
5097
+ // Focus the dialog editor
5098
+ setTimeout(() => {
5099
+ this.dialogEditor?.focus();
5100
+ }, 100);
5101
+ }
5102
+ }, 0);
5103
+ }
5104
+ /**
5105
+ * Close the dialog and optionally save/exit edit mode
5106
+ */
5107
+ closeDialog(saveAndExit = false) {
5108
+ if (!this.dialogOpen)
5109
+ return;
5110
+ // Reset flag immediately so document click handler works
5111
+ this.dialogOpen = false;
5112
+ // Close and remove dialog
5113
+ if (this.dialog) {
5114
+ this.dialog.open = false;
5115
+ const dialogRef = this.dialog;
5116
+ const dialogEditorRef = this.dialogEditor;
5117
+ this.dialog = undefined;
5118
+ this.dialogEditor = undefined;
5119
+ // Remove from DOM after animation
5120
+ setTimeout(() => {
5121
+ dialogRef?.remove();
5122
+ }, 200);
5123
+ if (saveAndExit && this.context) {
5124
+ // Save and exit edit mode
5125
+ this.context.onSave(this.getCurrentValue());
5126
+ }
5127
+ else {
5128
+ // Refocus the cell editor to stay in edit mode
5129
+ setTimeout(() => {
5130
+ this.focusEditor();
5131
+ }, 50);
5132
+ }
5133
+ }
5134
+ }
5135
+ /**
5136
+ * Apply all configuration options to the NileCodeEditor element
5137
+ */
5138
+ applyOptions() {
5139
+ if (!this.editor)
5140
+ return;
5141
+ // Language and syntax
5142
+ if (this.options?.language) {
5143
+ this.editor.language = this.options.language;
5144
+ }
5145
+ if (this.options?.disableSyntaxHighlighting) {
5146
+ this.editor.disableSyntaxHighlighting = this.options.disableSyntaxHighlighting;
5147
+ }
5148
+ // Editor appearance
5149
+ if (this.options?.placeholder) {
5150
+ this.editor.placeholder = this.options.placeholder;
5151
+ }
5152
+ if (this.options?.lineNumbers !== undefined) {
5153
+ this.editor.lineNumbers = this.options.lineNumbers;
5154
+ }
5155
+ if (this.options?.lineNumbersMultiline !== undefined) {
5156
+ this.editor.lineNumbersMultiline = this.options.lineNumbersMultiline;
5157
+ }
5158
+ if (this.options?.multiline !== undefined) {
5159
+ this.editor.multiline = this.options.multiline;
5160
+ }
5161
+ if (this.options?.defaultFont !== undefined) {
5162
+ this.editor.defaultFont = this.options.defaultFont;
5163
+ }
5164
+ // Editor behavior
5165
+ if (this.options?.readonly !== undefined) {
5166
+ this.editor.readonly = this.options.readonly;
5167
+ }
5168
+ if (this.options?.disabled !== undefined) {
5169
+ this.editor.disabled = this.options.disabled;
5170
+ }
5171
+ if (this.options?.tabCompletion !== undefined) {
5172
+ this.editor.tabCompletion = this.options.tabCompletion;
5173
+ }
5174
+ if (this.options?.enableSearch !== undefined) {
5175
+ this.editor.enableSearch = this.options.enableSearch;
5176
+ }
5177
+ if (this.options?.enableFoldGutters !== undefined) {
5178
+ this.editor.enableFoldGutters = this.options.enableFoldGutters;
5179
+ }
5180
+ if (this.options?.hasScroller !== undefined) {
5181
+ this.editor.hasScroller = this.options.hasScroller;
5182
+ }
5183
+ // Expandable - default to false for cell editing
5184
+ this.editor.expandable = this.options?.expandable ?? false;
5185
+ if (this.options?.expandIcon) {
5186
+ this.editor.expandIcon = this.options.expandIcon;
5187
+ }
5188
+ // Autocompletion
5189
+ if (this.options?.customAutoCompletions) {
5190
+ this.editor.customAutoCompletions = this.options.customAutoCompletions;
5191
+ }
5192
+ if (this.options?.customCompletionsPaths) {
5193
+ this.editor.customCompletionsPaths = this.options.customCompletionsPaths;
5194
+ }
5195
+ if (this.options?.allowVariableInCustomSuggestion !== undefined) {
5196
+ this.editor.allowVariableInCustomSuggestion = this.options.allowVariableInCustomSuggestion;
5197
+ }
5198
+ if (this.options?.aboveCursor !== undefined) {
5199
+ this.editor.aboveCursor = this.options.aboveCursor;
5200
+ }
5201
+ if (this.options?.autoCompleteStyle) {
5202
+ this.editor.autoCompleteStyle = this.options.autoCompleteStyle;
5203
+ }
5204
+ // Change handling
5205
+ if (this.options?.debounce !== undefined) {
5206
+ this.editor.debounce = this.options.debounce;
5207
+ }
5208
+ if (this.options?.debounceTimeout !== undefined) {
5209
+ this.editor.debounceTimeout = this.options.debounceTimeout;
5210
+ }
5211
+ // Visual states
5212
+ if (this.options?.error !== undefined) {
5213
+ this.editor.error = this.options.error;
5214
+ }
5215
+ if (this.options?.errorMessage) {
5216
+ this.editor.errorMessage = this.options.errorMessage;
5217
+ }
5218
+ // Custom theme
5219
+ if (this.options?.customThemeCSS) {
5220
+ this.editor.customThemeCSS = this.options.customThemeCSS;
5221
+ }
5222
+ }
5223
+ /**
5224
+ * Set up all event listeners with proper cleanup tracking
5225
+ */
5226
+ setupEventListeners(context) {
5227
+ if (!this.editor)
5228
+ return;
5229
+ const validateOnSave = this.options?.validateOnSave !== false;
5230
+ // Handle keyboard events
5231
+ const keydownHandler = (e) => {
5232
+ const keyEvent = e;
5233
+ // For single-line mode, Enter saves
5234
+ if (!this.options?.multiline && keyEvent.key === 'Enter') {
5235
+ keyEvent.preventDefault();
5236
+ keyEvent.stopPropagation();
5237
+ this.saveValue(context, validateOnSave);
5238
+ }
5239
+ // Escape cancels
5240
+ if (keyEvent.key === 'Escape') {
5241
+ keyEvent.preventDefault();
5242
+ keyEvent.stopPropagation();
5243
+ context.onCancel();
5244
+ }
5245
+ };
5246
+ this.editor.addEventListener('keydown', keydownHandler);
5247
+ this.eventListeners.push({ event: 'keydown', handler: keydownHandler });
5248
+ // Use nile-blur event for saving on blur
5249
+ const blurHandler = () => {
5250
+ // Don't save if dialog is open
5251
+ if (this.dialogOpen) {
5252
+ return;
5253
+ }
5254
+ // Don't save if expand button was clicked (mousedown sets this flag)
5255
+ if (this.expandButtonClicked) {
5256
+ // Reset flag - the click handler will open the dialog
5257
+ this.expandButtonClicked = false;
5258
+ return;
5259
+ }
5260
+ // Save and exit edit mode
5261
+ this.saveValue(context, validateOnSave);
5262
+ };
5263
+ this.editor.addEventListener('nile-blur', blurHandler);
5264
+ this.eventListeners.push({ event: 'nile-blur', handler: blurHandler });
5265
+ // Document-level mousedown handler to detect clicks outside the editor
5266
+ this.documentClickHandler = (e) => {
5267
+ // Don't process if dialog is open or expand button was clicked
5268
+ if (this.dialogOpen || this.expandButtonClicked) {
5269
+ return;
5270
+ }
5271
+ // Use composedPath to handle Shadow DOM boundaries
5272
+ const path = e.composedPath();
5273
+ // Check if any element in the path is our wrapper, editor, or expand button
5274
+ for (const element of path) {
5275
+ if (element === this.wrapper || element === this.editor || element === this.expandButton) {
5276
+ return;
5277
+ }
5278
+ // Also check if it's the container (the cell)
5279
+ if (element === context.container) {
5280
+ return;
5281
+ }
5282
+ }
5283
+ // Click is outside - save and exit
5284
+ this.saveValue(context, validateOnSave);
5285
+ };
5286
+ // Add with a small delay to avoid capturing the initial click that opened the editor
5287
+ setTimeout(() => {
5288
+ document.addEventListener('mousedown', this.documentClickHandler, true);
5289
+ }, 50);
5290
+ // Real-time value updates using nile-change
5291
+ const changeHandler = (e) => {
5292
+ const customEvent = e;
5293
+ const newValue = customEvent.detail?.value ?? '';
5294
+ this.trackedValue = newValue;
5295
+ context.onChange(newValue);
5296
+ };
5297
+ this.editor.addEventListener('nile-change', changeHandler);
5298
+ this.eventListeners.push({ event: 'nile-change', handler: changeHandler });
5299
+ // Handle expand event if expandable
5300
+ if (this.options?.expandable) {
5301
+ const expandHandler = () => {
5302
+ // Emit a custom event that the parent can listen to
5303
+ const expandEvent = new CustomEvent('st-code-editor-expand', {
5304
+ bubbles: true,
5305
+ detail: { value: this.getCurrentValue() }
5306
+ });
5307
+ this.editor?.dispatchEvent(expandEvent);
5308
+ };
5309
+ this.editor.addEventListener('nile-expand', expandHandler);
5310
+ this.eventListeners.push({ event: 'nile-expand', handler: expandHandler });
5311
+ }
5312
+ }
5313
+ /**
5314
+ * Save value with optional validation
5315
+ */
5316
+ saveValue(context, validate) {
5317
+ if (!this.editor)
5318
+ return;
5319
+ // Code editor doesn't have built-in validation like input
5320
+ // But we can check for error state
5321
+ if (validate && this.options?.error) {
5322
+ return;
5323
+ }
5324
+ const value = this.getCurrentValue();
5325
+ context.onSave(value);
5326
+ }
5327
+ destroy() {
5328
+ // Remove document click handler
5329
+ if (this.documentClickHandler) {
5330
+ document.removeEventListener('mousedown', this.documentClickHandler, true);
5331
+ this.documentClickHandler = undefined;
5332
+ }
5333
+ // Close dialog if open
5334
+ if (this.dialogOpen && this.dialog) {
5335
+ this.dialog.open = false;
5336
+ this.dialog.remove();
5337
+ this.dialog = undefined;
5338
+ this.dialogEditor = undefined;
5339
+ this.dialogOpen = false;
5340
+ }
5341
+ // Remove all event listeners
5342
+ if (this.editor) {
5343
+ this.eventListeners.forEach(({ event, handler }) => {
5344
+ this.editor?.removeEventListener(event, handler);
5345
+ });
5346
+ this.eventListeners = [];
5347
+ this.editor.remove();
5348
+ this.editor = undefined;
5349
+ }
5350
+ // Remove wrapper if exists
5351
+ if (this.wrapper) {
5352
+ this.wrapper.remove();
5353
+ this.wrapper = undefined;
5354
+ }
5355
+ // Clear expand button reference
5356
+ this.expandButton = undefined;
5357
+ this.context = undefined;
5358
+ this.expandButtonClicked = false;
5359
+ }
5360
+ focus() {
5361
+ this.editor?.focus();
5362
+ }
5363
+ getCurrentValue() {
5364
+ if (!this.editor)
5365
+ return '';
5366
+ const value = (this.trackedValue !== null ? this.trackedValue : this.editor.value ?? '');
5367
+ return value.replace(/\n+$/, '');
5368
+ }
5369
+ /**
5370
+ * Set value programmatically
5371
+ */
5372
+ setValue(value) {
5373
+ if (this.editor) {
5374
+ this.editor.value = String(value ?? '');
5375
+ }
5376
+ }
5377
+ /**
5378
+ * Get the CodeMirror instance (if needed for advanced usage)
5379
+ */
5380
+ getEditorInstance() {
5381
+ return this.editor;
5382
+ }
5383
+ }
5384
+
4727
5385
  /**
4728
5386
  * Custom cell editors for ngx-smart-table
4729
5387
  */
@@ -4953,15 +5611,28 @@ class ColumnConfigFactory {
4953
5611
  const Columns = ColumnConfigFactory;
4954
5612
 
4955
5613
  class StCellComponent {
4956
- constructor() {
5614
+ constructor(cdr) {
5615
+ this.cdr = cdr;
4957
5616
  this.editMode = EditMode.CLICK;
4958
5617
  this.cellChange = new EventEmitter();
4959
5618
  this.cellEdit = new EventEmitter();
4960
5619
  this.cellSave = new EventEmitter();
4961
5620
  this.cellCancel = new EventEmitter();
4962
5621
  this.cellSaveAndNavigate = new EventEmitter();
5622
+ this.cellLoading = false;
4963
5623
  }
4964
5624
  ngOnInit() {
5625
+ this.cell.onStateChange(() => {
5626
+ this.cellLoading = !!this.cell.getState().isLoading;
5627
+ try {
5628
+ this.cdr.detectChanges();
5629
+ }
5630
+ catch {
5631
+ // View may have been destroyed; safely ignore
5632
+ }
5633
+ });
5634
+ // Pick up loading state that was set before this component was created
5635
+ this.cellLoading = !!this.cell.getState().isLoading;
4965
5636
  // Subscribe to editing position changes
4966
5637
  // When another cell starts editing, save this cell if it's currently editing
4967
5638
  if (this.tableState && this.columnIndex !== undefined) {
@@ -5312,12 +5983,12 @@ class StCellComponent {
5312
5983
  }
5313
5984
  }
5314
5985
  }
5315
- StCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5316
- StCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StCellComponent, selector: "st-cell", inputs: { cell: "cell", editMode: "editMode", tableState: "tableState", tableConfig: "tableConfig", columnIndex: "columnIndex" }, outputs: { cellChange: "cellChange", cellEdit: "cellEdit", cellSave: "cellSave", cellCancel: "cellCancel", cellSaveAndNavigate: "cellSaveAndNavigate" }, host: { listeners: { "keydown": "onCellKeyDown($event)" } }, viewQueries: [{ propertyName: "editorContainer", first: true, predicate: ["editorContainer"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"st-cell\" \n [ngClass]=\"{\n 'editing': cell.isEditing(),\n 'dirty': cell.isDirty(),\n 'invalid': !cell.isValid(),\n 'readonly': !isEditable\n }\"\n (click)=\"onCellClick()\" \n (dblclick)=\"onCellDoubleClick()\">\n\n <!-- Display Mode with Template Support -->\n <ng-container *ngIf=\"!cell.isEditing()\">\n <!-- Custom Template -->\n <ng-container *ngIf=\"hasCellTemplate\">\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: templateContext\"></ng-container>\n </ng-container>\n\n <!-- Default Text Rendering -->\n <span *ngIf=\"!hasCellTemplate\" class=\"cell-display\">\n {{ cell.render() }}\n </span>\n </ng-container>\n\n <!-- Edit Mode -->\n <div *ngIf=\"cell.isEditing()\" class=\"cell-editor\" #editorContainer>\n </div>\n</div>", styles: [".st-cell{position:relative;cursor:pointer;transition:background-color .2s;min-height:28px;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;box-sizing:border-box}.st-cell.invalid{border-left:2px solid #e53e3e}.st-cell.readonly{cursor:default}.cell-display{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;align-content:center;width:100%;height:100%;padding-left:8px;padding-right:8px;font-size:12px;font-weight:300;letter-spacing:.2px;line-height:14px}.cell-editor{display:flex;height:100%;width:100%}.cell-editor input,.cell-editor select,.cell-editor textarea{width:100%;border:none;outline:none;font:inherit;padding:0;background:transparent;color:inherit}.cell-editor input[type=number]{text-align:inherit}.cell-editor nile-select::part(combobox){border:none!important;outline:none!important;box-shadow:none!important}.cell-editor nile-select::part(tag){border:none!important;outline:none!important}.cell-editor nile-select::part(listbox){border:none!important}.cell-error{position:absolute;right:4px;top:50%;transform:translateY(-50%);color:#e53e3e;font-weight:700;cursor:help;font-size:14px}\n"], directives: [{ type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
5986
+ StCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StCellComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
5987
+ StCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StCellComponent, selector: "st-cell", inputs: { cell: "cell", editMode: "editMode", tableState: "tableState", tableConfig: "tableConfig", columnIndex: "columnIndex" }, outputs: { cellChange: "cellChange", cellEdit: "cellEdit", cellSave: "cellSave", cellCancel: "cellCancel", cellSaveAndNavigate: "cellSaveAndNavigate" }, host: { listeners: { "keydown": "onCellKeyDown($event)" } }, viewQueries: [{ propertyName: "editorContainer", first: true, predicate: ["editorContainer"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"st-cell\" \n [ngClass]=\"{\n 'editing': cell.isEditing(),\n 'dirty': cell.isDirty(),\n 'invalid': !cell.isValid(),\n 'readonly': !isEditable,\n 'loading': cellLoading\n }\"\n (click)=\"onCellClick()\" \n (dblclick)=\"onCellDoubleClick()\">\n\n <!-- Loading Indicator -->\n <div *ngIf=\"cellLoading\" class=\"cell-loading\">\n <div class=\"cell-spinner\"></div>\n </div>\n\n <!-- Display Mode with Template Support -->\n <ng-container *ngIf=\"!cell.isEditing() && !cellLoading\">\n <!-- Custom Template -->\n <ng-container *ngIf=\"hasCellTemplate\">\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: templateContext\"></ng-container>\n </ng-container>\n\n <!-- Default Text Rendering -->\n <span *ngIf=\"!hasCellTemplate\" class=\"cell-display\">\n {{ cell.render() }}\n </span>\n </ng-container>\n\n <!-- Edit Mode -->\n <div *ngIf=\"cell.isEditing()\" class=\"cell-editor\" #editorContainer>\n </div>\n</div>", styles: [".st-cell{position:relative;cursor:pointer;transition:background-color .2s;min-height:28px;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;box-sizing:border-box;max-height:28px}.st-cell.invalid{border-left:2px solid #e53e3e}.st-cell.readonly{cursor:default}.cell-display{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;align-content:center;width:100%;height:100%;padding-left:8px;padding-right:8px;font-size:12px;font-weight:300;letter-spacing:.2px;line-height:14px}.cell-editor{display:flex;height:100%;width:100%}.cell-editor input,.cell-editor select,.cell-editor textarea{width:100%;border:none;outline:none;font:inherit;padding:0;background:transparent;color:inherit}.cell-editor input[type=number]{text-align:inherit}.cell-editor nile-select::part(combobox){border:none!important;outline:none!important;box-shadow:none!important;max-height:28px;overflow:hidden;flex-wrap:nowrap}.cell-editor nile-select::part(tag){border:none!important;outline:none!important;margin-right:2px;padding:1px 2px;flex-shrink:0}.cell-editor nile-select::part(listbox){border:none!important}.st-cell.loading{pointer-events:none;opacity:.6}.cell-loading{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.cell-spinner{width:14px;height:14px;border:2px solid #e2e8f0;border-top-color:#4a90d9;border-radius:50%;animation:cell-spin .6s linear infinite}@keyframes cell-spin{to{transform:rotate(360deg)}}.cell-error{position:absolute;right:4px;top:50%;transform:translateY(-50%);color:#e53e3e;font-weight:700;cursor:help;font-size:14px}\n"], directives: [{ type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
5317
5988
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StCellComponent, decorators: [{
5318
5989
  type: Component,
5319
- args: [{ selector: 'st-cell', template: "<div class=\"st-cell\" \n [ngClass]=\"{\n 'editing': cell.isEditing(),\n 'dirty': cell.isDirty(),\n 'invalid': !cell.isValid(),\n 'readonly': !isEditable\n }\"\n (click)=\"onCellClick()\" \n (dblclick)=\"onCellDoubleClick()\">\n\n <!-- Display Mode with Template Support -->\n <ng-container *ngIf=\"!cell.isEditing()\">\n <!-- Custom Template -->\n <ng-container *ngIf=\"hasCellTemplate\">\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: templateContext\"></ng-container>\n </ng-container>\n\n <!-- Default Text Rendering -->\n <span *ngIf=\"!hasCellTemplate\" class=\"cell-display\">\n {{ cell.render() }}\n </span>\n </ng-container>\n\n <!-- Edit Mode -->\n <div *ngIf=\"cell.isEditing()\" class=\"cell-editor\" #editorContainer>\n </div>\n</div>", styles: [".st-cell{position:relative;cursor:pointer;transition:background-color .2s;min-height:28px;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;box-sizing:border-box}.st-cell.invalid{border-left:2px solid #e53e3e}.st-cell.readonly{cursor:default}.cell-display{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;align-content:center;width:100%;height:100%;padding-left:8px;padding-right:8px;font-size:12px;font-weight:300;letter-spacing:.2px;line-height:14px}.cell-editor{display:flex;height:100%;width:100%}.cell-editor input,.cell-editor select,.cell-editor textarea{width:100%;border:none;outline:none;font:inherit;padding:0;background:transparent;color:inherit}.cell-editor input[type=number]{text-align:inherit}.cell-editor nile-select::part(combobox){border:none!important;outline:none!important;box-shadow:none!important}.cell-editor nile-select::part(tag){border:none!important;outline:none!important}.cell-editor nile-select::part(listbox){border:none!important}.cell-error{position:absolute;right:4px;top:50%;transform:translateY(-50%);color:#e53e3e;font-weight:700;cursor:help;font-size:14px}\n"] }]
5320
- }], ctorParameters: function () { return []; }, propDecorators: { cell: [{
5990
+ args: [{ selector: 'st-cell', template: "<div class=\"st-cell\" \n [ngClass]=\"{\n 'editing': cell.isEditing(),\n 'dirty': cell.isDirty(),\n 'invalid': !cell.isValid(),\n 'readonly': !isEditable,\n 'loading': cellLoading\n }\"\n (click)=\"onCellClick()\" \n (dblclick)=\"onCellDoubleClick()\">\n\n <!-- Loading Indicator -->\n <div *ngIf=\"cellLoading\" class=\"cell-loading\">\n <div class=\"cell-spinner\"></div>\n </div>\n\n <!-- Display Mode with Template Support -->\n <ng-container *ngIf=\"!cell.isEditing() && !cellLoading\">\n <!-- Custom Template -->\n <ng-container *ngIf=\"hasCellTemplate\">\n <ng-container *ngTemplateOutlet=\"cellTemplate; context: templateContext\"></ng-container>\n </ng-container>\n\n <!-- Default Text Rendering -->\n <span *ngIf=\"!hasCellTemplate\" class=\"cell-display\">\n {{ cell.render() }}\n </span>\n </ng-container>\n\n <!-- Edit Mode -->\n <div *ngIf=\"cell.isEditing()\" class=\"cell-editor\" #editorContainer>\n </div>\n</div>", styles: [".st-cell{position:relative;cursor:pointer;transition:background-color .2s;min-height:28px;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;box-sizing:border-box;max-height:28px}.st-cell.invalid{border-left:2px solid #e53e3e}.st-cell.readonly{cursor:default}.cell-display{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;align-content:center;width:100%;height:100%;padding-left:8px;padding-right:8px;font-size:12px;font-weight:300;letter-spacing:.2px;line-height:14px}.cell-editor{display:flex;height:100%;width:100%}.cell-editor input,.cell-editor select,.cell-editor textarea{width:100%;border:none;outline:none;font:inherit;padding:0;background:transparent;color:inherit}.cell-editor input[type=number]{text-align:inherit}.cell-editor nile-select::part(combobox){border:none!important;outline:none!important;box-shadow:none!important;max-height:28px;overflow:hidden;flex-wrap:nowrap}.cell-editor nile-select::part(tag){border:none!important;outline:none!important;margin-right:2px;padding:1px 2px;flex-shrink:0}.cell-editor nile-select::part(listbox){border:none!important}.st-cell.loading{pointer-events:none;opacity:.6}.cell-loading{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.cell-spinner{width:14px;height:14px;border:2px solid #e2e8f0;border-top-color:#4a90d9;border-radius:50%;animation:cell-spin .6s linear infinite}@keyframes cell-spin{to{transform:rotate(360deg)}}.cell-error{position:absolute;right:4px;top:50%;transform:translateY(-50%);color:#e53e3e;font-weight:700;cursor:help;font-size:14px}\n"] }]
5991
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { cell: [{
5321
5992
  type: Input
5322
5993
  }], editMode: [{
5323
5994
  type: Input
@@ -7991,7 +8662,20 @@ class StTableComponent {
7991
8662
  if (!this.data)
7992
8663
  return;
7993
8664
  const columns = this.getActiveColumns();
7994
- this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map(column => new Cell(column, rowData[column.key], rowData, rowIndex)));
8665
+ const oldGrid = this.internalCellGrid;
8666
+ this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map((column, colIndex) => {
8667
+ const newCell = new Cell(column, rowData[column.key], rowData, rowIndex);
8668
+ const oldCell = oldGrid?.[rowIndex]?.[colIndex];
8669
+ if (oldCell && oldCell.getColumnConfig().key === column.key) {
8670
+ oldCell.setReplacement(newCell);
8671
+ // Carry over transient state (e.g. loading) that was set on the old cell
8672
+ const oldState = oldCell.getState();
8673
+ if (oldState.isLoading) {
8674
+ newCell.setLoading(true);
8675
+ }
8676
+ }
8677
+ return newCell;
8678
+ }));
7995
8679
  }
7996
8680
  /**
7997
8681
  * Setup data source - either sync array or async Observable
@@ -12377,5 +13061,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
12377
13061
  * Generated bundle index. Do not edit.
12378
13062
  */
12379
13063
 
12380
- 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, NileDatePickerEditor, NileInputEditor, NileSelectEditor, NumberEditor, NumberFormatter, 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, isCellValid, isDisplayMode, isNullOrUndefined, isValidDate, isValidationSuccess, mergeTableConfig, restoreFromMemento };
13064
+ 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, 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, isCellValid, isDisplayMode, isNullOrUndefined, isValidDate, isValidationSuccess, mergeTableConfig, restoreFromMemento };
12381
13065
  //# sourceMappingURL=aquera-ngx-smart-table.mjs.map