@toolbox-web/grid 0.0.7 → 0.1.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 (86) hide show
  1. package/all.d.ts +151 -95
  2. package/all.js +1554 -1452
  3. package/all.js.map +1 -1
  4. package/custom-elements.json +89 -7
  5. package/index.d.ts +68 -23
  6. package/index.js +1066 -948
  7. package/index.js.map +1 -1
  8. package/lib/plugins/clipboard/index.js +48 -49
  9. package/lib/plugins/clipboard/index.js.map +1 -1
  10. package/lib/plugins/column-virtualization/index.js +6 -6
  11. package/lib/plugins/column-virtualization/index.js.map +1 -1
  12. package/lib/plugins/context-menu/index.js +32 -34
  13. package/lib/plugins/context-menu/index.js.map +1 -1
  14. package/lib/plugins/export/index.js +7 -7
  15. package/lib/plugins/export/index.js.map +1 -1
  16. package/lib/plugins/filtering/index.js +5 -38
  17. package/lib/plugins/filtering/index.js.map +1 -1
  18. package/lib/plugins/grouping-columns/index.js +4 -32
  19. package/lib/plugins/grouping-columns/index.js.map +1 -1
  20. package/lib/plugins/grouping-rows/index.js +8 -45
  21. package/lib/plugins/grouping-rows/index.js.map +1 -1
  22. package/lib/plugins/master-detail/index.js +6 -30
  23. package/lib/plugins/master-detail/index.js.map +1 -1
  24. package/lib/plugins/multi-sort/index.js +19 -42
  25. package/lib/plugins/multi-sort/index.js.map +1 -1
  26. package/lib/plugins/pinned-columns/index.js +5 -6
  27. package/lib/plugins/pinned-columns/index.js.map +1 -1
  28. package/lib/plugins/pinned-rows/index.js +6 -80
  29. package/lib/plugins/pinned-rows/index.js.map +1 -1
  30. package/lib/plugins/pivot/index.js +673 -145
  31. package/lib/plugins/pivot/index.js.map +1 -1
  32. package/lib/plugins/reorder/index.js +22 -51
  33. package/lib/plugins/reorder/index.js.map +1 -1
  34. package/lib/plugins/selection/index.js +53 -83
  35. package/lib/plugins/selection/index.js.map +1 -1
  36. package/lib/plugins/server-side/index.js +2 -2
  37. package/lib/plugins/server-side/index.js.map +1 -1
  38. package/lib/plugins/tree/index.js +6 -14
  39. package/lib/plugins/tree/index.js.map +1 -1
  40. package/lib/plugins/undo-redo/index.js +2 -3
  41. package/lib/plugins/undo-redo/index.js.map +1 -1
  42. package/lib/plugins/visibility/index.js +13 -105
  43. package/lib/plugins/visibility/index.js.map +1 -1
  44. package/package.json +1 -1
  45. package/themes/dg-theme-bootstrap.css +73 -0
  46. package/themes/dg-theme-material.css +71 -0
  47. package/umd/grid.all.umd.js +40 -415
  48. package/umd/grid.all.umd.js.map +1 -1
  49. package/umd/grid.umd.js +29 -60
  50. package/umd/grid.umd.js.map +1 -1
  51. package/umd/plugins/clipboard.umd.js +4 -4
  52. package/umd/plugins/clipboard.umd.js.map +1 -1
  53. package/umd/plugins/column-virtualization.umd.js +1 -1
  54. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  55. package/umd/plugins/context-menu.umd.js +2 -2
  56. package/umd/plugins/context-menu.umd.js.map +1 -1
  57. package/umd/plugins/export.umd.js +1 -1
  58. package/umd/plugins/export.umd.js.map +1 -1
  59. package/umd/plugins/filtering.umd.js +2 -34
  60. package/umd/plugins/filtering.umd.js.map +1 -1
  61. package/umd/plugins/grouping-columns.umd.js +1 -28
  62. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  63. package/umd/plugins/grouping-rows.umd.js +1 -39
  64. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  65. package/umd/plugins/master-detail.umd.js +1 -26
  66. package/umd/plugins/master-detail.umd.js.map +1 -1
  67. package/umd/plugins/multi-sort.umd.js +1 -25
  68. package/umd/plugins/multi-sort.umd.js.map +1 -1
  69. package/umd/plugins/pinned-columns.umd.js +1 -1
  70. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  71. package/umd/plugins/pinned-rows.umd.js +1 -72
  72. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  73. package/umd/plugins/pivot.umd.js +1 -7
  74. package/umd/plugins/pivot.umd.js.map +1 -1
  75. package/umd/plugins/reorder.umd.js +1 -30
  76. package/umd/plugins/reorder.umd.js.map +1 -1
  77. package/umd/plugins/selection.umd.js +1 -33
  78. package/umd/plugins/selection.umd.js.map +1 -1
  79. package/umd/plugins/server-side.umd.js +1 -1
  80. package/umd/plugins/server-side.umd.js.map +1 -1
  81. package/umd/plugins/tree.umd.js +1 -10
  82. package/umd/plugins/tree.umd.js.map +1 -1
  83. package/umd/plugins/undo-redo.umd.js +1 -1
  84. package/umd/plugins/undo-redo.umd.js.map +1 -1
  85. package/umd/plugins/visibility.umd.js +1 -93
  86. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,13 +1,14 @@
1
- const b = {
1
+ const P = {
2
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
5
5
  sortDesc: "▼",
6
6
  sortNone: "⇅",
7
7
  submenuArrow: "▶",
8
- dragHandle: "⋮⋮"
8
+ dragHandle: "⋮⋮",
9
+ toolPanel: "☰"
9
10
  };
10
- class m {
11
+ class N {
11
12
  /** Plugin version - override in subclass if needed */
12
13
  version = "1.0.0";
13
14
  /** CSS styles to inject into the grid's shadow DOM */
@@ -58,8 +59,8 @@ class m {
58
59
  /**
59
60
  * Emit a custom event from the grid.
60
61
  */
61
- emit(e, t) {
62
- this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
62
+ emit(e, i) {
63
+ this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: i, bubbles: !0 }));
63
64
  }
64
65
  /**
65
66
  * Request a re-render of the grid.
@@ -132,7 +133,7 @@ class m {
132
133
  */
133
134
  get gridIcons() {
134
135
  const e = this.grid?.gridConfig?.icons ?? {};
135
- return { ...b, ...e };
136
+ return { ...P, ...e };
136
137
  }
137
138
  /**
138
139
  * Resolve an icon value to string or HTMLElement.
@@ -142,8 +143,8 @@ class m {
142
143
  * @param pluginOverride - Optional plugin-level override
143
144
  * @returns The resolved icon value
144
145
  */
145
- resolveIcon(e, t) {
146
- return t !== void 0 ? t : this.gridIcons[e];
146
+ resolveIcon(e, i) {
147
+ return i !== void 0 ? i : this.gridIcons[e];
147
148
  }
148
149
  /**
149
150
  * Set an icon value on an element.
@@ -152,8 +153,8 @@ class m {
152
153
  * @param element - The element to set the icon on
153
154
  * @param icon - The icon value (string or HTMLElement)
154
155
  */
155
- setIcon(e, t) {
156
- typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
156
+ setIcon(e, i) {
157
+ typeof i == "string" ? e.innerHTML = i : i instanceof HTMLElement && (e.innerHTML = "", e.appendChild(i.cloneNode(!0)));
157
158
  }
158
159
  /**
159
160
  * Log a warning message.
@@ -162,223 +163,750 @@ class m {
162
163
  console.warn(`[tbw-grid:${this.name}] ${e}`);
163
164
  }
164
165
  }
165
- function y(s) {
166
- const e = [];
167
- 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;
166
+ const m = {
167
+ sum: (t, e) => t.reduce((i, o) => i + (Number(o[e]) || 0), 0),
168
+ avg: (t, e) => {
169
+ const i = t.reduce((o, n) => o + (Number(n[e]) || 0), 0);
170
+ return t.length ? i / t.length : 0;
171
+ },
172
+ count: (t) => t.length,
173
+ min: (t, e) => Math.min(...t.map((i) => Number(i[e]) || 1 / 0)),
174
+ max: (t, e) => Math.max(...t.map((i) => Number(i[e]) || -1 / 0)),
175
+ first: (t, e) => t[0]?.[e],
176
+ last: (t, e) => t[t.length - 1]?.[e]
177
+ }, v = /* @__PURE__ */ new Map(), h = {
178
+ /**
179
+ * Register a custom aggregator function.
180
+ */
181
+ register(t, e) {
182
+ v.set(t, e);
183
+ },
184
+ /**
185
+ * Unregister a custom aggregator function.
186
+ */
187
+ unregister(t) {
188
+ v.delete(t);
189
+ },
190
+ /**
191
+ * Get an aggregator function by reference.
192
+ */
193
+ get(t) {
194
+ if (t !== void 0)
195
+ return typeof t == "function" ? t : v.get(t) ?? m[t];
196
+ },
197
+ /**
198
+ * Run an aggregator on a set of rows.
199
+ */
200
+ run(t, e, i, o) {
201
+ const n = this.get(t);
202
+ return n ? n(e, i, o) : void 0;
203
+ },
204
+ /**
205
+ * Check if an aggregator exists.
206
+ */
207
+ has(t) {
208
+ return v.has(t) || t in m;
209
+ },
210
+ /**
211
+ * List all available aggregator names.
212
+ */
213
+ list() {
214
+ return [...Object.keys(m), ...v.keys()];
215
+ }
216
+ }, A = {
217
+ sum: (t) => t.reduce((e, i) => e + i, 0),
218
+ avg: (t) => t.length ? t.reduce((e, i) => e + i, 0) / t.length : 0,
219
+ count: (t) => t.length,
220
+ min: (t) => t.length ? Math.min(...t) : 0,
221
+ max: (t) => t.length ? Math.max(...t) : 0,
222
+ first: (t) => t[0] ?? 0,
223
+ last: (t) => t[t.length - 1] ?? 0
224
+ };
225
+ function k(t) {
226
+ return A[t] ?? A.sum;
168
227
  }
169
- function F(s) {
170
- switch (s) {
171
- case "sum":
172
- return (e) => e.reduce((t, o) => t + o, 0);
173
- case "avg":
174
- return (e) => e.length ? e.reduce((t, o) => t + o, 0) / e.length : 0;
175
- case "count":
176
- return (e) => e.length;
177
- case "min":
178
- return (e) => e.length ? Math.min(...e) : 0;
179
- case "max":
180
- return (e) => e.length ? Math.max(...e) : 0;
181
- case "first":
182
- return (e) => e[0] ?? 0;
183
- case "last":
184
- return (e) => e[e.length - 1] ?? 0;
185
- default:
186
- return (e) => e.reduce((t, o) => t + o, 0);
187
- }
228
+ h.register.bind(h);
229
+ h.unregister.bind(h);
230
+ h.get.bind(h);
231
+ h.run.bind(h);
232
+ h.list.bind(h);
233
+ const K = k;
234
+ function I(t) {
235
+ const e = [];
236
+ return !t.rowGroupFields?.length && !t.columnGroupFields?.length && e.push("At least one row or column group field is required"), t.valueFields?.length || e.push("At least one value field is required"), e;
188
237
  }
189
- function f(s, e) {
190
- return [...s, e].join("|");
238
+ function C(t, e) {
239
+ return [...t, e].join("|");
191
240
  }
192
- function C(s, e) {
193
- const t = e.rowGroupFields ?? [], o = e.columnGroupFields ?? [], r = e.valueFields ?? [], i = G(s, o), n = A(s, t), u = _(n, o, i, r, 0), l = P(u, i, r), a = Object.values(l).reduce((d, c) => d + c, 0);
241
+ function S(t, e) {
242
+ const i = e.rowGroupFields ?? [], o = e.columnGroupFields ?? [], n = e.valueFields ?? [], r = V(t, o), a = L(
243
+ t,
244
+ i,
245
+ o,
246
+ r,
247
+ n,
248
+ 0,
249
+ // starting depth
250
+ ""
251
+ // parent key prefix
252
+ ), s = H(a, r, n), l = Object.values(s).reduce((d, c) => d + c, 0);
194
253
  return {
195
- rows: u,
196
- columnKeys: i,
197
- totals: l,
198
- grandTotal: a
254
+ rows: a,
255
+ columnKeys: r,
256
+ totals: s,
257
+ grandTotal: l
199
258
  };
200
259
  }
201
- function G(s, e) {
260
+ function V(t, e) {
202
261
  if (e.length === 0) return ["value"];
203
- const t = /* @__PURE__ */ new Set();
204
- for (const o of s) {
205
- const r = e.map((i) => String(o[i] ?? "")).join("|");
206
- t.add(r);
262
+ const i = /* @__PURE__ */ new Set();
263
+ for (const o of t) {
264
+ const n = e.map((r) => String(o[r] ?? "")).join("|");
265
+ i.add(n);
207
266
  }
208
- return [...t].sort();
267
+ return [...i].sort();
209
268
  }
210
- function A(s, e) {
211
- const t = /* @__PURE__ */ new Map();
212
- for (const o of s) {
213
- const r = e.map((n) => String(o[n] ?? "")).join("|");
214
- t.has(r) || t.set(r, []);
215
- const i = t.get(r);
216
- i && i.push(o);
217
- }
218
- return t;
269
+ function M(t, e) {
270
+ const i = /* @__PURE__ */ new Map();
271
+ for (const o of t) {
272
+ const n = String(o[e] ?? ""), r = i.get(n);
273
+ r ? r.push(o) : i.set(n, [o]);
274
+ }
275
+ return i;
219
276
  }
220
- function _(s, e, t, o, r) {
221
- const i = [];
222
- for (const [n, u] of s) {
223
- const l = {};
224
- let a = 0;
225
- for (const d of t)
226
- for (const c of o) {
227
- const p = (e.length > 0 ? u.filter((g) => e.map((R) => String(g[R] ?? "")).join("|") === d) : u).map((g) => Number(g[c.field]) || 0), v = F(c.aggFunc), h = p.length > 0 ? v(p) : null, w = f([d], c.field);
228
- l[w] = h, h !== null && (a += h);
229
- }
230
- i.push({
231
- rowKey: n,
232
- rowLabel: n || "(blank)",
277
+ function L(t, e, i, o, n, r, a) {
278
+ const s = [];
279
+ if (e.length === 0) {
280
+ const u = _(t, i, o, n), g = G(u);
281
+ return s.push({
282
+ rowKey: a || "all",
283
+ rowLabel: a || "All",
284
+ depth: r,
285
+ values: u,
286
+ total: g,
287
+ isGroup: !1,
288
+ rowCount: t.length
289
+ }), s;
290
+ }
291
+ const l = e[0], d = e.slice(1), c = d.length > 0, p = M(t, l);
292
+ for (const [u, g] of p) {
293
+ const F = a ? `${a}|${u}` : u, y = _(g, i, o, n), E = G(y);
294
+ let R;
295
+ c && (R = L(
296
+ g,
297
+ d,
298
+ i,
299
+ o,
300
+ n,
301
+ r + 1,
302
+ F
303
+ )), s.push({
304
+ rowKey: F,
305
+ rowLabel: u || "(blank)",
233
306
  depth: r,
234
- values: l,
235
- total: a,
236
- isGroup: !1
307
+ values: y,
308
+ total: E,
309
+ isGroup: c,
310
+ children: R,
311
+ rowCount: g.length
237
312
  });
238
313
  }
239
- return i;
314
+ return s;
240
315
  }
241
- function P(s, e, t) {
242
- const o = {};
243
- for (const r of e)
244
- for (const i of t) {
245
- const n = f([r], i.field);
246
- o[n] = s.reduce((u, l) => u + (l.values[n] ?? 0), 0);
316
+ function _(t, e, i, o) {
317
+ const n = {};
318
+ for (const r of i)
319
+ for (const a of o) {
320
+ const l = (e.length > 0 ? t.filter((u) => e.map((g) => String(u[g] ?? "")).join("|") === r) : t).map((u) => Number(u[a.field]) || 0), d = K(a.aggFunc), c = l.length > 0 ? d(l) : null, p = C([r], a.field);
321
+ n[p] = c;
247
322
  }
323
+ return n;
324
+ }
325
+ function G(t) {
326
+ let e = 0;
327
+ for (const i of Object.values(t))
328
+ e += i ?? 0;
329
+ return e;
330
+ }
331
+ function H(t, e, i) {
332
+ const o = {};
333
+ function n(r) {
334
+ for (const a of r)
335
+ if (!a.isGroup || !a.children?.length)
336
+ for (const s of e)
337
+ for (const l of i) {
338
+ const d = C([s], l.field);
339
+ o[d] = (o[d] ?? 0) + (a.values[d] ?? 0);
340
+ }
341
+ else a.children && n(a.children);
342
+ }
343
+ return n(t), o;
344
+ }
345
+ function D(t, e, i = !0) {
346
+ const o = [];
347
+ function n(r) {
348
+ o.push(r);
349
+ const a = e ? e.has(r.rowKey) : i;
350
+ if (r.children && a)
351
+ for (const s of r.children)
352
+ n(s);
353
+ }
354
+ for (const r of t)
355
+ n(r);
248
356
  return o;
249
357
  }
250
- function q(s) {
358
+ function w(t) {
251
359
  const e = [];
252
- function t(o) {
253
- if (e.push(o), o.children)
254
- for (const r of o.children)
255
- t(r);
360
+ function i(o) {
361
+ if (o.isGroup && e.push(o.rowKey), o.children)
362
+ for (const n of o.children)
363
+ i(n);
256
364
  }
257
- for (const o of s)
258
- t(o);
365
+ for (const o of t)
366
+ i(o);
259
367
  return e;
260
368
  }
261
- class T extends m {
369
+ const z = ["sum", "avg", "count", "min", "max", "first", "last"];
370
+ function q(t, e, i, o) {
371
+ const n = new AbortController(), r = { config: e, callbacks: o, signal: n.signal }, a = document.createElement("div");
372
+ return a.className = "tbw-pivot-panel", a.appendChild(f("Options", () => U(i, r))), a.appendChild(f("Row Groups", () => T("rowGroups", r))), a.appendChild(f("Column Groups", () => T("columnGroups", r))), a.appendChild(f("Values", () => Z(r))), a.appendChild(f("Available Fields", () => j(r))), t.appendChild(a), () => {
373
+ n.abort(), a.remove();
374
+ };
375
+ }
376
+ function f(t, e) {
377
+ const i = document.createElement("div");
378
+ i.className = "tbw-pivot-section";
379
+ const o = document.createElement("div");
380
+ o.className = "tbw-pivot-section-header", o.textContent = t;
381
+ const n = document.createElement("div");
382
+ return n.className = "tbw-pivot-section-content", n.appendChild(e()), i.appendChild(o), i.appendChild(n), i;
383
+ }
384
+ function T(t, e) {
385
+ const { config: i, callbacks: o, signal: n } = e, r = document.createElement("div");
386
+ r.className = "tbw-pivot-drop-zone", r.setAttribute("data-zone", t);
387
+ const a = t === "rowGroups" ? i.rowGroupFields ?? [] : i.columnGroupFields ?? [];
388
+ if (a.length === 0) {
389
+ const s = document.createElement("div");
390
+ s.className = "tbw-pivot-placeholder", s.textContent = "Drag fields here or click to add", r.appendChild(s);
391
+ } else
392
+ for (const s of a)
393
+ r.appendChild(O(s, t, e));
394
+ return r.addEventListener(
395
+ "dragover",
396
+ (s) => {
397
+ s.preventDefault(), r.classList.add("drag-over");
398
+ },
399
+ { signal: n }
400
+ ), r.addEventListener(
401
+ "dragleave",
402
+ () => {
403
+ r.classList.remove("drag-over");
404
+ },
405
+ { signal: n }
406
+ ), r.addEventListener(
407
+ "drop",
408
+ (s) => {
409
+ s.preventDefault(), r.classList.remove("drag-over");
410
+ const l = s.dataTransfer?.getData("text/plain");
411
+ l && o.onAddFieldToZone(l, t);
412
+ },
413
+ { signal: n }
414
+ ), r;
415
+ }
416
+ function O(t, e, i) {
417
+ const { callbacks: o, signal: n } = i, r = document.createElement("div");
418
+ r.className = "tbw-pivot-field-chip", r.draggable = !0;
419
+ const a = o.getAvailableFields().find((d) => d.field === t), s = document.createElement("span");
420
+ s.className = "tbw-pivot-chip-label", s.textContent = a?.header ?? t;
421
+ const l = document.createElement("button");
422
+ return l.className = "tbw-pivot-chip-remove", l.innerHTML = "×", l.title = "Remove field", l.addEventListener(
423
+ "click",
424
+ (d) => {
425
+ d.stopPropagation(), o.onRemoveFieldFromZone(t, e);
426
+ },
427
+ { signal: n }
428
+ ), r.appendChild(s), r.appendChild(l), r.addEventListener(
429
+ "dragstart",
430
+ (d) => {
431
+ d.dataTransfer?.setData("text/plain", t), d.dataTransfer?.setData("source-zone", e), r.classList.add("dragging");
432
+ },
433
+ { signal: n }
434
+ ), r.addEventListener(
435
+ "dragend",
436
+ () => {
437
+ r.classList.remove("dragging");
438
+ },
439
+ { signal: n }
440
+ ), r;
441
+ }
442
+ function Z(t) {
443
+ const { config: e, callbacks: i, signal: o } = t, n = document.createElement("div");
444
+ n.className = "tbw-pivot-drop-zone tbw-pivot-values-zone", n.setAttribute("data-zone", "values");
445
+ const r = e.valueFields ?? [];
446
+ if (r.length === 0) {
447
+ const a = document.createElement("div");
448
+ a.className = "tbw-pivot-placeholder", a.textContent = "Drag numeric fields here for aggregation", n.appendChild(a);
449
+ } else
450
+ for (const a of r)
451
+ n.appendChild($(a, t));
452
+ return n.addEventListener(
453
+ "dragover",
454
+ (a) => {
455
+ a.preventDefault(), n.classList.add("drag-over");
456
+ },
457
+ { signal: o }
458
+ ), n.addEventListener(
459
+ "dragleave",
460
+ () => {
461
+ n.classList.remove("drag-over");
462
+ },
463
+ { signal: o }
464
+ ), n.addEventListener(
465
+ "drop",
466
+ (a) => {
467
+ a.preventDefault(), n.classList.remove("drag-over");
468
+ const s = a.dataTransfer?.getData("text/plain");
469
+ s && i.onAddValueField(s, "sum");
470
+ },
471
+ { signal: o }
472
+ ), n;
473
+ }
474
+ function $(t, e) {
475
+ const { callbacks: i, signal: o } = e, n = document.createElement("div");
476
+ n.className = "tbw-pivot-field-chip tbw-pivot-value-chip";
477
+ const r = i.getAvailableFields().find((c) => c.field === t.field), a = document.createElement("div");
478
+ a.className = "tbw-pivot-value-label-wrapper";
479
+ const s = document.createElement("span");
480
+ s.className = "tbw-pivot-chip-label", s.textContent = r?.header ?? t.field;
481
+ const l = document.createElement("select");
482
+ l.className = "tbw-pivot-agg-select", l.title = "Aggregation function";
483
+ for (const c of z) {
484
+ const p = document.createElement("option");
485
+ p.value = c, p.textContent = c.toUpperCase(), p.selected = c === t.aggFunc, l.appendChild(p);
486
+ }
487
+ l.addEventListener(
488
+ "change",
489
+ () => {
490
+ i.onUpdateValueAggFunc(t.field, l.value);
491
+ },
492
+ { signal: o }
493
+ );
494
+ const d = document.createElement("button");
495
+ return d.className = "tbw-pivot-chip-remove", d.innerHTML = "×", d.title = "Remove value field", d.addEventListener(
496
+ "click",
497
+ (c) => {
498
+ c.stopPropagation(), i.onRemoveValueField(t.field);
499
+ },
500
+ { signal: o }
501
+ ), a.appendChild(s), a.appendChild(l), n.appendChild(a), n.appendChild(d), n;
502
+ }
503
+ function j(t) {
504
+ const { config: e, callbacks: i, signal: o } = t, n = document.createElement("div");
505
+ n.className = "tbw-pivot-available-fields";
506
+ const r = i.getAvailableFields(), a = /* @__PURE__ */ new Set([
507
+ ...e.rowGroupFields ?? [],
508
+ ...e.columnGroupFields ?? [],
509
+ ...e.valueFields?.map((l) => l.field) ?? []
510
+ ]), s = r.filter((l) => !a.has(l.field));
511
+ if (s.length === 0) {
512
+ const l = document.createElement("div");
513
+ l.className = "tbw-pivot-placeholder", l.textContent = "All fields are in use", n.appendChild(l);
514
+ } else
515
+ for (const l of s) {
516
+ const d = document.createElement("div");
517
+ 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(
518
+ "dragstart",
519
+ (c) => {
520
+ c.dataTransfer?.setData("text/plain", l.field), d.classList.add("dragging");
521
+ },
522
+ { signal: o }
523
+ ), d.addEventListener(
524
+ "dragend",
525
+ () => {
526
+ d.classList.remove("dragging");
527
+ },
528
+ { signal: o }
529
+ ), n.appendChild(d);
530
+ }
531
+ return n;
532
+ }
533
+ function U(t, e) {
534
+ const { config: i, callbacks: o, signal: n } = e, r = document.createElement("div");
535
+ return r.className = "tbw-pivot-options", r.appendChild(
536
+ x(
537
+ "Enable Pivot View",
538
+ t,
539
+ (a) => {
540
+ o.onTogglePivot(a);
541
+ },
542
+ n
543
+ )
544
+ ), r.appendChild(
545
+ x(
546
+ "Show Row Totals",
547
+ i.showTotals ?? !0,
548
+ (a) => {
549
+ o.onOptionChange("showTotals", a);
550
+ },
551
+ n
552
+ )
553
+ ), r.appendChild(
554
+ x(
555
+ "Show Grand Total",
556
+ i.showGrandTotal ?? !0,
557
+ (a) => {
558
+ o.onOptionChange("showGrandTotal", a);
559
+ },
560
+ n
561
+ )
562
+ ), r;
563
+ }
564
+ function x(t, e, i, o) {
565
+ const n = document.createElement("label");
566
+ n.className = "tbw-pivot-checkbox";
567
+ const r = document.createElement("input");
568
+ r.type = "checkbox", r.checked = e, r.addEventListener("change", () => i(r.checked), { signal: o });
569
+ const a = document.createElement("span");
570
+ return a.textContent = t, n.appendChild(r), n.appendChild(a), n;
571
+ }
572
+ function B(t, e, i) {
573
+ return e.className = "pivot-group-row", e.setAttribute("data-pivot-depth", String(t.__pivotDepth ?? 0)), e.setAttribute("role", "row"), e.setAttribute("aria-expanded", String(t.__pivotExpanded)), e.innerHTML = "", i.columns.forEach((o, n) => {
574
+ const r = document.createElement("div");
575
+ if (r.className = "cell", r.setAttribute("data-col", String(n)), r.setAttribute("role", "gridcell"), n === 0) {
576
+ const a = Number(t.__pivotIndent) || 0;
577
+ r.style.paddingLeft = `${a}px`;
578
+ const s = String(t.__pivotRowKey), l = document.createElement("button");
579
+ l.type = "button", l.className = "pivot-toggle", l.setAttribute("aria-label", t.__pivotExpanded ? "Collapse group" : "Expand group"), i.setIcon(l, i.resolveIcon(t.__pivotExpanded ? "collapse" : "expand")), l.addEventListener("click", (p) => {
580
+ p.stopPropagation(), i.onToggle(s);
581
+ }), r.appendChild(l);
582
+ const d = document.createElement("span");
583
+ d.className = "pivot-label", d.textContent = String(t.__pivotLabel ?? ""), r.appendChild(d);
584
+ const c = document.createElement("span");
585
+ c.className = "pivot-count", c.textContent = ` (${Number(t.__pivotRowCount) || 0})`, r.appendChild(c);
586
+ } else {
587
+ const a = t[o.field];
588
+ r.textContent = a != null ? String(a) : "";
589
+ }
590
+ e.appendChild(r);
591
+ }), !0;
592
+ }
593
+ function W(t, e, i) {
594
+ return e.className = "pivot-leaf-row", e.setAttribute("data-pivot-depth", String(t.__pivotDepth ?? 0)), e.innerHTML = "", i.forEach((o, n) => {
595
+ const r = document.createElement("div");
596
+ if (r.className = "cell", r.setAttribute("data-col", String(n)), r.setAttribute("role", "gridcell"), n === 0) {
597
+ const a = Number(t.__pivotIndent) || 0;
598
+ r.style.paddingLeft = `${a + 20}px`;
599
+ const s = document.createElement("span");
600
+ s.className = "pivot-label", s.textContent = String(t.__pivotLabel ?? ""), r.appendChild(s);
601
+ } else {
602
+ const a = t[o.field];
603
+ r.textContent = a != null ? String(a) : "";
604
+ }
605
+ e.appendChild(r);
606
+ }), !0;
607
+ }
608
+ function J(t, e, i) {
609
+ return e.className = "pivot-grand-total-row", e.setAttribute("role", "row"), e.innerHTML = "", i.forEach((o, n) => {
610
+ const r = document.createElement("div");
611
+ if (r.className = "cell", r.setAttribute("data-col", String(n)), r.setAttribute("role", "gridcell"), n === 0) {
612
+ const a = document.createElement("span");
613
+ a.className = "pivot-label", a.textContent = "Grand Total", r.appendChild(a);
614
+ } else {
615
+ const a = t[o.field];
616
+ r.textContent = a != null ? String(a) : "";
617
+ }
618
+ e.appendChild(r);
619
+ }), !0;
620
+ }
621
+ 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;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}';
622
+ class b extends N {
262
623
  name = "pivot";
263
624
  version = "1.0.0";
625
+ /** Tool panel ID for shell integration */
626
+ static PANEL_ID = "pivot";
264
627
  get defaultConfig() {
265
628
  return {
266
- enabled: !0,
629
+ active: !0,
267
630
  showTotals: !0,
268
631
  showGrandTotal: !0
269
632
  };
270
633
  }
271
634
  // ===== Internal State =====
272
635
  isActive = !1;
636
+ hasInitialized = !1;
273
637
  pivotResult = null;
274
- columnHeaders = [];
275
- rowHeaders = [];
638
+ fieldHeaderMap = /* @__PURE__ */ new Map();
639
+ expandedKeys = /* @__PURE__ */ new Set();
640
+ defaultExpanded = !0;
641
+ originalColumns = [];
642
+ panelContainer = null;
643
+ grandTotalFooter = null;
644
+ /**
645
+ * Check if the plugin has valid pivot configuration (at least value fields).
646
+ */
647
+ hasValidPivotConfig() {
648
+ return (this.config.valueFields?.length ?? 0) > 0;
649
+ }
276
650
  // ===== Lifecycle =====
277
651
  detach() {
278
- this.isActive = !1, this.pivotResult = null, this.columnHeaders = [], this.rowHeaders = [];
652
+ this.isActive = !1, this.hasInitialized = !1, this.pivotResult = null, this.fieldHeaderMap.clear(), this.originalColumns = [], this.panelContainer = null, this.cleanupGrandTotalFooter();
653
+ }
654
+ // ===== Shell Integration =====
655
+ getToolPanel() {
656
+ return {
657
+ id: b.PANEL_ID,
658
+ title: "Pivot",
659
+ icon: "⊞",
660
+ tooltip: "Configure pivot table",
661
+ order: 90,
662
+ render: (e) => this.renderPanel(e)
663
+ };
279
664
  }
280
665
  // ===== Hooks =====
281
666
  processRows(e) {
282
- if (!this.config.enabled || !this.isActive)
667
+ if (!this.hasInitialized && this.config.active !== !1 && this.hasValidPivotConfig() && (this.hasInitialized = !0, this.isActive = !0), !this.isActive)
283
668
  return [...e];
284
- const t = y(this.config);
285
- return t.length > 0 ? (this.warn(`Config errors: ${t.join(", ")}`), [...e]) : (this.pivotResult = C(e, this.config), q(this.pivotResult.rows).map((o) => ({
286
- __pivotRowKey: o.rowKey,
287
- __pivotLabel: o.rowLabel,
288
- __pivotDepth: o.depth,
289
- __pivotIsGroup: o.isGroup,
290
- __pivotTotal: o.total,
291
- ...o.values
292
- })));
669
+ const i = I(this.config);
670
+ if (i.length > 0)
671
+ return this.warn(`Config errors: ${i.join(", ")}`), [...e];
672
+ if (this.buildFieldHeaderMap(), this.defaultExpanded = this.config.defaultExpanded ?? !0, this.expandedKeys.size === 0 && this.defaultExpanded && this.pivotResult) {
673
+ const r = w(this.pivotResult.rows);
674
+ for (const a of r)
675
+ this.expandedKeys.add(a);
676
+ }
677
+ if (this.pivotResult = S(e, this.config), this.expandedKeys.size === 0 && this.defaultExpanded) {
678
+ const r = w(this.pivotResult.rows);
679
+ for (const a of r)
680
+ this.expandedKeys.add(a);
681
+ }
682
+ const o = this.config.indentWidth ?? 20;
683
+ return D(
684
+ this.pivotResult.rows,
685
+ this.expandedKeys,
686
+ this.defaultExpanded
687
+ ).map((r) => ({
688
+ __pivotRowKey: r.rowKey,
689
+ __pivotLabel: r.rowLabel,
690
+ __pivotDepth: r.depth,
691
+ __pivotIsGroup: r.isGroup,
692
+ __pivotHasChildren: !!r.children?.length,
693
+ __pivotExpanded: this.expandedKeys.has(r.rowKey),
694
+ __pivotRowCount: r.rowCount ?? 0,
695
+ __pivotIndent: r.depth * o,
696
+ __pivotTotal: r.total,
697
+ ...r.values
698
+ }));
293
699
  }
294
700
  processColumns(e) {
295
- if (!this.config.enabled || !this.isActive || !this.pivotResult)
701
+ if (!this.isActive || !this.pivotResult)
296
702
  return [...e];
297
- const t = [];
298
- t.push({
703
+ const i = [], o = (this.config.rowGroupFields ?? []).map((n) => this.fieldHeaderMap.get(n) ?? n).join(" / ");
704
+ i.push({
299
705
  field: "__pivotLabel",
300
- header: this.config.rowGroupFields?.join(" / ") ?? "Group",
706
+ header: o || "Group",
301
707
  width: 200
302
708
  });
303
- for (const o of this.pivotResult.columnKeys)
709
+ for (const n of this.pivotResult.columnKeys)
304
710
  for (const r of this.config.valueFields ?? []) {
305
- const i = f([o], r.field);
306
- t.push({
307
- field: i,
308
- header: `${o} - ${r.header || r.field} (${r.aggFunc})`,
711
+ const a = C([n], r.field), s = r.header || this.fieldHeaderMap.get(r.field) || r.field;
712
+ i.push({
713
+ field: a,
714
+ header: `${n} - ${s} (${r.aggFunc})`,
309
715
  width: 120,
310
716
  type: "number"
311
717
  });
312
718
  }
313
- return this.config.showTotals && t.push({
719
+ return this.config.showTotals && i.push({
314
720
  field: "__pivotTotal",
315
721
  header: "Total",
316
722
  width: 100,
317
723
  type: "number"
318
- }), t;
724
+ }), i;
725
+ }
726
+ renderRow(e, i) {
727
+ const o = e;
728
+ return o.__pivotRowKey && o.__pivotHasChildren ? B(o, i, {
729
+ columns: this.gridColumns,
730
+ onToggle: (n) => this.toggle(n),
731
+ resolveIcon: (n) => this.resolveIcon(n),
732
+ setIcon: (n, r) => this.setIcon(n, r)
733
+ }) : o.__pivotRowKey !== void 0 && this.isActive ? W(o, i, this.gridColumns) : (this.cleanupPivotStyling(i), !1);
319
734
  }
320
- // ===== Public API =====
321
735
  /**
322
- * Enable pivot mode.
736
+ * Remove pivot-specific classes, attributes, and inline styles from a row element.
737
+ * Called when pivot mode is disabled to clean up reused DOM elements.
738
+ * Clears innerHTML so the grid's default renderer can rebuild the row.
323
739
  */
324
- enablePivot() {
325
- this.isActive = !0, this.requestRender();
740
+ cleanupPivotStyling(e) {
741
+ (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 = "");
742
+ }
743
+ afterRender() {
744
+ this.isActive && this.config.showGrandTotal && this.pivotResult ? this.renderGrandTotalFooter() : this.cleanupGrandTotalFooter();
326
745
  }
327
746
  /**
328
- * Disable pivot mode and return to normal grid view.
747
+ * Render the grand total row as a sticky footer pinned to the bottom.
329
748
  */
330
- disablePivot() {
331
- this.isActive = !1, this.pivotResult = null, this.requestRender();
749
+ renderGrandTotalFooter() {
750
+ if (!this.pivotResult) return;
751
+ const e = this.shadowRoot;
752
+ if (!e) return;
753
+ const i = e.querySelector(".tbw-scroll-area") ?? e.querySelector(".tbw-grid-content") ?? e.children[0];
754
+ if (!i) return;
755
+ this.grandTotalFooter || (this.grandTotalFooter = document.createElement("div"), this.grandTotalFooter.className = "pivot-grand-total-footer", i.appendChild(this.grandTotalFooter));
756
+ const o = {
757
+ __pivotRowKey: "__grandTotal",
758
+ __pivotLabel: "Grand Total",
759
+ __pivotIsGrandTotal: !0,
760
+ __pivotTotal: this.pivotResult.grandTotal,
761
+ ...this.pivotResult.totals
762
+ };
763
+ J(o, this.grandTotalFooter, this.gridColumns);
332
764
  }
333
765
  /**
334
- * Check if pivot mode is currently active.
766
+ * Remove the grand total footer element.
335
767
  */
768
+ cleanupGrandTotalFooter() {
769
+ this.grandTotalFooter && (this.grandTotalFooter.remove(), this.grandTotalFooter = null);
770
+ }
771
+ // ===== Expand/Collapse API =====
772
+ toggle(e) {
773
+ this.expandedKeys.has(e) ? this.expandedKeys.delete(e) : this.expandedKeys.add(e), this.requestRender();
774
+ }
775
+ expand(e) {
776
+ this.expandedKeys.add(e), this.requestRender();
777
+ }
778
+ collapse(e) {
779
+ this.expandedKeys.delete(e), this.requestRender();
780
+ }
781
+ expandAll() {
782
+ if (this.pivotResult) {
783
+ const e = w(this.pivotResult.rows);
784
+ for (const i of e)
785
+ this.expandedKeys.add(i);
786
+ this.requestRender();
787
+ }
788
+ }
789
+ collapseAll() {
790
+ this.expandedKeys.clear(), this.requestRender();
791
+ }
792
+ isExpanded(e) {
793
+ return this.expandedKeys.has(e);
794
+ }
795
+ // ===== Public API =====
796
+ enablePivot() {
797
+ this.originalColumns.length === 0 && this.captureOriginalColumns(), this.isActive = !0, this.requestRender();
798
+ }
799
+ disablePivot() {
800
+ this.isActive = !1, this.pivotResult = null, this.requestRender();
801
+ }
336
802
  isPivotActive() {
337
803
  return this.isActive;
338
804
  }
339
- /**
340
- * Get the current pivot result.
341
- */
342
805
  getPivotResult() {
343
806
  return this.pivotResult;
344
807
  }
345
- /**
346
- * Set the row group fields for pivoting.
347
- * @param fields - Array of field names to group rows by
348
- */
349
808
  setRowGroupFields(e) {
350
809
  this.config.rowGroupFields = e, this.requestRender();
351
810
  }
352
- /**
353
- * Set the column group fields for pivoting.
354
- * @param fields - Array of field names to create columns from
355
- */
356
811
  setColumnGroupFields(e) {
357
812
  this.config.columnGroupFields = e, this.requestRender();
358
813
  }
359
- /**
360
- * Set the value fields with aggregation functions.
361
- * @param fields - Array of value field configurations
362
- */
363
814
  setValueFields(e) {
364
815
  this.config.valueFields = e, this.requestRender();
365
816
  }
366
- /**
367
- * Refresh the pivot by clearing cached results.
368
- */
369
817
  refresh() {
370
818
  this.pivotResult = null, this.requestRender();
371
819
  }
820
+ // ===== Tool Panel API =====
821
+ showPanel() {
822
+ this.grid.openToolPanel(b.PANEL_ID);
823
+ }
824
+ hidePanel() {
825
+ this.grid.closeToolPanel();
826
+ }
827
+ togglePanel() {
828
+ this.grid.toggleToolPanel(b.PANEL_ID);
829
+ }
830
+ isPanelVisible() {
831
+ return this.grid.activeToolPanel === b.PANEL_ID;
832
+ }
833
+ // ===== Private Helpers =====
834
+ get gridColumns() {
835
+ return this.grid.columns ?? [];
836
+ }
837
+ buildFieldHeaderMap() {
838
+ const e = this.getAvailableFields();
839
+ this.fieldHeaderMap.clear();
840
+ for (const i of e)
841
+ this.fieldHeaderMap.set(i.field, i.header);
842
+ }
843
+ getAvailableFields() {
844
+ return this.originalColumns.length > 0 ? this.originalColumns : this.captureOriginalColumns();
845
+ }
846
+ captureOriginalColumns() {
847
+ const e = this.grid;
848
+ try {
849
+ const i = e.getAllColumns?.() ?? e.columns ?? [];
850
+ return this.originalColumns = i.filter((o) => !o.field.startsWith("__pivot")).map((o) => ({
851
+ field: o.field,
852
+ header: o.header ?? o.field
853
+ })), this.originalColumns;
854
+ } catch {
855
+ return [];
856
+ }
857
+ }
858
+ renderPanel(e) {
859
+ this.panelContainer = e, this.originalColumns.length === 0 && this.captureOriginalColumns();
860
+ const i = {
861
+ onTogglePivot: (o) => {
862
+ o ? this.enablePivot() : this.disablePivot(), this.refreshPanel();
863
+ },
864
+ onAddFieldToZone: (o, n) => this.addFieldToZone(o, n),
865
+ onRemoveFieldFromZone: (o, n) => this.removeFieldFromZone(o, n),
866
+ onAddValueField: (o, n) => this.addValueField(o, n),
867
+ onRemoveValueField: (o) => this.removeValueField(o),
868
+ onUpdateValueAggFunc: (o, n) => this.updateValueAggFunc(o, n),
869
+ onOptionChange: (o, n) => {
870
+ this.config[o] = n, this.isActive && this.refresh();
871
+ },
872
+ getAvailableFields: () => this.getAvailableFields()
873
+ };
874
+ return q(e, this.config, this.isActive, i);
875
+ }
876
+ refreshPanel() {
877
+ this.panelContainer && (this.panelContainer.innerHTML = "", this.renderPanel(this.panelContainer));
878
+ }
879
+ addFieldToZone(e, i) {
880
+ if (i === "rowGroups") {
881
+ const o = this.config.rowGroupFields ?? [];
882
+ o.includes(e) || (this.config.rowGroupFields = [...o, e]);
883
+ } else {
884
+ const o = this.config.columnGroupFields ?? [];
885
+ o.includes(e) || (this.config.columnGroupFields = [...o, e]);
886
+ }
887
+ this.removeFromOtherZones(e, i), this.isActive && this.refresh(), this.refreshPanel();
888
+ }
889
+ removeFieldFromZone(e, i) {
890
+ i === "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();
891
+ }
892
+ removeFromOtherZones(e, i) {
893
+ i !== "rowGroups" && (this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((o) => o !== e)), i !== "columnGroups" && (this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((o) => o !== e)), i !== "values" && (this.config.valueFields = (this.config.valueFields ?? []).filter((o) => o.field !== e));
894
+ }
895
+ addValueField(e, i) {
896
+ const o = this.config.valueFields ?? [];
897
+ o.some((n) => n.field === e) || (this.config.valueFields = [...o, { field: e, aggFunc: i }]), this.removeFromOtherZones(e, "values"), this.isActive && this.refresh(), this.refreshPanel();
898
+ }
899
+ removeValueField(e) {
900
+ this.config.valueFields = (this.config.valueFields ?? []).filter((i) => i.field !== e), this.isActive && this.refresh(), this.refreshPanel();
901
+ }
902
+ updateValueAggFunc(e, i) {
903
+ const o = this.config.valueFields ?? [], n = o.findIndex((r) => r.field === e);
904
+ n >= 0 && (o[n] = { ...o[n], aggFunc: i }, this.config.valueFields = [...o]), this.isActive && this.refresh();
905
+ }
372
906
  // ===== Styles =====
373
- styles = `
374
- [data-pivot-depth="1"] { padding-left: 20px; }
375
- [data-pivot-depth="2"] { padding-left: 40px; }
376
- [data-pivot-depth="3"] { padding-left: 60px; }
377
- .pivot-group-row { font-weight: bold; background: var(--tbw-pivot-group-bg, var(--tbw-color-panel-bg)); }
378
- .pivot-total-row { font-weight: bold; border-top: 2px solid var(--tbw-pivot-border, var(--tbw-color-border-strong)); }
379
- `;
907
+ styles = Q;
380
908
  }
381
909
  export {
382
- T as PivotPlugin
910
+ b as PivotPlugin
383
911
  };
384
912
  //# sourceMappingURL=index.js.map