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

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.
@@ -4781,11 +4781,13 @@ function injectCodeEditorStyles() {
4781
4781
  const style = document.createElement('style');
4782
4782
  style.id = styleId;
4783
4783
  style.textContent = `
4784
- /* Nile Code Editor cell styling */
4784
+ /* Nile Code Editor cell styling - constrained to cell height */
4785
4785
  nile-code-editor.st-cell-editor {
4786
4786
  display: block;
4787
4787
  width: 100%;
4788
4788
  height: 100%;
4789
+ max-height: 32px;
4790
+ overflow: hidden;
4789
4791
  font-size: inherit !important;
4790
4792
  font-family: inherit !important;
4791
4793
  line-height: inherit !important;
@@ -4793,19 +4795,31 @@ function injectCodeEditorStyles() {
4793
4795
  nile-code-editor.st-cell-editor::part(code-editor-base) {
4794
4796
  border: none !important;
4795
4797
  min-height: 100% !important;
4798
+ max-height: 32px !important;
4796
4799
  background: transparent !important;
4797
4800
  font-size: inherit !important;
4798
4801
  font-family: inherit !important;
4799
4802
  line-height: inherit !important;
4803
+ overflow: hidden !important;
4800
4804
  }
4801
4805
  /* Ensure proper sizing within table cell */
4802
4806
  .st-nile-code-editor {
4803
4807
  width: 100%;
4804
4808
  height: 100%;
4809
+ max-height: 32px;
4805
4810
  min-height: 28px;
4806
4811
  font-size: inherit !important;
4812
+ overflow: hidden;
4813
+ }
4814
+ /* CodeMirror content should inherit font size and be constrained */
4815
+ nile-code-editor.st-cell-editor .cm-editor {
4816
+ max-height: 32px !important;
4817
+ overflow: hidden !important;
4818
+ }
4819
+ nile-code-editor.st-cell-editor .cm-scroller {
4820
+ max-height: 32px !important;
4821
+ overflow: hidden !important;
4807
4822
  }
4808
- /* CodeMirror content should inherit font size */
4809
4823
  nile-code-editor.st-cell-editor .cm-content,
4810
4824
  nile-code-editor.st-cell-editor .cm-line {
4811
4825
  font-size: inherit !important;
@@ -4818,12 +4832,15 @@ function injectCodeEditorStyles() {
4818
4832
  align-items: center;
4819
4833
  width: 100%;
4820
4834
  height: 100%;
4835
+ max-height: 32px;
4821
4836
  gap: 4px;
4822
4837
  }
4823
4838
  .st-code-editor-wrapper .st-code-editor-input {
4824
4839
  flex: 1;
4825
4840
  min-width: 0;
4826
4841
  height: 100%;
4842
+ max-height: 32px;
4843
+ overflow: hidden;
4827
4844
  }
4828
4845
  .st-code-editor-wrapper .st-expand-button {
4829
4846
  display: flex;
@@ -4844,13 +4861,22 @@ function injectCodeEditorStyles() {
4844
4861
  background: var(--nile-color-neutral-100, #f3f4f6);
4845
4862
  color: var(--nile-color-neutral-700, #374151);
4846
4863
  }
4847
- /* Dialog code editor styling */
4864
+ /* Dialog code editor styling - fixed header/footer, scrollable content */
4848
4865
  .st-code-editor-dialog::part(panel) {
4849
4866
  max-height: var(--max-height, 80vh) !important;
4850
4867
  overflow: hidden !important;
4868
+ display: flex !important;
4869
+ flex-direction: column !important;
4870
+ }
4871
+ .st-code-editor-dialog::part(header) {
4872
+ flex-shrink: 0 !important;
4851
4873
  }
4852
4874
  .st-code-editor-dialog::part(body) {
4853
- overflow: auto !important;
4875
+ overflow: hidden !important;
4876
+ flex: 1 !important;
4877
+ display: flex !important;
4878
+ flex-direction: column !important;
4879
+ padding: 0 !important;
4854
4880
  }
4855
4881
  .st-code-editor-dialog nile-code-editor {
4856
4882
  width: 100%;
@@ -4859,14 +4885,6 @@ function injectCodeEditorStyles() {
4859
4885
  .st-code-editor-dialog nile-code-editor::part(code-editor-base) {
4860
4886
  border: 1px solid var(--nile-color-neutral-200, #e5e7eb) !important;
4861
4887
  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
4888
  }
4871
4889
  `;
4872
4890
  document.head.appendChild(style);
@@ -4883,6 +4901,10 @@ class NileCodeEditor {
4883
4901
  this.dialogOpen = false;
4884
4902
  this.expandButtonClicked = false;
4885
4903
  this.trackedValue = null;
4904
+ this.syncingFromDialog = false; // Flag to prevent inline editor from overwriting multiline content
4905
+ this.userEditedInline = false; // Flag to track if user has typed in inline editor
4906
+ this.dialogOriginalValue = ''; // Store original value when dialog opens
4907
+ this.dialogCurrentValue = ''; // Track current value in dialog
4886
4908
  }
4887
4909
  edit(context) {
4888
4910
  if (!context.container) {
@@ -4890,7 +4912,10 @@ class NileCodeEditor {
4890
4912
  return;
4891
4913
  }
4892
4914
  this.context = context;
4893
- this.trackedValue = null;
4915
+ // Initialize tracked value from context
4916
+ this.trackedValue = String(context.value ?? '');
4917
+ this.syncingFromDialog = false;
4918
+ this.userEditedInline = false;
4894
4919
  // Inject global styles once
4895
4920
  injectCodeEditorStyles();
4896
4921
  // Check if we should show expand button (default: true)
@@ -4910,6 +4935,11 @@ class NileCodeEditor {
4910
4935
  this.editor.style.height = '100%';
4911
4936
  this.editor.style.boxSizing = 'border-box';
4912
4937
  this.editor.noborder = this.options?.noborder !== false;
4938
+ // Enable multiline by default for inline editor to support paste and multiline content
4939
+ this.editor.multiline = this.options?.multiline !== false;
4940
+ this.editor.hasScroller = true;
4941
+ // No line numbers for inline editor
4942
+ this.editor.lineNumbers = false;
4913
4943
  editorContainer.appendChild(this.editor);
4914
4944
  this.wrapper.appendChild(editorContainer);
4915
4945
  // Create expand button
@@ -4943,6 +4973,11 @@ class NileCodeEditor {
4943
4973
  this.editor.style.height = '100%';
4944
4974
  this.editor.style.boxSizing = 'border-box';
4945
4975
  this.editor.noborder = this.options?.noborder !== false;
4976
+ // Enable multiline by default for inline editor to support paste and multiline content
4977
+ this.editor.multiline = this.options?.multiline !== false;
4978
+ this.editor.hasScroller = true;
4979
+ // No line numbers for inline editor
4980
+ this.editor.lineNumbers = false;
4946
4981
  // Clear container and append editor
4947
4982
  context.container.innerHTML = '';
4948
4983
  context.container.appendChild(this.editor);
@@ -4993,8 +5028,17 @@ class NileCodeEditor {
4993
5028
  /**
4994
5029
  * Read the live value directly from CodeMirror's internal state,
4995
5030
  * bypassing debounced nile-change events and the possibly-stale .value property.
5031
+ *
5032
+ * Priority order:
5033
+ * 1. trackedValue - always up to date from change events
5034
+ * 2. CodeMirror internal state - for real-time reading
5035
+ * 3. editor.value property - fallback
4996
5036
  */
4997
5037
  getLiveEditorValue() {
5038
+ // Use tracked value if available (updated by change events)
5039
+ if (this.trackedValue !== null) {
5040
+ return this.trackedValue;
5041
+ }
4998
5042
  if (!this.editor)
4999
5043
  return '';
5000
5044
  try {
@@ -5009,8 +5053,6 @@ class NileCodeEditor {
5009
5053
  catch {
5010
5054
  // Fall through to other methods
5011
5055
  }
5012
- if (this.trackedValue !== null)
5013
- return this.trackedValue;
5014
5056
  return this.editor.value ?? '';
5015
5057
  }
5016
5058
  /**
@@ -5021,6 +5063,8 @@ class NileCodeEditor {
5021
5063
  return;
5022
5064
  this.dialogOpen = true;
5023
5065
  this.expandButtonClicked = false; // Reset flag now that dialog is opening
5066
+ // Store original value for cancel functionality
5067
+ this.dialogOriginalValue = this.getLiveEditorValue();
5024
5068
  // Create dialog with configurable dimensions
5025
5069
  const dialogWidth = this.options?.dialogWidth || '600px';
5026
5070
  const dialogMaxHeight = this.options?.dialogMaxHeight || '80vh';
@@ -5031,26 +5075,26 @@ class NileCodeEditor {
5031
5075
  this.dialog.label = dialogTitle;
5032
5076
  this.dialog.style.setProperty('--width', dialogWidth);
5033
5077
  this.dialog.style.setProperty('--max-height', dialogMaxHeight);
5034
- // Create dialog content
5078
+ // Create dialog content wrapper - flex column to handle fixed header/footer
5079
+ const contentWrapper = document.createElement('div');
5080
+ contentWrapper.style.display = 'flex';
5081
+ contentWrapper.style.flexDirection = 'column';
5082
+ contentWrapper.style.height = `calc(${dialogMaxHeight} - 60px)`; // Account for dialog header
5083
+ contentWrapper.style.maxHeight = `calc(${dialogMaxHeight} - 60px)`;
5084
+ // Create editor content area - this is the scrollable part
5035
5085
  const content = document.createElement('div');
5036
5086
  content.style.padding = '16px';
5037
- content.style.maxHeight = `calc(${dialogMaxHeight} - 80px)`;
5087
+ content.style.paddingBottom = '8px';
5088
+ content.style.flex = '1';
5038
5089
  content.style.overflow = 'auto';
5090
+ content.style.minHeight = '0'; // Important for flex shrinking
5039
5091
  // Create full editor
5040
5092
  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);
5093
+ this.dialogEditor.value = this.dialogOriginalValue;
5046
5094
  this.dialogEditor.multiline = true;
5047
5095
  this.dialogEditor.lineNumbersMultiline = true;
5048
5096
  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})`);
5097
+ this.dialogEditor.style.minHeight = dialogEditorHeight;
5054
5098
  // Apply same options to dialog editor
5055
5099
  if (this.options?.language) {
5056
5100
  this.dialogEditor.language = this.options.language;
@@ -5077,38 +5121,44 @@ class NileCodeEditor {
5077
5121
  this.dialogEditor.customThemeCSS = this.options.customThemeCSS;
5078
5122
  }
5079
5123
  this.dialogEditor.expandable = false;
5080
- // Real-time sync: Update cell editor whenever dialog editor changes
5124
+ // Initialize dialog current value
5125
+ this.dialogCurrentValue = this.dialogOriginalValue;
5126
+ // Track changes in dialog editor
5081
5127
  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
- }
5128
+ this.dialogCurrentValue = e.detail?.value ?? '';
5090
5129
  });
5091
5130
  content.appendChild(this.dialogEditor);
5092
- this.dialog.appendChild(content);
5093
- // Handle dialog close events (clicking X button - stay in edit mode)
5131
+ contentWrapper.appendChild(content);
5132
+ // Create footer with Ok button - fixed at bottom
5133
+ const footer = document.createElement('div');
5134
+ footer.style.display = 'flex';
5135
+ footer.style.justifyContent = 'flex-end';
5136
+ footer.style.padding = '12px 16px';
5137
+ footer.style.borderTop = '1px solid var(--nile-color-neutral-200, #e5e7eb)';
5138
+ footer.style.gap = '8px';
5139
+ footer.style.flexShrink = '0'; // Prevent footer from shrinking
5140
+ footer.style.backgroundColor = 'var(--nile-color-neutral-0, #ffffff)';
5141
+ const okButton = document.createElement('nile-button');
5142
+ okButton.setAttribute('variant', 'primary');
5143
+ okButton.textContent = 'Ok';
5144
+ okButton.addEventListener('click', () => {
5145
+ this.applyDialogChanges();
5146
+ });
5147
+ footer.appendChild(okButton);
5148
+ contentWrapper.appendChild(footer);
5149
+ this.dialog.appendChild(contentWrapper);
5150
+ // Handle dialog close events (clicking X button - cancel changes)
5094
5151
  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
- }
5152
+ e.preventDefault();
5153
+ // X button or overlay click - cancel changes
5154
+ this.cancelDialogChanges();
5105
5155
  });
5106
- // Handle Escape key in dialog - stay in edit mode
5156
+ // Handle Escape key in dialog - cancel changes
5107
5157
  this.dialog.addEventListener('keydown', (e) => {
5108
5158
  if (e.key === 'Escape') {
5109
5159
  e.preventDefault();
5110
5160
  e.stopPropagation();
5111
- this.closeDialog(false);
5161
+ this.cancelDialogChanges();
5112
5162
  }
5113
5163
  });
5114
5164
  // Append to body and show
@@ -5125,34 +5175,113 @@ class NileCodeEditor {
5125
5175
  }, 0);
5126
5176
  }
5127
5177
  /**
5128
- * Close the dialog and optionally save/exit edit mode
5178
+ * Get the current value from the dialog editor
5129
5179
  */
5130
- closeDialog(saveAndExit = false) {
5180
+ getDialogEditorValue() {
5181
+ // Use tracked value from change events (most reliable)
5182
+ if (this.dialogCurrentValue) {
5183
+ return this.dialogCurrentValue.replace(/\n+$/, '');
5184
+ }
5185
+ if (!this.dialogEditor)
5186
+ return this.dialogOriginalValue;
5187
+ // Try to get value from CodeMirror's internal state
5188
+ try {
5189
+ const shadowRoot = this.dialogEditor.shadowRoot;
5190
+ if (shadowRoot) {
5191
+ const cmEditor = shadowRoot.querySelector('.cm-editor');
5192
+ if (cmEditor?.cmView?.view) {
5193
+ const value = cmEditor.cmView.view.state.doc.toString();
5194
+ return value.replace(/\n+$/, '');
5195
+ }
5196
+ }
5197
+ }
5198
+ catch {
5199
+ // Fall through to other methods
5200
+ }
5201
+ // Fallback to value property
5202
+ const value = this.dialogEditor.value;
5203
+ return (value ?? '').replace(/\n+$/, '');
5204
+ }
5205
+ /**
5206
+ * Apply changes from dialog and close it
5207
+ */
5208
+ applyDialogChanges() {
5131
5209
  if (!this.dialogOpen)
5132
5210
  return;
5133
- // Reset flag immediately so document click handler works
5211
+ // Get the value from dialog editor - try multiple sources
5212
+ let dialogValue = this.dialogCurrentValue;
5213
+ // If no tracked value, try reading directly from dialog editor
5214
+ if (!dialogValue && this.dialogEditor) {
5215
+ try {
5216
+ const shadowRoot = this.dialogEditor.shadowRoot;
5217
+ if (shadowRoot) {
5218
+ const cmEditor = shadowRoot.querySelector('.cm-editor');
5219
+ if (cmEditor?.cmView?.view) {
5220
+ dialogValue = cmEditor.cmView.view.state.doc.toString();
5221
+ }
5222
+ }
5223
+ }
5224
+ catch {
5225
+ // Fall through
5226
+ }
5227
+ // Fallback to value property
5228
+ if (!dialogValue) {
5229
+ dialogValue = this.dialogEditor.value ?? '';
5230
+ }
5231
+ }
5232
+ // Strip trailing newlines
5233
+ dialogValue = (dialogValue || '').replace(/\n+$/, '');
5234
+ // Update tracked value and inline editor
5235
+ this.trackedValue = dialogValue;
5236
+ this.userEditedInline = false;
5237
+ this.syncingFromDialog = true;
5238
+ if (this.editor) {
5239
+ this.editor.value = dialogValue;
5240
+ }
5241
+ setTimeout(() => {
5242
+ this.syncingFromDialog = false;
5243
+ }, 0);
5244
+ // Notify context of the change
5245
+ if (this.context) {
5246
+ this.context.onChange(dialogValue);
5247
+ }
5248
+ // Close dialog
5249
+ this.closeDialogUI();
5250
+ // Refocus the cell editor to stay in edit mode
5251
+ setTimeout(() => {
5252
+ this.focusEditor();
5253
+ }, 50);
5254
+ }
5255
+ /**
5256
+ * Cancel dialog changes and revert to original value
5257
+ */
5258
+ cancelDialogChanges() {
5259
+ if (!this.dialogOpen)
5260
+ return;
5261
+ // Revert to original value (don't change anything)
5262
+ // trackedValue and inline editor remain as they were before dialog opened
5263
+ // Close dialog
5264
+ this.closeDialogUI();
5265
+ // Refocus the cell editor to stay in edit mode
5266
+ setTimeout(() => {
5267
+ this.focusEditor();
5268
+ }, 50);
5269
+ }
5270
+ /**
5271
+ * Close and remove the dialog UI
5272
+ */
5273
+ closeDialogUI() {
5134
5274
  this.dialogOpen = false;
5135
- // Close and remove dialog
5275
+ this.dialogCurrentValue = '';
5136
5276
  if (this.dialog) {
5137
5277
  this.dialog.open = false;
5138
5278
  const dialogRef = this.dialog;
5139
- const dialogEditorRef = this.dialogEditor;
5140
5279
  this.dialog = undefined;
5141
5280
  this.dialogEditor = undefined;
5142
5281
  // Remove from DOM after animation
5143
5282
  setTimeout(() => {
5144
5283
  dialogRef?.remove();
5145
5284
  }, 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
5285
  }
5157
5286
  }
5158
5287
  /**
@@ -5314,6 +5443,11 @@ class NileCodeEditor {
5314
5443
  const changeHandler = (e) => {
5315
5444
  const customEvent = e;
5316
5445
  const newValue = customEvent.detail?.value ?? '';
5446
+ // Don't process if we're syncing from dialog (prevents feedback loop)
5447
+ if (this.syncingFromDialog) {
5448
+ return;
5449
+ }
5450
+ // Update tracked value
5317
5451
  this.trackedValue = newValue;
5318
5452
  context.onChange(newValue);
5319
5453
  };
@@ -5379,6 +5513,11 @@ class NileCodeEditor {
5379
5513
  this.expandButton = undefined;
5380
5514
  this.context = undefined;
5381
5515
  this.expandButtonClicked = false;
5516
+ this.syncingFromDialog = false;
5517
+ this.trackedValue = null;
5518
+ this.userEditedInline = false;
5519
+ this.dialogOriginalValue = '';
5520
+ this.dialogCurrentValue = '';
5382
5521
  }
5383
5522
  focus() {
5384
5523
  this.editor?.focus();