@aquera/ngx-smart-table 0.0.17-patch-0.3 → 0.0.17-patch-0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/editors/nile-code-editor.mjs +205 -66
- package/esm2020/lib/formatters/formatter-registry.mjs +21 -0
- package/esm2020/lib/formatters/index.mjs +3 -0
- package/esm2020/lib/formatters/ou-formatter.mjs +96 -0
- package/esm2020/lib/models/base-column-config.class.mjs +13 -6
- package/esm2020/lib/models/column-config.interface.mjs +1 -1
- package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +2 -3
- package/esm2020/lib/renderer/models/cell.class.mjs +14 -8
- package/esm2020/public-api.mjs +5 -1
- package/fesm2015/aquera-ngx-smart-table.mjs +369 -99
- package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -1
- package/fesm2020/aquera-ngx-smart-table.mjs +345 -79
- package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -1
- package/lib/editors/nile-code-editor.d.ts +23 -4
- package/lib/formatters/formatter-registry.d.ts +13 -0
- package/lib/formatters/index.d.ts +2 -0
- package/lib/formatters/ou-formatter.d.ts +45 -0
- package/lib/models/base-column-config.class.d.ts +1 -1
- package/lib/models/column-config.interface.d.ts +4 -2
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
|
@@ -2289,6 +2289,122 @@ class WorkbookState {
|
|
|
2289
2289
|
}
|
|
2290
2290
|
}
|
|
2291
2291
|
|
|
2292
|
+
/**
|
|
2293
|
+
* Convert an LDAP Distinguished Name (DN) string to a human-readable path.
|
|
2294
|
+
*
|
|
2295
|
+
* @example
|
|
2296
|
+
* "OU=Engineering,OU=India,DC=company,DC=com"
|
|
2297
|
+
* → "Engineering / India (company.com)"
|
|
2298
|
+
*
|
|
2299
|
+
* "CN=John Smith,OU=Admins,OU=Engineering,DC=company,DC=com"
|
|
2300
|
+
* → "John Smith / Admins / Engineering (company.com)"
|
|
2301
|
+
*
|
|
2302
|
+
* "OU=R\\,D,OU=Teams,DC=example,DC=org"
|
|
2303
|
+
* → "R,D / Teams (example.org)"
|
|
2304
|
+
*/
|
|
2305
|
+
function dnToHumanReadable(dn) {
|
|
2306
|
+
if (!/^\s*\S/.test(dn)) {
|
|
2307
|
+
return '';
|
|
2308
|
+
}
|
|
2309
|
+
const pathParts = [];
|
|
2310
|
+
const domainParts = [];
|
|
2311
|
+
for (const match of dn.matchAll(/(?:^|(?<!\\),)\s*(CN|OU|DC)=((?:\\.|[^,])+)/g)) {
|
|
2312
|
+
const key = match[1];
|
|
2313
|
+
const value = match[2]
|
|
2314
|
+
.trim()
|
|
2315
|
+
.replace(/\\([,\\#+<>;"=])/g, '$1');
|
|
2316
|
+
if (/^(?:CN|OU)$/.test(key)) {
|
|
2317
|
+
pathParts.push(value);
|
|
2318
|
+
}
|
|
2319
|
+
else if (/^DC$/.test(key)) {
|
|
2320
|
+
domainParts.push(value);
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
const path = pathParts.join(' / ');
|
|
2324
|
+
const domain = domainParts.join('.');
|
|
2325
|
+
return path && domain
|
|
2326
|
+
? `${path} (${domain})`
|
|
2327
|
+
: path || domain || dn;
|
|
2328
|
+
}
|
|
2329
|
+
/**
|
|
2330
|
+
* Cell formatter that converts LDAP Distinguished Name (DN) strings
|
|
2331
|
+
* into human-readable OU paths with optional domain suffix.
|
|
2332
|
+
*
|
|
2333
|
+
* @example
|
|
2334
|
+
* // In column config:
|
|
2335
|
+
* formatter: new OUFormatter()
|
|
2336
|
+
*
|
|
2337
|
+
* // With options:
|
|
2338
|
+
* formatter: new OUFormatter({ separator: ' > ', showDomain: false })
|
|
2339
|
+
*
|
|
2340
|
+
* // Handles arrays from multiselect:
|
|
2341
|
+
* // ['OU=Eng,DC=co,DC=com', 'OU=HR,DC=co,DC=com'] → "Eng (co.com), HR (co.com)"
|
|
2342
|
+
*/
|
|
2343
|
+
class OUFormatter {
|
|
2344
|
+
constructor(options) {
|
|
2345
|
+
this.options = options;
|
|
2346
|
+
}
|
|
2347
|
+
format(value) {
|
|
2348
|
+
if (Array.isArray(value)) {
|
|
2349
|
+
return value
|
|
2350
|
+
.map(v => this.formatSingle(v))
|
|
2351
|
+
.filter(v => !!v)
|
|
2352
|
+
.join(this.options?.arraySeparator ?? ', ');
|
|
2353
|
+
}
|
|
2354
|
+
return this.formatSingle(value);
|
|
2355
|
+
}
|
|
2356
|
+
formatSingle(value) {
|
|
2357
|
+
if (value === null || value === undefined || typeof value !== 'string' || !/^\s*\S/.test(value)) {
|
|
2358
|
+
return this.options?.emptyText ?? '';
|
|
2359
|
+
}
|
|
2360
|
+
const separator = this.options?.separator ?? ' / ';
|
|
2361
|
+
const showDomain = this.options?.showDomain !== false;
|
|
2362
|
+
const pathParts = [];
|
|
2363
|
+
const domainParts = [];
|
|
2364
|
+
for (const match of value.matchAll(/(?:^|(?<!\\),)\s*(CN|OU|DC)=((?:\\.|[^,])+)/g)) {
|
|
2365
|
+
const key = match[1];
|
|
2366
|
+
const val = match[2]
|
|
2367
|
+
.trim()
|
|
2368
|
+
.replace(/\\([,\\#+<>;"=])/g, '$1');
|
|
2369
|
+
if (/^(?:CN|OU)$/.test(key)) {
|
|
2370
|
+
pathParts.push(val);
|
|
2371
|
+
}
|
|
2372
|
+
else if (/^DC$/.test(key)) {
|
|
2373
|
+
domainParts.push(val);
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
const path = pathParts.join(separator);
|
|
2377
|
+
const domain = domainParts.join('.');
|
|
2378
|
+
if (path && domain && showDomain)
|
|
2379
|
+
return `${path} (${domain})`;
|
|
2380
|
+
if (path)
|
|
2381
|
+
return path;
|
|
2382
|
+
if (domain && showDomain)
|
|
2383
|
+
return domain;
|
|
2384
|
+
return value;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
const BUILTIN_FORMATTERS = {
|
|
2389
|
+
ouFormatter: () => new OUFormatter(),
|
|
2390
|
+
};
|
|
2391
|
+
const customFormatters = {};
|
|
2392
|
+
/**
|
|
2393
|
+
* Resolve a formatter by name. Looks up custom formatters first, then built-in.
|
|
2394
|
+
* Returns undefined if the name is not registered.
|
|
2395
|
+
*/
|
|
2396
|
+
function resolveFormatter(name) {
|
|
2397
|
+
const factory = customFormatters[name] ?? BUILTIN_FORMATTERS[name];
|
|
2398
|
+
return factory ? factory() : undefined;
|
|
2399
|
+
}
|
|
2400
|
+
/**
|
|
2401
|
+
* Register a custom formatter so it can be referenced by string name
|
|
2402
|
+
* in column configs (e.g. `formatter: 'myFormatter'`).
|
|
2403
|
+
*/
|
|
2404
|
+
function registerFormatter(name, factory) {
|
|
2405
|
+
customFormatters[name] = factory;
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2292
2408
|
/**
|
|
2293
2409
|
* Cell class - represents individual cell instances
|
|
2294
2410
|
* Combines ColumnConfig (Flyweight) with CellState (unique per instance)
|
|
@@ -2353,17 +2469,22 @@ class Cell {
|
|
|
2353
2469
|
* Render cell value as formatted string (delegates to formatter strategy)
|
|
2354
2470
|
*/
|
|
2355
2471
|
render() {
|
|
2356
|
-
|
|
2472
|
+
let formatter = this.columnConfig.formatter;
|
|
2473
|
+
if (!formatter) {
|
|
2357
2474
|
return String(this.state.value ?? '');
|
|
2358
2475
|
}
|
|
2359
|
-
if (
|
|
2360
|
-
|
|
2476
|
+
if (typeof formatter === 'string') {
|
|
2477
|
+
formatter = resolveFormatter(formatter);
|
|
2478
|
+
if (!formatter) {
|
|
2479
|
+
return String(this.state.value ?? '');
|
|
2480
|
+
}
|
|
2361
2481
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2482
|
+
if (formatter.formatWithContext) {
|
|
2483
|
+
return formatter.formatWithContext(this.state.value, this.rowData, this.columnConfig.key);
|
|
2484
|
+
}
|
|
2485
|
+
if (formatter.format) {
|
|
2486
|
+
return formatter.format(this.state.value);
|
|
2365
2487
|
}
|
|
2366
|
-
// Fallback if formatter exists but has no methods
|
|
2367
2488
|
return String(this.state.value ?? '');
|
|
2368
2489
|
}
|
|
2369
2490
|
/**
|
|
@@ -2816,7 +2937,9 @@ class BaseColumnConfig {
|
|
|
2816
2937
|
this.key = merged.key;
|
|
2817
2938
|
this.header = merged.header;
|
|
2818
2939
|
this.dataType = merged.dataType;
|
|
2819
|
-
this.formatter = merged.formatter
|
|
2940
|
+
this.formatter = typeof merged.formatter === 'string'
|
|
2941
|
+
? resolveFormatter(merged.formatter)
|
|
2942
|
+
: merged.formatter;
|
|
2820
2943
|
this.validator = merged.validator;
|
|
2821
2944
|
this.editor = merged.editor;
|
|
2822
2945
|
this.parser = merged.parser;
|
|
@@ -2977,11 +3100,15 @@ class BaseColumnConfig {
|
|
|
2977
3100
|
* Format value for display (can be overridden)
|
|
2978
3101
|
*/
|
|
2979
3102
|
formatValue(value, rowData) {
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
3103
|
+
let formatter = this.formatter;
|
|
3104
|
+
if (typeof formatter === 'string') {
|
|
3105
|
+
formatter = resolveFormatter(formatter);
|
|
3106
|
+
}
|
|
3107
|
+
if (formatter) {
|
|
3108
|
+
if (formatter.formatWithContext && rowData) {
|
|
3109
|
+
return formatter.formatWithContext(value, rowData, this.key);
|
|
2983
3110
|
}
|
|
2984
|
-
return
|
|
3111
|
+
return formatter.format(value);
|
|
2985
3112
|
}
|
|
2986
3113
|
return String(value ?? '');
|
|
2987
3114
|
}
|
|
@@ -4781,11 +4908,13 @@ function injectCodeEditorStyles() {
|
|
|
4781
4908
|
const style = document.createElement('style');
|
|
4782
4909
|
style.id = styleId;
|
|
4783
4910
|
style.textContent = `
|
|
4784
|
-
/* Nile Code Editor cell styling */
|
|
4911
|
+
/* Nile Code Editor cell styling - constrained to cell height */
|
|
4785
4912
|
nile-code-editor.st-cell-editor {
|
|
4786
4913
|
display: block;
|
|
4787
4914
|
width: 100%;
|
|
4788
4915
|
height: 100%;
|
|
4916
|
+
max-height: 32px;
|
|
4917
|
+
overflow: hidden;
|
|
4789
4918
|
font-size: inherit !important;
|
|
4790
4919
|
font-family: inherit !important;
|
|
4791
4920
|
line-height: inherit !important;
|
|
@@ -4793,19 +4922,31 @@ function injectCodeEditorStyles() {
|
|
|
4793
4922
|
nile-code-editor.st-cell-editor::part(code-editor-base) {
|
|
4794
4923
|
border: none !important;
|
|
4795
4924
|
min-height: 100% !important;
|
|
4925
|
+
max-height: 32px !important;
|
|
4796
4926
|
background: transparent !important;
|
|
4797
4927
|
font-size: inherit !important;
|
|
4798
4928
|
font-family: inherit !important;
|
|
4799
4929
|
line-height: inherit !important;
|
|
4930
|
+
overflow: hidden !important;
|
|
4800
4931
|
}
|
|
4801
4932
|
/* Ensure proper sizing within table cell */
|
|
4802
4933
|
.st-nile-code-editor {
|
|
4803
4934
|
width: 100%;
|
|
4804
4935
|
height: 100%;
|
|
4936
|
+
max-height: 32px;
|
|
4805
4937
|
min-height: 28px;
|
|
4806
4938
|
font-size: inherit !important;
|
|
4939
|
+
overflow: hidden;
|
|
4940
|
+
}
|
|
4941
|
+
/* CodeMirror content should inherit font size and be constrained */
|
|
4942
|
+
nile-code-editor.st-cell-editor .cm-editor {
|
|
4943
|
+
max-height: 32px !important;
|
|
4944
|
+
overflow: hidden !important;
|
|
4945
|
+
}
|
|
4946
|
+
nile-code-editor.st-cell-editor .cm-scroller {
|
|
4947
|
+
max-height: 32px !important;
|
|
4948
|
+
overflow: hidden !important;
|
|
4807
4949
|
}
|
|
4808
|
-
/* CodeMirror content should inherit font size */
|
|
4809
4950
|
nile-code-editor.st-cell-editor .cm-content,
|
|
4810
4951
|
nile-code-editor.st-cell-editor .cm-line {
|
|
4811
4952
|
font-size: inherit !important;
|
|
@@ -4818,12 +4959,15 @@ function injectCodeEditorStyles() {
|
|
|
4818
4959
|
align-items: center;
|
|
4819
4960
|
width: 100%;
|
|
4820
4961
|
height: 100%;
|
|
4962
|
+
max-height: 32px;
|
|
4821
4963
|
gap: 4px;
|
|
4822
4964
|
}
|
|
4823
4965
|
.st-code-editor-wrapper .st-code-editor-input {
|
|
4824
4966
|
flex: 1;
|
|
4825
4967
|
min-width: 0;
|
|
4826
4968
|
height: 100%;
|
|
4969
|
+
max-height: 32px;
|
|
4970
|
+
overflow: hidden;
|
|
4827
4971
|
}
|
|
4828
4972
|
.st-code-editor-wrapper .st-expand-button {
|
|
4829
4973
|
display: flex;
|
|
@@ -4844,13 +4988,22 @@ function injectCodeEditorStyles() {
|
|
|
4844
4988
|
background: var(--nile-color-neutral-100, #f3f4f6);
|
|
4845
4989
|
color: var(--nile-color-neutral-700, #374151);
|
|
4846
4990
|
}
|
|
4847
|
-
/* Dialog code editor styling */
|
|
4991
|
+
/* Dialog code editor styling - fixed header/footer, scrollable content */
|
|
4848
4992
|
.st-code-editor-dialog::part(panel) {
|
|
4849
4993
|
max-height: var(--max-height, 80vh) !important;
|
|
4850
4994
|
overflow: hidden !important;
|
|
4995
|
+
display: flex !important;
|
|
4996
|
+
flex-direction: column !important;
|
|
4997
|
+
}
|
|
4998
|
+
.st-code-editor-dialog::part(header) {
|
|
4999
|
+
flex-shrink: 0 !important;
|
|
4851
5000
|
}
|
|
4852
5001
|
.st-code-editor-dialog::part(body) {
|
|
4853
|
-
overflow:
|
|
5002
|
+
overflow: hidden !important;
|
|
5003
|
+
flex: 1 !important;
|
|
5004
|
+
display: flex !important;
|
|
5005
|
+
flex-direction: column !important;
|
|
5006
|
+
padding: 0 !important;
|
|
4854
5007
|
}
|
|
4855
5008
|
.st-code-editor-dialog nile-code-editor {
|
|
4856
5009
|
width: 100%;
|
|
@@ -4859,14 +5012,6 @@ function injectCodeEditorStyles() {
|
|
|
4859
5012
|
.st-code-editor-dialog nile-code-editor::part(code-editor-base) {
|
|
4860
5013
|
border: 1px solid var(--nile-color-neutral-200, #e5e7eb) !important;
|
|
4861
5014
|
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
5015
|
}
|
|
4871
5016
|
`;
|
|
4872
5017
|
document.head.appendChild(style);
|
|
@@ -4883,6 +5028,10 @@ class NileCodeEditor {
|
|
|
4883
5028
|
this.dialogOpen = false;
|
|
4884
5029
|
this.expandButtonClicked = false;
|
|
4885
5030
|
this.trackedValue = null;
|
|
5031
|
+
this.syncingFromDialog = false; // Flag to prevent inline editor from overwriting multiline content
|
|
5032
|
+
this.userEditedInline = false; // Flag to track if user has typed in inline editor
|
|
5033
|
+
this.dialogOriginalValue = ''; // Store original value when dialog opens
|
|
5034
|
+
this.dialogCurrentValue = ''; // Track current value in dialog
|
|
4886
5035
|
}
|
|
4887
5036
|
edit(context) {
|
|
4888
5037
|
if (!context.container) {
|
|
@@ -4890,7 +5039,10 @@ class NileCodeEditor {
|
|
|
4890
5039
|
return;
|
|
4891
5040
|
}
|
|
4892
5041
|
this.context = context;
|
|
4893
|
-
|
|
5042
|
+
// Initialize tracked value from context
|
|
5043
|
+
this.trackedValue = String(context.value ?? '');
|
|
5044
|
+
this.syncingFromDialog = false;
|
|
5045
|
+
this.userEditedInline = false;
|
|
4894
5046
|
// Inject global styles once
|
|
4895
5047
|
injectCodeEditorStyles();
|
|
4896
5048
|
// Check if we should show expand button (default: true)
|
|
@@ -4910,6 +5062,11 @@ class NileCodeEditor {
|
|
|
4910
5062
|
this.editor.style.height = '100%';
|
|
4911
5063
|
this.editor.style.boxSizing = 'border-box';
|
|
4912
5064
|
this.editor.noborder = this.options?.noborder !== false;
|
|
5065
|
+
// Enable multiline by default for inline editor to support paste and multiline content
|
|
5066
|
+
this.editor.multiline = this.options?.multiline !== false;
|
|
5067
|
+
this.editor.hasScroller = true;
|
|
5068
|
+
// No line numbers for inline editor
|
|
5069
|
+
this.editor.lineNumbers = false;
|
|
4913
5070
|
editorContainer.appendChild(this.editor);
|
|
4914
5071
|
this.wrapper.appendChild(editorContainer);
|
|
4915
5072
|
// Create expand button
|
|
@@ -4943,6 +5100,11 @@ class NileCodeEditor {
|
|
|
4943
5100
|
this.editor.style.height = '100%';
|
|
4944
5101
|
this.editor.style.boxSizing = 'border-box';
|
|
4945
5102
|
this.editor.noborder = this.options?.noborder !== false;
|
|
5103
|
+
// Enable multiline by default for inline editor to support paste and multiline content
|
|
5104
|
+
this.editor.multiline = this.options?.multiline !== false;
|
|
5105
|
+
this.editor.hasScroller = true;
|
|
5106
|
+
// No line numbers for inline editor
|
|
5107
|
+
this.editor.lineNumbers = false;
|
|
4946
5108
|
// Clear container and append editor
|
|
4947
5109
|
context.container.innerHTML = '';
|
|
4948
5110
|
context.container.appendChild(this.editor);
|
|
@@ -4993,8 +5155,17 @@ class NileCodeEditor {
|
|
|
4993
5155
|
/**
|
|
4994
5156
|
* Read the live value directly from CodeMirror's internal state,
|
|
4995
5157
|
* bypassing debounced nile-change events and the possibly-stale .value property.
|
|
5158
|
+
*
|
|
5159
|
+
* Priority order:
|
|
5160
|
+
* 1. trackedValue - always up to date from change events
|
|
5161
|
+
* 2. CodeMirror internal state - for real-time reading
|
|
5162
|
+
* 3. editor.value property - fallback
|
|
4996
5163
|
*/
|
|
4997
5164
|
getLiveEditorValue() {
|
|
5165
|
+
// Use tracked value if available (updated by change events)
|
|
5166
|
+
if (this.trackedValue !== null) {
|
|
5167
|
+
return this.trackedValue;
|
|
5168
|
+
}
|
|
4998
5169
|
if (!this.editor)
|
|
4999
5170
|
return '';
|
|
5000
5171
|
try {
|
|
@@ -5009,8 +5180,6 @@ class NileCodeEditor {
|
|
|
5009
5180
|
catch {
|
|
5010
5181
|
// Fall through to other methods
|
|
5011
5182
|
}
|
|
5012
|
-
if (this.trackedValue !== null)
|
|
5013
|
-
return this.trackedValue;
|
|
5014
5183
|
return this.editor.value ?? '';
|
|
5015
5184
|
}
|
|
5016
5185
|
/**
|
|
@@ -5021,6 +5190,8 @@ class NileCodeEditor {
|
|
|
5021
5190
|
return;
|
|
5022
5191
|
this.dialogOpen = true;
|
|
5023
5192
|
this.expandButtonClicked = false; // Reset flag now that dialog is opening
|
|
5193
|
+
// Store original value for cancel functionality
|
|
5194
|
+
this.dialogOriginalValue = this.getLiveEditorValue();
|
|
5024
5195
|
// Create dialog with configurable dimensions
|
|
5025
5196
|
const dialogWidth = this.options?.dialogWidth || '600px';
|
|
5026
5197
|
const dialogMaxHeight = this.options?.dialogMaxHeight || '80vh';
|
|
@@ -5031,26 +5202,26 @@ class NileCodeEditor {
|
|
|
5031
5202
|
this.dialog.label = dialogTitle;
|
|
5032
5203
|
this.dialog.style.setProperty('--width', dialogWidth);
|
|
5033
5204
|
this.dialog.style.setProperty('--max-height', dialogMaxHeight);
|
|
5034
|
-
// Create dialog content
|
|
5205
|
+
// Create dialog content wrapper - flex column to handle fixed header/footer
|
|
5206
|
+
const contentWrapper = document.createElement('div');
|
|
5207
|
+
contentWrapper.style.display = 'flex';
|
|
5208
|
+
contentWrapper.style.flexDirection = 'column';
|
|
5209
|
+
contentWrapper.style.height = `calc(${dialogMaxHeight} - 60px)`; // Account for dialog header
|
|
5210
|
+
contentWrapper.style.maxHeight = `calc(${dialogMaxHeight} - 60px)`;
|
|
5211
|
+
// Create editor content area - this is the scrollable part
|
|
5035
5212
|
const content = document.createElement('div');
|
|
5036
5213
|
content.style.padding = '16px';
|
|
5037
|
-
content.style.
|
|
5214
|
+
content.style.paddingBottom = '8px';
|
|
5215
|
+
content.style.flex = '1';
|
|
5038
5216
|
content.style.overflow = 'auto';
|
|
5217
|
+
content.style.minHeight = '0'; // Important for flex shrinking
|
|
5039
5218
|
// Create full editor
|
|
5040
5219
|
this.dialogEditor = document.createElement('nile-code-editor');
|
|
5041
|
-
|
|
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);
|
|
5220
|
+
this.dialogEditor.value = this.dialogOriginalValue;
|
|
5046
5221
|
this.dialogEditor.multiline = true;
|
|
5047
5222
|
this.dialogEditor.lineNumbersMultiline = true;
|
|
5048
5223
|
this.dialogEditor.hasScroller = true;
|
|
5049
|
-
|
|
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})`);
|
|
5224
|
+
this.dialogEditor.style.minHeight = dialogEditorHeight;
|
|
5054
5225
|
// Apply same options to dialog editor
|
|
5055
5226
|
if (this.options?.language) {
|
|
5056
5227
|
this.dialogEditor.language = this.options.language;
|
|
@@ -5077,38 +5248,44 @@ class NileCodeEditor {
|
|
|
5077
5248
|
this.dialogEditor.customThemeCSS = this.options.customThemeCSS;
|
|
5078
5249
|
}
|
|
5079
5250
|
this.dialogEditor.expandable = false;
|
|
5080
|
-
//
|
|
5251
|
+
// Initialize dialog current value
|
|
5252
|
+
this.dialogCurrentValue = this.dialogOriginalValue;
|
|
5253
|
+
// Track changes in dialog editor
|
|
5081
5254
|
this.dialogEditor.addEventListener('nile-change', (e) => {
|
|
5082
|
-
|
|
5083
|
-
this.trackedValue = dialogValue;
|
|
5084
|
-
if (this.editor) {
|
|
5085
|
-
this.editor.value = dialogValue;
|
|
5086
|
-
}
|
|
5087
|
-
if (this.context) {
|
|
5088
|
-
this.context.onChange(dialogValue);
|
|
5089
|
-
}
|
|
5255
|
+
this.dialogCurrentValue = e.detail?.value ?? '';
|
|
5090
5256
|
});
|
|
5091
5257
|
content.appendChild(this.dialogEditor);
|
|
5092
|
-
|
|
5093
|
-
//
|
|
5258
|
+
contentWrapper.appendChild(content);
|
|
5259
|
+
// Create footer with Ok button - fixed at bottom
|
|
5260
|
+
const footer = document.createElement('div');
|
|
5261
|
+
footer.style.display = 'flex';
|
|
5262
|
+
footer.style.justifyContent = 'flex-end';
|
|
5263
|
+
footer.style.padding = '12px 16px';
|
|
5264
|
+
footer.style.borderTop = '1px solid var(--nile-color-neutral-200, #e5e7eb)';
|
|
5265
|
+
footer.style.gap = '8px';
|
|
5266
|
+
footer.style.flexShrink = '0'; // Prevent footer from shrinking
|
|
5267
|
+
footer.style.backgroundColor = 'var(--nile-color-neutral-0, #ffffff)';
|
|
5268
|
+
const okButton = document.createElement('nile-button');
|
|
5269
|
+
okButton.setAttribute('variant', 'primary');
|
|
5270
|
+
okButton.textContent = 'Ok';
|
|
5271
|
+
okButton.addEventListener('click', () => {
|
|
5272
|
+
this.applyDialogChanges();
|
|
5273
|
+
});
|
|
5274
|
+
footer.appendChild(okButton);
|
|
5275
|
+
contentWrapper.appendChild(footer);
|
|
5276
|
+
this.dialog.appendChild(contentWrapper);
|
|
5277
|
+
// Handle dialog close events (clicking X button - cancel changes)
|
|
5094
5278
|
this.dialog.addEventListener('nile-request-close', (e) => {
|
|
5095
|
-
|
|
5096
|
-
//
|
|
5097
|
-
|
|
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
|
-
}
|
|
5279
|
+
e.preventDefault();
|
|
5280
|
+
// X button or overlay click - cancel changes
|
|
5281
|
+
this.cancelDialogChanges();
|
|
5105
5282
|
});
|
|
5106
|
-
// Handle Escape key in dialog -
|
|
5283
|
+
// Handle Escape key in dialog - cancel changes
|
|
5107
5284
|
this.dialog.addEventListener('keydown', (e) => {
|
|
5108
5285
|
if (e.key === 'Escape') {
|
|
5109
5286
|
e.preventDefault();
|
|
5110
5287
|
e.stopPropagation();
|
|
5111
|
-
this.
|
|
5288
|
+
this.cancelDialogChanges();
|
|
5112
5289
|
}
|
|
5113
5290
|
});
|
|
5114
5291
|
// Append to body and show
|
|
@@ -5125,34 +5302,113 @@ class NileCodeEditor {
|
|
|
5125
5302
|
}, 0);
|
|
5126
5303
|
}
|
|
5127
5304
|
/**
|
|
5128
|
-
*
|
|
5305
|
+
* Get the current value from the dialog editor
|
|
5306
|
+
*/
|
|
5307
|
+
getDialogEditorValue() {
|
|
5308
|
+
// Use tracked value from change events (most reliable)
|
|
5309
|
+
if (this.dialogCurrentValue) {
|
|
5310
|
+
return this.dialogCurrentValue.replace(/\n+$/, '');
|
|
5311
|
+
}
|
|
5312
|
+
if (!this.dialogEditor)
|
|
5313
|
+
return this.dialogOriginalValue;
|
|
5314
|
+
// Try to get value from CodeMirror's internal state
|
|
5315
|
+
try {
|
|
5316
|
+
const shadowRoot = this.dialogEditor.shadowRoot;
|
|
5317
|
+
if (shadowRoot) {
|
|
5318
|
+
const cmEditor = shadowRoot.querySelector('.cm-editor');
|
|
5319
|
+
if (cmEditor?.cmView?.view) {
|
|
5320
|
+
const value = cmEditor.cmView.view.state.doc.toString();
|
|
5321
|
+
return value.replace(/\n+$/, '');
|
|
5322
|
+
}
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
catch {
|
|
5326
|
+
// Fall through to other methods
|
|
5327
|
+
}
|
|
5328
|
+
// Fallback to value property
|
|
5329
|
+
const value = this.dialogEditor.value;
|
|
5330
|
+
return (value ?? '').replace(/\n+$/, '');
|
|
5331
|
+
}
|
|
5332
|
+
/**
|
|
5333
|
+
* Apply changes from dialog and close it
|
|
5129
5334
|
*/
|
|
5130
|
-
|
|
5335
|
+
applyDialogChanges() {
|
|
5131
5336
|
if (!this.dialogOpen)
|
|
5132
5337
|
return;
|
|
5133
|
-
//
|
|
5338
|
+
// Get the value from dialog editor - try multiple sources
|
|
5339
|
+
let dialogValue = this.dialogCurrentValue;
|
|
5340
|
+
// If no tracked value, try reading directly from dialog editor
|
|
5341
|
+
if (!dialogValue && this.dialogEditor) {
|
|
5342
|
+
try {
|
|
5343
|
+
const shadowRoot = this.dialogEditor.shadowRoot;
|
|
5344
|
+
if (shadowRoot) {
|
|
5345
|
+
const cmEditor = shadowRoot.querySelector('.cm-editor');
|
|
5346
|
+
if (cmEditor?.cmView?.view) {
|
|
5347
|
+
dialogValue = cmEditor.cmView.view.state.doc.toString();
|
|
5348
|
+
}
|
|
5349
|
+
}
|
|
5350
|
+
}
|
|
5351
|
+
catch {
|
|
5352
|
+
// Fall through
|
|
5353
|
+
}
|
|
5354
|
+
// Fallback to value property
|
|
5355
|
+
if (!dialogValue) {
|
|
5356
|
+
dialogValue = this.dialogEditor.value ?? '';
|
|
5357
|
+
}
|
|
5358
|
+
}
|
|
5359
|
+
// Strip trailing newlines
|
|
5360
|
+
dialogValue = (dialogValue || '').replace(/\n+$/, '');
|
|
5361
|
+
// Update tracked value and inline editor
|
|
5362
|
+
this.trackedValue = dialogValue;
|
|
5363
|
+
this.userEditedInline = false;
|
|
5364
|
+
this.syncingFromDialog = true;
|
|
5365
|
+
if (this.editor) {
|
|
5366
|
+
this.editor.value = dialogValue;
|
|
5367
|
+
}
|
|
5368
|
+
setTimeout(() => {
|
|
5369
|
+
this.syncingFromDialog = false;
|
|
5370
|
+
}, 0);
|
|
5371
|
+
// Notify context of the change
|
|
5372
|
+
if (this.context) {
|
|
5373
|
+
this.context.onChange(dialogValue);
|
|
5374
|
+
}
|
|
5375
|
+
// Close dialog
|
|
5376
|
+
this.closeDialogUI();
|
|
5377
|
+
// Refocus the cell editor to stay in edit mode
|
|
5378
|
+
setTimeout(() => {
|
|
5379
|
+
this.focusEditor();
|
|
5380
|
+
}, 50);
|
|
5381
|
+
}
|
|
5382
|
+
/**
|
|
5383
|
+
* Cancel dialog changes and revert to original value
|
|
5384
|
+
*/
|
|
5385
|
+
cancelDialogChanges() {
|
|
5386
|
+
if (!this.dialogOpen)
|
|
5387
|
+
return;
|
|
5388
|
+
// Revert to original value (don't change anything)
|
|
5389
|
+
// trackedValue and inline editor remain as they were before dialog opened
|
|
5390
|
+
// Close dialog
|
|
5391
|
+
this.closeDialogUI();
|
|
5392
|
+
// Refocus the cell editor to stay in edit mode
|
|
5393
|
+
setTimeout(() => {
|
|
5394
|
+
this.focusEditor();
|
|
5395
|
+
}, 50);
|
|
5396
|
+
}
|
|
5397
|
+
/**
|
|
5398
|
+
* Close and remove the dialog UI
|
|
5399
|
+
*/
|
|
5400
|
+
closeDialogUI() {
|
|
5134
5401
|
this.dialogOpen = false;
|
|
5135
|
-
|
|
5402
|
+
this.dialogCurrentValue = '';
|
|
5136
5403
|
if (this.dialog) {
|
|
5137
5404
|
this.dialog.open = false;
|
|
5138
5405
|
const dialogRef = this.dialog;
|
|
5139
|
-
const dialogEditorRef = this.dialogEditor;
|
|
5140
5406
|
this.dialog = undefined;
|
|
5141
5407
|
this.dialogEditor = undefined;
|
|
5142
5408
|
// Remove from DOM after animation
|
|
5143
5409
|
setTimeout(() => {
|
|
5144
5410
|
dialogRef?.remove();
|
|
5145
5411
|
}, 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
5412
|
}
|
|
5157
5413
|
}
|
|
5158
5414
|
/**
|
|
@@ -5314,6 +5570,11 @@ class NileCodeEditor {
|
|
|
5314
5570
|
const changeHandler = (e) => {
|
|
5315
5571
|
const customEvent = e;
|
|
5316
5572
|
const newValue = customEvent.detail?.value ?? '';
|
|
5573
|
+
// Don't process if we're syncing from dialog (prevents feedback loop)
|
|
5574
|
+
if (this.syncingFromDialog) {
|
|
5575
|
+
return;
|
|
5576
|
+
}
|
|
5577
|
+
// Update tracked value
|
|
5317
5578
|
this.trackedValue = newValue;
|
|
5318
5579
|
context.onChange(newValue);
|
|
5319
5580
|
};
|
|
@@ -5379,6 +5640,11 @@ class NileCodeEditor {
|
|
|
5379
5640
|
this.expandButton = undefined;
|
|
5380
5641
|
this.context = undefined;
|
|
5381
5642
|
this.expandButtonClicked = false;
|
|
5643
|
+
this.syncingFromDialog = false;
|
|
5644
|
+
this.trackedValue = null;
|
|
5645
|
+
this.userEditedInline = false;
|
|
5646
|
+
this.dialogOriginalValue = '';
|
|
5647
|
+
this.dialogCurrentValue = '';
|
|
5382
5648
|
}
|
|
5383
5649
|
focus() {
|
|
5384
5650
|
this.editor?.focus();
|
|
@@ -8687,7 +8953,7 @@ class StTableComponent {
|
|
|
8687
8953
|
const columns = this.getActiveColumns();
|
|
8688
8954
|
const oldGrid = this.internalCellGrid;
|
|
8689
8955
|
this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map((column, colIndex) => {
|
|
8690
|
-
const newCell =
|
|
8956
|
+
const newCell = column.createCell(rowData, rowIndex);
|
|
8691
8957
|
const oldCell = oldGrid?.[rowIndex]?.[colIndex];
|
|
8692
8958
|
if (oldCell && oldCell.getColumnConfig().key === column.key) {
|
|
8693
8959
|
oldCell.setReplacement(newCell);
|
|
@@ -13084,5 +13350,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
13084
13350
|
* Generated bundle index. Do not edit.
|
|
13085
13351
|
*/
|
|
13086
13352
|
|
|
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 };
|
|
13353
|
+
export { ArrayFormatter, AutosaveService, BaseColumnConfig, BooleanEditor, BooleanFormatter, BuilderPreviewComponent, BuilderToolbarComponent, Cell, CellAlignment, CellDataType, CellLifecycleState, CellVerticalAlignment, ChainValidator, ClickOutsideDirective, ColumnConfigFactory, ColumnEditorComponent, ColumnListComponent, Columns, CurrencyFormatter, DEFAULT_AUTOSAVE_CONFIG, DEFAULT_COLUMN_CONFIG, DEFAULT_TABLE_CONFIG, DateEditor, DateFormatter, DateRangeValidator, DefaultFormatter, DefinitionBuilderComponent, DefinitionBuilderModule, DefinitionBuilderService, DefinitionExportService, DefinitionImportService, EditMode, EmailValidator, FilterOperator, FunctionFormatter, FunctionValidator, JsonSchemaValidatorService, LengthValidator, NavigationDirection, NavigationKey, NileAutoCompleteEditor, NileCalendarEditor, NileCodeEditor, NileDatePickerEditor, NileInputEditor, NileSelectEditor, NumberEditor, NumberFormatter, OUFormatter, PatternValidators, PercentageFormatter, RangeValidator, RegexValidator, RequiredValidator, RowValidationService, SampleDataGeneratorService, SelectEditor, SharedTableComponentsModule, SheetState, SimpleColumnConfig, SmartTableModule, SortDirection, StAddColumnButtonComponent, StCellComponent, StColumnEditorModalComponent, StColumnFilterComponent, StColumnMenuDropdownComponent, StColumnResizeDirective, StColumnVisibilityComponent, StHeaderComponent, StKeyboardNavigationDirective, StPaginationComponent, StRowActionsDropdownComponent, StSheetActionsComponent, StSheetComponent, StTableActionsComponent, StTableComponent, StWorkbookComponent, StringFormatter, TableConfigEditorComponent, TableState, TableZIndex, TemplateFormatter, TextAreaEditor, TextEditor, UrlValidator, ValidationLoggerService, VirtualScrollService, WorkbookState, canEdit, createCellState, createMemento, dnToHumanReadable, isCellValid, isDisplayMode, isNullOrUndefined, isValidDate, isValidationSuccess, mergeTableConfig, registerFormatter, resolveFormatter, restoreFromMemento };
|
|
13088
13354
|
//# sourceMappingURL=aquera-ngx-smart-table.mjs.map
|