@toolbox-web/grid 1.21.0 → 1.21.2

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 (109) hide show
  1. package/all.js +2 -6850
  2. package/all.js.map +1 -1
  3. package/index.js +1 -4352
  4. package/index.js.map +1 -1
  5. package/lib/core/grid.d.ts +22 -6
  6. package/lib/core/grid.d.ts.map +1 -1
  7. package/lib/core/styles/index.d.ts.map +1 -1
  8. package/lib/plugins/clipboard/index.js +1 -733
  9. package/lib/plugins/clipboard/index.js.map +1 -1
  10. package/lib/plugins/column-virtualization/index.js +1 -560
  11. package/lib/plugins/column-virtualization/index.js.map +1 -1
  12. package/lib/plugins/context-menu/index.js +1 -754
  13. package/lib/plugins/context-menu/index.js.map +1 -1
  14. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  15. package/lib/plugins/editing/index.d.ts +1 -1
  16. package/lib/plugins/editing/index.d.ts.map +1 -1
  17. package/lib/plugins/editing/index.js +1 -1539
  18. package/lib/plugins/editing/index.js.map +1 -1
  19. package/lib/plugins/editing/types.d.ts +23 -0
  20. package/lib/plugins/editing/types.d.ts.map +1 -1
  21. package/lib/plugins/export/index.js +1 -589
  22. package/lib/plugins/export/index.js.map +1 -1
  23. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  24. package/lib/plugins/filtering/filter-model.d.ts.map +1 -1
  25. package/lib/plugins/filtering/index.js +1 -1283
  26. package/lib/plugins/filtering/index.js.map +1 -1
  27. package/lib/plugins/filtering/types.d.ts +4 -2
  28. package/lib/plugins/filtering/types.d.ts.map +1 -1
  29. package/lib/plugins/grouping-columns/index.js +1 -726
  30. package/lib/plugins/grouping-columns/index.js.map +1 -1
  31. package/lib/plugins/grouping-rows/index.js +2 -905
  32. package/lib/plugins/grouping-rows/index.js.map +1 -1
  33. package/lib/plugins/master-detail/index.js +1 -950
  34. package/lib/plugins/master-detail/index.js.map +1 -1
  35. package/lib/plugins/multi-sort/index.js +1 -553
  36. package/lib/plugins/multi-sort/index.js.map +1 -1
  37. package/lib/plugins/pinned-columns/index.js +1 -688
  38. package/lib/plugins/pinned-columns/index.js.map +1 -1
  39. package/lib/plugins/pinned-rows/index.js +1 -704
  40. package/lib/plugins/pinned-rows/index.js.map +1 -1
  41. package/lib/plugins/pivot/index.js +1 -1191
  42. package/lib/plugins/pivot/index.js.map +1 -1
  43. package/lib/plugins/print/index.js +1 -691
  44. package/lib/plugins/print/index.js.map +1 -1
  45. package/lib/plugins/reorder/index.js +1 -703
  46. package/lib/plugins/reorder/index.js.map +1 -1
  47. package/lib/plugins/responsive/index.js +1 -971
  48. package/lib/plugins/responsive/index.js.map +1 -1
  49. package/lib/plugins/row-reorder/index.js +1 -728
  50. package/lib/plugins/row-reorder/index.js.map +1 -1
  51. package/lib/plugins/selection/index.js +1 -1071
  52. package/lib/plugins/selection/index.js.map +1 -1
  53. package/lib/plugins/server-side/index.js +1 -521
  54. package/lib/plugins/server-side/index.js.map +1 -1
  55. package/lib/plugins/tree/index.js +1 -686
  56. package/lib/plugins/tree/index.js.map +1 -1
  57. package/lib/plugins/undo-redo/index.js +1 -584
  58. package/lib/plugins/undo-redo/index.js.map +1 -1
  59. package/lib/plugins/visibility/index.js +1 -792
  60. package/lib/plugins/visibility/index.js.map +1 -1
  61. package/package.json +4 -5
  62. package/umd/grid.all.umd.js +1 -186
  63. package/umd/grid.all.umd.js.map +1 -1
  64. package/umd/grid.umd.js +1 -90
  65. package/umd/grid.umd.js.map +1 -1
  66. package/umd/plugins/clipboard.umd.js +1 -6
  67. package/umd/plugins/clipboard.umd.js.map +1 -1
  68. package/umd/plugins/column-virtualization.umd.js +1 -1
  69. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  70. package/umd/plugins/context-menu.umd.js +1 -1
  71. package/umd/plugins/context-menu.umd.js.map +1 -1
  72. package/umd/plugins/editing.umd.js +1 -1
  73. package/umd/plugins/editing.umd.js.map +1 -1
  74. package/umd/plugins/export.umd.js +1 -13
  75. package/umd/plugins/export.umd.js.map +1 -1
  76. package/umd/plugins/filtering.umd.js +1 -1
  77. package/umd/plugins/filtering.umd.js.map +1 -1
  78. package/umd/plugins/grouping-columns.umd.js +1 -1
  79. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  80. package/umd/plugins/grouping-rows.umd.js +1 -4
  81. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  82. package/umd/plugins/master-detail.umd.js +1 -1
  83. package/umd/plugins/master-detail.umd.js.map +1 -1
  84. package/umd/plugins/multi-sort.umd.js +1 -1
  85. package/umd/plugins/multi-sort.umd.js.map +1 -1
  86. package/umd/plugins/pinned-columns.umd.js +1 -1
  87. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  88. package/umd/plugins/pinned-rows.umd.js +1 -1
  89. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  90. package/umd/plugins/pivot.umd.js +1 -1
  91. package/umd/plugins/pivot.umd.js.map +1 -1
  92. package/umd/plugins/print.umd.js +1 -75
  93. package/umd/plugins/print.umd.js.map +1 -1
  94. package/umd/plugins/reorder.umd.js +1 -1
  95. package/umd/plugins/reorder.umd.js.map +1 -1
  96. package/umd/plugins/responsive.umd.js +1 -1
  97. package/umd/plugins/responsive.umd.js.map +1 -1
  98. package/umd/plugins/row-reorder.umd.js +1 -1
  99. package/umd/plugins/row-reorder.umd.js.map +1 -1
  100. package/umd/plugins/selection.umd.js +1 -3
  101. package/umd/plugins/selection.umd.js.map +1 -1
  102. package/umd/plugins/server-side.umd.js +1 -1
  103. package/umd/plugins/server-side.umd.js.map +1 -1
  104. package/umd/plugins/tree.umd.js +1 -1
  105. package/umd/plugins/tree.umd.js.map +1 -1
  106. package/umd/plugins/undo-redo.umd.js +1 -1
  107. package/umd/plugins/undo-redo.umd.js.map +1 -1
  108. package/umd/plugins/visibility.umd.js +1 -1
  109. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,1192 +1,2 @@
1
- const A = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', P = {
2
- expand: "▶",
3
- collapse: "▼",
4
- sortAsc: "▲",
5
- sortDesc: "▼",
6
- sortNone: "⇅",
7
- submenuArrow: "▶",
8
- dragHandle: "⋮⋮",
9
- toolPanel: "☰",
10
- filter: A,
11
- filterActive: A,
12
- print: "🖨️"
13
- };
14
- class k {
15
- /**
16
- * Plugin dependencies - declare other plugins this one requires.
17
- *
18
- * Dependencies are validated when the plugin is attached.
19
- * Required dependencies throw an error if missing.
20
- * Optional dependencies log an info message if missing.
21
- *
22
- * @example
23
- * ```typescript
24
- * static readonly dependencies: PluginDependency[] = [
25
- * { name: 'editing', required: true, reason: 'Tracks cell edits for undo/redo' },
26
- * { name: 'selection', required: false, reason: 'Enables selection-based undo' },
27
- * ];
28
- * ```
29
- */
30
- static dependencies;
31
- /**
32
- * Plugin manifest - declares owned properties, config rules, and hook priorities.
33
- *
34
- * This is read by the configuration validator to:
35
- * - Validate that required plugins are loaded when their properties are used
36
- * - Execute configRules to detect invalid/conflicting settings
37
- * - Order hook execution based on priority
38
- *
39
- * @example
40
- * ```typescript
41
- * static override readonly manifest: PluginManifest<MyConfig> = {
42
- * ownedProperties: [
43
- * { property: 'myProp', level: 'column', description: 'the "myProp" column property' },
44
- * ],
45
- * configRules: [
46
- * { id: 'myPlugin/conflict', severity: 'warn', message: '...', check: (c) => c.a && c.b },
47
- * ],
48
- * };
49
- * ```
50
- */
51
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
- static manifest;
53
- /**
54
- * Plugin version - defaults to grid version for built-in plugins.
55
- * Third-party plugins can override with their own semver.
56
- */
57
- version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
58
- /** CSS styles to inject into the grid's shadow DOM */
59
- styles;
60
- /** Custom cell renderers keyed by type name */
61
- cellRenderers;
62
- /** Custom header renderers keyed by type name */
63
- headerRenderers;
64
- /** Custom cell editors keyed by type name */
65
- cellEditors;
66
- /** The grid instance this plugin is attached to */
67
- grid;
68
- /** Plugin configuration - merged with defaults in attach() */
69
- config;
70
- /** User-provided configuration from constructor */
71
- userConfig;
72
- /**
73
- * Plugin-level AbortController for event listener cleanup.
74
- * Created fresh in attach(), aborted in detach().
75
- * This ensures event listeners are properly cleaned up when plugins are re-attached.
76
- */
77
- #e;
78
- /**
79
- * Default configuration - subclasses should override this getter.
80
- * Note: This must be a getter (not property initializer) for proper inheritance
81
- * since property initializers run after parent constructor.
82
- */
83
- get defaultConfig() {
84
- return {};
85
- }
86
- constructor(e = {}) {
87
- this.userConfig = e;
88
- }
89
- /**
90
- * Called when the plugin is attached to a grid.
91
- * Override to set up event listeners, initialize state, etc.
92
- *
93
- * @example
94
- * ```ts
95
- * attach(grid: GridElement): void {
96
- * super.attach(grid);
97
- * // Set up document-level listeners with auto-cleanup
98
- * document.addEventListener('keydown', this.handleEscape, {
99
- * signal: this.disconnectSignal
100
- * });
101
- * }
102
- * ```
103
- */
104
- attach(e) {
105
- this.#e?.abort(), this.#e = new AbortController(), this.grid = e, this.config = { ...this.defaultConfig, ...this.userConfig };
106
- }
107
- /**
108
- * Called when the plugin is detached from a grid.
109
- * Override to clean up event listeners, timers, etc.
110
- *
111
- * @example
112
- * ```ts
113
- * detach(): void {
114
- * // Clean up any state not handled by disconnectSignal
115
- * this.selectedRows.clear();
116
- * this.cache = null;
117
- * }
118
- * ```
119
- */
120
- detach() {
121
- this.#e?.abort(), this.#e = void 0;
122
- }
123
- /**
124
- * Get another plugin instance from the same grid.
125
- * Use for inter-plugin communication.
126
- *
127
- * @example
128
- * ```ts
129
- * const selection = this.getPlugin(SelectionPlugin);
130
- * if (selection) {
131
- * const selectedRows = selection.getSelectedRows();
132
- * }
133
- * ```
134
- */
135
- getPlugin(e) {
136
- return this.grid?.getPlugin(e);
137
- }
138
- /**
139
- * Emit a custom event from the grid.
140
- */
141
- emit(e, t) {
142
- this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
143
- }
144
- /**
145
- * Emit a cancelable custom event from the grid.
146
- * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
147
- */
148
- emitCancelable(e, t) {
149
- const o = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
150
- return this.grid?.dispatchEvent?.(o), o.defaultPrevented;
151
- }
152
- // =========================================================================
153
- // Event Bus - Plugin-to-Plugin Communication
154
- // =========================================================================
155
- /**
156
- * Subscribe to an event from another plugin.
157
- * The subscription is automatically cleaned up when this plugin is detached.
158
- *
159
- * @category Plugin Development
160
- * @param eventType - The event type to listen for (e.g., 'filter-change')
161
- * @param callback - The callback to invoke when the event is emitted
162
- *
163
- * @example
164
- * ```typescript
165
- * // In attach() or other initialization
166
- * this.on('filter-change', (detail) => {
167
- * console.log('Filter changed:', detail);
168
- * });
169
- * ```
170
- */
171
- on(e, t) {
172
- this.grid?._pluginManager?.subscribe(this, e, t);
173
- }
174
- /**
175
- * Unsubscribe from a plugin event.
176
- *
177
- * @category Plugin Development
178
- * @param eventType - The event type to stop listening for
179
- *
180
- * @example
181
- * ```typescript
182
- * this.off('filter-change');
183
- * ```
184
- */
185
- off(e) {
186
- this.grid?._pluginManager?.unsubscribe(this, e);
187
- }
188
- /**
189
- * Emit an event to other plugins via the Event Bus.
190
- * This is for inter-plugin communication only; it does NOT dispatch DOM events.
191
- * Use `emit()` to dispatch DOM events that external consumers can listen to.
192
- *
193
- * @category Plugin Development
194
- * @param eventType - The event type to emit (should be declared in manifest.events)
195
- * @param detail - The event payload
196
- *
197
- * @example
198
- * ```typescript
199
- * // Emit to other plugins (not DOM)
200
- * this.emitPluginEvent('filter-change', { field: 'name', value: 'Alice' });
201
- *
202
- * // For DOM events that consumers can addEventListener to:
203
- * this.emit('filter-change', { field: 'name', value: 'Alice' });
204
- * ```
205
- */
206
- emitPluginEvent(e, t) {
207
- this.grid?._pluginManager?.emitPluginEvent(e, t);
208
- }
209
- /**
210
- * Request a re-render of the grid.
211
- * Uses ROWS phase - does NOT trigger processColumns hooks.
212
- */
213
- requestRender() {
214
- this.grid?.requestRender?.();
215
- }
216
- /**
217
- * Request a columns re-render of the grid.
218
- * Uses COLUMNS phase - triggers processColumns hooks.
219
- * Use this when your plugin needs to reprocess column configuration.
220
- */
221
- requestColumnsRender() {
222
- this.grid?.requestColumnsRender?.();
223
- }
224
- /**
225
- * Request a re-render and restore focus styling afterward.
226
- * Use this when a plugin action (like expand/collapse) triggers a render
227
- * but needs to maintain keyboard navigation focus.
228
- */
229
- requestRenderWithFocus() {
230
- this.grid?.requestRenderWithFocus?.();
231
- }
232
- /**
233
- * Request a lightweight style update without rebuilding DOM.
234
- * Use this instead of requestRender() when only CSS classes need updating.
235
- */
236
- requestAfterRender() {
237
- this.grid?.requestAfterRender?.();
238
- }
239
- /**
240
- * Get the current rows from the grid.
241
- */
242
- get rows() {
243
- return this.grid?.rows ?? [];
244
- }
245
- /**
246
- * Get the original unfiltered/unprocessed rows from the grid.
247
- * Use this when you need all source data regardless of active filters.
248
- */
249
- get sourceRows() {
250
- return this.grid?.sourceRows ?? [];
251
- }
252
- /**
253
- * Get the current columns from the grid.
254
- */
255
- get columns() {
256
- return this.grid?.columns ?? [];
257
- }
258
- /**
259
- * Get only visible columns from the grid (excludes hidden).
260
- * Use this for rendering that needs to match the grid template.
261
- */
262
- get visibleColumns() {
263
- return this.grid?._visibleColumns ?? [];
264
- }
265
- /**
266
- * Get the grid as an HTMLElement for direct DOM operations.
267
- * Use sparingly - prefer the typed GridElementRef API when possible.
268
- *
269
- * @example
270
- * ```ts
271
- * const width = this.gridElement.clientWidth;
272
- * this.gridElement.classList.add('my-plugin-active');
273
- * ```
274
- */
275
- get gridElement() {
276
- return this.grid;
277
- }
278
- /**
279
- * Get the disconnect signal for event listener cleanup.
280
- * This signal is aborted when the grid disconnects from the DOM.
281
- * Use this when adding event listeners that should be cleaned up automatically.
282
- *
283
- * Best for:
284
- * - Document/window-level listeners added in attach()
285
- * - Listeners on the grid element itself
286
- * - Any listener that should persist across renders
287
- *
288
- * Not needed for:
289
- * - Listeners on elements created in afterRender() (removed with element)
290
- *
291
- * @example
292
- * element.addEventListener('click', handler, { signal: this.disconnectSignal });
293
- * document.addEventListener('keydown', handler, { signal: this.disconnectSignal });
294
- */
295
- get disconnectSignal() {
296
- return this.#e?.signal ?? this.grid?.disconnectSignal;
297
- }
298
- /**
299
- * Get the grid-level icons configuration.
300
- * Returns merged icons (user config + defaults).
301
- */
302
- get gridIcons() {
303
- const e = this.grid?.gridConfig?.icons ?? {};
304
- return { ...P, ...e };
305
- }
306
- // #region Animation Helpers
307
- /**
308
- * Check if animations are enabled at the grid level.
309
- * Respects gridConfig.animation.mode and the CSS variable set by the grid.
310
- *
311
- * Plugins should use this to skip animations when:
312
- * - Animation mode is 'off' or `false`
313
- * - User prefers reduced motion and mode is 'reduced-motion' (default)
314
- *
315
- * @example
316
- * ```ts
317
- * private get animationStyle(): 'slide' | 'fade' | false {
318
- * if (!this.isAnimationEnabled) return false;
319
- * return this.config.animation ?? 'slide';
320
- * }
321
- * ```
322
- */
323
- get isAnimationEnabled() {
324
- const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
325
- if (e === !1 || e === "off") return !1;
326
- if (e === !0 || e === "on") return !0;
327
- const t = this.gridElement;
328
- return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
329
- }
330
- /**
331
- * Get the animation duration in milliseconds from CSS variable.
332
- * Falls back to 200ms if not set.
333
- *
334
- * Plugins can use this for their animation timing to stay consistent
335
- * with the grid-level animation.duration setting.
336
- *
337
- * @example
338
- * ```ts
339
- * element.animate(keyframes, { duration: this.animationDuration });
340
- * ```
341
- */
342
- get animationDuration() {
343
- const e = this.gridElement;
344
- if (e) {
345
- const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), o = parseInt(t, 10);
346
- if (!isNaN(o)) return o;
347
- }
348
- return 200;
349
- }
350
- // #endregion
351
- /**
352
- * Resolve an icon value to string or HTMLElement.
353
- * Checks plugin config first, then grid-level icons, then defaults.
354
- *
355
- * @param iconKey - The icon key in GridIcons (e.g., 'expand', 'collapse')
356
- * @param pluginOverride - Optional plugin-level override
357
- * @returns The resolved icon value
358
- */
359
- resolveIcon(e, t) {
360
- return t !== void 0 ? t : this.gridIcons[e];
361
- }
362
- /**
363
- * Set an icon value on an element.
364
- * Handles both string (text/HTML) and HTMLElement values.
365
- *
366
- * @param element - The element to set the icon on
367
- * @param icon - The icon value (string or HTMLElement)
368
- */
369
- setIcon(e, t) {
370
- typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
371
- }
372
- /**
373
- * Log a warning message.
374
- */
375
- warn(e) {
376
- console.warn(`[tbw-grid:${this.name}] ${e}`);
377
- }
378
- // #endregion
379
- }
380
- const m = {
381
- sum: (i, e) => i.reduce((t, o) => t + (Number(o[e]) || 0), 0),
382
- avg: (i, e) => {
383
- const t = i.reduce((o, r) => o + (Number(r[e]) || 0), 0);
384
- return i.length ? t / i.length : 0;
385
- },
386
- count: (i) => i.length,
387
- min: (i, e) => i.length ? Math.min(...i.map((t) => Number(t[e]) || 1 / 0)) : 0,
388
- max: (i, e) => i.length ? Math.max(...i.map((t) => Number(t[e]) || -1 / 0)) : 0,
389
- first: (i, e) => i[0]?.[e],
390
- last: (i, e) => i[i.length - 1]?.[e]
391
- }, f = /* @__PURE__ */ new Map(), g = {
392
- /**
393
- * Register a custom aggregator function.
394
- */
395
- register(i, e) {
396
- f.set(i, e);
397
- },
398
- /**
399
- * Unregister a custom aggregator function.
400
- */
401
- unregister(i) {
402
- f.delete(i);
403
- },
404
- /**
405
- * Get an aggregator function by reference.
406
- */
407
- get(i) {
408
- if (i !== void 0)
409
- return typeof i == "function" ? i : f.get(i) ?? m[i];
410
- },
411
- /**
412
- * Run an aggregator on a set of rows.
413
- */
414
- run(i, e, t, o) {
415
- const r = this.get(i);
416
- return r ? r(e, t, o) : void 0;
417
- },
418
- /**
419
- * Check if an aggregator exists.
420
- */
421
- has(i) {
422
- return f.has(i) || i in m;
423
- },
424
- /**
425
- * List all available aggregator names.
426
- */
427
- list() {
428
- return [...Object.keys(m), ...f.keys()];
429
- }
430
- }, _ = {
431
- sum: (i) => i.reduce((e, t) => e + t, 0),
432
- avg: (i) => i.length ? i.reduce((e, t) => e + t, 0) / i.length : 0,
433
- count: (i) => i.length,
434
- min: (i) => i.length ? Math.min(...i) : 0,
435
- max: (i) => i.length ? Math.max(...i) : 0,
436
- first: (i) => i[0] ?? 0,
437
- last: (i) => i[i.length - 1] ?? 0
438
- };
439
- function N(i) {
440
- return _[i] ?? _.sum;
441
- }
442
- g.register.bind(g);
443
- g.unregister.bind(g);
444
- g.get.bind(g);
445
- g.run.bind(g);
446
- g.list.bind(g);
447
- const S = N;
448
- function I(i) {
449
- const e = [];
450
- 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;
451
- }
452
- function C(i, e) {
453
- return [...i, e].join("|");
454
- }
455
- function K(i, e) {
456
- const t = e.rowGroupFields ?? [], o = e.columnGroupFields ?? [], r = e.valueFields ?? [], n = z(i, o), a = G(
457
- i,
458
- t,
459
- o,
460
- n,
461
- r,
462
- 0,
463
- // starting depth
464
- ""
465
- // parent key prefix
466
- ), s = H(a, n, r), l = Object.values(s).reduce((d, c) => d + c, 0);
467
- return {
468
- rows: a,
469
- columnKeys: n,
470
- totals: s,
471
- grandTotal: l
472
- };
473
- }
474
- function z(i, e) {
475
- if (e.length === 0) return ["value"];
476
- const t = /* @__PURE__ */ new Set();
477
- for (const o of i) {
478
- const r = e.map((n) => String(o[n] ?? "")).join("|");
479
- t.add(r);
480
- }
481
- return [...t].sort();
482
- }
483
- function V(i, e) {
484
- const t = /* @__PURE__ */ new Map();
485
- for (const o of i) {
486
- const r = String(o[e] ?? ""), n = t.get(r);
487
- n ? n.push(o) : t.set(r, [o]);
488
- }
489
- return t;
490
- }
491
- function G(i, e, t, o, r, n, a) {
492
- const s = [];
493
- if (e.length === 0) {
494
- const u = R(i, t, o, r), h = T(u);
495
- return s.push({
496
- rowKey: a || "all",
497
- rowLabel: a || "All",
498
- depth: n,
499
- values: u,
500
- total: h,
501
- isGroup: !1,
502
- rowCount: i.length
503
- }), s;
504
- }
505
- const l = e[0], d = e.slice(1), c = d.length > 0, p = V(i, l);
506
- for (const [u, h] of p) {
507
- const y = a ? `${a}|${u}` : u, x = R(h, t, o, r), L = T(x);
508
- let F;
509
- c && (F = G(
510
- h,
511
- d,
512
- t,
513
- o,
514
- r,
515
- n + 1,
516
- y
517
- )), s.push({
518
- rowKey: y,
519
- rowLabel: u || "(blank)",
520
- depth: n,
521
- values: x,
522
- total: L,
523
- isGroup: c,
524
- children: F,
525
- rowCount: h.length
526
- });
527
- }
528
- return s;
529
- }
530
- function R(i, e, t, o) {
531
- const r = {};
532
- for (const n of t)
533
- for (const a of o) {
534
- 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 = S(a.aggFunc), c = l.length > 0 ? d(l) : null, p = C([n], a.field);
535
- r[p] = c;
536
- }
537
- return r;
538
- }
539
- function T(i) {
540
- let e = 0;
541
- for (const t of Object.values(i))
542
- e += t ?? 0;
543
- return e;
544
- }
545
- function H(i, e, t) {
546
- const o = {};
547
- function r(n) {
548
- for (const a of n)
549
- if (!a.isGroup || !a.children?.length)
550
- for (const s of e)
551
- for (const l of t) {
552
- const d = C([s], l.field);
553
- o[d] = (o[d] ?? 0) + (a.values[d] ?? 0);
554
- }
555
- else a.children && r(a.children);
556
- }
557
- return r(i), o;
558
- }
559
- function D(i, e, t = !0) {
560
- const o = [];
561
- function r(n) {
562
- o.push(n);
563
- const a = e ? e.has(n.rowKey) : t;
564
- if (n.children && a)
565
- for (const s of n.children)
566
- r(s);
567
- }
568
- for (const n of i)
569
- r(n);
570
- return o;
571
- }
572
- function M(i) {
573
- const e = [];
574
- function t(o) {
575
- if (o.isGroup && e.push(o.rowKey), o.children)
576
- for (const r of o.children)
577
- t(r);
578
- }
579
- for (const o of i)
580
- t(o);
581
- return e;
582
- }
583
- const q = ["sum", "avg", "count", "min", "max", "first", "last"];
584
- function O(i, e, t, o) {
585
- const r = new AbortController(), n = { config: e, callbacks: o, signal: r.signal }, a = document.createElement("div");
586
- return a.className = "tbw-pivot-panel", a.appendChild(b("Options", () => W(t, n))), a.appendChild(b("Row Groups", () => E("rowGroups", n))), a.appendChild(b("Column Groups", () => E("columnGroups", n))), a.appendChild(b("Values", () => $(n))), a.appendChild(b("Available Fields", () => U(n))), i.appendChild(a), () => {
587
- r.abort(), a.remove();
588
- };
589
- }
590
- function b(i, e) {
591
- const t = document.createElement("div");
592
- t.className = "tbw-pivot-section";
593
- const o = document.createElement("div");
594
- o.className = "tbw-pivot-section-header", o.textContent = i;
595
- const r = document.createElement("div");
596
- return r.className = "tbw-pivot-section-content", r.appendChild(e()), t.appendChild(o), t.appendChild(r), t;
597
- }
598
- function E(i, e) {
599
- const { config: t, callbacks: o, signal: r } = e, n = document.createElement("div");
600
- n.className = "tbw-pivot-drop-zone", n.setAttribute("data-zone", i);
601
- const a = i === "rowGroups" ? t.rowGroupFields ?? [] : t.columnGroupFields ?? [];
602
- if (a.length === 0) {
603
- const s = document.createElement("div");
604
- s.className = "tbw-pivot-placeholder", s.textContent = "Drag fields here or click to add", n.appendChild(s);
605
- } else
606
- for (const s of a)
607
- n.appendChild(Z(s, i, e));
608
- return n.addEventListener(
609
- "dragover",
610
- (s) => {
611
- s.preventDefault(), n.classList.add("drag-over");
612
- },
613
- { signal: r }
614
- ), n.addEventListener(
615
- "dragleave",
616
- () => {
617
- n.classList.remove("drag-over");
618
- },
619
- { signal: r }
620
- ), n.addEventListener(
621
- "drop",
622
- (s) => {
623
- s.preventDefault(), n.classList.remove("drag-over");
624
- const l = s.dataTransfer?.getData("text/plain");
625
- l && o.onAddFieldToZone(l, i);
626
- },
627
- { signal: r }
628
- ), n;
629
- }
630
- function Z(i, e, t) {
631
- const { callbacks: o, signal: r } = t, n = document.createElement("div");
632
- n.className = "tbw-pivot-field-chip", n.draggable = !0;
633
- const a = o.getAvailableFields().find((d) => d.field === i), s = document.createElement("span");
634
- s.className = "tbw-pivot-chip-label", s.textContent = a?.header ?? i;
635
- const l = document.createElement("button");
636
- return l.className = "tbw-pivot-chip-remove", l.innerHTML = "×", l.title = "Remove field", l.addEventListener(
637
- "click",
638
- (d) => {
639
- d.stopPropagation(), o.onRemoveFieldFromZone(i, e);
640
- },
641
- { signal: r }
642
- ), n.appendChild(s), n.appendChild(l), n.addEventListener(
643
- "dragstart",
644
- (d) => {
645
- d.dataTransfer?.setData("text/plain", i), d.dataTransfer?.setData("source-zone", e), n.classList.add("dragging");
646
- },
647
- { signal: r }
648
- ), n.addEventListener(
649
- "dragend",
650
- () => {
651
- n.classList.remove("dragging");
652
- },
653
- { signal: r }
654
- ), n;
655
- }
656
- function $(i) {
657
- const { config: e, callbacks: t, signal: o } = i, r = document.createElement("div");
658
- r.className = "tbw-pivot-drop-zone tbw-pivot-values-zone", r.setAttribute("data-zone", "values");
659
- const n = e.valueFields ?? [];
660
- if (n.length === 0) {
661
- const a = document.createElement("div");
662
- a.className = "tbw-pivot-placeholder", a.textContent = "Drag numeric fields here for aggregation", r.appendChild(a);
663
- } else
664
- for (const a of n)
665
- r.appendChild(j(a, i));
666
- return r.addEventListener(
667
- "dragover",
668
- (a) => {
669
- a.preventDefault(), r.classList.add("drag-over");
670
- },
671
- { signal: o }
672
- ), r.addEventListener(
673
- "dragleave",
674
- () => {
675
- r.classList.remove("drag-over");
676
- },
677
- { signal: o }
678
- ), r.addEventListener(
679
- "drop",
680
- (a) => {
681
- a.preventDefault(), r.classList.remove("drag-over");
682
- const s = a.dataTransfer?.getData("text/plain");
683
- s && t.onAddValueField(s, "sum");
684
- },
685
- { signal: o }
686
- ), r;
687
- }
688
- function j(i, e) {
689
- const { callbacks: t, signal: o } = e, r = document.createElement("div");
690
- r.className = "tbw-pivot-field-chip tbw-pivot-value-chip";
691
- const n = t.getAvailableFields().find((c) => c.field === i.field), a = document.createElement("div");
692
- a.className = "tbw-pivot-value-label-wrapper";
693
- const s = document.createElement("span");
694
- s.className = "tbw-pivot-chip-label", s.textContent = n?.header ?? i.field;
695
- const l = document.createElement("select");
696
- l.className = "tbw-pivot-agg-select", l.title = "Aggregation function";
697
- for (const c of q) {
698
- const p = document.createElement("option");
699
- p.value = c, p.textContent = c.toUpperCase(), p.selected = c === i.aggFunc, l.appendChild(p);
700
- }
701
- l.addEventListener(
702
- "change",
703
- () => {
704
- t.onUpdateValueAggFunc(i.field, l.value);
705
- },
706
- { signal: o }
707
- );
708
- const d = document.createElement("button");
709
- return d.className = "tbw-pivot-chip-remove", d.innerHTML = "×", d.title = "Remove value field", d.addEventListener(
710
- "click",
711
- (c) => {
712
- c.stopPropagation(), t.onRemoveValueField(i.field);
713
- },
714
- { signal: o }
715
- ), a.appendChild(s), a.appendChild(l), r.appendChild(a), r.appendChild(d), r;
716
- }
717
- function U(i) {
718
- const { config: e, callbacks: t, signal: o } = i, r = document.createElement("div");
719
- r.className = "tbw-pivot-available-fields";
720
- const n = t.getAvailableFields(), a = /* @__PURE__ */ new Set([
721
- ...e.rowGroupFields ?? [],
722
- ...e.columnGroupFields ?? [],
723
- ...e.valueFields?.map((l) => l.field) ?? []
724
- ]), s = n.filter((l) => !a.has(l.field));
725
- if (s.length === 0) {
726
- const l = document.createElement("div");
727
- l.className = "tbw-pivot-placeholder", l.textContent = "All fields are in use", r.appendChild(l);
728
- } else
729
- for (const l of s) {
730
- const d = document.createElement("div");
731
- 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(
732
- "dragstart",
733
- (c) => {
734
- c.dataTransfer?.setData("text/plain", l.field), d.classList.add("dragging");
735
- },
736
- { signal: o }
737
- ), d.addEventListener(
738
- "dragend",
739
- () => {
740
- d.classList.remove("dragging");
741
- },
742
- { signal: o }
743
- ), r.appendChild(d);
744
- }
745
- return r;
746
- }
747
- function W(i, e) {
748
- const { config: t, callbacks: o, signal: r } = e, n = document.createElement("div");
749
- return n.className = "tbw-pivot-options", n.appendChild(
750
- w(
751
- "Enable Pivot View",
752
- i,
753
- (a) => {
754
- o.onTogglePivot(a);
755
- },
756
- r
757
- )
758
- ), n.appendChild(
759
- w(
760
- "Show Row Totals",
761
- t.showTotals ?? !0,
762
- (a) => {
763
- o.onOptionChange("showTotals", a);
764
- },
765
- r
766
- )
767
- ), n.appendChild(
768
- w(
769
- "Show Grand Total",
770
- t.showGrandTotal ?? !0,
771
- (a) => {
772
- o.onOptionChange("showGrandTotal", a);
773
- },
774
- r
775
- )
776
- ), n;
777
- }
778
- function w(i, e, t, o) {
779
- const r = document.createElement("label");
780
- r.className = "tbw-pivot-checkbox";
781
- const n = document.createElement("input");
782
- n.type = "checkbox", n.checked = e, n.addEventListener("change", () => t(n.checked), { signal: o });
783
- const a = document.createElement("span");
784
- return a.textContent = i, r.appendChild(n), r.appendChild(a), r;
785
- }
786
- function B(i, e, t) {
787
- 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) => {
788
- const n = document.createElement("div");
789
- if (n.className = "cell", n.setAttribute("data-col", String(r)), n.setAttribute("data-row", String(t.rowIndex)), n.setAttribute("role", "gridcell"), r === 0) {
790
- const a = Number(i.__pivotIndent) || 0;
791
- n.style.paddingLeft = `${a}px`;
792
- const s = String(i.__pivotRowKey), l = document.createElement("button");
793
- 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) => {
794
- p.stopPropagation(), t.onToggle(s);
795
- }), n.appendChild(l);
796
- const d = document.createElement("span");
797
- d.className = "pivot-label", d.textContent = String(i.__pivotLabel ?? ""), n.appendChild(d);
798
- const c = document.createElement("span");
799
- c.className = "pivot-count", c.textContent = ` (${Number(i.__pivotRowCount) || 0})`, n.appendChild(c);
800
- } else {
801
- const a = i[o.field];
802
- n.textContent = a != null ? String(a) : "";
803
- }
804
- e.appendChild(n);
805
- }), !0;
806
- }
807
- function J(i, e, t, o) {
808
- 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) => {
809
- const a = document.createElement("div");
810
- if (a.className = "cell", a.setAttribute("data-col", String(n)), a.setAttribute("data-row", String(o)), a.setAttribute("role", "gridcell"), n === 0) {
811
- const s = Number(i.__pivotIndent) || 0;
812
- a.style.paddingLeft = `${s + 20}px`;
813
- const l = document.createElement("span");
814
- l.className = "pivot-label", l.textContent = String(i.__pivotLabel ?? ""), a.appendChild(l);
815
- } else {
816
- const s = i[r.field];
817
- a.textContent = s != null ? String(s) : "";
818
- }
819
- e.appendChild(a);
820
- }), !0;
821
- }
822
- function Q(i, e, t) {
823
- return e.className = "pivot-grand-total-row", e.setAttribute("role", "presentation"), e.innerHTML = "", t.forEach((o, r) => {
824
- const n = document.createElement("div");
825
- if (n.className = "cell", n.setAttribute("data-col", String(r)), r === 0) {
826
- const a = document.createElement("span");
827
- a.className = "pivot-label", a.textContent = "Grand Total", n.appendChild(a);
828
- } else {
829
- const a = i[o.field];
830
- n.textContent = a != null ? String(a) : "";
831
- }
832
- e.appendChild(n);
833
- }), !0;
834
- }
835
- const X = '@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:var(--tbw-pivot-toggle-size, var(--tbw-toggle-size, 1.25em));height:var(--tbw-pivot-toggle-size, var(--tbw-toggle-size, 1.25em));margin-right:var(--tbw-spacing-sm, .375em);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 var(--tbw-transition-duration, .12s) var(--tbw-transition-ease, ease),color var(--tbw-transition-duration, .12s) var(--tbw-transition-ease, ease)}.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}}}';
836
- class v extends k {
837
- /** @internal */
838
- name = "pivot";
839
- /** @internal */
840
- styles = X;
841
- /** Tool panel ID for shell integration */
842
- static PANEL_ID = "pivot";
843
- /** @internal */
844
- get defaultConfig() {
845
- return {
846
- active: !0,
847
- showTotals: !0,
848
- showGrandTotal: !0,
849
- showToolPanel: !0,
850
- animation: "slide"
851
- };
852
- }
853
- // #region Internal State
854
- isActive = !1;
855
- hasInitialized = !1;
856
- pivotResult = null;
857
- fieldHeaderMap = /* @__PURE__ */ new Map();
858
- expandedKeys = /* @__PURE__ */ new Set();
859
- defaultExpanded = !0;
860
- /** Tracks whether user has manually interacted with expand/collapse */
861
- userHasToggledExpand = !1;
862
- originalColumns = [];
863
- panelContainer = null;
864
- grandTotalFooter = null;
865
- previousVisibleKeys = /* @__PURE__ */ new Set();
866
- keysToAnimate = /* @__PURE__ */ new Set();
867
- /**
868
- * Check if the plugin has valid pivot configuration (at least value fields).
869
- */
870
- hasValidPivotConfig() {
871
- return (this.config.valueFields?.length ?? 0) > 0;
872
- }
873
- /**
874
- * Get expand/collapse animation style from plugin config.
875
- * Uses base class isAnimationEnabled to respect grid-level settings.
876
- */
877
- get animationStyle() {
878
- return this.isAnimationEnabled ? this.config.animation ?? "slide" : !1;
879
- }
880
- // #endregion
881
- // #region Lifecycle
882
- /** @internal */
883
- detach() {
884
- this.isActive = !1, this.hasInitialized = !1, this.pivotResult = null, this.fieldHeaderMap.clear(), this.originalColumns = [], this.panelContainer = null, this.cleanupGrandTotalFooter(), this.previousVisibleKeys.clear(), this.keysToAnimate.clear(), this.userHasToggledExpand = !1;
885
- }
886
- // #endregion
887
- // #region Shell Integration
888
- /** @internal */
889
- getToolPanel() {
890
- if ((this.config?.showToolPanel ?? this.userConfig?.showToolPanel ?? !0) !== !1)
891
- return {
892
- id: v.PANEL_ID,
893
- title: "Pivot",
894
- icon: "⊞",
895
- tooltip: "Configure pivot table",
896
- order: 90,
897
- render: (t) => this.renderPanel(t)
898
- };
899
- }
900
- // #endregion
901
- // #region Hooks
902
- /** @internal */
903
- processRows(e) {
904
- if (!this.hasInitialized && this.config.active !== !1 && this.hasValidPivotConfig() && (this.hasInitialized = !0, this.isActive = !0), !this.isActive)
905
- return [...e];
906
- const t = I(this.config);
907
- if (t.length > 0)
908
- return this.warn(`Config errors: ${t.join(", ")}`), [...e];
909
- this.buildFieldHeaderMap(), this.defaultExpanded = this.config.defaultExpanded ?? !0, this.pivotResult = K(e, this.config), this.expandedKeys.size === 0 && this.defaultExpanded && !this.userHasToggledExpand && this.expandAllKeys();
910
- const o = this.config.indentWidth ?? 20, r = D(
911
- this.pivotResult.rows,
912
- this.expandedKeys,
913
- this.defaultExpanded
914
- ).map((a) => ({
915
- __pivotRowKey: a.rowKey,
916
- __pivotLabel: a.rowLabel,
917
- __pivotDepth: a.depth,
918
- __pivotIsGroup: a.isGroup,
919
- __pivotHasChildren: !!a.children?.length,
920
- __pivotExpanded: this.expandedKeys.has(a.rowKey),
921
- __pivotRowCount: a.rowCount ?? 0,
922
- __pivotIndent: a.depth * o,
923
- __pivotTotal: a.total,
924
- ...a.values
925
- }));
926
- this.keysToAnimate.clear();
927
- const n = /* @__PURE__ */ new Set();
928
- for (const a of r) {
929
- const s = a.__pivotRowKey;
930
- n.add(s), !this.previousVisibleKeys.has(s) && a.__pivotDepth > 0 && this.keysToAnimate.add(s);
931
- }
932
- return this.previousVisibleKeys = n, r;
933
- }
934
- /** @internal */
935
- processColumns(e) {
936
- if (!this.isActive || !this.pivotResult)
937
- return [...e];
938
- const t = [], o = (this.config.rowGroupFields ?? []).map((r) => this.fieldHeaderMap.get(r) ?? r).join(" / ");
939
- t.push({
940
- field: "__pivotLabel",
941
- header: o || "Group",
942
- width: 200
943
- });
944
- for (const r of this.pivotResult.columnKeys)
945
- for (const n of this.config.valueFields ?? []) {
946
- const a = C([r], n.field), s = n.header || this.fieldHeaderMap.get(n.field) || n.field;
947
- t.push({
948
- field: a,
949
- header: `${r} - ${s} (${n.aggFunc})`,
950
- width: 120,
951
- type: "number"
952
- });
953
- }
954
- return this.config.showTotals && t.push({
955
- field: "__pivotTotal",
956
- header: "Total",
957
- width: 100,
958
- type: "number"
959
- }), t;
960
- }
961
- /** @internal */
962
- renderRow(e, t, o) {
963
- const r = e;
964
- return r.__pivotRowKey && r.__pivotHasChildren ? B(r, t, {
965
- columns: this.gridColumns,
966
- rowIndex: o,
967
- onToggle: (n) => this.toggle(n),
968
- resolveIcon: (n) => this.resolveIcon(n),
969
- setIcon: (n, a) => this.setIcon(n, a)
970
- }) : r.__pivotRowKey !== void 0 && this.isActive ? J(r, t, this.gridColumns, o) : (this.cleanupPivotStyling(t), !1);
971
- }
972
- /**
973
- * Remove pivot-specific classes, attributes, and inline styles from a row element.
974
- * Called when pivot mode is disabled to clean up reused DOM elements.
975
- * Clears innerHTML so the grid's default renderer can rebuild the row.
976
- */
977
- cleanupPivotStyling(e) {
978
- (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 = "");
979
- }
980
- /** @internal */
981
- onKeyDown(e) {
982
- if (e.key !== " " || !this.isActive) return;
983
- const t = this.grid._focusRow, o = this.rows[t];
984
- if (!(!o?.__pivotIsGroup || !o.__pivotHasChildren))
985
- return e.preventDefault(), this.toggle(o.__pivotRowKey), this.requestRenderWithFocus(), !0;
986
- }
987
- /** @internal */
988
- afterRender() {
989
- this.isActive && this.config.showGrandTotal && this.pivotResult ? this.renderGrandTotalFooter() : this.cleanupGrandTotalFooter();
990
- const e = this.animationStyle;
991
- if (e === !1 || this.keysToAnimate.size === 0) return;
992
- const t = this.gridElement?.querySelector(".rows");
993
- if (!t) return;
994
- const o = e === "fade" ? "tbw-pivot-fade-in" : "tbw-pivot-slide-in";
995
- for (const r of t.querySelectorAll(".pivot-group-row, .pivot-leaf-row")) {
996
- const n = r.dataset.pivotKey;
997
- n && this.keysToAnimate.has(n) && (r.classList.add(o), r.addEventListener("animationend", () => r.classList.remove(o), { once: !0 }));
998
- }
999
- this.keysToAnimate.clear();
1000
- }
1001
- /**
1002
- * Render the grand total row as a sticky footer pinned to the bottom.
1003
- */
1004
- renderGrandTotalFooter() {
1005
- if (!this.pivotResult) return;
1006
- const e = this.gridElement;
1007
- if (!e) return;
1008
- const t = e.querySelector(".tbw-scroll-area") ?? e.querySelector(".tbw-grid-content") ?? e.children[0];
1009
- if (!t) return;
1010
- this.grandTotalFooter || (this.grandTotalFooter = document.createElement("div"), this.grandTotalFooter.className = "pivot-grand-total-footer", t.appendChild(this.grandTotalFooter));
1011
- const o = {
1012
- __pivotRowKey: "__grandTotal",
1013
- __pivotLabel: "Grand Total",
1014
- __pivotIsGrandTotal: !0,
1015
- __pivotTotal: this.pivotResult.grandTotal,
1016
- ...this.pivotResult.totals
1017
- };
1018
- Q(o, this.grandTotalFooter, this.gridColumns);
1019
- }
1020
- /**
1021
- * Remove the grand total footer element.
1022
- */
1023
- cleanupGrandTotalFooter() {
1024
- this.grandTotalFooter && (this.grandTotalFooter.remove(), this.grandTotalFooter = null);
1025
- }
1026
- // #endregion
1027
- // #region Expand/Collapse API
1028
- toggle(e) {
1029
- this.userHasToggledExpand = !0, this.expandedKeys.has(e) ? this.expandedKeys.delete(e) : this.expandedKeys.add(e), this.requestRender();
1030
- }
1031
- expand(e) {
1032
- this.userHasToggledExpand = !0, this.expandedKeys.add(e), this.requestRender();
1033
- }
1034
- collapse(e) {
1035
- this.userHasToggledExpand = !0, this.expandedKeys.delete(e), this.requestRender();
1036
- }
1037
- expandAll() {
1038
- this.userHasToggledExpand = !0, this.expandAllKeys(), this.requestRender();
1039
- }
1040
- collapseAll() {
1041
- this.userHasToggledExpand = !0, this.expandedKeys.clear(), this.requestRender();
1042
- }
1043
- /**
1044
- * Add all group keys from the current pivot result to expandedKeys.
1045
- */
1046
- expandAllKeys() {
1047
- if (!this.pivotResult) return;
1048
- const e = M(this.pivotResult.rows);
1049
- for (const t of e)
1050
- this.expandedKeys.add(t);
1051
- }
1052
- isExpanded(e) {
1053
- return this.expandedKeys.has(e);
1054
- }
1055
- // #endregion
1056
- // #region Public API
1057
- enablePivot() {
1058
- this.originalColumns.length === 0 && this.captureOriginalColumns(), this.isActive = !0, this.requestRender();
1059
- }
1060
- disablePivot() {
1061
- this.isActive = !1, this.pivotResult = null, this.requestRender();
1062
- }
1063
- isPivotActive() {
1064
- return this.isActive;
1065
- }
1066
- getPivotResult() {
1067
- return this.pivotResult;
1068
- }
1069
- setRowGroupFields(e) {
1070
- this.config.rowGroupFields = e, this.requestRender();
1071
- }
1072
- setColumnGroupFields(e) {
1073
- this.config.columnGroupFields = e, this.requestRender();
1074
- }
1075
- setValueFields(e) {
1076
- this.config.valueFields = e, this.requestRender();
1077
- }
1078
- refresh() {
1079
- this.pivotResult = null, this.requestRender();
1080
- }
1081
- // #endregion
1082
- // #region Tool Panel API
1083
- /**
1084
- * Show the pivot tool panel.
1085
- * Opens the tool panel and ensures this section is expanded.
1086
- */
1087
- showPanel() {
1088
- this.grid.openToolPanel(), this.grid.expandedToolPanelSections.includes(v.PANEL_ID) || this.grid.toggleToolPanelSection(v.PANEL_ID);
1089
- }
1090
- /**
1091
- * Hide the tool panel.
1092
- */
1093
- hidePanel() {
1094
- this.grid.closeToolPanel();
1095
- }
1096
- /**
1097
- * Toggle the pivot tool panel section.
1098
- */
1099
- togglePanel() {
1100
- this.grid.isToolPanelOpen || this.grid.openToolPanel(), this.grid.toggleToolPanelSection(v.PANEL_ID);
1101
- }
1102
- /**
1103
- * Check if the pivot panel section is currently expanded.
1104
- */
1105
- isPanelVisible() {
1106
- return this.grid.isToolPanelOpen && this.grid.expandedToolPanelSections.includes(v.PANEL_ID);
1107
- }
1108
- // #endregion
1109
- // #region Private Helpers
1110
- get gridColumns() {
1111
- return this.grid.columns ?? [];
1112
- }
1113
- /**
1114
- * Refresh pivot and update tool panel if active.
1115
- */
1116
- refreshIfActive() {
1117
- this.isActive && this.refresh(), this.refreshPanel();
1118
- }
1119
- buildFieldHeaderMap() {
1120
- const e = this.getAvailableFields();
1121
- this.fieldHeaderMap.clear();
1122
- for (const t of e)
1123
- this.fieldHeaderMap.set(t.field, t.header);
1124
- }
1125
- getAvailableFields() {
1126
- return this.originalColumns.length > 0 ? this.originalColumns : this.captureOriginalColumns();
1127
- }
1128
- captureOriginalColumns() {
1129
- try {
1130
- const e = this.grid.getAllColumns?.() ?? this.grid.columns ?? [];
1131
- return this.originalColumns = e.filter((t) => !t.field.startsWith("__pivot")).map((t) => ({
1132
- field: t.field,
1133
- header: t.header ?? t.field
1134
- })), this.originalColumns;
1135
- } catch {
1136
- return [];
1137
- }
1138
- }
1139
- renderPanel(e) {
1140
- this.panelContainer = e, this.originalColumns.length === 0 && this.captureOriginalColumns();
1141
- const t = {
1142
- onTogglePivot: (o) => {
1143
- o ? this.enablePivot() : this.disablePivot(), this.refreshPanel();
1144
- },
1145
- onAddFieldToZone: (o, r) => this.addFieldToZone(o, r),
1146
- onRemoveFieldFromZone: (o, r) => this.removeFieldFromZone(o, r),
1147
- onAddValueField: (o, r) => this.addValueField(o, r),
1148
- onRemoveValueField: (o) => this.removeValueField(o),
1149
- onUpdateValueAggFunc: (o, r) => this.updateValueAggFunc(o, r),
1150
- onOptionChange: (o, r) => {
1151
- this.config[o] = r, this.isActive && this.refresh();
1152
- },
1153
- getAvailableFields: () => this.getAvailableFields()
1154
- };
1155
- return O(e, this.config, this.isActive, t);
1156
- }
1157
- refreshPanel() {
1158
- this.panelContainer && (this.panelContainer.innerHTML = "", this.renderPanel(this.panelContainer));
1159
- }
1160
- addFieldToZone(e, t) {
1161
- if (t === "rowGroups") {
1162
- const o = this.config.rowGroupFields ?? [];
1163
- o.includes(e) || (this.config.rowGroupFields = [...o, e]);
1164
- } else {
1165
- const o = this.config.columnGroupFields ?? [];
1166
- o.includes(e) || (this.config.columnGroupFields = [...o, e]);
1167
- }
1168
- this.removeFromOtherZones(e, t), this.refreshIfActive();
1169
- }
1170
- removeFieldFromZone(e, t) {
1171
- t === "rowGroups" ? this.config.rowGroupFields = (this.config.rowGroupFields ?? []).filter((o) => o !== e) : this.config.columnGroupFields = (this.config.columnGroupFields ?? []).filter((o) => o !== e), this.refreshIfActive();
1172
- }
1173
- removeFromOtherZones(e, t) {
1174
- 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));
1175
- }
1176
- addValueField(e, t) {
1177
- const o = this.config.valueFields ?? [];
1178
- o.some((r) => r.field === e) || (this.config.valueFields = [...o, { field: e, aggFunc: t }]), this.removeFromOtherZones(e, "values"), this.refreshIfActive();
1179
- }
1180
- removeValueField(e) {
1181
- this.config.valueFields = (this.config.valueFields ?? []).filter((t) => t.field !== e), this.refreshIfActive();
1182
- }
1183
- updateValueAggFunc(e, t) {
1184
- const o = this.config.valueFields ?? [], r = o.findIndex((n) => n.field === e);
1185
- r >= 0 && (o[r] = { ...o[r], aggFunc: t }, this.config.valueFields = [...o]), this.isActive && this.refresh();
1186
- }
1187
- // #endregion
1188
- }
1189
- export {
1190
- v as PivotPlugin
1191
- };
1
+ const e='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',t={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:e,filterActive:e,print:"🖨️"};class i{static dependencies;static manifest;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const i=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(i),i.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...t,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),i=parseInt(t,10);if(!isNaN(i))return i}return 200}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}setIcon(e,t){"string"==typeof t?e.innerHTML=t:t instanceof HTMLElement&&(e.innerHTML="",e.appendChild(t.cloneNode(!0)))}warn(e){console.warn(`[tbw-grid:${this.name}] ${e}`)}}const o={sum:(e,t)=>e.reduce((e,i)=>e+(Number(i[t])||0),0),avg:(e,t)=>{const i=e.reduce((e,i)=>e+(Number(i[t])||0),0);return e.length?i/e.length:0},count:e=>e.length,min:(e,t)=>e.length?Math.min(...e.map(e=>Number(e[t])||1/0)):0,max:(e,t)=>e.length?Math.max(...e.map(e=>Number(e[t])||-1/0)):0,first:(e,t)=>e[0]?.[t],last:(e,t)=>e[e.length-1]?.[t]},r=/* @__PURE__ */new Map,n={register(e,t){r.set(e,t)},unregister(e){r.delete(e)},get(e){if(void 0!==e)return"function"==typeof e?e:r.get(e)??o[e]},run(e,t,i,o){const r=this.get(e);return r?r(t,i,o):void 0},has:e=>r.has(e)||e in o,list:()=>[...Object.keys(o),...r.keys()]},a={sum:e=>e.reduce((e,t)=>e+t,0),avg:e=>e.length?e.reduce((e,t)=>e+t,0)/e.length:0,count:e=>e.length,min:e=>e.length?Math.min(...e):0,max:e=>e.length?Math.max(...e):0,first:e=>e[0]??0,last:e=>e[e.length-1]??0};n.register.bind(n),n.unregister.bind(n),n.get.bind(n),n.run.bind(n),n.list.bind(n);const s=function(e){return a[e]??a.sum};function l(e,t){return[...e,t].join("|")}function d(e,t){const i=t.rowGroupFields??[],o=t.columnGroupFields??[],r=t.valueFields??[],n=function(e,t){if(0===t.length)return["value"];const i=/* @__PURE__ */new Set;for(const o of e){const e=t.map(e=>String(o[e]??"")).join("|");i.add(e)}return[...i].sort()}(e,o),a=c(e,i,o,n,r,0,""),s=function(e,t,i){const o={};function r(e){for(const n of e)if(n.isGroup&&n.children?.length)n.children&&r(n.children);else for(const e of t)for(const t of i){const i=l([e],t.field);o[i]=(o[i]??0)+(n.values[i]??0)}}return r(e),o}(a,n,r);return{rows:a,columnKeys:n,totals:s,grandTotal:Object.values(s).reduce((e,t)=>e+t,0)}}function c(e,t,i,o,r,n,a){const s=[];if(0===t.length){const t=p(e,i,o,r),l=g(t);return s.push({rowKey:a||"all",rowLabel:a||"All",depth:n,values:t,total:l,isGroup:!1,rowCount:e.length}),s}const l=t[0],d=t.slice(1),u=d.length>0,h=function(e,t){const i=/* @__PURE__ */new Map;for(const o of e){const e=String(o[t]??""),r=i.get(e);r?r.push(o):i.set(e,[o])}return i}(e,l);for(const[v,b]of h){const e=a?`${a}|${v}`:v,t=p(b,i,o,r),l=g(t);let h;u&&(h=c(b,d,i,o,r,n+1,e)),s.push({rowKey:e,rowLabel:v||"(blank)",depth:n,values:t,total:l,isGroup:u,children:h,rowCount:b.length})}return s}function p(e,t,i,o){const r={};for(const n of i)for(const i of o){const o=(t.length>0?e.filter(e=>t.map(t=>String(e[t]??"")).join("|")===n):e).map(e=>Number(e[i.field])||0),a=s(i.aggFunc),d=o.length>0?a(o):null;r[l([n],i.field)]=d}return r}function g(e){let t=0;for(const i of Object.values(e))t+=i??0;return t}const u=["sum","avg","count","min","max","first","last"];function h(e,t,i,o){const r=new AbortController,n={config:t,callbacks:o,signal:r.signal},a=document.createElement("div");return a.className="tbw-pivot-panel",a.appendChild(v("Options",()=>function(e,t){const{config:i,callbacks:o,signal:r}=t,n=document.createElement("div");return n.className="tbw-pivot-options",n.appendChild(m("Enable Pivot View",e,e=>{o.onTogglePivot(e)},r)),n.appendChild(m("Show Row Totals",i.showTotals??!0,e=>{o.onOptionChange("showTotals",e)},r)),n.appendChild(m("Show Grand Total",i.showGrandTotal??!0,e=>{o.onOptionChange("showGrandTotal",e)},r)),n}(i,n))),a.appendChild(v("Row Groups",()=>b("rowGroups",n))),a.appendChild(v("Column Groups",()=>b("columnGroups",n))),a.appendChild(v("Values",()=>function(e){const{config:t,callbacks:i,signal:o}=e,r=document.createElement("div");r.className="tbw-pivot-drop-zone tbw-pivot-values-zone",r.setAttribute("data-zone","values");const n=t.valueFields??[];if(0===n.length){const e=document.createElement("div");e.className="tbw-pivot-placeholder",e.textContent="Drag numeric fields here for aggregation",r.appendChild(e)}else for(const a of n)r.appendChild(w(a,e));return r.addEventListener("dragover",e=>{e.preventDefault(),r.classList.add("drag-over")},{signal:o}),r.addEventListener("dragleave",()=>{r.classList.remove("drag-over")},{signal:o}),r.addEventListener("drop",e=>{e.preventDefault(),r.classList.remove("drag-over");const t=e.dataTransfer?.getData("text/plain");t&&i.onAddValueField(t,"sum")},{signal:o}),r}(n))),a.appendChild(v("Available Fields",()=>function(e){const{config:t,callbacks:i,signal:o}=e,r=document.createElement("div");r.className="tbw-pivot-available-fields";const n=i.getAvailableFields(),a=/* @__PURE__ */new Set([...t.rowGroupFields??[],...t.columnGroupFields??[],...t.valueFields?.map(e=>e.field)??[]]),s=n.filter(e=>!a.has(e.field));if(0===s.length){const e=document.createElement("div");e.className="tbw-pivot-placeholder",e.textContent="All fields are in use",r.appendChild(e)}else for(const l of s){const e=document.createElement("div");e.className="tbw-pivot-field-chip available",e.textContent=l.header,e.draggable=!0,e.title=`Drag to add "${l.field}" to a zone`,e.addEventListener("dragstart",t=>{t.dataTransfer?.setData("text/plain",l.field),e.classList.add("dragging")},{signal:o}),e.addEventListener("dragend",()=>{e.classList.remove("dragging")},{signal:o}),r.appendChild(e)}return r}(n))),e.appendChild(a),()=>{r.abort(),a.remove()}}function v(e,t){const i=document.createElement("div");i.className="tbw-pivot-section";const o=document.createElement("div");o.className="tbw-pivot-section-header",o.textContent=e;const r=document.createElement("div");return r.className="tbw-pivot-section-content",r.appendChild(t()),i.appendChild(o),i.appendChild(r),i}function b(e,t){const{config:i,callbacks:o,signal:r}=t,n=document.createElement("div");n.className="tbw-pivot-drop-zone",n.setAttribute("data-zone",e);const a="rowGroups"===e?i.rowGroupFields??[]:i.columnGroupFields??[];if(0===a.length){const e=document.createElement("div");e.className="tbw-pivot-placeholder",e.textContent="Drag fields here or click to add",n.appendChild(e)}else for(const s of a)n.appendChild(f(s,e,t));return n.addEventListener("dragover",e=>{e.preventDefault(),n.classList.add("drag-over")},{signal:r}),n.addEventListener("dragleave",()=>{n.classList.remove("drag-over")},{signal:r}),n.addEventListener("drop",t=>{t.preventDefault(),n.classList.remove("drag-over");const i=t.dataTransfer?.getData("text/plain");i&&o.onAddFieldToZone(i,e)},{signal:r}),n}function f(e,t,i){const{callbacks:o,signal:r}=i,n=document.createElement("div");n.className="tbw-pivot-field-chip",n.draggable=!0;const a=o.getAvailableFields().find(t=>t.field===e),s=document.createElement("span");s.className="tbw-pivot-chip-label",s.textContent=a?.header??e;const l=document.createElement("button");return l.className="tbw-pivot-chip-remove",l.innerHTML="×",l.title="Remove field",l.addEventListener("click",i=>{i.stopPropagation(),o.onRemoveFieldFromZone(e,t)},{signal:r}),n.appendChild(s),n.appendChild(l),n.addEventListener("dragstart",i=>{i.dataTransfer?.setData("text/plain",e),i.dataTransfer?.setData("source-zone",t),n.classList.add("dragging")},{signal:r}),n.addEventListener("dragend",()=>{n.classList.remove("dragging")},{signal:r}),n}function w(e,t){const{callbacks:i,signal:o}=t,r=document.createElement("div");r.className="tbw-pivot-field-chip tbw-pivot-value-chip";const n=i.getAvailableFields().find(t=>t.field===e.field),a=document.createElement("div");a.className="tbw-pivot-value-label-wrapper";const s=document.createElement("span");s.className="tbw-pivot-chip-label",s.textContent=n?.header??e.field;const l=document.createElement("select");l.className="tbw-pivot-agg-select",l.title="Aggregation function";for(const c of u){const t=document.createElement("option");t.value=c,t.textContent=c.toUpperCase(),t.selected=c===e.aggFunc,l.appendChild(t)}l.addEventListener("change",()=>{i.onUpdateValueAggFunc(e.field,l.value)},{signal:o});const d=document.createElement("button");return d.className="tbw-pivot-chip-remove",d.innerHTML="×",d.title="Remove value field",d.addEventListener("click",t=>{t.stopPropagation(),i.onRemoveValueField(e.field)},{signal:o}),a.appendChild(s),a.appendChild(l),r.appendChild(a),r.appendChild(d),r}function m(e,t,i,o){const r=document.createElement("label");r.className="tbw-pivot-checkbox";const n=document.createElement("input");n.type="checkbox",n.checked=t,n.addEventListener("change",()=>i(n.checked),{signal:o});const a=document.createElement("span");return a.textContent=e,r.appendChild(n),r.appendChild(a),r}class C extends i{name="pivot";styles='@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:var(--tbw-pivot-toggle-size, var(--tbw-toggle-size, 1.25em));height:var(--tbw-pivot-toggle-size, var(--tbw-toggle-size, 1.25em));margin-right:var(--tbw-spacing-sm, .375em);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 var(--tbw-transition-duration, .12s) var(--tbw-transition-ease, ease),color var(--tbw-transition-duration, .12s) var(--tbw-transition-ease, ease)}.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}}}';static PANEL_ID="pivot";get defaultConfig(){return{active:!0,showTotals:!0,showGrandTotal:!0,showToolPanel:!0,animation:"slide"}}isActive=!1;hasInitialized=!1;pivotResult=null;fieldHeaderMap=/* @__PURE__ */new Map;expandedKeys=/* @__PURE__ */new Set;defaultExpanded=!0;userHasToggledExpand=!1;originalColumns=[];panelContainer=null;grandTotalFooter=null;previousVisibleKeys=/* @__PURE__ */new Set;keysToAnimate=/* @__PURE__ */new Set;hasValidPivotConfig(){return(this.config.valueFields?.length??0)>0}get animationStyle(){return!!this.isAnimationEnabled&&(this.config.animation??"slide")}detach(){this.isActive=!1,this.hasInitialized=!1,this.pivotResult=null,this.fieldHeaderMap.clear(),this.originalColumns=[],this.panelContainer=null,this.cleanupGrandTotalFooter(),this.previousVisibleKeys.clear(),this.keysToAnimate.clear(),this.userHasToggledExpand=!1}getToolPanel(){if(!1!==(this.config?.showToolPanel??this.userConfig?.showToolPanel??!0))return{id:C.PANEL_ID,title:"Pivot",icon:"⊞",tooltip:"Configure pivot table",order:90,render:e=>this.renderPanel(e)}}processRows(e){if(!this.hasInitialized&&!1!==this.config.active&&this.hasValidPivotConfig()&&(this.hasInitialized=!0,this.isActive=!0),!this.isActive)return[...e];const t=function(e){const t=[];return e.rowGroupFields?.length||e.columnGroupFields?.length||t.push("At least one row or column group field is required"),e.valueFields?.length||t.push("At least one value field is required"),t}(this.config);if(t.length>0)return this.warn(`Config errors: ${t.join(", ")}`),[...e];this.buildFieldHeaderMap(),this.defaultExpanded=this.config.defaultExpanded??!0,this.pivotResult=d(e,this.config),0===this.expandedKeys.size&&this.defaultExpanded&&!this.userHasToggledExpand&&this.expandAllKeys();const i=this.config.indentWidth??20,o=function(e,t,i=!0){const o=[];function r(e){o.push(e);const n=t?t.has(e.rowKey):i;if(e.children&&n)for(const t of e.children)r(t)}for(const n of e)r(n);return o}(this.pivotResult.rows,this.expandedKeys,this.defaultExpanded).map(e=>({__pivotRowKey:e.rowKey,__pivotLabel:e.rowLabel,__pivotDepth:e.depth,__pivotIsGroup:e.isGroup,__pivotHasChildren:Boolean(e.children?.length),__pivotExpanded:this.expandedKeys.has(e.rowKey),__pivotRowCount:e.rowCount??0,__pivotIndent:e.depth*i,__pivotTotal:e.total,...e.values}));this.keysToAnimate.clear();const r=/* @__PURE__ */new Set;for(const n of o){const e=n.__pivotRowKey;r.add(e),!this.previousVisibleKeys.has(e)&&n.__pivotDepth>0&&this.keysToAnimate.add(e)}return this.previousVisibleKeys=r,o}processColumns(e){if(!this.isActive||!this.pivotResult)return[...e];const t=[],i=(this.config.rowGroupFields??[]).map(e=>this.fieldHeaderMap.get(e)??e).join(" / ");t.push({field:"__pivotLabel",header:i||"Group",width:200});for(const o of this.pivotResult.columnKeys)for(const e of this.config.valueFields??[]){const i=l([o],e.field),r=e.header||this.fieldHeaderMap.get(e.field)||e.field;t.push({field:i,header:`${o} - ${r} (${e.aggFunc})`,width:120,type:"number"})}return this.config.showTotals&&t.push({field:"__pivotTotal",header:"Total",width:100,type:"number"}),t}renderRow(e,t,i){const o=e;return o.__pivotRowKey&&o.__pivotHasChildren?function(e,t,i){return t.className="data-grid-row pivot-group-row",t.setAttribute("data-pivot-depth",String(e.__pivotDepth??0)),t.setAttribute("data-pivot-key",String(e.__pivotRowKey??"")),t.setAttribute("role","row"),t.innerHTML="",i.columns.forEach((o,r)=>{const n=document.createElement("div");if(n.className="cell",n.setAttribute("data-col",String(r)),n.setAttribute("data-row",String(i.rowIndex)),n.setAttribute("role","gridcell"),0===r){const t=Number(e.__pivotIndent)||0;n.style.paddingLeft=`${t}px`;const o=String(e.__pivotRowKey),r=document.createElement("button");r.type="button",r.className="pivot-toggle",r.setAttribute("aria-label",e.__pivotExpanded?"Collapse group":"Expand group"),i.setIcon(r,i.resolveIcon(e.__pivotExpanded?"collapse":"expand")),r.addEventListener("click",e=>{e.stopPropagation(),i.onToggle(o)}),n.appendChild(r);const a=document.createElement("span");a.className="pivot-label",a.textContent=String(e.__pivotLabel??""),n.appendChild(a);const s=document.createElement("span");s.className="pivot-count",s.textContent=` (${Number(e.__pivotRowCount)||0})`,n.appendChild(s)}else{const t=e[o.field];n.textContent=null!=t?String(t):""}t.appendChild(n)}),!0}(o,t,{columns:this.gridColumns,rowIndex:i,onToggle:e=>this.toggle(e),resolveIcon:e=>this.resolveIcon(e),setIcon:(e,t)=>this.setIcon(e,t)}):void 0!==o.__pivotRowKey&&this.isActive?function(e,t,i,o){return t.className="data-grid-row pivot-leaf-row",t.setAttribute("data-pivot-depth",String(e.__pivotDepth??0)),t.setAttribute("data-pivot-key",String(e.__pivotRowKey??"")),t.innerHTML="",i.forEach((i,r)=>{const n=document.createElement("div");if(n.className="cell",n.setAttribute("data-col",String(r)),n.setAttribute("data-row",String(o)),n.setAttribute("role","gridcell"),0===r){const t=Number(e.__pivotIndent)||0;n.style.paddingLeft=`${t+20}px`;const i=document.createElement("span");i.className="pivot-label",i.textContent=String(e.__pivotLabel??""),n.appendChild(i)}else{const t=e[i.field];n.textContent=null!=t?String(t):""}t.appendChild(n)}),!0}(o,t,this.gridColumns,i):(this.cleanupPivotStyling(t),!1)}cleanupPivotStyling(e){(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="")}onKeyDown(e){if(" "!==e.key)return;if(!this.isActive)return;const t=this.grid._focusRow,i=this.rows[t];return i?.__pivotIsGroup&&i.__pivotHasChildren?(e.preventDefault(),this.toggle(i.__pivotRowKey),this.requestRenderWithFocus(),!0):void 0}afterRender(){this.isActive&&this.config.showGrandTotal&&this.pivotResult?this.renderGrandTotalFooter():this.cleanupGrandTotalFooter();const e=this.animationStyle;if(!1===e||0===this.keysToAnimate.size)return;const t=this.gridElement?.querySelector(".rows");if(!t)return;const i="fade"===e?"tbw-pivot-fade-in":"tbw-pivot-slide-in";for(const o of t.querySelectorAll(".pivot-group-row, .pivot-leaf-row")){const e=o.dataset.pivotKey;e&&this.keysToAnimate.has(e)&&(o.classList.add(i),o.addEventListener("animationend",()=>o.classList.remove(i),{once:!0}))}this.keysToAnimate.clear()}renderGrandTotalFooter(){if(!this.pivotResult)return;const e=this.gridElement;if(!e)return;const t=e.querySelector(".tbw-scroll-area")??e.querySelector(".tbw-grid-content")??e.children[0];if(!t)return;this.grandTotalFooter||(this.grandTotalFooter=document.createElement("div"),this.grandTotalFooter.className="pivot-grand-total-footer",t.appendChild(this.grandTotalFooter));const i={__pivotRowKey:"__grandTotal",__pivotLabel:"Grand Total",__pivotIsGrandTotal:!0,__pivotTotal:this.pivotResult.grandTotal,...this.pivotResult.totals};var o,r,n;o=i,r=this.grandTotalFooter,n=this.gridColumns,r.className="pivot-grand-total-row",r.setAttribute("role","presentation"),r.innerHTML="",n.forEach((e,t)=>{const i=document.createElement("div");if(i.className="cell",i.setAttribute("data-col",String(t)),0===t){const e=document.createElement("span");e.className="pivot-label",e.textContent="Grand Total",i.appendChild(e)}else{const t=o[e.field];i.textContent=null!=t?String(t):""}r.appendChild(i)})}cleanupGrandTotalFooter(){this.grandTotalFooter&&(this.grandTotalFooter.remove(),this.grandTotalFooter=null)}toggle(e){this.userHasToggledExpand=!0,this.expandedKeys.has(e)?this.expandedKeys.delete(e):this.expandedKeys.add(e),this.requestRender()}expand(e){this.userHasToggledExpand=!0,this.expandedKeys.add(e),this.requestRender()}collapse(e){this.userHasToggledExpand=!0,this.expandedKeys.delete(e),this.requestRender()}expandAll(){this.userHasToggledExpand=!0,this.expandAllKeys(),this.requestRender()}collapseAll(){this.userHasToggledExpand=!0,this.expandedKeys.clear(),this.requestRender()}expandAllKeys(){if(!this.pivotResult)return;const e=function(e){const t=[];function i(e){if(e.isGroup&&t.push(e.rowKey),e.children)for(const t of e.children)i(t)}for(const o of e)i(o);return t}(this.pivotResult.rows);for(const t of e)this.expandedKeys.add(t)}isExpanded(e){return this.expandedKeys.has(e)}enablePivot(){0===this.originalColumns.length&&this.captureOriginalColumns(),this.isActive=!0,this.requestRender()}disablePivot(){this.isActive=!1,this.pivotResult=null,this.requestRender()}isPivotActive(){return this.isActive}getPivotResult(){return this.pivotResult}setRowGroupFields(e){this.config.rowGroupFields=e,this.requestRender()}setColumnGroupFields(e){this.config.columnGroupFields=e,this.requestRender()}setValueFields(e){this.config.valueFields=e,this.requestRender()}refresh(){this.pivotResult=null,this.requestRender()}showPanel(){this.grid.openToolPanel(),this.grid.expandedToolPanelSections.includes(C.PANEL_ID)||this.grid.toggleToolPanelSection(C.PANEL_ID)}hidePanel(){this.grid.closeToolPanel()}togglePanel(){this.grid.isToolPanelOpen||this.grid.openToolPanel(),this.grid.toggleToolPanelSection(C.PANEL_ID)}isPanelVisible(){return this.grid.isToolPanelOpen&&this.grid.expandedToolPanelSections.includes(C.PANEL_ID)}get gridColumns(){return this.grid.columns??[]}refreshIfActive(){this.isActive&&this.refresh(),this.refreshPanel()}buildFieldHeaderMap(){const e=this.getAvailableFields();this.fieldHeaderMap.clear();for(const t of e)this.fieldHeaderMap.set(t.field,t.header)}getAvailableFields(){return this.originalColumns.length>0?this.originalColumns:this.captureOriginalColumns()}captureOriginalColumns(){try{const e=this.grid.getAllColumns?.()??this.grid.columns??[];return this.originalColumns=e.filter(e=>!e.field.startsWith("__pivot")).map(e=>({field:e.field,header:e.header??e.field})),this.originalColumns}catch{return[]}}renderPanel(e){this.panelContainer=e,0===this.originalColumns.length&&this.captureOriginalColumns();const t={onTogglePivot:e=>{e?this.enablePivot():this.disablePivot(),this.refreshPanel()},onAddFieldToZone:(e,t)=>this.addFieldToZone(e,t),onRemoveFieldFromZone:(e,t)=>this.removeFieldFromZone(e,t),onAddValueField:(e,t)=>this.addValueField(e,t),onRemoveValueField:e=>this.removeValueField(e),onUpdateValueAggFunc:(e,t)=>this.updateValueAggFunc(e,t),onOptionChange:(e,t)=>{this.config[e]=t,this.isActive&&this.refresh()},getAvailableFields:()=>this.getAvailableFields()};return h(e,this.config,this.isActive,t)}refreshPanel(){this.panelContainer&&(this.panelContainer.innerHTML="",this.renderPanel(this.panelContainer))}addFieldToZone(e,t){if("rowGroups"===t){const t=this.config.rowGroupFields??[];t.includes(e)||(this.config.rowGroupFields=[...t,e])}else{const t=this.config.columnGroupFields??[];t.includes(e)||(this.config.columnGroupFields=[...t,e])}this.removeFromOtherZones(e,t),this.refreshIfActive()}removeFieldFromZone(e,t){"rowGroups"===t?this.config.rowGroupFields=(this.config.rowGroupFields??[]).filter(t=>t!==e):this.config.columnGroupFields=(this.config.columnGroupFields??[]).filter(t=>t!==e),this.refreshIfActive()}removeFromOtherZones(e,t){"rowGroups"!==t&&(this.config.rowGroupFields=(this.config.rowGroupFields??[]).filter(t=>t!==e)),"columnGroups"!==t&&(this.config.columnGroupFields=(this.config.columnGroupFields??[]).filter(t=>t!==e)),"values"!==t&&(this.config.valueFields=(this.config.valueFields??[]).filter(t=>t.field!==e))}addValueField(e,t){const i=this.config.valueFields??[];i.some(t=>t.field===e)||(this.config.valueFields=[...i,{field:e,aggFunc:t}]),this.removeFromOtherZones(e,"values"),this.refreshIfActive()}removeValueField(e){this.config.valueFields=(this.config.valueFields??[]).filter(t=>t.field!==e),this.refreshIfActive()}updateValueAggFunc(e,t){const i=this.config.valueFields??[],o=i.findIndex(t=>t.field===e);o>=0&&(i[o]={...i[o],aggFunc:t},this.config.valueFields=[...i]),this.isActive&&this.refresh()}}export{C as PivotPlugin};
1192
2
  //# sourceMappingURL=index.js.map