@aquera/ngx-smart-table 0.0.17-patch-0.4 → 0.0.17-patch-0.6
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-chip-editor.mjs +293 -0
- package/esm2020/lib/editors/nile-code-editor.mjs +9 -10
- 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 +453 -25
- package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -1
- package/fesm2020/aquera-ngx-smart-table.mjs +442 -23
- package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -1
- package/lib/editors/index.d.ts +1 -0
- package/lib/editors/nile-chip-editor.d.ts +94 -0
- 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
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
if (formatter.formatWithContext) {
|
|
2483
|
+
return formatter.formatWithContext(this.state.value, this.rowData, this.columnConfig.key);
|
|
2361
2484
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
return this.columnConfig.formatter.format(this.state.value);
|
|
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
|
}
|
|
@@ -4763,6 +4890,299 @@ class NileDatePickerEditor {
|
|
|
4763
4890
|
}
|
|
4764
4891
|
}
|
|
4765
4892
|
|
|
4893
|
+
/**
|
|
4894
|
+
* Custom editor using NileChip from @aquera/nile-elements
|
|
4895
|
+
* Renders the chip input in a floating popover below the cell to avoid row height mismatch.
|
|
4896
|
+
*
|
|
4897
|
+
* @see https://nile.aqueralabs.com/1.6.3/chip?theme=enterprise
|
|
4898
|
+
*/
|
|
4899
|
+
let chipStylesInjected = false;
|
|
4900
|
+
function injectChipStyles() {
|
|
4901
|
+
if (chipStylesInjected)
|
|
4902
|
+
return;
|
|
4903
|
+
chipStylesInjected = true;
|
|
4904
|
+
const styleId = 'nile-chip-editor-styles';
|
|
4905
|
+
if (document.getElementById(styleId))
|
|
4906
|
+
return;
|
|
4907
|
+
const style = document.createElement('style');
|
|
4908
|
+
style.id = styleId;
|
|
4909
|
+
style.textContent = `
|
|
4910
|
+
.st-chip-popover {
|
|
4911
|
+
position: fixed;
|
|
4912
|
+
z-index: 10000;
|
|
4913
|
+
background: var(--nile-colors-white-base, #fff);
|
|
4914
|
+
border: 1px solid var(--nile-colors-neutral-200, #e2e8f0);
|
|
4915
|
+
border-radius: 6px;
|
|
4916
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
|
4917
|
+
padding: 8px;
|
|
4918
|
+
box-sizing: border-box;
|
|
4919
|
+
max-height: 200px;
|
|
4920
|
+
overflow-y: auto;
|
|
4921
|
+
}
|
|
4922
|
+
.st-chip-popover nile-chip {
|
|
4923
|
+
width: 100%;
|
|
4924
|
+
}
|
|
4925
|
+
.st-chip-popover nile-chip::part(base) {
|
|
4926
|
+
border: none !important;
|
|
4927
|
+
box-shadow: none !important;
|
|
4928
|
+
min-height: 32px;
|
|
4929
|
+
}
|
|
4930
|
+
.st-chip-popover nile-chip::part(input) {
|
|
4931
|
+
font-size: var(--nile-font-size-small, 13px);
|
|
4932
|
+
}
|
|
4933
|
+
`;
|
|
4934
|
+
document.head.appendChild(style);
|
|
4935
|
+
}
|
|
4936
|
+
/**
|
|
4937
|
+
* Custom editor that uses NileChip (tag input) component.
|
|
4938
|
+
* Renders in a floating popover below the cell to avoid expanding row height.
|
|
4939
|
+
*
|
|
4940
|
+
* Cell value is expected to be `string[]` (array of tag strings).
|
|
4941
|
+
*/
|
|
4942
|
+
class NileChipEditor {
|
|
4943
|
+
constructor(options) {
|
|
4944
|
+
this.options = options;
|
|
4945
|
+
this.acceptsInitialKeypress = false;
|
|
4946
|
+
this.eventListeners = [];
|
|
4947
|
+
this.trackedValues = [];
|
|
4948
|
+
}
|
|
4949
|
+
edit(context) {
|
|
4950
|
+
if (!context.container) {
|
|
4951
|
+
console.warn('NileChipEditor requires a container element');
|
|
4952
|
+
return;
|
|
4953
|
+
}
|
|
4954
|
+
injectChipStyles();
|
|
4955
|
+
this.cellContainer = context.container;
|
|
4956
|
+
// Create the floating popover
|
|
4957
|
+
this.popover = document.createElement('div');
|
|
4958
|
+
this.popover.className = 'st-chip-popover';
|
|
4959
|
+
// Create nile-chip inside the popover
|
|
4960
|
+
this.chip = document.createElement('nile-chip');
|
|
4961
|
+
this.chip.className = 'st-cell-editor st-nile-chip-editor';
|
|
4962
|
+
this.setInitialValue(context.value);
|
|
4963
|
+
this.applyOptions();
|
|
4964
|
+
this.popover.appendChild(this.chip);
|
|
4965
|
+
// Apply custom max-height if provided
|
|
4966
|
+
if (this.options?.popoverMaxHeight) {
|
|
4967
|
+
this.popover.style.maxHeight = `${this.options.popoverMaxHeight}px`;
|
|
4968
|
+
}
|
|
4969
|
+
// Append popover to body and position it
|
|
4970
|
+
document.body.appendChild(this.popover);
|
|
4971
|
+
this.positionPopover();
|
|
4972
|
+
this.setupEventListeners(context);
|
|
4973
|
+
if (this.options?.autoFocus !== false) {
|
|
4974
|
+
setTimeout(() => {
|
|
4975
|
+
try {
|
|
4976
|
+
this.chip?.focus();
|
|
4977
|
+
}
|
|
4978
|
+
catch { /* ignore */ }
|
|
4979
|
+
}, 0);
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
positionPopover() {
|
|
4983
|
+
if (!this.popover || !this.cellContainer)
|
|
4984
|
+
return;
|
|
4985
|
+
const rect = this.cellContainer.getBoundingClientRect();
|
|
4986
|
+
const minWidth = this.options?.popoverMinWidth ?? rect.width;
|
|
4987
|
+
const popoverWidth = Math.max(minWidth, rect.width);
|
|
4988
|
+
this.popover.style.top = `${rect.bottom + 2}px`;
|
|
4989
|
+
this.popover.style.left = `${rect.left}px`;
|
|
4990
|
+
this.popover.style.width = `${popoverWidth}px`;
|
|
4991
|
+
// After rendering, check if it goes off-screen bottom and flip above if needed
|
|
4992
|
+
requestAnimationFrame(() => {
|
|
4993
|
+
if (!this.popover)
|
|
4994
|
+
return;
|
|
4995
|
+
const popRect = this.popover.getBoundingClientRect();
|
|
4996
|
+
if (popRect.bottom > window.innerHeight) {
|
|
4997
|
+
this.popover.style.top = `${rect.top - popRect.height - 2}px`;
|
|
4998
|
+
}
|
|
4999
|
+
});
|
|
5000
|
+
}
|
|
5001
|
+
setInitialValue(value) {
|
|
5002
|
+
if (!this.chip)
|
|
5003
|
+
return;
|
|
5004
|
+
if (Array.isArray(value)) {
|
|
5005
|
+
this.trackedValues = [...value];
|
|
5006
|
+
this.chip.value = this.trackedValues;
|
|
5007
|
+
}
|
|
5008
|
+
else if (typeof value === 'string' && value) {
|
|
5009
|
+
this.trackedValues = [value];
|
|
5010
|
+
this.chip.value = this.trackedValues;
|
|
5011
|
+
}
|
|
5012
|
+
else {
|
|
5013
|
+
this.trackedValues = [];
|
|
5014
|
+
this.chip.value = [];
|
|
5015
|
+
}
|
|
5016
|
+
}
|
|
5017
|
+
applyOptions() {
|
|
5018
|
+
if (!this.chip || !this.options)
|
|
5019
|
+
return;
|
|
5020
|
+
if (this.options.placeholder) {
|
|
5021
|
+
this.chip.placeholder = this.options.placeholder;
|
|
5022
|
+
}
|
|
5023
|
+
if (this.options.label) {
|
|
5024
|
+
this.chip.label = this.options.label;
|
|
5025
|
+
}
|
|
5026
|
+
if (this.options.helpText) {
|
|
5027
|
+
this.chip.helpText = this.options.helpText;
|
|
5028
|
+
}
|
|
5029
|
+
if (this.options.disabled !== undefined) {
|
|
5030
|
+
this.chip.disabled = this.options.disabled;
|
|
5031
|
+
}
|
|
5032
|
+
if (this.options.readonly !== undefined) {
|
|
5033
|
+
this.chip.readonly = this.options.readonly;
|
|
5034
|
+
}
|
|
5035
|
+
if (this.options.acceptUserInput !== undefined) {
|
|
5036
|
+
this.chip.acceptUserInput = this.options.acceptUserInput;
|
|
5037
|
+
}
|
|
5038
|
+
if (this.options.noDuplicates !== undefined) {
|
|
5039
|
+
this.chip.noDuplicates = this.options.noDuplicates;
|
|
5040
|
+
}
|
|
5041
|
+
if (this.options.clearable !== undefined) {
|
|
5042
|
+
this.chip.clearable = this.options.clearable;
|
|
5043
|
+
}
|
|
5044
|
+
if (this.options.noWrap !== undefined) {
|
|
5045
|
+
this.chip.noWrap = this.options.noWrap;
|
|
5046
|
+
}
|
|
5047
|
+
if (this.options.noAutoComplete !== undefined) {
|
|
5048
|
+
this.chip.noAutoComplete = this.options.noAutoComplete;
|
|
5049
|
+
}
|
|
5050
|
+
if (this.options.enableVirtualScroll !== undefined) {
|
|
5051
|
+
this.chip.enableVirtualScroll = this.options.enableVirtualScroll;
|
|
5052
|
+
}
|
|
5053
|
+
if (this.options.openDropdownOnFocus !== undefined) {
|
|
5054
|
+
this.chip.openDropdownOnFocus = this.options.openDropdownOnFocus;
|
|
5055
|
+
}
|
|
5056
|
+
if (this.options.loading !== undefined) {
|
|
5057
|
+
this.chip.loading = this.options.loading;
|
|
5058
|
+
}
|
|
5059
|
+
// Visual states
|
|
5060
|
+
if (this.options.warning !== undefined) {
|
|
5061
|
+
this.chip.warning = this.options.warning;
|
|
5062
|
+
}
|
|
5063
|
+
if (this.options.error !== undefined) {
|
|
5064
|
+
this.chip.error = this.options.error;
|
|
5065
|
+
}
|
|
5066
|
+
if (this.options.success !== undefined) {
|
|
5067
|
+
this.chip.success = this.options.success;
|
|
5068
|
+
}
|
|
5069
|
+
if (this.options.errorMessage) {
|
|
5070
|
+
this.chip.errorMessage = this.options.errorMessage;
|
|
5071
|
+
}
|
|
5072
|
+
if (this.options.errorIndexes) {
|
|
5073
|
+
this.chip.errorIndexes = this.options.errorIndexes;
|
|
5074
|
+
}
|
|
5075
|
+
// Autocomplete options
|
|
5076
|
+
if (this.options.autoCompleteOptions) {
|
|
5077
|
+
const opts = this.options.autoCompleteOptions;
|
|
5078
|
+
const stringOpts = opts.map(o => typeof o === 'string' ? o : (o.label ?? o.value));
|
|
5079
|
+
this.chip.autoCompleteOptions = stringOpts;
|
|
5080
|
+
}
|
|
5081
|
+
if (this.options.filterFunction) {
|
|
5082
|
+
this.chip.filterFunction = this.options.filterFunction;
|
|
5083
|
+
}
|
|
5084
|
+
if (this.options.renderItemFunction) {
|
|
5085
|
+
this.chip.renderItemFunction = this.options.renderItemFunction;
|
|
5086
|
+
}
|
|
5087
|
+
}
|
|
5088
|
+
addListener(element, event, handler, capture) {
|
|
5089
|
+
element.addEventListener(event, handler, capture);
|
|
5090
|
+
this.eventListeners.push({ element, event, handler, capture });
|
|
5091
|
+
}
|
|
5092
|
+
setupEventListeners(context) {
|
|
5093
|
+
if (!this.chip)
|
|
5094
|
+
return;
|
|
5095
|
+
// Track chip changes
|
|
5096
|
+
this.addListener(this.chip, 'nile-chip-change', (e) => {
|
|
5097
|
+
const detail = e.detail;
|
|
5098
|
+
const newValue = Array.isArray(detail?.value) ? [...detail.value] : (this.chip?.value ? [...this.chip.value] : []);
|
|
5099
|
+
this.trackedValues = newValue;
|
|
5100
|
+
context.onChange(newValue);
|
|
5101
|
+
});
|
|
5102
|
+
// Keyboard handling on the chip element
|
|
5103
|
+
this.addListener(this.chip, 'keydown', (e) => {
|
|
5104
|
+
const keyEvent = e;
|
|
5105
|
+
if (keyEvent.key === 'Enter') {
|
|
5106
|
+
keyEvent.stopPropagation();
|
|
5107
|
+
}
|
|
5108
|
+
else if (keyEvent.key === 'Escape') {
|
|
5109
|
+
keyEvent.preventDefault();
|
|
5110
|
+
keyEvent.stopPropagation();
|
|
5111
|
+
context.onCancel();
|
|
5112
|
+
}
|
|
5113
|
+
else if (keyEvent.key === 'Tab') {
|
|
5114
|
+
keyEvent.preventDefault();
|
|
5115
|
+
keyEvent.stopPropagation();
|
|
5116
|
+
context.onSave(this.getCurrentValue());
|
|
5117
|
+
}
|
|
5118
|
+
});
|
|
5119
|
+
// Click-outside: save when clicking anywhere outside the popover
|
|
5120
|
+
let saveTriggered = false;
|
|
5121
|
+
const mousedownHandler = (e) => {
|
|
5122
|
+
if (saveTriggered)
|
|
5123
|
+
return;
|
|
5124
|
+
if (!this.popover)
|
|
5125
|
+
return;
|
|
5126
|
+
const path = e.composedPath();
|
|
5127
|
+
for (const el of path) {
|
|
5128
|
+
if (el === this.popover)
|
|
5129
|
+
return;
|
|
5130
|
+
if (el === this.chip)
|
|
5131
|
+
return;
|
|
5132
|
+
if (el instanceof HTMLElement) {
|
|
5133
|
+
if (el.tagName?.toLowerCase() === 'nile-chip')
|
|
5134
|
+
return;
|
|
5135
|
+
if (el.className && typeof el.className === 'string' && el.className.includes('nile-chip'))
|
|
5136
|
+
return;
|
|
5137
|
+
}
|
|
5138
|
+
}
|
|
5139
|
+
saveTriggered = true;
|
|
5140
|
+
context.onSave(this.getCurrentValue());
|
|
5141
|
+
};
|
|
5142
|
+
document.addEventListener('mousedown', mousedownHandler, true);
|
|
5143
|
+
this._documentMousedownHandler = mousedownHandler;
|
|
5144
|
+
// Reposition on scroll/resize so popover stays aligned with the cell
|
|
5145
|
+
const reposition = () => this.positionPopover();
|
|
5146
|
+
this.addListener(window, 'resize', reposition);
|
|
5147
|
+
this.addListener(window, 'scroll', reposition, true);
|
|
5148
|
+
}
|
|
5149
|
+
destroy() {
|
|
5150
|
+
// Remove document mousedown handler
|
|
5151
|
+
if (this._documentMousedownHandler) {
|
|
5152
|
+
document.removeEventListener('mousedown', this._documentMousedownHandler, true);
|
|
5153
|
+
delete this._documentMousedownHandler;
|
|
5154
|
+
}
|
|
5155
|
+
// Remove all tracked listeners
|
|
5156
|
+
for (const { element, event, handler, capture } of this.eventListeners) {
|
|
5157
|
+
element.removeEventListener(event, handler, capture);
|
|
5158
|
+
}
|
|
5159
|
+
this.eventListeners = [];
|
|
5160
|
+
// Remove the popover from the DOM
|
|
5161
|
+
if (this.popover) {
|
|
5162
|
+
this.popover.remove();
|
|
5163
|
+
this.popover = undefined;
|
|
5164
|
+
}
|
|
5165
|
+
this.chip = undefined;
|
|
5166
|
+
this.cellContainer = undefined;
|
|
5167
|
+
this.trackedValues = [];
|
|
5168
|
+
}
|
|
5169
|
+
focus() {
|
|
5170
|
+
try {
|
|
5171
|
+
this.chip?.focus();
|
|
5172
|
+
}
|
|
5173
|
+
catch { /* ignore */ }
|
|
5174
|
+
}
|
|
5175
|
+
getCurrentValue() {
|
|
5176
|
+
if (this.trackedValues.length > 0) {
|
|
5177
|
+
return [...this.trackedValues];
|
|
5178
|
+
}
|
|
5179
|
+
if (!this.chip)
|
|
5180
|
+
return [];
|
|
5181
|
+
const val = this.chip.value;
|
|
5182
|
+
return Array.isArray(val) ? [...val] : [];
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
5185
|
+
|
|
4766
5186
|
/**
|
|
4767
5187
|
* Custom editor using NileCodeEditor from @aquera/nile-elements
|
|
4768
5188
|
* This provides code editing capabilities with syntax highlighting for table cells
|
|
@@ -4904,7 +5324,7 @@ class NileCodeEditor {
|
|
|
4904
5324
|
this.syncingFromDialog = false; // Flag to prevent inline editor from overwriting multiline content
|
|
4905
5325
|
this.userEditedInline = false; // Flag to track if user has typed in inline editor
|
|
4906
5326
|
this.dialogOriginalValue = ''; // Store original value when dialog opens
|
|
4907
|
-
this.dialogCurrentValue =
|
|
5327
|
+
this.dialogCurrentValue = null; // Track current value in dialog
|
|
4908
5328
|
}
|
|
4909
5329
|
edit(context) {
|
|
4910
5330
|
if (!context.container) {
|
|
@@ -5179,7 +5599,7 @@ class NileCodeEditor {
|
|
|
5179
5599
|
*/
|
|
5180
5600
|
getDialogEditorValue() {
|
|
5181
5601
|
// Use tracked value from change events (most reliable)
|
|
5182
|
-
if (this.dialogCurrentValue) {
|
|
5602
|
+
if (this.dialogCurrentValue !== null && this.dialogCurrentValue !== undefined) {
|
|
5183
5603
|
return this.dialogCurrentValue.replace(/\n+$/, '');
|
|
5184
5604
|
}
|
|
5185
5605
|
if (!this.dialogEditor)
|
|
@@ -5208,10 +5628,9 @@ class NileCodeEditor {
|
|
|
5208
5628
|
applyDialogChanges() {
|
|
5209
5629
|
if (!this.dialogOpen)
|
|
5210
5630
|
return;
|
|
5211
|
-
//
|
|
5631
|
+
// Always read live dialog editor state to avoid stale tracked values from debounced updates
|
|
5212
5632
|
let dialogValue = this.dialogCurrentValue;
|
|
5213
|
-
|
|
5214
|
-
if (!dialogValue && this.dialogEditor) {
|
|
5633
|
+
if (this.dialogEditor) {
|
|
5215
5634
|
try {
|
|
5216
5635
|
const shadowRoot = this.dialogEditor.shadowRoot;
|
|
5217
5636
|
if (shadowRoot) {
|
|
@@ -5225,12 +5644,12 @@ class NileCodeEditor {
|
|
|
5225
5644
|
// Fall through
|
|
5226
5645
|
}
|
|
5227
5646
|
// Fallback to value property
|
|
5228
|
-
if (
|
|
5647
|
+
if (dialogValue === null || dialogValue === undefined) {
|
|
5229
5648
|
dialogValue = this.dialogEditor.value ?? '';
|
|
5230
5649
|
}
|
|
5231
5650
|
}
|
|
5232
5651
|
// Strip trailing newlines
|
|
5233
|
-
dialogValue = (dialogValue
|
|
5652
|
+
dialogValue = (dialogValue ?? '').replace(/\n+$/, '');
|
|
5234
5653
|
// Update tracked value and inline editor
|
|
5235
5654
|
this.trackedValue = dialogValue;
|
|
5236
5655
|
this.userEditedInline = false;
|
|
@@ -5272,7 +5691,7 @@ class NileCodeEditor {
|
|
|
5272
5691
|
*/
|
|
5273
5692
|
closeDialogUI() {
|
|
5274
5693
|
this.dialogOpen = false;
|
|
5275
|
-
this.dialogCurrentValue =
|
|
5694
|
+
this.dialogCurrentValue = null;
|
|
5276
5695
|
if (this.dialog) {
|
|
5277
5696
|
this.dialog.open = false;
|
|
5278
5697
|
const dialogRef = this.dialog;
|
|
@@ -5517,7 +5936,7 @@ class NileCodeEditor {
|
|
|
5517
5936
|
this.trackedValue = null;
|
|
5518
5937
|
this.userEditedInline = false;
|
|
5519
5938
|
this.dialogOriginalValue = '';
|
|
5520
|
-
this.dialogCurrentValue =
|
|
5939
|
+
this.dialogCurrentValue = null;
|
|
5521
5940
|
}
|
|
5522
5941
|
focus() {
|
|
5523
5942
|
this.editor?.focus();
|
|
@@ -8826,7 +9245,7 @@ class StTableComponent {
|
|
|
8826
9245
|
const columns = this.getActiveColumns();
|
|
8827
9246
|
const oldGrid = this.internalCellGrid;
|
|
8828
9247
|
this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map((column, colIndex) => {
|
|
8829
|
-
const newCell =
|
|
9248
|
+
const newCell = column.createCell(rowData, rowIndex);
|
|
8830
9249
|
const oldCell = oldGrid?.[rowIndex]?.[colIndex];
|
|
8831
9250
|
if (oldCell && oldCell.getColumnConfig().key === column.key) {
|
|
8832
9251
|
oldCell.setReplacement(newCell);
|
|
@@ -13223,5 +13642,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
13223
13642
|
* Generated bundle index. Do not edit.
|
|
13224
13643
|
*/
|
|
13225
13644
|
|
|
13226
|
-
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 };
|
|
13645
|
+
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, NileChipEditor, 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 };
|
|
13227
13646
|
//# sourceMappingURL=aquera-ngx-smart-table.mjs.map
|