@toolbox-web/grid 1.12.1 → 1.14.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.
Files changed (98) hide show
  1. package/all.js +1171 -943
  2. package/all.js.map +1 -1
  3. package/index.js +735 -737
  4. package/index.js.map +1 -1
  5. package/lib/core/grid.d.ts.map +1 -1
  6. package/lib/core/internal/row-animation.d.ts.map +1 -1
  7. package/lib/core/internal/sanitize.d.ts.map +1 -1
  8. package/lib/core/internal/validate-config.d.ts.map +1 -1
  9. package/lib/core/plugin/types.d.ts +1 -1
  10. package/lib/core/plugin/types.d.ts.map +1 -1
  11. package/lib/core/types.d.ts +48 -1
  12. package/lib/core/types.d.ts.map +1 -1
  13. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +69 -8
  14. package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
  15. package/lib/plugins/clipboard/index.d.ts +1 -1
  16. package/lib/plugins/clipboard/index.d.ts.map +1 -1
  17. package/lib/plugins/clipboard/index.js +257 -192
  18. package/lib/plugins/clipboard/index.js.map +1 -1
  19. package/lib/plugins/clipboard/types.d.ts +31 -0
  20. package/lib/plugins/clipboard/types.d.ts.map +1 -1
  21. package/lib/plugins/column-virtualization/index.js.map +1 -1
  22. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +8 -0
  23. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  24. package/lib/plugins/context-menu/index.js +75 -60
  25. package/lib/plugins/context-menu/index.js.map +1 -1
  26. package/lib/plugins/context-menu/types.d.ts +7 -0
  27. package/lib/plugins/context-menu/types.d.ts.map +1 -1
  28. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  29. package/lib/plugins/editing/editors.d.ts +2 -2
  30. package/lib/plugins/editing/editors.d.ts.map +1 -1
  31. package/lib/plugins/editing/index.d.ts +1 -1
  32. package/lib/plugins/editing/index.d.ts.map +1 -1
  33. package/lib/plugins/editing/index.js +393 -337
  34. package/lib/plugins/editing/index.js.map +1 -1
  35. package/lib/plugins/editing/types.d.ts +50 -23
  36. package/lib/plugins/editing/types.d.ts.map +1 -1
  37. package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
  38. package/lib/plugins/export/index.js +75 -66
  39. package/lib/plugins/export/index.js.map +1 -1
  40. package/lib/plugins/filtering/index.d.ts +1 -1
  41. package/lib/plugins/filtering/index.d.ts.map +1 -1
  42. package/lib/plugins/filtering/index.js +9 -9
  43. package/lib/plugins/filtering/index.js.map +1 -1
  44. package/lib/plugins/grouping-columns/index.js.map +1 -1
  45. package/lib/plugins/grouping-rows/index.js.map +1 -1
  46. package/lib/plugins/master-detail/index.js +57 -56
  47. package/lib/plugins/master-detail/index.js.map +1 -1
  48. package/lib/plugins/multi-sort/index.js.map +1 -1
  49. package/lib/plugins/pinned-columns/index.js.map +1 -1
  50. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -0
  51. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
  52. package/lib/plugins/pinned-rows/index.js +118 -87
  53. package/lib/plugins/pinned-rows/index.js.map +1 -1
  54. package/lib/plugins/pinned-rows/pinned-rows.d.ts +2 -1
  55. package/lib/plugins/pinned-rows/pinned-rows.d.ts.map +1 -1
  56. package/lib/plugins/pinned-rows/types.d.ts +23 -2
  57. package/lib/plugins/pinned-rows/types.d.ts.map +1 -1
  58. package/lib/plugins/pivot/index.js.map +1 -1
  59. package/lib/plugins/print/index.js.map +1 -1
  60. package/lib/plugins/reorder/index.js.map +1 -1
  61. package/lib/plugins/responsive/index.js +40 -39
  62. package/lib/plugins/responsive/index.js.map +1 -1
  63. package/lib/plugins/row-reorder/index.js.map +1 -1
  64. package/lib/plugins/selection/SelectionPlugin.d.ts +51 -0
  65. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  66. package/lib/plugins/selection/index.js +347 -145
  67. package/lib/plugins/selection/index.js.map +1 -1
  68. package/lib/plugins/selection/types.d.ts +18 -0
  69. package/lib/plugins/selection/types.d.ts.map +1 -1
  70. package/lib/plugins/server-side/index.js.map +1 -1
  71. package/lib/plugins/shared/data-collection.d.ts +33 -0
  72. package/lib/plugins/shared/data-collection.d.ts.map +1 -0
  73. package/lib/plugins/tree/index.js.map +1 -1
  74. package/lib/plugins/undo-redo/index.js.map +1 -1
  75. package/lib/plugins/visibility/index.js.map +1 -1
  76. package/package.json +1 -1
  77. package/public.d.ts +2 -0
  78. package/public.d.ts.map +1 -1
  79. package/themes/dg-theme-bootstrap.css +192 -8
  80. package/themes/dg-theme-material.css +243 -0
  81. package/umd/grid.all.umd.js +42 -42
  82. package/umd/grid.all.umd.js.map +1 -1
  83. package/umd/grid.umd.js +19 -19
  84. package/umd/grid.umd.js.map +1 -1
  85. package/umd/plugins/clipboard.umd.js +5 -5
  86. package/umd/plugins/clipboard.umd.js.map +1 -1
  87. package/umd/plugins/context-menu.umd.js +1 -1
  88. package/umd/plugins/context-menu.umd.js.map +1 -1
  89. package/umd/plugins/editing.umd.js +1 -1
  90. package/umd/plugins/editing.umd.js.map +1 -1
  91. package/umd/plugins/export.umd.js +7 -7
  92. package/umd/plugins/export.umd.js.map +1 -1
  93. package/umd/plugins/filtering.umd.js +1 -1
  94. package/umd/plugins/filtering.umd.js.map +1 -1
  95. package/umd/plugins/pinned-rows.umd.js +1 -1
  96. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  97. package/umd/plugins/selection.umd.js +2 -2
  98. package/umd/plugins/selection.umd.js.map +1 -1
@@ -1,46 +1,46 @@
1
- function k(s) {
2
- s && s.querySelectorAll(".cell-focus").forEach((e) => e.classList.remove("cell-focus"));
1
+ function P(r) {
2
+ r && r.querySelectorAll(".cell-focus").forEach((e) => e.classList.remove("cell-focus"));
3
3
  }
4
- const v = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])', I = document.createElement("template");
5
- I.innerHTML = '<div class="cell" role="gridcell" part="cell"></div>';
6
- const T = document.createElement("template");
7
- T.innerHTML = '<div class="data-grid-row" role="row" part="row"></div>';
8
- function R(s, e) {
9
- if (s._virtualization?.enabled) {
10
- const { rowHeight: l, container: o, viewportEl: a } = s._virtualization, c = o, d = a?.clientHeight ?? c?.clientHeight ?? 0;
11
- if (c && d > 0) {
12
- const h = s._focusRow * l;
13
- h < c.scrollTop ? c.scrollTop = h : h + l > c.scrollTop + d && (c.scrollTop = h - d + l);
4
+ const w = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])', M = document.createElement("template");
5
+ M.innerHTML = '<div class="cell" role="gridcell" part="cell"></div>';
6
+ const H = document.createElement("template");
7
+ H.innerHTML = '<div class="data-grid-row" role="row" part="row"></div>';
8
+ function L(r, e) {
9
+ if (r._virtualization?.enabled) {
10
+ const { rowHeight: l, container: o, viewportEl: c } = r._virtualization, a = o, d = c?.clientHeight ?? a?.clientHeight ?? 0;
11
+ if (a && d > 0) {
12
+ const g = r._focusRow * l;
13
+ g < a.scrollTop ? a.scrollTop = g : g + l > a.scrollTop + d && (a.scrollTop = g - d + l);
14
14
  }
15
15
  }
16
- const t = s._activeEditRows !== void 0 && s._activeEditRows !== -1;
17
- t || s.refreshVirtualWindow(!1), k(s._bodyEl), Array.from(s._bodyEl.querySelectorAll('[aria-selected="true"]')).forEach((l) => {
16
+ const t = r._activeEditRows !== void 0 && r._activeEditRows !== -1;
17
+ t || r.refreshVirtualWindow(!1), P(r._bodyEl), Array.from(r._bodyEl.querySelectorAll('[aria-selected="true"]')).forEach((l) => {
18
18
  l.setAttribute("aria-selected", "false");
19
19
  });
20
- const i = s._focusRow, n = s._virtualization.start ?? 0, r = s._virtualization.end ?? s._rows.length;
21
- if (i >= n && i < r) {
22
- const l = s._bodyEl.querySelectorAll(".data-grid-row")[i - n];
23
- let o = l?.children[s._focusCol];
24
- if ((!o || !o.classList?.contains("cell")) && (o = l?.querySelector(`.cell[data-col="${s._focusCol}"]`) ?? l?.querySelector(".cell[data-col]")), o) {
20
+ const i = r._focusRow, n = r._virtualization.start ?? 0, s = r._virtualization.end ?? r._rows.length;
21
+ if (i >= n && i < s) {
22
+ const l = r._bodyEl.querySelectorAll(".data-grid-row")[i - n];
23
+ let o = l?.children[r._focusCol];
24
+ if ((!o || !o.classList?.contains("cell")) && (o = l?.querySelector(`.cell[data-col="${r._focusCol}"]`) ?? l?.querySelector(".cell[data-col]")), o) {
25
25
  o.classList.add("cell-focus"), o.setAttribute("aria-selected", "true");
26
- const a = s.querySelector(".tbw-scroll-area");
27
- if (a && o && (!t || e?.forceHorizontalScroll))
26
+ const c = r.querySelector(".tbw-scroll-area");
27
+ if (c && o && (!t || e?.forceHorizontalScroll))
28
28
  if (e?.forceScrollLeft)
29
- a.scrollLeft = 0;
29
+ c.scrollLeft = 0;
30
30
  else if (e?.forceScrollRight)
31
- a.scrollLeft = a.scrollWidth - a.clientWidth;
31
+ c.scrollLeft = c.scrollWidth - c.clientWidth;
32
32
  else {
33
- const c = s._getHorizontalScrollOffsets?.(l ?? void 0, o) ?? { left: 0, right: 0 };
34
- if (!c.skipScroll) {
35
- const d = o.getBoundingClientRect(), h = a.getBoundingClientRect(), u = d.left - h.left + a.scrollLeft, m = u + d.width, p = a.scrollLeft + c.left, g = a.scrollLeft + a.clientWidth - c.right;
36
- u < p ? a.scrollLeft = u - c.left : m > g && (a.scrollLeft = m - a.clientWidth + c.right);
33
+ const a = r._getHorizontalScrollOffsets?.(l ?? void 0, o) ?? { left: 0, right: 0 };
34
+ if (!a.skipScroll) {
35
+ const d = o.getBoundingClientRect(), g = c.getBoundingClientRect(), f = d.left - g.left + c.scrollLeft, E = f + d.width, p = c.scrollLeft + a.left, m = c.scrollLeft + c.clientWidth - a.right;
36
+ f < p ? c.scrollLeft = f - a.left : E > m && (c.scrollLeft = E - c.clientWidth + a.right);
37
37
  }
38
38
  }
39
- if (s._activeEditRows !== void 0 && s._activeEditRows !== -1 && o.classList.contains("editing")) {
40
- const c = o.querySelector(v);
41
- if (c && document.activeElement !== c)
39
+ if (r._activeEditRows !== void 0 && r._activeEditRows !== -1 && o.classList.contains("editing")) {
40
+ const a = o.querySelector(w);
41
+ if (a && document.activeElement !== a)
42
42
  try {
43
- c.focus({ preventScroll: !0 });
43
+ a.focus({ preventScroll: !0 });
44
44
  } catch {
45
45
  }
46
46
  } else if (!o.contains(document.activeElement)) {
@@ -53,7 +53,7 @@ function R(s, e) {
53
53
  }
54
54
  }
55
55
  }
56
- 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 = {
56
+ const I = '<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>', D = {
57
57
  expand: "▶",
58
58
  collapse: "▼",
59
59
  sortAsc: "▲",
@@ -62,11 +62,11 @@ const L = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
62
62
  submenuArrow: "▶",
63
63
  dragHandle: "⋮⋮",
64
64
  toolPanel: "☰",
65
- filter: L,
66
- filterActive: L,
65
+ filter: I,
66
+ filterActive: I,
67
67
  print: "🖨️"
68
68
  };
69
- class P {
69
+ class O {
70
70
  /**
71
71
  * Plugin dependencies - declare other plugins this one requires.
72
72
  *
@@ -356,7 +356,7 @@ class P {
356
356
  */
357
357
  get gridIcons() {
358
358
  const e = this.grid?.gridConfig?.icons ?? {};
359
- return { ...q, ...e };
359
+ return { ...D, ...e };
360
360
  }
361
361
  // #region Animation Helpers
362
362
  /**
@@ -432,125 +432,125 @@ class P {
432
432
  }
433
433
  // #endregion
434
434
  }
435
- const M = "@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:not(.tbw-grid-mode) .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}}";
436
- function D(s) {
437
- const e = s.options;
435
+ const x = "@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:not(.tbw-grid-mode) .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}}";
436
+ function B(r) {
437
+ const e = r.options;
438
438
  return e ? typeof e == "function" ? e() : e : [];
439
439
  }
440
- function x(s) {
440
+ function N(r) {
441
441
  return (e) => {
442
- const t = s.editorParams, i = document.createElement("input");
442
+ const t = r.editorParams, i = document.createElement("input");
443
443
  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);
444
444
  const n = () => e.commit(i.value === "" ? null : Number(i.value));
445
- return i.addEventListener("blur", n), i.addEventListener("keydown", (r) => {
446
- r.key === "Enter" && n(), r.key === "Escape" && e.cancel();
445
+ return i.addEventListener("blur", n), i.addEventListener("keydown", (s) => {
446
+ s.key === "Enter" && n(), s.key === "Escape" && e.cancel();
447
447
  }), i;
448
448
  };
449
449
  }
450
- function H() {
451
- return (s) => {
450
+ function $() {
451
+ return (r) => {
452
452
  const e = document.createElement("input");
453
- return e.type = "checkbox", e.checked = !!s.value, e.addEventListener("change", () => s.commit(e.checked)), e;
453
+ return e.type = "checkbox", e.checked = !!r.value, e.addEventListener("change", () => r.commit(e.checked)), e;
454
454
  };
455
455
  }
456
- function O(s) {
456
+ function z(r) {
457
457
  return (e) => {
458
- const t = s.editorParams, i = document.createElement("input");
458
+ const t = r.editorParams, i = document.createElement("input");
459
459
  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);
460
460
  const n = () => {
461
461
  typeof e.value == "string" ? e.commit(i.value) : e.commit(i.valueAsDate);
462
462
  };
463
- return i.addEventListener("change", n), i.addEventListener("keydown", (r) => {
464
- r.key === "Escape" && e.cancel();
463
+ return i.addEventListener("change", n), i.addEventListener("keydown", (s) => {
464
+ s.key === "Escape" && e.cancel();
465
465
  }), i;
466
466
  };
467
467
  }
468
- function B(s) {
468
+ function G(r) {
469
469
  return (e) => {
470
- const t = s.editorParams, i = document.createElement("select");
471
- if (s.multi && (i.multiple = !0), t?.includeEmpty) {
470
+ const t = r.editorParams, i = document.createElement("select");
471
+ if (r.multi && (i.multiple = !0), t?.includeEmpty) {
472
472
  const l = document.createElement("option");
473
473
  l.value = "", l.textContent = t.emptyLabel ?? "", i.appendChild(l);
474
474
  }
475
- D(s).forEach((l) => {
475
+ B(r).forEach((l) => {
476
476
  const o = document.createElement("option");
477
- o.value = String(l.value), o.textContent = l.label, (s.multi && Array.isArray(e.value) && e.value.includes(l.value) || !s.multi && e.value === l.value) && (o.selected = !0), i.appendChild(o);
477
+ o.value = String(l.value), o.textContent = l.label, (r.multi && Array.isArray(e.value) && e.value.includes(l.value) || !r.multi && e.value === l.value) && (o.selected = !0), i.appendChild(o);
478
478
  });
479
- const r = () => {
480
- if (s.multi) {
479
+ const s = () => {
480
+ if (r.multi) {
481
481
  const l = Array.from(i.selectedOptions).map((o) => o.value);
482
482
  e.commit(l);
483
483
  } else
484
484
  e.commit(i.value);
485
485
  };
486
- return i.addEventListener("change", r), i.addEventListener("blur", r), i.addEventListener("keydown", (l) => {
486
+ return i.addEventListener("change", s), i.addEventListener("blur", s), i.addEventListener("keydown", (l) => {
487
487
  l.key === "Escape" && e.cancel();
488
488
  }), i;
489
489
  };
490
490
  }
491
- function N(s) {
491
+ function F(r) {
492
492
  return (e) => {
493
- const t = s.editorParams, i = document.createElement("input");
493
+ const t = r.editorParams, i = document.createElement("input");
494
494
  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);
495
495
  const n = () => {
496
- const r = i.value;
497
- typeof e.value == "number" && r !== "" ? e.commit(Number(r)) : e.commit(r);
496
+ const s = i.value;
497
+ (e.value === null || e.value === void 0) && s === "" || typeof e.value == "string" && s === e.value.replace(/[\n\r]/g, "") || (typeof e.value == "number" && s !== "" ? e.commit(Number(s)) : e.commit(s));
498
498
  };
499
- return i.addEventListener("blur", n), i.addEventListener("keydown", (r) => {
500
- r.key === "Enter" && n(), r.key === "Escape" && e.cancel();
499
+ return i.addEventListener("blur", n), i.addEventListener("keydown", (s) => {
500
+ s.key === "Enter" && n(), s.key === "Escape" && e.cancel();
501
501
  }), i;
502
502
  };
503
503
  }
504
- function z(s) {
505
- switch (s.type) {
504
+ function j(r) {
505
+ switch (r.type) {
506
506
  case "number":
507
- return x(s);
507
+ return N(r);
508
508
  case "boolean":
509
- return H();
509
+ return $();
510
510
  case "date":
511
- return O(s);
511
+ return z(r);
512
512
  case "select":
513
- return B(s);
513
+ return G(r);
514
514
  default:
515
- return N(s);
515
+ return F(r);
516
516
  }
517
517
  }
518
- function G(s, e) {
518
+ function W(r, e) {
519
519
  if (e.editor) return e.editor;
520
520
  if (e.__editorTemplate) return "template";
521
521
  if (!e.type) return;
522
- const i = s.effectiveConfig?.typeDefaults;
522
+ const i = r.effectiveConfig?.typeDefaults;
523
523
  if (i?.[e.type]?.editor)
524
524
  return i[e.type].editor;
525
- const n = s.__frameworkAdapter;
525
+ const n = r.__frameworkAdapter;
526
526
  if (n?.getTypeDefault) {
527
- const r = n.getTypeDefault(e.type);
528
- if (r?.editor)
529
- return r.editor;
527
+ const s = n.getTypeDefault(e.type);
528
+ if (s?.editor)
529
+ return s.editor;
530
530
  }
531
531
  }
532
- function C(s) {
533
- return !(typeof s != "string" || s === "__proto__" || s === "constructor" || s === "prototype");
532
+ function S(r) {
533
+ return !(typeof r != "string" || r === "__proto__" || r === "constructor" || r === "prototype");
534
534
  }
535
- function $(s) {
536
- const e = (s.__editingCellCount ?? 0) + 1;
537
- s.__editingCellCount = e, s.setAttribute("data-has-editing", "");
535
+ function K(r) {
536
+ const e = (r.__editingCellCount ?? 0) + 1;
537
+ r.__editingCellCount = e, r.setAttribute("data-has-editing", "");
538
538
  }
539
- function F(s) {
540
- s.__editingCellCount = 0, s.removeAttribute("data-has-editing");
539
+ function U(r) {
540
+ r.__editingCellCount = 0, r.removeAttribute("data-has-editing");
541
541
  }
542
- function y(s, e, t) {
543
- 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) : t == null && s.value === "" ? t : s.value : e?.type === "number" && s.value !== "" || typeof t == "number" && s.value !== "" ? Number(s.value) : t == null && s.value === "" ? t : s.value;
542
+ function _(r, e, t) {
543
+ return r instanceof HTMLInputElement ? r.type === "checkbox" ? r.checked : r.type === "number" ? r.value === "" ? null : Number(r.value) : r.type === "date" ? typeof t == "string" ? r.value : r.valueAsDate : typeof t == "number" ? r.value === "" ? null : Number(r.value) : t == null && r.value === "" || typeof t == "string" && r.value === t.replace(/[\n\r]/g, "") ? t : r.value : e?.type === "number" && r.value !== "" || typeof t == "number" && r.value !== "" ? Number(r.value) : t == null && r.value === "" ? t : r.value;
544
544
  }
545
- function A(s) {
545
+ function T(r) {
546
546
  }
547
- function j(s, e, t, i) {
548
- const n = s.querySelector("input,textarea,select");
547
+ function Q(r, e, t, i) {
548
+ const n = r.querySelector("input,textarea,select");
549
549
  n && (n.addEventListener("blur", () => {
550
- t(y(n, e, i));
551
- }), n instanceof HTMLInputElement && n.type === "checkbox" ? n.addEventListener("change", () => t(n.checked)) : n instanceof HTMLSelectElement && n.addEventListener("change", () => t(y(n, e, i))));
550
+ t(_(n, e, i));
551
+ }), n instanceof HTMLInputElement && n.type === "checkbox" ? n.addEventListener("change", () => t(n.checked)) : n instanceof HTMLSelectElement && n.addEventListener("change", () => t(_(n, e, i))));
552
552
  }
553
- class W extends P {
553
+ class X extends O {
554
554
  /**
555
555
  * Plugin manifest - declares owned properties for configuration validation.
556
556
  * @internal
@@ -590,7 +590,7 @@ class W extends P {
590
590
  /** @internal */
591
591
  name = "editing";
592
592
  /** @internal */
593
- styles = M;
593
+ styles = x;
594
594
  /** @internal */
595
595
  get defaultConfig() {
596
596
  return {
@@ -608,17 +608,23 @@ class W extends P {
608
608
  /** Currently active edit row index, or -1 if not editing */
609
609
  #e = -1;
610
610
  /** Currently active edit column index, or -1 if not editing */
611
- #c = -1;
611
+ #d = -1;
612
612
  /** Snapshots of row data before editing started */
613
613
  #l = /* @__PURE__ */ new Map();
614
614
  /** Set of row IDs that have been modified (ID-based for stability) */
615
- #r = /* @__PURE__ */ new Set();
615
+ #s = /* @__PURE__ */ new Set();
616
616
  /** Set of cells currently in edit mode: "rowIndex:colIndex" */
617
617
  #o = /* @__PURE__ */ new Set();
618
+ /**
619
+ * Value-change callbacks for active editors.
620
+ * Keyed by "rowIndex:field" → callback that pushes updated values to the editor.
621
+ * Populated during #injectEditor, cleaned up when editors are removed.
622
+ */
623
+ #c = /* @__PURE__ */ new Map();
618
624
  /** Flag to restore focus after next render (used when exiting edit mode) */
619
- #d = !1;
625
+ #u = !1;
620
626
  /** Row index pending animation after render, or -1 if none */
621
- #u = -1;
627
+ #f = -1;
622
628
  /**
623
629
  * Invalid cell tracking: Map<rowId, Map<field, message>>
624
630
  * Used for validation feedback without canceling edits.
@@ -630,7 +636,7 @@ class W extends P {
630
636
  * When false: arrow keys navigate between cells (navigation mode).
631
637
  * Escape switches to navigation mode, Enter switches to edit mode.
632
638
  */
633
- #s = !1;
639
+ #r = !1;
634
640
  /**
635
641
  * In grid mode, when true, prevents inputs from auto-focusing.
636
642
  * This is set when Escape is pressed (navigation mode) and cleared
@@ -649,8 +655,8 @@ class W extends P {
649
655
  }), Object.defineProperty(e, "changedRowIds", {
650
656
  get: () => this.changedRowIds,
651
657
  configurable: !0
652
- }), e.resetChangedRows = (n) => this.resetChangedRows(n), e.beginBulkEdit = (n, r) => {
653
- r && this.beginCellEdit(n, r);
658
+ }), e.resetChangedRows = (n) => this.resetChangedRows(n), e.beginBulkEdit = (n, s) => {
659
+ s && this.beginCellEdit(n, s);
654
660
  }, document.addEventListener(
655
661
  "keydown",
656
662
  (n) => {
@@ -665,52 +671,61 @@ class W extends P {
665
671
  "mousedown",
666
672
  (n) => {
667
673
  if (this.#t || this.#e === -1) return;
668
- const r = i.findRenderedRowElement?.(this.#e);
669
- !r || (n.composedPath && n.composedPath() || []).includes(r) || this.config.onBeforeEditClose && this.config.onBeforeEditClose(n) === !1 || queueMicrotask(() => {
674
+ const s = i.findRenderedRowElement?.(this.#e);
675
+ !s || (n.composedPath && n.composedPath() || []).includes(s) || this.config.onBeforeEditClose && this.config.onBeforeEditClose(n) === !1 || queueMicrotask(() => {
670
676
  this.#e !== -1 && this.#n(this.#e, !1);
671
677
  });
672
678
  },
673
679
  { signal: t }
680
+ ), this.gridElement.addEventListener(
681
+ "cell-change",
682
+ (n) => {
683
+ const s = n.detail;
684
+ if (s.source === "user") return;
685
+ const l = `${s.rowIndex}:${s.field}`, o = this.#c.get(l);
686
+ o && o(s.newValue);
687
+ },
688
+ { signal: t }
674
689
  ), this.#t && (this.gridElement.classList.add("tbw-grid-mode"), this.requestRender(), this.gridElement.addEventListener(
675
690
  "focusin",
676
691
  (n) => {
677
- const r = n.target;
678
- if (r.matches(v)) {
692
+ const s = n.target;
693
+ if (s.matches(w)) {
679
694
  if (this.#a) {
680
- r.blur(), this.gridElement.focus();
695
+ s.blur(), this.gridElement.focus();
681
696
  return;
682
697
  }
683
- this.#s = !0;
698
+ this.#r = !0;
684
699
  }
685
700
  },
686
701
  { signal: t }
687
702
  ), this.gridElement.addEventListener(
688
703
  "focusout",
689
704
  (n) => {
690
- const r = n.relatedTarget;
691
- (!r || !this.gridElement.contains(r) || !r.matches(v)) && (this.#s = !1);
705
+ const s = n.relatedTarget;
706
+ (!s || !this.gridElement.contains(s) || !s.matches(w)) && (this.#r = !1);
692
707
  },
693
708
  { signal: t }
694
709
  ), this.gridElement.addEventListener(
695
710
  "keydown",
696
711
  (n) => {
697
- if (n.key === "Escape" && this.#s) {
698
- const r = document.activeElement;
699
- r && this.gridElement.contains(r) && (r.blur(), this.gridElement.focus()), this.#s = !1, this.#a = !0, n.preventDefault(), n.stopPropagation();
712
+ if (n.key === "Escape" && this.#r) {
713
+ const s = document.activeElement;
714
+ s && this.gridElement.contains(s) && (s.blur(), this.gridElement.focus()), this.#r = !1, this.#a = !0, n.preventDefault(), n.stopPropagation();
700
715
  }
701
716
  },
702
717
  { capture: !0, signal: t }
703
718
  ), this.gridElement.addEventListener(
704
719
  "mousedown",
705
720
  (n) => {
706
- n.target.matches(v) && (this.#a = !1);
721
+ n.target.matches(w) && (this.#a = !1);
707
722
  },
708
723
  { signal: t }
709
724
  ));
710
725
  }
711
726
  /** @internal */
712
727
  detach() {
713
- this.gridElement.classList.remove("tbw-grid-mode"), this.#e = -1, this.#c = -1, this.#l.clear(), this.#r.clear(), this.#o.clear(), this.#s = !1, this.#a = !1, super.detach();
728
+ this.gridElement.classList.remove("tbw-grid-mode"), this.#e = -1, this.#d = -1, this.#l.clear(), this.#s.clear(), this.#o.clear(), this.#c.clear(), this.#r = !1, this.#a = !1, super.detach();
714
729
  }
715
730
  /**
716
731
  * Handle plugin queries.
@@ -734,8 +749,8 @@ class W extends P {
734
749
  if (i === !1 || i === "manual" || i !== "click" && i !== "dblclick") return !1;
735
750
  const n = e.originalEvent.type === "dblclick";
736
751
  if (i === "click" && n || i === "dblclick" && !n) return !1;
737
- const { rowIndex: r } = e;
738
- return t._columns?.some((o) => o.editable) ? (e.originalEvent.stopPropagation(), this.beginBulkEdit(r), !0) : !1;
752
+ const { rowIndex: s } = e;
753
+ return t._columns?.some((o) => o.editable) ? (e.originalEvent.stopPropagation(), this.beginBulkEdit(s), !0) : !1;
739
754
  }
740
755
  /**
741
756
  * Handle keyboard events for edit lifecycle.
@@ -744,72 +759,72 @@ class W extends P {
744
759
  onKeyDown(e) {
745
760
  const t = this.grid;
746
761
  if (e.key === "Escape") {
747
- if (this.#t && this.#s) {
762
+ if (this.#t && this.#r) {
748
763
  const i = document.activeElement;
749
- return i && this.gridElement.contains(i) && i.blur(), this.#s = !1, this.requestAfterRender(), !0;
764
+ return i && this.gridElement.contains(i) && i.blur(), this.#r = !1, this.requestAfterRender(), !0;
750
765
  }
751
766
  if (this.#e !== -1 && !this.#t)
752
767
  return this.config.onBeforeEditClose && this.config.onBeforeEditClose(e) === !1 || this.#n(this.#e, !0), !0;
753
768
  }
754
- if (this.#t && !this.#s && (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "ArrowLeft" || e.key === "ArrowRight"))
769
+ if (this.#t && !this.#r && (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "ArrowLeft" || e.key === "ArrowRight"))
755
770
  return !1;
756
771
  if ((e.key === "ArrowUp" || e.key === "ArrowDown") && this.#e !== -1 && !this.#t) {
757
772
  if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(e) === !1)
758
773
  return !0;
759
774
  const i = t._rows.length - 1, n = this.#e;
760
- return this.#n(n, !1), e.key === "ArrowDown" ? t._focusRow = Math.min(i, t._focusRow + 1) : t._focusRow = Math.max(0, t._focusRow - 1), e.preventDefault(), R(t), this.requestAfterRender(), !0;
775
+ return this.#n(n, !1), e.key === "ArrowDown" ? t._focusRow = Math.min(i, t._focusRow + 1) : t._focusRow = Math.max(0, t._focusRow - 1), e.preventDefault(), L(t), this.requestAfterRender(), !0;
761
776
  }
762
777
  if (e.key === "Tab" && (this.#e !== -1 || this.#t)) {
763
778
  e.preventDefault();
764
779
  const i = !e.shiftKey;
765
- return this.#b(i), !0;
780
+ return this.#y(i), !0;
766
781
  }
767
782
  if (e.key === " " || e.key === "Spacebar") {
768
783
  if (this.#e !== -1)
769
784
  return !1;
770
785
  const i = t._focusRow, n = t._focusCol;
771
786
  if (i >= 0 && n >= 0) {
772
- const r = t._visibleColumns[n], l = t._rows[i];
773
- if (r?.editable && r.type === "boolean" && l) {
774
- const o = r.field;
775
- if (C(o)) {
776
- const c = !l[o];
777
- return this.#p(i, r, c, l), e.preventDefault(), this.requestRender(), !0;
787
+ const s = t._visibleColumns[n], l = t._rows[i];
788
+ if (s?.editable && s.type === "boolean" && l) {
789
+ const o = s.field;
790
+ if (S(o)) {
791
+ const a = !l[o];
792
+ return this.#m(i, s, a, l), e.preventDefault(), this.requestRender(), !0;
778
793
  }
779
794
  }
780
795
  }
781
796
  return !1;
782
797
  }
783
798
  if (e.key === "Enter" && !e.shiftKey) {
784
- if (this.#t && !this.#s)
785
- return this.#v(), !0;
799
+ if (this.#t && !this.#r)
800
+ return this.#b(), !0;
786
801
  if (this.#e !== -1)
787
802
  return !!(this.config.onBeforeEditClose && this.config.onBeforeEditClose(e) === !1);
788
803
  const i = this.config.editOn ?? t.effectiveConfig?.editOn;
789
804
  if (i === !1 || i === "manual") return !1;
790
- const n = t._focusRow, r = t._focusCol;
805
+ const n = t._focusRow, s = t._focusCol;
791
806
  if (n >= 0 && t._columns?.some((o) => o.editable)) {
792
- const o = t._visibleColumns[r], a = t._rows[n], c = o?.field ?? "", d = c && a ? a[c] : void 0, h = this.gridElement.querySelector(`[data-row="${n}"][data-col="${r}"]`), u = new CustomEvent("cell-activate", {
807
+ const o = t._visibleColumns[s], c = t._rows[n], a = o?.field ?? "", d = a && c ? c[a] : void 0, g = this.gridElement.querySelector(`[data-row="${n}"][data-col="${s}"]`), f = new CustomEvent("cell-activate", {
793
808
  cancelable: !0,
794
809
  bubbles: !0,
795
810
  detail: {
796
811
  rowIndex: n,
797
- colIndex: r,
798
- field: c,
812
+ colIndex: s,
813
+ field: a,
799
814
  value: d,
800
- row: a,
801
- cellEl: h,
815
+ row: c,
816
+ cellEl: g,
802
817
  trigger: "keyboard",
803
818
  originalEvent: e
804
819
  }
805
820
  });
806
- this.gridElement.dispatchEvent(u);
807
- const m = new CustomEvent("activate-cell", {
821
+ this.gridElement.dispatchEvent(f);
822
+ const E = new CustomEvent("activate-cell", {
808
823
  cancelable: !0,
809
824
  bubbles: !0,
810
- detail: { row: n, col: r }
825
+ detail: { row: n, col: s }
811
826
  });
812
- return this.gridElement.dispatchEvent(m), u.defaultPrevented || m.defaultPrevented ? (e.preventDefault(), !0) : (this.beginBulkEdit(n), !0);
827
+ return this.gridElement.dispatchEvent(E), f.defaultPrevented || E.defaultPrevented ? (e.preventDefault(), !0) : (this.beginBulkEdit(n), !0);
813
828
  }
814
829
  return !1;
815
830
  }
@@ -824,17 +839,17 @@ class W extends P {
824
839
  */
825
840
  processColumns(e) {
826
841
  const t = this.grid, i = t.effectiveConfig?.typeDefaults, n = t.__frameworkAdapter;
827
- return !i && !n?.getTypeDefault ? e : e.map((r) => {
828
- if (!r.type) return r;
842
+ return !i && !n?.getTypeDefault ? e : e.map((s) => {
843
+ if (!s.type) return s;
829
844
  let l;
830
- if (i?.[r.type]?.editorParams && (l = i[r.type].editorParams), !l && n?.getTypeDefault) {
831
- const o = n.getTypeDefault(r.type);
845
+ if (i?.[s.type]?.editorParams && (l = i[s.type].editorParams), !l && n?.getTypeDefault) {
846
+ const o = n.getTypeDefault(s.type);
832
847
  o?.editorParams && (l = o.editorParams);
833
848
  }
834
849
  return l ? {
835
- ...r,
836
- editorParams: { ...l, ...r.editorParams }
837
- } : r;
850
+ ...s,
851
+ editorParams: { ...l, ...s.editorParams }
852
+ } : s;
838
853
  });
839
854
  }
840
855
  /**
@@ -845,18 +860,18 @@ class W extends P {
845
860
  */
846
861
  afterRender() {
847
862
  const e = this.grid;
848
- if (this.#d && (this.#d = !1, this.#E(e)), this.#u !== -1) {
849
- const t = this.#u;
850
- this.#u = -1, e.animateRow?.(t, "change");
863
+ if (this.#u && (this.#u = !1, this.#v(e)), this.#f !== -1) {
864
+ const t = this.#f;
865
+ this.#f = -1, e.animateRow?.(t, "change");
851
866
  }
852
867
  if (!this.#t && this.#o.size !== 0)
853
868
  for (const t of this.#o) {
854
- const [i, n] = t.split(":"), r = parseInt(i, 10), l = parseInt(n, 10), o = e.findRenderedRowElement?.(r);
869
+ const [i, n] = t.split(":"), s = parseInt(i, 10), l = parseInt(n, 10), o = e.findRenderedRowElement?.(s);
855
870
  if (!o) continue;
856
- const a = o.querySelector(`.cell[data-col="${l}"]`);
857
- if (!a || a.classList.contains("editing")) continue;
858
- const c = e._rows[r], d = e._visibleColumns[l];
859
- c && d && this.#g(c, r, d, l, a, !0);
871
+ const c = o.querySelector(`.cell[data-col="${l}"]`);
872
+ if (!c || c.classList.contains("editing")) continue;
873
+ const a = e._rows[s], d = e._visibleColumns[l];
874
+ a && d && this.#p(a, s, d, l, c, !0);
860
875
  }
861
876
  }
862
877
  /**
@@ -866,8 +881,8 @@ class W extends P {
866
881
  */
867
882
  afterCellRender(e) {
868
883
  if (!this.#t) return;
869
- const { row: t, rowIndex: i, column: n, colIndex: r, cellElement: l } = e;
870
- n.editable && (l.classList.contains("editing") || this.#g(t, i, n, r, l, !0));
884
+ const { row: t, rowIndex: i, column: n, colIndex: s, cellElement: l } = e;
885
+ n.editable && (l.classList.contains("editing") || this.#p(t, i, n, s, l, !0));
871
886
  }
872
887
  /**
873
888
  * On scroll render, reapply editors to recycled cells.
@@ -884,7 +899,7 @@ class W extends P {
884
899
  */
885
900
  get changedRows() {
886
901
  const e = [];
887
- for (const t of this.#r) {
902
+ for (const t of this.#s) {
888
903
  const i = this.grid.getRow(t);
889
904
  i && e.push(i);
890
905
  }
@@ -894,7 +909,7 @@ class W extends P {
894
909
  * Get IDs of all modified rows.
895
910
  */
896
911
  get changedRowIds() {
897
- return Array.from(this.#r);
912
+ return Array.from(this.#s);
898
913
  }
899
914
  /**
900
915
  * Get the currently active edit row index, or -1 if not editing.
@@ -906,7 +921,7 @@ class W extends P {
906
921
  * Get the currently active edit column index, or -1 if not editing.
907
922
  */
908
923
  get activeEditCol() {
909
- return this.#c;
924
+ return this.#d;
910
925
  }
911
926
  /**
912
927
  * Check if a specific row is currently being edited.
@@ -929,7 +944,7 @@ class W extends P {
929
944
  if (!i) return !1;
930
945
  try {
931
946
  const n = t.getRowId?.(i);
932
- return n ? this.#r.has(n) : !1;
947
+ return n ? this.#s.has(n) : !1;
933
948
  } catch {
934
949
  return !1;
935
950
  }
@@ -939,7 +954,7 @@ class W extends P {
939
954
  * @param rowId - Row ID to check
940
955
  */
941
956
  isRowChangedById(e) {
942
- return this.#r.has(e);
957
+ return this.#s.has(e);
943
958
  }
944
959
  // #region Cell Validation
945
960
  /**
@@ -965,7 +980,7 @@ class W extends P {
965
980
  */
966
981
  setInvalid(e, t, i = "") {
967
982
  let n = this.#i.get(e);
968
- n || (n = /* @__PURE__ */ new Map(), this.#i.set(e, n)), n.set(t, i), this.#f(e, t, !0);
983
+ n || (n = /* @__PURE__ */ new Map(), this.#i.set(e, n)), n.set(t, i), this.#h(e, t, !0);
969
984
  }
970
985
  /**
971
986
  * Clear the invalid state for a specific cell.
@@ -975,7 +990,7 @@ class W extends P {
975
990
  */
976
991
  clearInvalid(e, t) {
977
992
  const i = this.#i.get(e);
978
- i && (i.delete(t), i.size === 0 && this.#i.delete(e)), this.#f(e, t, !1);
993
+ i && (i.delete(t), i.size === 0 && this.#i.delete(e)), this.#h(e, t, !1);
979
994
  }
980
995
  /**
981
996
  * Clear all invalid cells for a specific row.
@@ -986,7 +1001,7 @@ class W extends P {
986
1001
  const t = this.#i.get(e);
987
1002
  if (t) {
988
1003
  const i = Array.from(t.keys());
989
- this.#i.delete(e), i.forEach((n) => this.#f(e, n, !1));
1004
+ this.#i.delete(e), i.forEach((n) => this.#h(e, n, !1));
990
1005
  }
991
1006
  }
992
1007
  /**
@@ -995,7 +1010,7 @@ class W extends P {
995
1010
  clearAllInvalid() {
996
1011
  const e = Array.from(this.#i.entries());
997
1012
  this.#i.clear(), e.forEach(([t, i]) => {
998
- i.forEach((n, r) => this.#f(t, r, !1));
1013
+ i.forEach((n, s) => this.#h(t, s, !1));
999
1014
  });
1000
1015
  }
1001
1016
  /**
@@ -1040,9 +1055,9 @@ class W extends P {
1040
1055
  /**
1041
1056
  * Sync the data-invalid attribute on a cell element.
1042
1057
  */
1043
- #f(e, t, i) {
1044
- const n = this.grid, r = n._visibleColumns?.findIndex((d) => d.field === t);
1045
- if (r === -1 || r === void 0) return;
1058
+ #h(e, t, i) {
1059
+ const n = this.grid, s = n._visibleColumns?.findIndex((d) => d.field === t);
1060
+ if (s === -1 || s === void 0) return;
1046
1061
  const o = n._rows?.findIndex((d) => {
1047
1062
  try {
1048
1063
  return n.getRowId?.(d) === e;
@@ -1051,14 +1066,14 @@ class W extends P {
1051
1066
  }
1052
1067
  });
1053
1068
  if (o === -1 || o === void 0) return;
1054
- const c = n.findRenderedRowElement?.(o)?.querySelector(`.cell[data-col="${r}"]`);
1055
- if (c)
1069
+ const a = n.findRenderedRowElement?.(o)?.querySelector(`.cell[data-col="${s}"]`);
1070
+ if (a)
1056
1071
  if (i) {
1057
- c.setAttribute("data-invalid", "true");
1072
+ a.setAttribute("data-invalid", "true");
1058
1073
  const d = this.#i.get(e)?.get(t);
1059
- d && c.setAttribute("title", d);
1074
+ d && a.setAttribute("title", d);
1060
1075
  } else
1061
- c.removeAttribute("data-invalid"), c.removeAttribute("title");
1076
+ a.removeAttribute("data-invalid"), a.removeAttribute("title");
1062
1077
  }
1063
1078
  // #endregion
1064
1079
  /**
@@ -1068,7 +1083,7 @@ class W extends P {
1068
1083
  */
1069
1084
  resetChangedRows(e) {
1070
1085
  const t = this.changedRows, i = this.changedRowIds;
1071
- this.#r.clear(), this.#h(), e || this.emit("changed-rows-reset", { rows: t, ids: i }), this.grid._rowPool?.forEach((r) => r.classList.remove("changed"));
1086
+ this.#s.clear(), this.#g(), e || this.emit("changed-rows-reset", { rows: t, ids: i }), this.grid._rowPool?.forEach((s) => s.classList.remove("changed"));
1072
1087
  }
1073
1088
  /**
1074
1089
  * Programmatically begin editing a cell.
@@ -1077,7 +1092,7 @@ class W extends P {
1077
1092
  * @fires cell-commit - Emitted when the cell value is committed (on blur or Enter)
1078
1093
  */
1079
1094
  beginCellEdit(e, t) {
1080
- const i = this.grid, n = i._visibleColumns.findIndex((a) => a.field === t);
1095
+ const i = this.grid, n = i._visibleColumns.findIndex((c) => c.field === t);
1081
1096
  if (n === -1 || !i._visibleColumns[n]?.editable) return;
1082
1097
  const o = i.findRenderedRowElement?.(e)?.querySelector(`.cell[data-col="${n}"]`);
1083
1098
  o && this.#w(e, n, o);
@@ -1091,21 +1106,21 @@ class W extends P {
1091
1106
  beginBulkEdit(e) {
1092
1107
  const t = this.grid;
1093
1108
  if ((this.config.editOn ?? t.effectiveConfig?.editOn) === !1 || !t._columns?.some((o) => o.editable)) return;
1094
- const r = t.findRenderedRowElement?.(e);
1095
- if (!r) return;
1109
+ const s = t.findRenderedRowElement?.(e);
1110
+ if (!s) return;
1096
1111
  const l = t._rows[e];
1097
- this.#m(e, l), Array.from(r.children).forEach((o, a) => {
1098
- const c = t._visibleColumns[a];
1099
- if (c?.editable) {
1112
+ this.#E(e, l), Array.from(s.children).forEach((o, c) => {
1113
+ const a = t._visibleColumns[c];
1114
+ if (a?.editable) {
1100
1115
  const d = o;
1101
- d.classList.contains("editing") || this.#g(l, e, c, a, d, !0);
1116
+ d.classList.contains("editing") || this.#p(l, e, a, c, d, !0);
1102
1117
  }
1103
1118
  }), setTimeout(() => {
1104
- let o = r.querySelector(`.cell[data-col="${t._focusCol}"]`);
1105
- if (o?.classList.contains("editing") || (o = r.querySelector(".cell.editing")), o?.classList.contains("editing")) {
1106
- const a = o.querySelector(v);
1119
+ let o = s.querySelector(`.cell[data-col="${t._focusCol}"]`);
1120
+ if (o?.classList.contains("editing") || (o = s.querySelector(".cell.editing")), o?.classList.contains("editing")) {
1121
+ const c = o.querySelector(w);
1107
1122
  try {
1108
- a?.focus({ preventScroll: !0 });
1123
+ c?.focus({ preventScroll: !0 });
1109
1124
  } catch {
1110
1125
  }
1111
1126
  }
@@ -1130,20 +1145,20 @@ class W extends P {
1130
1145
  * Begin editing a single cell.
1131
1146
  */
1132
1147
  #w(e, t, i) {
1133
- const n = this.grid, r = n._rows[e], l = n._visibleColumns[t];
1134
- !r || !l?.editable || i.classList.contains("editing") || (this.#e !== e && this.#m(e, r), this.#c = t, this.#g(r, e, l, t, i, !1));
1148
+ const n = this.grid, s = n._rows[e], l = n._visibleColumns[t];
1149
+ !s || !l?.editable || i.classList.contains("editing") || (this.#e !== e && this.#E(e, s), this.#d = t, this.#p(s, e, l, t, i, !1));
1135
1150
  }
1136
1151
  /**
1137
1152
  * Focus the editor input in the currently focused cell (grid mode only).
1138
1153
  * Used when pressing Enter to enter edit mode from navigation mode.
1139
1154
  */
1140
- #v() {
1155
+ #b() {
1141
1156
  const e = this.grid, t = e._focusRow, i = e._focusCol;
1142
1157
  if (t < 0 || i < 0) return;
1143
- const r = e.findRenderedRowElement?.(t)?.querySelector(`.cell[data-col="${i}"]`);
1144
- if (r?.classList.contains("editing")) {
1145
- const l = r.querySelector(v);
1146
- l && (this.#a = !1, l.focus(), this.#s = !0, l instanceof HTMLInputElement && (l.type === "text" || l.type === "number") && l.select());
1158
+ const s = e.findRenderedRowElement?.(t)?.querySelector(`.cell[data-col="${i}"]`);
1159
+ if (s?.classList.contains("editing")) {
1160
+ const l = s.querySelector(w);
1161
+ l && (this.#a = !1, l.focus(), this.#r = !0, l instanceof HTMLInputElement && (l.type === "text" || l.type === "number") && l.select());
1147
1162
  }
1148
1163
  }
1149
1164
  /**
@@ -1151,121 +1166,140 @@ class W extends P {
1151
1166
  * Moves to next/previous editable cell, staying in edit mode.
1152
1167
  * Wraps to next/previous row when reaching row boundaries.
1153
1168
  */
1154
- #b(e) {
1155
- const t = this.grid, i = t._rows, n = this.#t ? t._focusRow : this.#e, r = t._visibleColumns.map((c, d) => c.editable ? d : -1).filter((c) => c >= 0);
1156
- if (r.length === 0) return;
1157
- const o = r.indexOf(t._focusCol) + (e ? 1 : -1);
1158
- if (o >= 0 && o < r.length) {
1159
- t._focusCol = r[o];
1160
- const d = t.findRenderedRowElement?.(n)?.querySelector(`.cell[data-col="${r[o]}"]`);
1161
- d?.classList.contains("editing") && d.querySelector(v)?.focus({ preventScroll: !0 }), R(t, { forceHorizontalScroll: !0 });
1169
+ #y(e) {
1170
+ const t = this.grid, i = t._rows, n = this.#t ? t._focusRow : this.#e, s = t._visibleColumns.map((a, d) => a.editable ? d : -1).filter((a) => a >= 0);
1171
+ if (s.length === 0) return;
1172
+ const o = s.indexOf(t._focusCol) + (e ? 1 : -1);
1173
+ if (o >= 0 && o < s.length) {
1174
+ t._focusCol = s[o];
1175
+ const d = t.findRenderedRowElement?.(n)?.querySelector(`.cell[data-col="${s[o]}"]`);
1176
+ d?.classList.contains("editing") && d.querySelector(w)?.focus({ preventScroll: !0 }), L(t, { forceHorizontalScroll: !0 });
1162
1177
  return;
1163
1178
  }
1164
- const a = n + (e ? 1 : -1);
1165
- a >= 0 && a < i.length && (this.#t ? (t._focusRow = a, t._focusCol = e ? r[0] : r[r.length - 1], R(t, { forceHorizontalScroll: !0 }), this.requestAfterRender(), setTimeout(() => {
1166
- const d = t.findRenderedRowElement?.(a)?.querySelector(`.cell[data-col="${t._focusCol}"]`);
1167
- d?.classList.contains("editing") && d.querySelector(v)?.focus({ preventScroll: !0 });
1168
- }, 0)) : (this.#n(n, !1), t._focusRow = a, t._focusCol = e ? r[0] : r[r.length - 1], this.beginBulkEdit(a), R(t, { forceHorizontalScroll: !0 })));
1179
+ const c = n + (e ? 1 : -1);
1180
+ c >= 0 && c < i.length && (this.#t ? (t._focusRow = c, t._focusCol = e ? s[0] : s[s.length - 1], L(t, { forceHorizontalScroll: !0 }), this.requestAfterRender(), setTimeout(() => {
1181
+ const d = t.findRenderedRowElement?.(c)?.querySelector(`.cell[data-col="${t._focusCol}"]`);
1182
+ d?.classList.contains("editing") && d.querySelector(w)?.focus({ preventScroll: !0 });
1183
+ }, 0)) : (this.#n(n, !1), t._focusRow = c, t._focusCol = e ? s[0] : s[s.length - 1], this.beginBulkEdit(c), L(t, { forceHorizontalScroll: !0 })));
1169
1184
  }
1170
1185
  /**
1171
1186
  * Sync the internal grid state with the plugin's editing state.
1172
1187
  */
1173
- #h() {
1188
+ #g() {
1174
1189
  const e = this.grid;
1175
1190
  e._activeEditRows = this.#e, e._rowEditSnapshots = this.#l;
1176
1191
  }
1177
1192
  /**
1178
1193
  * Snapshot original row data and mark as editing.
1179
1194
  */
1180
- #m(e, t) {
1181
- this.#e !== e && (this.#l.set(e, { ...t }), this.#e = e, this.#h());
1195
+ #E(e, t) {
1196
+ if (this.#e !== e && (this.#l.set(e, { ...t }), this.#e = e, this.#g(), !this.#t)) {
1197
+ const i = this.grid;
1198
+ let n = "";
1199
+ try {
1200
+ n = i.getRowId?.(t) ?? "";
1201
+ } catch {
1202
+ }
1203
+ this.emit("edit-open", {
1204
+ rowIndex: e,
1205
+ rowId: n,
1206
+ row: t
1207
+ });
1208
+ }
1182
1209
  }
1183
1210
  /**
1184
1211
  * Exit editing for a row.
1185
1212
  */
1186
1213
  #n(e, t) {
1187
1214
  if (this.#e !== e) return;
1188
- const i = this.grid, n = this.#l.get(e), r = i._rows[e], l = i.findRenderedRowElement?.(e);
1215
+ const i = this.grid, n = this.#l.get(e), s = i._rows[e], l = i.findRenderedRowElement?.(e);
1189
1216
  let o;
1190
- if (r)
1217
+ if (s)
1191
1218
  try {
1192
- o = i.getRowId?.(r);
1219
+ o = i.getRowId?.(s);
1193
1220
  } catch {
1194
1221
  }
1195
- if (!t && l && r && l.querySelectorAll(".cell.editing").forEach((c) => {
1196
- const d = Number(c.getAttribute("data-col"));
1222
+ if (!t && l && s && l.querySelectorAll(".cell.editing").forEach((a) => {
1223
+ const d = Number(a.getAttribute("data-col"));
1197
1224
  if (isNaN(d)) return;
1198
- const h = i._visibleColumns[d];
1199
- if (!h || c.hasAttribute("data-editor-managed"))
1225
+ const g = i._visibleColumns[d];
1226
+ if (!g || a.hasAttribute("data-editor-managed"))
1200
1227
  return;
1201
- const u = c.querySelector("input,textarea,select");
1202
- if (u) {
1203
- const m = h.field, p = r[m], g = y(u, h, p);
1204
- p !== g && this.#p(e, h, g, r);
1228
+ const f = a.querySelector("input,textarea,select");
1229
+ if (f) {
1230
+ const E = g.field, p = s[E], m = _(f, g, p);
1231
+ p !== m && this.#m(e, g, m, s);
1205
1232
  }
1206
- }), t && n && r)
1207
- Object.keys(n).forEach((a) => {
1208
- r[a] = n[a];
1209
- }), o && (this.#r.delete(o), this.clearRowInvalid(o));
1210
- else if (!t && r) {
1211
- const a = this.#C(n, r), c = o ? this.#r.has(o) : a, d = this.emitCancelable("row-commit", {
1233
+ }), t && n && s)
1234
+ Object.keys(n).forEach((c) => {
1235
+ s[c] = n[c];
1236
+ }), o && (this.#s.delete(o), this.clearRowInvalid(o));
1237
+ else if (!t && s) {
1238
+ const c = this.#R(n, s), a = o ? this.#s.has(o) : c, d = this.emitCancelable("row-commit", {
1212
1239
  rowIndex: e,
1213
1240
  rowId: o ?? "",
1214
- row: r,
1241
+ row: s,
1215
1242
  oldValue: n,
1216
- newValue: r,
1217
- changed: c,
1243
+ newValue: s,
1244
+ changed: a,
1218
1245
  changedRows: this.changedRows,
1219
1246
  changedRowIds: this.changedRowIds
1220
1247
  });
1221
- d && n ? (Object.keys(n).forEach((h) => {
1222
- r[h] = n[h];
1223
- }), o && (this.#r.delete(o), this.clearRowInvalid(o))) : !d && a && this.isAnimationEnabled && (this.#u = e);
1248
+ d && n ? (Object.keys(n).forEach((g) => {
1249
+ s[g] = n[g];
1250
+ }), o && (this.#s.delete(o), this.clearRowInvalid(o))) : !d && c && this.isAnimationEnabled && (this.#f = e);
1224
1251
  }
1225
- this.#l.delete(e), this.#e = -1, this.#c = -1, this.#h();
1226
- for (const a of this.#o)
1227
- a.startsWith(`${e}:`) && this.#o.delete(a);
1228
- l && (l.querySelectorAll(".cell.editing").forEach((a) => {
1229
- a.classList.remove("editing"), F(a.parentElement);
1230
- }), this.requestRender()), this.#d = !0, l || (this.#E(i), this.#d = !1);
1252
+ this.#l.delete(e), this.#e = -1, this.#d = -1, this.#g();
1253
+ for (const c of this.#o)
1254
+ c.startsWith(`${e}:`) && this.#o.delete(c);
1255
+ for (const c of this.#c.keys())
1256
+ c.startsWith(`${e}:`) && this.#c.delete(c);
1257
+ l && (l.querySelectorAll(".cell.editing").forEach((c) => {
1258
+ c.classList.remove("editing"), U(c.parentElement);
1259
+ }), this.requestRender()), this.#u = !0, l || (this.#v(i), this.#u = !1), !this.#t && s && this.emit("edit-close", {
1260
+ rowIndex: e,
1261
+ rowId: o ?? "",
1262
+ row: s,
1263
+ reverted: t
1264
+ });
1231
1265
  }
1232
1266
  /**
1233
1267
  * Commit a single cell value change.
1234
1268
  * Uses ID-based change tracking for stability when rows are reordered.
1235
1269
  */
1236
- #p(e, t, i, n) {
1237
- const r = t.field;
1238
- if (!C(r)) return;
1239
- const l = n[r];
1270
+ #m(e, t, i, n) {
1271
+ const s = t.field;
1272
+ if (!S(s)) return;
1273
+ const l = n[s];
1240
1274
  if (l === i) return;
1241
1275
  const o = this.grid;
1242
- let a;
1276
+ let c;
1243
1277
  try {
1244
- a = this.grid.getRowId(n);
1278
+ c = this.grid.getRowId(n);
1245
1279
  } catch {
1246
1280
  }
1247
- const c = a ? !this.#r.has(a) : !0, d = a ? (g) => this.grid.updateRow(a, g, "cascade") : A;
1248
- let h = !1;
1249
- const u = a ? (g) => {
1250
- h = !0, this.setInvalid(a, r, g ?? "");
1281
+ const a = c ? !this.#s.has(c) : !0, d = c ? (m) => this.grid.updateRow(c, m, "cascade") : T;
1282
+ let g = !1;
1283
+ const f = c ? (m) => {
1284
+ g = !0, this.setInvalid(c, s, m ?? "");
1251
1285
  } : () => {
1252
1286
  };
1253
1287
  if (this.emitCancelable("cell-commit", {
1254
1288
  row: n,
1255
- rowId: a ?? "",
1256
- field: r,
1289
+ rowId: c ?? "",
1290
+ field: s,
1257
1291
  oldValue: l,
1258
1292
  value: i,
1259
1293
  rowIndex: e,
1260
1294
  changedRows: this.changedRows,
1261
1295
  changedRowIds: this.changedRowIds,
1262
- firstTimeForRow: c,
1296
+ firstTimeForRow: a,
1263
1297
  updateRow: d,
1264
- setInvalid: u
1298
+ setInvalid: f
1265
1299
  })) return;
1266
- a && !h && this.isCellInvalid(a, r) && this.clearInvalid(a, r), n[r] = i, a && this.#r.add(a), this.#h(), this.emitPluginEvent("cell-edit-committed", {
1300
+ c && !g && this.isCellInvalid(c, s) && this.clearInvalid(c, s), n[s] = i, c && this.#s.add(c), this.#g(), this.emitPluginEvent("cell-edit-committed", {
1267
1301
  rowIndex: e,
1268
- field: r,
1302
+ field: s,
1269
1303
  oldValue: l,
1270
1304
  newValue: i
1271
1305
  });
@@ -1275,134 +1309,156 @@ class W extends P {
1275
1309
  /**
1276
1310
  * Inject an editor into a cell.
1277
1311
  */
1278
- #g(e, t, i, n, r, l) {
1279
- if (!i.editable || r.classList.contains("editing")) return;
1312
+ #p(e, t, i, n, s, l) {
1313
+ if (!i.editable || s.classList.contains("editing")) return;
1280
1314
  let o;
1281
1315
  try {
1282
1316
  o = this.grid.getRowId(e);
1283
1317
  } catch {
1284
1318
  }
1285
- const a = o ? (f) => this.grid.updateRow(o, f, "cascade") : A, c = C(i.field) ? e[i.field] : void 0;
1286
- r.classList.add("editing"), this.#o.add(`${t}:${n}`);
1287
- const d = r.parentElement;
1288
- d && $(d);
1289
- let h = !1;
1290
- const u = (f) => {
1291
- h || !this.#t && this.#e === -1 || this.#p(t, i, f, e);
1292
- }, m = () => {
1293
- h = !0, C(i.field) && (e[i.field] = c);
1319
+ const c = o ? (u) => this.grid.updateRow(o, u, "cascade") : T, a = S(i.field) ? e[i.field] : void 0;
1320
+ s.classList.add("editing"), this.#o.add(`${t}:${n}`);
1321
+ const d = s.parentElement;
1322
+ d && K(d);
1323
+ let g = !1;
1324
+ const f = (u) => {
1325
+ g || !this.#t && this.#e === -1 || this.#m(t, i, u, e);
1326
+ }, E = () => {
1327
+ g = !0, S(i.field) && (e[i.field] = a);
1294
1328
  }, p = document.createElement("div");
1295
- p.className = "tbw-editor-host", r.innerHTML = "", r.appendChild(p), p.addEventListener("keydown", (f) => {
1296
- if (f.key === "Enter") {
1329
+ p.className = "tbw-editor-host", s.innerHTML = "", s.appendChild(p), p.addEventListener("keydown", (u) => {
1330
+ if (u.key === "Enter") {
1297
1331
  if (this.#t) {
1298
- f.stopPropagation(), f.preventDefault();
1299
- const E = p.querySelector("input,textarea,select");
1300
- E && u(y(E, i, c));
1332
+ u.stopPropagation(), u.preventDefault();
1333
+ const h = p.querySelector("input,textarea,select");
1334
+ h && f(_(h, i, a));
1301
1335
  return;
1302
1336
  }
1303
- if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(f) === !1)
1337
+ if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(u) === !1)
1304
1338
  return;
1305
- f.stopPropagation(), f.preventDefault(), h = !0, this.#n(t, !1);
1339
+ u.stopPropagation(), u.preventDefault(), g = !0, this.#n(t, !1);
1306
1340
  }
1307
- if (f.key === "Escape") {
1341
+ if (u.key === "Escape") {
1308
1342
  if (this.#t) {
1309
- f.stopPropagation(), f.preventDefault();
1343
+ u.stopPropagation(), u.preventDefault();
1310
1344
  return;
1311
1345
  }
1312
- if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(f) === !1)
1346
+ if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(u) === !1)
1313
1347
  return;
1314
- f.stopPropagation(), f.preventDefault(), m(), this.#n(t, !0);
1348
+ u.stopPropagation(), u.preventDefault(), E(), this.#n(t, !0);
1315
1349
  }
1316
1350
  });
1317
- const g = i, b = g.__editorTemplate, w = G(this.grid, g) ?? z(i), _ = c;
1318
- if (w === "template" && b)
1319
- this.#y(p, g, e, c, u, m, l, t);
1320
- else if (typeof w == "string") {
1321
- const f = document.createElement(w);
1322
- f.value = _, f.addEventListener("change", () => u(f.value)), p.appendChild(f), l || queueMicrotask(() => {
1323
- p.querySelector(v)?.focus({ preventScroll: !0 });
1351
+ const m = i, y = m.__editorTemplate, v = W(this.grid, m) ?? j(i), k = a, q = `${t}:${i.field}`, A = [];
1352
+ this.#c.set(q, (u) => {
1353
+ for (const h of A) h(u);
1354
+ });
1355
+ const C = (u) => {
1356
+ A.push(u);
1357
+ };
1358
+ if (v === "template" && y)
1359
+ this.#C(p, m, e, a, f, E, l, t), C((u) => {
1360
+ const h = p.querySelector(
1361
+ "input,textarea,select"
1362
+ );
1363
+ h && (h instanceof HTMLInputElement && h.type === "checkbox" ? h.checked = !!u : h.value = String(u ?? ""));
1324
1364
  });
1325
- } else if (typeof w == "function") {
1326
- const f = {
1365
+ else if (typeof v == "string") {
1366
+ const u = document.createElement(v);
1367
+ u.value = k, u.addEventListener("change", () => f(u.value)), C((h) => {
1368
+ u.value = h;
1369
+ }), p.appendChild(u), l || queueMicrotask(() => {
1370
+ p.querySelector(w)?.focus({ preventScroll: !0 });
1371
+ });
1372
+ } else if (typeof v == "function") {
1373
+ const u = {
1327
1374
  row: e,
1328
1375
  rowId: o ?? "",
1329
- value: _,
1376
+ value: k,
1330
1377
  field: i.field,
1331
1378
  column: i,
1332
- commit: u,
1333
- cancel: m,
1334
- updateRow: a
1335
- }, E = w(f);
1336
- typeof E == "string" ? (p.innerHTML = E, j(p, i, u, c)) : E instanceof Node && (p.appendChild(E), E instanceof HTMLInputElement || E instanceof HTMLSelectElement || E instanceof HTMLTextAreaElement || r.setAttribute("data-editor-managed", "")), l || queueMicrotask(() => {
1337
- p.querySelector(v)?.focus({ preventScroll: !0 });
1379
+ commit: f,
1380
+ cancel: E,
1381
+ updateRow: c,
1382
+ onValueChange: C
1383
+ }, h = v(u);
1384
+ typeof h == "string" ? (p.innerHTML = h, Q(p, i, f, a), C((R) => {
1385
+ const b = p.querySelector(
1386
+ "input,textarea,select"
1387
+ );
1388
+ b && (b instanceof HTMLInputElement && b.type === "checkbox" ? b.checked = !!R : b.value = String(R ?? ""));
1389
+ })) : h instanceof Node && (p.appendChild(h), h instanceof HTMLInputElement || h instanceof HTMLSelectElement || h instanceof HTMLTextAreaElement ? C((b) => {
1390
+ h instanceof HTMLInputElement && h.type === "checkbox" ? h.checked = !!b : h.value = String(b ?? "");
1391
+ }) : s.setAttribute("data-editor-managed", "")), l || queueMicrotask(() => {
1392
+ p.querySelector(w)?.focus({ preventScroll: !0 });
1338
1393
  });
1339
- } else if (w && typeof w == "object") {
1340
- const f = document.createElement("div");
1341
- f.setAttribute("data-external-editor", ""), f.setAttribute("data-field", i.field), p.appendChild(f), r.setAttribute("data-editor-managed", "");
1342
- const E = {
1394
+ } else if (v && typeof v == "object") {
1395
+ const u = document.createElement("div");
1396
+ u.setAttribute("data-external-editor", ""), u.setAttribute("data-field", i.field), p.appendChild(u), s.setAttribute("data-editor-managed", "");
1397
+ const h = {
1343
1398
  row: e,
1344
1399
  rowId: o ?? "",
1345
- value: _,
1400
+ value: k,
1346
1401
  field: i.field,
1347
1402
  column: i,
1348
- commit: u,
1349
- cancel: m,
1350
- updateRow: a
1403
+ commit: f,
1404
+ cancel: E,
1405
+ updateRow: c,
1406
+ onValueChange: C
1351
1407
  };
1352
- if (w.mount)
1408
+ if (v.mount)
1353
1409
  try {
1354
- w.mount({ placeholder: f, context: E, spec: w });
1355
- } catch (S) {
1356
- console.warn(`[tbw-grid] External editor mount error for column '${i.field}':`, S);
1410
+ v.mount({ placeholder: u, context: h, spec: v });
1411
+ } catch (R) {
1412
+ console.warn(`[tbw-grid] External editor mount error for column '${i.field}':`, R);
1357
1413
  }
1358
1414
  else
1359
1415
  this.grid.dispatchEvent(
1360
- new CustomEvent("mount-external-editor", { detail: { placeholder: f, spec: w, context: E } })
1416
+ new CustomEvent("mount-external-editor", { detail: { placeholder: u, spec: v, context: h } })
1361
1417
  );
1362
1418
  }
1363
1419
  }
1364
1420
  /**
1365
1421
  * Render a template-based editor.
1366
1422
  */
1367
- #y(e, t, i, n, r, l, o, a) {
1368
- const c = t.__editorTemplate;
1369
- if (!c) return;
1370
- const d = c.cloneNode(!0), h = t.__compiledEditor;
1371
- h ? d.innerHTML = h({
1423
+ #C(e, t, i, n, s, l, o, c) {
1424
+ const a = t.__editorTemplate;
1425
+ if (!a) return;
1426
+ const d = a.cloneNode(!0), g = t.__compiledEditor;
1427
+ g ? d.innerHTML = g({
1372
1428
  row: i,
1373
1429
  value: n,
1374
1430
  field: t.field,
1375
1431
  column: t,
1376
- commit: r,
1432
+ commit: s,
1377
1433
  cancel: l
1378
- }) : d.querySelectorAll("*").forEach((m) => {
1379
- m.childNodes.length === 1 && m.firstChild?.nodeType === Node.TEXT_NODE && (m.textContent = m.textContent?.replace(/{{\s*value\s*}}/g, n == null ? "" : String(n)).replace(/{{\s*row\.([a-zA-Z0-9_]+)\s*}}/g, (p, g) => {
1380
- if (!C(g)) return "";
1381
- const b = i[g];
1382
- return b == null ? "" : String(b);
1434
+ }) : d.querySelectorAll("*").forEach((E) => {
1435
+ E.childNodes.length === 1 && E.firstChild?.nodeType === Node.TEXT_NODE && (E.textContent = E.textContent?.replace(/{{\s*value\s*}}/g, n == null ? "" : String(n)).replace(/{{\s*row\.([a-zA-Z0-9_]+)\s*}}/g, (p, m) => {
1436
+ if (!S(m)) return "";
1437
+ const y = i[m];
1438
+ return y == null ? "" : String(y);
1383
1439
  }) || "");
1384
1440
  });
1385
- const u = d.querySelector(
1441
+ const f = d.querySelector(
1386
1442
  "input,textarea,select"
1387
1443
  );
1388
- if (u) {
1389
- u instanceof HTMLInputElement && u.type === "checkbox" ? u.checked = !!n : u.value = String(n ?? "");
1390
- let m = !1;
1391
- u.addEventListener("blur", () => {
1392
- m || r(y(u, t, n));
1393
- }), u.addEventListener("keydown", (p) => {
1394
- const g = p;
1395
- if (g.key === "Enter") {
1396
- if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(g) === !1)
1444
+ if (f) {
1445
+ f instanceof HTMLInputElement && f.type === "checkbox" ? f.checked = !!n : f.value = String(n ?? "");
1446
+ let E = !1;
1447
+ f.addEventListener("blur", () => {
1448
+ E || s(_(f, t, n));
1449
+ }), f.addEventListener("keydown", (p) => {
1450
+ const m = p;
1451
+ if (m.key === "Enter") {
1452
+ if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(m) === !1)
1397
1453
  return;
1398
- g.stopPropagation(), g.preventDefault(), m = !0, r(y(u, t, n)), this.#n(a, !1);
1454
+ m.stopPropagation(), m.preventDefault(), E = !0, s(_(f, t, n)), this.#n(c, !1);
1399
1455
  }
1400
- if (g.key === "Escape") {
1401
- if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(g) === !1)
1456
+ if (m.key === "Escape") {
1457
+ if (this.config.onBeforeEditClose && this.config.onBeforeEditClose(m) === !1)
1402
1458
  return;
1403
- g.stopPropagation(), g.preventDefault(), l(), this.#n(a, !0);
1459
+ m.stopPropagation(), m.preventDefault(), l(), this.#n(c, !0);
1404
1460
  }
1405
- }), u instanceof HTMLInputElement && u.type === "checkbox" && u.addEventListener("change", () => r(u.checked)), o || setTimeout(() => u.focus({ preventScroll: !0 }), 0);
1461
+ }), f instanceof HTMLInputElement && f.type === "checkbox" && f.addEventListener("change", () => s(f.checked)), o || setTimeout(() => f.focus({ preventScroll: !0 }), 0);
1406
1462
  }
1407
1463
  e.appendChild(d);
1408
1464
  }
@@ -1410,10 +1466,10 @@ class W extends P {
1410
1466
  * Compare snapshot vs current row to detect if any values changed during this edit session.
1411
1467
  * Uses shallow comparison of all properties.
1412
1468
  */
1413
- #C(e, t) {
1469
+ #R(e, t) {
1414
1470
  if (!e) return !1;
1415
- const i = e, n = t, r = /* @__PURE__ */ new Set([...Object.keys(i), ...Object.keys(n)]);
1416
- for (const l of r)
1471
+ const i = e, n = t, s = /* @__PURE__ */ new Set([...Object.keys(i), ...Object.keys(n)]);
1472
+ for (const l of s)
1417
1473
  if (i[l] !== n[l])
1418
1474
  return !0;
1419
1475
  return !1;
@@ -1421,7 +1477,7 @@ class W extends P {
1421
1477
  /**
1422
1478
  * Restore focus to cell after exiting edit mode.
1423
1479
  */
1424
- #E(e) {
1480
+ #v(e) {
1425
1481
  queueMicrotask(() => {
1426
1482
  try {
1427
1483
  const t = e._focusRow, i = e._focusCol, n = e.findRenderedRowElement?.(t);
@@ -1429,8 +1485,8 @@ class W extends P {
1429
1485
  Array.from(e._bodyEl.querySelectorAll(".cell-focus")).forEach(
1430
1486
  (l) => l.classList.remove("cell-focus")
1431
1487
  );
1432
- const r = n.querySelector(`.cell[data-row="${t}"][data-col="${i}"]`);
1433
- r && (r.classList.add("cell-focus"), r.setAttribute("aria-selected", "true"), r.hasAttribute("tabindex") || r.setAttribute("tabindex", "-1"), r.focus({ preventScroll: !0 }));
1488
+ const s = n.querySelector(`.cell[data-row="${t}"][data-col="${i}"]`);
1489
+ s && (s.classList.add("cell-focus"), s.setAttribute("aria-selected", "true"), s.hasAttribute("tabindex") || s.setAttribute("tabindex", "-1"), s.focus({ preventScroll: !0 }));
1434
1490
  }
1435
1491
  } catch {
1436
1492
  }
@@ -1439,7 +1495,7 @@ class W extends P {
1439
1495
  // #endregion
1440
1496
  }
1441
1497
  export {
1442
- W as EditingPlugin,
1443
- z as defaultEditorFor
1498
+ X as EditingPlugin,
1499
+ j as defaultEditorFor
1444
1500
  };
1445
1501
  //# sourceMappingURL=index.js.map