@toolbox-web/grid 0.2.6 → 0.2.7

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 (52) hide show
  1. package/all.d.ts +434 -61
  2. package/all.js +844 -541
  3. package/all.js.map +1 -1
  4. package/index-DG2CZ_Zo.js +3229 -0
  5. package/index-DG2CZ_Zo.js.map +1 -0
  6. package/index.d.ts +210 -6
  7. package/index.js +25 -3194
  8. package/index.js.map +1 -1
  9. package/lib/plugins/clipboard/index.js.map +1 -1
  10. package/lib/plugins/column-virtualization/index.js.map +1 -1
  11. package/lib/plugins/context-menu/index.js.map +1 -1
  12. package/lib/plugins/export/index.js.map +1 -1
  13. package/lib/plugins/filtering/index.js +183 -148
  14. package/lib/plugins/filtering/index.js.map +1 -1
  15. package/lib/plugins/grouping-columns/index.js.map +1 -1
  16. package/lib/plugins/grouping-rows/index.js +116 -82
  17. package/lib/plugins/grouping-rows/index.js.map +1 -1
  18. package/lib/plugins/master-detail/index.js +139 -81
  19. package/lib/plugins/master-detail/index.js.map +1 -1
  20. package/lib/plugins/multi-sort/index.js +17 -17
  21. package/lib/plugins/multi-sort/index.js.map +1 -1
  22. package/lib/plugins/pinned-columns/index.js.map +1 -1
  23. package/lib/plugins/pinned-rows/index.js.map +1 -1
  24. package/lib/plugins/pivot/index.js +369 -337
  25. package/lib/plugins/pivot/index.js.map +1 -1
  26. package/lib/plugins/reorder/index.js +264 -91
  27. package/lib/plugins/reorder/index.js.map +1 -1
  28. package/lib/plugins/selection/index.js.map +1 -1
  29. package/lib/plugins/server-side/index.js.map +1 -1
  30. package/lib/plugins/tree/index.js +180 -169
  31. package/lib/plugins/tree/index.js.map +1 -1
  32. package/lib/plugins/undo-redo/index.js.map +1 -1
  33. package/lib/plugins/visibility/index.js.map +1 -1
  34. package/package.json +1 -1
  35. package/umd/grid.all.umd.js +21 -21
  36. package/umd/grid.all.umd.js.map +1 -1
  37. package/umd/grid.umd.js +12 -12
  38. package/umd/grid.umd.js.map +1 -1
  39. package/umd/plugins/filtering.umd.js +1 -1
  40. package/umd/plugins/filtering.umd.js.map +1 -1
  41. package/umd/plugins/grouping-rows.umd.js +1 -1
  42. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  43. package/umd/plugins/master-detail.umd.js +1 -1
  44. package/umd/plugins/master-detail.umd.js.map +1 -1
  45. package/umd/plugins/multi-sort.umd.js +1 -1
  46. package/umd/plugins/multi-sort.umd.js.map +1 -1
  47. package/umd/plugins/pivot.umd.js +1 -1
  48. package/umd/plugins/pivot.umd.js.map +1 -1
  49. package/umd/plugins/reorder.umd.js +1 -1
  50. package/umd/plugins/reorder.umd.js.map +1 -1
  51. package/umd/plugins/tree.umd.js +1 -1
  52. package/umd/plugins/tree.umd.js.map +1 -1
package/all.js CHANGED
@@ -1,5 +1,5 @@
1
- import { BaseGridPlugin as y, DEFAULT_GRID_ICONS as Ge, runAggregator as se, PLUGIN_QUERIES as Ke, getAggregator as le, getValueAggregator as Oe } from "./index.js";
2
- import { DGEvents as Pn, DataGridElement as Kn, FitModeEnum as qn, GridCSSVars as Dn, GridClasses as Hn, GridDataAttrs as Gn, DataGridElement as On, GridSelectors as Bn, PluginEvents as Vn, PluginManager as zn, aggregatorRegistry as Wn, listAggregators as $n, registerAggregator as jn, runValueAggregator as Un, unregisterAggregator as Yn } from "./index.js";
1
+ import { B as v, D as Ve, r as se, P as N, g as le, a as Oe, e as Ge } from "./index-DG2CZ_Zo.js";
2
+ import { k as Kn, i as Nn, b as qn, F as Dn, o as Hn, G as Vn, p as On, b as Gn, q as Bn, j as zn, c as Wn, d as $n, m as jn, n as Un, l as Yn, f as Zn, h as Xn, u as Jn } from "./index-DG2CZ_Zo.js";
3
3
  function Be(s, e, t, n) {
4
4
  if (n.processCell)
5
5
  return n.processCell(s, e, t);
@@ -10,7 +10,7 @@ function Be(s, e, t, n) {
10
10
  `;
11
11
  return n.quoteStrings || o.includes(i) || o.includes(r) || o.includes('"') ? `"${o.replace(/"/g, '""')}"` : o;
12
12
  }
13
- function H(s) {
13
+ function V(s) {
14
14
  const { rows: e, columns: t, selectedIndices: n, config: o } = s, i = o.delimiter ?? " ", r = o.newline ?? `
15
15
  `, l = t.filter((u) => !u.hidden && !u.field.startsWith("__")), a = [];
16
16
  if (o.includeHeaders) {
@@ -25,13 +25,13 @@ function H(s) {
25
25
  const h = e[u];
26
26
  if (!h) continue;
27
27
  const g = l.map(
28
- (p) => Be(h[p.field], p.field, h, o)
28
+ (f) => Be(h[f.field], f.field, h, o)
29
29
  );
30
30
  a.push(g.join(i));
31
31
  }
32
32
  return a.join(r);
33
33
  }
34
- async function G(s) {
34
+ async function O(s) {
35
35
  try {
36
36
  return await navigator.clipboard.writeText(s), !0;
37
37
  } catch {
@@ -60,7 +60,7 @@ async function de() {
60
60
  return "";
61
61
  }
62
62
  }
63
- class bn extends y {
63
+ class bn extends v {
64
64
  name = "clipboard";
65
65
  version = "1.0.0";
66
66
  get defaultConfig() {
@@ -95,7 +95,7 @@ class bn extends y {
95
95
  const t = this.#n(), n = t?.getSelectedRows() ?? [], o = n.length > 0, i = t?.getRanges() ?? [], r = i.length > 0, l = t?.getSelectedCell() != null;
96
96
  let a, d, c;
97
97
  if (o && t)
98
- a = H({
98
+ a = V({
99
99
  rows: this.rows,
100
100
  columns: [...this.columns],
101
101
  selectedIndices: n,
@@ -118,7 +118,7 @@ class bn extends y {
118
118
  if (!u) return;
119
119
  a = u.text, d = 1, c = 1;
120
120
  }
121
- G(a).then(() => {
121
+ O(a).then(() => {
122
122
  this.lastCopied = { text: a, timestamp: Date.now() }, this.emit("copy", { text: a, rowCount: d, columnCount: c });
123
123
  });
124
124
  }
@@ -170,17 +170,17 @@ class bn extends y {
170
170
  const { startRow: t, startCol: n, endRow: o, endCol: i } = e, r = Math.min(t, o), l = Math.max(t, o), a = Math.min(n, i), d = Math.max(n, i), c = this.config.delimiter ?? " ", u = this.config.newline ?? `
171
171
  `, h = [], g = this.columns.slice(a, d + 1);
172
172
  if (this.config.includeHeaders) {
173
- const p = g.map((m) => m.header || m.field);
174
- h.push(p.join(c));
173
+ const f = g.map((m) => m.header || m.field);
174
+ h.push(f.join(c));
175
175
  }
176
- for (let p = r; p <= l; p++) {
177
- const m = this.rows[p];
176
+ for (let f = r; f <= l; f++) {
177
+ const m = this.rows[f];
178
178
  if (!m) continue;
179
- const f = g.map((b) => {
180
- const E = m[b.field];
179
+ const p = g.map((R) => {
180
+ const E = m[R.field];
181
181
  return E == null ? "" : E instanceof Date ? E.toISOString() : String(E);
182
182
  });
183
- h.push(f.join(c));
183
+ h.push(p.join(c));
184
184
  }
185
185
  return {
186
186
  text: h.join(u),
@@ -219,13 +219,13 @@ class bn extends y {
219
219
  * @returns The copied text
220
220
  */
221
221
  async copy() {
222
- const t = this.#n()?.getSelectedRows() ?? [], n = H({
222
+ const t = this.#n()?.getSelectedRows() ?? [], n = V({
223
223
  rows: this.rows,
224
224
  columns: [...this.columns],
225
225
  selectedIndices: t,
226
226
  config: this.config
227
227
  });
228
- return await G(n), this.lastCopied = { text: n, timestamp: Date.now() }, n;
228
+ return await O(n), this.lastCopied = { text: n, timestamp: Date.now() }, n;
229
229
  }
230
230
  /**
231
231
  * Copy specific rows by index to clipboard.
@@ -233,13 +233,13 @@ class bn extends y {
233
233
  * @returns The copied text
234
234
  */
235
235
  async copyRows(e) {
236
- const t = H({
236
+ const t = V({
237
237
  rows: this.rows,
238
238
  columns: [...this.columns],
239
239
  selectedIndices: e,
240
240
  config: this.config
241
241
  });
242
- return await G(t), this.lastCopied = { text: t, timestamp: Date.now() }, t;
242
+ return await O(t), this.lastCopied = { text: t, timestamp: Date.now() }, t;
243
243
  }
244
244
  /**
245
245
  * Read and parse clipboard content.
@@ -259,7 +259,7 @@ class bn extends y {
259
259
  // #endregion
260
260
  }
261
261
  const ce = 100;
262
- function Q(s) {
262
+ function ee(s) {
263
263
  if (s == null)
264
264
  return ce;
265
265
  if (typeof s == "number")
@@ -268,23 +268,23 @@ function Q(s) {
268
268
  return isNaN(e) ? ce : e;
269
269
  }
270
270
  function ue(s) {
271
- return s.map((e) => Q(e.width));
271
+ return s.map((e) => ee(e.width));
272
272
  }
273
273
  function he(s) {
274
274
  const e = [];
275
275
  let t = 0;
276
276
  for (const n of s)
277
- e.push(t), t += Q(n.width);
277
+ e.push(t), t += ee(n.width);
278
278
  return e;
279
279
  }
280
280
  function ge(s) {
281
- return s.reduce((e, t) => e + Q(t.width), 0);
281
+ return s.reduce((e, t) => e + ee(t.width), 0);
282
282
  }
283
- function Ve(s, e, t, n, o) {
283
+ function ze(s, e, t, n, o) {
284
284
  const i = t.length;
285
285
  if (i === 0)
286
286
  return { startCol: 0, endCol: 0, visibleColumns: [] };
287
- let r = ze(s, t, n);
287
+ let r = We(s, t, n);
288
288
  r = Math.max(0, r - o);
289
289
  const l = s + e;
290
290
  let a = r;
@@ -301,7 +301,7 @@ function Ve(s, e, t, n, o) {
301
301
  d.push(c);
302
302
  return { startCol: r, endCol: a, visibleColumns: d };
303
303
  }
304
- function ze(s, e, t) {
304
+ function We(s, e, t) {
305
305
  let n = 0, o = e.length - 1;
306
306
  for (; n < o; ) {
307
307
  const i = Math.floor((n + o) / 2);
@@ -309,10 +309,10 @@ function ze(s, e, t) {
309
309
  }
310
310
  return n;
311
311
  }
312
- function We(s, e, t) {
312
+ function $e(s, e, t) {
313
313
  return t ? s > e : !1;
314
314
  }
315
- class vn extends y {
315
+ class vn extends v {
316
316
  name = "columnVirtualization";
317
317
  version = "1.0.0";
318
318
  get defaultConfig() {
@@ -343,10 +343,10 @@ class vn extends y {
343
343
  // #endregion
344
344
  // #region Hooks
345
345
  processColumns(e) {
346
- const t = We(e.length, this.config.threshold ?? 30, this.config.autoEnable ?? !0);
346
+ const t = $e(e.length, this.config.threshold ?? 30, this.config.autoEnable ?? !0);
347
347
  if (this.isVirtualized = t ?? !1, this.columnWidths = ue(e), this.columnOffsets = he(e), this.totalWidth = ge(e), !t)
348
348
  return this.startCol = 0, this.endCol = e.length - 1, [...e];
349
- const n = this.grid.clientWidth || 800, o = Ve(
349
+ const n = this.grid.clientWidth || 800, o = ze(
350
350
  this.scrollLeft,
351
351
  n,
352
352
  this.columnOffsets,
@@ -406,14 +406,14 @@ class vn extends y {
406
406
  }
407
407
  // #endregion
408
408
  }
409
- const $e = ".tbw-context-menu{position:fixed;background:light-dark(#f5f5f5,#2a2a2a);color:light-dark(#222,#eee);border:1px solid light-dark(#d0d0d4,#454545);border-radius:4px;box-shadow:0 2px 10px #00000026;min-width:160px;padding:4px 0;z-index:10000;font-size:13px;font-family:system-ui,sans-serif}.tbw-context-menu-item{display:flex;align-items:center;padding:6px 12px;cursor:pointer;gap:8px}.tbw-context-menu-item:hover:not(.disabled){background:light-dark(#e8e8e8,#3a3a3a)}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:light-dark(#c00,#f66)}.tbw-context-menu-icon{width:16px;text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:light-dark(#888,#888);font-size:11px}.tbw-context-menu-arrow{font-size:10px;color:light-dark(#888,#888)}.tbw-context-menu-separator{height:1px;background:light-dark(#d0d0d4,#454545);margin:4px 0}";
410
- function Y(s, e) {
409
+ const je = ".tbw-context-menu{position:fixed;background:light-dark(#f5f5f5,#2a2a2a);color:light-dark(#222,#eee);border:1px solid light-dark(#d0d0d4,#454545);border-radius:4px;box-shadow:0 2px 10px #00000026;min-width:160px;padding:4px 0;z-index:10000;font-size:13px;font-family:system-ui,sans-serif}.tbw-context-menu-item{display:flex;align-items:center;padding:6px 12px;cursor:pointer;gap:8px}.tbw-context-menu-item:hover:not(.disabled){background:light-dark(#e8e8e8,#3a3a3a)}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:light-dark(#c00,#f66)}.tbw-context-menu-icon{width:16px;text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:light-dark(#888,#888);font-size:11px}.tbw-context-menu-arrow{font-size:10px;color:light-dark(#888,#888)}.tbw-context-menu-separator{height:1px;background:light-dark(#d0d0d4,#454545);margin:4px 0}";
410
+ function Z(s, e) {
411
411
  return (typeof s == "function" ? s(e) : s).filter((n) => !(n.hidden === !0 || typeof n.hidden == "function" && n.hidden(e)));
412
412
  }
413
- function je(s, e) {
413
+ function Ue(s, e) {
414
414
  return s.disabled === !0 ? !0 : typeof s.disabled == "function" ? s.disabled(e) : !1;
415
415
  }
416
- function Z(s, e, t, n = Ge.submenuArrow) {
416
+ function X(s, e, t, n = Ve.submenuArrow) {
417
417
  const o = document.createElement("div");
418
418
  o.className = "tbw-context-menu", o.setAttribute("role", "menu");
419
419
  for (const i of s) {
@@ -424,7 +424,7 @@ function Z(s, e, t, n = Ge.submenuArrow) {
424
424
  }
425
425
  const r = document.createElement("div");
426
426
  r.className = "tbw-context-menu-item", i.cssClass && r.classList.add(i.cssClass), r.setAttribute("role", "menuitem"), r.setAttribute("data-id", i.id);
427
- const l = je(i, e);
427
+ const l = Ue(i, e);
428
428
  if (l && (r.classList.add("disabled"), r.setAttribute("aria-disabled", "true")), i.icon) {
429
429
  const d = document.createElement("span");
430
430
  d.className = "tbw-context-menu-icon", d.innerHTML = i.icon, r.appendChild(d);
@@ -438,7 +438,7 @@ function Z(s, e, t, n = Ge.submenuArrow) {
438
438
  const d = document.createElement("span");
439
439
  d.className = "tbw-context-menu-arrow", typeof n == "string" ? d.innerHTML = n : n instanceof HTMLElement && d.appendChild(n.cloneNode(!0)), r.appendChild(d), r.addEventListener("mouseenter", () => {
440
440
  if (r.querySelector(".tbw-context-menu") || !i.subMenu) return;
441
- const u = Y(i.subMenu, e), h = Z(u, e, t, n);
441
+ const u = Z(i.subMenu, e), h = X(u, e, t, n);
442
442
  h.classList.add("tbw-context-submenu"), h.style.position = "absolute", h.style.left = "100%", h.style.top = "0", r.style.position = "relative", r.appendChild(h);
443
443
  }), r.addEventListener("mouseleave", () => {
444
444
  const c = r.querySelector(".tbw-context-menu");
@@ -451,13 +451,13 @@ function Z(s, e, t, n = Ge.submenuArrow) {
451
451
  }
452
452
  return o;
453
453
  }
454
- function pe(s, e, t) {
454
+ function fe(s, e, t) {
455
455
  s.style.position = "fixed", s.style.left = `${e}px`, s.style.top = `${t}px`, s.style.visibility = "hidden", s.style.zIndex = "10000";
456
456
  const n = s.getBoundingClientRect(), o = window.innerWidth, i = window.innerHeight;
457
457
  let r = e, l = t;
458
458
  e + n.width > o && (r = e - n.width), t + n.height > i && (l = t - n.height), r = Math.max(0, r), l = Math.max(0, l), s.style.left = `${r}px`, s.style.top = `${l}px`, s.style.visibility = "visible";
459
459
  }
460
- let I = null, L = null, A = null, O = 0;
460
+ let _ = null, I = null, k = null, G = 0;
461
461
  const B = [
462
462
  {
463
463
  id: "copy",
@@ -476,7 +476,7 @@ const B = [
476
476
  }
477
477
  }
478
478
  ];
479
- class xn extends y {
479
+ class xn extends v {
480
480
  name = "contextMenu";
481
481
  version = "1.0.0";
482
482
  get defaultConfig() {
@@ -492,7 +492,7 @@ class xn extends y {
492
492
  // #endregion
493
493
  // #region Lifecycle
494
494
  attach(e) {
495
- super.attach(e), this.installGlobalHandlers(), O++;
495
+ super.attach(e), this.installGlobalHandlers(), G++;
496
496
  }
497
497
  detach() {
498
498
  this.menuElement && (this.menuElement.remove(), this.menuElement = null), this.isOpen = !1, this.params = null, this.uninstallGlobalHandlers();
@@ -500,18 +500,18 @@ class xn extends y {
500
500
  // #endregion
501
501
  // #region Private Methods
502
502
  installGlobalHandlers() {
503
- !A && typeof document < "u" && (A = document.createElement("style"), A.id = "tbw-context-menu-styles", A.textContent = $e, document.head.appendChild(A)), I || (I = () => {
503
+ !k && typeof document < "u" && (k = document.createElement("style"), k.id = "tbw-context-menu-styles", k.textContent = je, document.head.appendChild(k)), _ || (_ = () => {
504
504
  document.querySelectorAll(".tbw-context-menu").forEach((t) => t.remove());
505
- }, document.addEventListener("click", I)), L || (L = (e) => {
505
+ }, document.addEventListener("click", _)), I || (I = (e) => {
506
506
  e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((n) => n.remove());
507
- }, document.addEventListener("keydown", L));
507
+ }, document.addEventListener("keydown", I));
508
508
  }
509
509
  /**
510
510
  * Clean up global handlers when the last instance detaches.
511
511
  * Uses reference counting to ensure handlers persist while any grid uses the plugin.
512
512
  */
513
513
  uninstallGlobalHandlers() {
514
- O--, !(O > 0) && (I && (document.removeEventListener("click", I), I = null), L && (document.removeEventListener("keydown", L), L = null), A && (A.remove(), A = null));
514
+ G--, !(G > 0) && (_ && (document.removeEventListener("click", _), _ = null), I && (document.removeEventListener("keydown", I), I = null), k && (k.remove(), k = null));
515
515
  }
516
516
  // #endregion
517
517
  // #region Hooks
@@ -551,15 +551,15 @@ class xn extends y {
551
551
  } else
552
552
  return;
553
553
  this.params = a, this.position = { x: o.clientX, y: o.clientY };
554
- const d = Y(this.config.items ?? B, a);
555
- d.length && (this.menuElement && this.menuElement.remove(), this.menuElement = Z(
554
+ const d = Z(this.config.items ?? B, a);
555
+ d.length && (this.menuElement && this.menuElement.remove(), this.menuElement = X(
556
556
  d,
557
557
  a,
558
558
  (c) => {
559
559
  c.action && c.action(a), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
560
560
  },
561
561
  this.gridIcons.submenuArrow
562
- ), document.body.appendChild(this.menuElement), pe(this.menuElement, o.clientX, o.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: a, items: d }));
562
+ ), document.body.appendChild(this.menuElement), fe(this.menuElement, o.clientX, o.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: a, items: d }));
563
563
  }));
564
564
  }
565
565
  // #endregion
@@ -580,15 +580,15 @@ class xn extends y {
580
580
  value: n.value ?? null,
581
581
  isHeader: n.isHeader ?? !1,
582
582
  event: n.event ?? new MouseEvent("contextmenu")
583
- }, i = Y(this.config.items ?? B, o);
584
- this.menuElement && this.menuElement.remove(), this.menuElement = Z(
583
+ }, i = Z(this.config.items ?? B, o);
584
+ this.menuElement && this.menuElement.remove(), this.menuElement = X(
585
585
  i,
586
586
  o,
587
587
  (r) => {
588
588
  r.action && r.action(o), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
589
589
  },
590
590
  this.gridIcons.submenuArrow
591
- ), document.body.appendChild(this.menuElement), pe(this.menuElement, e, t), this.isOpen = !0;
591
+ ), document.body.appendChild(this.menuElement), fe(this.menuElement, e, t), this.isOpen = !0;
592
592
  }
593
593
  /**
594
594
  * Hide the context menu.
@@ -606,7 +606,7 @@ class xn extends y {
606
606
  // #endregion
607
607
  // Styles are injected globally via installGlobalHandlers() since menu renders in document.body
608
608
  }
609
- function fe(s, e = !0) {
609
+ function pe(s, e = !0) {
610
610
  if (s == null) return "";
611
611
  if (s instanceof Date) return s.toISOString();
612
612
  if (typeof s == "object") return JSON.stringify(s);
@@ -614,37 +614,37 @@ function fe(s, e = !0) {
614
614
  return e && (t.includes(",") || t.includes('"') || t.includes(`
615
615
  `) || t.includes("\r")) ? `"${t.replace(/"/g, '""')}"` : t;
616
616
  }
617
- function Ue(s, e, t, n = {}) {
617
+ function Ye(s, e, t, n = {}) {
618
618
  const o = n.delimiter ?? ",", i = n.newline ?? `
619
619
  `, r = [], l = n.bom ? "\uFEFF" : "";
620
620
  if (t.includeHeaders !== !1) {
621
621
  const a = e.map((d) => {
622
622
  const c = d.header || d.field, u = t.processHeader ? t.processHeader(c, d.field) : c;
623
- return fe(u);
623
+ return pe(u);
624
624
  });
625
625
  r.push(a.join(o));
626
626
  }
627
627
  for (const a of s) {
628
628
  const d = e.map((c) => {
629
629
  let u = a[c.field];
630
- return t.processCell && (u = t.processCell(u, c.field, a)), fe(u);
630
+ return t.processCell && (u = t.processCell(u, c.field, a)), pe(u);
631
631
  });
632
632
  r.push(d.join(o));
633
633
  }
634
634
  return l + r.join(i);
635
635
  }
636
- function ee(s, e) {
636
+ function te(s, e) {
637
637
  const t = URL.createObjectURL(s), n = document.createElement("a");
638
638
  n.href = t, n.download = e, n.style.display = "none", document.body.appendChild(n), n.click(), document.body.removeChild(n), URL.revokeObjectURL(t);
639
639
  }
640
- function Ye(s, e) {
640
+ function Ze(s, e) {
641
641
  const t = new Blob([s], { type: "text/csv;charset=utf-8;" });
642
- ee(t, e);
642
+ te(t, e);
643
643
  }
644
644
  function me(s) {
645
645
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
646
646
  }
647
- function Ze(s, e, t) {
647
+ function Xe(s, e, t) {
648
648
  let n = `<?xml version="1.0" encoding="UTF-8"?>
649
649
  <?mso-application progid="Excel.Sheet"?>
650
650
  <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
@@ -676,13 +676,13 @@ function Ze(s, e, t) {
676
676
  </Worksheet>
677
677
  </Workbook>`, n;
678
678
  }
679
- function Xe(s, e) {
679
+ function Je(s, e) {
680
680
  const t = e.endsWith(".xls") ? e : `${e}.xls`, n = new Blob([s], {
681
681
  type: "application/vnd.ms-excel;charset=utf-8;"
682
682
  });
683
- ee(n, t);
683
+ te(n, t);
684
684
  }
685
- class yn extends y {
685
+ class yn extends v {
686
686
  name = "export";
687
687
  version = "1.0.0";
688
688
  get defaultConfig() {
@@ -723,27 +723,27 @@ class yn extends y {
723
723
  try {
724
724
  switch (e) {
725
725
  case "csv": {
726
- const a = Ue(r, i, o, { bom: !0 });
727
- l = l.endsWith(".csv") ? l : `${l}.csv`, Ye(a, l);
726
+ const a = Ye(r, i, o, { bom: !0 });
727
+ l = l.endsWith(".csv") ? l : `${l}.csv`, Ze(a, l);
728
728
  break;
729
729
  }
730
730
  case "excel": {
731
- const a = Ze(r, i, o);
732
- l = l.endsWith(".xls") ? l : `${l}.xls`, Xe(a, l);
731
+ const a = Xe(r, i, o);
732
+ l = l.endsWith(".xls") ? l : `${l}.xls`, Je(a, l);
733
733
  break;
734
734
  }
735
735
  case "json": {
736
736
  const a = r.map((u) => {
737
737
  const h = {};
738
738
  for (const g of i) {
739
- let p = u[g.field];
740
- o.processCell && (p = o.processCell(p, g.field, u)), h[g.field] = p;
739
+ let f = u[g.field];
740
+ o.processCell && (f = o.processCell(f, g.field, u)), h[g.field] = f;
741
741
  }
742
742
  return h;
743
743
  }), d = JSON.stringify(a, null, 2);
744
744
  l = l.endsWith(".json") ? l : `${l}.json`;
745
745
  const c = new Blob([d], { type: "application/json" });
746
- ee(c, l);
746
+ te(c, l);
747
747
  break;
748
748
  }
749
749
  }
@@ -803,7 +803,7 @@ class yn extends y {
803
803
  }
804
804
  // #endregion
805
805
  }
806
- function Je(s) {
806
+ function Qe(s) {
807
807
  const { totalRows: e, viewportHeight: t, scrollTop: n, rowHeight: o, overscan: i } = s, r = Math.ceil(t / o);
808
808
  let l = Math.floor(n / o) - i;
809
809
  l < 0 && (l = 0);
@@ -815,10 +815,10 @@ function Je(s) {
815
815
  totalHeight: e * o
816
816
  };
817
817
  }
818
- function Qe(s, e) {
818
+ function et(s, e) {
819
819
  return s <= e;
820
820
  }
821
- function et(s, e, t = !1) {
821
+ function tt(s, e, t = !1) {
822
822
  const n = s[e.field];
823
823
  if (e.operator === "blank")
824
824
  return n == null || n === "";
@@ -860,10 +860,10 @@ function et(s, e, t = !1) {
860
860
  return !0;
861
861
  }
862
862
  }
863
- function tt(s, e, t = !1) {
864
- return e.length ? s.filter((n) => e.every((o) => et(n, o, t))) : s;
863
+ function nt(s, e, t = !1) {
864
+ return e.length ? s.filter((n) => e.every((o) => tt(n, o, t))) : s;
865
865
  }
866
- function nt(s) {
866
+ function ot(s) {
867
867
  return JSON.stringify(
868
868
  s.map((e) => ({
869
869
  field: e.field,
@@ -881,8 +881,8 @@ function we(s, e) {
881
881
  }
882
882
  return [...t].sort((n, o) => typeof n == "number" && typeof o == "number" ? n - o : String(n).localeCompare(String(o)));
883
883
  }
884
- const ot = '.header-cell.filtered:before{content:"";position:absolute;top:4px;right:4px;width:6px;height:6px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}.tbw-filter-btn{display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:4px;opacity:.4;transition:opacity .15s;color:inherit;vertical-align:middle}.tbw-filter-btn:hover,.tbw-filter-btn.active{opacity:1}.tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}', it = ".tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, 4px));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:12px;z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, 13px)}.tbw-filter-search{margin-bottom:8px}.tbw-filter-search-input{width:100%;padding:6px 10px;background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, 4px);font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:4px 2px;margin-bottom:8px;border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-action-btn{background:transparent;border:none;color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));cursor:pointer;font-size:12px;padding:2px 0}.tbw-filter-action-btn:hover{text-decoration:underline}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:8px;max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:8px;padding:4px 2px;cursor:pointer;border-radius:3px}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:8px 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:8px;padding-top:8px;border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:6px 12px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:6px 12px;background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}";
885
- class _ extends y {
884
+ const it = '.header-cell.filtered:before{content:"";position:absolute;top:4px;right:4px;width:6px;height:6px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}.tbw-filter-btn{display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:4px;opacity:.4;transition:opacity .15s;color:inherit;vertical-align:middle}.tbw-filter-btn:hover,.tbw-filter-btn.active{opacity:1}.tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}', rt = ".tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, 4px));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:12px;z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, 13px)}.tbw-filter-search{margin-bottom:8px}.tbw-filter-search-input{width:100%;padding:6px 10px;background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, 4px);font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:4px 2px;margin-bottom:8px;border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-action-btn{background:transparent;border:none;color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));cursor:pointer;font-size:12px;padding:2px 0}.tbw-filter-action-btn:hover{text-decoration:underline}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:8px;max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:8px;padding:4px 2px;cursor:pointer;border-radius:3px}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:8px 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:8px;padding-top:8px;border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:6px 12px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:6px 12px;background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}";
885
+ class A extends v {
886
886
  name = "filtering";
887
887
  version = "1.0.0";
888
888
  get defaultConfig() {
@@ -922,10 +922,12 @@ class _ extends y {
922
922
  processRows(e) {
923
923
  const t = [...this.filters.values()];
924
924
  if (!t.length) return [...e];
925
- const n = nt(t);
925
+ if (this.config.filterHandler)
926
+ return this.cachedResult ? this.cachedResult : [...e];
927
+ const n = ot(t);
926
928
  if (this.cacheKey === n && this.cachedResult)
927
929
  return this.cachedResult;
928
- const o = tt([...e], t, this.config.caseSensitive);
930
+ const o = nt([...e], t, this.config.caseSensitive);
929
931
  return this.cachedResult = o, this.cacheKey = n, o;
930
932
  }
931
933
  afterRender() {
@@ -934,14 +936,19 @@ class _ extends y {
934
936
  e.querySelectorAll('[part~="header-cell"]').forEach((n) => {
935
937
  const o = n.getAttribute("data-col");
936
938
  if (o === null) return;
937
- const i = this.columns[parseInt(o, 10)];
938
- if (!i || i.filterable === !1 || n.querySelector(".tbw-filter-btn")) return;
939
+ const i = this.visibleColumns[parseInt(o, 10)];
940
+ if (!i || i.filterable === !1) return;
939
941
  const r = i.field;
940
942
  if (!r) return;
941
- const l = document.createElement("button");
942
- l.className = "tbw-filter-btn", l.setAttribute("aria-label", `Filter ${i.header ?? r}`), l.innerHTML = '<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>', this.filters.has(r) && (l.classList.add("active"), n.classList.add("filtered")), l.addEventListener("click", (a) => {
943
- a.stopPropagation(), this.toggleFilterPanel(r, i, l);
944
- }), n.appendChild(l);
943
+ const l = this.filters.has(r);
944
+ let a = n.querySelector(".tbw-filter-btn");
945
+ if (a) {
946
+ a.classList.toggle("active", l), n.classList.toggle("filtered", l);
947
+ return;
948
+ }
949
+ a = document.createElement("button"), a.className = "tbw-filter-btn", a.setAttribute("aria-label", `Filter ${i.header ?? r}`), a.innerHTML = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', l && (a.classList.add("active"), n.classList.add("filtered")), a.addEventListener("click", (d) => {
950
+ d.stopPropagation(), this.toggleFilterPanel(r, i, a);
951
+ }), n.appendChild(a);
945
952
  });
946
953
  }
947
954
  // #endregion
@@ -951,7 +958,7 @@ class _ extends y {
951
958
  * Pass null to remove the filter.
952
959
  */
953
960
  setFilter(e, t) {
954
- t === null ? this.filters.delete(e) : this.filters.set(e, { ...t, field: e }), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
961
+ t === null ? (this.filters.delete(e), this.excludedValues.delete(e)) : (this.filters.set(e, { ...t, field: e }), t.type === "set" && t.operator === "notIn" && Array.isArray(t.value) ? this.excludedValues.set(e, new Set(t.value)) : t.type === "set" && this.excludedValues.delete(e)), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
955
962
  filters: [...this.filters.values()],
956
963
  filteredRowCount: 0
957
964
  // Will be accurate after processRows
@@ -979,9 +986,9 @@ class _ extends y {
979
986
  * Set filters from an array (replaces all existing filters).
980
987
  */
981
988
  setFilterModel(e) {
982
- this.filters.clear();
989
+ this.filters.clear(), this.excludedValues.clear();
983
990
  for (const t of e)
984
- this.filters.set(t.field, t);
991
+ this.filters.set(t.field, t), t.type === "set" && t.operator === "notIn" && Array.isArray(t.value) && this.excludedValues.set(t.field, new Set(t.value));
985
992
  this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
986
993
  filters: [...this.filters.values()],
987
994
  filteredRowCount: 0
@@ -991,19 +998,13 @@ class _ extends y {
991
998
  * Clear all filters.
992
999
  */
993
1000
  clearAllFilters() {
994
- this.filters.clear(), this.excludedValues.clear(), this.searchText.clear(), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
995
- filters: [],
996
- filteredRowCount: this.rows.length
997
- }), this.requestRender();
1001
+ this.filters.clear(), this.excludedValues.clear(), this.searchText.clear(), this.applyFiltersInternal();
998
1002
  }
999
1003
  /**
1000
1004
  * Clear filter for a specific field.
1001
1005
  */
1002
1006
  clearFieldFilter(e) {
1003
- this.filters.delete(e), this.excludedValues.delete(e), this.searchText.delete(e), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
1004
- filters: [...this.filters.values()],
1005
- filteredRowCount: 0
1006
- }), this.requestRender();
1007
+ this.filters.delete(e), this.excludedValues.delete(e), this.searchText.delete(e), this.applyFiltersInternal();
1007
1008
  }
1008
1009
  /**
1009
1010
  * Check if a field has an active filter.
@@ -1042,7 +1043,7 @@ class _ extends y {
1042
1043
  return;
1043
1044
  }
1044
1045
  const e = document.createElement("style");
1045
- e.id = "tbw-filter-panel-styles", e.textContent = it, document.head.appendChild(e), this.globalStylesInjected = !0;
1046
+ e.id = "tbw-filter-panel-styles", e.textContent = rt, document.head.appendChild(e), this.globalStylesInjected = !0;
1046
1047
  }
1047
1048
  /**
1048
1049
  * Toggle the filter panel for a field
@@ -1054,33 +1055,50 @@ class _ extends y {
1054
1055
  }
1055
1056
  this.closeFilterPanel();
1056
1057
  const o = document.createElement("div");
1057
- o.className = "tbw-filter-panel", this.panelElement = o, this.openPanelField = e;
1058
+ if (o.className = "tbw-filter-panel", this.panelElement = o, this.openPanelField = e, this.config.valuesHandler) {
1059
+ o.innerHTML = '<div class="tbw-filter-loading">Loading...</div>', document.body.appendChild(o), this.positionPanel(o, n), this.setupPanelCloseHandler(o, n), this.config.valuesHandler(e, t).then((r) => {
1060
+ this.openPanelField !== e || !this.panelElement || (o.innerHTML = "", this.renderPanelContent(e, t, o, r));
1061
+ });
1062
+ return;
1063
+ }
1058
1064
  const i = we(this.sourceRows, e);
1059
- let r = this.excludedValues.get(e);
1060
- r || (r = /* @__PURE__ */ new Set(), this.excludedValues.set(e, r));
1061
- const l = this.searchText.get(e) ?? "", a = {
1065
+ this.renderPanelContent(e, t, o, i), document.body.appendChild(o), this.positionPanel(o, n), this.setupPanelCloseHandler(o, n);
1066
+ }
1067
+ /**
1068
+ * Render filter panel content with given values
1069
+ */
1070
+ renderPanelContent(e, t, n, o) {
1071
+ let i = this.excludedValues.get(e);
1072
+ i || (i = /* @__PURE__ */ new Set(), this.excludedValues.set(e, i));
1073
+ const r = this.searchText.get(e) ?? "", l = {
1062
1074
  field: e,
1063
1075
  column: t,
1064
- uniqueValues: i,
1065
- excludedValues: r,
1066
- searchText: l,
1067
- applySetFilter: (c) => {
1068
- this.applySetFilter(e, c), this.closeFilterPanel();
1076
+ uniqueValues: o,
1077
+ excludedValues: i,
1078
+ searchText: r,
1079
+ applySetFilter: (d) => {
1080
+ this.applySetFilter(e, d), this.closeFilterPanel();
1069
1081
  },
1070
- applyTextFilter: (c, u, h) => {
1071
- this.applyTextFilter(e, c, u, h), this.closeFilterPanel();
1082
+ applyTextFilter: (d, c, u) => {
1083
+ this.applyTextFilter(e, d, c, u), this.closeFilterPanel();
1072
1084
  },
1073
1085
  clearFilter: () => {
1074
1086
  this.clearFieldFilter(e), this.closeFilterPanel();
1075
1087
  },
1076
1088
  closePanel: () => this.closeFilterPanel()
1077
1089
  };
1078
- let d = !1;
1079
- this.config.filterPanelRenderer && (this.config.filterPanelRenderer(o, a), d = o.children.length > 0), d || this.renderDefaultFilterPanel(o, a, i, r), document.body.appendChild(o), this.positionPanel(o, n), this.panelAbortController = new AbortController(), setTimeout(() => {
1090
+ let a = !1;
1091
+ this.config.filterPanelRenderer && (this.config.filterPanelRenderer(n, l), a = n.children.length > 0), a || this.renderDefaultFilterPanel(n, l, o, i);
1092
+ }
1093
+ /**
1094
+ * Setup click-outside handler to close the panel
1095
+ */
1096
+ setupPanelCloseHandler(e, t) {
1097
+ this.panelAbortController = new AbortController(), setTimeout(() => {
1080
1098
  document.addEventListener(
1081
1099
  "click",
1082
- (c) => {
1083
- !o.contains(c.target) && c.target !== n && this.closeFilterPanel();
1100
+ (n) => {
1101
+ !e.contains(n.target) && n.target !== t && this.closeFilterPanel();
1084
1102
  },
1085
1103
  { signal: this.panelAbortController?.signal }
1086
1104
  );
@@ -1119,71 +1137,71 @@ class _ extends y {
1119
1137
  const u = document.createElement("span");
1120
1138
  u.textContent = "Select All", d.appendChild(c), d.appendChild(u), a.appendChild(d);
1121
1139
  const h = () => {
1122
- const w = [...f.values()], R = w.every((C) => C), S = w.every((C) => !C);
1123
- c.checked = R, c.indeterminate = !R && !S;
1140
+ const w = [...p.values()], y = w.every((x) => x), C = w.every((x) => !x);
1141
+ c.checked = y, c.indeterminate = !y && !C;
1124
1142
  };
1125
1143
  c.addEventListener("change", () => {
1126
1144
  const w = c.checked;
1127
- for (const R of f.keys())
1128
- f.set(R, w);
1129
- h(), v();
1145
+ for (const y of p.keys())
1146
+ p.set(y, w);
1147
+ h(), H();
1130
1148
  }), e.appendChild(a);
1131
1149
  const g = document.createElement("div");
1132
1150
  g.className = "tbw-filter-values";
1133
- const p = document.createElement("div");
1134
- p.className = "tbw-filter-values-spacer", g.appendChild(p);
1151
+ const f = document.createElement("div");
1152
+ f.className = "tbw-filter-values-spacer", g.appendChild(f);
1135
1153
  const m = document.createElement("div");
1136
1154
  m.className = "tbw-filter-values-content", g.appendChild(m);
1137
- const f = /* @__PURE__ */ new Map();
1155
+ const p = /* @__PURE__ */ new Map();
1138
1156
  n.forEach((w) => {
1139
- const R = w == null ? "__null__" : String(w);
1140
- f.set(R, !o.has(w));
1157
+ const y = w == null ? "__null__" : String(w);
1158
+ p.set(y, !o.has(w));
1141
1159
  }), h();
1142
- let b = [];
1143
- const E = (w, R) => {
1144
- const S = w == null ? "(Blank)" : String(w), C = w == null ? "__null__" : String(w), x = document.createElement("label");
1145
- x.className = "tbw-filter-value-item", x.style.position = "absolute", x.style.top = `${R * _.LIST_ITEM_HEIGHT}px`, x.style.left = "0", x.style.right = "0", x.style.height = `${_.LIST_ITEM_HEIGHT}px`, x.style.boxSizing = "border-box";
1146
- const k = document.createElement("input");
1147
- k.type = "checkbox", k.className = "tbw-filter-checkbox", k.checked = f.get(C) ?? !0, k.dataset.value = C, k.addEventListener("change", () => {
1148
- f.set(C, k.checked), h();
1160
+ let R = [];
1161
+ const E = (w, y) => {
1162
+ const C = w == null ? "(Blank)" : String(w), x = w == null ? "__null__" : String(w), b = document.createElement("label");
1163
+ b.className = "tbw-filter-value-item", b.style.position = "absolute", b.style.top = `${y * A.LIST_ITEM_HEIGHT}px`, b.style.left = "0", b.style.right = "0", b.style.height = `${A.LIST_ITEM_HEIGHT}px`, b.style.boxSizing = "border-box";
1164
+ const S = document.createElement("input");
1165
+ S.type = "checkbox", S.className = "tbw-filter-checkbox", S.checked = p.get(x) ?? !0, S.dataset.value = x, S.addEventListener("change", () => {
1166
+ p.set(x, S.checked), h();
1149
1167
  });
1150
1168
  const re = document.createElement("span");
1151
- return re.textContent = S, x.appendChild(k), x.appendChild(re), x;
1152
- }, v = () => {
1153
- const w = b.length, R = g.clientHeight, S = g.scrollTop;
1154
- if (p.style.height = `${w * _.LIST_ITEM_HEIGHT}px`, Qe(w, _.LIST_BYPASS_THRESHOLD / 3)) {
1155
- m.innerHTML = "", m.style.transform = "translateY(0px)", b.forEach((x, k) => {
1156
- m.appendChild(E(x, k));
1169
+ return re.textContent = C, b.appendChild(S), b.appendChild(re), b;
1170
+ }, H = () => {
1171
+ const w = R.length, y = g.clientHeight, C = g.scrollTop;
1172
+ if (f.style.height = `${w * A.LIST_ITEM_HEIGHT}px`, et(w, A.LIST_BYPASS_THRESHOLD / 3)) {
1173
+ m.innerHTML = "", m.style.transform = "translateY(0px)", R.forEach((b, S) => {
1174
+ m.appendChild(E(b, S));
1157
1175
  });
1158
1176
  return;
1159
1177
  }
1160
- const C = Je({
1178
+ const x = Qe({
1161
1179
  totalRows: w,
1162
- viewportHeight: R,
1163
- scrollTop: S,
1164
- rowHeight: _.LIST_ITEM_HEIGHT,
1165
- overscan: _.LIST_OVERSCAN
1180
+ viewportHeight: y,
1181
+ scrollTop: C,
1182
+ rowHeight: A.LIST_ITEM_HEIGHT,
1183
+ overscan: A.LIST_OVERSCAN
1166
1184
  });
1167
- m.style.transform = `translateY(${C.offsetY}px)`, m.innerHTML = "";
1168
- for (let x = C.start; x < C.end; x++)
1169
- m.appendChild(E(b[x], x - C.start));
1185
+ m.style.transform = `translateY(${x.offsetY}px)`, m.innerHTML = "";
1186
+ for (let b = x.start; b < x.end; b++)
1187
+ m.appendChild(E(R[b], b - x.start));
1170
1188
  }, oe = (w) => {
1171
- const R = w.toLowerCase();
1172
- if (b = n.filter((S) => {
1173
- const C = S == null ? "(Blank)" : String(S);
1174
- return !w || C.toLowerCase().includes(R);
1175
- }), b.length === 0) {
1176
- p.style.height = "0px", m.innerHTML = "";
1177
- const S = document.createElement("div");
1178
- S.className = "tbw-filter-no-match", S.textContent = "No matching values", m.appendChild(S);
1189
+ const y = w.toLowerCase();
1190
+ if (R = n.filter((C) => {
1191
+ const x = C == null ? "(Blank)" : String(C);
1192
+ return !w || x.toLowerCase().includes(y);
1193
+ }), R.length === 0) {
1194
+ f.style.height = "0px", m.innerHTML = "";
1195
+ const C = document.createElement("div");
1196
+ C.className = "tbw-filter-no-match", C.textContent = "No matching values", m.appendChild(C);
1179
1197
  return;
1180
1198
  }
1181
- v();
1199
+ H();
1182
1200
  };
1183
1201
  g.addEventListener(
1184
1202
  "scroll",
1185
1203
  () => {
1186
- b.length > 0 && v();
1204
+ R.length > 0 && H();
1187
1205
  },
1188
1206
  { passive: !0 }
1189
1207
  ), oe(l.value), e.appendChild(g);
@@ -1193,25 +1211,25 @@ class _ extends y {
1193
1211
  this.searchText.set(i, l.value), oe(l.value);
1194
1212
  }, this.config.debounceMs ?? 150);
1195
1213
  });
1196
- const N = document.createElement("div");
1197
- N.className = "tbw-filter-buttons";
1198
- const P = document.createElement("button");
1199
- P.className = "tbw-filter-apply-btn", P.textContent = "Apply", P.addEventListener("click", () => {
1214
+ const P = document.createElement("div");
1215
+ P.className = "tbw-filter-buttons";
1216
+ const M = document.createElement("button");
1217
+ M.className = "tbw-filter-apply-btn", M.textContent = "Apply", M.addEventListener("click", () => {
1200
1218
  const w = [];
1201
- for (const [R, S] of f)
1202
- if (!S)
1203
- if (R === "__null__")
1219
+ for (const [y, C] of p)
1220
+ if (!C)
1221
+ if (y === "__null__")
1204
1222
  w.push(null);
1205
1223
  else {
1206
- const C = n.find((x) => String(x) === R);
1207
- w.push(C !== void 0 ? C : R);
1224
+ const x = n.find((b) => String(b) === y);
1225
+ w.push(x !== void 0 ? x : y);
1208
1226
  }
1209
1227
  t.applySetFilter(w);
1210
- }), N.appendChild(P);
1228
+ }), P.appendChild(M);
1211
1229
  const K = document.createElement("button");
1212
1230
  K.className = "tbw-filter-clear-btn", K.textContent = "Clear Filter", K.addEventListener("click", () => {
1213
1231
  t.clearFilter();
1214
- }), N.appendChild(K), e.appendChild(N);
1232
+ }), P.appendChild(K), e.appendChild(P);
1215
1233
  }
1216
1234
  /**
1217
1235
  * Apply a set filter (exclude values)
@@ -1222,10 +1240,7 @@ class _ extends y {
1222
1240
  type: "set",
1223
1241
  operator: "notIn",
1224
1242
  value: t
1225
- }), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
1226
- filters: [...this.filters.values()],
1227
- filteredRowCount: 0
1228
- }), this.requestRender();
1243
+ }), this.applyFiltersInternal();
1229
1244
  }
1230
1245
  /**
1231
1246
  * Apply a text filter
@@ -1237,8 +1252,28 @@ class _ extends y {
1237
1252
  operator: t,
1238
1253
  value: n,
1239
1254
  valueTo: o
1240
- }), this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
1241
- filters: [...this.filters.values()],
1255
+ }), this.applyFiltersInternal();
1256
+ }
1257
+ /**
1258
+ * Internal method to apply filters (sync or async based on config)
1259
+ */
1260
+ applyFiltersInternal() {
1261
+ this.cachedResult = null, this.cacheKey = null;
1262
+ const e = [...this.filters.values()];
1263
+ if (this.config.filterHandler) {
1264
+ const t = this.grid;
1265
+ t.setAttribute("aria-busy", "true");
1266
+ const n = this.config.filterHandler(e, this.sourceRows), o = (i) => {
1267
+ t.removeAttribute("aria-busy"), this.cachedResult = i, this.grid.rows = i, this.emit("filter-change", {
1268
+ filters: e,
1269
+ filteredRowCount: i.length
1270
+ }), this.requestRender();
1271
+ };
1272
+ n && typeof n.then == "function" ? n.then(o) : o(n);
1273
+ return;
1274
+ }
1275
+ this.emit("filter-change", {
1276
+ filters: e,
1242
1277
  filteredRowCount: 0
1243
1278
  }), this.requestRender();
1244
1279
  }
@@ -1278,10 +1313,10 @@ class _ extends y {
1278
1313
  }
1279
1314
  // #endregion
1280
1315
  // #region Styles
1281
- styles = ot;
1316
+ styles = it;
1282
1317
  // #endregion
1283
1318
  }
1284
- function rt(s) {
1319
+ function st(s) {
1285
1320
  if (!s.length) return [];
1286
1321
  const e = /* @__PURE__ */ new Map(), t = [], n = (r, l) => {
1287
1322
  if (!l.length) return;
@@ -1316,7 +1351,7 @@ function rt(s) {
1316
1351
  }, e.set(d, c), t.push(c)), c.columns.push(r);
1317
1352
  }), o.length && n(i, o), t.length === 1 && t[0].implicit && t[0].columns.length === s.length ? [] : t;
1318
1353
  }
1319
- function st(s, e, t) {
1354
+ function lt(s, e, t) {
1320
1355
  if (!e.length || !s) return;
1321
1356
  const n = /* @__PURE__ */ new Map();
1322
1357
  for (const i of e)
@@ -1332,7 +1367,7 @@ function st(s, e, t) {
1332
1367
  l && l.classList.add("group-end");
1333
1368
  }
1334
1369
  }
1335
- function lt(s, e) {
1370
+ function at(s, e) {
1336
1371
  if (s.length === 0) return null;
1337
1372
  const t = document.createElement("div");
1338
1373
  t.className = "header-group-row", t.setAttribute("role", "row");
@@ -1342,11 +1377,11 @@ function lt(s, e) {
1342
1377
  }
1343
1378
  return t;
1344
1379
  }
1345
- function at(s) {
1380
+ function dt(s) {
1346
1381
  return s.some((e) => e.group != null);
1347
1382
  }
1348
- const dt = ".header-group-row{display:grid;grid-auto-flow:column;background:var(--tbw-grouping-columns-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell{display:flex;align-items:center;justify-content:center;padding:4px 8px;font-weight:600;font-size:.9em;text-transform:uppercase;letter-spacing:.5px;border-right:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell:last-child{border-right:none}.header-row .cell.grouped{border-top:none}.header-row .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong))}.header-row .cell.group-end:last-child{border-right:none}.header-group-row.no-borders{border-bottom:none}.header-group-row.no-borders .header-group-cell{border-right:none}.header-row.no-group-borders .cell.group-end{border-right:1px solid var(--tbw-color-border)}";
1349
- class Cn extends y {
1383
+ const ct = ".header-group-row{display:grid;grid-auto-flow:column;background:var(--tbw-grouping-columns-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell{display:flex;align-items:center;justify-content:center;padding:4px 8px;font-weight:600;font-size:.9em;text-transform:uppercase;letter-spacing:.5px;border-right:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell:last-child{border-right:none}.header-row .cell.grouped{border-top:none}.header-row .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong))}.header-row .cell.group-end:last-child{border-right:none}.header-group-row.no-borders{border-bottom:none}.header-group-row.no-borders .header-group-cell{border-right:none}.header-row.no-group-borders .cell.group-end{border-right:1px solid var(--tbw-color-border)}";
1384
+ class Cn extends v {
1350
1385
  name = "groupingColumns";
1351
1386
  version = "1.0.0";
1352
1387
  get defaultConfig() {
@@ -1369,12 +1404,12 @@ class Cn extends y {
1369
1404
  */
1370
1405
  static detect(e, t) {
1371
1406
  const n = t?.columns;
1372
- return Array.isArray(n) ? at(n) : !1;
1407
+ return Array.isArray(n) ? dt(n) : !1;
1373
1408
  }
1374
1409
  // #endregion
1375
1410
  // #region Hooks
1376
1411
  processColumns(e) {
1377
- const t = rt(e);
1412
+ const t = st(e);
1378
1413
  return t.length === 0 ? (this.isActive = !1, this.groups = [], [...e]) : (this.isActive = !0, this.groups = t, [...e]);
1379
1414
  }
1380
1415
  afterRender() {
@@ -1387,14 +1422,14 @@ class Cn extends y {
1387
1422
  if (!e) return;
1388
1423
  const t = e.querySelector(".header-group-row");
1389
1424
  t && t.remove();
1390
- const n = lt(this.groups, this.columns);
1425
+ const n = at(this.groups, this.columns);
1391
1426
  if (n) {
1392
1427
  n.classList.toggle("no-borders", !this.config.showGroupBorders);
1393
1428
  const i = e.querySelector(".header-row");
1394
1429
  i ? e.insertBefore(n, i) : e.appendChild(n);
1395
1430
  }
1396
1431
  const o = e.querySelector(".header-row");
1397
- o && (o.classList.toggle("no-group-borders", !this.config.showGroupBorders), st(o, this.groups, this.columns));
1432
+ o && (o.classList.toggle("no-group-borders", !this.config.showGroupBorders), lt(o, this.groups, this.columns));
1398
1433
  }
1399
1434
  // #endregion
1400
1435
  // #region Public API
@@ -1429,10 +1464,10 @@ class Cn extends y {
1429
1464
  }
1430
1465
  // #endregion
1431
1466
  // #region Styles
1432
- styles = dt;
1467
+ styles = ct;
1433
1468
  // #endregion
1434
1469
  }
1435
- function ct({ rows: s, config: e, expanded: t }) {
1470
+ function ut({ rows: s, config: e, expanded: t }) {
1436
1471
  const n = e.groupOn;
1437
1472
  if (typeof n != "function")
1438
1473
  return [];
@@ -1443,8 +1478,8 @@ function ct({ rows: s, config: e, expanded: t }) {
1443
1478
  let d = o;
1444
1479
  a.forEach((c, u) => {
1445
1480
  const h = c == null ? "∅" : String(c), g = d.key === "__root__" ? h : d.key + "||" + h;
1446
- let p = d.children.get(h);
1447
- p || (p = { key: g, value: c, depth: u, rows: [], children: /* @__PURE__ */ new Map(), parent: d }, d.children.set(h, p)), d = p;
1481
+ let f = d.children.get(h);
1482
+ f || (f = { key: g, value: c, depth: u, rows: [], children: /* @__PURE__ */ new Map(), parent: d }, d.children.set(h, f)), d = f;
1448
1483
  }), d.rows.push(l);
1449
1484
  }), o.children.size === 1 && o.children.has("__ungrouped__") && o.children.get("__ungrouped__").rows.length === s.length)
1450
1485
  return [];
@@ -1465,24 +1500,24 @@ function ct({ rows: s, config: e, expanded: t }) {
1465
1500
  };
1466
1501
  return r(o), i;
1467
1502
  }
1468
- function ut(s, e) {
1503
+ function ht(s, e) {
1469
1504
  const t = new Set(s);
1470
1505
  return t.has(e) ? t.delete(e) : t.add(e), t;
1471
1506
  }
1472
- function ht(s) {
1507
+ function gt(s) {
1473
1508
  const e = /* @__PURE__ */ new Set();
1474
1509
  for (const t of s)
1475
1510
  t.kind === "group" && e.add(t.key);
1476
1511
  return e;
1477
1512
  }
1478
- function gt() {
1513
+ function ft() {
1479
1514
  return /* @__PURE__ */ new Set();
1480
1515
  }
1481
1516
  function pt(s) {
1482
1517
  return s.kind !== "group" ? 0 : s.rows.length;
1483
1518
  }
1484
- const ft = '.group-row{background:var(--tbw-grouping-rows-bg, var(--tbw-color-panel-bg));font-weight:500}.group-row:hover{background:var(--tbw-grouping-rows-bg-hover, var(--tbw-color-row-hover))}.group-toggle{cursor:pointer;user-select:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:4px;font-size:10px}.group-toggle:hover{background:var(--tbw-grouping-rows-toggle-hover, var(--tbw-color-row-hover));border-radius:2px}.group-label{display:inline-flex;align-items:center;gap:8px}.group-count{color:var(--tbw-grouping-rows-count-color, var(--tbw-color-fg-muted));font-size:.85em;font-weight:400}[data-group-depth="0"] .group-label{padding-left:0}[data-group-depth="1"] .group-label{padding-left:20px}[data-group-depth="2"] .group-label{padding-left:40px}[data-group-depth="3"] .group-label{padding-left:60px}[data-group-depth="4"] .group-label{padding-left:80px}';
1485
- class Rn extends y {
1519
+ const mt = '.group-row{background:var(--tbw-grouping-rows-bg, var(--tbw-color-panel-bg));font-weight:500}.group-row:hover{background:var(--tbw-grouping-rows-bg-hover, var(--tbw-color-row-hover))}.group-toggle{cursor:pointer;user-select:none;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:4px}.group-toggle:hover{background:var(--tbw-grouping-rows-toggle-hover, var(--tbw-color-row-hover));border-radius:2px}.group-label{display:inline-flex;align-items:center;gap:8px}.group-count{color:var(--tbw-grouping-rows-count-color, var(--tbw-color-fg-muted));font-size:.85em;font-weight:400}[data-group-depth="0"] .group-label{padding-left:0}[data-group-depth="1"] .group-label{padding-left:20px}[data-group-depth="2"] .group-label{padding-left:40px}[data-group-depth="3"] .group-label{padding-left:60px}[data-group-depth="4"] .group-label{padding-left:80px}.data-grid-row.tbw-group-slide-in{animation:tbw-group-slide-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-group-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}.data-grid-row.tbw-group-fade-in{animation:tbw-group-fade-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-group-fade-in{0%{opacity:0}to{opacity:1}}';
1520
+ class Rn extends v {
1486
1521
  name = "groupingRows";
1487
1522
  version = "1.0.0";
1488
1523
  get defaultConfig() {
@@ -1490,17 +1525,32 @@ class Rn extends y {
1490
1525
  defaultExpanded: !1,
1491
1526
  showRowCount: !0,
1492
1527
  indentWidth: 20,
1493
- aggregators: {}
1528
+ aggregators: {},
1529
+ animation: "slide"
1494
1530
  };
1495
1531
  }
1496
1532
  // #region Internal State
1497
1533
  expandedKeys = /* @__PURE__ */ new Set();
1498
1534
  flattenedRows = [];
1499
1535
  isActive = !1;
1536
+ previousVisibleKeys = /* @__PURE__ */ new Set();
1537
+ keysToAnimate = /* @__PURE__ */ new Set();
1538
+ // #endregion
1539
+ // #region Animation
1540
+ get animationStyle() {
1541
+ const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
1542
+ if (t === !1 || t === "off") return !1;
1543
+ if (t !== !0 && t !== "on") {
1544
+ const n = this.shadowRoot?.host;
1545
+ if (n && getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() === "0")
1546
+ return !1;
1547
+ }
1548
+ return this.config.animation ?? "slide";
1549
+ }
1500
1550
  // #endregion
1501
1551
  // #region Lifecycle
1502
1552
  detach() {
1503
- this.expandedKeys.clear(), this.flattenedRows = [], this.isActive = !1;
1553
+ this.expandedKeys.clear(), this.flattenedRows = [], this.isActive = !1, this.previousVisibleKeys.clear(), this.keysToAnimate.clear();
1504
1554
  }
1505
1555
  // #endregion
1506
1556
  // #region Hooks
@@ -1515,20 +1565,29 @@ class Rn extends y {
1515
1565
  const t = this.config;
1516
1566
  if (typeof t.groupOn != "function")
1517
1567
  return this.isActive = !1, this.flattenedRows = [], [...e];
1518
- const n = ct({
1568
+ const n = ut({
1519
1569
  rows: e,
1520
1570
  config: t,
1521
1571
  expanded: this.expandedKeys
1522
1572
  });
1523
- return n.length === 0 ? (this.isActive = !1, this.flattenedRows = [], [...e]) : (this.isActive = !0, this.flattenedRows = n, n.map((o) => o.kind === "group" ? {
1573
+ if (n.length === 0)
1574
+ return this.isActive = !1, this.flattenedRows = [], [...e];
1575
+ this.isActive = !0, this.flattenedRows = n, this.keysToAnimate.clear();
1576
+ const o = /* @__PURE__ */ new Set();
1577
+ return n.forEach((i, r) => {
1578
+ if (i.kind === "data") {
1579
+ const l = `data-${r}`;
1580
+ o.add(l), this.previousVisibleKeys.has(l) || this.keysToAnimate.add(l);
1581
+ }
1582
+ }), this.previousVisibleKeys = o, n.map((i) => i.kind === "group" ? {
1524
1583
  __isGroupRow: !0,
1525
- __groupKey: o.key,
1526
- __groupValue: o.value,
1527
- __groupDepth: o.depth,
1528
- __groupRows: o.rows,
1529
- __groupExpanded: o.expanded,
1530
- __groupRowCount: pt(o)
1531
- } : o.row));
1584
+ __groupKey: i.key,
1585
+ __groupValue: i.value,
1586
+ __groupDepth: i.depth,
1587
+ __groupRows: i.rows,
1588
+ __groupExpanded: i.expanded,
1589
+ __groupRowCount: pt(i)
1590
+ } : i.row);
1532
1591
  }
1533
1592
  onCellClick(e) {
1534
1593
  const t = e.row;
@@ -1562,6 +1621,16 @@ class Rn extends y {
1562
1621
  return t.className = "group-row", t.__isCustomRow = !0, t.setAttribute("data-group-depth", String(e.__groupDepth)), t.setAttribute("role", "row"), t.setAttribute("aria-expanded", String(e.__groupExpanded)), t.style.paddingLeft = `${(e.__groupDepth || 0) * (o.indentWidth ?? 20)}px`, t.innerHTML = "", o.fullWidth !== !1 ? this.renderFullWidthGroupRow(e, t, i) : this.renderPerColumnGroupRow(e, t, i), !0;
1563
1622
  }
1564
1623
  afterRender() {
1624
+ const e = this.animationStyle;
1625
+ if (e === !1 || this.keysToAnimate.size === 0) return;
1626
+ const t = this.shadowRoot?.querySelector(".rows");
1627
+ if (!t) return;
1628
+ const n = e === "fade" ? "tbw-group-fade-in" : "tbw-group-slide-in";
1629
+ for (const o of t.querySelectorAll(".data-grid-row:not(.group-row)")) {
1630
+ const i = o.querySelector(".cell[data-row]"), r = i ? parseInt(i.getAttribute("data-row") ?? "-1", 10) : -1, a = this.flattenedRows[r]?.kind === "data" ? `data-${r}` : void 0;
1631
+ a && this.keysToAnimate.has(a) && (o.classList.add(n), o.addEventListener("animationend", () => o.classList.remove(n), { once: !0 }));
1632
+ }
1633
+ this.keysToAnimate.clear();
1565
1634
  }
1566
1635
  // #endregion
1567
1636
  // #region Private Rendering Helpers
@@ -1569,7 +1638,7 @@ class Rn extends y {
1569
1638
  const o = this.config, i = document.createElement("div");
1570
1639
  i.className = "cell group-full", i.style.gridColumn = "1 / -1", i.setAttribute("role", "gridcell");
1571
1640
  const r = document.createElement("button");
1572
- r.type = "button", r.className = "group-toggle", r.setAttribute("aria-label", e.__groupExpanded ? "Collapse group" : "Expand group"), this.setIcon(r, this.resolveIcon(e.__groupExpanded ? "collapse" : "expand")), r.addEventListener("click", (d) => {
1641
+ r.type = "button", r.className = `group-toggle${e.__groupExpanded ? " expanded" : ""}`, r.setAttribute("aria-label", e.__groupExpanded ? "Collapse group" : "Expand group"), this.setIcon(r, this.resolveIcon(e.__groupExpanded ? "collapse" : "expand")), r.addEventListener("click", (d) => {
1573
1642
  d.stopPropagation(), n();
1574
1643
  }), i.appendChild(r);
1575
1644
  const l = document.createElement("span");
@@ -1587,26 +1656,26 @@ class Rn extends y {
1587
1656
  const h = document.createElement("div");
1588
1657
  if (h.className = "cell group-cell", h.setAttribute("data-col", String(u)), h.setAttribute("role", "gridcell"), u === 0) {
1589
1658
  const g = document.createElement("button");
1590
- g.type = "button", g.className = "group-toggle", g.setAttribute("aria-label", e.__groupExpanded ? "Collapse group" : "Expand group"), this.setIcon(g, this.resolveIcon(e.__groupExpanded ? "collapse" : "expand")), g.addEventListener("click", (f) => {
1591
- f.stopPropagation(), n();
1659
+ g.type = "button", g.className = `group-toggle${e.__groupExpanded ? " expanded" : ""}`, g.setAttribute("aria-label", e.__groupExpanded ? "Collapse group" : "Expand group"), this.setIcon(g, this.resolveIcon(e.__groupExpanded ? "collapse" : "expand")), g.addEventListener("click", (p) => {
1660
+ p.stopPropagation(), n();
1592
1661
  }), h.appendChild(g);
1593
- const p = document.createElement("span"), m = i[c.field];
1662
+ const f = document.createElement("span"), m = i[c.field];
1594
1663
  if (m) {
1595
- const f = se(m, l, c.field, c);
1596
- p.textContent = f != null ? String(f) : String(e.__groupValue);
1664
+ const p = se(m, l, c.field, c);
1665
+ f.textContent = p != null ? String(p) : String(e.__groupValue);
1597
1666
  } else {
1598
- const f = o.formatLabel ? o.formatLabel(e.__groupValue, e.__groupDepth || 0, e.__groupKey) : String(e.__groupValue);
1599
- p.textContent = f;
1667
+ const p = o.formatLabel ? o.formatLabel(e.__groupValue, e.__groupDepth || 0, e.__groupKey) : String(e.__groupValue);
1668
+ f.textContent = p;
1600
1669
  }
1601
- if (h.appendChild(p), o.showRowCount !== !1) {
1602
- const f = document.createElement("span");
1603
- f.className = "group-count", f.textContent = ` (${l.length})`, h.appendChild(f);
1670
+ if (h.appendChild(f), o.showRowCount !== !1) {
1671
+ const p = document.createElement("span");
1672
+ p.className = "group-count", p.textContent = ` (${l.length})`, h.appendChild(p);
1604
1673
  }
1605
1674
  } else {
1606
1675
  const g = i[c.field];
1607
1676
  if (g) {
1608
- const p = se(g, l, c.field, c);
1609
- h.textContent = p != null ? String(p) : "";
1677
+ const f = se(g, l, c.field, c);
1678
+ h.textContent = f != null ? String(f) : "";
1610
1679
  } else
1611
1680
  h.textContent = "";
1612
1681
  }
@@ -1619,20 +1688,20 @@ class Rn extends y {
1619
1688
  * Expand all groups.
1620
1689
  */
1621
1690
  expandAll() {
1622
- this.expandedKeys = ht(this.flattenedRows), this.requestRender();
1691
+ this.expandedKeys = gt(this.flattenedRows), this.requestRender();
1623
1692
  }
1624
1693
  /**
1625
1694
  * Collapse all groups.
1626
1695
  */
1627
1696
  collapseAll() {
1628
- this.expandedKeys = gt(), this.requestRender();
1697
+ this.expandedKeys = ft(), this.requestRender();
1629
1698
  }
1630
1699
  /**
1631
1700
  * Toggle expansion of a specific group.
1632
1701
  * @param key - The group key to toggle
1633
1702
  */
1634
1703
  toggle(e) {
1635
- this.expandedKeys = ut(this.expandedKeys, e);
1704
+ this.expandedKeys = ht(this.expandedKeys, e);
1636
1705
  const t = this.flattenedRows.find((n) => n.kind === "group" && n.key === e);
1637
1706
  this.emit("group-toggle", {
1638
1707
  key: e,
@@ -1723,25 +1792,25 @@ class Rn extends y {
1723
1792
  }
1724
1793
  // #endregion
1725
1794
  // #region Styles
1726
- styles = ft;
1795
+ styles = mt;
1727
1796
  // #endregion
1728
1797
  }
1729
- function V(s, e) {
1798
+ function z(s, e) {
1730
1799
  const t = new Set(s);
1731
1800
  return t.has(e) ? t.delete(e) : t.add(e), t;
1732
1801
  }
1733
- function mt(s, e) {
1802
+ function wt(s, e) {
1734
1803
  const t = new Set(s);
1735
1804
  return t.add(e), t;
1736
1805
  }
1737
- function wt(s, e) {
1806
+ function bt(s, e) {
1738
1807
  const t = new Set(s);
1739
1808
  return t.delete(e), t;
1740
1809
  }
1741
- function bt(s, e) {
1810
+ function vt(s, e) {
1742
1811
  return s.has(e);
1743
1812
  }
1744
- function vt(s, e, t, n) {
1813
+ function xt(s, e, t, n) {
1745
1814
  const o = document.createElement("div");
1746
1815
  o.className = "master-detail-row", o.setAttribute("data-detail-for", String(e)), o.setAttribute("role", "row");
1747
1816
  const i = document.createElement("div");
@@ -1749,8 +1818,8 @@ function vt(s, e, t, n) {
1749
1818
  const r = t(s, e);
1750
1819
  return typeof r == "string" ? i.innerHTML = r : r instanceof HTMLElement && i.appendChild(r), o.appendChild(i), o;
1751
1820
  }
1752
- const xt = ".master-detail-cell-wrapper{display:flex;align-items:center;gap:4px}.master-detail-toggle{cursor:pointer;font-size:10px;opacity:.7;user-select:none}.master-detail-toggle:hover{opacity:1}.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))}.master-detail-cell{padding:16px;overflow:auto}";
1753
- class Sn extends y {
1821
+ const yt = ".master-detail-cell-wrapper{display:flex;align-items:center;gap:4px}.master-detail-toggle{cursor:pointer;opacity:.7;user-select:none;display:inline-flex;align-items:center;justify-content:center}.master-detail-toggle:hover{opacity:1}.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}.master-detail-cell{padding:16px;overflow:auto}.master-detail-row.tbw-expanding{animation:tbw-detail-expand var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}.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:500px;padding-top:16px;padding-bottom:16px}}@keyframes tbw-detail-collapse{0%{opacity:1;max-height:500px}to{opacity:0;max-height:0}}";
1822
+ class Sn extends v {
1754
1823
  name = "masterDetail";
1755
1824
  version = "1.0.0";
1756
1825
  get defaultConfig() {
@@ -1758,9 +1827,67 @@ class Sn extends y {
1758
1827
  detailHeight: "auto",
1759
1828
  expandOnRowClick: !1,
1760
1829
  collapseOnClickOutside: !1,
1761
- showExpandColumn: !0
1830
+ showExpandColumn: !0,
1831
+ animation: "slide"
1832
+ // Plugin's own default
1762
1833
  };
1763
1834
  }
1835
+ // #region Animation Helpers
1836
+ /**
1837
+ * Check if animations are enabled at the grid level.
1838
+ * Respects gridConfig.animation.mode and CSS variable.
1839
+ */
1840
+ get isAnimationEnabled() {
1841
+ const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
1842
+ if (t === !1 || t === "off") return !1;
1843
+ if (t === !0 || t === "on") return !0;
1844
+ const n = this.shadowRoot?.host;
1845
+ return n ? getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
1846
+ }
1847
+ /**
1848
+ * Get expand/collapse animation style from plugin config.
1849
+ */
1850
+ get animationStyle() {
1851
+ return this.isAnimationEnabled ? this.config.animation ?? "slide" : !1;
1852
+ }
1853
+ /**
1854
+ * Get animation duration from CSS variable (set by grid).
1855
+ */
1856
+ get animationDuration() {
1857
+ const e = this.shadowRoot?.host;
1858
+ if (e) {
1859
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(t, 10);
1860
+ if (!isNaN(n)) return n;
1861
+ }
1862
+ return 200;
1863
+ }
1864
+ /**
1865
+ * Apply expand animation to a detail element.
1866
+ */
1867
+ animateExpand(e) {
1868
+ !this.isAnimationEnabled || this.animationStyle === !1 || (e.classList.add("tbw-expanding"), e.addEventListener(
1869
+ "animationend",
1870
+ () => {
1871
+ e.classList.remove("tbw-expanding");
1872
+ },
1873
+ { once: !0 }
1874
+ ));
1875
+ }
1876
+ /**
1877
+ * Apply collapse animation to a detail element and remove after animation.
1878
+ */
1879
+ animateCollapse(e, t) {
1880
+ if (!this.isAnimationEnabled || this.animationStyle === !1) {
1881
+ t();
1882
+ return;
1883
+ }
1884
+ e.classList.add("tbw-collapsing");
1885
+ const n = () => {
1886
+ e.classList.remove("tbw-collapsing"), t();
1887
+ };
1888
+ e.addEventListener("animationend", n, { once: !0 }), setTimeout(n, this.animationDuration + 50);
1889
+ }
1890
+ // #endregion
1764
1891
  // #region Internal State
1765
1892
  expandedRows = /* @__PURE__ */ new Set();
1766
1893
  detailElements = /* @__PURE__ */ new Map();
@@ -1783,11 +1910,11 @@ class Sn extends y {
1783
1910
  const { value: l, row: a } = r, d = this.expandedRows.has(a), c = document.createElement("span");
1784
1911
  c.className = "master-detail-cell-wrapper";
1785
1912
  const u = document.createElement("span");
1786
- u.className = "master-detail-toggle", this.setIcon(u, this.resolveIcon(d ? "collapse" : "expand")), u.setAttribute("role", "button"), u.setAttribute("tabindex", "0"), u.setAttribute("aria-expanded", String(d)), u.setAttribute("aria-label", d ? "Collapse details" : "Expand details"), u.addEventListener("click", (g) => {
1913
+ u.className = `master-detail-toggle${d ? " expanded" : ""}`, this.setIcon(u, this.resolveIcon(d ? "collapse" : "expand")), u.setAttribute("role", "button"), u.setAttribute("tabindex", "0"), u.setAttribute("aria-expanded", String(d)), u.setAttribute("aria-label", d ? "Collapse details" : "Expand details"), u.addEventListener("click", (g) => {
1787
1914
  g.stopPropagation();
1788
- const p = this.rows.indexOf(a);
1789
- this.expandedRows = V(this.expandedRows, a), this.emit("detail-expand", {
1790
- rowIndex: p,
1915
+ const f = this.rows.indexOf(a);
1916
+ this.expandedRows = z(this.expandedRows, a), this.emit("detail-expand", {
1917
+ rowIndex: f,
1791
1918
  row: a,
1792
1919
  expanded: this.expandedRows.has(a)
1793
1920
  }), this.requestRender();
@@ -1806,7 +1933,7 @@ class Sn extends y {
1806
1933
  }
1807
1934
  onRowClick(e) {
1808
1935
  if (!(!this.config.expandOnRowClick || !this.config.detailRenderer))
1809
- return this.expandedRows = V(this.expandedRows, e.row), this.emit("detail-expand", {
1936
+ return this.expandedRows = z(this.expandedRows, e.row), this.emit("detail-expand", {
1810
1937
  rowIndex: e.rowIndex,
1811
1938
  row: e.row,
1812
1939
  expanded: this.expandedRows.has(e.row)
@@ -1851,8 +1978,8 @@ class Sn extends y {
1851
1978
  d.previousElementSibling !== l && l.after(d);
1852
1979
  continue;
1853
1980
  }
1854
- const c = vt(a, r, this.config.detailRenderer, o);
1855
- typeof this.config.detailHeight == "number" && (c.style.height = `${this.config.detailHeight}px`), l.after(c), this.detailElements.set(a, c);
1981
+ const c = xt(a, r, this.config.detailRenderer, o);
1982
+ typeof this.config.detailHeight == "number" && (c.style.height = `${this.config.detailHeight}px`), l.after(c), this.detailElements.set(a, c), this.animateExpand(c);
1856
1983
  }
1857
1984
  }
1858
1985
  /**
@@ -1919,7 +2046,7 @@ class Sn extends y {
1919
2046
  */
1920
2047
  expand(e) {
1921
2048
  const t = this.rows[e];
1922
- t && (this.expandedRows = mt(this.expandedRows, t), this.requestRender());
2049
+ t && (this.expandedRows = wt(this.expandedRows, t), this.requestRender());
1923
2050
  }
1924
2051
  /**
1925
2052
  * Collapse the detail row at the given index.
@@ -1927,7 +2054,7 @@ class Sn extends y {
1927
2054
  */
1928
2055
  collapse(e) {
1929
2056
  const t = this.rows[e];
1930
- t && (this.expandedRows = wt(this.expandedRows, t), this.requestRender());
2057
+ t && (this.expandedRows = bt(this.expandedRows, t), this.requestRender());
1931
2058
  }
1932
2059
  /**
1933
2060
  * Toggle the detail row at the given index.
@@ -1935,7 +2062,7 @@ class Sn extends y {
1935
2062
  */
1936
2063
  toggle(e) {
1937
2064
  const t = this.rows[e];
1938
- t && (this.expandedRows = V(this.expandedRows, t), this.requestRender());
2065
+ t && (this.expandedRows = z(this.expandedRows, t), this.requestRender());
1939
2066
  }
1940
2067
  /**
1941
2068
  * Check if the detail row at the given index is expanded.
@@ -1944,7 +2071,7 @@ class Sn extends y {
1944
2071
  */
1945
2072
  isExpanded(e) {
1946
2073
  const t = this.rows[e];
1947
- return t ? bt(this.expandedRows, t) : !1;
2074
+ return t ? vt(this.expandedRows, t) : !1;
1948
2075
  }
1949
2076
  /**
1950
2077
  * Expand all detail rows.
@@ -1983,23 +2110,23 @@ class Sn extends y {
1983
2110
  }
1984
2111
  // #endregion
1985
2112
  // #region Styles
1986
- styles = xt;
2113
+ styles = yt;
1987
2114
  // #endregion
1988
2115
  }
1989
- function yt(s, e, t) {
2116
+ function Ct(s, e, t) {
1990
2117
  return e.length ? [...s].sort((n, o) => {
1991
2118
  for (const i of e) {
1992
- const l = t.find((u) => u.field === i.field)?.sortComparator ?? Ct, a = n[i.field], d = o[i.field], c = l(a, d, n, o);
2119
+ const l = t.find((u) => u.field === i.field)?.sortComparator ?? Rt, a = n[i.field], d = o[i.field], c = l(a, d, n, o);
1993
2120
  if (c !== 0)
1994
2121
  return i.direction === "asc" ? c : -c;
1995
2122
  }
1996
2123
  return 0;
1997
2124
  }) : [...s];
1998
2125
  }
1999
- function Ct(s, e) {
2126
+ function Rt(s, e) {
2000
2127
  return s == null && e == null ? 0 : s == null ? 1 : e == null ? -1 : typeof s == "number" && typeof e == "number" ? s - e : s instanceof Date && e instanceof Date ? s.getTime() - e.getTime() : typeof s == "boolean" && typeof e == "boolean" ? s === e ? 0 : s ? -1 : 1 : String(s).localeCompare(String(e));
2001
2128
  }
2002
- function Rt(s, e, t, n) {
2129
+ function St(s, e, t, n) {
2003
2130
  const o = s.find((i) => i.field === e);
2004
2131
  return t ? o ? o.direction === "asc" ? s.map((i) => i.field === e ? { ...i, direction: "desc" } : i) : s.filter((i) => i.field !== e) : s.length < n ? [...s, { field: e, direction: "asc" }] : s : o?.direction === "asc" ? [{ field: e, direction: "desc" }] : o?.direction === "desc" ? [] : [{ field: e, direction: "asc" }];
2005
2132
  }
@@ -2010,8 +2137,8 @@ function be(s, e) {
2010
2137
  function ve(s, e) {
2011
2138
  return s.find((t) => t.field === e)?.direction;
2012
2139
  }
2013
- const St = '.header-cell[data-sort=asc]:after{content:"↑";margin-left:4px;opacity:.8}.header-cell[data-sort=desc]:after{content:"↓";margin-left:4px;opacity:.8}.sort-index{font-size:10px;background:var(--tbw-multi-sort-badge-bg, var(--tbw-color-panel-bg));color:var(--tbw-multi-sort-badge-color, var(--tbw-color-fg));border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;margin-left:2px;font-weight:600}';
2014
- class En extends y {
2140
+ const kt = '.header-cell[data-sort=asc]:after{content:"↑";margin-left:4px;opacity:.8}.header-cell[data-sort=desc]:after{content:"↓";margin-left:4px;opacity:.8}.sort-indicator{margin-left:4px;opacity:.8}.sort-index{font-size:10px;background:var(--tbw-multi-sort-badge-bg, var(--tbw-color-panel-bg));color:var(--tbw-multi-sort-badge-color, var(--tbw-color-fg));border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center;margin-left:2px;font-weight:600}';
2141
+ class kn extends v {
2015
2142
  name = "multiSort";
2016
2143
  version = "1.0.0";
2017
2144
  get defaultConfig() {
@@ -2030,12 +2157,12 @@ class En extends y {
2030
2157
  // #endregion
2031
2158
  // #region Hooks
2032
2159
  processRows(e) {
2033
- return this.sortModel.length === 0 ? [...e] : yt([...e], this.sortModel, [...this.columns]);
2160
+ return this.sortModel.length === 0 ? [...e] : Ct([...e], this.sortModel, [...this.columns]);
2034
2161
  }
2035
2162
  onHeaderClick(e) {
2036
2163
  if (!this.columns.find((i) => i.field === e.field)?.sortable) return !1;
2037
2164
  const n = e.originalEvent.shiftKey, o = this.config.maxSortColumns ?? 3;
2038
- return this.sortModel = Rt(this.sortModel, e.field, n, o), this.emit("sort-change", { sortModel: [...this.sortModel] }), this.requestRender(), !0;
2165
+ return this.sortModel = St(this.sortModel, e.field, n, o), this.emit("sort-change", { sortModel: [...this.sortModel] }), this.requestRender(), !0;
2039
2166
  }
2040
2167
  afterRender() {
2041
2168
  const e = this.shadowRoot;
@@ -2048,7 +2175,7 @@ class En extends y {
2048
2175
  if (o.querySelector(".sort-index")?.remove(), l) {
2049
2176
  o.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove(), o.setAttribute("data-sort", l);
2050
2177
  const c = document.createElement("span");
2051
- if (c.className = "sort-indicator", c.style.marginLeft = "4px", c.style.opacity = "0.8", this.setIcon(c, this.resolveIcon(l === "asc" ? "sortAsc" : "sortDesc")), o.appendChild(c), t && this.sortModel.length > 1 && r !== void 0) {
2178
+ if (c.className = "sort-indicator", this.setIcon(c, this.resolveIcon(l === "asc" ? "sortAsc" : "sortDesc")), o.appendChild(c), t && this.sortModel.length > 1 && r !== void 0) {
2052
2179
  const u = document.createElement("span");
2053
2180
  u.className = "sort-index", u.textContent = String(r), o.appendChild(u);
2054
2181
  }
@@ -2125,16 +2252,16 @@ class En extends y {
2125
2252
  }
2126
2253
  // #endregion
2127
2254
  // #region Styles
2128
- styles = St;
2255
+ styles = kt;
2129
2256
  // #endregion
2130
2257
  }
2131
2258
  function Et(s) {
2132
2259
  return s.filter((e) => e.sticky === "left");
2133
2260
  }
2134
- function kt(s) {
2261
+ function At(s) {
2135
2262
  return s.filter((e) => e.sticky === "right");
2136
2263
  }
2137
- function z(s) {
2264
+ function W(s) {
2138
2265
  return s.some((e) => e.sticky === "left" || e.sticky === "right");
2139
2266
  }
2140
2267
  function xe(s, e) {
@@ -2170,7 +2297,7 @@ function ye(s) {
2170
2297
  n.classList.remove("sticky-left", "sticky-right"), n.style.position = "", n.style.left = "", n.style.right = "";
2171
2298
  });
2172
2299
  }
2173
- class kn extends y {
2300
+ class En extends v {
2174
2301
  name = "pinnedColumns";
2175
2302
  version = "1.0.0";
2176
2303
  get defaultConfig() {
@@ -2192,18 +2319,18 @@ class kn extends y {
2192
2319
  */
2193
2320
  static detect(e, t) {
2194
2321
  const n = t?.columns;
2195
- return Array.isArray(n) ? z(n) : !1;
2322
+ return Array.isArray(n) ? W(n) : !1;
2196
2323
  }
2197
2324
  // #endregion
2198
2325
  // #region Hooks
2199
2326
  processColumns(e) {
2200
- return this.isApplied = z([...e]), [...e];
2327
+ return this.isApplied = W([...e]), [...e];
2201
2328
  }
2202
2329
  afterRender() {
2203
2330
  if (!this.isApplied)
2204
2331
  return;
2205
2332
  const e = this.grid, t = [...this.columns];
2206
- if (!z(t)) {
2333
+ if (!W(t)) {
2207
2334
  ye(e), this.isApplied = !1;
2208
2335
  return;
2209
2336
  }
@@ -2216,7 +2343,7 @@ class kn extends y {
2216
2343
  */
2217
2344
  onPluginQuery(e) {
2218
2345
  switch (e.type) {
2219
- case Ke.CAN_MOVE_COLUMN: {
2346
+ case N.CAN_MOVE_COLUMN: {
2220
2347
  const t = e.context, n = t.sticky;
2221
2348
  if (n === "left" || n === "right")
2222
2349
  return !1;
@@ -2248,7 +2375,7 @@ class kn extends y {
2248
2375
  */
2249
2376
  getRightPinnedColumns() {
2250
2377
  const e = [...this.columns];
2251
- return kt(e);
2378
+ return At(e);
2252
2379
  }
2253
2380
  /**
2254
2381
  * Clear all sticky positioning.
@@ -2282,10 +2409,10 @@ class kn extends y {
2282
2409
  }
2283
2410
  // #endregion
2284
2411
  }
2285
- function At(s) {
2412
+ function _t(s) {
2286
2413
  return typeof s == "object" && s !== null && "aggFunc" in s;
2287
2414
  }
2288
- function W(s, e) {
2415
+ function $(s, e) {
2289
2416
  const t = document.createElement("div");
2290
2417
  t.className = "tbw-pinned-rows", t.setAttribute("role", "presentation"), t.setAttribute("aria-live", "polite");
2291
2418
  const n = document.createElement("div");
@@ -2307,7 +2434,7 @@ function W(s, e) {
2307
2434
  }
2308
2435
  if (s.customPanels)
2309
2436
  for (const r of s.customPanels) {
2310
- const l = _t(r, e);
2437
+ const l = It(r, e);
2311
2438
  switch (r.position) {
2312
2439
  case "left":
2313
2440
  n.appendChild(l);
@@ -2340,7 +2467,7 @@ function Re(s, e, t, n) {
2340
2467
  let a, d;
2341
2468
  const c = o.aggregators?.[r.field];
2342
2469
  if (c)
2343
- if (At(c)) {
2470
+ if (_t(c)) {
2344
2471
  const u = le(c.aggFunc);
2345
2472
  u && (a = u(n, r.field, r)), d = c.formatter;
2346
2473
  } else {
@@ -2356,7 +2483,7 @@ function Re(s, e, t, n) {
2356
2483
  s.appendChild(i);
2357
2484
  }
2358
2485
  }
2359
- function _t(s, e) {
2486
+ function It(s, e) {
2360
2487
  const t = document.createElement("div");
2361
2488
  t.className = "tbw-status-panel tbw-status-panel-custom", t.id = `status-panel-${s.id}`;
2362
2489
  const n = s.render(e);
@@ -2372,8 +2499,8 @@ function Se(s, e, t, n, o) {
2372
2499
  grid: t
2373
2500
  };
2374
2501
  }
2375
- const It = ".tbw-footer{position:sticky;bottom:0;z-index:var(--tbw-z-layer-pinned-rows, 20);background:var(--tbw-color-panel-bg)}.tbw-pinned-rows{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--tbw-pinned-rows-bg, var(--tbw-color-panel-bg));border-top:1px solid var(--tbw-pinned-rows-border, var(--tbw-color-border));font-size:12px;color:var(--tbw-pinned-rows-color, var(--tbw-color-fg-muted));min-height:32px;box-sizing:border-box;min-width:fit-content}.tbw-pinned-rows-left,.tbw-pinned-rows-center,.tbw-pinned-rows-right{display:flex;align-items:center;gap:16px}.tbw-pinned-rows-left{justify-content:flex-start}.tbw-pinned-rows-center{justify-content:center;flex:1}.tbw-pinned-rows-right{justify-content:flex-end}.tbw-status-panel{white-space:nowrap}.tbw-aggregation-rows{min-width:fit-content;background:var(--tbw-aggregation-bg, var(--tbw-color-header-bg))}.tbw-aggregation-rows-top{border-bottom:1px solid var(--tbw-aggregation-border, var(--tbw-color-border))}.tbw-aggregation-rows-bottom{border-top:1px solid var(--tbw-aggregation-border, var(--tbw-color-border))}.tbw-aggregation-row{display:grid;grid-template-columns:var(--tbw-column-template);font-size:var(--tbw-aggregation-font-size, .8em);font-weight:var(--tbw-aggregation-font-weight, 600)}.tbw-aggregation-cell{padding:var(--tbw-cell-padding, 2px 8px);min-height:var(--tbw-row-height, 28px);display:flex;align-items:center;border-right:1px solid var(--tbw-color-border-cell)}.tbw-aggregation-cell:last-child{border-right:0}.tbw-aggregation-cell-full{grid-column:1 / -1;border-right:0}";
2376
- class An extends y {
2502
+ const Lt = ".tbw-footer{position:sticky;bottom:0;z-index:var(--tbw-z-layer-pinned-rows, 20);background:var(--tbw-color-panel-bg)}.tbw-pinned-rows{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;background:var(--tbw-pinned-rows-bg, var(--tbw-color-panel-bg));border-top:1px solid var(--tbw-pinned-rows-border, var(--tbw-color-border));font-size:12px;color:var(--tbw-pinned-rows-color, var(--tbw-color-fg-muted));min-height:32px;box-sizing:border-box;min-width:fit-content}.tbw-pinned-rows-left,.tbw-pinned-rows-center,.tbw-pinned-rows-right{display:flex;align-items:center;gap:16px}.tbw-pinned-rows-left{justify-content:flex-start}.tbw-pinned-rows-center{justify-content:center;flex:1}.tbw-pinned-rows-right{justify-content:flex-end}.tbw-status-panel{white-space:nowrap}.tbw-aggregation-rows{min-width:fit-content;background:var(--tbw-aggregation-bg, var(--tbw-color-header-bg))}.tbw-aggregation-rows-top{border-bottom:1px solid var(--tbw-aggregation-border, var(--tbw-color-border))}.tbw-aggregation-rows-bottom{border-top:1px solid var(--tbw-aggregation-border, var(--tbw-color-border))}.tbw-aggregation-row{display:grid;grid-template-columns:var(--tbw-column-template);font-size:var(--tbw-aggregation-font-size, .8em);font-weight:var(--tbw-aggregation-font-weight, 600)}.tbw-aggregation-cell{padding:var(--tbw-cell-padding, 2px 8px);min-height:var(--tbw-row-height, 28px);display:flex;align-items:center;border-right:1px solid var(--tbw-color-border-cell)}.tbw-aggregation-cell:last-child{border-right:0}.tbw-aggregation-cell-full{grid-column:1 / -1;border-right:0}";
2503
+ class An extends v {
2377
2504
  name = "pinnedRows";
2378
2505
  version = "1.0.0";
2379
2506
  get defaultConfig() {
@@ -2424,9 +2551,9 @@ class An extends y {
2424
2551
  const d = this.config.showRowCount !== !1 || this.config.showSelectedCount && i.selectedRows > 0 || this.config.showFilteredCount && i.filteredRows !== i.totalRows || this.config.customPanels && this.config.customPanels.length > 0, c = d && this.config.position !== "top", u = a.length > 0 || c;
2425
2552
  if (d && this.config.position === "top")
2426
2553
  if (!this.infoBarElement)
2427
- this.infoBarElement = W(this.config, i), t.insertBefore(this.infoBarElement, t.firstChild);
2554
+ this.infoBarElement = $(this.config, i), t.insertBefore(this.infoBarElement, t.firstChild);
2428
2555
  else {
2429
- const h = W(this.config, i);
2556
+ const h = $(this.config, i);
2430
2557
  this.infoBarElement.replaceWith(h), this.infoBarElement = h;
2431
2558
  }
2432
2559
  else this.config.position === "top" && this.infoBarElement && (this.infoBarElement.remove(), this.infoBarElement = null);
@@ -2435,7 +2562,7 @@ class An extends y {
2435
2562
  a,
2436
2563
  this.visibleColumns,
2437
2564
  this.rows
2438
- )), c && (this.infoBarElement = W(this.config, i), this.footerWrapper.appendChild(this.infoBarElement))) : this.cleanupFooter();
2565
+ )), c && (this.infoBarElement = $(this.config, i), this.footerWrapper.appendChild(this.infoBarElement))) : this.cleanupFooter();
2439
2566
  }
2440
2567
  // #endregion
2441
2568
  // #region Private Methods
@@ -2511,18 +2638,18 @@ class An extends y {
2511
2638
  }
2512
2639
  // #endregion
2513
2640
  // #region Styles
2514
- styles = It;
2641
+ styles = Lt;
2515
2642
  // #endregion
2516
2643
  }
2517
- const Lt = Oe;
2518
- function Tt(s) {
2644
+ const Tt = Oe;
2645
+ function Ft(s) {
2519
2646
  const e = [];
2520
2647
  return !s.rowGroupFields?.length && !s.columnGroupFields?.length && e.push("At least one row or column group field is required"), s.valueFields?.length || e.push("At least one value field is required"), e;
2521
2648
  }
2522
- function te(s, e) {
2649
+ function ne(s, e) {
2523
2650
  return [...s, e].join("|");
2524
2651
  }
2525
- function Ft(s, e) {
2652
+ function Pt(s, e) {
2526
2653
  const t = e.rowGroupFields ?? [], n = e.columnGroupFields ?? [], o = e.valueFields ?? [], i = Mt(s, n), r = qe(
2527
2654
  s,
2528
2655
  t,
@@ -2533,7 +2660,7 @@ function Ft(s, e) {
2533
2660
  // starting depth
2534
2661
  ""
2535
2662
  // parent key prefix
2536
- ), l = Pt(r, i, o), a = Object.values(l).reduce((d, c) => d + c, 0);
2663
+ ), l = Nt(r, i, o), a = Object.values(l).reduce((d, c) => d + c, 0);
2537
2664
  return {
2538
2665
  rows: r,
2539
2666
  columnKeys: i,
@@ -2550,7 +2677,7 @@ function Mt(s, e) {
2550
2677
  }
2551
2678
  return [...t].sort();
2552
2679
  }
2553
- function Nt(s, e) {
2680
+ function Kt(s, e) {
2554
2681
  const t = /* @__PURE__ */ new Map();
2555
2682
  for (const n of s) {
2556
2683
  const o = String(n[e] ?? ""), i = t.get(o);
@@ -2561,7 +2688,7 @@ function Nt(s, e) {
2561
2688
  function qe(s, e, t, n, o, i, r) {
2562
2689
  const l = [];
2563
2690
  if (e.length === 0) {
2564
- const h = Ee(s, t, n, o), g = ke(h);
2691
+ const h = ke(s, t, n, o), g = Ee(h);
2565
2692
  return l.push({
2566
2693
  rowKey: r || "all",
2567
2694
  rowLabel: r || "All",
@@ -2572,61 +2699,61 @@ function qe(s, e, t, n, o, i, r) {
2572
2699
  rowCount: s.length
2573
2700
  }), l;
2574
2701
  }
2575
- const a = e[0], d = e.slice(1), c = d.length > 0, u = Nt(s, a);
2702
+ const a = e[0], d = e.slice(1), c = d.length > 0, u = Kt(s, a);
2576
2703
  for (const [h, g] of u) {
2577
- const p = r ? `${r}|${h}` : h, m = Ee(g, t, n, o), f = ke(m);
2578
- let b;
2579
- c && (b = qe(
2704
+ const f = r ? `${r}|${h}` : h, m = ke(g, t, n, o), p = Ee(m);
2705
+ let R;
2706
+ c && (R = qe(
2580
2707
  g,
2581
2708
  d,
2582
2709
  t,
2583
2710
  n,
2584
2711
  o,
2585
2712
  i + 1,
2586
- p
2713
+ f
2587
2714
  )), l.push({
2588
- rowKey: p,
2715
+ rowKey: f,
2589
2716
  rowLabel: h || "(blank)",
2590
2717
  depth: i,
2591
2718
  values: m,
2592
- total: f,
2719
+ total: p,
2593
2720
  isGroup: c,
2594
- children: b,
2721
+ children: R,
2595
2722
  rowCount: g.length
2596
2723
  });
2597
2724
  }
2598
2725
  return l;
2599
2726
  }
2600
- function Ee(s, e, t, n) {
2727
+ function ke(s, e, t, n) {
2601
2728
  const o = {};
2602
2729
  for (const i of t)
2603
2730
  for (const r of n) {
2604
- const a = (e.length > 0 ? s.filter((h) => e.map((g) => String(h[g] ?? "")).join("|") === i) : s).map((h) => Number(h[r.field]) || 0), d = Lt(r.aggFunc), c = a.length > 0 ? d(a) : null, u = te([i], r.field);
2731
+ const a = (e.length > 0 ? s.filter((h) => e.map((g) => String(h[g] ?? "")).join("|") === i) : s).map((h) => Number(h[r.field]) || 0), d = Tt(r.aggFunc), c = a.length > 0 ? d(a) : null, u = ne([i], r.field);
2605
2732
  o[u] = c;
2606
2733
  }
2607
2734
  return o;
2608
2735
  }
2609
- function ke(s) {
2736
+ function Ee(s) {
2610
2737
  let e = 0;
2611
2738
  for (const t of Object.values(s))
2612
2739
  e += t ?? 0;
2613
2740
  return e;
2614
2741
  }
2615
- function Pt(s, e, t) {
2742
+ function Nt(s, e, t) {
2616
2743
  const n = {};
2617
2744
  function o(i) {
2618
2745
  for (const r of i)
2619
2746
  if (!r.isGroup || !r.children?.length)
2620
2747
  for (const l of e)
2621
2748
  for (const a of t) {
2622
- const d = te([l], a.field);
2749
+ const d = ne([l], a.field);
2623
2750
  n[d] = (n[d] ?? 0) + (r.values[d] ?? 0);
2624
2751
  }
2625
2752
  else r.children && o(r.children);
2626
2753
  }
2627
2754
  return o(s), n;
2628
2755
  }
2629
- function Kt(s, e, t = !0) {
2756
+ function qt(s, e, t = !0) {
2630
2757
  const n = [];
2631
2758
  function o(i) {
2632
2759
  n.push(i);
@@ -2639,7 +2766,7 @@ function Kt(s, e, t = !0) {
2639
2766
  o(i);
2640
2767
  return n;
2641
2768
  }
2642
- function $(s) {
2769
+ function j(s) {
2643
2770
  const e = [];
2644
2771
  function t(n) {
2645
2772
  if (n.isGroup && e.push(n.rowKey), n.children)
@@ -2650,14 +2777,14 @@ function $(s) {
2650
2777
  t(n);
2651
2778
  return e;
2652
2779
  }
2653
- const qt = ["sum", "avg", "count", "min", "max", "first", "last"];
2654
- function Dt(s, e, t, n) {
2780
+ const Dt = ["sum", "avg", "count", "min", "max", "first", "last"];
2781
+ function Ht(s, e, t, n) {
2655
2782
  const o = new AbortController(), i = { config: e, callbacks: n, signal: o.signal }, r = document.createElement("div");
2656
- return r.className = "tbw-pivot-panel", r.appendChild(T("Options", () => Vt(t, i))), r.appendChild(T("Row Groups", () => Ae("rowGroups", i))), r.appendChild(T("Column Groups", () => Ae("columnGroups", i))), r.appendChild(T("Values", () => Gt(i))), r.appendChild(T("Available Fields", () => Bt(i))), s.appendChild(r), () => {
2783
+ return r.className = "tbw-pivot-panel", r.appendChild(L("Options", () => zt(t, i))), r.appendChild(L("Row Groups", () => Ae("rowGroups", i))), r.appendChild(L("Column Groups", () => Ae("columnGroups", i))), r.appendChild(L("Values", () => Ot(i))), r.appendChild(L("Available Fields", () => Bt(i))), s.appendChild(r), () => {
2657
2784
  o.abort(), r.remove();
2658
2785
  };
2659
2786
  }
2660
- function T(s, e) {
2787
+ function L(s, e) {
2661
2788
  const t = document.createElement("div");
2662
2789
  t.className = "tbw-pivot-section";
2663
2790
  const n = document.createElement("div");
@@ -2674,7 +2801,7 @@ function Ae(s, e) {
2674
2801
  l.className = "tbw-pivot-placeholder", l.textContent = "Drag fields here or click to add", i.appendChild(l);
2675
2802
  } else
2676
2803
  for (const l of r)
2677
- i.appendChild(Ht(l, s, e));
2804
+ i.appendChild(Vt(l, s, e));
2678
2805
  return i.addEventListener(
2679
2806
  "dragover",
2680
2807
  (l) => {
@@ -2697,7 +2824,7 @@ function Ae(s, e) {
2697
2824
  { signal: o }
2698
2825
  ), i;
2699
2826
  }
2700
- function Ht(s, e, t) {
2827
+ function Vt(s, e, t) {
2701
2828
  const { callbacks: n, signal: o } = t, i = document.createElement("div");
2702
2829
  i.className = "tbw-pivot-field-chip", i.draggable = !0;
2703
2830
  const r = n.getAvailableFields().find((d) => d.field === s), l = document.createElement("span");
@@ -2723,7 +2850,7 @@ function Ht(s, e, t) {
2723
2850
  { signal: o }
2724
2851
  ), i;
2725
2852
  }
2726
- function Gt(s) {
2853
+ function Ot(s) {
2727
2854
  const { config: e, callbacks: t, signal: n } = s, o = document.createElement("div");
2728
2855
  o.className = "tbw-pivot-drop-zone tbw-pivot-values-zone", o.setAttribute("data-zone", "values");
2729
2856
  const i = e.valueFields ?? [];
@@ -2732,7 +2859,7 @@ function Gt(s) {
2732
2859
  r.className = "tbw-pivot-placeholder", r.textContent = "Drag numeric fields here for aggregation", o.appendChild(r);
2733
2860
  } else
2734
2861
  for (const r of i)
2735
- o.appendChild(Ot(r, s));
2862
+ o.appendChild(Gt(r, s));
2736
2863
  return o.addEventListener(
2737
2864
  "dragover",
2738
2865
  (r) => {
@@ -2755,7 +2882,7 @@ function Gt(s) {
2755
2882
  { signal: n }
2756
2883
  ), o;
2757
2884
  }
2758
- function Ot(s, e) {
2885
+ function Gt(s, e) {
2759
2886
  const { callbacks: t, signal: n } = e, o = document.createElement("div");
2760
2887
  o.className = "tbw-pivot-field-chip tbw-pivot-value-chip";
2761
2888
  const i = t.getAvailableFields().find((c) => c.field === s.field), r = document.createElement("div");
@@ -2764,7 +2891,7 @@ function Ot(s, e) {
2764
2891
  l.className = "tbw-pivot-chip-label", l.textContent = i?.header ?? s.field;
2765
2892
  const a = document.createElement("select");
2766
2893
  a.className = "tbw-pivot-agg-select", a.title = "Aggregation function";
2767
- for (const c of qt) {
2894
+ for (const c of Dt) {
2768
2895
  const u = document.createElement("option");
2769
2896
  u.value = c, u.textContent = c.toUpperCase(), u.selected = c === s.aggFunc, a.appendChild(u);
2770
2897
  }
@@ -2814,10 +2941,10 @@ function Bt(s) {
2814
2941
  }
2815
2942
  return o;
2816
2943
  }
2817
- function Vt(s, e) {
2944
+ function zt(s, e) {
2818
2945
  const { config: t, callbacks: n, signal: o } = e, i = document.createElement("div");
2819
2946
  return i.className = "tbw-pivot-options", i.appendChild(
2820
- j(
2947
+ U(
2821
2948
  "Enable Pivot View",
2822
2949
  s,
2823
2950
  (r) => {
@@ -2826,7 +2953,7 @@ function Vt(s, e) {
2826
2953
  o
2827
2954
  )
2828
2955
  ), i.appendChild(
2829
- j(
2956
+ U(
2830
2957
  "Show Row Totals",
2831
2958
  t.showTotals ?? !0,
2832
2959
  (r) => {
@@ -2835,7 +2962,7 @@ function Vt(s, e) {
2835
2962
  o
2836
2963
  )
2837
2964
  ), i.appendChild(
2838
- j(
2965
+ U(
2839
2966
  "Show Grand Total",
2840
2967
  t.showGrandTotal ?? !0,
2841
2968
  (r) => {
@@ -2845,7 +2972,7 @@ function Vt(s, e) {
2845
2972
  )
2846
2973
  ), i;
2847
2974
  }
2848
- function j(s, e, t, n) {
2975
+ function U(s, e, t, n) {
2849
2976
  const o = document.createElement("label");
2850
2977
  o.className = "tbw-pivot-checkbox";
2851
2978
  const i = document.createElement("input");
@@ -2853,8 +2980,8 @@ function j(s, e, t, n) {
2853
2980
  const r = document.createElement("span");
2854
2981
  return r.textContent = s, o.appendChild(i), o.appendChild(r), o;
2855
2982
  }
2856
- function zt(s, e, t) {
2857
- return e.className = "pivot-group-row", e.setAttribute("data-pivot-depth", String(s.__pivotDepth ?? 0)), e.setAttribute("role", "row"), e.innerHTML = "", t.columns.forEach((n, o) => {
2983
+ function Wt(s, e, t) {
2984
+ return e.className = "pivot-group-row", e.setAttribute("data-pivot-depth", String(s.__pivotDepth ?? 0)), e.setAttribute("data-pivot-key", String(s.__pivotRowKey ?? "")), e.setAttribute("role", "row"), e.innerHTML = "", t.columns.forEach((n, o) => {
2858
2985
  const i = document.createElement("div");
2859
2986
  if (i.className = "cell", i.setAttribute("data-col", String(o)), i.setAttribute("role", "gridcell"), o === 0) {
2860
2987
  const r = Number(s.__pivotIndent) || 0;
@@ -2874,8 +3001,8 @@ function zt(s, e, t) {
2874
3001
  e.appendChild(i);
2875
3002
  }), !0;
2876
3003
  }
2877
- function Wt(s, e, t) {
2878
- return e.className = "pivot-leaf-row", e.setAttribute("data-pivot-depth", String(s.__pivotDepth ?? 0)), e.innerHTML = "", t.forEach((n, o) => {
3004
+ function $t(s, e, t) {
3005
+ return e.className = "pivot-leaf-row", e.setAttribute("data-pivot-depth", String(s.__pivotDepth ?? 0)), e.setAttribute("data-pivot-key", String(s.__pivotRowKey ?? "")), e.innerHTML = "", t.forEach((n, o) => {
2879
3006
  const i = document.createElement("div");
2880
3007
  if (i.className = "cell", i.setAttribute("data-col", String(o)), i.setAttribute("role", "gridcell"), o === 0) {
2881
3008
  const r = Number(s.__pivotIndent) || 0;
@@ -2889,7 +3016,7 @@ function Wt(s, e, t) {
2889
3016
  e.appendChild(i);
2890
3017
  }), !0;
2891
3018
  }
2892
- function $t(s, e, t) {
3019
+ function jt(s, e, t) {
2893
3020
  return e.className = "pivot-grand-total-row", e.setAttribute("role", "presentation"), e.innerHTML = "", t.forEach((n, o) => {
2894
3021
  const i = document.createElement("div");
2895
3022
  if (i.className = "cell", i.setAttribute("data-col", String(o)), o === 0) {
@@ -2902,8 +3029,8 @@ function $t(s, e, t) {
2902
3029
  e.appendChild(i);
2903
3030
  }), !0;
2904
3031
  }
2905
- const jt = '.pivot-group-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:600;background:var(--tbw-pivot-group-bg, var(--tbw-color-row-alt));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-group-row:hover{background:var(--tbw-pivot-group-hover, var(--tbw-color-row-hover))}.pivot-leaf-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-pivot-leaf-bg, var(--tbw-color-bg));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-grand-total-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:700;background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-height:var(--tbw-row-height);border-top:2px solid var(--tbw-color-border-strong)}.pivot-grand-total-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-grand-total-row>.cell:last-child{border-right:0}.pivot-grand-total-footer{position:sticky;bottom:0;z-index:var(--tbw-z-layer-pinned-rows, 20);background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-width:fit-content}.pivot-group-row>.cell,.pivot-leaf-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-group-row>.cell:last-child,.pivot-leaf-row>.cell:last-child{border-right:0}.pivot-toggle{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-right:6px;border:none;background:transparent;cursor:pointer;font-size:10px;color:var(--tbw-pivot-toggle-color, var(--tbw-color-fg-muted));border-radius:var(--tbw-border-radius);transition:background .15s,color .15s}.pivot-toggle:hover{background:var(--tbw-pivot-toggle-hover-bg, var(--tbw-color-row-hover));color:var(--tbw-pivot-toggle-hover-color, var(--tbw-color-fg))}.pivot-toggle:focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}.pivot-label{font-weight:inherit}.pivot-count{color:var(--tbw-pivot-count-color, var(--tbw-color-fg-muted));font-size:.9em;font-weight:400}.pivot-total-row{font-weight:700;border-top:2px solid var(--tbw-pivot-border, var(--tbw-color-border-strong))}[data-pivot-depth="1"]{--tbw-pivot-depth: 1}[data-pivot-depth="2"]{--tbw-pivot-depth: 2}[data-pivot-depth="3"]{--tbw-pivot-depth: 3}[data-pivot-depth="4"]{--tbw-pivot-depth: 4}.tbw-pivot-panel{display:flex;flex-direction:column;gap:12px;padding:12px;height:100%;overflow-y:auto;font-size:13px}.tbw-pivot-section{border:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-section-bg, var(--tbw-color-bg))}.tbw-pivot-section-header{padding:8px 12px;font-weight:600;background:var(--tbw-pivot-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius) var(--tbw-border-radius) 0 0}.tbw-pivot-section-content{padding:8px}.tbw-pivot-toggle-wrapper{display:flex;align-items:center}.tbw-pivot-toggle-label{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-toggle-label input{width:16px;height:16px;cursor:pointer}.tbw-pivot-drop-zone{min-height:60px;padding:8px;border:2px dashed var(--tbw-pivot-drop-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-drop-bg, var(--tbw-color-row-alt));display:flex;flex-wrap:wrap;gap:6px;align-content:flex-start;transition:all .15s ease}.tbw-pivot-drop-zone.drag-over{border-color:var(--tbw-color-accent);background:var(--tbw-pivot-drop-active, var(--tbw-focus-background))}.tbw-pivot-placeholder{color:var(--tbw-color-fg-muted);font-style:italic;padding:8px;text-align:center;width:100%}.tbw-pivot-field-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;background:var(--tbw-pivot-chip-bg, var(--tbw-color-header-bg));border:1px solid var(--tbw-pivot-chip-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);cursor:grab;font-size:12px;transition:all .15s ease}.tbw-pivot-field-chip:hover{background:var(--tbw-pivot-chip-hover, var(--tbw-color-row-hover));border-color:var(--tbw-color-accent)}.tbw-pivot-field-chip.available{background:var(--tbw-color-bg)}.tbw-pivot-field-chip.dragging{opacity:.5;cursor:grabbing}.tbw-pivot-chip-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.tbw-pivot-chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--tbw-color-fg-muted);font-size:14px;font-weight:700;cursor:pointer;border-radius:50%;transition:all .15s ease}.tbw-pivot-chip-remove:hover{background:var(--tbw-pivot-chip-remove-hover-bg, var(--tbw-color-accent));color:var(--tbw-pivot-chip-remove-hover-fg, var(--tbw-color-accent-fg))}.tbw-pivot-value-chip{padding:4px 8px}.tbw-pivot-value-label-wrapper{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.tbw-pivot-agg-select{padding:2px 4px;font-size:11px;border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);cursor:pointer}.tbw-pivot-available-fields{display:flex;flex-wrap:wrap;gap:6px;min-height:40px}.tbw-pivot-options{display:flex;flex-direction:column;gap:8px}.tbw-pivot-checkbox{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-checkbox input{width:14px;height:14px;cursor:pointer}';
2906
- class F extends y {
3032
+ const Ut = '.pivot-group-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:600;background:var(--tbw-pivot-group-bg, var(--tbw-color-row-alt));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-group-row:hover{background:var(--tbw-pivot-group-hover, var(--tbw-color-row-hover))}.pivot-leaf-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-pivot-leaf-bg, var(--tbw-color-bg));min-height:var(--tbw-row-height);border-bottom:var(--tbw-row-divider)}.pivot-grand-total-row{display:grid;grid-template-columns:var(--tbw-column-template);font-weight:700;background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-height:var(--tbw-row-height);border-top:2px solid var(--tbw-color-border-strong)}.pivot-grand-total-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-grand-total-row>.cell:last-child{border-right:0}.pivot-grand-total-footer{position:sticky;bottom:0;z-index:var(--tbw-z-layer-pinned-rows, 20);background:var(--tbw-pivot-grand-total-bg, var(--tbw-color-header-bg));min-width:fit-content}.pivot-group-row>.cell,.pivot-leaf-row>.cell{display:flex;align-items:center;padding:var(--tbw-cell-padding);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}.pivot-group-row>.cell:last-child,.pivot-leaf-row>.cell:last-child{border-right:0}.pivot-toggle{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;margin-right:6px;border:none;background:transparent;cursor:pointer;color:var(--tbw-pivot-toggle-color, var(--tbw-color-fg-muted));border-radius:var(--tbw-border-radius);transition:background .15s,color .15s}.pivot-toggle:hover{background:var(--tbw-pivot-toggle-hover-bg, var(--tbw-color-row-hover));color:var(--tbw-pivot-toggle-hover-color, var(--tbw-color-fg))}.pivot-toggle:focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}.pivot-label{font-weight:inherit}.pivot-count{color:var(--tbw-pivot-count-color, var(--tbw-color-fg-muted));font-size:.9em;font-weight:400}.pivot-total-row{font-weight:700;border-top:2px solid var(--tbw-pivot-border, var(--tbw-color-border-strong))}[data-pivot-depth="1"]{--tbw-pivot-depth: 1}[data-pivot-depth="2"]{--tbw-pivot-depth: 2}[data-pivot-depth="3"]{--tbw-pivot-depth: 3}[data-pivot-depth="4"]{--tbw-pivot-depth: 4}.tbw-pivot-panel{display:flex;flex-direction:column;gap:12px;padding:12px;height:100%;overflow-y:auto;font-size:13px}.tbw-pivot-section{border:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-section-bg, var(--tbw-color-bg))}.tbw-pivot-section-header{padding:8px 12px;font-weight:600;background:var(--tbw-pivot-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-pivot-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius) var(--tbw-border-radius) 0 0}.tbw-pivot-section-content{padding:8px}.tbw-pivot-toggle-wrapper{display:flex;align-items:center}.tbw-pivot-toggle-label{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-toggle-label input{width:16px;height:16px;cursor:pointer}.tbw-pivot-drop-zone{min-height:60px;padding:8px;border:2px dashed var(--tbw-pivot-drop-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);background:var(--tbw-pivot-drop-bg, var(--tbw-color-row-alt));display:flex;flex-wrap:wrap;gap:6px;align-content:flex-start;transition:all .15s ease}.tbw-pivot-drop-zone.drag-over{border-color:var(--tbw-color-accent);background:var(--tbw-pivot-drop-active, var(--tbw-focus-background))}.tbw-pivot-placeholder{color:var(--tbw-color-fg-muted);font-style:italic;padding:8px;text-align:center;width:100%}.tbw-pivot-field-chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;background:var(--tbw-pivot-chip-bg, var(--tbw-color-header-bg));border:1px solid var(--tbw-pivot-chip-border, var(--tbw-color-border));border-radius:var(--tbw-border-radius);cursor:grab;font-size:12px;transition:all .15s ease}.tbw-pivot-field-chip:hover{background:var(--tbw-pivot-chip-hover, var(--tbw-color-row-hover));border-color:var(--tbw-color-accent)}.tbw-pivot-field-chip.available{background:var(--tbw-color-bg)}.tbw-pivot-field-chip.dragging{opacity:.5;cursor:grabbing}.tbw-pivot-chip-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:120px}.tbw-pivot-chip-remove{display:flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;background:transparent;color:var(--tbw-color-fg-muted);font-size:14px;font-weight:700;cursor:pointer;border-radius:50%;transition:all .15s ease}.tbw-pivot-chip-remove:hover{background:var(--tbw-pivot-chip-remove-hover-bg, var(--tbw-color-accent));color:var(--tbw-pivot-chip-remove-hover-fg, var(--tbw-color-accent-fg))}.tbw-pivot-value-chip{padding:4px 8px}.tbw-pivot-value-label-wrapper{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.tbw-pivot-agg-select{padding:2px 4px;font-size:11px;border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);cursor:pointer}.tbw-pivot-available-fields{display:flex;flex-wrap:wrap;gap:6px;min-height:40px}.tbw-pivot-options{display:flex;flex-direction:column;gap:8px}.tbw-pivot-checkbox{display:flex;align-items:center;gap:8px;cursor:pointer}.tbw-pivot-checkbox input{width:14px;height:14px;cursor:pointer}.pivot-group-row.tbw-pivot-slide-in,.pivot-leaf-row.tbw-pivot-slide-in{animation:tbw-pivot-slide-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-pivot-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}.pivot-group-row.tbw-pivot-fade-in,.pivot-leaf-row.tbw-pivot-fade-in{animation:tbw-pivot-fade-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-pivot-fade-in{0%{opacity:0}to{opacity:1}}';
3033
+ class T extends v {
2907
3034
  name = "pivot";
2908
3035
  version = "1.0.0";
2909
3036
  /** Tool panel ID for shell integration */
@@ -2913,7 +3040,8 @@ class F extends y {
2913
3040
  active: !0,
2914
3041
  showTotals: !0,
2915
3042
  showGrandTotal: !0,
2916
- showToolPanel: !0
3043
+ showToolPanel: !0,
3044
+ animation: "slide"
2917
3045
  };
2918
3046
  }
2919
3047
  // #region Internal State
@@ -2926,23 +3054,38 @@ class F extends y {
2926
3054
  originalColumns = [];
2927
3055
  panelContainer = null;
2928
3056
  grandTotalFooter = null;
3057
+ previousVisibleKeys = /* @__PURE__ */ new Set();
3058
+ keysToAnimate = /* @__PURE__ */ new Set();
2929
3059
  /**
2930
3060
  * Check if the plugin has valid pivot configuration (at least value fields).
2931
3061
  */
2932
3062
  hasValidPivotConfig() {
2933
3063
  return (this.config.valueFields?.length ?? 0) > 0;
2934
3064
  }
3065
+ /**
3066
+ * Get animation style respecting grid-level animation mode.
3067
+ */
3068
+ get animationStyle() {
3069
+ const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
3070
+ if (t === !1 || t === "off") return !1;
3071
+ if (t !== !0 && t !== "on") {
3072
+ const n = this.shadowRoot?.host;
3073
+ if (n && getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() === "0")
3074
+ return !1;
3075
+ }
3076
+ return this.config.animation ?? "slide";
3077
+ }
2935
3078
  // #endregion
2936
3079
  // #region Lifecycle
2937
3080
  detach() {
2938
- this.isActive = !1, this.hasInitialized = !1, this.pivotResult = null, this.fieldHeaderMap.clear(), this.originalColumns = [], this.panelContainer = null, this.cleanupGrandTotalFooter();
3081
+ this.isActive = !1, this.hasInitialized = !1, this.pivotResult = null, this.fieldHeaderMap.clear(), this.originalColumns = [], this.panelContainer = null, this.cleanupGrandTotalFooter(), this.previousVisibleKeys.clear(), this.keysToAnimate.clear();
2939
3082
  }
2940
3083
  // #endregion
2941
3084
  // #region Shell Integration
2942
3085
  getToolPanel() {
2943
3086
  if ((this.config?.showToolPanel ?? this.userConfig?.showToolPanel ?? !0) !== !1)
2944
3087
  return {
2945
- id: F.PANEL_ID,
3088
+ id: T.PANEL_ID,
2946
3089
  title: "Pivot",
2947
3090
  icon: "⊞",
2948
3091
  tooltip: "Configure pivot table",
@@ -2955,36 +3098,42 @@ class F extends y {
2955
3098
  processRows(e) {
2956
3099
  if (!this.hasInitialized && this.config.active !== !1 && this.hasValidPivotConfig() && (this.hasInitialized = !0, this.isActive = !0), !this.isActive)
2957
3100
  return [...e];
2958
- const t = Tt(this.config);
3101
+ const t = Ft(this.config);
2959
3102
  if (t.length > 0)
2960
3103
  return this.warn(`Config errors: ${t.join(", ")}`), [...e];
2961
3104
  if (this.buildFieldHeaderMap(), this.defaultExpanded = this.config.defaultExpanded ?? !0, this.expandedKeys.size === 0 && this.defaultExpanded && this.pivotResult) {
2962
- const i = $(this.pivotResult.rows);
2963
- for (const r of i)
2964
- this.expandedKeys.add(r);
3105
+ const r = j(this.pivotResult.rows);
3106
+ for (const l of r)
3107
+ this.expandedKeys.add(l);
2965
3108
  }
2966
- if (this.pivotResult = Ft(e, this.config), this.expandedKeys.size === 0 && this.defaultExpanded) {
2967
- const i = $(this.pivotResult.rows);
2968
- for (const r of i)
2969
- this.expandedKeys.add(r);
3109
+ if (this.pivotResult = Pt(e, this.config), this.expandedKeys.size === 0 && this.defaultExpanded) {
3110
+ const r = j(this.pivotResult.rows);
3111
+ for (const l of r)
3112
+ this.expandedKeys.add(l);
2970
3113
  }
2971
- const n = this.config.indentWidth ?? 20;
2972
- return Kt(
3114
+ const n = this.config.indentWidth ?? 20, o = qt(
2973
3115
  this.pivotResult.rows,
2974
3116
  this.expandedKeys,
2975
3117
  this.defaultExpanded
2976
- ).map((i) => ({
2977
- __pivotRowKey: i.rowKey,
2978
- __pivotLabel: i.rowLabel,
2979
- __pivotDepth: i.depth,
2980
- __pivotIsGroup: i.isGroup,
2981
- __pivotHasChildren: !!i.children?.length,
2982
- __pivotExpanded: this.expandedKeys.has(i.rowKey),
2983
- __pivotRowCount: i.rowCount ?? 0,
2984
- __pivotIndent: i.depth * n,
2985
- __pivotTotal: i.total,
2986
- ...i.values
3118
+ ).map((r) => ({
3119
+ __pivotRowKey: r.rowKey,
3120
+ __pivotLabel: r.rowLabel,
3121
+ __pivotDepth: r.depth,
3122
+ __pivotIsGroup: r.isGroup,
3123
+ __pivotHasChildren: !!r.children?.length,
3124
+ __pivotExpanded: this.expandedKeys.has(r.rowKey),
3125
+ __pivotRowCount: r.rowCount ?? 0,
3126
+ __pivotIndent: r.depth * n,
3127
+ __pivotTotal: r.total,
3128
+ ...r.values
2987
3129
  }));
3130
+ this.keysToAnimate.clear();
3131
+ const i = /* @__PURE__ */ new Set();
3132
+ for (const r of o) {
3133
+ const l = r.__pivotRowKey;
3134
+ i.add(l), !this.previousVisibleKeys.has(l) && r.__pivotDepth > 0 && this.keysToAnimate.add(l);
3135
+ }
3136
+ return this.previousVisibleKeys = i, o;
2988
3137
  }
2989
3138
  processColumns(e) {
2990
3139
  if (!this.isActive || !this.pivotResult)
@@ -2997,7 +3146,7 @@ class F extends y {
2997
3146
  });
2998
3147
  for (const o of this.pivotResult.columnKeys)
2999
3148
  for (const i of this.config.valueFields ?? []) {
3000
- const r = te([o], i.field), l = i.header || this.fieldHeaderMap.get(i.field) || i.field;
3149
+ const r = ne([o], i.field), l = i.header || this.fieldHeaderMap.get(i.field) || i.field;
3001
3150
  t.push({
3002
3151
  field: r,
3003
3152
  header: `${o} - ${l} (${i.aggFunc})`,
@@ -3014,12 +3163,12 @@ class F extends y {
3014
3163
  }
3015
3164
  renderRow(e, t) {
3016
3165
  const n = e;
3017
- return n.__pivotRowKey && n.__pivotHasChildren ? zt(n, t, {
3166
+ return n.__pivotRowKey && n.__pivotHasChildren ? Wt(n, t, {
3018
3167
  columns: this.gridColumns,
3019
3168
  onToggle: (o) => this.toggle(o),
3020
3169
  resolveIcon: (o) => this.resolveIcon(o),
3021
3170
  setIcon: (o, i) => this.setIcon(o, i)
3022
- }) : n.__pivotRowKey !== void 0 && this.isActive ? Wt(n, t, this.gridColumns) : (this.cleanupPivotStyling(t), !1);
3171
+ }) : n.__pivotRowKey !== void 0 && this.isActive ? $t(n, t, this.gridColumns) : (this.cleanupPivotStyling(t), !1);
3023
3172
  }
3024
3173
  /**
3025
3174
  * Remove pivot-specific classes, attributes, and inline styles from a row element.
@@ -3031,6 +3180,16 @@ class F extends y {
3031
3180
  }
3032
3181
  afterRender() {
3033
3182
  this.isActive && this.config.showGrandTotal && this.pivotResult ? this.renderGrandTotalFooter() : this.cleanupGrandTotalFooter();
3183
+ const e = this.animationStyle;
3184
+ if (e === !1 || this.keysToAnimate.size === 0) return;
3185
+ const t = this.shadowRoot?.querySelector(".rows");
3186
+ if (!t) return;
3187
+ const n = e === "fade" ? "tbw-pivot-fade-in" : "tbw-pivot-slide-in";
3188
+ for (const o of t.querySelectorAll(".pivot-group-row, .pivot-leaf-row")) {
3189
+ const i = o.dataset.pivotKey;
3190
+ i && this.keysToAnimate.has(i) && (o.classList.add(n), o.addEventListener("animationend", () => o.classList.remove(n), { once: !0 }));
3191
+ }
3192
+ this.keysToAnimate.clear();
3034
3193
  }
3035
3194
  /**
3036
3195
  * Render the grand total row as a sticky footer pinned to the bottom.
@@ -3049,7 +3208,7 @@ class F extends y {
3049
3208
  __pivotTotal: this.pivotResult.grandTotal,
3050
3209
  ...this.pivotResult.totals
3051
3210
  };
3052
- $t(n, this.grandTotalFooter, this.gridColumns);
3211
+ jt(n, this.grandTotalFooter, this.gridColumns);
3053
3212
  }
3054
3213
  /**
3055
3214
  * Remove the grand total footer element.
@@ -3070,7 +3229,7 @@ class F extends y {
3070
3229
  }
3071
3230
  expandAll() {
3072
3231
  if (this.pivotResult) {
3073
- const e = $(this.pivotResult.rows);
3232
+ const e = j(this.pivotResult.rows);
3074
3233
  for (const t of e)
3075
3234
  this.expandedKeys.add(t);
3076
3235
  this.requestRender();
@@ -3111,16 +3270,16 @@ class F extends y {
3111
3270
  // #endregion
3112
3271
  // #region Tool Panel API
3113
3272
  showPanel() {
3114
- this.grid.openToolPanel(F.PANEL_ID);
3273
+ this.grid.openToolPanel(T.PANEL_ID);
3115
3274
  }
3116
3275
  hidePanel() {
3117
3276
  this.grid.closeToolPanel();
3118
3277
  }
3119
3278
  togglePanel() {
3120
- this.grid.toggleToolPanel(F.PANEL_ID);
3279
+ this.grid.toggleToolPanel(T.PANEL_ID);
3121
3280
  }
3122
3281
  isPanelVisible() {
3123
- return this.grid.activeToolPanel === F.PANEL_ID;
3282
+ return this.grid.activeToolPanel === T.PANEL_ID;
3124
3283
  }
3125
3284
  // #endregion
3126
3285
  // #region Private Helpers
@@ -3164,7 +3323,7 @@ class F extends y {
3164
3323
  },
3165
3324
  getAvailableFields: () => this.getAvailableFields()
3166
3325
  };
3167
- return Dt(e, this.config, this.isActive, t);
3326
+ return Ht(e, this.config, this.isActive, t);
3168
3327
  }
3169
3328
  refreshPanel() {
3170
3329
  this.panelContainer && (this.panelContainer.innerHTML = "", this.renderPanel(this.panelContainer));
@@ -3198,27 +3357,59 @@ class F extends y {
3198
3357
  }
3199
3358
  // #endregion
3200
3359
  // #region Styles
3201
- styles = jt;
3360
+ styles = Ut;
3202
3361
  // #endregion
3203
3362
  }
3204
- function Ut(s) {
3363
+ function _e(s) {
3205
3364
  const e = s.meta ?? {};
3206
3365
  return e.lockPosition !== !0 && e.suppressMovable !== !0;
3207
3366
  }
3208
- function _e(s, e, t) {
3367
+ function Ie(s, e, t) {
3209
3368
  if (e === t || e < 0 || e >= s.length || t < 0 || t > s.length) return s;
3210
3369
  const n = [...s], [o] = n.splice(e, 1);
3211
3370
  return n.splice(t, 0, o), n;
3212
3371
  }
3213
- const Yt = '.header-row>.cell[draggable=true]{cursor:grab;position:relative}.header-row>.cell.dragging{opacity:.5;cursor:grabbing}.header-row>.cell.drop-before:before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--tbw-reorder-indicator, var(--tbw-color-accent));z-index:1}.header-row>.cell.drop-after:after{content:"";position:absolute;right:0;top:0;bottom:0;width:2px;background:var(--tbw-reorder-indicator, var(--tbw-color-accent));z-index:1}';
3214
- class _n extends y {
3372
+ const Yt = '.header-row>.cell[draggable=true]{cursor:grab;position:relative}.header-row>.cell.dragging{opacity:.5;cursor:grabbing}.header-row>.cell.drop-before:before{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--tbw-reorder-indicator, var(--tbw-color-accent));z-index:1}.header-row>.cell.drop-after:after{content:"";position:absolute;right:0;top:0;bottom:0;width:2px;background:var(--tbw-reorder-indicator, var(--tbw-color-accent));z-index:1}.cell.flip-animating{transition:transform var(--tbw-animation-duration, .2s) ease-out;will-change:transform;z-index:1}@keyframes reorder-fade-in{0%{opacity:0}to{opacity:1}}.cell.fade-animating{animation:reorder-fade-in var(--tbw-animation-duration, .2s) ease-out backwards}';
3373
+ class _n extends v {
3215
3374
  name = "reorder";
3216
3375
  version = "1.0.0";
3217
3376
  get defaultConfig() {
3218
3377
  return {
3219
- viewTransition: !0
3378
+ animation: "flip"
3379
+ // Plugin's own default
3220
3380
  };
3221
3381
  }
3382
+ /**
3383
+ * Resolve animation type from plugin config.
3384
+ * Respects grid-level animation.mode (disabled = no animation).
3385
+ */
3386
+ get animationType() {
3387
+ return this.isAnimationEnabled ? this.config.animation !== void 0 ? this.config.animation : this.config.viewTransition === !1 ? !1 : (this.config.viewTransition === !0, "flip") : !1;
3388
+ }
3389
+ /**
3390
+ * Check if animations are enabled at the grid level.
3391
+ * Respects gridConfig.animation.mode and CSS variable.
3392
+ */
3393
+ get isAnimationEnabled() {
3394
+ const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
3395
+ if (t === !1 || t === "off") return !1;
3396
+ if (t === !0 || t === "on") return !0;
3397
+ const n = this.shadowRoot?.host;
3398
+ return n ? getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
3399
+ }
3400
+ /**
3401
+ * Get animation duration from CSS variable (set by grid config).
3402
+ */
3403
+ get animationDuration() {
3404
+ if (this.config.animationDuration !== void 0)
3405
+ return this.config.animationDuration;
3406
+ const e = this.shadowRoot?.host;
3407
+ if (e) {
3408
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(t, 10);
3409
+ if (!isNaN(n)) return n;
3410
+ }
3411
+ return 200;
3412
+ }
3222
3413
  // #region Internal State
3223
3414
  isDragging = !1;
3224
3415
  draggedField = null;
@@ -3248,10 +3439,10 @@ class _n extends y {
3248
3439
  const o = n, i = o.getAttribute("data-field");
3249
3440
  if (!i) return;
3250
3441
  const r = this.columns.find((c) => c.field === i), d = !this.grid.queryPlugins({
3251
- type: Ke.CAN_MOVE_COLUMN,
3442
+ type: N.CAN_MOVE_COLUMN,
3252
3443
  context: r
3253
3444
  }).includes(!1);
3254
- if (!r || !Ut(r) || !d) {
3445
+ if (!r || !_e(r) || !d) {
3255
3446
  o.draggable = !1;
3256
3447
  return;
3257
3448
  }
@@ -3264,8 +3455,8 @@ class _n extends y {
3264
3455
  });
3265
3456
  }), o.addEventListener("dragover", (c) => {
3266
3457
  if (c.preventDefault(), !this.isDragging || this.draggedField === i) return;
3267
- const u = o.getBoundingClientRect(), h = u.left + u.width / 2, p = this.getColumnOrder().indexOf(i);
3268
- this.dropIndex = c.clientX < h ? p : p + 1, o.classList.add("drop-target"), o.classList.toggle("drop-before", c.clientX < h), o.classList.toggle("drop-after", c.clientX >= h);
3458
+ const u = o.getBoundingClientRect(), h = u.left + u.width / 2, f = this.getColumnOrder().indexOf(i);
3459
+ this.dropIndex = c.clientX < h ? f : f + 1, o.classList.add("drop-target"), o.classList.toggle("drop-before", c.clientX < h), o.classList.toggle("drop-after", c.clientX >= h);
3269
3460
  }), o.addEventListener("dragleave", () => {
3270
3461
  o.classList.remove("drop-target", "drop-before", "drop-after");
3271
3462
  }), o.addEventListener("drop", (c) => {
@@ -3273,16 +3464,42 @@ class _n extends y {
3273
3464
  const u = this.draggedField, h = this.draggedIndex, g = this.dropIndex;
3274
3465
  if (!this.isDragging || u === null || h === null || g === null)
3275
3466
  return;
3276
- const p = g > h ? g - 1 : g, m = this.getColumnOrder(), f = _e(m, h, p), b = {
3467
+ const f = g > h ? g - 1 : g, m = this.getColumnOrder(), p = Ie(m, h, f), R = {
3277
3468
  field: u,
3278
3469
  fromIndex: h,
3279
- toIndex: p,
3280
- columnOrder: f
3470
+ toIndex: f,
3471
+ columnOrder: p
3281
3472
  };
3282
- this.updateColumnOrder(f), this.emit("column-move", b);
3473
+ this.updateColumnOrder(p), this.emit("column-move", R);
3283
3474
  }));
3284
3475
  });
3285
3476
  }
3477
+ /**
3478
+ * Handle Alt+Arrow keyboard shortcuts for column reordering.
3479
+ */
3480
+ onKeyDown(e) {
3481
+ if (!e.altKey || e.key !== "ArrowLeft" && e.key !== "ArrowRight")
3482
+ return;
3483
+ const t = this.grid, n = t._focusCol, o = t._visibleColumns;
3484
+ if (n < 0 || n >= o.length) return;
3485
+ const i = o[n];
3486
+ if (!i || !_e(i)) return;
3487
+ const r = this.grid;
3488
+ if (r.queryPlugins({
3489
+ type: N.CAN_MOVE_COLUMN,
3490
+ context: i
3491
+ }).includes(!1)) return;
3492
+ const a = this.getColumnOrder(), d = a.indexOf(i.field);
3493
+ if (d === -1) return;
3494
+ const c = e.key === "ArrowLeft" ? d - 1 : d + 1;
3495
+ if (c < 0 || c >= a.length) return;
3496
+ const u = o.find((h) => h.field === a[c]);
3497
+ if (!(u && r.queryPlugins({
3498
+ type: N.CAN_MOVE_COLUMN,
3499
+ context: u
3500
+ }).includes(!1)))
3501
+ return this.moveColumn(i.field, c), t._focusCol = c, Ge(this.grid), e.preventDefault(), e.stopPropagation(), !0;
3502
+ }
3286
3503
  // #endregion
3287
3504
  // #region Public API
3288
3505
  /**
@@ -3300,7 +3517,7 @@ class _n extends y {
3300
3517
  moveColumn(e, t) {
3301
3518
  const n = this.getColumnOrder(), o = n.indexOf(e);
3302
3519
  if (o === -1) return;
3303
- const i = _e(n, o, t);
3520
+ const i = Ie(n, o, t);
3304
3521
  this.updateColumnOrder(i), this.emit("column-move", {
3305
3522
  field: e,
3306
3523
  fromIndex: o,
@@ -3325,23 +3542,95 @@ class _n extends y {
3325
3542
  // #endregion
3326
3543
  // #region View Transition
3327
3544
  /**
3328
- * Update column order with optional view transition animation.
3329
- * Falls back to instant update if View Transitions API is not supported.
3330
- */
3331
- updateColumnOrder(e) {
3332
- const t = this.grid, n = this.shadowRoot;
3333
- if (this.config.viewTransition && "startViewTransition" in document && n) {
3334
- const o = n.querySelectorAll(".cell[data-field]");
3545
+ * Capture header cell positions before reorder.
3546
+ */
3547
+ captureHeaderPositions() {
3548
+ const e = /* @__PURE__ */ new Map();
3549
+ return this.shadowRoot?.querySelectorAll(".header-row > .cell[data-field]").forEach((t) => {
3550
+ const n = t.getAttribute("data-field");
3551
+ n && e.set(n, t.getBoundingClientRect().left);
3552
+ }), e;
3553
+ }
3554
+ /**
3555
+ * Apply FLIP animation for column reorder.
3556
+ * Uses CSS transitions - JS sets initial transform and toggles class.
3557
+ * @param oldPositions - Header positions captured before DOM change
3558
+ */
3559
+ animateFLIP(e) {
3560
+ const t = this.shadowRoot;
3561
+ if (!t || e.size === 0) return;
3562
+ const n = /* @__PURE__ */ new Map();
3563
+ if (t.querySelectorAll(".header-row > .cell[data-field]").forEach((r) => {
3564
+ const l = r.getAttribute("data-field");
3565
+ if (!l) return;
3566
+ const a = e.get(l);
3567
+ if (a === void 0) return;
3568
+ const d = a - r.getBoundingClientRect().left;
3569
+ Math.abs(d) > 1 && n.set(l, d);
3570
+ }), n.size === 0) return;
3571
+ const o = [];
3572
+ if (t.querySelectorAll(".cell[data-field]").forEach((r) => {
3573
+ const l = n.get(r.getAttribute("data-field") ?? "");
3574
+ if (l !== void 0) {
3575
+ const a = r;
3576
+ a.style.transform = `translateX(${l}px)`, o.push(a);
3577
+ }
3578
+ }), o.length === 0) return;
3579
+ t.host.offsetHeight;
3580
+ const i = this.animationDuration;
3581
+ requestAnimationFrame(() => {
3335
3582
  o.forEach((r) => {
3336
- const l = r.getAttribute("data-field");
3337
- l && (r.style.viewTransitionName = `col-${l}`);
3338
- }), document.startViewTransition(() => t.setColumnOrder(e)).finished.finally(() => {
3583
+ r.classList.add("flip-animating"), r.style.transform = "";
3584
+ }), setTimeout(() => {
3339
3585
  o.forEach((r) => {
3340
- r.style.viewTransitionName = "";
3586
+ r.style.transform = "", r.classList.remove("flip-animating");
3341
3587
  });
3342
- });
3343
- } else
3344
- t.setColumnOrder(e);
3588
+ }, i + 50);
3589
+ });
3590
+ }
3591
+ /**
3592
+ * Apply crossfade animation for moved columns.
3593
+ * Uses CSS keyframes - JS just toggles classes.
3594
+ */
3595
+ animateFade(e) {
3596
+ const t = this.shadowRoot;
3597
+ if (!t) {
3598
+ e();
3599
+ return;
3600
+ }
3601
+ const n = this.captureHeaderPositions();
3602
+ e();
3603
+ const o = /* @__PURE__ */ new Set();
3604
+ if (t.querySelectorAll(".header-row > .cell[data-field]").forEach((l) => {
3605
+ const a = l.getAttribute("data-field");
3606
+ if (!a) return;
3607
+ const d = n.get(a);
3608
+ if (d === void 0) return;
3609
+ const c = l.getBoundingClientRect().left;
3610
+ Math.abs(d - c) > 1 && o.add(a);
3611
+ }), o.size === 0) return;
3612
+ const i = [];
3613
+ if (t.querySelectorAll(".cell[data-field]").forEach((l) => {
3614
+ const a = l.getAttribute("data-field");
3615
+ if (a && o.has(a)) {
3616
+ const d = l;
3617
+ d.classList.add("fade-animating"), i.push(d);
3618
+ }
3619
+ }), i.length === 0) return;
3620
+ const r = this.animationDuration;
3621
+ setTimeout(() => {
3622
+ i.forEach((l) => l.classList.remove("fade-animating"));
3623
+ }, r + 50);
3624
+ }
3625
+ /**
3626
+ * Update column order with configured animation.
3627
+ */
3628
+ updateColumnOrder(e) {
3629
+ const t = this.grid, n = this.animationType;
3630
+ if (n === "flip" && this.shadowRoot) {
3631
+ const o = this.captureHeaderPositions();
3632
+ t.setColumnOrder(e), this.shadowRoot.host.offsetHeight, this.animateFLIP(o);
3633
+ } else n === "fade" ? this.animateFade(() => t.setColumnOrder(e)) : t.setColumnOrder(e);
3345
3634
  t.requestStateChange?.();
3346
3635
  }
3347
3636
  // #endregion
@@ -3364,14 +3653,14 @@ function Zt(s) {
3364
3653
  to: { row: e.endRow, col: e.endCol }
3365
3654
  };
3366
3655
  }
3367
- function X(s) {
3656
+ function J(s) {
3368
3657
  return s.map(Zt);
3369
3658
  }
3370
3659
  function Xt(s, e, t) {
3371
3660
  const n = D(t);
3372
3661
  return s >= n.startRow && s <= n.endRow && e >= n.startCol && e <= n.endCol;
3373
3662
  }
3374
- function Ie(s, e, t) {
3663
+ function Le(s, e, t) {
3375
3664
  return t.some((n) => Xt(s, e, n));
3376
3665
  }
3377
3666
  function Jt(s) {
@@ -3388,7 +3677,7 @@ function Qt(s) {
3388
3677
  e.set(`${n.row},${n.col}`, n);
3389
3678
  return [...e.values()];
3390
3679
  }
3391
- function U(s, e) {
3680
+ function Y(s, e) {
3392
3681
  return {
3393
3682
  startRow: s.row,
3394
3683
  startCol: s.col,
@@ -3415,9 +3704,9 @@ function tn(s, e, t) {
3415
3704
  }));
3416
3705
  return { mode: s, ranges: n };
3417
3706
  }
3418
- return s === "range" && e.ranges.length > 0 ? { mode: s, ranges: X(e.ranges) } : { mode: s, ranges: [] };
3707
+ return s === "range" && e.ranges.length > 0 ? { mode: s, ranges: J(e.ranges) } : { mode: s, ranges: [] };
3419
3708
  }
3420
- class In extends y {
3709
+ class In extends v {
3421
3710
  name = "selection";
3422
3711
  version = "1.0.0";
3423
3712
  get defaultConfig() {
@@ -3455,7 +3744,7 @@ class In extends y {
3455
3744
  if (i === "range") {
3456
3745
  const r = o.shiftKey, l = o.ctrlKey || o.metaKey;
3457
3746
  if (r && this.cellAnchor) {
3458
- const a = U(this.cellAnchor, { row: t, col: n });
3747
+ const a = Y(this.cellAnchor, { row: t, col: n });
3459
3748
  l ? this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = a : this.ranges.push(a) : this.ranges = [a], this.activeRange = a;
3460
3749
  } else if (l) {
3461
3750
  const a = {
@@ -3522,7 +3811,7 @@ class In extends y {
3522
3811
  }
3523
3812
  onCellMouseMove(e) {
3524
3813
  if (this.config.mode !== "range" || !this.isDragging || !this.cellAnchor || e.rowIndex === void 0 || e.colIndex === void 0 || e.rowIndex < 0) return;
3525
- const t = U(this.cellAnchor, { row: e.rowIndex, col: e.colIndex });
3814
+ const t = Y(this.cellAnchor, { row: e.rowIndex, col: e.colIndex });
3526
3815
  return this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = t : this.ranges.push(t), this.activeRange = t, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
3527
3816
  }
3528
3817
  onCellMouseUp(e) {
@@ -3550,7 +3839,7 @@ class In extends y {
3550
3839
  const i = this.activeRange ? D(this.activeRange) : null;
3551
3840
  e.querySelectorAll(".cell[data-row][data-col]").forEach((l) => {
3552
3841
  const a = parseInt(l.getAttribute("data-row") ?? "-1", 10), d = parseInt(l.getAttribute("data-col") ?? "-1", 10);
3553
- a >= 0 && d >= 0 && Ie(a, d, this.ranges) && (l.classList.add("selected"), l.classList.remove("cell-focus"), i && (a === i.startRow && l.classList.add("top"), a === i.endRow && l.classList.add("bottom"), d === i.startCol && l.classList.add("first"), d === i.endCol && l.classList.add("last")));
3842
+ a >= 0 && d >= 0 && Le(a, d, this.ranges) && (l.classList.add("selected"), l.classList.remove("cell-focus"), i && (a === i.startRow && l.classList.add("top"), a === i.endRow && l.classList.add("bottom"), d === i.startCol && l.classList.add("first"), d === i.endCol && l.classList.add("last")));
3554
3843
  });
3555
3844
  }
3556
3845
  t === "cell" && this.selectedCell && e.querySelectorAll(".cell-focus").forEach((i) => i.classList.remove("cell-focus"));
@@ -3564,7 +3853,7 @@ class In extends y {
3564
3853
  this.pendingKeyboardUpdate = null;
3565
3854
  const i = this.grid._focusRow, r = this.grid._focusCol;
3566
3855
  if (o && this.cellAnchor) {
3567
- const l = U(this.cellAnchor, { row: i, col: r });
3856
+ const l = Y(this.cellAnchor, { row: i, col: r });
3568
3857
  this.ranges = [l], this.activeRange = l;
3569
3858
  } else o || (this.ranges = [], this.activeRange = null, this.cellAnchor = { row: i, col: r });
3570
3859
  this.emit("selection-change", this.#e());
@@ -3596,7 +3885,7 @@ class In extends y {
3596
3885
  * Get all selected cell ranges in public format.
3597
3886
  */
3598
3887
  getRanges() {
3599
- return X(this.ranges);
3888
+ return J(this.ranges);
3600
3889
  }
3601
3890
  /**
3602
3891
  * Get all selected cells across all ranges.
@@ -3608,7 +3897,7 @@ class In extends y {
3608
3897
  * Check if a specific cell is in range selection.
3609
3898
  */
3610
3899
  isCellSelected(e, t) {
3611
- return Ie(e, t, this.ranges);
3900
+ return Le(e, t, this.ranges);
3612
3901
  }
3613
3902
  /**
3614
3903
  * Clear all selection.
@@ -3627,7 +3916,7 @@ class In extends y {
3627
3916
  endCol: t.to.col
3628
3917
  })), this.activeRange = this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] : null, this.emit("selection-change", {
3629
3918
  mode: this.config.mode,
3630
- ranges: X(this.ranges)
3919
+ ranges: J(this.ranges)
3631
3920
  }), this.requestAfterRender();
3632
3921
  }
3633
3922
  // #endregion
@@ -3663,7 +3952,7 @@ function on(s, e, t) {
3663
3952
  i.push(r);
3664
3953
  return i;
3665
3954
  }
3666
- async function Le(s, e, t, n) {
3955
+ async function Te(s, e, t, n) {
3667
3956
  const o = nn(e, t);
3668
3957
  return s.getRows({
3669
3958
  startRow: o.start,
@@ -3679,7 +3968,7 @@ function rn(s, e, t) {
3679
3968
  return o[i];
3680
3969
  }
3681
3970
  const sn = 100;
3682
- class Ln extends y {
3971
+ class Ln extends v {
3683
3972
  name = "serverSide";
3684
3973
  version = "1.0.0";
3685
3974
  get defaultConfig() {
@@ -3713,7 +4002,7 @@ class Ln extends y {
3713
4002
  if (!(this.loadedBlocks.has(i) || this.loadingBlocks.has(i))) {
3714
4003
  if (this.loadingBlocks.size >= (this.config.maxConcurrentRequests ?? 2))
3715
4004
  break;
3716
- this.loadingBlocks.add(i), Le(this.dataSource, i, t, {}).then((r) => {
4005
+ this.loadingBlocks.add(i), Te(this.dataSource, i, t, {}).then((r) => {
3717
4006
  this.loadedBlocks.set(i, r.rows), this.totalRowCount = r.totalRowCount, this.loadingBlocks.delete(i), this.requestRender(), this.loadRequiredBlocks();
3718
4007
  }).catch(() => {
3719
4008
  this.loadingBlocks.delete(i);
@@ -3745,7 +4034,7 @@ class Ln extends y {
3745
4034
  setDataSource(e) {
3746
4035
  this.dataSource = e, this.loadedBlocks.clear(), this.loadingBlocks.clear();
3747
4036
  const t = this.config.cacheBlockSize ?? 100;
3748
- Le(e, 0, t, {}).then((n) => {
4037
+ Te(e, 0, t, {}).then((n) => {
3749
4038
  this.loadedBlocks.set(0, n.rows), this.totalRowCount = n.totalRowCount, this.requestRender();
3750
4039
  });
3751
4040
  }
@@ -3783,38 +4072,20 @@ class Ln extends y {
3783
4072
  }
3784
4073
  // #endregion
3785
4074
  }
3786
- function ne(s, e, t) {
4075
+ function De(s, e, t) {
3787
4076
  return s.id !== void 0 ? String(s.id) : t ? `${t}-${e}` : String(e);
3788
4077
  }
3789
- function De(s, e, t, n = null, o = 0) {
3790
- const i = e.childrenField ?? "children", r = [];
3791
- for (let l = 0; l < s.length; l++) {
3792
- const a = s[l], d = ne(a, l, n), c = a[i], u = Array.isArray(c) && c.length > 0, h = t.has(d);
3793
- if (r.push({
3794
- key: d,
3795
- data: a,
3796
- depth: o,
3797
- hasChildren: u,
3798
- isExpanded: h,
3799
- parentKey: n
3800
- }), u && h) {
3801
- const g = De(c, e, t, d, o + 1);
3802
- r.push(...g);
3803
- }
3804
- }
3805
- return r;
3806
- }
3807
- function Te(s, e) {
4078
+ function Fe(s, e) {
3808
4079
  const t = new Set(s);
3809
4080
  return t.has(e) ? t.delete(e) : t.add(e), t;
3810
4081
  }
3811
- function J(s, e, t = null, n = 0) {
4082
+ function Q(s, e, t = null, n = 0) {
3812
4083
  const o = e.childrenField ?? "children", i = /* @__PURE__ */ new Set();
3813
4084
  for (let r = 0; r < s.length; r++) {
3814
- const l = s[r], a = ne(l, r, t), d = l[o];
4085
+ const l = s[r], a = De(l, r, t), d = l[o];
3815
4086
  if (Array.isArray(d) && d.length > 0) {
3816
4087
  i.add(a);
3817
- const c = J(d, e, a, n + 1);
4088
+ const c = Q(d, e, a, n + 1);
3818
4089
  for (const u of c) i.add(u);
3819
4090
  }
3820
4091
  }
@@ -3826,7 +4097,7 @@ function ln() {
3826
4097
  function He(s, e, t, n = null, o = 0) {
3827
4098
  const i = t.childrenField ?? "children";
3828
4099
  for (let r = 0; r < s.length; r++) {
3829
- const l = s[r], a = ne(l, r, n);
4100
+ const l = s[r], a = De(l, r, n);
3830
4101
  if (a === e)
3831
4102
  return [a];
3832
4103
  const d = l[i];
@@ -3846,7 +4117,7 @@ function an(s, e, t, n) {
3846
4117
  i.add(o[r]);
3847
4118
  return i;
3848
4119
  }
3849
- function Fe(s, e = "children") {
4120
+ function Pe(s, e = "children") {
3850
4121
  if (!Array.isArray(s) || s.length === 0) return !1;
3851
4122
  for (const t of s)
3852
4123
  if (t && Array.isArray(t[e]) && t[e].length > 0)
@@ -3864,170 +4135,199 @@ function dn(s) {
3864
4135
  }
3865
4136
  return null;
3866
4137
  }
3867
- const cn = ".tree-toggle{cursor:pointer;user-select:none;transition:transform .2s}.tree-toggle:hover{color:var(--tbw-tree-accent, var(--tbw-color-accent))}";
3868
- class Tn extends y {
4138
+ const cn = ".tree-cell{display:flex;align-items:center;padding-left:calc(var(--tree-depth, 0) * var(--tbw-tree-indent, 20px))}.tree-toggle{cursor:pointer;user-select:none;display:inline-flex;align-items:center;justify-content:center;margin-right:4px}.tree-toggle:hover{color:var(--tbw-tree-accent, var(--tbw-color-accent))}.tree-spacer{width:14px;display:inline-block}.data-grid-row.tbw-tree-slide-in{animation:tbw-tree-slide-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-tree-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}.data-grid-row.tbw-tree-fade-in{animation:tbw-tree-fade-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-tree-fade-in{0%{opacity:0}to{opacity:1}}";
4139
+ class Tn extends v {
3869
4140
  name = "tree";
3870
4141
  version = "1.0.0";
4142
+ styles = cn;
3871
4143
  get defaultConfig() {
3872
4144
  return {
3873
4145
  childrenField: "children",
3874
4146
  autoDetect: !0,
3875
4147
  defaultExpanded: !1,
3876
4148
  indentWidth: 20,
3877
- showExpandIcons: !0
4149
+ showExpandIcons: !0,
4150
+ animation: "slide"
3878
4151
  };
3879
4152
  }
3880
- // #region Internal State
3881
- /** Set of expanded row keys */
4153
+ // #region State
3882
4154
  expandedKeys = /* @__PURE__ */ new Set();
3883
- /** Whether initial expansion (based on defaultExpanded config) has been applied */
3884
4155
  initialExpansionDone = !1;
3885
- /** Flattened tree rows for rendering */
3886
4156
  flattenedRows = [];
3887
- /** Map from key to flattened row for quick lookup */
3888
4157
  rowKeyMap = /* @__PURE__ */ new Map();
3889
- // #endregion
3890
- // #region Lifecycle
4158
+ previousVisibleKeys = /* @__PURE__ */ new Set();
4159
+ keysToAnimate = /* @__PURE__ */ new Set();
4160
+ sortState = null;
3891
4161
  detach() {
3892
- this.expandedKeys.clear(), this.initialExpansionDone = !1, this.flattenedRows = [], this.rowKeyMap.clear();
4162
+ this.expandedKeys.clear(), this.initialExpansionDone = !1, this.flattenedRows = [], this.rowKeyMap.clear(), this.previousVisibleKeys.clear(), this.keysToAnimate.clear(), this.sortState = null;
4163
+ }
4164
+ // #endregion
4165
+ // #region Animation
4166
+ get animationStyle() {
4167
+ const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
4168
+ if (t === !1 || t === "off") return !1;
4169
+ if (t !== !0 && t !== "on") {
4170
+ const n = this.shadowRoot?.host;
4171
+ if (n && getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() === "0")
4172
+ return !1;
4173
+ }
4174
+ return this.config.animation ?? "slide";
3893
4175
  }
3894
4176
  // #endregion
3895
4177
  // #region Auto-Detection
3896
- /**
3897
- * Detects if tree functionality should be enabled based on data structure.
3898
- * Called by the grid during plugin initialization.
3899
- */
3900
4178
  detect(e) {
3901
4179
  if (!this.config.autoDetect) return !1;
3902
4180
  const t = this.config.childrenField ?? dn(e) ?? "children";
3903
- return Fe(e, t);
4181
+ return Pe(e, t);
3904
4182
  }
3905
4183
  // #endregion
3906
4184
  // #region Data Processing
3907
4185
  processRows(e) {
3908
4186
  const t = this.config.childrenField ?? "children";
3909
- if (!Fe(e, t))
3910
- return this.flattenedRows = [], this.rowKeyMap.clear(), [...e];
3911
- this.config.defaultExpanded && !this.initialExpansionDone && (this.expandedKeys = J(e, this.config), this.initialExpansionDone = !0), this.flattenedRows = De(e, this.config, this.expandedKeys), this.rowKeyMap.clear();
3912
- for (const n of this.flattenedRows)
3913
- this.rowKeyMap.set(n.key, n);
3914
- return this.flattenedRows.map((n) => ({
3915
- ...n.data,
3916
- __treeKey: n.key,
3917
- __treeDepth: n.depth,
3918
- __treeHasChildren: n.hasChildren,
3919
- __treeExpanded: n.isExpanded
4187
+ if (!Pe(e, t))
4188
+ return this.flattenedRows = [], this.rowKeyMap.clear(), this.previousVisibleKeys.clear(), [...e];
4189
+ let n = this.withStableKeys(e);
4190
+ this.sortState && (n = this.sortTree(n, this.sortState.field, this.sortState.direction)), this.config.defaultExpanded && !this.initialExpansionDone && (this.expandedKeys = Q(n, this.config), this.initialExpansionDone = !0), this.flattenedRows = this.flattenTree(n, this.expandedKeys), this.rowKeyMap.clear(), this.keysToAnimate.clear();
4191
+ const o = /* @__PURE__ */ new Set();
4192
+ for (const i of this.flattenedRows)
4193
+ this.rowKeyMap.set(i.key, i), o.add(i.key), !this.previousVisibleKeys.has(i.key) && i.depth > 0 && this.keysToAnimate.add(i.key);
4194
+ return this.previousVisibleKeys = o, this.flattenedRows.map((i) => ({
4195
+ ...i.data,
4196
+ __treeKey: i.key,
4197
+ __treeDepth: i.depth,
4198
+ __treeHasChildren: i.hasChildren,
4199
+ __treeExpanded: i.isExpanded
3920
4200
  }));
3921
4201
  }
4202
+ /** Assign stable keys to rows (preserves key across sort operations) */
4203
+ withStableKeys(e, t = null) {
4204
+ const n = this.config.childrenField ?? "children";
4205
+ return e.map((o, i) => {
4206
+ const r = o.id !== void 0 ? String(o.id) : o.__stableKey ?? (t ? `${t}-${i}` : String(i)), l = o[n], a = Array.isArray(l) && l.length > 0;
4207
+ return {
4208
+ ...o,
4209
+ __stableKey: r,
4210
+ ...a ? { [n]: this.withStableKeys(l, r) } : {}
4211
+ };
4212
+ });
4213
+ }
4214
+ /** Flatten tree using stable keys */
4215
+ flattenTree(e, t, n = 0) {
4216
+ const o = this.config.childrenField ?? "children", i = [];
4217
+ for (const r of e) {
4218
+ const l = r.__stableKey ?? r.id ?? "?", a = r[o], d = Array.isArray(a) && a.length > 0, c = t.has(l);
4219
+ i.push({
4220
+ key: l,
4221
+ data: r,
4222
+ depth: n,
4223
+ hasChildren: d,
4224
+ isExpanded: c,
4225
+ parentKey: n > 0 && l.substring(0, l.lastIndexOf("-")) || null
4226
+ }), d && c && i.push(...this.flattenTree(a, t, n + 1));
4227
+ }
4228
+ return i;
4229
+ }
4230
+ /** Sort tree recursively, keeping children with parents */
4231
+ sortTree(e, t, n) {
4232
+ const o = this.config.childrenField ?? "children";
4233
+ return [...e].sort((r, l) => {
4234
+ const a = r[t], d = l[t];
4235
+ return a == null && d == null ? 0 : a == null ? -1 : d == null ? 1 : a > d ? n : a < d ? -n : 0;
4236
+ }).map((r) => {
4237
+ const l = r[o];
4238
+ return Array.isArray(l) && l.length > 0 ? { ...r, [o]: this.sortTree(l, t, n) } : r;
4239
+ });
4240
+ }
3922
4241
  processColumns(e) {
3923
4242
  if (this.flattenedRows.length === 0) return [...e];
3924
4243
  const t = [...e];
3925
- if (t.length > 0) {
3926
- const n = { ...t[0] }, o = n.viewRenderer;
3927
- if (o?.__treeWrapped)
3928
- return t;
3929
- const i = () => this.config, r = (l) => {
3930
- const { value: a, row: d, column: c } = l, u = d.__treeDepth ?? 0, h = d.__treeHasChildren ?? !1, g = d.__treeExpanded ?? !1, p = i(), m = p.indentWidth ?? 20, f = p.showExpandIcons ?? !0, b = document.createElement("span");
3931
- if (b.style.display = "flex", b.style.alignItems = "center", b.style.paddingLeft = `${u * m}px`, h && f) {
3932
- const v = document.createElement("span");
3933
- v.className = "tree-toggle", this.setIcon(v, this.resolveIcon(g ? "collapse" : "expand")), v.style.cursor = "pointer", v.style.marginRight = "4px", v.style.fontSize = "10px", v.setAttribute("data-tree-key", d.__treeKey), b.appendChild(v);
3934
- } else if (f) {
3935
- const v = document.createElement("span");
3936
- v.style.width = "14px", v.style.display = "inline-block", b.appendChild(v);
3937
- }
3938
- const E = document.createElement("span");
3939
- if (o) {
3940
- const v = o(l);
3941
- v instanceof Node ? E.appendChild(v) : E.textContent = String(v ?? a ?? "");
3942
- } else
3943
- E.textContent = String(a ?? "");
3944
- return b.appendChild(E), b;
3945
- };
3946
- r.__treeWrapped = !0, n.viewRenderer = r, t[0] = n;
3947
- }
3948
- return t;
4244
+ if (t.length === 0) return t;
4245
+ const n = { ...t[0] }, o = n.viewRenderer;
4246
+ if (o?.__treeWrapped) return t;
4247
+ const i = () => this.config, r = this.setIcon.bind(this), l = this.resolveIcon.bind(this), a = (d) => {
4248
+ const { value: c, row: u } = d, { indentWidth: h = 20, showExpandIcons: g = !0 } = i(), f = document.createElement("span");
4249
+ if (f.className = "tree-cell", f.style.setProperty("--tree-depth", String(u.__treeDepth ?? 0)), f.style.setProperty("--tbw-tree-indent", `${h}px`), u.__treeHasChildren && g) {
4250
+ const p = document.createElement("span");
4251
+ p.className = `tree-toggle${u.__treeExpanded ? " expanded" : ""}`, r(p, l(u.__treeExpanded ? "collapse" : "expand")), p.setAttribute("data-tree-key", u.__treeKey), f.appendChild(p);
4252
+ } else if (g) {
4253
+ const p = document.createElement("span");
4254
+ p.className = "tree-spacer", f.appendChild(p);
4255
+ }
4256
+ const m = document.createElement("span");
4257
+ if (o) {
4258
+ const p = o(d);
4259
+ p instanceof Node ? m.appendChild(p) : m.textContent = String(p ?? c ?? "");
4260
+ } else
4261
+ m.textContent = String(c ?? "");
4262
+ return f.appendChild(m), f;
4263
+ };
4264
+ return a.__treeWrapped = !0, n.viewRenderer = a, t[0] = n, t;
3949
4265
  }
3950
4266
  // #endregion
3951
4267
  // #region Event Handlers
3952
4268
  onCellClick(e) {
3953
4269
  const t = e.originalEvent?.target;
3954
4270
  if (!t?.classList.contains("tree-toggle")) return !1;
3955
- const n = t.getAttribute("data-tree-key");
3956
- if (!n) return !1;
3957
- const o = this.rowKeyMap.get(n);
3958
- return o ? (this.expandedKeys = Te(this.expandedKeys, n), this.emit("tree-expand", {
4271
+ const n = t.getAttribute("data-tree-key"), o = n ? this.rowKeyMap.get(n) : null;
4272
+ return o ? (this.expandedKeys = Fe(this.expandedKeys, n), this.emit("tree-expand", {
3959
4273
  key: n,
3960
4274
  row: o.data,
3961
4275
  expanded: this.expandedKeys.has(n),
3962
4276
  depth: o.depth
3963
4277
  }), this.requestRender(), !0) : !1;
3964
4278
  }
4279
+ onHeaderClick(e) {
4280
+ if (this.flattenedRows.length === 0 || !e.column.sortable) return !1;
4281
+ const { field: t } = e.column;
4282
+ !this.sortState || this.sortState.field !== t ? this.sortState = { field: t, direction: 1 } : this.sortState.direction === 1 ? this.sortState = { field: t, direction: -1 } : this.sortState = null;
4283
+ const n = this.grid;
4284
+ return n._sortState !== void 0 && (n._sortState = this.sortState ? { ...this.sortState } : null), this.emit("sort-change", { field: t, direction: this.sortState?.direction ?? 0 }), this.requestRender(), !0;
4285
+ }
4286
+ afterRender() {
4287
+ const e = this.animationStyle;
4288
+ if (e === !1 || this.keysToAnimate.size === 0) return;
4289
+ const t = this.shadowRoot?.querySelector(".rows");
4290
+ if (!t) return;
4291
+ const n = e === "fade" ? "tbw-tree-fade-in" : "tbw-tree-slide-in";
4292
+ for (const o of t.querySelectorAll(".data-grid-row")) {
4293
+ const i = o.querySelector(".cell[data-row]"), r = i ? parseInt(i.getAttribute("data-row") ?? "-1", 10) : -1, l = this.flattenedRows[r]?.key;
4294
+ l && this.keysToAnimate.has(l) && (o.classList.add(n), o.addEventListener("animationend", () => o.classList.remove(n), { once: !0 }));
4295
+ }
4296
+ this.keysToAnimate.clear();
4297
+ }
3965
4298
  // #endregion
3966
4299
  // #region Public API
3967
- /**
3968
- * Expand a specific node by key.
3969
- */
3970
4300
  expand(e) {
3971
4301
  this.expandedKeys.add(e), this.requestRender();
3972
4302
  }
3973
- /**
3974
- * Collapse a specific node by key.
3975
- */
3976
4303
  collapse(e) {
3977
4304
  this.expandedKeys.delete(e), this.requestRender();
3978
4305
  }
3979
- /**
3980
- * Toggle the expansion state of a node.
3981
- */
3982
4306
  toggle(e) {
3983
- this.expandedKeys = Te(this.expandedKeys, e), this.requestRender();
4307
+ this.expandedKeys = Fe(this.expandedKeys, e), this.requestRender();
3984
4308
  }
3985
- /**
3986
- * Expand all nodes in the tree.
3987
- */
3988
4309
  expandAll() {
3989
- this.expandedKeys = J(this.rows, this.config), this.requestRender();
4310
+ this.expandedKeys = Q(this.rows, this.config), this.requestRender();
3990
4311
  }
3991
- /**
3992
- * Collapse all nodes in the tree.
3993
- */
3994
4312
  collapseAll() {
3995
4313
  this.expandedKeys = ln(), this.requestRender();
3996
4314
  }
3997
- /**
3998
- * Check if a node is currently expanded.
3999
- */
4000
4315
  isExpanded(e) {
4001
4316
  return this.expandedKeys.has(e);
4002
4317
  }
4003
- /**
4004
- * Get all currently expanded keys.
4005
- */
4006
4318
  getExpandedKeys() {
4007
4319
  return [...this.expandedKeys];
4008
4320
  }
4009
- /**
4010
- * Get the flattened tree rows with metadata.
4011
- */
4012
4321
  getFlattenedRows() {
4013
4322
  return [...this.flattenedRows];
4014
4323
  }
4015
- /**
4016
- * Get a row's original data by its key.
4017
- */
4018
4324
  getRowByKey(e) {
4019
4325
  return this.rowKeyMap.get(e)?.data;
4020
4326
  }
4021
- /**
4022
- * Expand all ancestors of a node to make it visible.
4023
- */
4024
4327
  expandToKey(e) {
4025
4328
  this.expandedKeys = an(this.rows, e, this.config, this.expandedKeys), this.requestRender();
4026
4329
  }
4027
4330
  // #endregion
4028
- // #region Styles
4029
- styles = cn;
4030
- // #endregion
4031
4331
  }
4032
4332
  function un(s, e, t) {
4033
4333
  const n = [...s.undoStack, e];
@@ -4051,7 +4351,7 @@ function Me(s) {
4051
4351
  action: t
4052
4352
  } : { newState: s, action: null };
4053
4353
  }
4054
- function Ne(s) {
4354
+ function Ke(s) {
4055
4355
  if (s.redoStack.length === 0)
4056
4356
  return { newState: s, action: null };
4057
4357
  const e = [...s.redoStack], t = e.pop();
@@ -4069,10 +4369,10 @@ function hn(s) {
4069
4369
  function gn(s) {
4070
4370
  return s.redoStack.length > 0;
4071
4371
  }
4072
- function pn() {
4372
+ function fn() {
4073
4373
  return { undoStack: [], redoStack: [] };
4074
4374
  }
4075
- function fn(s, e, t, n) {
4375
+ function pn(s, e, t, n) {
4076
4376
  return {
4077
4377
  type: "cell-edit",
4078
4378
  rowIndex: s,
@@ -4082,7 +4382,7 @@ function fn(s, e, t, n) {
4082
4382
  timestamp: Date.now()
4083
4383
  };
4084
4384
  }
4085
- class Fn extends y {
4385
+ class Fn extends v {
4086
4386
  name = "undoRedo";
4087
4387
  version = "1.0.0";
4088
4388
  get defaultConfig() {
@@ -4118,7 +4418,7 @@ class Fn extends y {
4118
4418
  return !0;
4119
4419
  }
4120
4420
  if (n) {
4121
- const o = Ne({ undoStack: this.undoStack, redoStack: this.redoStack });
4421
+ const o = Ke({ undoStack: this.undoStack, redoStack: this.redoStack });
4122
4422
  if (o.action) {
4123
4423
  const i = this.rows;
4124
4424
  i[o.action.rowIndex] && (i[o.action.rowIndex][o.action.field] = o.action.newValue), this.undoStack = o.newState.undoStack, this.redoStack = o.newState.redoStack, this.emit("redo", {
@@ -4141,7 +4441,7 @@ class Fn extends y {
4141
4441
  * @param newValue - The value after the edit
4142
4442
  */
4143
4443
  recordEdit(e, t, n, o) {
4144
- const i = fn(e, t, n, o), r = un(
4444
+ const i = pn(e, t, n, o), r = un(
4145
4445
  { undoStack: this.undoStack, redoStack: this.redoStack },
4146
4446
  i,
4147
4447
  this.config.maxHistorySize ?? 100
@@ -4167,7 +4467,7 @@ class Fn extends y {
4167
4467
  * @returns The redone action, or null if nothing to redo
4168
4468
  */
4169
4469
  redo() {
4170
- const e = Ne({ undoStack: this.undoStack, redoStack: this.redoStack });
4470
+ const e = Ke({ undoStack: this.undoStack, redoStack: this.redoStack });
4171
4471
  if (e.action) {
4172
4472
  const t = this.rows;
4173
4473
  t[e.action.rowIndex] && (t[e.action.rowIndex][e.action.field] = e.action.newValue), this.undoStack = e.newState.undoStack, this.redoStack = e.newState.redoStack, this.requestRender();
@@ -4190,7 +4490,7 @@ class Fn extends y {
4190
4490
  * Clear all undo/redo history.
4191
4491
  */
4192
4492
  clearHistory() {
4193
- const e = pn();
4493
+ const e = fn();
4194
4494
  this.undoStack = e.undoStack, this.redoStack = e.redoStack;
4195
4495
  }
4196
4496
  /**
@@ -4208,11 +4508,11 @@ class Fn extends y {
4208
4508
  // #endregion
4209
4509
  }
4210
4510
  const mn = '.tbw-visibility-content{display:flex;flex-direction:column;height:100%}.tbw-visibility-list{flex:1;overflow-y:auto;padding:8px}.tbw-visibility-row{display:flex;align-items:center;gap:8px;padding:6px 4px;cursor:pointer;font-size:13px;border-radius:var(--tbw-border-radius, 4px);position:relative}.tbw-visibility-row:hover{background:var(--tbw-visibility-hover, var(--tbw-color-row-hover, #f3f4f6))}.tbw-visibility-row input[type=checkbox]{cursor:pointer}.tbw-visibility-row.locked span{color:var(--tbw-color-fg-muted, #888)}.tbw-visibility-handle{cursor:grab;color:var(--tbw-color-fg-muted, #888);font-size:10px;letter-spacing:-2px;user-select:none;flex-shrink:0}.tbw-visibility-row.reorderable:hover .tbw-visibility-handle{color:var(--tbw-color-fg, #1f2937)}.tbw-visibility-label{display:flex;align-items:center;gap:8px;flex:1;cursor:pointer}.tbw-visibility-row.dragging{opacity:.5;cursor:grabbing}.tbw-visibility-row.drop-before:before{content:"";position:absolute;left:0;right:0;top:0;height:2px;background:var(--tbw-reorder-indicator, var(--tbw-color-accent, #3b82f6))}.tbw-visibility-row.drop-after:after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--tbw-reorder-indicator, var(--tbw-color-accent, #3b82f6))}.tbw-visibility-show-all{margin:8px;padding:8px 12px;border:1px solid var(--tbw-visibility-border, var(--tbw-color-border, #e5e7eb));border-radius:var(--tbw-border-radius, 4px);background:var(--tbw-visibility-btn-bg, var(--tbw-color-header-bg, #f9fafb));color:var(--tbw-color-fg, #1f2937);cursor:pointer;font-size:13px}.tbw-visibility-show-all:hover{background:var(--tbw-visibility-hover, var(--tbw-color-row-hover, #f3f4f6))}';
4211
- function Pe(s) {
4511
+ function Ne(s) {
4212
4512
  const e = s.meta ?? {};
4213
4513
  return e.lockPosition !== !0 && e.suppressMovable !== !0;
4214
4514
  }
4215
- class M extends y {
4515
+ class F extends v {
4216
4516
  name = "visibility";
4217
4517
  version = "1.0.0";
4218
4518
  /** Tool panel ID for shell integration */
@@ -4241,7 +4541,7 @@ class M extends y {
4241
4541
  */
4242
4542
  getToolPanel() {
4243
4543
  return {
4244
- id: M.PANEL_ID,
4544
+ id: F.PANEL_ID,
4245
4545
  title: "Columns",
4246
4546
  icon: "☰",
4247
4547
  tooltip: "Column visibility",
@@ -4256,7 +4556,7 @@ class M extends y {
4256
4556
  * Show the visibility sidebar panel.
4257
4557
  */
4258
4558
  show() {
4259
- this.grid.openToolPanel(M.PANEL_ID);
4559
+ this.grid.openToolPanel(F.PANEL_ID);
4260
4560
  }
4261
4561
  /**
4262
4562
  * Hide the visibility sidebar panel.
@@ -4268,7 +4568,7 @@ class M extends y {
4268
4568
  * Toggle the visibility sidebar panel.
4269
4569
  */
4270
4570
  toggle() {
4271
- this.grid.toggleToolPanel(M.PANEL_ID);
4571
+ this.grid.toggleToolPanel(F.PANEL_ID);
4272
4572
  }
4273
4573
  /**
4274
4574
  * Check if a specific column is visible.
@@ -4346,7 +4646,7 @@ class M extends y {
4346
4646
  * @returns True if the panel is open
4347
4647
  */
4348
4648
  isPanelVisible() {
4349
- return this.grid.activeToolPanel === M.PANEL_ID;
4649
+ return this.grid.activeToolPanel === F.PANEL_ID;
4350
4650
  }
4351
4651
  // #endregion
4352
4652
  // #region Private Methods
@@ -4383,7 +4683,7 @@ class M extends y {
4383
4683
  const o = t.getAllColumns();
4384
4684
  for (let i = 0; i < o.length; i++) {
4385
4685
  const r = o[i], l = r.header || r.field, a = document.createElement("div");
4386
- a.className = r.lockVisible ? "tbw-visibility-row locked" : "tbw-visibility-row", a.setAttribute("data-field", r.field), a.setAttribute("data-index", String(i)), n && Pe(r) && (a.draggable = !0, a.classList.add("reorderable"), this.setupDragListeners(a, r.field, i, e));
4686
+ a.className = r.lockVisible ? "tbw-visibility-row locked" : "tbw-visibility-row", a.setAttribute("data-field", r.field), a.setAttribute("data-index", String(i)), n && Ne(r) && (a.draggable = !0, a.classList.add("reorderable"), this.setupDragListeners(a, r.field, i, e));
4387
4687
  const d = document.createElement("label");
4388
4688
  d.className = "tbw-visibility-label";
4389
4689
  const c = document.createElement("input");
@@ -4391,7 +4691,7 @@ class M extends y {
4391
4691
  t.toggleColumnVisibility(r.field), setTimeout(() => this.rebuildToggles(e), 0);
4392
4692
  });
4393
4693
  const u = document.createElement("span");
4394
- if (u.textContent = l, d.appendChild(c), d.appendChild(u), n && Pe(r)) {
4694
+ if (u.textContent = l, d.appendChild(c), d.appendChild(u), n && Ne(r)) {
4395
4695
  const h = document.createElement("span");
4396
4696
  h.className = "tbw-visibility-handle", this.setIcon(h, this.resolveIcon("dragHandle")), h.title = "Drag to reorder", a.appendChild(h);
4397
4697
  }
@@ -4441,44 +4741,47 @@ class M extends y {
4441
4741
  // #endregion
4442
4742
  }
4443
4743
  export {
4444
- y as BaseGridPlugin,
4744
+ v as BaseGridPlugin,
4445
4745
  bn as ClipboardPlugin,
4446
4746
  vn as ColumnVirtualizationPlugin,
4447
4747
  xn as ContextMenuPlugin,
4448
- Ge as DEFAULT_GRID_ICONS,
4449
- Pn as DGEvents,
4450
- Kn as DataGridElement,
4748
+ Kn as DEFAULT_ANIMATION_CONFIG,
4749
+ Ve as DEFAULT_GRID_ICONS,
4750
+ Nn as DGEvents,
4751
+ qn as DataGridElement,
4451
4752
  yn as ExportPlugin,
4452
- _ as FilteringPlugin,
4453
- qn as FitModeEnum,
4454
- Dn as GridCSSVars,
4455
- Hn as GridClasses,
4456
- Gn as GridDataAttrs,
4457
- On as GridElement,
4753
+ A as FilteringPlugin,
4754
+ Dn as FitModeEnum,
4755
+ Hn as GridCSSVars,
4756
+ Vn as GridClasses,
4757
+ On as GridDataAttrs,
4758
+ Gn as GridElement,
4458
4759
  Bn as GridSelectors,
4459
4760
  Cn as GroupingColumnsPlugin,
4460
4761
  Rn as GroupingRowsPlugin,
4461
4762
  Sn as MasterDetailPlugin,
4462
- En as MultiSortPlugin,
4463
- Ke as PLUGIN_QUERIES,
4464
- kn as PinnedColumnsPlugin,
4763
+ kn as MultiSortPlugin,
4764
+ N as PLUGIN_QUERIES,
4765
+ En as PinnedColumnsPlugin,
4465
4766
  An as PinnedRowsPlugin,
4466
- F as PivotPlugin,
4467
- Vn as PluginEvents,
4468
- zn as PluginManager,
4767
+ T as PivotPlugin,
4768
+ zn as PluginEvents,
4769
+ Wn as PluginManager,
4469
4770
  _n as ReorderPlugin,
4470
4771
  In as SelectionPlugin,
4471
4772
  Ln as ServerSidePlugin,
4472
4773
  Tn as TreePlugin,
4473
4774
  Fn as UndoRedoPlugin,
4474
- M as VisibilityPlugin,
4475
- Wn as aggregatorRegistry,
4775
+ F as VisibilityPlugin,
4776
+ $n as aggregatorRegistry,
4777
+ jn as builtInSort,
4778
+ Un as defaultComparator,
4476
4779
  le as getAggregator,
4477
4780
  Oe as getValueAggregator,
4478
- $n as listAggregators,
4479
- jn as registerAggregator,
4781
+ Yn as listAggregators,
4782
+ Zn as registerAggregator,
4480
4783
  se as runAggregator,
4481
- Un as runValueAggregator,
4482
- Yn as unregisterAggregator
4784
+ Xn as runValueAggregator,
4785
+ Jn as unregisterAggregator
4483
4786
  };
4484
4787
  //# sourceMappingURL=all.js.map