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