@toolbox-web/grid 1.11.0 → 1.12.1

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 (96) hide show
  1. package/all.js +1224 -1110
  2. package/all.js.map +1 -1
  3. package/index.js +2000 -1700
  4. package/index.js.map +1 -1
  5. package/lib/core/grid.d.ts +21 -1
  6. package/lib/core/grid.d.ts.map +1 -1
  7. package/lib/core/internal/aria.d.ts +52 -0
  8. package/lib/core/internal/aria.d.ts.map +1 -0
  9. package/lib/core/internal/config-manager.d.ts.map +1 -1
  10. package/lib/core/internal/idle-scheduler.d.ts +0 -27
  11. package/lib/core/internal/idle-scheduler.d.ts.map +1 -1
  12. package/lib/core/internal/loading.d.ts +0 -38
  13. package/lib/core/internal/loading.d.ts.map +1 -1
  14. package/lib/core/internal/row-animation.d.ts.map +1 -1
  15. package/lib/core/internal/shell.d.ts +6 -0
  16. package/lib/core/internal/shell.d.ts.map +1 -1
  17. package/lib/core/internal/style-injector.d.ts +0 -8
  18. package/lib/core/internal/style-injector.d.ts.map +1 -1
  19. package/lib/core/internal/utils.d.ts +6 -4
  20. package/lib/core/internal/utils.d.ts.map +1 -1
  21. package/lib/core/internal/validate-config.d.ts.map +1 -1
  22. package/lib/core/internal/virtualization.d.ts +177 -23
  23. package/lib/core/internal/virtualization.d.ts.map +1 -1
  24. package/lib/core/plugin/base-plugin.d.ts +50 -0
  25. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  26. package/lib/core/plugin/plugin-manager.d.ts +18 -0
  27. package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
  28. package/lib/core/plugin/types.d.ts +16 -0
  29. package/lib/core/plugin/types.d.ts.map +1 -1
  30. package/lib/core/types.d.ts +56 -3
  31. package/lib/core/types.d.ts.map +1 -1
  32. package/lib/plugins/clipboard/index.js.map +1 -1
  33. package/lib/plugins/column-virtualization/index.js.map +1 -1
  34. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  35. package/lib/plugins/context-menu/index.js +1 -1
  36. package/lib/plugins/context-menu/index.js.map +1 -1
  37. package/lib/plugins/editing/EditingPlugin.d.ts +7 -5
  38. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  39. package/lib/plugins/editing/index.js +379 -278
  40. package/lib/plugins/editing/index.js.map +1 -1
  41. package/lib/plugins/editing/types.d.ts +14 -1
  42. package/lib/plugins/editing/types.d.ts.map +1 -1
  43. package/lib/plugins/export/index.js.map +1 -1
  44. package/lib/plugins/filtering/index.js.map +1 -1
  45. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +8 -1
  46. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  47. package/lib/plugins/grouping-columns/index.js +59 -60
  48. package/lib/plugins/grouping-columns/index.js.map +1 -1
  49. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -0
  50. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
  51. package/lib/plugins/grouping-rows/index.js +88 -69
  52. package/lib/plugins/grouping-rows/index.js.map +1 -1
  53. package/lib/plugins/grouping-rows/types.d.ts +17 -0
  54. package/lib/plugins/grouping-rows/types.d.ts.map +1 -1
  55. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +24 -0
  56. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
  57. package/lib/plugins/master-detail/index.js +203 -128
  58. package/lib/plugins/master-detail/index.js.map +1 -1
  59. package/lib/plugins/multi-sort/index.js.map +1 -1
  60. package/lib/plugins/pinned-columns/index.js.map +1 -1
  61. package/lib/plugins/pinned-rows/index.js +2 -2
  62. package/lib/plugins/pinned-rows/index.js.map +1 -1
  63. package/lib/plugins/pivot/index.js +2 -2
  64. package/lib/plugins/pivot/index.js.map +1 -1
  65. package/lib/plugins/print/index.js.map +1 -1
  66. package/lib/plugins/reorder/index.js.map +1 -1
  67. package/lib/plugins/responsive/ResponsivePlugin.d.ts +13 -0
  68. package/lib/plugins/responsive/ResponsivePlugin.d.ts.map +1 -1
  69. package/lib/plugins/responsive/index.js +65 -49
  70. package/lib/plugins/responsive/index.js.map +1 -1
  71. package/lib/plugins/row-reorder/index.js.map +1 -1
  72. package/lib/plugins/selection/index.js +5 -5
  73. package/lib/plugins/selection/index.js.map +1 -1
  74. package/lib/plugins/server-side/index.js.map +1 -1
  75. package/lib/plugins/tree/index.js.map +1 -1
  76. package/lib/plugins/undo-redo/index.js.map +1 -1
  77. package/lib/plugins/visibility/index.js.map +1 -1
  78. package/package.json +1 -1
  79. package/umd/grid.all.umd.js +27 -25
  80. package/umd/grid.all.umd.js.map +1 -1
  81. package/umd/grid.umd.js +18 -16
  82. package/umd/grid.umd.js.map +1 -1
  83. package/umd/plugins/context-menu.umd.js +1 -1
  84. package/umd/plugins/context-menu.umd.js.map +1 -1
  85. package/umd/plugins/editing.umd.js +1 -1
  86. package/umd/plugins/editing.umd.js.map +1 -1
  87. package/umd/plugins/grouping-columns.umd.js +1 -1
  88. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  89. package/umd/plugins/grouping-rows.umd.js +2 -2
  90. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  91. package/umd/plugins/master-detail.umd.js +1 -1
  92. package/umd/plugins/master-detail.umd.js.map +1 -1
  93. package/umd/plugins/responsive.umd.js +1 -1
  94. package/umd/plugins/responsive.umd.js.map +1 -1
  95. package/umd/plugins/selection.umd.js +2 -2
  96. package/umd/plugins/selection.umd.js.map +1 -1
@@ -1,4 +1,4 @@
1
- const R = /{{\s*([^}]+)\s*}}/g, u = "__DG_EMPTY__", E = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, v = /__(proto|defineGetter|defineSetter)|constructor|window|globalThis|global|process|Function|import|eval|Reflect|Proxy|Error|arguments|document|location|cookie|localStorage|sessionStorage|indexedDB|fetch|XMLHttpRequest|WebSocket|Worker|SharedWorker|ServiceWorker|opener|parent|top|frames|self|this\b/, y = /* @__PURE__ */ new Set([
1
+ const A = /{{\s*([^}]+)\s*}}/g, g = "__DG_EMPTY__", C = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, _ = /__(proto|defineGetter|defineSetter)|constructor|window|globalThis|global|process|Function|import|eval|Reflect|Proxy|Error|arguments|document|location|cookie|localStorage|sessionStorage|indexedDB|fetch|XMLHttpRequest|WebSocket|Worker|SharedWorker|ServiceWorker|opener|parent|top|frames|self|this\b/, y = /* @__PURE__ */ new Set([
2
2
  "script",
3
3
  "iframe",
4
4
  "object",
@@ -23,14 +23,14 @@ const R = /{{\s*([^}]+)\s*}}/g, u = "__DG_EMPTY__", E = /^[\w$. '?+\-*/%:()!<>=,
23
23
  "plaintext",
24
24
  "xmp",
25
25
  "listing"
26
- ]), f = /^on\w+$/i, C = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), _ = /^\s*(javascript|vbscript|data|blob):/i;
27
- function A(n) {
26
+ ]), w = /^on\w+$/i, D = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), S = /^\s*(javascript|vbscript|data|blob):/i;
27
+ function H(n) {
28
28
  if (!n || typeof n != "string") return "";
29
29
  if (n.indexOf("<") === -1) return n;
30
30
  const e = document.createElement("template");
31
- return e.innerHTML = n, D(e.content), e.innerHTML;
31
+ return e.innerHTML = n, T(e.content), e.innerHTML;
32
32
  }
33
- function D(n) {
33
+ function T(n) {
34
34
  const e = [], t = n.querySelectorAll("*");
35
35
  for (const i of t) {
36
36
  const s = i.tagName.toLowerCase();
@@ -39,60 +39,60 @@ function D(n) {
39
39
  continue;
40
40
  }
41
41
  if ((s === "svg" || i.namespaceURI === "http://www.w3.org/2000/svg") && Array.from(i.attributes).some(
42
- (r) => f.test(r.name) || r.name === "href" || r.name === "xlink:href"
42
+ (o) => w.test(o.name) || o.name === "href" || o.name === "xlink:href"
43
43
  )) {
44
44
  e.push(i);
45
45
  continue;
46
46
  }
47
- const l = [];
48
- for (const o of i.attributes) {
49
- const r = o.name.toLowerCase();
50
- if (f.test(r)) {
51
- l.push(o.name);
47
+ const r = [];
48
+ for (const a of i.attributes) {
49
+ const o = a.name.toLowerCase();
50
+ if (w.test(o)) {
51
+ r.push(a.name);
52
52
  continue;
53
53
  }
54
- if (C.has(r) && _.test(o.value)) {
55
- l.push(o.name);
54
+ if (D.has(o) && S.test(a.value)) {
55
+ r.push(a.name);
56
56
  continue;
57
57
  }
58
- if (r === "style" && /expression\s*\(|javascript:|behavior\s*:/i.test(o.value)) {
59
- l.push(o.name);
58
+ if (o === "style" && /expression\s*\(|javascript:|behavior\s*:/i.test(a.value)) {
59
+ r.push(a.name);
60
60
  continue;
61
61
  }
62
62
  }
63
- l.forEach((o) => i.removeAttribute(o));
63
+ r.forEach((a) => i.removeAttribute(a));
64
64
  }
65
65
  e.forEach((i) => i.remove());
66
66
  }
67
- function S(n, e) {
67
+ function L(n, e) {
68
68
  if (!n || n.indexOf("{{") === -1) return n;
69
- const t = [], i = n.replace(R, (r, a) => {
70
- const d = L(a, e);
71
- return t.push({ expr: a.trim(), result: d }), d;
72
- }), s = I(i), l = t.length && t.every((r) => r.result === "" || r.result === u);
73
- return /Reflect\.|\bProxy\b|ownKeys\(/.test(n) || l ? "" : s;
69
+ const t = [], i = n.replace(A, (o, c) => {
70
+ const d = I(c, e);
71
+ return t.push({ expr: c.trim(), result: d }), d;
72
+ }), s = O(i), r = t.length && t.every((o) => o.result === "" || o.result === g);
73
+ return /Reflect\.|\bProxy\b|ownKeys\(/.test(n) || r ? "" : s;
74
74
  }
75
- function L(n, e) {
76
- if (n = (n || "").trim(), !n || /\b(Reflect|Proxy|ownKeys)\b/.test(n)) return u;
77
- if (n === "value") return e.value == null ? u : String(e.value);
75
+ function I(n, e) {
76
+ if (n = (n || "").trim(), !n || /\b(Reflect|Proxy|ownKeys)\b/.test(n)) return g;
77
+ if (n === "value") return e.value == null ? g : String(e.value);
78
78
  if (n.startsWith("row.") && !/[()?]/.test(n) && !n.includes(":")) {
79
79
  const i = n.slice(4), s = e.row ? e.row[i] : void 0;
80
- return s == null ? u : String(s);
80
+ return s == null ? g : String(s);
81
81
  }
82
- if (n.length > 80 || !E.test(n) || v.test(n)) return u;
82
+ if (n.length > 80 || !C.test(n) || _.test(n)) return g;
83
83
  const t = n.match(/\./g);
84
- if (t && t.length > 1) return u;
84
+ if (t && t.length > 1) return g;
85
85
  try {
86
- const s = new Function("value", "row", `return (${n});`)(e.value, e.row), l = s == null ? "" : String(s);
87
- return /Reflect|Proxy|ownKeys/.test(l) ? u : l || u;
86
+ const s = new Function("value", "row", `return (${n});`)(e.value, e.row), r = s == null ? "" : String(s);
87
+ return /Reflect|Proxy|ownKeys/.test(r) ? g : r || g;
88
88
  } catch {
89
- return u;
89
+ return g;
90
90
  }
91
91
  }
92
- function I(n) {
93
- return n && n.replace(new RegExp(u, "g"), "").replace(/Reflect\.[^<>{}\s]+/g, "").replace(/\bProxy\b/g, "").replace(/ownKeys\([^)]*\)/g, "");
92
+ function O(n) {
93
+ return n && n.replace(new RegExp(g, "g"), "").replace(/Reflect\.[^<>{}\s]+/g, "").replace(/\bProxy\b/g, "").replace(/ownKeys\([^)]*\)/g, "");
94
94
  }
95
- const h = '<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>', T = {
95
+ const b = '<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>', k = {
96
96
  expand: "▶",
97
97
  collapse: "▼",
98
98
  sortAsc: "▲",
@@ -101,11 +101,11 @@ const h = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
101
101
  submenuArrow: "▶",
102
102
  dragHandle: "⋮⋮",
103
103
  toolPanel: "☰",
104
- filter: h,
105
- filterActive: h,
104
+ filter: b,
105
+ filterActive: b,
106
106
  print: "🖨️"
107
107
  };
108
- class H {
108
+ class N {
109
109
  /**
110
110
  * Plugin dependencies - declare other plugins this one requires.
111
111
  *
@@ -395,7 +395,7 @@ class H {
395
395
  */
396
396
  get gridIcons() {
397
397
  const e = this.grid?.gridConfig?.icons ?? {};
398
- return { ...T, ...e };
398
+ return { ...k, ...e };
399
399
  }
400
400
  // #region Animation Helpers
401
401
  /**
@@ -471,19 +471,19 @@ class H {
471
471
  }
472
472
  // #endregion
473
473
  }
474
- const m = "__tbw_expander", k = 32;
475
- function w(n) {
476
- return n.field === m;
474
+ const R = "__tbw_expander", P = 32;
475
+ function E(n) {
476
+ return n.field === R;
477
477
  }
478
- function O(n) {
479
- return n.find(w);
478
+ function M(n) {
479
+ return n.find(E);
480
480
  }
481
- function N(n) {
481
+ function q(n) {
482
482
  return {
483
- field: m,
483
+ field: R,
484
484
  header: "",
485
485
  // No header text - visually merges with next column
486
- width: k,
486
+ width: P,
487
487
  resizable: !1,
488
488
  sortable: !1,
489
489
  filterable: !1,
@@ -498,35 +498,35 @@ function N(n) {
498
498
  }
499
499
  };
500
500
  }
501
- function p(n, e) {
501
+ function x(n, e) {
502
502
  const t = new Set(n);
503
503
  return t.has(e) ? t.delete(e) : t.add(e), t;
504
504
  }
505
- function q(n, e) {
505
+ function F(n, e) {
506
506
  const t = new Set(n);
507
507
  return t.add(e), t;
508
508
  }
509
- function P(n, e) {
509
+ function U(n, e) {
510
510
  const t = new Set(n);
511
511
  return t.delete(e), t;
512
512
  }
513
- function M(n, e) {
513
+ function z(n, e) {
514
514
  return n.has(e);
515
515
  }
516
- function F(n, e, t, i) {
516
+ function G(n, e, t, i) {
517
517
  const s = document.createElement("div");
518
518
  s.className = "master-detail-row", s.setAttribute("data-detail-for", String(e)), s.setAttribute("role", "row");
519
- const l = document.createElement("div");
520
- l.className = "master-detail-cell", l.setAttribute("role", "cell"), l.style.gridColumn = `1 / ${i + 1}`;
521
- const o = t(n, e);
522
- return typeof o == "string" ? l.innerHTML = o : o instanceof HTMLElement && l.appendChild(o), s.appendChild(l), s;
519
+ const r = document.createElement("div");
520
+ r.className = "master-detail-cell", r.setAttribute("role", "cell"), r.style.gridColumn = `1 / ${i + 1}`;
521
+ const a = t(n, e);
522
+ return typeof a == "string" ? r.innerHTML = a : a instanceof HTMLElement && r.appendChild(a), s.appendChild(r), s;
523
523
  }
524
- const U = "@layer tbw-plugins{tbw-grid .cell[data-field=__tbw_expander]{border-right:none!important;padding:0;display:flex;align-items:center;justify-content:center}tbw-grid .header-row .cell[data-field=__tbw_expander]{display:none}tbw-grid .header-row .cell[data-field=__tbw_expander]+.cell{grid-column:1 / 3}tbw-grid .master-detail-expander{display:flex;align-items:center;justify-content:center;width:100%;height:100%}tbw-grid .master-detail-toggle{cursor:pointer;opacity:.7;-webkit-user-select:none;user-select:none;display:inline-flex;align-items:center;justify-content:center}tbw-grid .master-detail-toggle:hover{opacity:1}tbw-grid .master-detail-row{grid-column:1 / -1;display:grid;background:var(--tbw-master-detail-bg, var(--tbw-color-row-alt));border-bottom:1px solid var(--tbw-master-detail-border, var(--tbw-color-border));overflow:hidden}tbw-grid .master-detail-cell{padding:var(--tbw-detail-padding, var(--tbw-spacing-xl, 1rem));overflow:auto}tbw-grid .master-detail-row.tbw-expanding{animation:tbw-detail-expand var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}tbw-grid .master-detail-row.tbw-collapsing{animation:tbw-detail-collapse var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-detail-expand{0%{opacity:0;max-height:0;padding-top:0;padding-bottom:0}to{opacity:1;max-height:var(--tbw-detail-max-height, 31.25rem);padding-top:var(--tbw-detail-padding, var(--tbw-spacing-xl, 1rem));padding-bottom:var(--tbw-detail-padding, var(--tbw-spacing-xl, 1rem))}}@keyframes tbw-detail-collapse{0%{opacity:1;max-height:var(--tbw-detail-max-height, 31.25rem)}to{opacity:0;max-height:0}}}";
525
- class b extends H {
524
+ const W = "@layer tbw-plugins{tbw-grid .cell[data-field=__tbw_expander]{border-right:none!important;padding:0;display:flex;align-items:center;justify-content:center}tbw-grid .header-row .cell[data-field=__tbw_expander]{display:none}tbw-grid .header-row .cell[data-field=__tbw_expander]+.cell{grid-column:1 / 3}tbw-grid .master-detail-expander{display:flex;align-items:center;justify-content:center;width:100%;height:100%}tbw-grid .master-detail-toggle{cursor:pointer;opacity:.7;-webkit-user-select:none;user-select:none;display:inline-flex;align-items:center;justify-content:center}tbw-grid .master-detail-toggle:hover{opacity:1}tbw-grid .master-detail-row{grid-column:1 / -1;display:grid;background:var(--tbw-master-detail-bg, var(--tbw-color-row-alt));border-bottom:1px solid var(--tbw-master-detail-border, var(--tbw-color-border));overflow:hidden}tbw-grid .master-detail-cell{padding:var(--tbw-detail-padding, var(--tbw-spacing-xl, 1rem));overflow:auto}tbw-grid .master-detail-row.tbw-expanding{animation:tbw-detail-expand var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}tbw-grid .master-detail-row.tbw-collapsing{animation:tbw-detail-collapse var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-detail-expand{0%{opacity:0;max-height:0;padding-top:0;padding-bottom:0}to{opacity:1;max-height:var(--tbw-detail-max-height, 31.25rem);padding-top:var(--tbw-detail-padding, var(--tbw-spacing-xl, 1rem));padding-bottom:var(--tbw-detail-padding, var(--tbw-spacing-xl, 1rem))}}@keyframes tbw-detail-collapse{0%{opacity:1;max-height:var(--tbw-detail-max-height, 31.25rem)}to{opacity:0;max-height:0}}}";
525
+ class v extends N {
526
526
  /** @internal */
527
527
  name = "masterDetail";
528
528
  /** @internal */
529
- styles = U;
529
+ styles = W;
530
530
  /** @internal */
531
531
  get defaultConfig() {
532
532
  return {
@@ -578,18 +578,18 @@ class b extends H {
578
578
  if (!t) return;
579
579
  const i = e;
580
580
  if (i.__frameworkAdapter?.parseDetailElement) {
581
- const g = i.__frameworkAdapter.parseDetailElement(t);
582
- if (g) {
583
- this.config = { ...this.config, detailRenderer: g };
581
+ const u = i.__frameworkAdapter.parseDetailElement(t);
582
+ if (u) {
583
+ this.config = { ...this.config, detailRenderer: u };
584
584
  return;
585
585
  }
586
586
  }
587
- const s = t.getAttribute("animation"), l = t.getAttribute("show-expand-column"), o = t.getAttribute("expand-on-row-click"), r = t.getAttribute("collapse-on-click-outside"), a = t.getAttribute("height"), d = {};
588
- s !== null && (d.animation = s === "false" ? !1 : s), l !== null && (d.showExpandColumn = l !== "false"), o !== null && (d.expandOnRowClick = o === "true"), r !== null && (d.collapseOnClickOutside = r === "true"), a !== null && (d.detailHeight = a === "auto" ? "auto" : parseInt(a, 10));
589
- const c = t.innerHTML.trim();
590
- c && !this.config.detailRenderer && (d.detailRenderer = (g, G) => {
591
- const x = S(c, { value: g, row: g });
592
- return A(x);
587
+ const s = t.getAttribute("animation"), r = t.getAttribute("show-expand-column"), a = t.getAttribute("expand-on-row-click"), o = t.getAttribute("collapse-on-click-outside"), c = t.getAttribute("height"), d = {};
588
+ s !== null && (d.animation = s === "false" ? !1 : s), r !== null && (d.showExpandColumn = r !== "false"), a !== null && (d.expandOnRowClick = a === "true"), o !== null && (d.collapseOnClickOutside = o === "true"), c !== null && (d.detailHeight = c === "auto" ? "auto" : parseInt(c, 10));
589
+ const l = t.innerHTML.trim();
590
+ l && !this.config.detailRenderer && (d.detailRenderer = (u, h) => {
591
+ const f = L(l, { value: u, row: u });
592
+ return H(f);
593
593
  }), Object.keys(d).length > 0 && (this.config = { ...this.config, ...d });
594
594
  }
595
595
  // #endregion
@@ -603,15 +603,18 @@ class b extends H {
603
603
  }
604
604
  /**
605
605
  * Apply expand animation to a detail element.
606
- */
607
- animateExpand(e) {
608
- !this.isAnimationEnabled || this.animationStyle === !1 || (e.classList.add("tbw-expanding"), e.addEventListener(
609
- "animationend",
610
- () => {
611
- e.classList.remove("tbw-expanding");
612
- },
613
- { once: !0 }
614
- ));
606
+ * Returns true if animation was applied, false if skipped.
607
+ * When animated, height measurement is deferred to animationend to avoid
608
+ * measuring during the max-height: 0 CSS animation constraint.
609
+ */
610
+ animateExpand(e, t, i) {
611
+ if (!this.isAnimationEnabled || this.animationStyle === !1) return !1;
612
+ e.classList.add("tbw-expanding");
613
+ let s = !1;
614
+ const r = () => {
615
+ s || (s = !0, e.classList.remove("tbw-expanding"), t !== void 0 && i !== void 0 && this.#e(e, t, i));
616
+ };
617
+ return e.addEventListener("animationend", r, { once: !0 }), setTimeout(r, this.animationDuration + 50), !0;
615
618
  }
616
619
  /**
617
620
  * Apply collapse animation to a detail element and remove after animation.
@@ -627,34 +630,61 @@ class b extends H {
627
630
  };
628
631
  e.addEventListener("animationend", i, { once: !0 }), setTimeout(i, this.animationDuration + 50);
629
632
  }
633
+ /**
634
+ * Measure a detail element's height and update the position cache if it changed.
635
+ * Used after layout settles (RAF) or after animation completes (animationend).
636
+ */
637
+ #e(e, t, i) {
638
+ if (!e.isConnected) return;
639
+ const s = e.offsetHeight;
640
+ if (s > 0) {
641
+ const r = this.measuredDetailHeights.get(t);
642
+ this.measuredDetailHeights.set(t, s), r !== s && this.grid.invalidateRowHeight(i);
643
+ }
644
+ }
630
645
  // #endregion
631
646
  // #region Internal State
632
647
  expandedRows = /* @__PURE__ */ new Set();
633
648
  detailElements = /* @__PURE__ */ new Map();
649
+ /** Cached measured heights - persists even when elements are virtualized out */
650
+ measuredDetailHeights = /* @__PURE__ */ new Map();
651
+ /** Rows that were just expanded by user action and should animate.
652
+ * Prevents re-animation when rows scroll back into the virtual window. */
653
+ rowsToAnimate = /* @__PURE__ */ new Set();
634
654
  /** Default height for detail rows when not configured */
635
655
  static DEFAULT_DETAIL_HEIGHT = 150;
636
656
  /**
637
657
  * Get the estimated height for a detail row.
658
+ * Uses cached measured height when available (survives virtualization).
659
+ * Avoids reading offsetHeight during CSS animations to prevent poisoning the cache.
638
660
  */
639
661
  getDetailHeight(e) {
640
662
  const t = this.detailElements.get(e);
641
- return t ? t.offsetHeight : typeof this.config?.detailHeight == "number" ? this.config.detailHeight : b.DEFAULT_DETAIL_HEIGHT;
663
+ if (t && !(t.classList.contains("tbw-expanding") || t.classList.contains("tbw-collapsing"))) {
664
+ const r = t.offsetHeight;
665
+ if (r > 0)
666
+ return this.measuredDetailHeights.set(e, r), r;
667
+ }
668
+ const i = this.measuredDetailHeights.get(e);
669
+ return i && i > 0 ? i : typeof this.config?.detailHeight == "number" ? this.config.detailHeight : v.DEFAULT_DETAIL_HEIGHT;
642
670
  }
643
671
  /**
644
672
  * Toggle a row's detail and emit event.
645
673
  */
646
674
  toggleAndEmit(e, t) {
647
- this.expandedRows = p(this.expandedRows, e), this.emit("detail-expand", {
675
+ this.expandedRows = x(this.expandedRows, e);
676
+ const i = this.expandedRows.has(e);
677
+ i && this.rowsToAnimate.add(e), this.emit("detail-expand", {
648
678
  rowIndex: t,
649
679
  row: e,
650
- expanded: this.expandedRows.has(e)
680
+ expanded: i
651
681
  }), this.requestRender();
652
682
  }
653
683
  // #endregion
654
684
  // #region Lifecycle
655
685
  /** @internal */
656
686
  detach() {
657
- this.expandedRows.clear(), this.detailElements.clear();
687
+ this.expandedRows.clear(), this.detailElements.clear(), this.measuredDetailHeights.clear(), this.rowsToAnimate.clear();
658
688
  }
659
689
  // #endregion
660
690
  // #region Hooks
@@ -663,15 +693,15 @@ class b extends H {
663
693
  if (!(this.config.showExpandColumn === !0 || this.config.showExpandColumn !== !1 && !!this.config.detailRenderer))
664
694
  return [...e];
665
695
  const i = [...e];
666
- if (O(i))
696
+ if (M(i))
667
697
  return i;
668
- const l = N(this.name);
669
- return l.viewRenderer = (o) => {
670
- const { row: r } = o, a = this.expandedRows.has(r), d = document.createElement("span");
698
+ const r = q(this.name);
699
+ return r.viewRenderer = (a) => {
700
+ const { row: o } = a, c = this.expandedRows.has(o), d = document.createElement("span");
671
701
  d.className = "master-detail-expander expander-cell";
672
- const c = document.createElement("span");
673
- return c.className = `master-detail-toggle${a ? " expanded" : ""}`, this.setIcon(c, this.resolveIcon(a ? "collapse" : "expand")), c.setAttribute("role", "button"), c.setAttribute("tabindex", "0"), c.setAttribute("aria-expanded", String(a)), c.setAttribute("aria-label", a ? "Collapse details" : "Expand details"), d.appendChild(c), d;
674
- }, [l, ...i];
702
+ const l = document.createElement("span");
703
+ return l.className = `master-detail-toggle${c ? " expanded" : ""}`, this.setIcon(l, this.resolveIcon(c ? "collapse" : "expand")), l.setAttribute("role", "button"), l.setAttribute("tabindex", "0"), l.setAttribute("aria-expanded", String(c)), l.setAttribute("aria-label", c ? "Collapse details" : "Expand details"), d.appendChild(l), d;
704
+ }, [r, ...i];
675
705
  }
676
706
  /** @internal */
677
707
  onRowClick(e) {
@@ -682,20 +712,20 @@ class b extends H {
682
712
  onCellClick(e) {
683
713
  if (e.originalEvent?.target?.classList.contains("master-detail-toggle"))
684
714
  return this.toggleAndEmit(e.row, e.rowIndex), !0;
685
- this.expandedRows.size > 0 && queueMicrotask(() => this.#e());
715
+ this.expandedRows.size > 0 && queueMicrotask(() => this.#t());
686
716
  }
687
717
  /** @internal */
688
718
  onKeyDown(e) {
689
719
  if (e.key !== " ") return;
690
720
  const t = this.grid._focusCol, i = this.grid._focusRow, s = this.columns[t];
691
- if (!s || !w(s)) return;
692
- const l = this.rows[i];
693
- if (l)
694
- return e.preventDefault(), this.toggleAndEmit(l, i), this.requestRenderWithFocus(), !0;
721
+ if (!s || !E(s)) return;
722
+ const r = this.rows[i];
723
+ if (r)
724
+ return e.preventDefault(), this.toggleAndEmit(r, i), this.requestRenderWithFocus(), !0;
695
725
  }
696
726
  /** @internal */
697
727
  afterRender() {
698
- this.#e();
728
+ this.#t();
699
729
  }
700
730
  /**
701
731
  * Called on scroll to sync detail elements with visible rows.
@@ -703,41 +733,59 @@ class b extends H {
703
733
  * @internal
704
734
  */
705
735
  onScrollRender() {
706
- !this.config.detailRenderer || this.expandedRows.size === 0 || this.#e();
736
+ !this.config.detailRenderer || this.expandedRows.size === 0 || this.#t();
707
737
  }
708
738
  /**
709
739
  * Full sync of detail rows - cleans up stale elements and creates new ones.
710
740
  * Detail rows are inserted as siblings AFTER their master row to survive row rebuilds.
741
+ *
742
+ * PERF: Uses the grid's row pool (_rowPool) and virtual window (_virtualization.start/end)
743
+ * to avoid querySelectorAll on every scroll frame. The pool is index-aligned with the
744
+ * virtual window, so pool[i] corresponds to row index (start + i).
711
745
  */
712
- #e() {
746
+ #t() {
713
747
  if (!this.config.detailRenderer) return;
714
748
  const e = this.gridElement?.querySelector(".rows");
715
749
  if (!e) return;
716
- const t = /* @__PURE__ */ new Map(), i = e.querySelectorAll(".data-grid-row"), s = this.columns.length;
717
- for (const o of i) {
718
- const r = o.querySelector(".cell[data-row]"), a = r ? parseInt(r.getAttribute("data-row") ?? "-1", 10) : -1;
719
- a >= 0 && t.set(a, o);
750
+ const t = this.grid, i = t._rowPool, s = t._virtualization?.start ?? 0, r = t._virtualization?.end ?? 0, a = this.columns.length, o = s, c = r, d = /* @__PURE__ */ new Map();
751
+ if (i) {
752
+ const l = Math.min(i.length, c - o);
753
+ for (let u = 0; u < l; u++) {
754
+ const h = i[u];
755
+ h.parentNode === e && d.set(o + u, h);
756
+ }
757
+ } else {
758
+ const l = e.querySelectorAll(".data-grid-row");
759
+ for (const u of l) {
760
+ const h = u.querySelector(".cell[data-row]"), f = h ? parseInt(h.getAttribute("data-row") ?? "-1", 10) : -1;
761
+ f >= 0 && d.set(f, u);
762
+ }
720
763
  }
721
- const l = e.querySelectorAll(".master-detail-row");
722
- for (const o of l) {
723
- const r = parseInt(o.getAttribute("data-detail-for") ?? "-1", 10), a = r >= 0 ? this.rows[r] : void 0, d = a && this.expandedRows.has(a), c = t.has(r);
724
- (!d || !c) && (o.remove(), a && this.detailElements.delete(a));
764
+ for (const [l, u] of this.detailElements) {
765
+ const h = this.rows.indexOf(l), f = this.expandedRows.has(l), m = h >= 0 && d.has(h);
766
+ (!f || !m) && (u.parentNode && u.remove(), this.detailElements.delete(l));
725
767
  }
726
- for (const [o, r] of t) {
727
- const a = this.rows[o];
728
- if (!a || !this.expandedRows.has(a)) continue;
729
- const d = this.detailElements.get(a);
730
- if (d) {
731
- d.previousElementSibling !== r && r.after(d);
768
+ for (const [l, u] of d) {
769
+ const h = this.rows[l];
770
+ if (!h || !this.expandedRows.has(h)) continue;
771
+ const f = this.detailElements.get(h);
772
+ if (f) {
773
+ f.previousElementSibling !== u && u.after(f);
732
774
  continue;
733
775
  }
734
- const c = F(a, o, this.config.detailRenderer, s);
735
- typeof this.config.detailHeight == "number" && (c.style.height = `${this.config.detailHeight}px`), r.after(c), this.detailElements.set(a, c), this.animateExpand(c);
776
+ const m = G(h, l, this.config.detailRenderer, a);
777
+ typeof this.config.detailHeight == "number" && (m.style.height = `${this.config.detailHeight}px`), u.after(m), this.detailElements.set(h, m);
778
+ const p = this.rowsToAnimate.has(h);
779
+ p && this.rowsToAnimate.delete(h), p && this.animateExpand(m, h, l) || requestAnimationFrame(() => {
780
+ this.#e(m, h, l);
781
+ });
736
782
  }
737
783
  }
738
784
  /**
739
785
  * Return total extra height from all expanded detail rows.
740
786
  * Used by grid virtualization to adjust scrollbar height.
787
+ *
788
+ * @deprecated Use getRowHeight() instead. This hook will be removed in v3.0.
741
789
  */
742
790
  getExtraHeight() {
743
791
  let e = 0;
@@ -748,6 +796,8 @@ class b extends H {
748
796
  /**
749
797
  * Return extra height that appears before a given row index.
750
798
  * This is the sum of heights of all expanded details whose parent row is before the given index.
799
+ *
800
+ * @deprecated Use getRowHeight() instead. This hook will be removed in v3.0.
751
801
  */
752
802
  getExtraHeightBefore(e) {
753
803
  let t = 0;
@@ -757,24 +807,49 @@ class b extends H {
757
807
  }
758
808
  return t;
759
809
  }
810
+ /**
811
+ * Get the height of a specific row, including any expanded detail content.
812
+ * Always returns a height to ensure the position cache uses plugin-controlled values
813
+ * rather than stale DOM measurements.
814
+ *
815
+ * @param row - The row data
816
+ * @param _index - The row index (unused, but part of the interface)
817
+ * @returns The row height in pixels (base height for collapsed, base + detail for expanded)
818
+ */
819
+ getRowHeight(e, t) {
820
+ if (!this.expandedRows.has(e))
821
+ return;
822
+ const s = this.grid.defaultRowHeight ?? 28, r = this.getDetailHeight(e);
823
+ return s + r;
824
+ }
760
825
  /**
761
826
  * Adjust the virtualization start index to keep expanded row visible while its detail is visible.
762
827
  * This ensures the detail scrolls smoothly out of view instead of disappearing abruptly.
763
828
  */
764
829
  adjustVirtualStart(e, t, i) {
765
830
  if (this.expandedRows.size === 0) return e;
766
- const s = [];
767
- for (const r of this.expandedRows) {
768
- const a = this.rows.indexOf(r);
769
- a >= 0 && s.push({ index: a, row: r });
770
- }
771
- s.sort((r, a) => r.index - a.index);
772
- let l = e, o = 0;
773
- for (const { index: r, row: a } of s) {
774
- const d = r * i + o, c = this.getDetailHeight(a), g = d + i + c;
775
- o += c, !(r >= e) && g > t && r < l && (l = r);
831
+ const s = this.grid?._virtualization?.positionCache;
832
+ let r = e;
833
+ if (s && s.length > 0)
834
+ for (const a of this.expandedRows) {
835
+ const o = this.rows.indexOf(a);
836
+ if (o < 0 || o >= e) continue;
837
+ s[o].offset + s[o].height > t && o < r && (r = o);
838
+ }
839
+ else {
840
+ const a = [];
841
+ for (const c of this.expandedRows) {
842
+ const d = this.rows.indexOf(c);
843
+ d >= 0 && a.push({ index: d, row: c });
844
+ }
845
+ a.sort((c, d) => c.index - d.index);
846
+ let o = 0;
847
+ for (const { index: c, row: d } of a) {
848
+ const l = c * i + o, u = this.getDetailHeight(d), h = l + i + u;
849
+ o += u, !(c >= e) && h > t && c < r && (r = c);
850
+ }
776
851
  }
777
- return l;
852
+ return r;
778
853
  }
779
854
  // #endregion
780
855
  // #region Public API
@@ -784,7 +859,7 @@ class b extends H {
784
859
  */
785
860
  expand(e) {
786
861
  const t = this.rows[e];
787
- t && (this.expandedRows = q(this.expandedRows, t), this.requestRender());
862
+ t && (this.rowsToAnimate.add(t), this.expandedRows = F(this.expandedRows, t), this.requestRender());
788
863
  }
789
864
  /**
790
865
  * Collapse the detail row at the given index.
@@ -792,7 +867,7 @@ class b extends H {
792
867
  */
793
868
  collapse(e) {
794
869
  const t = this.rows[e];
795
- t && (this.expandedRows = P(this.expandedRows, t), this.requestRender());
870
+ t && (this.expandedRows = U(this.expandedRows, t), this.requestRender());
796
871
  }
797
872
  /**
798
873
  * Toggle the detail row at the given index.
@@ -800,7 +875,7 @@ class b extends H {
800
875
  */
801
876
  toggle(e) {
802
877
  const t = this.rows[e];
803
- t && (this.expandedRows = p(this.expandedRows, t), this.requestRender());
878
+ t && (this.expandedRows = x(this.expandedRows, t), this.expandedRows.has(t) && this.rowsToAnimate.add(t), this.requestRender());
804
879
  }
805
880
  /**
806
881
  * Check if the detail row at the given index is expanded.
@@ -809,14 +884,14 @@ class b extends H {
809
884
  */
810
885
  isExpanded(e) {
811
886
  const t = this.rows[e];
812
- return t ? M(this.expandedRows, t) : !1;
887
+ return t ? z(this.expandedRows, t) : !1;
813
888
  }
814
889
  /**
815
890
  * Expand all detail rows.
816
891
  */
817
892
  expandAll() {
818
893
  for (const e of this.rows)
819
- this.expandedRows.add(e);
894
+ this.rowsToAnimate.add(e), this.expandedRows.add(e);
820
895
  this.requestRender();
821
896
  }
822
897
  /**
@@ -863,6 +938,6 @@ class b extends H {
863
938
  // #endregion
864
939
  }
865
940
  export {
866
- b as MasterDetailPlugin
941
+ v as MasterDetailPlugin
867
942
  };
868
943
  //# sourceMappingURL=index.js.map