@toolbox-web/grid 1.14.1 → 1.16.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 (91) hide show
  1. package/README.md +5 -1
  2. package/all.js +2013 -1564
  3. package/all.js.map +1 -1
  4. package/index.js +918 -880
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts.map +1 -1
  7. package/lib/core/internal/columns.d.ts +0 -5
  8. package/lib/core/internal/columns.d.ts.map +1 -1
  9. package/lib/core/internal/rows.d.ts.map +1 -1
  10. package/lib/core/internal/validate-config.d.ts.map +1 -1
  11. package/lib/core/types.d.ts +12 -0
  12. package/lib/core/types.d.ts.map +1 -1
  13. package/lib/plugins/clipboard/index.js.map +1 -1
  14. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
  15. package/lib/plugins/column-virtualization/index.js +1 -1
  16. package/lib/plugins/column-virtualization/index.js.map +1 -1
  17. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +20 -1
  18. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  19. package/lib/plugins/context-menu/index.d.ts +1 -1
  20. package/lib/plugins/context-menu/index.d.ts.map +1 -1
  21. package/lib/plugins/context-menu/index.js +177 -84
  22. package/lib/plugins/context-menu/index.js.map +1 -1
  23. package/lib/plugins/context-menu/menu.d.ts +7 -0
  24. package/lib/plugins/context-menu/menu.d.ts.map +1 -1
  25. package/lib/plugins/context-menu/types.d.ts +48 -2
  26. package/lib/plugins/context-menu/types.d.ts.map +1 -1
  27. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  28. package/lib/plugins/editing/index.js +327 -298
  29. package/lib/plugins/editing/index.js.map +1 -1
  30. package/lib/plugins/export/index.js.map +1 -1
  31. package/lib/plugins/filtering/FilteringPlugin.d.ts +7 -1
  32. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  33. package/lib/plugins/filtering/filter-model.d.ts.map +1 -1
  34. package/lib/plugins/filtering/index.js +173 -138
  35. package/lib/plugins/filtering/index.js.map +1 -1
  36. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +5 -1
  37. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  38. package/lib/plugins/grouping-columns/index.js +242 -109
  39. package/lib/plugins/grouping-columns/index.js.map +1 -1
  40. package/lib/plugins/grouping-columns/types.d.ts +7 -0
  41. package/lib/plugins/grouping-columns/types.d.ts.map +1 -1
  42. package/lib/plugins/grouping-rows/index.js.map +1 -1
  43. package/lib/plugins/master-detail/index.js.map +1 -1
  44. package/lib/plugins/multi-sort/index.js.map +1 -1
  45. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +11 -1
  46. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  47. package/lib/plugins/pinned-columns/index.d.ts +1 -1
  48. package/lib/plugins/pinned-columns/index.d.ts.map +1 -1
  49. package/lib/plugins/pinned-columns/index.js +174 -79
  50. package/lib/plugins/pinned-columns/index.js.map +1 -1
  51. package/lib/plugins/pinned-columns/pinned-columns.d.ts +23 -4
  52. package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
  53. package/lib/plugins/pinned-columns/types.d.ts +21 -9
  54. package/lib/plugins/pinned-columns/types.d.ts.map +1 -1
  55. package/lib/plugins/pinned-rows/index.js.map +1 -1
  56. package/lib/plugins/pivot/index.js.map +1 -1
  57. package/lib/plugins/print/index.js.map +1 -1
  58. package/lib/plugins/reorder/index.js.map +1 -1
  59. package/lib/plugins/responsive/index.js.map +1 -1
  60. package/lib/plugins/row-reorder/index.js.map +1 -1
  61. package/lib/plugins/selection/index.js.map +1 -1
  62. package/lib/plugins/server-side/index.js.map +1 -1
  63. package/lib/plugins/tree/index.js.map +1 -1
  64. package/lib/plugins/undo-redo/index.js.map +1 -1
  65. package/lib/plugins/visibility/VisibilityPlugin.d.ts +42 -2
  66. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  67. package/lib/plugins/visibility/index.d.ts +1 -1
  68. package/lib/plugins/visibility/index.d.ts.map +1 -1
  69. package/lib/plugins/visibility/index.js +219 -59
  70. package/lib/plugins/visibility/index.js.map +1 -1
  71. package/lib/plugins/visibility/types.d.ts +25 -0
  72. package/lib/plugins/visibility/types.d.ts.map +1 -1
  73. package/package.json +1 -1
  74. package/umd/grid.all.umd.js +27 -27
  75. package/umd/grid.all.umd.js.map +1 -1
  76. package/umd/grid.umd.js +21 -21
  77. package/umd/grid.umd.js.map +1 -1
  78. package/umd/plugins/column-virtualization.umd.js +1 -1
  79. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  80. package/umd/plugins/context-menu.umd.js +1 -1
  81. package/umd/plugins/context-menu.umd.js.map +1 -1
  82. package/umd/plugins/editing.umd.js +1 -1
  83. package/umd/plugins/editing.umd.js.map +1 -1
  84. package/umd/plugins/filtering.umd.js +1 -1
  85. package/umd/plugins/filtering.umd.js.map +1 -1
  86. package/umd/plugins/grouping-columns.umd.js +1 -1
  87. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  88. package/umd/plugins/pinned-columns.umd.js +1 -1
  89. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  90. package/umd/plugins/visibility.umd.js +1 -1
  91. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,4 +1,4 @@
1
- import { AfterCellRenderContext, PluginManifest, BaseGridPlugin } from '../../core/plugin/base-plugin';
1
+ import { AfterCellRenderContext, PluginManifest, PluginQuery, BaseGridPlugin } from '../../core/plugin/base-plugin';
2
2
  import { ColumnConfig } from '../../core/types';
3
3
  import { ColumnGroup, GroupingColumnsConfig } from './types';
4
4
  /**
@@ -96,7 +96,11 @@ export declare class GroupingColumnsPlugin extends BaseGridPlugin<GroupingColumn
96
96
  private groups;
97
97
  private isActive;
98
98
  /** @internal */
99
+ attach(grid: import('../../core/plugin/base-plugin').GridElement): void;
100
+ /** @internal */
99
101
  detach(): void;
102
+ /** @internal */
103
+ handleQuery(query: PluginQuery): unknown;
100
104
  /**
101
105
  * Auto-detect column groups from column configuration.
102
106
  * Detects both inline `column.group` properties and declarative `columnGroups` config.
@@ -1 +1 @@
1
- {"version":3,"file":"GroupingColumnsPlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/grouping-columns/GroupingColumnsPlugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAQrD,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,qBAAa,qBAAsB,SAAQ,cAAc,CAAC,qBAAqB,CAAC;;IAC9E;;;OAGG;IACH,gBAAyB,QAAQ,EAAE,cAAc,CAc/C;IAEF,gBAAgB;IAChB,QAAQ,CAAC,IAAI,qBAAqB;IAClC,gBAAgB;IAChB,SAAkB,MAAM,SAAU;IAElC,gBAAgB;IAChB,cAAuB,aAAa,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAIrE;IAGD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,QAAQ,CAAS;IAOzB,gBAAgB;IACP,MAAM,IAAI,IAAI;IASvB;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO;IAczD,gBAAgB;IACP,cAAc,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,EAAE;IAmDzE,gBAAgB;IACP,WAAW,IAAI,IAAI;IA6C5B;;;;;OAKG;IACM,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI;IAQ/D;;;OAGG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;;OAGG;IACH,SAAS,IAAI,WAAW,EAAE;IAI1B;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE;IAKhD;;OAEG;IACH,OAAO,IAAI,IAAI;CAIhB"}
1
+ {"version":3,"file":"GroupingColumnsPlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/grouping-columns/GroupingColumnsPlugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AASrD,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,qBAAa,qBAAsB,SAAQ,cAAc,CAAC,qBAAqB,CAAC;;IAC9E;;;OAGG;IACH,gBAAyB,QAAQ,EAAE,cAAc,CAe/C;IAEF,gBAAgB;IAChB,QAAQ,CAAC,IAAI,qBAAqB;IAClC,gBAAgB;IAChB,SAAkB,MAAM,SAAU;IAElC,gBAAgB;IAChB,cAAuB,aAAa,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAKrE;IAGD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,QAAQ,CAAS;IAOzB,gBAAgB;IACP,MAAM,CAAC,IAAI,EAAE,OAAO,+BAA+B,EAAE,WAAW,GAAG,IAAI;IAShF,gBAAgB;IACP,MAAM,IAAI,IAAI;IAmHvB,gBAAgB;IACP,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO;IAmFjD;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO;IAczD,gBAAgB;IACP,cAAc,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,EAAE;IAmDzE,gBAAgB;IACP,WAAW,IAAI,IAAI;IAyD5B;;;;;OAKG;IACM,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI;IAQ/D;;;OAGG;IACH,gBAAgB,IAAI,OAAO;IAI3B;;;OAGG;IACH,SAAS,IAAI,WAAW,EAAE;IAI1B;;;;OAIG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE;IAKhD;;OAEG;IACH,OAAO,IAAI,IAAI;CAIhB"}
@@ -1,4 +1,4 @@
1
- const c = '<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>', h = {
1
+ const g = '<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
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
@@ -7,11 +7,11 @@ const c = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
7
7
  submenuArrow: "▶",
8
8
  dragHandle: "⋮⋮",
9
9
  toolPanel: "☰",
10
- filter: c,
11
- filterActive: c,
10
+ filter: g,
11
+ filterActive: g,
12
12
  print: "🖨️"
13
13
  };
14
- class p {
14
+ class f {
15
15
  /**
16
16
  * Plugin dependencies - declare other plugins this one requires.
17
17
  *
@@ -138,16 +138,16 @@ class p {
138
138
  /**
139
139
  * Emit a custom event from the grid.
140
140
  */
141
- emit(e, r) {
142
- this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: r, bubbles: !0 }));
141
+ emit(e, t) {
142
+ this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
143
143
  }
144
144
  /**
145
145
  * Emit a cancelable custom event from the grid.
146
146
  * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
147
147
  */
148
- emitCancelable(e, r) {
149
- const t = new CustomEvent(e, { detail: r, bubbles: !0, cancelable: !0 });
150
- return this.grid?.dispatchEvent?.(t), t.defaultPrevented;
148
+ emitCancelable(e, t) {
149
+ const s = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
150
+ return this.grid?.dispatchEvent?.(s), s.defaultPrevented;
151
151
  }
152
152
  // =========================================================================
153
153
  // Event Bus - Plugin-to-Plugin Communication
@@ -168,8 +168,8 @@ class p {
168
168
  * });
169
169
  * ```
170
170
  */
171
- on(e, r) {
172
- this.grid?._pluginManager?.subscribe(this, e, r);
171
+ on(e, t) {
172
+ this.grid?._pluginManager?.subscribe(this, e, t);
173
173
  }
174
174
  /**
175
175
  * Unsubscribe from a plugin event.
@@ -203,8 +203,8 @@ class p {
203
203
  * this.emit('filter-change', { field: 'name', value: 'Alice' });
204
204
  * ```
205
205
  */
206
- emitPluginEvent(e, r) {
207
- this.grid?._pluginManager?.emitPluginEvent(e, r);
206
+ emitPluginEvent(e, t) {
207
+ this.grid?._pluginManager?.emitPluginEvent(e, t);
208
208
  }
209
209
  /**
210
210
  * Request a re-render of the grid.
@@ -301,7 +301,7 @@ class p {
301
301
  */
302
302
  get gridIcons() {
303
303
  const e = this.grid?.gridConfig?.icons ?? {};
304
- return { ...h, ...e };
304
+ return { ...p, ...e };
305
305
  }
306
306
  // #region Animation Helpers
307
307
  /**
@@ -324,8 +324,8 @@ class p {
324
324
  const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
325
325
  if (e === !1 || e === "off") return !1;
326
326
  if (e === !0 || e === "on") return !0;
327
- const r = this.gridElement;
328
- return r ? getComputedStyle(r).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
327
+ const t = this.gridElement;
328
+ return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
329
329
  }
330
330
  /**
331
331
  * Get the animation duration in milliseconds from CSS variable.
@@ -342,8 +342,8 @@ class p {
342
342
  get animationDuration() {
343
343
  const e = this.gridElement;
344
344
  if (e) {
345
- const r = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), t = parseInt(r, 10);
346
- if (!isNaN(t)) return t;
345
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), s = parseInt(t, 10);
346
+ if (!isNaN(s)) return s;
347
347
  }
348
348
  return 200;
349
349
  }
@@ -356,8 +356,8 @@ class p {
356
356
  * @param pluginOverride - Optional plugin-level override
357
357
  * @returns The resolved icon value
358
358
  */
359
- resolveIcon(e, r) {
360
- return r !== void 0 ? r : this.gridIcons[e];
359
+ resolveIcon(e, t) {
360
+ return t !== void 0 ? t : this.gridIcons[e];
361
361
  }
362
362
  /**
363
363
  * Set an icon value on an element.
@@ -366,8 +366,8 @@ class p {
366
366
  * @param element - The element to set the icon on
367
367
  * @param icon - The icon value (string or HTMLElement)
368
368
  */
369
- setIcon(e, r) {
370
- typeof r == "string" ? e.innerHTML = r : r instanceof HTMLElement && (e.innerHTML = "", e.appendChild(r.cloneNode(!0)));
369
+ setIcon(e, t) {
370
+ typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
371
371
  }
372
372
  /**
373
373
  * Log a warning message.
@@ -377,74 +377,74 @@ class p {
377
377
  }
378
378
  // #endregion
379
379
  }
380
- function g(u) {
381
- if (!u.length) return [];
382
- const e = /* @__PURE__ */ new Map(), r = [], t = (o, s) => {
383
- if (!s.length) return;
384
- const i = r[r.length - 1];
385
- if (i && i.implicit && i.firstIndex + i.columns.length === o) {
386
- i.columns.push(...s);
380
+ function c(d) {
381
+ if (!d.length) return [];
382
+ const e = /* @__PURE__ */ new Map(), t = [], s = (o, n) => {
383
+ if (!n.length) return;
384
+ const l = t[t.length - 1];
385
+ if (l && l.implicit && l.firstIndex + l.columns.length === o) {
386
+ l.columns.push(...n);
387
387
  return;
388
388
  }
389
- r.push({
389
+ t.push({
390
390
  id: "__implicit__" + o,
391
391
  label: void 0,
392
- columns: s,
392
+ columns: n,
393
393
  firstIndex: o,
394
394
  implicit: !0
395
395
  });
396
396
  };
397
- let l = [], n = 0;
398
- return u.forEach((o, s) => {
399
- const i = o.group;
400
- if (!i) {
401
- l.length === 0 && (n = s), l.push(o);
397
+ let i = [], r = 0;
398
+ return d.forEach((o, n) => {
399
+ const l = o.group;
400
+ if (!l) {
401
+ i.length === 0 && (r = n), i.push(o);
402
402
  return;
403
403
  }
404
- l.length && (t(n, l.slice()), l = []);
405
- const d = typeof i == "string" ? i : i.id;
406
- let a = e.get(d);
404
+ i.length && (s(r, i.slice()), i = []);
405
+ const u = typeof l == "string" ? l : l.id;
406
+ let a = e.get(u);
407
407
  a || (a = {
408
- id: d,
409
- label: typeof i == "string" ? void 0 : i.label,
408
+ id: u,
409
+ label: typeof l == "string" ? void 0 : l.label,
410
410
  columns: [],
411
- firstIndex: s
412
- }, e.set(d, a), r.push(a)), a.columns.push(o);
413
- }), l.length && t(n, l), r.length === 1 && r[0].implicit && r[0].columns.length === u.length ? [] : r;
411
+ firstIndex: n
412
+ }, e.set(u, a), t.push(a)), a.columns.push(o);
413
+ }), i.length && s(r, i), t.length === 1 && t[0].implicit && t[0].columns.length === d.length ? [] : t;
414
414
  }
415
- function f(u, e, r) {
416
- if (!e.length || !u) return;
417
- const t = /* @__PURE__ */ new Map();
418
- for (const n of e)
419
- for (const o of n.columns)
420
- o.field && t.set(o.field, n.id);
421
- const l = Array.from(u.querySelectorAll(".cell[data-field]"));
422
- l.forEach((n) => {
423
- const o = n.getAttribute("data-field") || "", s = t.get(o);
424
- s && (n.classList.add("grouped"), n.getAttribute("data-group") || n.setAttribute("data-group", s));
415
+ function h(d, e, t) {
416
+ if (!e.length || !d) return;
417
+ const s = /* @__PURE__ */ new Map();
418
+ for (const r of e)
419
+ for (const o of r.columns)
420
+ o.field && s.set(o.field, r.id);
421
+ const i = Array.from(d.querySelectorAll(".cell[data-field]"));
422
+ i.forEach((r) => {
423
+ const o = r.getAttribute("data-field") || "", n = s.get(o);
424
+ n && (r.classList.add("grouped"), r.getAttribute("data-group") || r.setAttribute("data-group", n));
425
425
  });
426
- for (const n of e) {
427
- const o = n.columns[n.columns.length - 1], s = l.find((i) => i.getAttribute("data-field") === o.field);
428
- s && s.classList.add("group-end");
426
+ for (const r of e) {
427
+ const o = r.columns[r.columns.length - 1], n = i.find((l) => l.getAttribute("data-field") === o.field);
428
+ n && n.classList.add("group-end");
429
429
  }
430
430
  }
431
- function m(u, e) {
432
- if (u.length === 0) return null;
433
- const r = document.createElement("div");
434
- r.className = "header-group-row", r.setAttribute("role", "row");
435
- for (const t of u) {
436
- const l = t.columns[0], n = l ? e.findIndex((d) => d.field === l.field) : -1;
437
- if (n === -1) continue;
438
- const o = String(t.id).startsWith("__implicit__"), s = o ? "" : t.label || t.id, i = document.createElement("div");
439
- i.className = "cell header-group-cell", o && i.classList.add("implicit-group"), i.setAttribute("data-group", String(t.id)), i.style.gridColumn = `${n + 1} / span ${t.columns.length}`, i.textContent = s, r.appendChild(i);
440
- }
441
- return r;
431
+ function m(d, e) {
432
+ if (d.length === 0) return null;
433
+ const t = document.createElement("div");
434
+ t.className = "header-group-row", t.setAttribute("role", "row");
435
+ for (const s of d) {
436
+ const i = s.columns[0], r = i ? e.findIndex((u) => u.field === i.field) : -1;
437
+ if (r === -1) continue;
438
+ const o = String(s.id).startsWith("__implicit__"), n = o ? "" : s.label || s.id, l = document.createElement("div");
439
+ l.className = "cell header-group-cell", o && l.classList.add("implicit-group"), l.setAttribute("data-group", String(s.id)), l.style.gridColumn = `${r + 1} / span ${s.columns.length}`, l.textContent = n, t.appendChild(l);
440
+ }
441
+ return t;
442
442
  }
443
- function b(u) {
444
- return u.some((e) => e.group != null);
443
+ function b(d) {
444
+ return d.some((e) => e.group != null);
445
445
  }
446
446
  const w = "@layer tbw-plugins{.header-group-row{display:grid;grid-auto-flow:column;background:var(--tbw-grouping-columns-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell{display:flex;align-items:center;justify-content:center;padding:var(--tbw-button-padding-sm, .25rem .5rem);font-weight:600;font-size:var(--tbw-font-size-sm, .9em);text-transform:uppercase;letter-spacing:.5px;border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.header-group-cell:last-child{border-right:none}.header-row .cell.grouped{border-top:none}.header-row .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.header-row .cell.group-end:last-child{border-right:none}.rows .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.rows .cell.group-end:last-child{border-right:none}.header-group-row.no-borders{border-bottom:none}.header-group-row.no-borders .header-group-cell{border-right:none}.header-row.no-group-borders .cell.group-end{border-right:1px solid var(--tbw-color-border)}}";
447
- class v extends p {
447
+ class v extends f {
448
448
  /**
449
449
  * Plugin manifest - declares owned properties for configuration validation.
450
450
  * @internal
@@ -462,7 +462,8 @@ class v extends p {
462
462
  description: 'the "columnGroups" config property',
463
463
  isUsed: (e) => Array.isArray(e) && e.length > 0
464
464
  }
465
- ]
465
+ ],
466
+ queries: [{ type: "getColumnGrouping", description: "Returns column group metadata for the visibility panel" }]
466
467
  };
467
468
  /** @internal */
468
469
  name = "groupingColumns";
@@ -471,7 +472,8 @@ class v extends p {
471
472
  /** @internal */
472
473
  get defaultConfig() {
473
474
  return {
474
- showGroupBorders: !0
475
+ showGroupBorders: !0,
476
+ lockGroupOrder: !1
475
477
  };
476
478
  }
477
479
  // #region Internal State
@@ -482,69 +484,200 @@ class v extends p {
482
484
  // #endregion
483
485
  // #region Lifecycle
484
486
  /** @internal */
487
+ attach(e) {
488
+ super.attach(e), e.addEventListener("column-move", this.#r, {
489
+ signal: this.disconnectSignal
490
+ });
491
+ }
492
+ /** @internal */
485
493
  detach() {
486
494
  this.groups = [], this.isActive = !1, this.#e.clear();
487
495
  }
496
+ // #region Column Move Guard
497
+ /**
498
+ * Handle the cancelable column-move event.
499
+ * - When lockGroupOrder is enabled, prevents moves that would break group contiguity.
500
+ * - Always refreshes #groupEndFields after a successful move so that afterCellRender
501
+ * applies group-end borders to the correct (reordered) last column.
502
+ */
503
+ #r = (e) => {
504
+ if (!this.isActive) return;
505
+ const t = e, { field: s, columnOrder: i } = t.detail;
506
+ if (this.config.lockGroupOrder) {
507
+ for (const r of this.groups)
508
+ if (!r.id.startsWith("__implicit__") && !this.#i(r, i)) {
509
+ t.preventDefault(), this.#s(s);
510
+ return;
511
+ }
512
+ }
513
+ this.#t(i);
514
+ };
515
+ /**
516
+ * Recompute which fields are group-end based on a column order.
517
+ * The last field of each explicit group in the order gets the group-end class.
518
+ */
519
+ #t(e) {
520
+ this.#e.clear();
521
+ const t = this.#o(e);
522
+ for (const s of this.groups) {
523
+ const i = new Set(s.columns.map((r) => r.field));
524
+ for (let r = e.length - 1; r >= 0; r--)
525
+ if (i.has(e[r])) {
526
+ const o = e[r];
527
+ o !== t && this.#e.add(o);
528
+ break;
529
+ }
530
+ }
531
+ }
532
+ /**
533
+ * Find the trailing field of the last group in column order (to exclude from group-end marking).
534
+ */
535
+ #o(e) {
536
+ if (this.groups.length === 0) return null;
537
+ for (let t = e.length - 1; t >= 0; t--) {
538
+ const s = e[t];
539
+ for (const i of this.groups)
540
+ if (i.columns.some((r) => r.field === s)) {
541
+ const r = new Set(i.columns.map((o) => o.field));
542
+ for (let o = e.length - 1; o >= 0; o--)
543
+ if (r.has(e[o])) return e[o];
544
+ }
545
+ }
546
+ return null;
547
+ }
548
+ /**
549
+ * Check if all columns in a group are contiguous in the proposed column order.
550
+ */
551
+ #i(e, t) {
552
+ const s = e.columns.map((i) => t.indexOf(i.field)).filter((i) => i !== -1).sort((i, r) => i - r);
553
+ return s.length <= 1 ? !0 : s.length === s[s.length - 1] - s[0] + 1;
554
+ }
555
+ /**
556
+ * Flash the header cell with an error color to indicate a blocked move.
557
+ */
558
+ #s(e) {
559
+ const t = this.gridElement?.querySelector(
560
+ `.header-row [part~="header-cell"][data-field="${e}"]`
561
+ );
562
+ t && (t.style.setProperty("--_flash-color", "var(--tbw-color-error)"), t.animate(
563
+ [{ backgroundColor: "rgba(from var(--_flash-color) r g b / 30%)" }, { backgroundColor: "transparent" }],
564
+ { duration: 400, easing: "ease-out" }
565
+ ));
566
+ }
567
+ // #endregion
568
+ /** @internal */
569
+ handleQuery(e) {
570
+ if (e.type === "getColumnGrouping")
571
+ return this.#n();
572
+ }
573
+ /**
574
+ * Get stable column grouping info that includes ALL columns (visible and hidden).
575
+ * Used by the visibility panel to maintain group structure regardless of visibility state.
576
+ * Fields within each group are sorted by current display order.
577
+ */
578
+ #n() {
579
+ let e;
580
+ const t = this.grid?.gridConfig?.columnGroups;
581
+ if (t && Array.isArray(t) && t.length > 0)
582
+ e = t.filter((i) => i.children.length > 0).map((i) => ({
583
+ id: i.id,
584
+ label: i.header,
585
+ fields: [...i.children]
586
+ }));
587
+ else if (this.isActive && this.groups.length > 0) {
588
+ e = this.groups.filter((r) => !r.id.startsWith("__implicit__")).map((r) => ({
589
+ id: r.id,
590
+ label: r.label ?? r.id,
591
+ fields: r.columns.map((o) => o.field)
592
+ }));
593
+ const i = this.columns;
594
+ for (const r of i)
595
+ if (r.hidden && r.group) {
596
+ const o = typeof r.group == "string" ? r.group : r.group.id, n = typeof r.group == "string" ? r.group : r.group.label ?? r.group.id, l = e.find((u) => u.id === o);
597
+ l ? l.fields.includes(r.field) || l.fields.push(r.field) : e.push({ id: o, label: n, fields: [r.field] });
598
+ }
599
+ } else {
600
+ const i = this.columns, r = /* @__PURE__ */ new Map();
601
+ for (const o of i) {
602
+ if (!o.group) continue;
603
+ const n = typeof o.group == "string" ? o.group : o.group.id, l = typeof o.group == "string" ? o.group : o.group.label ?? o.group.id, u = r.get(n);
604
+ u ? u.fields.includes(o.field) || u.fields.push(o.field) : r.set(n, { id: n, label: l, fields: [o.field] });
605
+ }
606
+ e = Array.from(r.values());
607
+ }
608
+ const s = this.grid?.getColumnOrder();
609
+ if (s && s.length > 0) {
610
+ const i = new Map(s.map((r, o) => [r, o]));
611
+ for (const r of e)
612
+ r.fields.sort((o, n) => (i.get(o) ?? 1 / 0) - (i.get(n) ?? 1 / 0));
613
+ }
614
+ return e;
615
+ }
488
616
  // #endregion
489
617
  // #region Static Detection
490
618
  /**
491
619
  * Auto-detect column groups from column configuration.
492
620
  * Detects both inline `column.group` properties and declarative `columnGroups` config.
493
621
  */
494
- static detect(e, r) {
495
- if (r?.columnGroups && Array.isArray(r.columnGroups) && r.columnGroups.length > 0)
622
+ static detect(e, t) {
623
+ if (t?.columnGroups && Array.isArray(t.columnGroups) && t.columnGroups.length > 0)
496
624
  return !0;
497
- const t = r?.columns;
498
- return Array.isArray(t) ? b(t) : !1;
625
+ const s = t?.columns;
626
+ return Array.isArray(s) ? b(s) : !1;
499
627
  }
500
628
  // #endregion
501
629
  // #region Hooks
502
630
  /** @internal */
503
631
  processColumns(e) {
504
- const r = this.grid?.gridConfig?.columnGroups;
505
- let t;
506
- if (r && Array.isArray(r) && r.length > 0) {
507
- const n = /* @__PURE__ */ new Map();
508
- for (const o of r)
509
- for (const s of o.children)
510
- n.set(s, { id: o.id, label: o.header });
511
- t = e.map((o) => {
512
- const s = n.get(o.field);
513
- return s && !o.group ? { ...o, group: s } : o;
632
+ const t = this.grid?.gridConfig?.columnGroups;
633
+ let s;
634
+ if (t && Array.isArray(t) && t.length > 0) {
635
+ const r = /* @__PURE__ */ new Map();
636
+ for (const o of t)
637
+ for (const n of o.children)
638
+ r.set(n, { id: o.id, label: o.header });
639
+ s = e.map((o) => {
640
+ const n = r.get(o.field);
641
+ return n && !o.group ? { ...o, group: n } : o;
514
642
  });
515
643
  } else
516
- t = [...e];
517
- const l = g(t);
518
- if (l.length === 0)
519
- return this.isActive = !1, this.groups = [], t;
520
- this.isActive = !0, this.groups = l, this.#e.clear();
521
- for (const n of l) {
522
- const o = n.columns[n.columns.length - 1];
644
+ s = [...e];
645
+ const i = c(s);
646
+ if (i.length === 0)
647
+ return this.isActive = !1, this.groups = [], s;
648
+ this.isActive = !0, this.groups = i, this.#e.clear();
649
+ for (const r of i) {
650
+ const o = r.columns[r.columns.length - 1];
523
651
  o?.field && this.#e.add(o.field);
524
652
  }
525
- return t;
653
+ return s;
526
654
  }
527
655
  /** @internal */
528
656
  afterRender() {
529
657
  if (!this.isActive) {
530
- const i = this.gridElement?.querySelector(".header")?.querySelector(".header-group-row");
531
- i && i.remove();
658
+ const l = this.gridElement?.querySelector(".header")?.querySelector(".header-group-row");
659
+ l && l.remove();
532
660
  return;
533
661
  }
534
662
  const e = this.gridElement?.querySelector(".header");
535
663
  if (!e) return;
536
- const r = e.querySelector(".header-group-row");
537
- r && r.remove();
538
- const t = this.columns, l = g(t);
539
- if (l.length === 0) return;
540
- const n = m(l, t);
541
- if (n) {
542
- n.classList.toggle("no-borders", !this.config.showGroupBorders);
543
- const s = e.querySelector(".header-row");
544
- s ? e.insertBefore(n, s) : e.appendChild(n);
664
+ const t = e.querySelector(".header-group-row");
665
+ t && t.remove();
666
+ const s = this.visibleColumns, i = c(s);
667
+ if (i.length === 0) return;
668
+ this.#e.clear();
669
+ for (let n = 0; n < i.length; n++) {
670
+ const l = i[n], u = l.columns[l.columns.length - 1];
671
+ u?.field && n < i.length - 1 && this.#e.add(u.field);
672
+ }
673
+ const r = m(i, s);
674
+ if (r) {
675
+ r.classList.toggle("no-borders", !this.config.showGroupBorders);
676
+ const n = e.querySelector(".header-row");
677
+ n ? e.insertBefore(r, n) : e.appendChild(r);
545
678
  }
546
679
  const o = e.querySelector(".header-row");
547
- o && (o.classList.toggle("no-group-borders", !this.config.showGroupBorders), f(o, l));
680
+ o && (o.classList.toggle("no-group-borders", !this.config.showGroupBorders), h(o, i));
548
681
  }
549
682
  /**
550
683
  * Apply group-end class to individual cells during render and scroll.
@@ -577,8 +710,8 @@ class v extends p {
577
710
  * @returns Array of columns in the group
578
711
  */
579
712
  getGroupColumns(e) {
580
- const r = this.groups.find((t) => t.id === e);
581
- return r ? r.columns : [];
713
+ const t = this.groups.find((s) => s.id === e);
714
+ return t ? t.columns : [];
582
715
  }
583
716
  /**
584
717
  * Refresh column groups (recompute from current columns).