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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,648 @@ 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
+ * Read the live value directly from CodeMirror's internal state,
4995
+ * bypassing debounced nile-change events and the possibly-stale .value property.
4996
+ */
4997
+ getLiveEditorValue() {
4998
+ if (!this.editor)
4999
+ return '';
5000
+ try {
5001
+ const shadowRoot = this.editor.shadowRoot;
5002
+ if (shadowRoot) {
5003
+ const cmEditor = shadowRoot.querySelector('.cm-editor');
5004
+ if (cmEditor?.cmView?.view) {
5005
+ return cmEditor.cmView.view.state.doc.toString();
5006
+ }
5007
+ }
5008
+ }
5009
+ catch {
5010
+ // Fall through to other methods
5011
+ }
5012
+ if (this.trackedValue !== null)
5013
+ return this.trackedValue;
5014
+ return this.editor.value ?? '';
5015
+ }
5016
+ /**
5017
+ * Open the full editor dialog
5018
+ */
5019
+ openDialog() {
5020
+ if (this.dialogOpen)
5021
+ return;
5022
+ this.dialogOpen = true;
5023
+ this.expandButtonClicked = false; // Reset flag now that dialog is opening
5024
+ // Create dialog with configurable dimensions
5025
+ const dialogWidth = this.options?.dialogWidth || '600px';
5026
+ const dialogMaxHeight = this.options?.dialogMaxHeight || '80vh';
5027
+ const dialogEditorHeight = this.options?.dialogEditorHeight || '300px';
5028
+ const dialogTitle = this.options?.dialogTitle || 'Edit Code';
5029
+ this.dialog = document.createElement('nile-dialog');
5030
+ this.dialog.className = 'st-code-editor-dialog';
5031
+ this.dialog.label = dialogTitle;
5032
+ this.dialog.style.setProperty('--width', dialogWidth);
5033
+ this.dialog.style.setProperty('--max-height', dialogMaxHeight);
5034
+ // Create dialog content
5035
+ const content = document.createElement('div');
5036
+ content.style.padding = '16px';
5037
+ content.style.maxHeight = `calc(${dialogMaxHeight} - 80px)`;
5038
+ content.style.overflow = 'auto';
5039
+ // Create full editor
5040
+ this.dialogEditor = document.createElement('nile-code-editor');
5041
+ const minLines = this.options?.dialogMinLines ?? 20;
5042
+ const currentValue = this.getLiveEditorValue();
5043
+ const currentLineCount = (currentValue.match(/\n/g) || []).length + 1;
5044
+ const paddingLines = Math.max(0, minLines - currentLineCount);
5045
+ this.dialogEditor.value = currentValue + '\n'.repeat(paddingLines);
5046
+ this.dialogEditor.multiline = true;
5047
+ this.dialogEditor.lineNumbersMultiline = true;
5048
+ this.dialogEditor.hasScroller = true;
5049
+ const lineHeightPx = 20;
5050
+ const minHeightFromLines = `${minLines * lineHeightPx}px`;
5051
+ this.dialogEditor.style.minHeight = `max(${dialogEditorHeight}, ${minHeightFromLines})`;
5052
+ this.dialogEditor.style.maxHeight = `calc(${dialogMaxHeight} - 120px)`;
5053
+ content.style.setProperty('--dialog-editor-min-height', `max(${dialogEditorHeight}, ${minHeightFromLines})`);
5054
+ // Apply same options to dialog editor
5055
+ if (this.options?.language) {
5056
+ this.dialogEditor.language = this.options.language;
5057
+ }
5058
+ if (this.options?.placeholder) {
5059
+ this.dialogEditor.placeholder = this.options.placeholder;
5060
+ }
5061
+ if (this.options?.tabCompletion !== undefined) {
5062
+ this.dialogEditor.tabCompletion = this.options.tabCompletion;
5063
+ }
5064
+ if (this.options?.enableSearch !== undefined) {
5065
+ this.dialogEditor.enableSearch = this.options.enableSearch;
5066
+ }
5067
+ if (this.options?.enableFoldGutters !== undefined) {
5068
+ this.dialogEditor.enableFoldGutters = this.options.enableFoldGutters;
5069
+ }
5070
+ if (this.options?.customAutoCompletions) {
5071
+ this.dialogEditor.customAutoCompletions = this.options.customAutoCompletions;
5072
+ }
5073
+ if (this.options?.customCompletionsPaths) {
5074
+ this.dialogEditor.customCompletionsPaths = this.options.customCompletionsPaths;
5075
+ }
5076
+ if (this.options?.customThemeCSS) {
5077
+ this.dialogEditor.customThemeCSS = this.options.customThemeCSS;
5078
+ }
5079
+ this.dialogEditor.expandable = false;
5080
+ // Real-time sync: Update cell editor whenever dialog editor changes
5081
+ this.dialogEditor.addEventListener('nile-change', (e) => {
5082
+ const dialogValue = e.detail?.value || '';
5083
+ this.trackedValue = dialogValue;
5084
+ if (this.editor) {
5085
+ this.editor.value = dialogValue;
5086
+ }
5087
+ if (this.context) {
5088
+ this.context.onChange(dialogValue);
5089
+ }
5090
+ });
5091
+ content.appendChild(this.dialogEditor);
5092
+ this.dialog.appendChild(content);
5093
+ // Handle dialog close events (clicking X button - stay in edit mode)
5094
+ this.dialog.addEventListener('nile-request-close', (e) => {
5095
+ const customEvent = e;
5096
+ // Check if close was triggered by overlay click (clicking outside)
5097
+ if (customEvent.detail?.source === 'overlay') {
5098
+ // Clicking outside the dialog - save and exit edit mode
5099
+ this.closeDialog(true);
5100
+ }
5101
+ else {
5102
+ // Clicking X button - stay in edit mode
5103
+ this.closeDialog(false);
5104
+ }
5105
+ });
5106
+ // Handle Escape key in dialog - stay in edit mode
5107
+ this.dialog.addEventListener('keydown', (e) => {
5108
+ if (e.key === 'Escape') {
5109
+ e.preventDefault();
5110
+ e.stopPropagation();
5111
+ this.closeDialog(false);
5112
+ }
5113
+ });
5114
+ // Append to body and show
5115
+ document.body.appendChild(this.dialog);
5116
+ // Open dialog after a tick to ensure it's in the DOM
5117
+ setTimeout(() => {
5118
+ if (this.dialog) {
5119
+ this.dialog.open = true;
5120
+ // Focus the dialog editor
5121
+ setTimeout(() => {
5122
+ this.dialogEditor?.focus();
5123
+ }, 100);
5124
+ }
5125
+ }, 0);
5126
+ }
5127
+ /**
5128
+ * Close the dialog and optionally save/exit edit mode
5129
+ */
5130
+ closeDialog(saveAndExit = false) {
5131
+ if (!this.dialogOpen)
5132
+ return;
5133
+ // Reset flag immediately so document click handler works
5134
+ this.dialogOpen = false;
5135
+ // Close and remove dialog
5136
+ if (this.dialog) {
5137
+ this.dialog.open = false;
5138
+ const dialogRef = this.dialog;
5139
+ const dialogEditorRef = this.dialogEditor;
5140
+ this.dialog = undefined;
5141
+ this.dialogEditor = undefined;
5142
+ // Remove from DOM after animation
5143
+ setTimeout(() => {
5144
+ dialogRef?.remove();
5145
+ }, 200);
5146
+ if (saveAndExit && this.context) {
5147
+ // Save and exit edit mode
5148
+ this.context.onSave(this.getCurrentValue());
5149
+ }
5150
+ else {
5151
+ // Refocus the cell editor to stay in edit mode
5152
+ setTimeout(() => {
5153
+ this.focusEditor();
5154
+ }, 50);
5155
+ }
5156
+ }
5157
+ }
5158
+ /**
5159
+ * Apply all configuration options to the NileCodeEditor element
5160
+ */
5161
+ applyOptions() {
5162
+ if (!this.editor)
5163
+ return;
5164
+ // Language and syntax
5165
+ if (this.options?.language) {
5166
+ this.editor.language = this.options.language;
5167
+ }
5168
+ if (this.options?.disableSyntaxHighlighting) {
5169
+ this.editor.disableSyntaxHighlighting = this.options.disableSyntaxHighlighting;
5170
+ }
5171
+ // Editor appearance
5172
+ if (this.options?.placeholder) {
5173
+ this.editor.placeholder = this.options.placeholder;
5174
+ }
5175
+ if (this.options?.lineNumbers !== undefined) {
5176
+ this.editor.lineNumbers = this.options.lineNumbers;
5177
+ }
5178
+ if (this.options?.lineNumbersMultiline !== undefined) {
5179
+ this.editor.lineNumbersMultiline = this.options.lineNumbersMultiline;
5180
+ }
5181
+ if (this.options?.multiline !== undefined) {
5182
+ this.editor.multiline = this.options.multiline;
5183
+ }
5184
+ if (this.options?.defaultFont !== undefined) {
5185
+ this.editor.defaultFont = this.options.defaultFont;
5186
+ }
5187
+ // Editor behavior
5188
+ if (this.options?.readonly !== undefined) {
5189
+ this.editor.readonly = this.options.readonly;
5190
+ }
5191
+ if (this.options?.disabled !== undefined) {
5192
+ this.editor.disabled = this.options.disabled;
5193
+ }
5194
+ if (this.options?.tabCompletion !== undefined) {
5195
+ this.editor.tabCompletion = this.options.tabCompletion;
5196
+ }
5197
+ if (this.options?.enableSearch !== undefined) {
5198
+ this.editor.enableSearch = this.options.enableSearch;
5199
+ }
5200
+ if (this.options?.enableFoldGutters !== undefined) {
5201
+ this.editor.enableFoldGutters = this.options.enableFoldGutters;
5202
+ }
5203
+ if (this.options?.hasScroller !== undefined) {
5204
+ this.editor.hasScroller = this.options.hasScroller;
5205
+ }
5206
+ // Expandable - default to false for cell editing
5207
+ this.editor.expandable = this.options?.expandable ?? false;
5208
+ if (this.options?.expandIcon) {
5209
+ this.editor.expandIcon = this.options.expandIcon;
5210
+ }
5211
+ // Autocompletion
5212
+ if (this.options?.customAutoCompletions) {
5213
+ this.editor.customAutoCompletions = this.options.customAutoCompletions;
5214
+ }
5215
+ if (this.options?.customCompletionsPaths) {
5216
+ this.editor.customCompletionsPaths = this.options.customCompletionsPaths;
5217
+ }
5218
+ if (this.options?.allowVariableInCustomSuggestion !== undefined) {
5219
+ this.editor.allowVariableInCustomSuggestion = this.options.allowVariableInCustomSuggestion;
5220
+ }
5221
+ if (this.options?.aboveCursor !== undefined) {
5222
+ this.editor.aboveCursor = this.options.aboveCursor;
5223
+ }
5224
+ if (this.options?.autoCompleteStyle) {
5225
+ this.editor.autoCompleteStyle = this.options.autoCompleteStyle;
5226
+ }
5227
+ // Change handling
5228
+ if (this.options?.debounce !== undefined) {
5229
+ this.editor.debounce = this.options.debounce;
5230
+ }
5231
+ if (this.options?.debounceTimeout !== undefined) {
5232
+ this.editor.debounceTimeout = this.options.debounceTimeout;
5233
+ }
5234
+ // Visual states
5235
+ if (this.options?.error !== undefined) {
5236
+ this.editor.error = this.options.error;
5237
+ }
5238
+ if (this.options?.errorMessage) {
5239
+ this.editor.errorMessage = this.options.errorMessage;
5240
+ }
5241
+ // Custom theme
5242
+ if (this.options?.customThemeCSS) {
5243
+ this.editor.customThemeCSS = this.options.customThemeCSS;
5244
+ }
5245
+ }
5246
+ /**
5247
+ * Set up all event listeners with proper cleanup tracking
5248
+ */
5249
+ setupEventListeners(context) {
5250
+ if (!this.editor)
5251
+ return;
5252
+ const validateOnSave = this.options?.validateOnSave !== false;
5253
+ // Handle keyboard events
5254
+ const keydownHandler = (e) => {
5255
+ const keyEvent = e;
5256
+ // For single-line mode, Enter saves
5257
+ if (!this.options?.multiline && keyEvent.key === 'Enter') {
5258
+ keyEvent.preventDefault();
5259
+ keyEvent.stopPropagation();
5260
+ this.saveValue(context, validateOnSave);
5261
+ }
5262
+ // Escape cancels
5263
+ if (keyEvent.key === 'Escape') {
5264
+ keyEvent.preventDefault();
5265
+ keyEvent.stopPropagation();
5266
+ context.onCancel();
5267
+ }
5268
+ };
5269
+ this.editor.addEventListener('keydown', keydownHandler);
5270
+ this.eventListeners.push({ event: 'keydown', handler: keydownHandler });
5271
+ // Use nile-blur event for saving on blur
5272
+ const blurHandler = () => {
5273
+ // Don't save if dialog is open
5274
+ if (this.dialogOpen) {
5275
+ return;
5276
+ }
5277
+ // Don't save if expand button was clicked (mousedown sets this flag)
5278
+ if (this.expandButtonClicked) {
5279
+ // Reset flag - the click handler will open the dialog
5280
+ this.expandButtonClicked = false;
5281
+ return;
5282
+ }
5283
+ // Save and exit edit mode
5284
+ this.saveValue(context, validateOnSave);
5285
+ };
5286
+ this.editor.addEventListener('nile-blur', blurHandler);
5287
+ this.eventListeners.push({ event: 'nile-blur', handler: blurHandler });
5288
+ // Document-level mousedown handler to detect clicks outside the editor
5289
+ this.documentClickHandler = (e) => {
5290
+ // Don't process if dialog is open or expand button was clicked
5291
+ if (this.dialogOpen || this.expandButtonClicked) {
5292
+ return;
5293
+ }
5294
+ // Use composedPath to handle Shadow DOM boundaries
5295
+ const path = e.composedPath();
5296
+ // Check if any element in the path is our wrapper, editor, or expand button
5297
+ for (const element of path) {
5298
+ if (element === this.wrapper || element === this.editor || element === this.expandButton) {
5299
+ return;
5300
+ }
5301
+ // Also check if it's the container (the cell)
5302
+ if (element === context.container) {
5303
+ return;
5304
+ }
5305
+ }
5306
+ // Click is outside - save and exit
5307
+ this.saveValue(context, validateOnSave);
5308
+ };
5309
+ // Add with a small delay to avoid capturing the initial click that opened the editor
5310
+ setTimeout(() => {
5311
+ document.addEventListener('mousedown', this.documentClickHandler, true);
5312
+ }, 50);
5313
+ // Real-time value updates using nile-change
5314
+ const changeHandler = (e) => {
5315
+ const customEvent = e;
5316
+ const newValue = customEvent.detail?.value ?? '';
5317
+ this.trackedValue = newValue;
5318
+ context.onChange(newValue);
5319
+ };
5320
+ this.editor.addEventListener('nile-change', changeHandler);
5321
+ this.eventListeners.push({ event: 'nile-change', handler: changeHandler });
5322
+ // Handle expand event if expandable
5323
+ if (this.options?.expandable) {
5324
+ const expandHandler = () => {
5325
+ // Emit a custom event that the parent can listen to
5326
+ const expandEvent = new CustomEvent('st-code-editor-expand', {
5327
+ bubbles: true,
5328
+ detail: { value: this.getCurrentValue() }
5329
+ });
5330
+ this.editor?.dispatchEvent(expandEvent);
5331
+ };
5332
+ this.editor.addEventListener('nile-expand', expandHandler);
5333
+ this.eventListeners.push({ event: 'nile-expand', handler: expandHandler });
5334
+ }
5335
+ }
5336
+ /**
5337
+ * Save value with optional validation
5338
+ */
5339
+ saveValue(context, validate) {
5340
+ if (!this.editor)
5341
+ return;
5342
+ // Code editor doesn't have built-in validation like input
5343
+ // But we can check for error state
5344
+ if (validate && this.options?.error) {
5345
+ return;
5346
+ }
5347
+ const value = this.getCurrentValue();
5348
+ context.onSave(value);
5349
+ }
5350
+ destroy() {
5351
+ // Remove document click handler
5352
+ if (this.documentClickHandler) {
5353
+ document.removeEventListener('mousedown', this.documentClickHandler, true);
5354
+ this.documentClickHandler = undefined;
5355
+ }
5356
+ // Close dialog if open
5357
+ if (this.dialogOpen && this.dialog) {
5358
+ this.dialog.open = false;
5359
+ this.dialog.remove();
5360
+ this.dialog = undefined;
5361
+ this.dialogEditor = undefined;
5362
+ this.dialogOpen = false;
5363
+ }
5364
+ // Remove all event listeners
5365
+ if (this.editor) {
5366
+ this.eventListeners.forEach(({ event, handler }) => {
5367
+ this.editor?.removeEventListener(event, handler);
5368
+ });
5369
+ this.eventListeners = [];
5370
+ this.editor.remove();
5371
+ this.editor = undefined;
5372
+ }
5373
+ // Remove wrapper if exists
5374
+ if (this.wrapper) {
5375
+ this.wrapper.remove();
5376
+ this.wrapper = undefined;
5377
+ }
5378
+ // Clear expand button reference
5379
+ this.expandButton = undefined;
5380
+ this.context = undefined;
5381
+ this.expandButtonClicked = false;
5382
+ }
5383
+ focus() {
5384
+ this.editor?.focus();
5385
+ }
5386
+ getCurrentValue() {
5387
+ if (!this.editor)
5388
+ return '';
5389
+ const value = this.getLiveEditorValue();
5390
+ return value.replace(/\n+$/, '');
5391
+ }
5392
+ /**
5393
+ * Set value programmatically
5394
+ */
5395
+ setValue(value) {
5396
+ if (this.editor) {
5397
+ this.editor.value = String(value ?? '');
5398
+ }
5399
+ }
5400
+ /**
5401
+ * Get the CodeMirror instance (if needed for advanced usage)
5402
+ */
5403
+ getEditorInstance() {
5404
+ return this.editor;
5405
+ }
5406
+ }
5407
+
4727
5408
  /**
4728
5409
  * Custom cell editors for ngx-smart-table
4729
5410
  */
@@ -4953,15 +5634,28 @@ class ColumnConfigFactory {
4953
5634
  const Columns = ColumnConfigFactory;
4954
5635
 
4955
5636
  class StCellComponent {
4956
- constructor() {
5637
+ constructor(cdr) {
5638
+ this.cdr = cdr;
4957
5639
  this.editMode = EditMode.CLICK;
4958
5640
  this.cellChange = new EventEmitter();
4959
5641
  this.cellEdit = new EventEmitter();
4960
5642
  this.cellSave = new EventEmitter();
4961
5643
  this.cellCancel = new EventEmitter();
4962
5644
  this.cellSaveAndNavigate = new EventEmitter();
5645
+ this.cellLoading = false;
4963
5646
  }
4964
5647
  ngOnInit() {
5648
+ this.cell.onStateChange(() => {
5649
+ this.cellLoading = !!this.cell.getState().isLoading;
5650
+ try {
5651
+ this.cdr.detectChanges();
5652
+ }
5653
+ catch {
5654
+ // View may have been destroyed; safely ignore
5655
+ }
5656
+ });
5657
+ // Pick up loading state that was set before this component was created
5658
+ this.cellLoading = !!this.cell.getState().isLoading;
4965
5659
  // Subscribe to editing position changes
4966
5660
  // When another cell starts editing, save this cell if it's currently editing
4967
5661
  if (this.tableState && this.columnIndex !== undefined) {
@@ -5312,12 +6006,12 @@ class StCellComponent {
5312
6006
  }
5313
6007
  }
5314
6008
  }
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"] }] });
6009
+ StCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StCellComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
6010
+ 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
6011
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StCellComponent, decorators: [{
5318
6012
  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: [{
6013
+ 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"] }]
6014
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { cell: [{
5321
6015
  type: Input
5322
6016
  }], editMode: [{
5323
6017
  type: Input
@@ -7991,7 +8685,20 @@ class StTableComponent {
7991
8685
  if (!this.data)
7992
8686
  return;
7993
8687
  const columns = this.getActiveColumns();
7994
- this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map(column => new Cell(column, rowData[column.key], rowData, rowIndex)));
8688
+ const oldGrid = this.internalCellGrid;
8689
+ this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map((column, colIndex) => {
8690
+ const newCell = new Cell(column, rowData[column.key], rowData, rowIndex);
8691
+ const oldCell = oldGrid?.[rowIndex]?.[colIndex];
8692
+ if (oldCell && oldCell.getColumnConfig().key === column.key) {
8693
+ oldCell.setReplacement(newCell);
8694
+ // Carry over transient state (e.g. loading) that was set on the old cell
8695
+ const oldState = oldCell.getState();
8696
+ if (oldState.isLoading) {
8697
+ newCell.setLoading(true);
8698
+ }
8699
+ }
8700
+ return newCell;
8701
+ }));
7995
8702
  }
7996
8703
  /**
7997
8704
  * Setup data source - either sync array or async Observable
@@ -12377,5 +13084,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
12377
13084
  * Generated bundle index. Do not edit.
12378
13085
  */
12379
13086
 
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 };
13087
+ 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
13088
  //# sourceMappingURL=aquera-ngx-smart-table.mjs.map