@toolbox-web/grid 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.md +9 -13
  2. package/all.js +1678 -1588
  3. package/all.js.map +1 -1
  4. package/index.js +762 -568
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts +21 -0
  7. package/lib/core/grid.d.ts.map +1 -1
  8. package/lib/core/internal/config-manager.d.ts +1 -0
  9. package/lib/core/internal/config-manager.d.ts.map +1 -1
  10. package/lib/core/internal/dom-builder.d.ts +2 -0
  11. package/lib/core/internal/dom-builder.d.ts.map +1 -1
  12. package/lib/core/internal/header.d.ts.map +1 -1
  13. package/lib/core/internal/keyboard.d.ts.map +1 -1
  14. package/lib/core/internal/resize.d.ts.map +1 -1
  15. package/lib/core/internal/rows.d.ts.map +1 -1
  16. package/lib/core/internal/shell.d.ts +19 -13
  17. package/lib/core/internal/shell.d.ts.map +1 -1
  18. package/lib/core/internal/utils.d.ts +1 -0
  19. package/lib/core/internal/utils.d.ts.map +1 -1
  20. package/lib/core/plugin/base-plugin.d.ts +70 -3
  21. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  22. package/lib/core/plugin/expander-column.d.ts +51 -0
  23. package/lib/core/plugin/expander-column.d.ts.map +1 -0
  24. package/lib/core/plugin/plugin-manager.d.ts +6 -2
  25. package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
  26. package/lib/core/plugin/types.d.ts +117 -1
  27. package/lib/core/plugin/types.d.ts.map +1 -1
  28. package/lib/core/types.d.ts +10 -5
  29. package/lib/core/types.d.ts.map +1 -1
  30. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
  31. package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
  32. package/lib/plugins/clipboard/index.d.ts +1 -1
  33. package/lib/plugins/clipboard/index.d.ts.map +1 -1
  34. package/lib/plugins/clipboard/index.js +295 -190
  35. package/lib/plugins/clipboard/index.js.map +1 -1
  36. package/lib/plugins/clipboard/types.d.ts +72 -2
  37. package/lib/plugins/clipboard/types.d.ts.map +1 -1
  38. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
  39. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
  40. package/lib/plugins/column-virtualization/index.js +143 -56
  41. package/lib/plugins/column-virtualization/index.js.map +1 -1
  42. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
  43. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  44. package/lib/plugins/context-menu/index.js +189 -102
  45. package/lib/plugins/context-menu/index.js.map +1 -1
  46. package/lib/plugins/editing/EditingPlugin.d.ts +2 -7
  47. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  48. package/lib/plugins/editing/index.js +227 -150
  49. package/lib/plugins/editing/index.js.map +1 -1
  50. package/lib/plugins/export/ExportPlugin.d.ts +0 -1
  51. package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
  52. package/lib/plugins/export/index.js +184 -97
  53. package/lib/plugins/export/index.js.map +1 -1
  54. package/lib/plugins/filtering/FilteringPlugin.d.ts +14 -3
  55. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  56. package/lib/plugins/filtering/index.js +296 -176
  57. package/lib/plugins/filtering/index.js.map +1 -1
  58. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
  59. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  60. package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
  61. package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
  62. package/lib/plugins/grouping-columns/index.js +169 -61
  63. package/lib/plugins/grouping-columns/index.js.map +1 -1
  64. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
  65. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
  66. package/lib/plugins/grouping-rows/index.js +243 -140
  67. package/lib/plugins/grouping-rows/index.js.map +1 -1
  68. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
  69. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
  70. package/lib/plugins/master-detail/index.js +278 -196
  71. package/lib/plugins/master-detail/index.js.map +1 -1
  72. package/lib/plugins/master-detail/types.d.ts +0 -10
  73. package/lib/plugins/master-detail/types.d.ts.map +1 -1
  74. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
  75. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
  76. package/lib/plugins/multi-sort/index.js +125 -40
  77. package/lib/plugins/multi-sort/index.js.map +1 -1
  78. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
  79. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  80. package/lib/plugins/pinned-columns/index.js +156 -75
  81. package/lib/plugins/pinned-columns/index.js.map +1 -1
  82. package/lib/plugins/pinned-columns/pinned-columns.d.ts +2 -2
  83. package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
  84. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
  85. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
  86. package/lib/plugins/pinned-rows/index.js +202 -117
  87. package/lib/plugins/pinned-rows/index.js.map +1 -1
  88. package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
  89. package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
  90. package/lib/plugins/pivot/index.js +413 -314
  91. package/lib/plugins/pivot/index.js.map +1 -1
  92. package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
  93. package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
  94. package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
  95. package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
  96. package/lib/plugins/reorder/index.d.ts +1 -1
  97. package/lib/plugins/reorder/index.d.ts.map +1 -1
  98. package/lib/plugins/reorder/index.js +296 -223
  99. package/lib/plugins/reorder/index.js.map +1 -1
  100. package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
  101. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  102. package/lib/plugins/selection/index.d.ts +2 -2
  103. package/lib/plugins/selection/index.d.ts.map +1 -1
  104. package/lib/plugins/selection/index.js +282 -141
  105. package/lib/plugins/selection/index.js.map +1 -1
  106. package/lib/plugins/selection/types.d.ts +24 -0
  107. package/lib/plugins/selection/types.d.ts.map +1 -1
  108. package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
  109. package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
  110. package/lib/plugins/server-side/index.js +96 -9
  111. package/lib/plugins/server-side/index.js.map +1 -1
  112. package/lib/plugins/tree/TreePlugin.d.ts +5 -1
  113. package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
  114. package/lib/plugins/tree/index.js +209 -113
  115. package/lib/plugins/tree/index.js.map +1 -1
  116. package/lib/plugins/tree/types.d.ts +0 -10
  117. package/lib/plugins/tree/types.d.ts.map +1 -1
  118. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
  119. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
  120. package/lib/plugins/undo-redo/index.js +98 -11
  121. package/lib/plugins/undo-redo/index.js.map +1 -1
  122. package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
  123. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  124. package/lib/plugins/visibility/index.js +155 -64
  125. package/lib/plugins/visibility/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/themes/dg-theme-bootstrap.css +55 -53
  128. package/themes/dg-theme-contrast.css +42 -40
  129. package/themes/dg-theme-large.css +38 -37
  130. package/themes/dg-theme-material.css +54 -52
  131. package/themes/dg-theme-standard.css +19 -17
  132. package/themes/dg-theme-vibrant.css +16 -14
  133. package/umd/grid.all.umd.js +23 -24
  134. package/umd/grid.all.umd.js.map +1 -1
  135. package/umd/grid.umd.js +12 -11
  136. package/umd/grid.umd.js.map +1 -1
  137. package/umd/plugins/clipboard.umd.js +5 -7
  138. package/umd/plugins/clipboard.umd.js.map +1 -1
  139. package/umd/plugins/column-virtualization.umd.js +1 -1
  140. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  141. package/umd/plugins/context-menu.umd.js +1 -1
  142. package/umd/plugins/context-menu.umd.js.map +1 -1
  143. package/umd/plugins/editing.umd.js +1 -1
  144. package/umd/plugins/editing.umd.js.map +1 -1
  145. package/umd/plugins/export.umd.js +1 -1
  146. package/umd/plugins/export.umd.js.map +1 -1
  147. package/umd/plugins/filtering.umd.js +1 -1
  148. package/umd/plugins/filtering.umd.js.map +1 -1
  149. package/umd/plugins/grouping-columns.umd.js +1 -1
  150. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  151. package/umd/plugins/grouping-rows.umd.js +1 -1
  152. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  153. package/umd/plugins/master-detail.umd.js +1 -1
  154. package/umd/plugins/master-detail.umd.js.map +1 -1
  155. package/umd/plugins/multi-sort.umd.js +1 -1
  156. package/umd/plugins/multi-sort.umd.js.map +1 -1
  157. package/umd/plugins/pinned-columns.umd.js +1 -1
  158. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  159. package/umd/plugins/pinned-rows.umd.js +1 -1
  160. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  161. package/umd/plugins/pivot.umd.js +1 -1
  162. package/umd/plugins/pivot.umd.js.map +1 -1
  163. package/umd/plugins/reorder.umd.js +1 -1
  164. package/umd/plugins/reorder.umd.js.map +1 -1
  165. package/umd/plugins/selection.umd.js +1 -1
  166. package/umd/plugins/selection.umd.js.map +1 -1
  167. package/umd/plugins/server-side.umd.js +1 -1
  168. package/umd/plugins/server-side.umd.js.map +1 -1
  169. package/umd/plugins/tree.umd.js +1 -1
  170. package/umd/plugins/tree.umd.js.map +1 -1
  171. package/umd/plugins/undo-redo.umd.js +1 -1
  172. package/umd/plugins/undo-redo.umd.js.map +1 -1
  173. package/umd/plugins/visibility.umd.js +1 -1
  174. package/umd/plugins/visibility.umd.js.map +1 -1
  175. package/lib/core/internal/editing.d.ts +0 -76
  176. package/lib/core/internal/editing.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- const E = {
1
+ const L = {
2
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
@@ -25,8 +25,11 @@ class P {
25
25
  * ```
26
26
  */
27
27
  static dependencies;
28
- /** Plugin version - override in subclass if needed */
29
- version = "1.0.0";
28
+ /**
29
+ * Plugin version - defaults to grid version for built-in plugins.
30
+ * Third-party plugins can override with their own semver.
31
+ */
32
+ version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
30
33
  /** CSS styles to inject into the grid's shadow DOM */
31
34
  styles;
32
35
  /** Custom cell renderers keyed by type name */
@@ -113,12 +116,28 @@ class P {
113
116
  emit(e, t) {
114
117
  this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
115
118
  }
119
+ /**
120
+ * Emit a cancelable custom event from the grid.
121
+ * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
122
+ */
123
+ emitCancelable(e, t) {
124
+ const o = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
125
+ return this.grid?.dispatchEvent?.(o), o.defaultPrevented;
126
+ }
116
127
  /**
117
128
  * Request a re-render of the grid.
118
129
  */
119
130
  requestRender() {
120
131
  this.grid?.requestRender?.();
121
132
  }
133
+ /**
134
+ * Request a re-render and restore focus styling afterward.
135
+ * Use this when a plugin action (like expand/collapse) triggers a render
136
+ * but needs to maintain keyboard navigation focus.
137
+ */
138
+ requestRenderWithFocus() {
139
+ this.grid?.requestRenderWithFocus?.();
140
+ }
122
141
  /**
123
142
  * Request a lightweight style update without rebuilding DOM.
124
143
  * Use this instead of requestRender() when only CSS classes need updating.
@@ -153,10 +172,34 @@ class P {
153
172
  return this.grid?._visibleColumns ?? [];
154
173
  }
155
174
  /**
156
- * Get the shadow root of the grid.
175
+ * Get the grid as an HTMLElement for direct DOM operations.
176
+ * Use sparingly - prefer the typed GridElementRef API when possible.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * const width = this.gridElement.clientWidth;
181
+ * this.gridElement.classList.add('my-plugin-active');
182
+ * ```
183
+ */
184
+ get gridElement() {
185
+ return this.grid;
186
+ }
187
+ /**
188
+ * Get the render root of the grid for DOM queries.
189
+ * @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
190
+ *
191
+ * With Shadow DOM removed, the grid element itself is the render root.
192
+ * All new code should use `this.gridElement` for DOM queries.
193
+ *
194
+ * @example
195
+ * // OLD (deprecated)
196
+ * const rows = this.shadowRoot?.querySelector('.rows');
197
+ *
198
+ * // NEW (preferred)
199
+ * const rows = this.gridElement.querySelector('.rows');
157
200
  */
158
201
  get shadowRoot() {
159
- return this.grid?.shadowRoot ?? null;
202
+ return this.gridElement;
160
203
  }
161
204
  /**
162
205
  * Get the disconnect signal for event listener cleanup.
@@ -184,8 +227,53 @@ class P {
184
227
  */
185
228
  get gridIcons() {
186
229
  const e = this.grid?.gridConfig?.icons ?? {};
187
- return { ...E, ...e };
230
+ return { ...L, ...e };
231
+ }
232
+ // #region Animation Helpers
233
+ /**
234
+ * Check if animations are enabled at the grid level.
235
+ * Respects gridConfig.animation.mode and the CSS variable set by the grid.
236
+ *
237
+ * Plugins should use this to skip animations when:
238
+ * - Animation mode is 'off' or `false`
239
+ * - User prefers reduced motion and mode is 'reduced-motion' (default)
240
+ *
241
+ * @example
242
+ * ```ts
243
+ * private get animationStyle(): 'slide' | 'fade' | false {
244
+ * if (!this.isAnimationEnabled) return false;
245
+ * return this.config.animation ?? 'slide';
246
+ * }
247
+ * ```
248
+ */
249
+ get isAnimationEnabled() {
250
+ const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
251
+ if (e === !1 || e === "off") return !1;
252
+ if (e === !0 || e === "on") return !0;
253
+ const t = this.gridElement;
254
+ return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
188
255
  }
256
+ /**
257
+ * Get the animation duration in milliseconds from CSS variable.
258
+ * Falls back to 200ms if not set.
259
+ *
260
+ * Plugins can use this for their animation timing to stay consistent
261
+ * with the grid-level animation.duration setting.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * element.animate(keyframes, { duration: this.animationDuration });
266
+ * ```
267
+ */
268
+ get animationDuration() {
269
+ const e = this.gridElement;
270
+ if (e) {
271
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), o = parseInt(t, 10);
272
+ if (!isNaN(o)) return o;
273
+ }
274
+ return 200;
275
+ }
276
+ // #endregion
189
277
  /**
190
278
  * Resolve an icon value to string or HTMLElement.
191
279
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -218,7 +306,7 @@ class P {
218
306
  const m = {
219
307
  sum: (i, e) => i.reduce((t, o) => t + (Number(o[e]) || 0), 0),
220
308
  avg: (i, e) => {
221
- const t = i.reduce((o, n) => o + (Number(n[e]) || 0), 0);
309
+ const t = i.reduce((o, r) => o + (Number(r[e]) || 0), 0);
222
310
  return i.length ? t / i.length : 0;
223
311
  },
224
312
  count: (i) => i.length,
@@ -226,46 +314,46 @@ const m = {
226
314
  max: (i, e) => Math.max(...i.map((t) => Number(t[e]) || -1 / 0)),
227
315
  first: (i, e) => i[0]?.[e],
228
316
  last: (i, e) => i[i.length - 1]?.[e]
229
- }, v = /* @__PURE__ */ new Map(), h = {
317
+ }, f = /* @__PURE__ */ new Map(), g = {
230
318
  /**
231
319
  * Register a custom aggregator function.
232
320
  */
233
321
  register(i, e) {
234
- v.set(i, e);
322
+ f.set(i, e);
235
323
  },
236
324
  /**
237
325
  * Unregister a custom aggregator function.
238
326
  */
239
327
  unregister(i) {
240
- v.delete(i);
328
+ f.delete(i);
241
329
  },
242
330
  /**
243
331
  * Get an aggregator function by reference.
244
332
  */
245
333
  get(i) {
246
334
  if (i !== void 0)
247
- return typeof i == "function" ? i : v.get(i) ?? m[i];
335
+ return typeof i == "function" ? i : f.get(i) ?? m[i];
248
336
  },
249
337
  /**
250
338
  * Run an aggregator on a set of rows.
251
339
  */
252
340
  run(i, e, t, o) {
253
- const n = this.get(i);
254
- return n ? n(e, t, o) : void 0;
341
+ const r = this.get(i);
342
+ return r ? r(e, t, o) : void 0;
255
343
  },
256
344
  /**
257
345
  * Check if an aggregator exists.
258
346
  */
259
347
  has(i) {
260
- return v.has(i) || i in m;
348
+ return f.has(i) || i in m;
261
349
  },
262
350
  /**
263
351
  * List all available aggregator names.
264
352
  */
265
353
  list() {
266
- return [...Object.keys(m), ...v.keys()];
354
+ return [...Object.keys(m), ...f.keys()];
267
355
  }
268
- }, R = {
356
+ }, A = {
269
357
  sum: (i) => i.reduce((e, t) => e + t, 0),
270
358
  avg: (i) => i.length ? i.reduce((e, t) => e + t, 0) / i.length : 0,
271
359
  count: (i) => i.length,
@@ -274,15 +362,15 @@ const m = {
274
362
  first: (i) => i[0] ?? 0,
275
363
  last: (i) => i[i.length - 1] ?? 0
276
364
  };
277
- function N(i) {
278
- return R[i] ?? R.sum;
365
+ function k(i) {
366
+ return A[i] ?? A.sum;
279
367
  }
280
- h.register.bind(h);
281
- h.unregister.bind(h);
282
- h.get.bind(h);
283
- h.run.bind(h);
284
- h.list.bind(h);
285
- const K = N;
368
+ g.register.bind(g);
369
+ g.unregister.bind(g);
370
+ g.get.bind(g);
371
+ g.run.bind(g);
372
+ g.list.bind(g);
373
+ const N = k;
286
374
  function S(i) {
287
375
  const e = [];
288
376
  return !i.rowGroupFields?.length && !i.columnGroupFields?.length && e.push("At least one row or column group field is required"), i.valueFields?.length || e.push("At least one value field is required"), e;
@@ -290,249 +378,249 @@ function S(i) {
290
378
  function C(i, e) {
291
379
  return [...i, e].join("|");
292
380
  }
293
- function I(i, e) {
294
- const t = e.rowGroupFields ?? [], o = e.columnGroupFields ?? [], n = e.valueFields ?? [], r = V(i, o), s = L(
381
+ function K(i, e) {
382
+ const t = e.rowGroupFields ?? [], o = e.columnGroupFields ?? [], r = e.valueFields ?? [], n = I(i, o), a = E(
295
383
  i,
296
384
  t,
297
385
  o,
298
- r,
299
386
  n,
387
+ r,
300
388
  0,
301
389
  // starting depth
302
390
  ""
303
391
  // parent key prefix
304
- ), a = D(s, r, n), l = Object.values(a).reduce((d, c) => d + c, 0);
392
+ ), s = z(a, n, r), l = Object.values(s).reduce((d, c) => d + c, 0);
305
393
  return {
306
- rows: s,
307
- columnKeys: r,
308
- totals: a,
394
+ rows: a,
395
+ columnKeys: n,
396
+ totals: s,
309
397
  grandTotal: l
310
398
  };
311
399
  }
312
- function V(i, e) {
400
+ function I(i, e) {
313
401
  if (e.length === 0) return ["value"];
314
402
  const t = /* @__PURE__ */ new Set();
315
403
  for (const o of i) {
316
- const n = e.map((r) => String(o[r] ?? "")).join("|");
317
- t.add(n);
404
+ const r = e.map((n) => String(o[n] ?? "")).join("|");
405
+ t.add(r);
318
406
  }
319
407
  return [...t].sort();
320
408
  }
321
- function M(i, e) {
409
+ function V(i, e) {
322
410
  const t = /* @__PURE__ */ new Map();
323
411
  for (const o of i) {
324
- const n = String(o[e] ?? ""), r = t.get(n);
325
- r ? r.push(o) : t.set(n, [o]);
412
+ const r = String(o[e] ?? ""), n = t.get(r);
413
+ n ? n.push(o) : t.set(r, [o]);
326
414
  }
327
415
  return t;
328
416
  }
329
- function L(i, e, t, o, n, r, s) {
330
- const a = [];
417
+ function E(i, e, t, o, r, n, a) {
418
+ const s = [];
331
419
  if (e.length === 0) {
332
- const u = T(i, t, o, n), g = _(u);
333
- return a.push({
334
- rowKey: s || "all",
335
- rowLabel: s || "All",
336
- depth: r,
420
+ const u = _(i, t, o, r), h = R(u);
421
+ return s.push({
422
+ rowKey: a || "all",
423
+ rowLabel: a || "All",
424
+ depth: n,
337
425
  values: u,
338
- total: g,
426
+ total: h,
339
427
  isGroup: !1,
340
428
  rowCount: i.length
341
- }), a;
342
- }
343
- const l = e[0], d = e.slice(1), c = d.length > 0, p = M(i, l);
344
- for (const [u, g] of p) {
345
- const y = s ? `${s}|${u}` : u, F = T(g, t, o, n), k = _(F);
346
- let A;
347
- c && (A = L(
348
- g,
429
+ }), s;
430
+ }
431
+ const l = e[0], d = e.slice(1), c = d.length > 0, p = V(i, l);
432
+ for (const [u, h] of p) {
433
+ const y = a ? `${a}|${u}` : u, x = _(h, t, o, r), G = R(x);
434
+ let F;
435
+ c && (F = E(
436
+ h,
349
437
  d,
350
438
  t,
351
439
  o,
352
- n,
353
- r + 1,
440
+ r,
441
+ n + 1,
354
442
  y
355
- )), a.push({
443
+ )), s.push({
356
444
  rowKey: y,
357
445
  rowLabel: u || "(blank)",
358
- depth: r,
359
- values: F,
360
- total: k,
446
+ depth: n,
447
+ values: x,
448
+ total: G,
361
449
  isGroup: c,
362
- children: A,
363
- rowCount: g.length
450
+ children: F,
451
+ rowCount: h.length
364
452
  });
365
453
  }
366
- return a;
454
+ return s;
367
455
  }
368
- function T(i, e, t, o) {
369
- const n = {};
370
- for (const r of t)
371
- for (const s of o) {
372
- const l = (e.length > 0 ? i.filter((u) => e.map((g) => String(u[g] ?? "")).join("|") === r) : i).map((u) => Number(u[s.field]) || 0), d = K(s.aggFunc), c = l.length > 0 ? d(l) : null, p = C([r], s.field);
373
- n[p] = c;
456
+ function _(i, e, t, o) {
457
+ const r = {};
458
+ for (const n of t)
459
+ for (const a of o) {
460
+ const l = (e.length > 0 ? i.filter((u) => e.map((h) => String(u[h] ?? "")).join("|") === n) : i).map((u) => Number(u[a.field]) || 0), d = N(a.aggFunc), c = l.length > 0 ? d(l) : null, p = C([n], a.field);
461
+ r[p] = c;
374
462
  }
375
- return n;
463
+ return r;
376
464
  }
377
- function _(i) {
465
+ function R(i) {
378
466
  let e = 0;
379
467
  for (const t of Object.values(i))
380
468
  e += t ?? 0;
381
469
  return e;
382
470
  }
383
- function D(i, e, t) {
471
+ function z(i, e, t) {
384
472
  const o = {};
385
- function n(r) {
386
- for (const s of r)
387
- if (!s.isGroup || !s.children?.length)
388
- for (const a of e)
473
+ function r(n) {
474
+ for (const a of n)
475
+ if (!a.isGroup || !a.children?.length)
476
+ for (const s of e)
389
477
  for (const l of t) {
390
- const d = C([a], l.field);
391
- o[d] = (o[d] ?? 0) + (s.values[d] ?? 0);
478
+ const d = C([s], l.field);
479
+ o[d] = (o[d] ?? 0) + (a.values[d] ?? 0);
392
480
  }
393
- else s.children && n(s.children);
481
+ else a.children && r(a.children);
394
482
  }
395
- return n(i), o;
483
+ return r(i), o;
396
484
  }
397
- function H(i, e, t = !0) {
485
+ function D(i, e, t = !0) {
398
486
  const o = [];
399
- function n(r) {
400
- o.push(r);
401
- const s = e ? e.has(r.rowKey) : t;
402
- if (r.children && s)
403
- for (const a of r.children)
404
- n(a);
405
- }
406
- for (const r of i)
407
- n(r);
487
+ function r(n) {
488
+ o.push(n);
489
+ const a = e ? e.has(n.rowKey) : t;
490
+ if (n.children && a)
491
+ for (const s of n.children)
492
+ r(s);
493
+ }
494
+ for (const n of i)
495
+ r(n);
408
496
  return o;
409
497
  }
410
- function w(i) {
498
+ function q(i) {
411
499
  const e = [];
412
500
  function t(o) {
413
501
  if (o.isGroup && e.push(o.rowKey), o.children)
414
- for (const n of o.children)
415
- t(n);
502
+ for (const r of o.children)
503
+ t(r);
416
504
  }
417
505
  for (const o of i)
418
506
  t(o);
419
507
  return e;
420
508
  }
421
- const q = ["sum", "avg", "count", "min", "max", "first", "last"];
422
- function z(i, e, t, o) {
423
- const n = new AbortController(), r = { config: e, callbacks: o, signal: n.signal }, s = document.createElement("div");
424
- return s.className = "tbw-pivot-panel", s.appendChild(f("Options", () => U(t, r))), s.appendChild(f("Row Groups", () => G("rowGroups", r))), s.appendChild(f("Column Groups", () => G("columnGroups", r))), s.appendChild(f("Values", () => Z(r))), s.appendChild(f("Available Fields", () => j(r))), i.appendChild(s), () => {
425
- n.abort(), s.remove();
509
+ const H = ["sum", "avg", "count", "min", "max", "first", "last"];
510
+ function M(i, e, t, o) {
511
+ const r = new AbortController(), n = { config: e, callbacks: o, signal: r.signal }, a = document.createElement("div");
512
+ return a.className = "tbw-pivot-panel", a.appendChild(b("Options", () => W(t, n))), a.appendChild(b("Row Groups", () => T("rowGroups", n))), a.appendChild(b("Column Groups", () => T("columnGroups", n))), a.appendChild(b("Values", () => Z(n))), a.appendChild(b("Available Fields", () => j(n))), i.appendChild(a), () => {
513
+ r.abort(), a.remove();
426
514
  };
427
515
  }
428
- function f(i, e) {
516
+ function b(i, e) {
429
517
  const t = document.createElement("div");
430
518
  t.className = "tbw-pivot-section";
431
519
  const o = document.createElement("div");
432
520
  o.className = "tbw-pivot-section-header", o.textContent = i;
433
- const n = document.createElement("div");
434
- return n.className = "tbw-pivot-section-content", n.appendChild(e()), t.appendChild(o), t.appendChild(n), t;
521
+ const r = document.createElement("div");
522
+ return r.className = "tbw-pivot-section-content", r.appendChild(e()), t.appendChild(o), t.appendChild(r), t;
435
523
  }
436
- function G(i, e) {
437
- const { config: t, callbacks: o, signal: n } = e, r = document.createElement("div");
438
- r.className = "tbw-pivot-drop-zone", r.setAttribute("data-zone", i);
439
- const s = i === "rowGroups" ? t.rowGroupFields ?? [] : t.columnGroupFields ?? [];
440
- if (s.length === 0) {
441
- const a = document.createElement("div");
442
- a.className = "tbw-pivot-placeholder", a.textContent = "Drag fields here or click to add", r.appendChild(a);
524
+ function T(i, e) {
525
+ const { config: t, callbacks: o, signal: r } = e, n = document.createElement("div");
526
+ n.className = "tbw-pivot-drop-zone", n.setAttribute("data-zone", i);
527
+ const a = i === "rowGroups" ? t.rowGroupFields ?? [] : t.columnGroupFields ?? [];
528
+ if (a.length === 0) {
529
+ const s = document.createElement("div");
530
+ s.className = "tbw-pivot-placeholder", s.textContent = "Drag fields here or click to add", n.appendChild(s);
443
531
  } else
444
- for (const a of s)
445
- r.appendChild(O(a, i, e));
446
- return r.addEventListener(
532
+ for (const s of a)
533
+ n.appendChild(O(s, i, e));
534
+ return n.addEventListener(
447
535
  "dragover",
448
- (a) => {
449
- a.preventDefault(), r.classList.add("drag-over");
536
+ (s) => {
537
+ s.preventDefault(), n.classList.add("drag-over");
450
538
  },
451
- { signal: n }
452
- ), r.addEventListener(
539
+ { signal: r }
540
+ ), n.addEventListener(
453
541
  "dragleave",
454
542
  () => {
455
- r.classList.remove("drag-over");
543
+ n.classList.remove("drag-over");
456
544
  },
457
- { signal: n }
458
- ), r.addEventListener(
545
+ { signal: r }
546
+ ), n.addEventListener(
459
547
  "drop",
460
- (a) => {
461
- a.preventDefault(), r.classList.remove("drag-over");
462
- const l = a.dataTransfer?.getData("text/plain");
548
+ (s) => {
549
+ s.preventDefault(), n.classList.remove("drag-over");
550
+ const l = s.dataTransfer?.getData("text/plain");
463
551
  l && o.onAddFieldToZone(l, i);
464
552
  },
465
- { signal: n }
466
- ), r;
553
+ { signal: r }
554
+ ), n;
467
555
  }
468
556
  function O(i, e, t) {
469
- const { callbacks: o, signal: n } = t, r = document.createElement("div");
470
- r.className = "tbw-pivot-field-chip", r.draggable = !0;
471
- const s = o.getAvailableFields().find((d) => d.field === i), a = document.createElement("span");
472
- a.className = "tbw-pivot-chip-label", a.textContent = s?.header ?? i;
557
+ const { callbacks: o, signal: r } = t, n = document.createElement("div");
558
+ n.className = "tbw-pivot-field-chip", n.draggable = !0;
559
+ const a = o.getAvailableFields().find((d) => d.field === i), s = document.createElement("span");
560
+ s.className = "tbw-pivot-chip-label", s.textContent = a?.header ?? i;
473
561
  const l = document.createElement("button");
474
562
  return l.className = "tbw-pivot-chip-remove", l.innerHTML = "×", l.title = "Remove field", l.addEventListener(
475
563
  "click",
476
564
  (d) => {
477
565
  d.stopPropagation(), o.onRemoveFieldFromZone(i, e);
478
566
  },
479
- { signal: n }
480
- ), r.appendChild(a), r.appendChild(l), r.addEventListener(
567
+ { signal: r }
568
+ ), n.appendChild(s), n.appendChild(l), n.addEventListener(
481
569
  "dragstart",
482
570
  (d) => {
483
- d.dataTransfer?.setData("text/plain", i), d.dataTransfer?.setData("source-zone", e), r.classList.add("dragging");
571
+ d.dataTransfer?.setData("text/plain", i), d.dataTransfer?.setData("source-zone", e), n.classList.add("dragging");
484
572
  },
485
- { signal: n }
486
- ), r.addEventListener(
573
+ { signal: r }
574
+ ), n.addEventListener(
487
575
  "dragend",
488
576
  () => {
489
- r.classList.remove("dragging");
577
+ n.classList.remove("dragging");
490
578
  },
491
- { signal: n }
492
- ), r;
579
+ { signal: r }
580
+ ), n;
493
581
  }
494
582
  function Z(i) {
495
- const { config: e, callbacks: t, signal: o } = i, n = document.createElement("div");
496
- n.className = "tbw-pivot-drop-zone tbw-pivot-values-zone", n.setAttribute("data-zone", "values");
497
- const r = e.valueFields ?? [];
498
- if (r.length === 0) {
499
- const s = document.createElement("div");
500
- s.className = "tbw-pivot-placeholder", s.textContent = "Drag numeric fields here for aggregation", n.appendChild(s);
583
+ const { config: e, callbacks: t, signal: o } = i, r = document.createElement("div");
584
+ r.className = "tbw-pivot-drop-zone tbw-pivot-values-zone", r.setAttribute("data-zone", "values");
585
+ const n = e.valueFields ?? [];
586
+ if (n.length === 0) {
587
+ const a = document.createElement("div");
588
+ a.className = "tbw-pivot-placeholder", a.textContent = "Drag numeric fields here for aggregation", r.appendChild(a);
501
589
  } else
502
- for (const s of r)
503
- n.appendChild($(s, i));
504
- return n.addEventListener(
590
+ for (const a of n)
591
+ r.appendChild($(a, i));
592
+ return r.addEventListener(
505
593
  "dragover",
506
- (s) => {
507
- s.preventDefault(), n.classList.add("drag-over");
594
+ (a) => {
595
+ a.preventDefault(), r.classList.add("drag-over");
508
596
  },
509
597
  { signal: o }
510
- ), n.addEventListener(
598
+ ), r.addEventListener(
511
599
  "dragleave",
512
600
  () => {
513
- n.classList.remove("drag-over");
601
+ r.classList.remove("drag-over");
514
602
  },
515
603
  { signal: o }
516
- ), n.addEventListener(
604
+ ), r.addEventListener(
517
605
  "drop",
518
- (s) => {
519
- s.preventDefault(), n.classList.remove("drag-over");
520
- const a = s.dataTransfer?.getData("text/plain");
521
- a && t.onAddValueField(a, "sum");
606
+ (a) => {
607
+ a.preventDefault(), r.classList.remove("drag-over");
608
+ const s = a.dataTransfer?.getData("text/plain");
609
+ s && t.onAddValueField(s, "sum");
522
610
  },
523
611
  { signal: o }
524
- ), n;
612
+ ), r;
525
613
  }
526
614
  function $(i, e) {
527
- const { callbacks: t, signal: o } = e, n = document.createElement("div");
528
- n.className = "tbw-pivot-field-chip tbw-pivot-value-chip";
529
- const r = t.getAvailableFields().find((c) => c.field === i.field), s = document.createElement("div");
530
- s.className = "tbw-pivot-value-label-wrapper";
531
- const a = document.createElement("span");
532
- a.className = "tbw-pivot-chip-label", a.textContent = r?.header ?? i.field;
615
+ const { callbacks: t, signal: o } = e, r = document.createElement("div");
616
+ r.className = "tbw-pivot-field-chip tbw-pivot-value-chip";
617
+ const n = t.getAvailableFields().find((c) => c.field === i.field), a = document.createElement("div");
618
+ a.className = "tbw-pivot-value-label-wrapper";
619
+ const s = document.createElement("span");
620
+ s.className = "tbw-pivot-chip-label", s.textContent = n?.header ?? i.field;
533
621
  const l = document.createElement("select");
534
622
  l.className = "tbw-pivot-agg-select", l.title = "Aggregation function";
535
- for (const c of q) {
623
+ for (const c of H) {
536
624
  const p = document.createElement("option");
537
625
  p.value = c, p.textContent = c.toUpperCase(), p.selected = c === i.aggFunc, l.appendChild(p);
538
626
  }
@@ -550,21 +638,21 @@ function $(i, e) {
550
638
  c.stopPropagation(), t.onRemoveValueField(i.field);
551
639
  },
552
640
  { signal: o }
553
- ), s.appendChild(a), s.appendChild(l), n.appendChild(s), n.appendChild(d), n;
641
+ ), a.appendChild(s), a.appendChild(l), r.appendChild(a), r.appendChild(d), r;
554
642
  }
555
643
  function j(i) {
556
- const { config: e, callbacks: t, signal: o } = i, n = document.createElement("div");
557
- n.className = "tbw-pivot-available-fields";
558
- const r = t.getAvailableFields(), s = /* @__PURE__ */ new Set([
644
+ const { config: e, callbacks: t, signal: o } = i, r = document.createElement("div");
645
+ r.className = "tbw-pivot-available-fields";
646
+ const n = t.getAvailableFields(), a = /* @__PURE__ */ new Set([
559
647
  ...e.rowGroupFields ?? [],
560
648
  ...e.columnGroupFields ?? [],
561
649
  ...e.valueFields?.map((l) => l.field) ?? []
562
- ]), a = r.filter((l) => !s.has(l.field));
563
- if (a.length === 0) {
650
+ ]), s = n.filter((l) => !a.has(l.field));
651
+ if (s.length === 0) {
564
652
  const l = document.createElement("div");
565
- l.className = "tbw-pivot-placeholder", l.textContent = "All fields are in use", n.appendChild(l);
653
+ l.className = "tbw-pivot-placeholder", l.textContent = "All fields are in use", r.appendChild(l);
566
654
  } else
567
- for (const l of a) {
655
+ for (const l of s) {
568
656
  const d = document.createElement("div");
569
657
  d.className = "tbw-pivot-field-chip available", d.textContent = l.header, d.draggable = !0, d.title = `Drag to add "${l.field}" to a zone`, d.addEventListener(
570
658
  "dragstart",
@@ -578,102 +666,102 @@ function j(i) {
578
666
  d.classList.remove("dragging");
579
667
  },
580
668
  { signal: o }
581
- ), n.appendChild(d);
669
+ ), r.appendChild(d);
582
670
  }
583
- return n;
671
+ return r;
584
672
  }
585
- function U(i, e) {
586
- const { config: t, callbacks: o, signal: n } = e, r = document.createElement("div");
587
- return r.className = "tbw-pivot-options", r.appendChild(
588
- x(
673
+ function W(i, e) {
674
+ const { config: t, callbacks: o, signal: r } = e, n = document.createElement("div");
675
+ return n.className = "tbw-pivot-options", n.appendChild(
676
+ w(
589
677
  "Enable Pivot View",
590
678
  i,
591
- (s) => {
592
- o.onTogglePivot(s);
679
+ (a) => {
680
+ o.onTogglePivot(a);
593
681
  },
594
- n
682
+ r
595
683
  )
596
- ), r.appendChild(
597
- x(
684
+ ), n.appendChild(
685
+ w(
598
686
  "Show Row Totals",
599
687
  t.showTotals ?? !0,
600
- (s) => {
601
- o.onOptionChange("showTotals", s);
688
+ (a) => {
689
+ o.onOptionChange("showTotals", a);
602
690
  },
603
- n
691
+ r
604
692
  )
605
- ), r.appendChild(
606
- x(
693
+ ), n.appendChild(
694
+ w(
607
695
  "Show Grand Total",
608
696
  t.showGrandTotal ?? !0,
609
- (s) => {
610
- o.onOptionChange("showGrandTotal", s);
697
+ (a) => {
698
+ o.onOptionChange("showGrandTotal", a);
611
699
  },
612
- n
700
+ r
613
701
  )
614
- ), r;
702
+ ), n;
615
703
  }
616
- function x(i, e, t, o) {
617
- const n = document.createElement("label");
618
- n.className = "tbw-pivot-checkbox";
619
- const r = document.createElement("input");
620
- r.type = "checkbox", r.checked = e, r.addEventListener("change", () => t(r.checked), { signal: o });
621
- const s = document.createElement("span");
622
- return s.textContent = i, n.appendChild(r), n.appendChild(s), n;
704
+ function w(i, e, t, o) {
705
+ const r = document.createElement("label");
706
+ r.className = "tbw-pivot-checkbox";
707
+ const n = document.createElement("input");
708
+ n.type = "checkbox", n.checked = e, n.addEventListener("change", () => t(n.checked), { signal: o });
709
+ const a = document.createElement("span");
710
+ return a.textContent = i, r.appendChild(n), r.appendChild(a), r;
623
711
  }
624
- function B(i, e, t) {
625
- return e.className = "pivot-group-row", e.setAttribute("data-pivot-depth", String(i.__pivotDepth ?? 0)), e.setAttribute("data-pivot-key", String(i.__pivotRowKey ?? "")), e.setAttribute("role", "row"), e.innerHTML = "", t.columns.forEach((o, n) => {
626
- const r = document.createElement("div");
627
- if (r.className = "cell", r.setAttribute("data-col", String(n)), r.setAttribute("role", "gridcell"), n === 0) {
628
- const s = Number(i.__pivotIndent) || 0;
629
- r.style.paddingLeft = `${s}px`;
630
- const a = String(i.__pivotRowKey), l = document.createElement("button");
712
+ function U(i, e, t) {
713
+ return e.className = "data-grid-row pivot-group-row", e.setAttribute("data-pivot-depth", String(i.__pivotDepth ?? 0)), e.setAttribute("data-pivot-key", String(i.__pivotRowKey ?? "")), e.setAttribute("role", "row"), e.innerHTML = "", t.columns.forEach((o, r) => {
714
+ const n = document.createElement("div");
715
+ if (n.className = "cell", n.setAttribute("data-col", String(r)), n.setAttribute("data-row", String(t.rowIndex)), n.setAttribute("role", "gridcell"), r === 0) {
716
+ const a = Number(i.__pivotIndent) || 0;
717
+ n.style.paddingLeft = `${a}px`;
718
+ const s = String(i.__pivotRowKey), l = document.createElement("button");
631
719
  l.type = "button", l.className = "pivot-toggle", l.setAttribute("aria-label", i.__pivotExpanded ? "Collapse group" : "Expand group"), t.setIcon(l, t.resolveIcon(i.__pivotExpanded ? "collapse" : "expand")), l.addEventListener("click", (p) => {
632
- p.stopPropagation(), t.onToggle(a);
633
- }), r.appendChild(l);
720
+ p.stopPropagation(), t.onToggle(s);
721
+ }), n.appendChild(l);
634
722
  const d = document.createElement("span");
635
- d.className = "pivot-label", d.textContent = String(i.__pivotLabel ?? ""), r.appendChild(d);
723
+ d.className = "pivot-label", d.textContent = String(i.__pivotLabel ?? ""), n.appendChild(d);
636
724
  const c = document.createElement("span");
637
- c.className = "pivot-count", c.textContent = ` (${Number(i.__pivotRowCount) || 0})`, r.appendChild(c);
725
+ c.className = "pivot-count", c.textContent = ` (${Number(i.__pivotRowCount) || 0})`, n.appendChild(c);
638
726
  } else {
639
- const s = i[o.field];
640
- r.textContent = s != null ? String(s) : "";
727
+ const a = i[o.field];
728
+ n.textContent = a != null ? String(a) : "";
641
729
  }
642
- e.appendChild(r);
730
+ e.appendChild(n);
643
731
  }), !0;
644
732
  }
645
- function W(i, e, t) {
646
- return e.className = "pivot-leaf-row", e.setAttribute("data-pivot-depth", String(i.__pivotDepth ?? 0)), e.setAttribute("data-pivot-key", String(i.__pivotRowKey ?? "")), e.innerHTML = "", t.forEach((o, n) => {
647
- const r = document.createElement("div");
648
- if (r.className = "cell", r.setAttribute("data-col", String(n)), r.setAttribute("role", "gridcell"), n === 0) {
733
+ function B(i, e, t, o) {
734
+ return e.className = "data-grid-row pivot-leaf-row", e.setAttribute("data-pivot-depth", String(i.__pivotDepth ?? 0)), e.setAttribute("data-pivot-key", String(i.__pivotRowKey ?? "")), e.innerHTML = "", t.forEach((r, n) => {
735
+ const a = document.createElement("div");
736
+ if (a.className = "cell", a.setAttribute("data-col", String(n)), a.setAttribute("data-row", String(o)), a.setAttribute("role", "gridcell"), n === 0) {
649
737
  const s = Number(i.__pivotIndent) || 0;
650
- r.style.paddingLeft = `${s + 20}px`;
651
- const a = document.createElement("span");
652
- a.className = "pivot-label", a.textContent = String(i.__pivotLabel ?? ""), r.appendChild(a);
738
+ a.style.paddingLeft = `${s + 20}px`;
739
+ const l = document.createElement("span");
740
+ l.className = "pivot-label", l.textContent = String(i.__pivotLabel ?? ""), a.appendChild(l);
653
741
  } else {
654
- const s = i[o.field];
655
- r.textContent = s != null ? String(s) : "";
742
+ const s = i[r.field];
743
+ a.textContent = s != null ? String(s) : "";
656
744
  }
657
- e.appendChild(r);
745
+ e.appendChild(a);
658
746
  }), !0;
659
747
  }
660
748
  function J(i, e, t) {
661
- return e.className = "pivot-grand-total-row", e.setAttribute("role", "presentation"), e.innerHTML = "", t.forEach((o, n) => {
662
- const r = document.createElement("div");
663
- if (r.className = "cell", r.setAttribute("data-col", String(n)), n === 0) {
664
- const s = document.createElement("span");
665
- s.className = "pivot-label", s.textContent = "Grand Total", r.appendChild(s);
749
+ return e.className = "pivot-grand-total-row", e.setAttribute("role", "presentation"), e.innerHTML = "", t.forEach((o, r) => {
750
+ const n = document.createElement("div");
751
+ if (n.className = "cell", n.setAttribute("data-col", String(r)), r === 0) {
752
+ const a = document.createElement("span");
753
+ a.className = "pivot-label", a.textContent = "Grand Total", n.appendChild(a);
666
754
  } else {
667
- const s = i[o.field];
668
- r.textContent = s != null ? String(s) : "";
755
+ const a = i[o.field];
756
+ n.textContent = a != null ? String(a) : "";
669
757
  }
670
- e.appendChild(r);
758
+ e.appendChild(n);
671
759
  }), !0;
672
760
  }
673
- const Q = '.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}}';
674
- class b extends P {
761
+ const Q = '@layer tbw-plugins{.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:var(--tbw-panel-padding, var(--tbw-spacing-lg, .75rem));padding:var(--tbw-panel-padding, var(--tbw-spacing-lg, .75rem));height:100%;overflow-y:auto;font-size:var(--tbw-font-size-sm, .8125rem)}.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:var(--tbw-button-padding, var(--tbw-spacing-md, .5rem) var(--tbw-spacing-lg, .75rem));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:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-pivot-toggle-wrapper{display:flex;align-items:center}.tbw-pivot-toggle-label{display:flex;align-items:center;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));cursor:pointer}.tbw-pivot-toggle-label input{width:var(--tbw-icon-size, 1rem);height:var(--tbw-icon-size, 1rem);cursor:pointer}.tbw-pivot-drop-zone{min-height:60px;padding:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));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:var(--tbw-spacing-sm, .375rem);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:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));text-align:center;width:100%}.tbw-pivot-field-chip{display:inline-flex;align-items:center;gap:var(--tbw-spacing-sm, .375rem);padding:var(--tbw-button-padding-sm, var(--tbw-spacing-xs, .25rem) var(--tbw-spacing-md, .5rem));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:var(--tbw-font-size-xs, .75rem);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:var(--tbw-icon-size, 1rem);height:var(--tbw-icon-size, 1rem);padding:0;border:none;background:transparent;color:var(--tbw-color-fg-muted);font-size:var(--tbw-font-size-sm, .875rem);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:var(--tbw-button-padding-sm, var(--tbw-spacing-xs, .25rem) var(--tbw-spacing-md, .5rem))}.tbw-pivot-value-label-wrapper{display:flex;align-items:center;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));flex:1;min-width:0}.tbw-pivot-agg-select{padding:var(--tbw-spacing-xs, .125rem) var(--tbw-spacing-xs, .25rem);font-size:var(--tbw-font-size-xs, .6875rem);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:var(--tbw-spacing-sm, .375rem);min-height:40px}.tbw-pivot-options{display:flex;flex-direction:column;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-pivot-checkbox{display:flex;align-items:center;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));cursor:pointer}.tbw-pivot-checkbox input{width:var(--tbw-icon-size-sm, .875rem);height:var(--tbw-icon-size-sm, .875rem);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}}}';
762
+ class v extends P {
675
763
  name = "pivot";
676
- version = "1.0.0";
764
+ styles = Q;
677
765
  /** Tool panel ID for shell integration */
678
766
  static PANEL_ID = "pivot";
679
767
  get defaultConfig() {
@@ -704,17 +792,11 @@ class b extends P {
704
792
  return (this.config.valueFields?.length ?? 0) > 0;
705
793
  }
706
794
  /**
707
- * Get animation style respecting grid-level animation mode.
795
+ * Get expand/collapse animation style from plugin config.
796
+ * Uses base class isAnimationEnabled to respect grid-level settings.
708
797
  */
709
798
  get animationStyle() {
710
- const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
711
- if (t === !1 || t === "off") return !1;
712
- if (t !== !0 && t !== "on") {
713
- const o = this.shadowRoot?.host;
714
- if (o && getComputedStyle(o).getPropertyValue("--tbw-animation-enabled").trim() === "0")
715
- return !1;
716
- }
717
- return this.config.animation ?? "slide";
799
+ return this.isAnimationEnabled ? this.config.animation ?? "slide" : !1;
718
800
  }
719
801
  // #endregion
720
802
  // #region Lifecycle
@@ -726,7 +808,7 @@ class b extends P {
726
808
  getToolPanel() {
727
809
  if ((this.config?.showToolPanel ?? this.userConfig?.showToolPanel ?? !0) !== !1)
728
810
  return {
729
- id: b.PANEL_ID,
811
+ id: v.PANEL_ID,
730
812
  title: "Pivot",
731
813
  icon: "⊞",
732
814
  tooltip: "Configure pivot table",
@@ -742,55 +824,46 @@ class b extends P {
742
824
  const t = S(this.config);
743
825
  if (t.length > 0)
744
826
  return this.warn(`Config errors: ${t.join(", ")}`), [...e];
745
- if (this.buildFieldHeaderMap(), this.defaultExpanded = this.config.defaultExpanded ?? !0, this.expandedKeys.size === 0 && this.defaultExpanded && this.pivotResult) {
746
- const s = w(this.pivotResult.rows);
747
- for (const a of s)
748
- this.expandedKeys.add(a);
749
- }
750
- if (this.pivotResult = I(e, this.config), this.expandedKeys.size === 0 && this.defaultExpanded) {
751
- const s = w(this.pivotResult.rows);
752
- for (const a of s)
753
- this.expandedKeys.add(a);
754
- }
755
- const o = this.config.indentWidth ?? 20, n = H(
827
+ this.buildFieldHeaderMap(), this.defaultExpanded = this.config.defaultExpanded ?? !0, this.expandedKeys.size === 0 && this.defaultExpanded && this.pivotResult && this.expandAllKeys(), this.pivotResult = K(e, this.config), this.expandedKeys.size === 0 && this.defaultExpanded && this.expandAllKeys();
828
+ const o = this.config.indentWidth ?? 20, r = D(
756
829
  this.pivotResult.rows,
757
830
  this.expandedKeys,
758
831
  this.defaultExpanded
759
- ).map((s) => ({
760
- __pivotRowKey: s.rowKey,
761
- __pivotLabel: s.rowLabel,
762
- __pivotDepth: s.depth,
763
- __pivotIsGroup: s.isGroup,
764
- __pivotHasChildren: !!s.children?.length,
765
- __pivotExpanded: this.expandedKeys.has(s.rowKey),
766
- __pivotRowCount: s.rowCount ?? 0,
767
- __pivotIndent: s.depth * o,
768
- __pivotTotal: s.total,
769
- ...s.values
832
+ ).map((a) => ({
833
+ __pivotRowKey: a.rowKey,
834
+ __pivotLabel: a.rowLabel,
835
+ __pivotDepth: a.depth,
836
+ __pivotIsGroup: a.isGroup,
837
+ __pivotHasChildren: !!a.children?.length,
838
+ __pivotExpanded: this.expandedKeys.has(a.rowKey),
839
+ __pivotRowCount: a.rowCount ?? 0,
840
+ __pivotIndent: a.depth * o,
841
+ __pivotTotal: a.total,
842
+ ...a.values
770
843
  }));
771
844
  this.keysToAnimate.clear();
772
- const r = /* @__PURE__ */ new Set();
773
- for (const s of n) {
774
- const a = s.__pivotRowKey;
775
- r.add(a), !this.previousVisibleKeys.has(a) && s.__pivotDepth > 0 && this.keysToAnimate.add(a);
845
+ const n = /* @__PURE__ */ new Set();
846
+ for (const a of r) {
847
+ const s = a.__pivotRowKey;
848
+ n.add(s), !this.previousVisibleKeys.has(s) && a.__pivotDepth > 0 && this.keysToAnimate.add(s);
776
849
  }
777
- return this.previousVisibleKeys = r, n;
850
+ return this.previousVisibleKeys = n, r;
778
851
  }
779
852
  processColumns(e) {
780
853
  if (!this.isActive || !this.pivotResult)
781
854
  return [...e];
782
- const t = [], o = (this.config.rowGroupFields ?? []).map((n) => this.fieldHeaderMap.get(n) ?? n).join(" / ");
855
+ const t = [], o = (this.config.rowGroupFields ?? []).map((r) => this.fieldHeaderMap.get(r) ?? r).join(" / ");
783
856
  t.push({
784
857
  field: "__pivotLabel",
785
858
  header: o || "Group",
786
859
  width: 200
787
860
  });
788
- for (const n of this.pivotResult.columnKeys)
789
- for (const r of this.config.valueFields ?? []) {
790
- const s = C([n], r.field), a = r.header || this.fieldHeaderMap.get(r.field) || r.field;
861
+ for (const r of this.pivotResult.columnKeys)
862
+ for (const n of this.config.valueFields ?? []) {
863
+ const a = C([r], n.field), s = n.header || this.fieldHeaderMap.get(n.field) || n.field;
791
864
  t.push({
792
- field: s,
793
- header: `${n} - ${a} (${r.aggFunc})`,
865
+ field: a,
866
+ header: `${r} - ${s} (${n.aggFunc})`,
794
867
  width: 120,
795
868
  type: "number"
796
869
  });
@@ -802,14 +875,15 @@ class b extends P {
802
875
  type: "number"
803
876
  }), t;
804
877
  }
805
- renderRow(e, t) {
806
- const o = e;
807
- return o.__pivotRowKey && o.__pivotHasChildren ? B(o, t, {
878
+ renderRow(e, t, o) {
879
+ const r = e;
880
+ return r.__pivotRowKey && r.__pivotHasChildren ? U(r, t, {
808
881
  columns: this.gridColumns,
882
+ rowIndex: o,
809
883
  onToggle: (n) => this.toggle(n),
810
884
  resolveIcon: (n) => this.resolveIcon(n),
811
- setIcon: (n, r) => this.setIcon(n, r)
812
- }) : o.__pivotRowKey !== void 0 && this.isActive ? W(o, t, this.gridColumns) : (this.cleanupPivotStyling(t), !1);
885
+ setIcon: (n, a) => this.setIcon(n, a)
886
+ }) : r.__pivotRowKey !== void 0 && this.isActive ? B(r, t, this.gridColumns, o) : (this.cleanupPivotStyling(t), !1);
813
887
  }
814
888
  /**
815
889
  * Remove pivot-specific classes, attributes, and inline styles from a row element.
@@ -819,16 +893,22 @@ class b extends P {
819
893
  cleanupPivotStyling(e) {
820
894
  (e.classList.contains("pivot-group-row") || e.classList.contains("pivot-leaf-row") || e.classList.contains("pivot-grand-total-row")) && (e.classList.remove("pivot-group-row", "pivot-leaf-row", "pivot-grand-total-row"), e.classList.add("data-grid-row"), e.removeAttribute("data-pivot-depth"), e.innerHTML = "");
821
895
  }
896
+ onKeyDown(e) {
897
+ if (e.key !== " " || !this.isActive) return;
898
+ const t = this.grid._focusRow, o = this.rows[t];
899
+ if (!(!o?.__pivotIsGroup || !o.__pivotHasChildren))
900
+ return e.preventDefault(), this.toggle(o.__pivotRowKey), this.requestRenderWithFocus(), !0;
901
+ }
822
902
  afterRender() {
823
903
  this.isActive && this.config.showGrandTotal && this.pivotResult ? this.renderGrandTotalFooter() : this.cleanupGrandTotalFooter();
824
904
  const e = this.animationStyle;
825
905
  if (e === !1 || this.keysToAnimate.size === 0) return;
826
- const t = this.shadowRoot?.querySelector(".rows");
906
+ const t = this.gridElement?.querySelector(".rows");
827
907
  if (!t) return;
828
908
  const o = e === "fade" ? "tbw-pivot-fade-in" : "tbw-pivot-slide-in";
829
- for (const n of t.querySelectorAll(".pivot-group-row, .pivot-leaf-row")) {
830
- const r = n.dataset.pivotKey;
831
- r && this.keysToAnimate.has(r) && (n.classList.add(o), n.addEventListener("animationend", () => n.classList.remove(o), { once: !0 }));
909
+ for (const r of t.querySelectorAll(".pivot-group-row, .pivot-leaf-row")) {
910
+ const n = r.dataset.pivotKey;
911
+ n && this.keysToAnimate.has(n) && (r.classList.add(o), r.addEventListener("animationend", () => r.classList.remove(o), { once: !0 }));
832
912
  }
833
913
  this.keysToAnimate.clear();
834
914
  }
@@ -837,7 +917,7 @@ class b extends P {
837
917
  */
838
918
  renderGrandTotalFooter() {
839
919
  if (!this.pivotResult) return;
840
- const e = this.shadowRoot;
920
+ const e = this.gridElement;
841
921
  if (!e) return;
842
922
  const t = e.querySelector(".tbw-scroll-area") ?? e.querySelector(".tbw-grid-content") ?? e.children[0];
843
923
  if (!t) return;
@@ -869,16 +949,20 @@ class b extends P {
869
949
  this.expandedKeys.delete(e), this.requestRender();
870
950
  }
871
951
  expandAll() {
872
- if (this.pivotResult) {
873
- const e = w(this.pivotResult.rows);
874
- for (const t of e)
875
- this.expandedKeys.add(t);
876
- this.requestRender();
877
- }
952
+ this.expandAllKeys(), this.requestRender();
878
953
  }
879
954
  collapseAll() {
880
955
  this.expandedKeys.clear(), this.requestRender();
881
956
  }
957
+ /**
958
+ * Add all group keys from the current pivot result to expandedKeys.
959
+ */
960
+ expandAllKeys() {
961
+ if (!this.pivotResult) return;
962
+ const e = q(this.pivotResult.rows);
963
+ for (const t of e)
964
+ this.expandedKeys.add(t);
965
+ }
882
966
  isExpanded(e) {
883
967
  return this.expandedKeys.has(e);
884
968
  }
@@ -910,23 +994,42 @@ class b extends P {
910
994
  }
911
995
  // #endregion
912
996
  // #region Tool Panel API
997
+ /**
998
+ * Show the pivot tool panel.
999
+ * Opens the tool panel and ensures this section is expanded.
1000
+ */
913
1001
  showPanel() {
914
- this.grid.openToolPanel(b.PANEL_ID);
1002
+ this.grid.openToolPanel(), this.grid.expandedToolPanelSections.includes(v.PANEL_ID) || this.grid.toggleToolPanelSection(v.PANEL_ID);
915
1003
  }
1004
+ /**
1005
+ * Hide the tool panel.
1006
+ */
916
1007
  hidePanel() {
917
1008
  this.grid.closeToolPanel();
918
1009
  }
1010
+ /**
1011
+ * Toggle the pivot tool panel section.
1012
+ */
919
1013
  togglePanel() {
920
- this.grid.toggleToolPanel(b.PANEL_ID);
1014
+ this.grid.isToolPanelOpen || this.grid.openToolPanel(), this.grid.toggleToolPanelSection(v.PANEL_ID);
921
1015
  }
1016
+ /**
1017
+ * Check if the pivot panel section is currently expanded.
1018
+ */
922
1019
  isPanelVisible() {
923
- return this.grid.activeToolPanel === b.PANEL_ID;
1020
+ return this.grid.isToolPanelOpen && this.grid.expandedToolPanelSections.includes(v.PANEL_ID);
924
1021
  }
925
1022
  // #endregion
926
1023
  // #region Private Helpers
927
1024
  get gridColumns() {
928
1025
  return this.grid.columns ?? [];
929
1026
  }
1027
+ /**
1028
+ * Refresh pivot and update tool panel if active.
1029
+ */
1030
+ refreshIfActive() {
1031
+ this.isActive && this.refresh(), this.refreshPanel();
1032
+ }
930
1033
  buildFieldHeaderMap() {
931
1034
  const e = this.getAvailableFields();
932
1035
  this.fieldHeaderMap.clear();
@@ -937,12 +1040,11 @@ class b extends P {
937
1040
  return this.originalColumns.length > 0 ? this.originalColumns : this.captureOriginalColumns();
938
1041
  }
939
1042
  captureOriginalColumns() {
940
- const e = this.grid;
941
1043
  try {
942
- const t = e.getAllColumns?.() ?? e.columns ?? [];
943
- return this.originalColumns = t.filter((o) => !o.field.startsWith("__pivot")).map((o) => ({
944
- field: o.field,
945
- header: o.header ?? o.field
1044
+ const e = this.grid.getAllColumns?.() ?? this.grid.columns ?? [];
1045
+ return this.originalColumns = e.filter((t) => !t.field.startsWith("__pivot")).map((t) => ({
1046
+ field: t.field,
1047
+ header: t.header ?? t.field
946
1048
  })), this.originalColumns;
947
1049
  } catch {
948
1050
  return [];
@@ -954,17 +1056,17 @@ class b extends P {
954
1056
  onTogglePivot: (o) => {
955
1057
  o ? this.enablePivot() : this.disablePivot(), this.refreshPanel();
956
1058
  },
957
- onAddFieldToZone: (o, n) => this.addFieldToZone(o, n),
958
- onRemoveFieldFromZone: (o, n) => this.removeFieldFromZone(o, n),
959
- onAddValueField: (o, n) => this.addValueField(o, n),
1059
+ onAddFieldToZone: (o, r) => this.addFieldToZone(o, r),
1060
+ onRemoveFieldFromZone: (o, r) => this.removeFieldFromZone(o, r),
1061
+ onAddValueField: (o, r) => this.addValueField(o, r),
960
1062
  onRemoveValueField: (o) => this.removeValueField(o),
961
- onUpdateValueAggFunc: (o, n) => this.updateValueAggFunc(o, n),
962
- onOptionChange: (o, n) => {
963
- this.config[o] = n, this.isActive && this.refresh();
1063
+ onUpdateValueAggFunc: (o, r) => this.updateValueAggFunc(o, r),
1064
+ onOptionChange: (o, r) => {
1065
+ this.config[o] = r, this.isActive && this.refresh();
964
1066
  },
965
1067
  getAvailableFields: () => this.getAvailableFields()
966
1068
  };
967
- return z(e, this.config, this.isActive, t);
1069
+ return M(e, this.config, this.isActive, t);
968
1070
  }
969
1071
  refreshPanel() {
970
1072
  this.panelContainer && (this.panelContainer.innerHTML = "", this.renderPanel(this.panelContainer));
@@ -977,31 +1079,28 @@ class b extends P {
977
1079
  const o = this.config.columnGroupFields ?? [];
978
1080
  o.includes(e) || (this.config.columnGroupFields = [...o, e]);
979
1081
  }
980
- this.removeFromOtherZones(e, t), this.isActive && this.refresh(), this.refreshPanel();
1082
+ this.removeFromOtherZones(e, t), this.refreshIfActive();
981
1083
  }
982
1084
  removeFieldFromZone(e, t) {
983
- t === "rowGroups" ? this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((o) => o !== e) : this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((o) => o !== e), this.isActive && this.refresh(), this.refreshPanel();
1085
+ t === "rowGroups" ? this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((o) => o !== e) : this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((o) => o !== e), this.refreshIfActive();
984
1086
  }
985
1087
  removeFromOtherZones(e, t) {
986
1088
  t !== "rowGroups" && (this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((o) => o !== e)), t !== "columnGroups" && (this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((o) => o !== e)), t !== "values" && (this.config.valueFields = (this.config.valueFields ?? []).filter((o) => o.field !== e));
987
1089
  }
988
1090
  addValueField(e, t) {
989
1091
  const o = this.config.valueFields ?? [];
990
- o.some((n) => n.field === e) || (this.config.valueFields = [...o, { field: e, aggFunc: t }]), this.removeFromOtherZones(e, "values"), this.isActive && this.refresh(), this.refreshPanel();
1092
+ o.some((r) => r.field === e) || (this.config.valueFields = [...o, { field: e, aggFunc: t }]), this.removeFromOtherZones(e, "values"), this.refreshIfActive();
991
1093
  }
992
1094
  removeValueField(e) {
993
- this.config.valueFields = (this.config.valueFields ?? []).filter((t) => t.field !== e), this.isActive && this.refresh(), this.refreshPanel();
1095
+ this.config.valueFields = (this.config.valueFields ?? []).filter((t) => t.field !== e), this.refreshIfActive();
994
1096
  }
995
1097
  updateValueAggFunc(e, t) {
996
- const o = this.config.valueFields ?? [], n = o.findIndex((r) => r.field === e);
997
- n >= 0 && (o[n] = { ...o[n], aggFunc: t }, this.config.valueFields = [...o]), this.isActive && this.refresh();
1098
+ const o = this.config.valueFields ?? [], r = o.findIndex((n) => n.field === e);
1099
+ r >= 0 && (o[r] = { ...o[r], aggFunc: t }, this.config.valueFields = [...o]), this.isActive && this.refresh();
998
1100
  }
999
1101
  // #endregion
1000
- // #region Styles
1001
- styles = Q;
1002
- // #endregion
1003
1102
  }
1004
1103
  export {
1005
- b as PivotPlugin
1104
+ v as PivotPlugin
1006
1105
  };
1007
1106
  //# sourceMappingURL=index.js.map