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

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.
@@ -2211,6 +2211,125 @@ class WorkbookState {
2211
2211
  }
2212
2212
  }
2213
2213
 
2214
+ /**
2215
+ * Convert an LDAP Distinguished Name (DN) string to a human-readable path.
2216
+ *
2217
+ * @example
2218
+ * "OU=Engineering,OU=India,DC=company,DC=com"
2219
+ * → "Engineering / India (company.com)"
2220
+ *
2221
+ * "CN=John Smith,OU=Admins,OU=Engineering,DC=company,DC=com"
2222
+ * → "John Smith / Admins / Engineering (company.com)"
2223
+ *
2224
+ * "OU=R\\,D,OU=Teams,DC=example,DC=org"
2225
+ * → "R,D / Teams (example.org)"
2226
+ */
2227
+ function dnToHumanReadable(dn) {
2228
+ if (!/^\s*\S/.test(dn)) {
2229
+ return '';
2230
+ }
2231
+ const pathParts = [];
2232
+ const domainParts = [];
2233
+ for (const match of dn.matchAll(/(?:^|(?<!\\),)\s*(CN|OU|DC)=((?:\\.|[^,])+)/g)) {
2234
+ const key = match[1];
2235
+ const value = match[2]
2236
+ .trim()
2237
+ .replace(/\\([,\\#+<>;"=])/g, '$1');
2238
+ if (/^(?:CN|OU)$/.test(key)) {
2239
+ pathParts.push(value);
2240
+ }
2241
+ else if (/^DC$/.test(key)) {
2242
+ domainParts.push(value);
2243
+ }
2244
+ }
2245
+ const path = pathParts.join(' / ');
2246
+ const domain = domainParts.join('.');
2247
+ return path && domain
2248
+ ? `${path} (${domain})`
2249
+ : path || domain || dn;
2250
+ }
2251
+ /**
2252
+ * Cell formatter that converts LDAP Distinguished Name (DN) strings
2253
+ * into human-readable OU paths with optional domain suffix.
2254
+ *
2255
+ * @example
2256
+ * // In column config:
2257
+ * formatter: new OUFormatter()
2258
+ *
2259
+ * // With options:
2260
+ * formatter: new OUFormatter({ separator: ' > ', showDomain: false })
2261
+ *
2262
+ * // Handles arrays from multiselect:
2263
+ * // ['OU=Eng,DC=co,DC=com', 'OU=HR,DC=co,DC=com'] → "Eng (co.com), HR (co.com)"
2264
+ */
2265
+ class OUFormatter {
2266
+ constructor(options) {
2267
+ this.options = options;
2268
+ }
2269
+ format(value) {
2270
+ var _a, _b;
2271
+ if (Array.isArray(value)) {
2272
+ return value
2273
+ .map(v => this.formatSingle(v))
2274
+ .filter(v => !!v)
2275
+ .join((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.arraySeparator) !== null && _b !== void 0 ? _b : ', ');
2276
+ }
2277
+ return this.formatSingle(value);
2278
+ }
2279
+ formatSingle(value) {
2280
+ var _a, _b, _c, _d, _e;
2281
+ if (value === null || value === undefined || typeof value !== 'string' || !/^\s*\S/.test(value)) {
2282
+ return (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.emptyText) !== null && _b !== void 0 ? _b : '';
2283
+ }
2284
+ const separator = (_d = (_c = this.options) === null || _c === void 0 ? void 0 : _c.separator) !== null && _d !== void 0 ? _d : ' / ';
2285
+ const showDomain = ((_e = this.options) === null || _e === void 0 ? void 0 : _e.showDomain) !== false;
2286
+ const pathParts = [];
2287
+ const domainParts = [];
2288
+ for (const match of value.matchAll(/(?:^|(?<!\\),)\s*(CN|OU|DC)=((?:\\.|[^,])+)/g)) {
2289
+ const key = match[1];
2290
+ const val = match[2]
2291
+ .trim()
2292
+ .replace(/\\([,\\#+<>;"=])/g, '$1');
2293
+ if (/^(?:CN|OU)$/.test(key)) {
2294
+ pathParts.push(val);
2295
+ }
2296
+ else if (/^DC$/.test(key)) {
2297
+ domainParts.push(val);
2298
+ }
2299
+ }
2300
+ const path = pathParts.join(separator);
2301
+ const domain = domainParts.join('.');
2302
+ if (path && domain && showDomain)
2303
+ return `${path} (${domain})`;
2304
+ if (path)
2305
+ return path;
2306
+ if (domain && showDomain)
2307
+ return domain;
2308
+ return value;
2309
+ }
2310
+ }
2311
+
2312
+ const BUILTIN_FORMATTERS = {
2313
+ ouFormatter: () => new OUFormatter(),
2314
+ };
2315
+ const customFormatters = {};
2316
+ /**
2317
+ * Resolve a formatter by name. Looks up custom formatters first, then built-in.
2318
+ * Returns undefined if the name is not registered.
2319
+ */
2320
+ function resolveFormatter(name) {
2321
+ var _a;
2322
+ const factory = (_a = customFormatters[name]) !== null && _a !== void 0 ? _a : BUILTIN_FORMATTERS[name];
2323
+ return factory ? factory() : undefined;
2324
+ }
2325
+ /**
2326
+ * Register a custom formatter so it can be referenced by string name
2327
+ * in column configs (e.g. `formatter: 'myFormatter'`).
2328
+ */
2329
+ function registerFormatter(name, factory) {
2330
+ customFormatters[name] = factory;
2331
+ }
2332
+
2214
2333
  /**
2215
2334
  * Cell class - represents individual cell instances
2216
2335
  * Combines ColumnConfig (Flyweight) with CellState (unique per instance)
@@ -2276,19 +2395,24 @@ class Cell {
2276
2395
  * Render cell value as formatted string (delegates to formatter strategy)
2277
2396
  */
2278
2397
  render() {
2279
- var _a, _b;
2280
- if (!this.columnConfig.formatter) {
2398
+ var _a, _b, _c;
2399
+ let formatter = this.columnConfig.formatter;
2400
+ if (!formatter) {
2281
2401
  return String((_a = this.state.value) !== null && _a !== void 0 ? _a : '');
2282
2402
  }
2283
- if (this.columnConfig.formatter.formatWithContext) {
2284
- return this.columnConfig.formatter.formatWithContext(this.state.value, this.rowData, this.columnConfig.key);
2403
+ if (typeof formatter === 'string') {
2404
+ formatter = resolveFormatter(formatter);
2405
+ if (!formatter) {
2406
+ return String((_b = this.state.value) !== null && _b !== void 0 ? _b : '');
2407
+ }
2408
+ }
2409
+ if (formatter.formatWithContext) {
2410
+ return formatter.formatWithContext(this.state.value, this.rowData, this.columnConfig.key);
2285
2411
  }
2286
- // Ensure format method exists before calling it
2287
- if (this.columnConfig.formatter.format) {
2288
- return this.columnConfig.formatter.format(this.state.value);
2412
+ if (formatter.format) {
2413
+ return formatter.format(this.state.value);
2289
2414
  }
2290
- // Fallback if formatter exists but has no methods
2291
- return String((_b = this.state.value) !== null && _b !== void 0 ? _b : '');
2415
+ return String((_c = this.state.value) !== null && _c !== void 0 ? _c : '');
2292
2416
  }
2293
2417
  /**
2294
2418
  * Validate cell value (delegates to validator strategy)
@@ -2738,7 +2862,9 @@ class BaseColumnConfig {
2738
2862
  this.key = merged.key;
2739
2863
  this.header = merged.header;
2740
2864
  this.dataType = merged.dataType;
2741
- this.formatter = merged.formatter;
2865
+ this.formatter = typeof merged.formatter === 'string'
2866
+ ? resolveFormatter(merged.formatter)
2867
+ : merged.formatter;
2742
2868
  this.validator = merged.validator;
2743
2869
  this.editor = merged.editor;
2744
2870
  this.parser = merged.parser;
@@ -2902,11 +3028,15 @@ class BaseColumnConfig {
2902
3028
  * Format value for display (can be overridden)
2903
3029
  */
2904
3030
  formatValue(value, rowData) {
2905
- if (this.formatter) {
2906
- if (this.formatter.formatWithContext && rowData) {
2907
- return this.formatter.formatWithContext(value, rowData, this.key);
3031
+ let formatter = this.formatter;
3032
+ if (typeof formatter === 'string') {
3033
+ formatter = resolveFormatter(formatter);
3034
+ }
3035
+ if (formatter) {
3036
+ if (formatter.formatWithContext && rowData) {
3037
+ return formatter.formatWithContext(value, rowData, this.key);
2908
3038
  }
2909
- return this.formatter.format(value);
3039
+ return formatter.format(value);
2910
3040
  }
2911
3041
  return String(value !== null && value !== void 0 ? value : '');
2912
3042
  }
@@ -4731,11 +4861,13 @@ function injectCodeEditorStyles() {
4731
4861
  const style = document.createElement('style');
4732
4862
  style.id = styleId;
4733
4863
  style.textContent = `
4734
- /* Nile Code Editor cell styling */
4864
+ /* Nile Code Editor cell styling - constrained to cell height */
4735
4865
  nile-code-editor.st-cell-editor {
4736
4866
  display: block;
4737
4867
  width: 100%;
4738
4868
  height: 100%;
4869
+ max-height: 32px;
4870
+ overflow: hidden;
4739
4871
  font-size: inherit !important;
4740
4872
  font-family: inherit !important;
4741
4873
  line-height: inherit !important;
@@ -4743,19 +4875,31 @@ function injectCodeEditorStyles() {
4743
4875
  nile-code-editor.st-cell-editor::part(code-editor-base) {
4744
4876
  border: none !important;
4745
4877
  min-height: 100% !important;
4878
+ max-height: 32px !important;
4746
4879
  background: transparent !important;
4747
4880
  font-size: inherit !important;
4748
4881
  font-family: inherit !important;
4749
4882
  line-height: inherit !important;
4883
+ overflow: hidden !important;
4750
4884
  }
4751
4885
  /* Ensure proper sizing within table cell */
4752
4886
  .st-nile-code-editor {
4753
4887
  width: 100%;
4754
4888
  height: 100%;
4889
+ max-height: 32px;
4755
4890
  min-height: 28px;
4756
4891
  font-size: inherit !important;
4892
+ overflow: hidden;
4893
+ }
4894
+ /* CodeMirror content should inherit font size and be constrained */
4895
+ nile-code-editor.st-cell-editor .cm-editor {
4896
+ max-height: 32px !important;
4897
+ overflow: hidden !important;
4898
+ }
4899
+ nile-code-editor.st-cell-editor .cm-scroller {
4900
+ max-height: 32px !important;
4901
+ overflow: hidden !important;
4757
4902
  }
4758
- /* CodeMirror content should inherit font size */
4759
4903
  nile-code-editor.st-cell-editor .cm-content,
4760
4904
  nile-code-editor.st-cell-editor .cm-line {
4761
4905
  font-size: inherit !important;
@@ -4768,12 +4912,15 @@ function injectCodeEditorStyles() {
4768
4912
  align-items: center;
4769
4913
  width: 100%;
4770
4914
  height: 100%;
4915
+ max-height: 32px;
4771
4916
  gap: 4px;
4772
4917
  }
4773
4918
  .st-code-editor-wrapper .st-code-editor-input {
4774
4919
  flex: 1;
4775
4920
  min-width: 0;
4776
4921
  height: 100%;
4922
+ max-height: 32px;
4923
+ overflow: hidden;
4777
4924
  }
4778
4925
  .st-code-editor-wrapper .st-expand-button {
4779
4926
  display: flex;
@@ -4794,13 +4941,22 @@ function injectCodeEditorStyles() {
4794
4941
  background: var(--nile-color-neutral-100, #f3f4f6);
4795
4942
  color: var(--nile-color-neutral-700, #374151);
4796
4943
  }
4797
- /* Dialog code editor styling */
4944
+ /* Dialog code editor styling - fixed header/footer, scrollable content */
4798
4945
  .st-code-editor-dialog::part(panel) {
4799
4946
  max-height: var(--max-height, 80vh) !important;
4800
4947
  overflow: hidden !important;
4948
+ display: flex !important;
4949
+ flex-direction: column !important;
4950
+ }
4951
+ .st-code-editor-dialog::part(header) {
4952
+ flex-shrink: 0 !important;
4801
4953
  }
4802
4954
  .st-code-editor-dialog::part(body) {
4803
- overflow: auto !important;
4955
+ overflow: hidden !important;
4956
+ flex: 1 !important;
4957
+ display: flex !important;
4958
+ flex-direction: column !important;
4959
+ padding: 0 !important;
4804
4960
  }
4805
4961
  .st-code-editor-dialog nile-code-editor {
4806
4962
  width: 100%;
@@ -4809,14 +4965,6 @@ function injectCodeEditorStyles() {
4809
4965
  .st-code-editor-dialog nile-code-editor::part(code-editor-base) {
4810
4966
  border: 1px solid var(--nile-color-neutral-200, #e5e7eb) !important;
4811
4967
  border-radius: 4px !important;
4812
- overflow: auto !important;
4813
- min-height: var(--dialog-editor-min-height, 300px) !important;
4814
- }
4815
- .st-code-editor-dialog nile-code-editor .cm-editor {
4816
- min-height: var(--dialog-editor-min-height, 300px) !important;
4817
- }
4818
- .st-code-editor-dialog nile-code-editor .cm-content {
4819
- min-height: var(--dialog-editor-min-height, 300px) !important;
4820
4968
  }
4821
4969
  `;
4822
4970
  document.head.appendChild(style);
@@ -4833,19 +4981,26 @@ class NileCodeEditor {
4833
4981
  this.dialogOpen = false;
4834
4982
  this.expandButtonClicked = false;
4835
4983
  this.trackedValue = null;
4984
+ this.syncingFromDialog = false; // Flag to prevent inline editor from overwriting multiline content
4985
+ this.userEditedInline = false; // Flag to track if user has typed in inline editor
4986
+ this.dialogOriginalValue = ''; // Store original value when dialog opens
4987
+ this.dialogCurrentValue = ''; // Track current value in dialog
4836
4988
  }
4837
4989
  edit(context) {
4838
- var _a, _b, _c, _d, _e, _f;
4990
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
4839
4991
  if (!context.container) {
4840
4992
  console.warn('NileCodeEditor requires a container element');
4841
4993
  return;
4842
4994
  }
4843
4995
  this.context = context;
4844
- this.trackedValue = null;
4996
+ // Initialize tracked value from context
4997
+ this.trackedValue = String((_a = context.value) !== null && _a !== void 0 ? _a : '');
4998
+ this.syncingFromDialog = false;
4999
+ this.userEditedInline = false;
4845
5000
  // Inject global styles once
4846
5001
  injectCodeEditorStyles();
4847
5002
  // Check if we should show expand button (default: true)
4848
- const showExpandButton = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.showExpandButton) !== false;
5003
+ const showExpandButton = ((_b = this.options) === null || _b === void 0 ? void 0 : _b.showExpandButton) !== false;
4849
5004
  if (showExpandButton) {
4850
5005
  // Create wrapper for editor + expand button
4851
5006
  this.wrapper = document.createElement('div');
@@ -4855,12 +5010,17 @@ class NileCodeEditor {
4855
5010
  editorContainer.className = 'st-code-editor-input';
4856
5011
  // Create NileCodeEditor custom element
4857
5012
  this.editor = document.createElement('nile-code-editor');
4858
- this.editor.value = String((_b = context.value) !== null && _b !== void 0 ? _b : '');
5013
+ this.editor.value = String((_c = context.value) !== null && _c !== void 0 ? _c : '');
4859
5014
  this.editor.className = 'st-cell-editor st-nile-code-editor';
4860
5015
  this.editor.style.width = '100%';
4861
5016
  this.editor.style.height = '100%';
4862
5017
  this.editor.style.boxSizing = 'border-box';
4863
- this.editor.noborder = ((_c = this.options) === null || _c === void 0 ? void 0 : _c.noborder) !== false;
5018
+ this.editor.noborder = ((_d = this.options) === null || _d === void 0 ? void 0 : _d.noborder) !== false;
5019
+ // Enable multiline by default for inline editor to support paste and multiline content
5020
+ this.editor.multiline = ((_e = this.options) === null || _e === void 0 ? void 0 : _e.multiline) !== false;
5021
+ this.editor.hasScroller = true;
5022
+ // No line numbers for inline editor
5023
+ this.editor.lineNumbers = false;
4864
5024
  editorContainer.appendChild(this.editor);
4865
5025
  this.wrapper.appendChild(editorContainer);
4866
5026
  // Create expand button
@@ -4888,12 +5048,17 @@ class NileCodeEditor {
4888
5048
  else {
4889
5049
  // Create NileCodeEditor custom element without wrapper
4890
5050
  this.editor = document.createElement('nile-code-editor');
4891
- this.editor.value = String((_d = context.value) !== null && _d !== void 0 ? _d : '');
5051
+ this.editor.value = String((_f = context.value) !== null && _f !== void 0 ? _f : '');
4892
5052
  this.editor.className = 'st-cell-editor st-nile-code-editor';
4893
5053
  this.editor.style.width = '100%';
4894
5054
  this.editor.style.height = '100%';
4895
5055
  this.editor.style.boxSizing = 'border-box';
4896
- this.editor.noborder = ((_e = this.options) === null || _e === void 0 ? void 0 : _e.noborder) !== false;
5056
+ this.editor.noborder = ((_g = this.options) === null || _g === void 0 ? void 0 : _g.noborder) !== false;
5057
+ // Enable multiline by default for inline editor to support paste and multiline content
5058
+ this.editor.multiline = ((_h = this.options) === null || _h === void 0 ? void 0 : _h.multiline) !== false;
5059
+ this.editor.hasScroller = true;
5060
+ // No line numbers for inline editor
5061
+ this.editor.lineNumbers = false;
4897
5062
  // Clear container and append editor
4898
5063
  context.container.innerHTML = '';
4899
5064
  context.container.appendChild(this.editor);
@@ -4903,7 +5068,7 @@ class NileCodeEditor {
4903
5068
  // Set up event listeners
4904
5069
  this.setupEventListeners(context);
4905
5070
  // Auto focus - need a slight delay for nile-code-editor to fully initialize
4906
- if (((_f = this.options) === null || _f === void 0 ? void 0 : _f.autoFocus) !== false) {
5071
+ if (((_j = this.options) === null || _j === void 0 ? void 0 : _j.autoFocus) !== false) {
4907
5072
  // Listen for the nile-after-init event which fires when editor is ready
4908
5073
  const initHandler = () => {
4909
5074
  var _a;
@@ -4945,9 +5110,18 @@ class NileCodeEditor {
4945
5110
  /**
4946
5111
  * Read the live value directly from CodeMirror's internal state,
4947
5112
  * bypassing debounced nile-change events and the possibly-stale .value property.
5113
+ *
5114
+ * Priority order:
5115
+ * 1. trackedValue - always up to date from change events
5116
+ * 2. CodeMirror internal state - for real-time reading
5117
+ * 3. editor.value property - fallback
4948
5118
  */
4949
5119
  getLiveEditorValue() {
4950
5120
  var _a, _b;
5121
+ // Use tracked value if available (updated by change events)
5122
+ if (this.trackedValue !== null) {
5123
+ return this.trackedValue;
5124
+ }
4951
5125
  if (!this.editor)
4952
5126
  return '';
4953
5127
  try {
@@ -4962,19 +5136,19 @@ class NileCodeEditor {
4962
5136
  catch (_c) {
4963
5137
  // Fall through to other methods
4964
5138
  }
4965
- if (this.trackedValue !== null)
4966
- return this.trackedValue;
4967
5139
  return (_b = this.editor.value) !== null && _b !== void 0 ? _b : '';
4968
5140
  }
4969
5141
  /**
4970
5142
  * Open the full editor dialog
4971
5143
  */
4972
5144
  openDialog() {
4973
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
5145
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
4974
5146
  if (this.dialogOpen)
4975
5147
  return;
4976
5148
  this.dialogOpen = true;
4977
5149
  this.expandButtonClicked = false; // Reset flag now that dialog is opening
5150
+ // Store original value for cancel functionality
5151
+ this.dialogOriginalValue = this.getLiveEditorValue();
4978
5152
  // Create dialog with configurable dimensions
4979
5153
  const dialogWidth = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.dialogWidth) || '600px';
4980
5154
  const dialogMaxHeight = ((_b = this.options) === null || _b === void 0 ? void 0 : _b.dialogMaxHeight) || '80vh';
@@ -4985,86 +5159,91 @@ class NileCodeEditor {
4985
5159
  this.dialog.label = dialogTitle;
4986
5160
  this.dialog.style.setProperty('--width', dialogWidth);
4987
5161
  this.dialog.style.setProperty('--max-height', dialogMaxHeight);
4988
- // Create dialog content
5162
+ // Create dialog content wrapper - flex column to handle fixed header/footer
5163
+ const contentWrapper = document.createElement('div');
5164
+ contentWrapper.style.display = 'flex';
5165
+ contentWrapper.style.flexDirection = 'column';
5166
+ contentWrapper.style.height = `calc(${dialogMaxHeight} - 60px)`; // Account for dialog header
5167
+ contentWrapper.style.maxHeight = `calc(${dialogMaxHeight} - 60px)`;
5168
+ // Create editor content area - this is the scrollable part
4989
5169
  const content = document.createElement('div');
4990
5170
  content.style.padding = '16px';
4991
- content.style.maxHeight = `calc(${dialogMaxHeight} - 80px)`;
5171
+ content.style.paddingBottom = '8px';
5172
+ content.style.flex = '1';
4992
5173
  content.style.overflow = 'auto';
5174
+ content.style.minHeight = '0'; // Important for flex shrinking
4993
5175
  // Create full editor
4994
5176
  this.dialogEditor = document.createElement('nile-code-editor');
4995
- const minLines = (_f = (_e = this.options) === null || _e === void 0 ? void 0 : _e.dialogMinLines) !== null && _f !== void 0 ? _f : 20;
4996
- const currentValue = this.getLiveEditorValue();
4997
- const currentLineCount = (currentValue.match(/\n/g) || []).length + 1;
4998
- const paddingLines = Math.max(0, minLines - currentLineCount);
4999
- this.dialogEditor.value = currentValue + '\n'.repeat(paddingLines);
5177
+ this.dialogEditor.value = this.dialogOriginalValue;
5000
5178
  this.dialogEditor.multiline = true;
5001
5179
  this.dialogEditor.lineNumbersMultiline = true;
5002
5180
  this.dialogEditor.hasScroller = true;
5003
- const lineHeightPx = 20;
5004
- const minHeightFromLines = `${minLines * lineHeightPx}px`;
5005
- this.dialogEditor.style.minHeight = `max(${dialogEditorHeight}, ${minHeightFromLines})`;
5006
- this.dialogEditor.style.maxHeight = `calc(${dialogMaxHeight} - 120px)`;
5007
- content.style.setProperty('--dialog-editor-min-height', `max(${dialogEditorHeight}, ${minHeightFromLines})`);
5181
+ this.dialogEditor.style.minHeight = dialogEditorHeight;
5008
5182
  // Apply same options to dialog editor
5009
- if ((_g = this.options) === null || _g === void 0 ? void 0 : _g.language) {
5183
+ if ((_e = this.options) === null || _e === void 0 ? void 0 : _e.language) {
5010
5184
  this.dialogEditor.language = this.options.language;
5011
5185
  }
5012
- if ((_h = this.options) === null || _h === void 0 ? void 0 : _h.placeholder) {
5186
+ if ((_f = this.options) === null || _f === void 0 ? void 0 : _f.placeholder) {
5013
5187
  this.dialogEditor.placeholder = this.options.placeholder;
5014
5188
  }
5015
- if (((_j = this.options) === null || _j === void 0 ? void 0 : _j.tabCompletion) !== undefined) {
5189
+ if (((_g = this.options) === null || _g === void 0 ? void 0 : _g.tabCompletion) !== undefined) {
5016
5190
  this.dialogEditor.tabCompletion = this.options.tabCompletion;
5017
5191
  }
5018
- if (((_k = this.options) === null || _k === void 0 ? void 0 : _k.enableSearch) !== undefined) {
5192
+ if (((_h = this.options) === null || _h === void 0 ? void 0 : _h.enableSearch) !== undefined) {
5019
5193
  this.dialogEditor.enableSearch = this.options.enableSearch;
5020
5194
  }
5021
- if (((_l = this.options) === null || _l === void 0 ? void 0 : _l.enableFoldGutters) !== undefined) {
5195
+ if (((_j = this.options) === null || _j === void 0 ? void 0 : _j.enableFoldGutters) !== undefined) {
5022
5196
  this.dialogEditor.enableFoldGutters = this.options.enableFoldGutters;
5023
5197
  }
5024
- if ((_m = this.options) === null || _m === void 0 ? void 0 : _m.customAutoCompletions) {
5198
+ if ((_k = this.options) === null || _k === void 0 ? void 0 : _k.customAutoCompletions) {
5025
5199
  this.dialogEditor.customAutoCompletions = this.options.customAutoCompletions;
5026
5200
  }
5027
- if ((_o = this.options) === null || _o === void 0 ? void 0 : _o.customCompletionsPaths) {
5201
+ if ((_l = this.options) === null || _l === void 0 ? void 0 : _l.customCompletionsPaths) {
5028
5202
  this.dialogEditor.customCompletionsPaths = this.options.customCompletionsPaths;
5029
5203
  }
5030
- if ((_p = this.options) === null || _p === void 0 ? void 0 : _p.customThemeCSS) {
5204
+ if ((_m = this.options) === null || _m === void 0 ? void 0 : _m.customThemeCSS) {
5031
5205
  this.dialogEditor.customThemeCSS = this.options.customThemeCSS;
5032
5206
  }
5033
5207
  this.dialogEditor.expandable = false;
5034
- // Real-time sync: Update cell editor whenever dialog editor changes
5208
+ // Initialize dialog current value
5209
+ this.dialogCurrentValue = this.dialogOriginalValue;
5210
+ // Track changes in dialog editor
5035
5211
  this.dialogEditor.addEventListener('nile-change', (e) => {
5036
- var _a;
5037
- const dialogValue = ((_a = e.detail) === null || _a === void 0 ? void 0 : _a.value) || '';
5038
- this.trackedValue = dialogValue;
5039
- if (this.editor) {
5040
- this.editor.value = dialogValue;
5041
- }
5042
- if (this.context) {
5043
- this.context.onChange(dialogValue);
5044
- }
5212
+ var _a, _b;
5213
+ this.dialogCurrentValue = (_b = (_a = e.detail) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '';
5045
5214
  });
5046
5215
  content.appendChild(this.dialogEditor);
5047
- this.dialog.appendChild(content);
5048
- // Handle dialog close events (clicking X button - stay in edit mode)
5216
+ contentWrapper.appendChild(content);
5217
+ // Create footer with Ok button - fixed at bottom
5218
+ const footer = document.createElement('div');
5219
+ footer.style.display = 'flex';
5220
+ footer.style.justifyContent = 'flex-end';
5221
+ footer.style.padding = '12px 16px';
5222
+ footer.style.borderTop = '1px solid var(--nile-color-neutral-200, #e5e7eb)';
5223
+ footer.style.gap = '8px';
5224
+ footer.style.flexShrink = '0'; // Prevent footer from shrinking
5225
+ footer.style.backgroundColor = 'var(--nile-color-neutral-0, #ffffff)';
5226
+ const okButton = document.createElement('nile-button');
5227
+ okButton.setAttribute('variant', 'primary');
5228
+ okButton.textContent = 'Ok';
5229
+ okButton.addEventListener('click', () => {
5230
+ this.applyDialogChanges();
5231
+ });
5232
+ footer.appendChild(okButton);
5233
+ contentWrapper.appendChild(footer);
5234
+ this.dialog.appendChild(contentWrapper);
5235
+ // Handle dialog close events (clicking X button - cancel changes)
5049
5236
  this.dialog.addEventListener('nile-request-close', (e) => {
5050
- var _a;
5051
- const customEvent = e;
5052
- // Check if close was triggered by overlay click (clicking outside)
5053
- if (((_a = customEvent.detail) === null || _a === void 0 ? void 0 : _a.source) === 'overlay') {
5054
- // Clicking outside the dialog - save and exit edit mode
5055
- this.closeDialog(true);
5056
- }
5057
- else {
5058
- // Clicking X button - stay in edit mode
5059
- this.closeDialog(false);
5060
- }
5237
+ e.preventDefault();
5238
+ // X button or overlay click - cancel changes
5239
+ this.cancelDialogChanges();
5061
5240
  });
5062
- // Handle Escape key in dialog - stay in edit mode
5241
+ // Handle Escape key in dialog - cancel changes
5063
5242
  this.dialog.addEventListener('keydown', (e) => {
5064
5243
  if (e.key === 'Escape') {
5065
5244
  e.preventDefault();
5066
5245
  e.stopPropagation();
5067
- this.closeDialog(false);
5246
+ this.cancelDialogChanges();
5068
5247
  }
5069
5248
  });
5070
5249
  // Append to body and show
@@ -5082,34 +5261,115 @@ class NileCodeEditor {
5082
5261
  }, 0);
5083
5262
  }
5084
5263
  /**
5085
- * Close the dialog and optionally save/exit edit mode
5264
+ * Get the current value from the dialog editor
5086
5265
  */
5087
- closeDialog(saveAndExit = false) {
5266
+ getDialogEditorValue() {
5267
+ var _a;
5268
+ // Use tracked value from change events (most reliable)
5269
+ if (this.dialogCurrentValue) {
5270
+ return this.dialogCurrentValue.replace(/\n+$/, '');
5271
+ }
5272
+ if (!this.dialogEditor)
5273
+ return this.dialogOriginalValue;
5274
+ // Try to get value from CodeMirror's internal state
5275
+ try {
5276
+ const shadowRoot = this.dialogEditor.shadowRoot;
5277
+ if (shadowRoot) {
5278
+ const cmEditor = shadowRoot.querySelector('.cm-editor');
5279
+ if ((_a = cmEditor === null || cmEditor === void 0 ? void 0 : cmEditor.cmView) === null || _a === void 0 ? void 0 : _a.view) {
5280
+ const value = cmEditor.cmView.view.state.doc.toString();
5281
+ return value.replace(/\n+$/, '');
5282
+ }
5283
+ }
5284
+ }
5285
+ catch (_b) {
5286
+ // Fall through to other methods
5287
+ }
5288
+ // Fallback to value property
5289
+ const value = this.dialogEditor.value;
5290
+ return (value !== null && value !== void 0 ? value : '').replace(/\n+$/, '');
5291
+ }
5292
+ /**
5293
+ * Apply changes from dialog and close it
5294
+ */
5295
+ applyDialogChanges() {
5296
+ var _a, _b;
5088
5297
  if (!this.dialogOpen)
5089
5298
  return;
5090
- // Reset flag immediately so document click handler works
5299
+ // Get the value from dialog editor - try multiple sources
5300
+ let dialogValue = this.dialogCurrentValue;
5301
+ // If no tracked value, try reading directly from dialog editor
5302
+ if (!dialogValue && this.dialogEditor) {
5303
+ try {
5304
+ const shadowRoot = this.dialogEditor.shadowRoot;
5305
+ if (shadowRoot) {
5306
+ const cmEditor = shadowRoot.querySelector('.cm-editor');
5307
+ if ((_a = cmEditor === null || cmEditor === void 0 ? void 0 : cmEditor.cmView) === null || _a === void 0 ? void 0 : _a.view) {
5308
+ dialogValue = cmEditor.cmView.view.state.doc.toString();
5309
+ }
5310
+ }
5311
+ }
5312
+ catch (_c) {
5313
+ // Fall through
5314
+ }
5315
+ // Fallback to value property
5316
+ if (!dialogValue) {
5317
+ dialogValue = (_b = this.dialogEditor.value) !== null && _b !== void 0 ? _b : '';
5318
+ }
5319
+ }
5320
+ // Strip trailing newlines
5321
+ dialogValue = (dialogValue || '').replace(/\n+$/, '');
5322
+ // Update tracked value and inline editor
5323
+ this.trackedValue = dialogValue;
5324
+ this.userEditedInline = false;
5325
+ this.syncingFromDialog = true;
5326
+ if (this.editor) {
5327
+ this.editor.value = dialogValue;
5328
+ }
5329
+ setTimeout(() => {
5330
+ this.syncingFromDialog = false;
5331
+ }, 0);
5332
+ // Notify context of the change
5333
+ if (this.context) {
5334
+ this.context.onChange(dialogValue);
5335
+ }
5336
+ // Close dialog
5337
+ this.closeDialogUI();
5338
+ // Refocus the cell editor to stay in edit mode
5339
+ setTimeout(() => {
5340
+ this.focusEditor();
5341
+ }, 50);
5342
+ }
5343
+ /**
5344
+ * Cancel dialog changes and revert to original value
5345
+ */
5346
+ cancelDialogChanges() {
5347
+ if (!this.dialogOpen)
5348
+ return;
5349
+ // Revert to original value (don't change anything)
5350
+ // trackedValue and inline editor remain as they were before dialog opened
5351
+ // Close dialog
5352
+ this.closeDialogUI();
5353
+ // Refocus the cell editor to stay in edit mode
5354
+ setTimeout(() => {
5355
+ this.focusEditor();
5356
+ }, 50);
5357
+ }
5358
+ /**
5359
+ * Close and remove the dialog UI
5360
+ */
5361
+ closeDialogUI() {
5091
5362
  this.dialogOpen = false;
5092
- // Close and remove dialog
5363
+ this.dialogCurrentValue = '';
5093
5364
  if (this.dialog) {
5094
5365
  this.dialog.open = false;
5095
5366
  const dialogRef = this.dialog;
5096
- const dialogEditorRef = this.dialogEditor;
5097
5367
  this.dialog = undefined;
5098
5368
  this.dialogEditor = undefined;
5099
5369
  // Remove from DOM after animation
5100
5370
  setTimeout(() => {
5101
5371
  dialogRef === null || dialogRef === void 0 ? void 0 : dialogRef.remove();
5102
5372
  }, 200);
5103
- if (saveAndExit && this.context) {
5104
- // Save and exit edit mode
5105
- this.context.onSave(this.getCurrentValue());
5106
- }
5107
- else {
5108
- // Refocus the cell editor to stay in edit mode
5109
- setTimeout(() => {
5110
- this.focusEditor();
5111
- }, 50);
5112
- }
5113
5373
  }
5114
5374
  }
5115
5375
  /**
@@ -5275,6 +5535,11 @@ class NileCodeEditor {
5275
5535
  var _a, _b;
5276
5536
  const customEvent = e;
5277
5537
  const newValue = (_b = (_a = customEvent.detail) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '';
5538
+ // Don't process if we're syncing from dialog (prevents feedback loop)
5539
+ if (this.syncingFromDialog) {
5540
+ return;
5541
+ }
5542
+ // Update tracked value
5278
5543
  this.trackedValue = newValue;
5279
5544
  context.onChange(newValue);
5280
5545
  };
@@ -5343,6 +5608,11 @@ class NileCodeEditor {
5343
5608
  this.expandButton = undefined;
5344
5609
  this.context = undefined;
5345
5610
  this.expandButtonClicked = false;
5611
+ this.syncingFromDialog = false;
5612
+ this.trackedValue = null;
5613
+ this.userEditedInline = false;
5614
+ this.dialogOriginalValue = '';
5615
+ this.dialogCurrentValue = '';
5346
5616
  }
5347
5617
  focus() {
5348
5618
  var _a;
@@ -8645,7 +8915,7 @@ class StTableComponent {
8645
8915
  const oldGrid = this.internalCellGrid;
8646
8916
  this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map((column, colIndex) => {
8647
8917
  var _a;
8648
- const newCell = new Cell(column, rowData[column.key], rowData, rowIndex);
8918
+ const newCell = column.createCell(rowData, rowIndex);
8649
8919
  const oldCell = (_a = oldGrid === null || oldGrid === void 0 ? void 0 : oldGrid[rowIndex]) === null || _a === void 0 ? void 0 : _a[colIndex];
8650
8920
  if (oldCell && oldCell.getColumnConfig().key === column.key) {
8651
8921
  oldCell.setReplacement(newCell);
@@ -13070,5 +13340,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
13070
13340
  * Generated bundle index. Do not edit.
13071
13341
  */
13072
13342
 
13073
- 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 };
13343
+ export { ArrayFormatter, AutosaveService, BaseColumnConfig, BooleanEditor, BooleanFormatter, BuilderPreviewComponent, BuilderToolbarComponent, Cell, CellAlignment, CellDataType, CellLifecycleState, CellVerticalAlignment, ChainValidator, ClickOutsideDirective, ColumnConfigFactory, ColumnEditorComponent, ColumnListComponent, Columns, CurrencyFormatter, DEFAULT_AUTOSAVE_CONFIG, DEFAULT_COLUMN_CONFIG, DEFAULT_TABLE_CONFIG, DateEditor, DateFormatter, DateRangeValidator, DefaultFormatter, DefinitionBuilderComponent, DefinitionBuilderModule, DefinitionBuilderService, DefinitionExportService, DefinitionImportService, EditMode, EmailValidator, FilterOperator, FunctionFormatter, FunctionValidator, JsonSchemaValidatorService, LengthValidator, NavigationDirection, NavigationKey, NileAutoCompleteEditor, NileCalendarEditor, NileCodeEditor, NileDatePickerEditor, NileInputEditor, NileSelectEditor, NumberEditor, NumberFormatter, OUFormatter, PatternValidators, PercentageFormatter, RangeValidator, RegexValidator, RequiredValidator, RowValidationService, SampleDataGeneratorService, SelectEditor, SharedTableComponentsModule, SheetState, SimpleColumnConfig, SmartTableModule, SortDirection, StAddColumnButtonComponent, StCellComponent, StColumnEditorModalComponent, StColumnFilterComponent, StColumnMenuDropdownComponent, StColumnResizeDirective, StColumnVisibilityComponent, StHeaderComponent, StKeyboardNavigationDirective, StPaginationComponent, StRowActionsDropdownComponent, StSheetActionsComponent, StSheetComponent, StTableActionsComponent, StTableComponent, StWorkbookComponent, StringFormatter, TableConfigEditorComponent, TableState, TableZIndex, TemplateFormatter, TextAreaEditor, TextEditor, UrlValidator, ValidationLoggerService, VirtualScrollService, WorkbookState, canEdit, createCellState, createMemento, dnToHumanReadable, isCellValid, isDisplayMode, isNullOrUndefined, isValidDate, isValidationSuccess, mergeTableConfig, registerFormatter, resolveFormatter, restoreFromMemento };
13074
13344
  //# sourceMappingURL=aquera-ngx-smart-table.mjs.map