@toolbox-web/grid 1.9.1 → 1.10.0
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/all.js +1082 -975
- package/all.js.map +1 -1
- package/index.js +350 -324
- package/index.js.map +1 -1
- package/lib/core/grid.d.ts +40 -1
- package/lib/core/grid.d.ts.map +1 -1
- package/lib/core/plugin/base-plugin.d.ts +11 -0
- package/lib/core/plugin/base-plugin.d.ts.map +1 -1
- package/lib/core/types.d.ts +0 -64
- package/lib/core/types.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.js +9 -0
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +3 -0
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/index.js +90 -57
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/index.js +9 -0
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/editing/EditingPlugin.d.ts +69 -0
- package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
- package/lib/plugins/editing/editors.d.ts.map +1 -1
- package/lib/plugins/editing/index.d.ts +1 -1
- package/lib/plugins/editing/index.d.ts.map +1 -1
- package/lib/plugins/editing/index.js +435 -293
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/editing/types.d.ts +117 -1
- package/lib/plugins/editing/types.d.ts.map +1 -1
- package/lib/plugins/export/index.js +38 -29
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/index.js +14 -5
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/index.js +9 -0
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/index.js +63 -54
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/index.js +25 -16
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/multi-sort/index.js +13 -4
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/index.js +13 -4
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-rows/index.js +16 -7
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/index.js +13 -4
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/print/index.js +9 -0
- package/lib/plugins/print/index.js.map +1 -1
- package/lib/plugins/reorder/index.js +13 -4
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/responsive/index.js +42 -33
- package/lib/plugins/responsive/index.js.map +1 -1
- package/lib/plugins/row-reorder/index.js +9 -0
- package/lib/plugins/row-reorder/index.js.map +1 -1
- package/lib/plugins/selection/index.js +9 -0
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/server-side/index.js +29 -20
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tree/index.js +20 -11
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/undo-redo/index.js +15 -6
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/index.js +9 -0
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/public.d.ts +1 -1
- package/public.d.ts.map +1 -1
- package/umd/grid.all.umd.js +20 -20
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +14 -14
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/column-virtualization.umd.js +1 -1
- package/umd/plugins/column-virtualization.umd.js.map +1 -1
- package/umd/plugins/editing.umd.js +1 -1
- package/umd/plugins/editing.umd.js.map +1 -1
- package/umd/plugins/pinned-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
|
@@ -1,33 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
change: "--tbw-row-change-duration",
|
|
3
|
-
insert: "--tbw-row-insert-duration",
|
|
4
|
-
remove: "--tbw-row-remove-duration"
|
|
5
|
-
}, P = {
|
|
6
|
-
change: 500,
|
|
7
|
-
insert: 300,
|
|
8
|
-
remove: 200
|
|
9
|
-
};
|
|
10
|
-
function T(s) {
|
|
11
|
-
const e = s.trim().toLowerCase();
|
|
12
|
-
return e.endsWith("ms") ? parseFloat(e) : e.endsWith("s") ? parseFloat(e) * 1e3 : parseFloat(e);
|
|
13
|
-
}
|
|
14
|
-
function I(s, e) {
|
|
15
|
-
const i = A[e], t = getComputedStyle(s).getPropertyValue(i);
|
|
16
|
-
if (t) {
|
|
17
|
-
const r = T(t);
|
|
18
|
-
if (!isNaN(r) && r > 0)
|
|
19
|
-
return r;
|
|
20
|
-
}
|
|
21
|
-
return P[e];
|
|
22
|
-
}
|
|
23
|
-
function D(s, e, i) {
|
|
24
|
-
s.removeAttribute(R), s.offsetWidth, s.setAttribute(R, e);
|
|
25
|
-
const t = I(s, e);
|
|
26
|
-
setTimeout(() => {
|
|
27
|
-
s.removeAttribute(R);
|
|
28
|
-
}, t);
|
|
29
|
-
}
|
|
30
|
-
const L = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', q = {
|
|
1
|
+
const S = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', L = {
|
|
31
2
|
expand: "▶",
|
|
32
3
|
collapse: "▼",
|
|
33
4
|
sortAsc: "▲",
|
|
@@ -36,11 +7,11 @@ const L = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
|
|
|
36
7
|
submenuArrow: "▶",
|
|
37
8
|
dragHandle: "⋮⋮",
|
|
38
9
|
toolPanel: "☰",
|
|
39
|
-
filter:
|
|
40
|
-
filterActive:
|
|
10
|
+
filter: S,
|
|
11
|
+
filterActive: S,
|
|
41
12
|
print: "🖨️"
|
|
42
13
|
};
|
|
43
|
-
class
|
|
14
|
+
class I {
|
|
44
15
|
/**
|
|
45
16
|
* Plugin dependencies - declare other plugins this one requires.
|
|
46
17
|
*
|
|
@@ -167,16 +138,16 @@ class O {
|
|
|
167
138
|
/**
|
|
168
139
|
* Emit a custom event from the grid.
|
|
169
140
|
*/
|
|
170
|
-
emit(e,
|
|
171
|
-
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail:
|
|
141
|
+
emit(e, t) {
|
|
142
|
+
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
|
|
172
143
|
}
|
|
173
144
|
/**
|
|
174
145
|
* Emit a cancelable custom event from the grid.
|
|
175
146
|
* @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
|
|
176
147
|
*/
|
|
177
|
-
emitCancelable(e,
|
|
178
|
-
const
|
|
179
|
-
return this.grid?.dispatchEvent?.(
|
|
148
|
+
emitCancelable(e, t) {
|
|
149
|
+
const i = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
|
|
150
|
+
return this.grid?.dispatchEvent?.(i), i.defaultPrevented;
|
|
180
151
|
}
|
|
181
152
|
// =========================================================================
|
|
182
153
|
// Event Bus - Plugin-to-Plugin Communication
|
|
@@ -197,8 +168,8 @@ class O {
|
|
|
197
168
|
* });
|
|
198
169
|
* ```
|
|
199
170
|
*/
|
|
200
|
-
on(e,
|
|
201
|
-
this.grid?._pluginManager?.subscribe(this, e,
|
|
171
|
+
on(e, t) {
|
|
172
|
+
this.grid?._pluginManager?.subscribe(this, e, t);
|
|
202
173
|
}
|
|
203
174
|
/**
|
|
204
175
|
* Unsubscribe from a plugin event.
|
|
@@ -232,15 +203,24 @@ class O {
|
|
|
232
203
|
* this.emit('filter-change', { field: 'name', value: 'Alice' });
|
|
233
204
|
* ```
|
|
234
205
|
*/
|
|
235
|
-
emitPluginEvent(e,
|
|
236
|
-
this.grid?._pluginManager?.emitPluginEvent(e,
|
|
206
|
+
emitPluginEvent(e, t) {
|
|
207
|
+
this.grid?._pluginManager?.emitPluginEvent(e, t);
|
|
237
208
|
}
|
|
238
209
|
/**
|
|
239
210
|
* Request a re-render of the grid.
|
|
211
|
+
* Uses ROWS phase - does NOT trigger processColumns hooks.
|
|
240
212
|
*/
|
|
241
213
|
requestRender() {
|
|
242
214
|
this.grid?.requestRender?.();
|
|
243
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Request a columns re-render of the grid.
|
|
218
|
+
* Uses COLUMNS phase - triggers processColumns hooks.
|
|
219
|
+
* Use this when your plugin needs to reprocess column configuration.
|
|
220
|
+
*/
|
|
221
|
+
requestColumnsRender() {
|
|
222
|
+
this.grid?.requestColumnsRender?.();
|
|
223
|
+
}
|
|
244
224
|
/**
|
|
245
225
|
* Request a re-render and restore focus styling afterward.
|
|
246
226
|
* Use this when a plugin action (like expand/collapse) triggers a render
|
|
@@ -321,7 +301,7 @@ class O {
|
|
|
321
301
|
*/
|
|
322
302
|
get gridIcons() {
|
|
323
303
|
const e = this.grid?.gridConfig?.icons ?? {};
|
|
324
|
-
return { ...
|
|
304
|
+
return { ...L, ...e };
|
|
325
305
|
}
|
|
326
306
|
// #region Animation Helpers
|
|
327
307
|
/**
|
|
@@ -344,8 +324,8 @@ class O {
|
|
|
344
324
|
const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
|
|
345
325
|
if (e === !1 || e === "off") return !1;
|
|
346
326
|
if (e === !0 || e === "on") return !0;
|
|
347
|
-
const
|
|
348
|
-
return
|
|
327
|
+
const t = this.gridElement;
|
|
328
|
+
return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
|
|
349
329
|
}
|
|
350
330
|
/**
|
|
351
331
|
* Get the animation duration in milliseconds from CSS variable.
|
|
@@ -362,8 +342,8 @@ class O {
|
|
|
362
342
|
get animationDuration() {
|
|
363
343
|
const e = this.gridElement;
|
|
364
344
|
if (e) {
|
|
365
|
-
const
|
|
366
|
-
if (!isNaN(
|
|
345
|
+
const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), i = parseInt(t, 10);
|
|
346
|
+
if (!isNaN(i)) return i;
|
|
367
347
|
}
|
|
368
348
|
return 200;
|
|
369
349
|
}
|
|
@@ -376,8 +356,8 @@ class O {
|
|
|
376
356
|
* @param pluginOverride - Optional plugin-level override
|
|
377
357
|
* @returns The resolved icon value
|
|
378
358
|
*/
|
|
379
|
-
resolveIcon(e,
|
|
380
|
-
return
|
|
359
|
+
resolveIcon(e, t) {
|
|
360
|
+
return t !== void 0 ? t : this.gridIcons[e];
|
|
381
361
|
}
|
|
382
362
|
/**
|
|
383
363
|
* Set an icon value on an element.
|
|
@@ -386,8 +366,8 @@ class O {
|
|
|
386
366
|
* @param element - The element to set the icon on
|
|
387
367
|
* @param icon - The icon value (string or HTMLElement)
|
|
388
368
|
*/
|
|
389
|
-
setIcon(e,
|
|
390
|
-
typeof
|
|
369
|
+
setIcon(e, t) {
|
|
370
|
+
typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
|
|
391
371
|
}
|
|
392
372
|
/**
|
|
393
373
|
* Log a warning message.
|
|
@@ -397,88 +377,97 @@ class O {
|
|
|
397
377
|
}
|
|
398
378
|
// #endregion
|
|
399
379
|
}
|
|
400
|
-
const
|
|
401
|
-
function
|
|
380
|
+
const A = "@layer tbw-plugins{tbw-grid{--tbw-editing-bg: var(--tbw-color-selection);--tbw-editing-row-bg: var(--tbw-editing-bg);--tbw-editing-border: var(--tbw-border-input, 1px solid var(--tbw-color-border-strong));--tbw-padding-editing-input: var(--tbw-cell-padding-input, 2px 6px);--tbw-font-size-editor: inherit;--tbw-editing-row-outline-color: var(--tbw-color-accent);--tbw-editing-row-outline-width: 1px;--tbw-invalid-bg: light-dark(#fef2f2, #450a0a);--tbw-invalid-border-color: light-dark(#ef4444, #f87171)}tbw-grid .data-grid-row:has(.editing){background:var(--tbw-editing-row-bg);outline:var(--tbw-editing-row-outline-width) solid var(--tbw-editing-row-outline-color);outline-offset:calc(-1 * var(--tbw-editing-row-outline-width))}tbw-grid .data-grid-row>.cell.editing{overflow:hidden;padding:0;display:flex;min-height:calc(var(--tbw-row-height) + 2px);align-items:center;justify-content:center}tbw-grid .data-grid-row>.cell.editing input:not([type=checkbox]),tbw-grid .data-grid-row>.cell.editing select,tbw-grid .data-grid-row>.cell.editing textarea{width:100%;height:100%;flex:1 1 auto;min-width:0;border:var(--tbw-editing-border);padding:var(--tbw-padding-editing-input);font-size:var(--tbw-font-size-editor)}tbw-grid .tbw-editor-host{display:contents}tbw-grid .data-grid-row>.cell[data-invalid=true]{background:var(--tbw-invalid-bg);outline:1px solid var(--tbw-invalid-border-color);outline-offset:-1px}}";
|
|
381
|
+
function P(s) {
|
|
402
382
|
const e = s.options;
|
|
403
383
|
return e ? typeof e == "function" ? e() : e : [];
|
|
404
384
|
}
|
|
405
|
-
function
|
|
385
|
+
function T(s) {
|
|
406
386
|
return (e) => {
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
const r = () => e.commit(
|
|
410
|
-
return
|
|
387
|
+
const t = s.editorParams, i = document.createElement("input");
|
|
388
|
+
i.type = "number", i.value = e.value != null ? String(e.value) : "", t?.min !== void 0 && (i.min = String(t.min)), t?.max !== void 0 && (i.max = String(t.max)), t?.step !== void 0 && (i.step = String(t.step)), t?.placeholder && (i.placeholder = t.placeholder);
|
|
389
|
+
const r = () => e.commit(i.value === "" ? null : Number(i.value));
|
|
390
|
+
return i.addEventListener("blur", r), i.addEventListener("keydown", (n) => {
|
|
411
391
|
n.key === "Enter" && r(), n.key === "Escape" && e.cancel();
|
|
412
|
-
}),
|
|
392
|
+
}), i;
|
|
413
393
|
};
|
|
414
394
|
}
|
|
415
|
-
function
|
|
395
|
+
function q() {
|
|
416
396
|
return (s) => {
|
|
417
397
|
const e = document.createElement("input");
|
|
418
398
|
return e.type = "checkbox", e.checked = !!s.value, e.addEventListener("change", () => s.commit(e.checked)), e;
|
|
419
399
|
};
|
|
420
400
|
}
|
|
421
|
-
function
|
|
401
|
+
function O(s) {
|
|
422
402
|
return (e) => {
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
403
|
+
const t = s.editorParams, i = document.createElement("input");
|
|
404
|
+
i.type = "date", e.value instanceof Date ? i.valueAsDate = e.value : typeof e.value == "string" && e.value && (i.value = e.value.split("T")[0]), t?.min && (i.min = t.min), t?.max && (i.max = t.max), t?.placeholder && (i.placeholder = t.placeholder);
|
|
405
|
+
const r = () => {
|
|
406
|
+
typeof e.value == "string" ? e.commit(i.value) : e.commit(i.valueAsDate);
|
|
407
|
+
};
|
|
408
|
+
return i.addEventListener("change", r), i.addEventListener("keydown", (n) => {
|
|
409
|
+
n.key === "Escape" && e.cancel();
|
|
410
|
+
}), i;
|
|
427
411
|
};
|
|
428
412
|
}
|
|
429
|
-
function
|
|
413
|
+
function D(s) {
|
|
430
414
|
return (e) => {
|
|
431
|
-
const
|
|
432
|
-
if (s.multi && (
|
|
415
|
+
const t = s.editorParams, i = document.createElement("select");
|
|
416
|
+
if (s.multi && (i.multiple = !0), t?.includeEmpty) {
|
|
433
417
|
const o = document.createElement("option");
|
|
434
|
-
o.value = "", o.textContent =
|
|
418
|
+
o.value = "", o.textContent = t.emptyLabel ?? "", i.appendChild(o);
|
|
435
419
|
}
|
|
436
|
-
|
|
420
|
+
P(s).forEach((o) => {
|
|
437
421
|
const a = document.createElement("option");
|
|
438
|
-
a.value = String(o.value), a.textContent = o.label, (s.multi && Array.isArray(e.value) && e.value.includes(o.value) || !s.multi && e.value === o.value) && (a.selected = !0),
|
|
422
|
+
a.value = String(o.value), a.textContent = o.label, (s.multi && Array.isArray(e.value) && e.value.includes(o.value) || !s.multi && e.value === o.value) && (a.selected = !0), i.appendChild(a);
|
|
439
423
|
});
|
|
440
424
|
const n = () => {
|
|
441
425
|
if (s.multi) {
|
|
442
|
-
const o = Array.from(
|
|
426
|
+
const o = Array.from(i.selectedOptions).map((a) => a.value);
|
|
443
427
|
e.commit(o);
|
|
444
428
|
} else
|
|
445
|
-
e.commit(
|
|
429
|
+
e.commit(i.value);
|
|
446
430
|
};
|
|
447
|
-
return
|
|
431
|
+
return i.addEventListener("change", n), i.addEventListener("blur", n), i.addEventListener("keydown", (o) => {
|
|
448
432
|
o.key === "Escape" && e.cancel();
|
|
449
|
-
}),
|
|
433
|
+
}), i;
|
|
450
434
|
};
|
|
451
435
|
}
|
|
452
|
-
function
|
|
436
|
+
function M(s) {
|
|
453
437
|
return (e) => {
|
|
454
|
-
const
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
438
|
+
const t = s.editorParams, i = document.createElement("input");
|
|
439
|
+
i.type = "text", i.value = e.value != null ? String(e.value) : "", t?.maxLength !== void 0 && (i.maxLength = t.maxLength), t?.pattern && (i.pattern = t.pattern), t?.placeholder && (i.placeholder = t.placeholder);
|
|
440
|
+
const r = () => {
|
|
441
|
+
const n = i.value;
|
|
442
|
+
typeof e.value == "number" && n !== "" ? e.commit(Number(n)) : e.commit(n);
|
|
443
|
+
};
|
|
444
|
+
return i.addEventListener("blur", r), i.addEventListener("keydown", (n) => {
|
|
445
|
+
n.key === "Enter" && r(), n.key === "Escape" && e.cancel();
|
|
446
|
+
}), i;
|
|
458
447
|
};
|
|
459
448
|
}
|
|
460
|
-
function
|
|
449
|
+
function N(s) {
|
|
461
450
|
switch (s.type) {
|
|
462
451
|
case "number":
|
|
463
|
-
return
|
|
452
|
+
return T(s);
|
|
464
453
|
case "boolean":
|
|
465
|
-
return
|
|
454
|
+
return q();
|
|
466
455
|
case "date":
|
|
467
|
-
return
|
|
456
|
+
return O(s);
|
|
468
457
|
case "select":
|
|
469
|
-
return
|
|
458
|
+
return D(s);
|
|
470
459
|
default:
|
|
471
|
-
return
|
|
460
|
+
return M(s);
|
|
472
461
|
}
|
|
473
462
|
}
|
|
474
|
-
const
|
|
475
|
-
function
|
|
463
|
+
const R = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])';
|
|
464
|
+
function G(s, e) {
|
|
476
465
|
if (e.editor) return e.editor;
|
|
477
466
|
if (e.__editorTemplate) return "template";
|
|
478
467
|
if (!e.type) return;
|
|
479
|
-
const
|
|
480
|
-
if (
|
|
481
|
-
return
|
|
468
|
+
const i = s.effectiveConfig?.typeDefaults;
|
|
469
|
+
if (i?.[e.type]?.editor)
|
|
470
|
+
return i[e.type].editor;
|
|
482
471
|
const r = s.__frameworkAdapter;
|
|
483
472
|
if (r?.getTypeDefault) {
|
|
484
473
|
const n = r.getTypeDefault(e.type);
|
|
@@ -486,28 +475,28 @@ function B(s, e) {
|
|
|
486
475
|
return n.editor;
|
|
487
476
|
}
|
|
488
477
|
}
|
|
489
|
-
function
|
|
478
|
+
function w(s) {
|
|
490
479
|
return !(typeof s != "string" || s === "__proto__" || s === "constructor" || s === "prototype");
|
|
491
480
|
}
|
|
492
|
-
function
|
|
481
|
+
function H(s) {
|
|
493
482
|
const e = (s.__editingCellCount ?? 0) + 1;
|
|
494
483
|
s.__editingCellCount = e, s.setAttribute("data-has-editing", "");
|
|
495
484
|
}
|
|
496
|
-
function
|
|
485
|
+
function x(s) {
|
|
497
486
|
s.__editingCellCount = 0, s.removeAttribute("data-has-editing");
|
|
498
487
|
}
|
|
499
|
-
function E(s, e) {
|
|
500
|
-
return s instanceof HTMLInputElement ? s.type === "checkbox" ? s.checked : s.type === "number" ? s.value === "" ? null : Number(s.value) : s.type === "date" ? s.valueAsDate : s.value : e?.type === "number" && s.value !== "" ? Number(s.value) : s.value;
|
|
488
|
+
function E(s, e, t) {
|
|
489
|
+
return s instanceof HTMLInputElement ? s.type === "checkbox" ? s.checked : s.type === "number" ? s.value === "" ? null : Number(s.value) : s.type === "date" ? typeof t == "string" ? s.value : s.valueAsDate : typeof t == "number" ? s.value === "" ? null : Number(s.value) : s.value : e?.type === "number" && s.value !== "" || typeof t == "number" && s.value !== "" ? Number(s.value) : s.value;
|
|
501
490
|
}
|
|
502
491
|
function k(s) {
|
|
503
492
|
}
|
|
504
|
-
function
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}),
|
|
493
|
+
function $(s, e, t, i) {
|
|
494
|
+
const r = s.querySelector("input,textarea,select");
|
|
495
|
+
r && (r.addEventListener("blur", () => {
|
|
496
|
+
t(E(r, e, i));
|
|
497
|
+
}), r instanceof HTMLInputElement && r.type === "checkbox" ? r.addEventListener("change", () => t(r.checked)) : r instanceof HTMLSelectElement && r.addEventListener("change", () => t(E(r, e, i))));
|
|
509
498
|
}
|
|
510
|
-
class
|
|
499
|
+
class z extends I {
|
|
511
500
|
/**
|
|
512
501
|
* Plugin manifest - declares owned properties for configuration validation.
|
|
513
502
|
* @internal
|
|
@@ -547,7 +536,7 @@ class K extends O {
|
|
|
547
536
|
/** @internal */
|
|
548
537
|
name = "editing";
|
|
549
538
|
/** @internal */
|
|
550
|
-
styles =
|
|
539
|
+
styles = A;
|
|
551
540
|
/** @internal */
|
|
552
541
|
get defaultConfig() {
|
|
553
542
|
return {
|
|
@@ -558,22 +547,29 @@ class K extends O {
|
|
|
558
547
|
/** Currently active edit row index, or -1 if not editing */
|
|
559
548
|
#e = -1;
|
|
560
549
|
/** Currently active edit column index, or -1 if not editing */
|
|
561
|
-
#
|
|
550
|
+
#o = -1;
|
|
562
551
|
/** Snapshots of row data before editing started */
|
|
563
|
-
#
|
|
552
|
+
#s = /* @__PURE__ */ new Map();
|
|
564
553
|
/** Set of row IDs that have been modified (ID-based for stability) */
|
|
565
|
-
#
|
|
554
|
+
#i = /* @__PURE__ */ new Set();
|
|
566
555
|
/** Set of cells currently in edit mode: "rowIndex:colIndex" */
|
|
567
|
-
#
|
|
556
|
+
#r = /* @__PURE__ */ new Set();
|
|
568
557
|
/** Flag to restore focus after next render (used when exiting edit mode) */
|
|
569
|
-
#
|
|
558
|
+
#a = !1;
|
|
559
|
+
/** Row index pending animation after render, or -1 if none */
|
|
560
|
+
#l = -1;
|
|
561
|
+
/**
|
|
562
|
+
* Invalid cell tracking: Map<rowId, Map<field, message>>
|
|
563
|
+
* Used for validation feedback without canceling edits.
|
|
564
|
+
*/
|
|
565
|
+
#t = /* @__PURE__ */ new Map();
|
|
570
566
|
// #endregion
|
|
571
567
|
// #region Lifecycle
|
|
572
568
|
/** @internal */
|
|
573
569
|
attach(e) {
|
|
574
570
|
super.attach(e);
|
|
575
|
-
const
|
|
576
|
-
|
|
571
|
+
const t = this.disconnectSignal, i = e;
|
|
572
|
+
i._activeEditRows = -1, i._rowEditSnapshots = /* @__PURE__ */ new Map(), Object.defineProperty(e, "changedRows", {
|
|
577
573
|
get: () => this.changedRows,
|
|
578
574
|
configurable: !0
|
|
579
575
|
}), Object.defineProperty(e, "changedRowIds", {
|
|
@@ -584,24 +580,24 @@ class K extends O {
|
|
|
584
580
|
}, document.addEventListener(
|
|
585
581
|
"keydown",
|
|
586
582
|
(r) => {
|
|
587
|
-
r.key === "Escape" && this.#e !== -1 && this.#
|
|
583
|
+
r.key === "Escape" && this.#e !== -1 && this.#n(this.#e, !0);
|
|
588
584
|
},
|
|
589
|
-
{ capture: !0, signal:
|
|
585
|
+
{ capture: !0, signal: t }
|
|
590
586
|
), document.addEventListener(
|
|
591
587
|
"mousedown",
|
|
592
588
|
(r) => {
|
|
593
589
|
if (this.#e === -1) return;
|
|
594
|
-
const n =
|
|
590
|
+
const n = i.findRenderedRowElement?.(this.#e);
|
|
595
591
|
!n || (r.composedPath && r.composedPath() || []).includes(n) || queueMicrotask(() => {
|
|
596
|
-
this.#e !== -1 && this.#
|
|
592
|
+
this.#e !== -1 && this.#n(this.#e, !1);
|
|
597
593
|
});
|
|
598
594
|
},
|
|
599
|
-
{ signal:
|
|
595
|
+
{ signal: t }
|
|
600
596
|
);
|
|
601
597
|
}
|
|
602
598
|
/** @internal */
|
|
603
599
|
detach() {
|
|
604
|
-
this.#e = -1, this.#
|
|
600
|
+
this.#e = -1, this.#o = -1, this.#s.clear(), this.#i.clear(), this.#r.clear(), super.detach();
|
|
605
601
|
}
|
|
606
602
|
/**
|
|
607
603
|
* Handle plugin queries.
|
|
@@ -620,30 +616,30 @@ class K extends O {
|
|
|
620
616
|
* @internal
|
|
621
617
|
*/
|
|
622
618
|
onCellClick(e) {
|
|
623
|
-
const
|
|
624
|
-
if (
|
|
619
|
+
const t = this.grid, i = this.config.editOn ?? t.effectiveConfig?.editOn;
|
|
620
|
+
if (i === !1 || i === "manual" || i !== "click" && i !== "dblclick") return !1;
|
|
625
621
|
const r = e.originalEvent.type === "dblclick";
|
|
626
|
-
if (
|
|
622
|
+
if (i === "click" && r || i === "dblclick" && !r) return !1;
|
|
627
623
|
const { rowIndex: n } = e;
|
|
628
|
-
return
|
|
624
|
+
return t._columns?.some((a) => a.editable) ? (e.originalEvent.stopPropagation(), this.beginBulkEdit(n), !0) : !1;
|
|
629
625
|
}
|
|
630
626
|
/**
|
|
631
627
|
* Handle keyboard events for edit lifecycle.
|
|
632
628
|
* @internal
|
|
633
629
|
*/
|
|
634
630
|
onKeyDown(e) {
|
|
635
|
-
const
|
|
631
|
+
const t = this.grid;
|
|
636
632
|
if (e.key === "Escape" && this.#e !== -1)
|
|
637
|
-
return this.#
|
|
633
|
+
return this.#n(this.#e, !0), !0;
|
|
638
634
|
if (e.key === " " || e.key === "Spacebar") {
|
|
639
|
-
const
|
|
640
|
-
if (
|
|
641
|
-
const n =
|
|
635
|
+
const i = t._focusRow, r = t._focusCol;
|
|
636
|
+
if (i >= 0 && r >= 0) {
|
|
637
|
+
const n = t._visibleColumns[r], o = t._rows[i];
|
|
642
638
|
if (n?.editable && n.type === "boolean" && o) {
|
|
643
639
|
const a = n.field;
|
|
644
|
-
if (
|
|
645
|
-
const
|
|
646
|
-
return this.#
|
|
640
|
+
if (w(a)) {
|
|
641
|
+
const d = !o[a];
|
|
642
|
+
return this.#u(i, n, d, o), e.preventDefault(), this.requestRender(), !0;
|
|
647
643
|
}
|
|
648
644
|
}
|
|
649
645
|
}
|
|
@@ -652,31 +648,31 @@ class K extends O {
|
|
|
652
648
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
653
649
|
if (this.#e !== -1)
|
|
654
650
|
return !1;
|
|
655
|
-
const
|
|
656
|
-
if (
|
|
657
|
-
const r =
|
|
658
|
-
if (r >= 0 &&
|
|
659
|
-
const a =
|
|
651
|
+
const i = this.config.editOn ?? t.effectiveConfig?.editOn;
|
|
652
|
+
if (i === !1 || i === "manual") return !1;
|
|
653
|
+
const r = t._focusRow, n = t._focusCol;
|
|
654
|
+
if (r >= 0 && t._columns?.some((a) => a.editable)) {
|
|
655
|
+
const a = t._visibleColumns[n], l = t._rows[r], d = a?.field ?? "", c = d && l ? l[d] : void 0, p = this.gridElement.querySelector(`[data-row="${r}"][data-col="${n}"]`), u = new CustomEvent("cell-activate", {
|
|
660
656
|
cancelable: !0,
|
|
661
657
|
bubbles: !0,
|
|
662
658
|
detail: {
|
|
663
659
|
rowIndex: r,
|
|
664
660
|
colIndex: n,
|
|
665
|
-
field:
|
|
666
|
-
value:
|
|
661
|
+
field: d,
|
|
662
|
+
value: c,
|
|
667
663
|
row: l,
|
|
668
|
-
cellEl:
|
|
664
|
+
cellEl: p,
|
|
669
665
|
trigger: "keyboard",
|
|
670
666
|
originalEvent: e
|
|
671
667
|
}
|
|
672
668
|
});
|
|
673
|
-
this.gridElement.dispatchEvent(
|
|
674
|
-
const
|
|
669
|
+
this.gridElement.dispatchEvent(u);
|
|
670
|
+
const m = new CustomEvent("activate-cell", {
|
|
675
671
|
cancelable: !0,
|
|
676
672
|
bubbles: !0,
|
|
677
673
|
detail: { row: r, col: n }
|
|
678
674
|
});
|
|
679
|
-
return this.gridElement.dispatchEvent(
|
|
675
|
+
return this.gridElement.dispatchEvent(m), u.defaultPrevented || m.defaultPrevented ? (e.preventDefault(), !0) : (this.beginBulkEdit(r), !0);
|
|
680
676
|
}
|
|
681
677
|
return !1;
|
|
682
678
|
}
|
|
@@ -690,11 +686,11 @@ class K extends O {
|
|
|
690
686
|
* @internal
|
|
691
687
|
*/
|
|
692
688
|
processColumns(e) {
|
|
693
|
-
const
|
|
694
|
-
return !
|
|
689
|
+
const t = this.grid, i = t.effectiveConfig?.typeDefaults, r = t.__frameworkAdapter;
|
|
690
|
+
return !i && !r?.getTypeDefault ? e : e.map((n) => {
|
|
695
691
|
if (!n.type) return n;
|
|
696
692
|
let o;
|
|
697
|
-
if (
|
|
693
|
+
if (i?.[n.type]?.editorParams && (o = i[n.type].editorParams), !o && r?.getTypeDefault) {
|
|
698
694
|
const a = r.getTypeDefault(n.type);
|
|
699
695
|
a?.editorParams && (o = a.editorParams);
|
|
700
696
|
}
|
|
@@ -712,14 +708,18 @@ class K extends O {
|
|
|
712
708
|
*/
|
|
713
709
|
afterRender() {
|
|
714
710
|
const e = this.grid;
|
|
715
|
-
if (this.#
|
|
716
|
-
|
|
717
|
-
|
|
711
|
+
if (this.#a && (this.#a = !1, this.#g(e)), this.#l !== -1) {
|
|
712
|
+
const t = this.#l;
|
|
713
|
+
this.#l = -1, e.animateRow?.(t, "change");
|
|
714
|
+
}
|
|
715
|
+
if (this.#r.size !== 0)
|
|
716
|
+
for (const t of this.#r) {
|
|
717
|
+
const [i, r] = t.split(":"), n = parseInt(i, 10), o = parseInt(r, 10), a = e.findRenderedRowElement?.(n);
|
|
718
718
|
if (!a) continue;
|
|
719
719
|
const l = a.querySelector(`.cell[data-col="${o}"]`);
|
|
720
720
|
if (!l || l.classList.contains("editing")) continue;
|
|
721
|
-
const
|
|
722
|
-
|
|
721
|
+
const d = e._rows[n], c = e._visibleColumns[o];
|
|
722
|
+
d && c && this.#f(d, n, c, o, l, !0);
|
|
723
723
|
}
|
|
724
724
|
}
|
|
725
725
|
/**
|
|
@@ -737,9 +737,9 @@ class K extends O {
|
|
|
737
737
|
*/
|
|
738
738
|
get changedRows() {
|
|
739
739
|
const e = [];
|
|
740
|
-
for (const
|
|
741
|
-
const
|
|
742
|
-
|
|
740
|
+
for (const t of this.#i) {
|
|
741
|
+
const i = this.grid.getRow(t);
|
|
742
|
+
i && e.push(i);
|
|
743
743
|
}
|
|
744
744
|
return e;
|
|
745
745
|
}
|
|
@@ -747,7 +747,7 @@ class K extends O {
|
|
|
747
747
|
* Get IDs of all modified rows.
|
|
748
748
|
*/
|
|
749
749
|
get changedRowIds() {
|
|
750
|
-
return Array.from(this.#
|
|
750
|
+
return Array.from(this.#i);
|
|
751
751
|
}
|
|
752
752
|
/**
|
|
753
753
|
* Get the currently active edit row index, or -1 if not editing.
|
|
@@ -759,7 +759,7 @@ class K extends O {
|
|
|
759
759
|
* Get the currently active edit column index, or -1 if not editing.
|
|
760
760
|
*/
|
|
761
761
|
get activeEditCol() {
|
|
762
|
-
return this.#
|
|
762
|
+
return this.#o;
|
|
763
763
|
}
|
|
764
764
|
/**
|
|
765
765
|
* Check if a specific row is currently being edited.
|
|
@@ -770,19 +770,19 @@ class K extends O {
|
|
|
770
770
|
/**
|
|
771
771
|
* Check if a specific cell is currently being edited.
|
|
772
772
|
*/
|
|
773
|
-
isCellEditing(e,
|
|
774
|
-
return this.#
|
|
773
|
+
isCellEditing(e, t) {
|
|
774
|
+
return this.#r.has(`${e}:${t}`);
|
|
775
775
|
}
|
|
776
776
|
/**
|
|
777
777
|
* Check if a specific row has been modified.
|
|
778
778
|
* @param rowIndex - Row index to check (will be converted to ID internally)
|
|
779
779
|
*/
|
|
780
780
|
isRowChanged(e) {
|
|
781
|
-
const
|
|
782
|
-
if (!
|
|
781
|
+
const t = this.grid, i = t._rows[e];
|
|
782
|
+
if (!i) return !1;
|
|
783
783
|
try {
|
|
784
|
-
const r =
|
|
785
|
-
return r ? this.#
|
|
784
|
+
const r = t.getRowId?.(i);
|
|
785
|
+
return r ? this.#i.has(r) : !1;
|
|
786
786
|
} catch {
|
|
787
787
|
return !1;
|
|
788
788
|
}
|
|
@@ -792,16 +792,136 @@ class K extends O {
|
|
|
792
792
|
* @param rowId - Row ID to check
|
|
793
793
|
*/
|
|
794
794
|
isRowChangedById(e) {
|
|
795
|
-
return this.#
|
|
795
|
+
return this.#i.has(e);
|
|
796
|
+
}
|
|
797
|
+
// #region Cell Validation
|
|
798
|
+
/**
|
|
799
|
+
* Mark a cell as invalid with an optional validation message.
|
|
800
|
+
* Invalid cells are marked with a `data-invalid` attribute for styling.
|
|
801
|
+
*
|
|
802
|
+
* @param rowId - The row ID (from getRowId)
|
|
803
|
+
* @param field - The field name
|
|
804
|
+
* @param message - Optional validation message (for tooltips or display)
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```typescript
|
|
808
|
+
* // In cell-commit handler:
|
|
809
|
+
* grid.addEventListener('cell-commit', (e) => {
|
|
810
|
+
* if (e.detail.field === 'email' && !isValidEmail(e.detail.value)) {
|
|
811
|
+
* e.detail.setInvalid('Invalid email format');
|
|
812
|
+
* }
|
|
813
|
+
* });
|
|
814
|
+
*
|
|
815
|
+
* // Or programmatically:
|
|
816
|
+
* editingPlugin.setInvalid('row-123', 'email', 'Invalid email format');
|
|
817
|
+
* ```
|
|
818
|
+
*/
|
|
819
|
+
setInvalid(e, t, i = "") {
|
|
820
|
+
let r = this.#t.get(e);
|
|
821
|
+
r || (r = /* @__PURE__ */ new Map(), this.#t.set(e, r)), r.set(t, i), this.#d(e, t, !0);
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Clear the invalid state for a specific cell.
|
|
825
|
+
*
|
|
826
|
+
* @param rowId - The row ID (from getRowId)
|
|
827
|
+
* @param field - The field name
|
|
828
|
+
*/
|
|
829
|
+
clearInvalid(e, t) {
|
|
830
|
+
const i = this.#t.get(e);
|
|
831
|
+
i && (i.delete(t), i.size === 0 && this.#t.delete(e)), this.#d(e, t, !1);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Clear all invalid cells for a specific row.
|
|
835
|
+
*
|
|
836
|
+
* @param rowId - The row ID (from getRowId)
|
|
837
|
+
*/
|
|
838
|
+
clearRowInvalid(e) {
|
|
839
|
+
const t = this.#t.get(e);
|
|
840
|
+
if (t) {
|
|
841
|
+
const i = Array.from(t.keys());
|
|
842
|
+
this.#t.delete(e), i.forEach((r) => this.#d(e, r, !1));
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Clear all invalid cell states across all rows.
|
|
847
|
+
*/
|
|
848
|
+
clearAllInvalid() {
|
|
849
|
+
const e = Array.from(this.#t.entries());
|
|
850
|
+
this.#t.clear(), e.forEach(([t, i]) => {
|
|
851
|
+
i.forEach((r, n) => this.#d(t, n, !1));
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Check if a specific cell is marked as invalid.
|
|
856
|
+
*
|
|
857
|
+
* @param rowId - The row ID (from getRowId)
|
|
858
|
+
* @param field - The field name
|
|
859
|
+
* @returns True if the cell is marked as invalid
|
|
860
|
+
*/
|
|
861
|
+
isCellInvalid(e, t) {
|
|
862
|
+
return this.#t.get(e)?.has(t) ?? !1;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Get the validation message for an invalid cell.
|
|
866
|
+
*
|
|
867
|
+
* @param rowId - The row ID (from getRowId)
|
|
868
|
+
* @param field - The field name
|
|
869
|
+
* @returns The validation message, or undefined if cell is valid
|
|
870
|
+
*/
|
|
871
|
+
getInvalidMessage(e, t) {
|
|
872
|
+
return this.#t.get(e)?.get(t);
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Check if a row has any invalid cells.
|
|
876
|
+
*
|
|
877
|
+
* @param rowId - The row ID (from getRowId)
|
|
878
|
+
* @returns True if the row has at least one invalid cell
|
|
879
|
+
*/
|
|
880
|
+
hasInvalidCells(e) {
|
|
881
|
+
const t = this.#t.get(e);
|
|
882
|
+
return t ? t.size > 0 : !1;
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Get all invalid fields for a row.
|
|
886
|
+
*
|
|
887
|
+
* @param rowId - The row ID (from getRowId)
|
|
888
|
+
* @returns Map of field names to validation messages
|
|
889
|
+
*/
|
|
890
|
+
getInvalidFields(e) {
|
|
891
|
+
return new Map(this.#t.get(e) ?? []);
|
|
796
892
|
}
|
|
893
|
+
/**
|
|
894
|
+
* Sync the data-invalid attribute on a cell element.
|
|
895
|
+
*/
|
|
896
|
+
#d(e, t, i) {
|
|
897
|
+
const r = this.grid, n = r._visibleColumns?.findIndex((c) => c.field === t);
|
|
898
|
+
if (n === -1 || n === void 0) return;
|
|
899
|
+
const a = r._rows?.findIndex((c) => {
|
|
900
|
+
try {
|
|
901
|
+
return r.getRowId?.(c) === e;
|
|
902
|
+
} catch {
|
|
903
|
+
return !1;
|
|
904
|
+
}
|
|
905
|
+
});
|
|
906
|
+
if (a === -1 || a === void 0) return;
|
|
907
|
+
const d = r.findRenderedRowElement?.(a)?.querySelector(`.cell[data-col="${n}"]`);
|
|
908
|
+
if (d)
|
|
909
|
+
if (i) {
|
|
910
|
+
d.setAttribute("data-invalid", "true");
|
|
911
|
+
const c = this.#t.get(e)?.get(t);
|
|
912
|
+
c && d.setAttribute("title", c);
|
|
913
|
+
} else
|
|
914
|
+
d.removeAttribute("data-invalid"), d.removeAttribute("title");
|
|
915
|
+
}
|
|
916
|
+
// #endregion
|
|
797
917
|
/**
|
|
798
918
|
* Reset all change tracking.
|
|
799
919
|
* @param silent - If true, suppresses the `changed-rows-reset` event
|
|
800
920
|
* @fires changed-rows-reset - Emitted when tracking is reset (unless silent)
|
|
801
921
|
*/
|
|
802
922
|
resetChangedRows(e) {
|
|
803
|
-
const
|
|
804
|
-
this.#
|
|
923
|
+
const t = this.changedRows, i = this.changedRowIds;
|
|
924
|
+
this.#i.clear(), this.#c(), e || this.emit("changed-rows-reset", { rows: t, ids: i }), this.grid._rowPool?.forEach((n) => n.classList.remove("changed"));
|
|
805
925
|
}
|
|
806
926
|
/**
|
|
807
927
|
* Programmatically begin editing a cell.
|
|
@@ -809,11 +929,11 @@ class K extends O {
|
|
|
809
929
|
* @param field - Field name of the column to edit
|
|
810
930
|
* @fires cell-commit - Emitted when the cell value is committed (on blur or Enter)
|
|
811
931
|
*/
|
|
812
|
-
beginCellEdit(e,
|
|
813
|
-
const
|
|
814
|
-
if (r === -1 || !
|
|
815
|
-
const a =
|
|
816
|
-
a && this.#
|
|
932
|
+
beginCellEdit(e, t) {
|
|
933
|
+
const i = this.grid, r = i._visibleColumns.findIndex((l) => l.field === t);
|
|
934
|
+
if (r === -1 || !i._visibleColumns[r]?.editable) return;
|
|
935
|
+
const a = i.findRenderedRowElement?.(e)?.querySelector(`.cell[data-col="${r}"]`);
|
|
936
|
+
a && this.#p(e, r, a);
|
|
817
937
|
}
|
|
818
938
|
/**
|
|
819
939
|
* Programmatically begin editing all editable cells in a row.
|
|
@@ -822,21 +942,21 @@ class K extends O {
|
|
|
822
942
|
* @fires row-commit - Emitted when focus leaves the row
|
|
823
943
|
*/
|
|
824
944
|
beginBulkEdit(e) {
|
|
825
|
-
const
|
|
826
|
-
if ((this.config.editOn ??
|
|
827
|
-
const n =
|
|
945
|
+
const t = this.grid;
|
|
946
|
+
if ((this.config.editOn ?? t.effectiveConfig?.editOn) === !1 || !t._columns?.some((a) => a.editable)) return;
|
|
947
|
+
const n = t.findRenderedRowElement?.(e);
|
|
828
948
|
if (!n) return;
|
|
829
|
-
const o =
|
|
830
|
-
this.#
|
|
831
|
-
const
|
|
832
|
-
if (
|
|
833
|
-
const
|
|
834
|
-
|
|
949
|
+
const o = t._rows[e];
|
|
950
|
+
this.#h(e, o), Array.from(n.children).forEach((a, l) => {
|
|
951
|
+
const d = t._visibleColumns[l];
|
|
952
|
+
if (d?.editable) {
|
|
953
|
+
const c = a;
|
|
954
|
+
c.classList.contains("editing") || this.#f(o, e, d, l, c, !0);
|
|
835
955
|
}
|
|
836
956
|
}), setTimeout(() => {
|
|
837
|
-
let a = n.querySelector(`.cell[data-col="${
|
|
957
|
+
let a = n.querySelector(`.cell[data-col="${t._focusCol}"]`);
|
|
838
958
|
if (a?.classList.contains("editing") || (a = n.querySelector(".cell.editing")), a?.classList.contains("editing")) {
|
|
839
|
-
const l = a.querySelector(
|
|
959
|
+
const l = a.querySelector(R);
|
|
840
960
|
try {
|
|
841
961
|
l?.focus({ preventScroll: !0 });
|
|
842
962
|
} catch {
|
|
@@ -849,235 +969,257 @@ class K extends O {
|
|
|
849
969
|
* @fires row-commit - Emitted after the row edit is committed
|
|
850
970
|
*/
|
|
851
971
|
commitActiveRowEdit() {
|
|
852
|
-
this.#e !== -1 && this.#
|
|
972
|
+
this.#e !== -1 && this.#n(this.#e, !1);
|
|
853
973
|
}
|
|
854
974
|
/**
|
|
855
975
|
* Cancel the currently active row edit.
|
|
856
976
|
*/
|
|
857
977
|
cancelActiveRowEdit() {
|
|
858
|
-
this.#e !== -1 && this.#
|
|
978
|
+
this.#e !== -1 && this.#n(this.#e, !0);
|
|
859
979
|
}
|
|
860
980
|
// #endregion
|
|
861
981
|
// #region Internal Methods
|
|
862
982
|
/**
|
|
863
983
|
* Begin editing a single cell.
|
|
864
984
|
*/
|
|
865
|
-
#
|
|
866
|
-
const r = this.grid, n = r._rows[e], o = r._visibleColumns[
|
|
867
|
-
!n || !o?.editable ||
|
|
985
|
+
#p(e, t, i) {
|
|
986
|
+
const r = this.grid, n = r._rows[e], o = r._visibleColumns[t];
|
|
987
|
+
!n || !o?.editable || i.classList.contains("editing") || (this.#e !== e && this.#h(e, n), this.#o = t, this.#f(n, e, o, t, i, !1));
|
|
868
988
|
}
|
|
869
989
|
/**
|
|
870
990
|
* Sync the internal grid state with the plugin's editing state.
|
|
871
991
|
*/
|
|
872
|
-
#
|
|
992
|
+
#c() {
|
|
873
993
|
const e = this.grid;
|
|
874
|
-
e._activeEditRows = this.#e, e._rowEditSnapshots = this.#
|
|
994
|
+
e._activeEditRows = this.#e, e._rowEditSnapshots = this.#s;
|
|
875
995
|
}
|
|
876
996
|
/**
|
|
877
997
|
* Snapshot original row data and mark as editing.
|
|
878
998
|
*/
|
|
879
|
-
#
|
|
880
|
-
this.#e !== e && (this.#
|
|
999
|
+
#h(e, t) {
|
|
1000
|
+
this.#e !== e && (this.#s.set(e, { ...t }), this.#e = e, this.#c());
|
|
881
1001
|
}
|
|
882
1002
|
/**
|
|
883
1003
|
* Exit editing for a row.
|
|
884
1004
|
*/
|
|
885
|
-
#
|
|
1005
|
+
#n(e, t) {
|
|
886
1006
|
if (this.#e !== e) return;
|
|
887
|
-
const
|
|
1007
|
+
const i = this.grid, r = this.#s.get(e), n = i._rows[e], o = i.findRenderedRowElement?.(e);
|
|
888
1008
|
let a;
|
|
889
1009
|
if (n)
|
|
890
1010
|
try {
|
|
891
|
-
a =
|
|
1011
|
+
a = i.getRowId?.(n);
|
|
892
1012
|
} catch {
|
|
893
1013
|
}
|
|
894
|
-
if (!
|
|
895
|
-
const
|
|
896
|
-
if (isNaN(
|
|
897
|
-
const
|
|
898
|
-
if (!
|
|
899
|
-
const
|
|
900
|
-
if (
|
|
901
|
-
const h = E(
|
|
902
|
-
|
|
1014
|
+
if (!t && o && n && o.querySelectorAll(".cell.editing").forEach((d) => {
|
|
1015
|
+
const c = Number(d.getAttribute("data-col"));
|
|
1016
|
+
if (isNaN(c)) return;
|
|
1017
|
+
const p = i._visibleColumns[c];
|
|
1018
|
+
if (!p) return;
|
|
1019
|
+
const u = d.querySelector("input,textarea,select");
|
|
1020
|
+
if (u) {
|
|
1021
|
+
const m = p.field, h = n[m], g = E(u, p, h);
|
|
1022
|
+
h !== g && this.#u(e, p, g, n);
|
|
903
1023
|
}
|
|
904
|
-
}),
|
|
1024
|
+
}), t && r && n)
|
|
905
1025
|
Object.keys(r).forEach((l) => {
|
|
906
1026
|
n[l] = r[l];
|
|
907
|
-
}), a && this.#
|
|
908
|
-
else if (!
|
|
909
|
-
const l = a ? this.#
|
|
910
|
-
this.emit("row-commit", {
|
|
1027
|
+
}), a && (this.#i.delete(a), this.clearRowInvalid(a));
|
|
1028
|
+
else if (!t && n) {
|
|
1029
|
+
const l = this.#v(r, n), d = a ? this.#i.has(a) : l, c = this.emitCancelable("row-commit", {
|
|
911
1030
|
rowIndex: e,
|
|
912
1031
|
rowId: a ?? "",
|
|
913
1032
|
row: n,
|
|
914
|
-
|
|
1033
|
+
oldValue: r,
|
|
1034
|
+
newValue: n,
|
|
1035
|
+
changed: d,
|
|
915
1036
|
changedRows: this.changedRows,
|
|
916
1037
|
changedRowIds: this.changedRowIds
|
|
917
|
-
})
|
|
1038
|
+
});
|
|
1039
|
+
c && r ? (Object.keys(r).forEach((p) => {
|
|
1040
|
+
n[p] = r[p];
|
|
1041
|
+
}), a && (this.#i.delete(a), this.clearRowInvalid(a))) : !c && l && this.isAnimationEnabled && (this.#l = e);
|
|
918
1042
|
}
|
|
919
|
-
this.#
|
|
920
|
-
for (const l of this.#
|
|
921
|
-
l.startsWith(`${e}:`) && this.#
|
|
1043
|
+
this.#s.delete(e), this.#e = -1, this.#o = -1, this.#c();
|
|
1044
|
+
for (const l of this.#r)
|
|
1045
|
+
l.startsWith(`${e}:`) && this.#r.delete(l);
|
|
922
1046
|
o && (o.querySelectorAll(".cell.editing").forEach((l) => {
|
|
923
|
-
l.classList.remove("editing"),
|
|
924
|
-
}), this.requestRender()), this.#
|
|
1047
|
+
l.classList.remove("editing"), x(l.parentElement);
|
|
1048
|
+
}), this.requestRender()), this.#a = !0, o || (this.#g(i), this.#a = !1);
|
|
925
1049
|
}
|
|
926
1050
|
/**
|
|
927
1051
|
* Commit a single cell value change.
|
|
928
1052
|
* Uses ID-based change tracking for stability when rows are reordered.
|
|
929
1053
|
*/
|
|
930
|
-
#
|
|
931
|
-
const n =
|
|
932
|
-
if (!
|
|
1054
|
+
#u(e, t, i, r) {
|
|
1055
|
+
const n = t.field;
|
|
1056
|
+
if (!w(n)) return;
|
|
933
1057
|
const o = r[n];
|
|
934
|
-
if (o ===
|
|
1058
|
+
if (o === i) return;
|
|
935
1059
|
const a = this.grid;
|
|
936
1060
|
let l;
|
|
937
1061
|
try {
|
|
938
1062
|
l = this.grid.getRowId(r);
|
|
939
1063
|
} catch {
|
|
940
1064
|
}
|
|
941
|
-
const
|
|
1065
|
+
const d = l ? !this.#i.has(l) : !0, c = l ? (g) => this.grid.updateRow(l, g, "cascade") : k;
|
|
1066
|
+
let p = !1;
|
|
1067
|
+
const u = l ? (g) => {
|
|
1068
|
+
p = !0, this.setInvalid(l, n, g ?? "");
|
|
1069
|
+
} : () => {
|
|
1070
|
+
};
|
|
942
1071
|
if (this.emitCancelable("cell-commit", {
|
|
943
1072
|
row: r,
|
|
944
1073
|
rowId: l ?? "",
|
|
945
1074
|
field: n,
|
|
946
1075
|
oldValue: o,
|
|
947
|
-
value:
|
|
1076
|
+
value: i,
|
|
948
1077
|
rowIndex: e,
|
|
949
1078
|
changedRows: this.changedRows,
|
|
950
1079
|
changedRowIds: this.changedRowIds,
|
|
951
|
-
firstTimeForRow:
|
|
952
|
-
updateRow:
|
|
1080
|
+
firstTimeForRow: d,
|
|
1081
|
+
updateRow: c,
|
|
1082
|
+
setInvalid: u
|
|
953
1083
|
})) return;
|
|
954
|
-
r[n] =
|
|
1084
|
+
l && !p && this.isCellInvalid(l, n) && this.clearInvalid(l, n), r[n] = i, l && this.#i.add(l), this.#c(), this.emitPluginEvent("cell-edit-committed", {
|
|
955
1085
|
rowIndex: e,
|
|
956
1086
|
field: n,
|
|
957
1087
|
oldValue: o,
|
|
958
|
-
newValue:
|
|
1088
|
+
newValue: i
|
|
959
1089
|
});
|
|
960
|
-
const
|
|
961
|
-
|
|
1090
|
+
const h = a.findRenderedRowElement?.(e);
|
|
1091
|
+
h && h.classList.add("changed");
|
|
962
1092
|
}
|
|
963
1093
|
/**
|
|
964
1094
|
* Inject an editor into a cell.
|
|
965
1095
|
*/
|
|
966
|
-
#
|
|
967
|
-
if (!
|
|
1096
|
+
#f(e, t, i, r, n, o) {
|
|
1097
|
+
if (!i.editable || n.classList.contains("editing")) return;
|
|
968
1098
|
let a;
|
|
969
1099
|
try {
|
|
970
1100
|
a = this.grid.getRowId(e);
|
|
971
1101
|
} catch {
|
|
972
1102
|
}
|
|
973
|
-
const l = a ? (
|
|
974
|
-
n.classList.add("editing"), this.#
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
let
|
|
978
|
-
const
|
|
979
|
-
|
|
980
|
-
},
|
|
981
|
-
|
|
982
|
-
},
|
|
983
|
-
|
|
984
|
-
|
|
1103
|
+
const l = a ? (f) => this.grid.updateRow(a, f, "cascade") : k, d = w(i.field) ? e[i.field] : void 0;
|
|
1104
|
+
n.classList.add("editing"), this.#r.add(`${t}:${r}`);
|
|
1105
|
+
const c = n.parentElement;
|
|
1106
|
+
c && H(c);
|
|
1107
|
+
let p = !1;
|
|
1108
|
+
const u = (f) => {
|
|
1109
|
+
p || this.#e === -1 || this.#u(t, i, f, e);
|
|
1110
|
+
}, m = () => {
|
|
1111
|
+
p = !0, w(i.field) && (e[i.field] = d);
|
|
1112
|
+
}, h = document.createElement("div");
|
|
1113
|
+
h.className = "tbw-editor-host", n.innerHTML = "", n.appendChild(h), h.addEventListener("keydown", (f) => {
|
|
1114
|
+
f.key === "Enter" && (f.stopPropagation(), f.preventDefault(), p = !0, this.#n(t, !1)), f.key === "Escape" && (f.stopPropagation(), f.preventDefault(), m(), this.#n(t, !0));
|
|
985
1115
|
});
|
|
986
|
-
const
|
|
987
|
-
if (
|
|
988
|
-
this.#h
|
|
989
|
-
else if (typeof
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
|
|
1116
|
+
const g = i, y = g.__editorTemplate, v = G(this.grid, g) ?? N(i), C = d;
|
|
1117
|
+
if (v === "template" && y)
|
|
1118
|
+
this.#m(h, g, e, d, u, m, o, t);
|
|
1119
|
+
else if (typeof v == "string") {
|
|
1120
|
+
const f = document.createElement(v);
|
|
1121
|
+
f.value = C, f.addEventListener("change", () => u(f.value)), h.appendChild(f), o || queueMicrotask(() => {
|
|
1122
|
+
h.querySelector(R)?.focus({ preventScroll: !0 });
|
|
993
1123
|
});
|
|
994
|
-
} else if (typeof
|
|
995
|
-
const
|
|
1124
|
+
} else if (typeof v == "function") {
|
|
1125
|
+
const f = {
|
|
996
1126
|
row: e,
|
|
997
1127
|
rowId: a ?? "",
|
|
998
1128
|
value: C,
|
|
999
|
-
field:
|
|
1000
|
-
column:
|
|
1001
|
-
commit:
|
|
1002
|
-
cancel:
|
|
1129
|
+
field: i.field,
|
|
1130
|
+
column: i,
|
|
1131
|
+
commit: u,
|
|
1132
|
+
cancel: m,
|
|
1003
1133
|
updateRow: l
|
|
1004
|
-
},
|
|
1005
|
-
typeof
|
|
1006
|
-
|
|
1134
|
+
}, b = v(f);
|
|
1135
|
+
typeof b == "string" ? (h.innerHTML = b, $(h, i, u, d)) : b instanceof Node && h.appendChild(b), o || queueMicrotask(() => {
|
|
1136
|
+
h.querySelector(R)?.focus({ preventScroll: !0 });
|
|
1007
1137
|
});
|
|
1008
|
-
} else if (
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
const
|
|
1138
|
+
} else if (v && typeof v == "object") {
|
|
1139
|
+
const f = document.createElement("div");
|
|
1140
|
+
f.setAttribute("data-external-editor", ""), f.setAttribute("data-field", i.field), h.appendChild(f);
|
|
1141
|
+
const b = {
|
|
1012
1142
|
row: e,
|
|
1013
1143
|
rowId: a ?? "",
|
|
1014
1144
|
value: C,
|
|
1015
|
-
field:
|
|
1016
|
-
column:
|
|
1017
|
-
commit:
|
|
1018
|
-
cancel:
|
|
1145
|
+
field: i.field,
|
|
1146
|
+
column: i,
|
|
1147
|
+
commit: u,
|
|
1148
|
+
cancel: m,
|
|
1019
1149
|
updateRow: l
|
|
1020
1150
|
};
|
|
1021
|
-
if (
|
|
1151
|
+
if (v.mount)
|
|
1022
1152
|
try {
|
|
1023
|
-
|
|
1024
|
-
} catch (
|
|
1025
|
-
console.warn(`[tbw-grid] External editor mount error for column '${
|
|
1153
|
+
v.mount({ placeholder: f, context: b, spec: v });
|
|
1154
|
+
} catch (_) {
|
|
1155
|
+
console.warn(`[tbw-grid] External editor mount error for column '${i.field}':`, _);
|
|
1026
1156
|
}
|
|
1027
1157
|
else
|
|
1028
1158
|
this.grid.dispatchEvent(
|
|
1029
|
-
new CustomEvent("mount-external-editor", { detail: { placeholder:
|
|
1159
|
+
new CustomEvent("mount-external-editor", { detail: { placeholder: f, spec: v, context: b } })
|
|
1030
1160
|
);
|
|
1031
1161
|
}
|
|
1032
1162
|
}
|
|
1033
1163
|
/**
|
|
1034
1164
|
* Render a template-based editor.
|
|
1035
1165
|
*/
|
|
1036
|
-
#
|
|
1037
|
-
const
|
|
1038
|
-
if (!
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
row:
|
|
1166
|
+
#m(e, t, i, r, n, o, a, l) {
|
|
1167
|
+
const d = t.__editorTemplate;
|
|
1168
|
+
if (!d) return;
|
|
1169
|
+
const c = d.cloneNode(!0), p = t.__compiledEditor;
|
|
1170
|
+
p ? c.innerHTML = p({
|
|
1171
|
+
row: i,
|
|
1042
1172
|
value: r,
|
|
1043
|
-
field:
|
|
1044
|
-
column:
|
|
1173
|
+
field: t.field,
|
|
1174
|
+
column: t,
|
|
1045
1175
|
commit: n,
|
|
1046
1176
|
cancel: o
|
|
1047
|
-
}) :
|
|
1048
|
-
|
|
1049
|
-
if (!
|
|
1050
|
-
const y =
|
|
1177
|
+
}) : c.querySelectorAll("*").forEach((m) => {
|
|
1178
|
+
m.childNodes.length === 1 && m.firstChild?.nodeType === Node.TEXT_NODE && (m.textContent = m.textContent?.replace(/{{\s*value\s*}}/g, r == null ? "" : String(r)).replace(/{{\s*row\.([a-zA-Z0-9_]+)\s*}}/g, (h, g) => {
|
|
1179
|
+
if (!w(g)) return "";
|
|
1180
|
+
const y = i[g];
|
|
1051
1181
|
return y == null ? "" : String(y);
|
|
1052
1182
|
}) || "");
|
|
1053
1183
|
});
|
|
1054
|
-
const
|
|
1184
|
+
const u = c.querySelector(
|
|
1055
1185
|
"input,textarea,select"
|
|
1056
1186
|
);
|
|
1057
|
-
if (
|
|
1058
|
-
|
|
1059
|
-
let
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
}),
|
|
1063
|
-
const
|
|
1064
|
-
|
|
1065
|
-
}),
|
|
1187
|
+
if (u) {
|
|
1188
|
+
u instanceof HTMLInputElement && u.type === "checkbox" ? u.checked = !!r : u.value = String(r ?? "");
|
|
1189
|
+
let m = !1;
|
|
1190
|
+
u.addEventListener("blur", () => {
|
|
1191
|
+
m || n(E(u, t, r));
|
|
1192
|
+
}), u.addEventListener("keydown", (h) => {
|
|
1193
|
+
const g = h;
|
|
1194
|
+
g.key === "Enter" && (g.stopPropagation(), g.preventDefault(), m = !0, n(E(u, t, r)), this.#n(l, !1)), g.key === "Escape" && (g.stopPropagation(), g.preventDefault(), o(), this.#n(l, !0));
|
|
1195
|
+
}), u instanceof HTMLInputElement && u.type === "checkbox" && u.addEventListener("change", () => n(u.checked)), a || setTimeout(() => u.focus({ preventScroll: !0 }), 0);
|
|
1066
1196
|
}
|
|
1067
|
-
e.appendChild(
|
|
1197
|
+
e.appendChild(c);
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Compare snapshot vs current row to detect if any values changed during this edit session.
|
|
1201
|
+
* Uses shallow comparison of all properties.
|
|
1202
|
+
*/
|
|
1203
|
+
#v(e, t) {
|
|
1204
|
+
if (!e) return !1;
|
|
1205
|
+
const i = e, r = t, n = /* @__PURE__ */ new Set([...Object.keys(i), ...Object.keys(r)]);
|
|
1206
|
+
for (const o of n)
|
|
1207
|
+
if (i[o] !== r[o])
|
|
1208
|
+
return !0;
|
|
1209
|
+
return !1;
|
|
1068
1210
|
}
|
|
1069
1211
|
/**
|
|
1070
1212
|
* Restore focus to cell after exiting edit mode.
|
|
1071
1213
|
*/
|
|
1072
|
-
#
|
|
1214
|
+
#g(e) {
|
|
1073
1215
|
queueMicrotask(() => {
|
|
1074
1216
|
try {
|
|
1075
|
-
const
|
|
1217
|
+
const t = e._focusRow, i = e._focusCol, r = e.findRenderedRowElement?.(t);
|
|
1076
1218
|
if (r) {
|
|
1077
1219
|
Array.from(e._bodyEl.querySelectorAll(".cell-focus")).forEach(
|
|
1078
1220
|
(o) => o.classList.remove("cell-focus")
|
|
1079
1221
|
);
|
|
1080
|
-
const n = r.querySelector(`.cell[data-row="${
|
|
1222
|
+
const n = r.querySelector(`.cell[data-row="${t}"][data-col="${i}"]`);
|
|
1081
1223
|
n && (n.classList.add("cell-focus"), n.setAttribute("aria-selected", "true"), n.hasAttribute("tabindex") || n.setAttribute("tabindex", "-1"), n.focus({ preventScroll: !0 }));
|
|
1082
1224
|
}
|
|
1083
1225
|
} catch {
|
|
@@ -1087,7 +1229,7 @@ class K extends O {
|
|
|
1087
1229
|
// #endregion
|
|
1088
1230
|
}
|
|
1089
1231
|
export {
|
|
1090
|
-
|
|
1091
|
-
|
|
1232
|
+
z as EditingPlugin,
|
|
1233
|
+
N as defaultEditorFor
|
|
1092
1234
|
};
|
|
1093
1235
|
//# sourceMappingURL=index.js.map
|