@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.
- package/esm2020/lib/editors/index.mjs +2 -1
- package/esm2020/lib/editors/nile-code-editor.mjs +642 -0
- package/esm2020/lib/editors/nile-select-editor.mjs +16 -5
- package/esm2020/lib/renderer/components/st-cell/st-cell.component.mjs +19 -6
- package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +15 -2
- package/esm2020/lib/renderer/models/cell.class.mjs +30 -2
- package/fesm2015/aquera-ngx-smart-table.mjs +736 -12
- package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -1
- package/fesm2020/aquera-ngx-smart-table.mjs +719 -12
- package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -1
- package/lib/editors/index.d.ts +1 -0
- package/lib/editors/nile-code-editor.d.ts +159 -0
- package/lib/renderer/components/st-cell/st-cell.component.d.ts +4 -2
- package/lib/renderer/models/cell.class.d.ts +18 -1
- package/package.json +1 -1
|
@@ -2573,10 +2573,38 @@ class Cell {
|
|
|
2573
2573
|
return this.rowIndex;
|
|
2574
2574
|
}
|
|
2575
2575
|
/**
|
|
2576
|
-
*
|
|
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:
|
|
3680
|
+
background-color: transparent !important;
|
|
3653
3681
|
border: solid 1px transparent !important;
|
|
3654
|
-
margin:
|
|
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:
|
|
3689
|
+
background-color: transparent !important;
|
|
3661
3690
|
border: solid 1px transparent !important;
|
|
3662
|
-
margin:
|
|
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
|
-
|
|
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
|