@toolbox-web/grid 1.14.0 → 1.15.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 (82) hide show
  1. package/README.md +5 -1
  2. package/all.js +1888 -1433
  3. package/all.js.map +1 -1
  4. package/index.js +188 -149
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts.map +1 -1
  7. package/lib/core/internal/loading.d.ts +2 -0
  8. package/lib/core/internal/loading.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/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
  12. package/lib/plugins/column-virtualization/index.js +1 -1
  13. package/lib/plugins/column-virtualization/index.js.map +1 -1
  14. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +20 -1
  15. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  16. package/lib/plugins/context-menu/index.d.ts +1 -1
  17. package/lib/plugins/context-menu/index.d.ts.map +1 -1
  18. package/lib/plugins/context-menu/index.js +153 -70
  19. package/lib/plugins/context-menu/index.js.map +1 -1
  20. package/lib/plugins/context-menu/menu.d.ts +7 -0
  21. package/lib/plugins/context-menu/menu.d.ts.map +1 -1
  22. package/lib/plugins/context-menu/types.d.ts +46 -0
  23. package/lib/plugins/context-menu/types.d.ts.map +1 -1
  24. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  25. package/lib/plugins/editing/index.js +214 -197
  26. package/lib/plugins/editing/index.js.map +1 -1
  27. package/lib/plugins/filtering/FilteringPlugin.d.ts +9 -1
  28. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  29. package/lib/plugins/filtering/filter-model.d.ts.map +1 -1
  30. package/lib/plugins/filtering/index.js +348 -283
  31. package/lib/plugins/filtering/index.js.map +1 -1
  32. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +5 -1
  33. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  34. package/lib/plugins/grouping-columns/index.js +242 -109
  35. package/lib/plugins/grouping-columns/index.js.map +1 -1
  36. package/lib/plugins/grouping-columns/types.d.ts +7 -0
  37. package/lib/plugins/grouping-columns/types.d.ts.map +1 -1
  38. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +11 -1
  39. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  40. package/lib/plugins/pinned-columns/index.d.ts +1 -1
  41. package/lib/plugins/pinned-columns/index.d.ts.map +1 -1
  42. package/lib/plugins/pinned-columns/index.js +174 -79
  43. package/lib/plugins/pinned-columns/index.js.map +1 -1
  44. package/lib/plugins/pinned-columns/pinned-columns.d.ts +23 -4
  45. package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
  46. package/lib/plugins/pinned-columns/types.d.ts +21 -9
  47. package/lib/plugins/pinned-columns/types.d.ts.map +1 -1
  48. package/lib/plugins/reorder/index.js.map +1 -1
  49. package/lib/plugins/responsive/index.js.map +1 -1
  50. package/lib/plugins/row-reorder/index.js.map +1 -1
  51. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  52. package/lib/plugins/selection/index.js +122 -122
  53. package/lib/plugins/selection/index.js.map +1 -1
  54. package/lib/plugins/visibility/VisibilityPlugin.d.ts +42 -2
  55. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  56. package/lib/plugins/visibility/index.d.ts +1 -1
  57. package/lib/plugins/visibility/index.d.ts.map +1 -1
  58. package/lib/plugins/visibility/index.js +219 -59
  59. package/lib/plugins/visibility/index.js.map +1 -1
  60. package/lib/plugins/visibility/types.d.ts +25 -0
  61. package/lib/plugins/visibility/types.d.ts.map +1 -1
  62. package/package.json +1 -1
  63. package/umd/grid.all.umd.js +30 -30
  64. package/umd/grid.all.umd.js.map +1 -1
  65. package/umd/grid.umd.js +4 -4
  66. package/umd/grid.umd.js.map +1 -1
  67. package/umd/plugins/column-virtualization.umd.js +1 -1
  68. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  69. package/umd/plugins/context-menu.umd.js +1 -1
  70. package/umd/plugins/context-menu.umd.js.map +1 -1
  71. package/umd/plugins/editing.umd.js +1 -1
  72. package/umd/plugins/editing.umd.js.map +1 -1
  73. package/umd/plugins/filtering.umd.js +1 -1
  74. package/umd/plugins/filtering.umd.js.map +1 -1
  75. package/umd/plugins/grouping-columns.umd.js +1 -1
  76. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  77. package/umd/plugins/pinned-columns.umd.js +1 -1
  78. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  79. package/umd/plugins/selection.umd.js +2 -2
  80. package/umd/plugins/selection.umd.js.map +1 -1
  81. package/umd/plugins/visibility.umd.js +1 -1
  82. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,4 +1,4 @@
1
- import { BaseGridPlugin } from '../../core/plugin/base-plugin';
1
+ import { PluginManifest, BaseGridPlugin } from '../../core/plugin/base-plugin';
2
2
  import { ContextMenuConfig, ContextMenuParams } from './types';
3
3
  /**
4
4
  * Context Menu Plugin for tbw-grid
@@ -81,6 +81,11 @@ import { ContextMenuConfig, ContextMenuParams } from './types';
81
81
  * @internal Extends BaseGridPlugin
82
82
  */
83
83
  export declare class ContextMenuPlugin extends BaseGridPlugin<ContextMenuConfig> {
84
+ /**
85
+ * Plugin manifest - declares queries used by this plugin.
86
+ * @internal
87
+ */
88
+ static readonly manifest: PluginManifest;
84
89
  /** @internal */
85
90
  readonly name = "contextMenu";
86
91
  /** @internal */
@@ -118,6 +123,20 @@ export declare class ContextMenuPlugin extends BaseGridPlugin<ContextMenuConfig>
118
123
  * Uses reference counting to ensure handlers persist while any grid uses the plugin.
119
124
  */
120
125
  private uninstallGlobalHandlers;
126
+ /**
127
+ * Query all plugins for context menu items via the query system.
128
+ * Each plugin that handles `getContextMenuItems` can return an array of HeaderContextMenuItem.
129
+ */
130
+ private collectPluginItems;
131
+ /**
132
+ * Insert separators between groups of items with different order ranges.
133
+ * Groups are defined by the tens digit (10-19, 20-29, etc.).
134
+ */
135
+ private insertGroupSeparators;
136
+ /**
137
+ * Convert plugin-contributed HeaderContextMenuItems to the internal ContextMenuItem format.
138
+ */
139
+ private convertPluginItems;
121
140
  /** @internal */
122
141
  afterRender(): void;
123
142
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ContextMenuPlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/context-menu/ContextMenuPlugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,KAAK,EAAE,iBAAiB,EAAmB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAkCrF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IACtE,gBAAgB;IAChB,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,gBAAgB;IAChB,cAAuB,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAIjE;IAGD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,WAAW,CAA4B;IAK/C,gBAAgB;IACP,MAAM,CAAC,IAAI,EAAE,OAAO,+BAA+B,EAAE,WAAW,GAAG,IAAI;IAMhF,gBAAgB;IACP,MAAM,IAAI,IAAI;IAavB;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAoBlC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAoCtC;IAEF;;;;OAIG;IACH,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,qBAAqB;IAqC7B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAsB/B,gBAAgB;IACP,WAAW,IAAI,IAAI;IAoG5B;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAqCxE;;OAEG;IACH,QAAQ,IAAI,IAAI;IAQhB;;;OAGG;IACH,UAAU,IAAI,OAAO;CAMtB"}
1
+ {"version":3,"file":"ContextMenuPlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/context-menu/ContextMenuPlugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,KAAK,EAAE,iBAAiB,EAAmB,iBAAiB,EAAyB,MAAM,SAAS,CAAC;AAqC5G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,iBAAiB,CAAC;IACtE;;;OAGG;IACH,gBAAyB,QAAQ,EAAE,cAAc,CAO/C;IAEF,gBAAgB;IAChB,QAAQ,CAAC,IAAI,iBAAiB;IAE9B,gBAAgB;IAChB,cAAuB,aAAa,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAIjE;IAGD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,WAAW,CAA4B;IAK/C,gBAAgB;IACP,MAAM,CAAC,IAAI,EAAE,OAAO,+BAA+B,EAAE,WAAW,GAAG,IAAI;IAMhF,gBAAgB;IACP,MAAM,IAAI,IAAI;IAavB;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAoBlC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAoCtC;IAEF;;;;OAIG;IACH,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,qBAAqB;IAqC7B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAmB/B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IA6B7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgB1B,gBAAgB;IACP,WAAW,IAAI,IAAI;IAuH5B;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAkDxE;;OAEG;IACH,QAAQ,IAAI,IAAI;IAQhB;;;OAGG;IACH,UAAU,IAAI,OAAO;CAMtB"}
@@ -5,5 +5,5 @@
5
5
  * @module Plugins/Context Menu
6
6
  */
7
7
  export { ContextMenuPlugin } from './ContextMenuPlugin';
8
- export type { ContextMenuConfig, ContextMenuItem, ContextMenuParams } from './types';
8
+ export type { ContextMenuConfig, ContextMenuItem, ContextMenuParams, HeaderContextMenuItem } from './types';
9
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/context-menu/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/context-menu/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC"}
@@ -1,4 +1,4 @@
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>', I = {
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>', R = {
2
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
@@ -7,11 +7,11 @@ const E = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentCo
7
7
  submenuArrow: "▶",
8
8
  dragHandle: "⋮⋮",
9
9
  toolPanel: "☰",
10
- filter: E,
11
- filterActive: E,
10
+ filter: C,
11
+ filterActive: C,
12
12
  print: "🖨️"
13
13
  };
14
- class R {
14
+ class z {
15
15
  /**
16
16
  * Plugin dependencies - declare other plugins this one requires.
17
17
  *
@@ -301,7 +301,7 @@ class R {
301
301
  */
302
302
  get gridIcons() {
303
303
  const e = this.grid?.gridConfig?.icons ?? {};
304
- return { ...I, ...e };
304
+ return { ...R, ...e };
305
305
  }
306
306
  // #region Animation Helpers
307
307
  /**
@@ -377,83 +377,106 @@ class R {
377
377
  }
378
378
  // #endregion
379
379
  }
380
- const g = "@layer tbw-plugins{.tbw-context-menu{position:fixed;background:var(--tbw-context-menu-bg, var(--tbw-color-panel-bg));color:var(--tbw-context-menu-fg, var(--tbw-color-fg));border:1px solid var(--tbw-context-menu-border, var(--tbw-color-border));border-radius:var(--tbw-context-menu-radius, var(--tbw-border-radius));box-shadow:var(--tbw-context-menu-shadow, 0 2px 10px var(--tbw-color-shadow));min-width:var(--tbw-context-menu-min-width, var(--tbw-menu-min-width));padding:var(--tbw-spacing-xs) 0;z-index:10000;font-size:var(--tbw-context-menu-font-size, var(--tbw-font-size-sm));font-family:var(--tbw-context-menu-font-family, var(--tbw-font-family))}.tbw-context-menu-item{display:flex;align-items:center;padding:var(--tbw-context-menu-item-padding, var(--tbw-menu-item-padding));cursor:pointer;gap:var(--tbw-context-menu-item-gap, var(--tbw-menu-item-gap))}.tbw-context-menu-item:hover:not(.disabled){background:var(--tbw-context-menu-hover, var(--tbw-color-row-hover))}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:var(--tbw-context-menu-danger, var(--tbw-color-danger))}.tbw-context-menu-icon{width:var(--tbw-context-menu-icon-size, var(--tbw-icon-size));text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:var(--tbw-context-menu-muted, var(--tbw-color-fg-muted));font-size:var(--tbw-context-menu-shortcut-size, var(--tbw-font-size-xs))}.tbw-context-menu-arrow{font-size:var(--tbw-context-menu-arrow-size, var(--tbw-font-size-2xs));color:var(--tbw-context-menu-muted, var(--tbw-color-fg-muted))}.tbw-context-menu-separator{height:1px;background:var(--tbw-context-menu-border, var(--tbw-color-border));margin:var(--tbw-spacing-xs) 0}}";
381
- function x(r, e) {
382
- return (typeof r == "function" ? r(e) : r).filter((n) => !(n.hidden === !0 || typeof n.hidden == "function" && n.hidden(e)));
380
+ const p = "@layer tbw-plugins{.tbw-context-menu{position:fixed;background:var(--tbw-context-menu-bg, var(--tbw-color-panel-bg));color:var(--tbw-context-menu-fg, var(--tbw-color-fg));border:1px solid var(--tbw-context-menu-border, var(--tbw-color-border));border-radius:var(--tbw-context-menu-radius, var(--tbw-border-radius));box-shadow:var(--tbw-context-menu-shadow, 0 2px 10px var(--tbw-color-shadow));min-width:var(--tbw-context-menu-min-width, var(--tbw-menu-min-width));padding:var(--tbw-spacing-xs) 0;z-index:10000;font-size:var(--tbw-context-menu-font-size, var(--tbw-font-size-sm));font-family:var(--tbw-context-menu-font-family, var(--tbw-font-family))}.tbw-context-menu-item{display:flex;align-items:center;padding:var(--tbw-context-menu-item-padding, var(--tbw-menu-item-padding));cursor:pointer;gap:var(--tbw-context-menu-item-gap, var(--tbw-menu-item-gap))}.tbw-context-menu-item:hover:not(.disabled){background:var(--tbw-context-menu-hover, var(--tbw-color-row-hover))}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:var(--tbw-context-menu-danger, var(--tbw-color-danger))}.tbw-context-menu-icon{width:var(--tbw-context-menu-icon-size, var(--tbw-icon-size));text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:var(--tbw-context-menu-muted, var(--tbw-color-fg-muted));font-size:var(--tbw-context-menu-shortcut-size, var(--tbw-font-size-xs))}.tbw-context-menu-arrow{font-size:var(--tbw-context-menu-arrow-size, var(--tbw-font-size-2xs));color:var(--tbw-context-menu-muted, var(--tbw-color-fg-muted))}.tbw-context-menu-separator{height:1px;background:var(--tbw-context-menu-border, var(--tbw-color-border));margin:var(--tbw-spacing-xs) 0}}";
381
+ function v(l, e) {
382
+ return (typeof l == "function" ? l(e) : l).filter((n) => !(n.hidden === !0 || typeof n.hidden == "function" && n.hidden(e)));
383
383
  }
384
- function z(r, e) {
385
- return r.disabled === !0 ? !0 : typeof r.disabled == "function" ? r.disabled(e) : !1;
384
+ function I(l) {
385
+ const e = [];
386
+ for (const t of l)
387
+ t.separator && (e.length === 0 || e[e.length - 1].separator) || e.push(t);
388
+ return e.length > 0 && e[e.length - 1].separator && e.pop(), e;
386
389
  }
387
- function v(r, e, t, n = I.submenuArrow) {
390
+ function H(l, e) {
391
+ return l.disabled === !0 ? !0 : typeof l.disabled == "function" ? l.disabled(e) : !1;
392
+ }
393
+ function y(l, e, t, n = R.submenuArrow) {
388
394
  const s = document.createElement("div");
389
395
  s.className = "tbw-context-menu", s.setAttribute("role", "menu");
390
- for (const o of r) {
396
+ const u = l.some((o) => !o.separator && o.icon);
397
+ for (const o of l) {
391
398
  if (o.separator) {
392
- const l = document.createElement("div");
393
- l.className = "tbw-context-menu-separator", l.setAttribute("role", "separator"), s.appendChild(l);
399
+ const r = document.createElement("div");
400
+ r.className = "tbw-context-menu-separator", r.setAttribute("role", "separator"), s.appendChild(r);
394
401
  continue;
395
402
  }
396
403
  const i = document.createElement("div");
397
404
  i.className = "tbw-context-menu-item", o.cssClass && i.classList.add(o.cssClass), i.setAttribute("role", "menuitem"), i.setAttribute("data-id", o.id);
398
- const u = z(o, e);
399
- if (u && (i.classList.add("disabled"), i.setAttribute("aria-disabled", "true")), o.icon) {
400
- const l = document.createElement("span");
401
- l.className = "tbw-context-menu-icon", l.innerHTML = o.icon, i.appendChild(l);
405
+ const a = H(o, e);
406
+ if (a && (i.classList.add("disabled"), i.setAttribute("aria-disabled", "true")), o.icon) {
407
+ const r = document.createElement("span");
408
+ r.className = "tbw-context-menu-icon", r.innerHTML = o.icon, i.appendChild(r);
409
+ } else if (u) {
410
+ const r = document.createElement("span");
411
+ r.className = "tbw-context-menu-icon", r.innerHTML = "&nbsp;", i.appendChild(r);
402
412
  }
403
- const a = document.createElement("span");
404
- if (a.className = "tbw-context-menu-label", a.textContent = o.name, i.appendChild(a), o.shortcut) {
405
- const l = document.createElement("span");
406
- l.className = "tbw-context-menu-shortcut", l.textContent = o.shortcut, i.appendChild(l);
413
+ const b = document.createElement("span");
414
+ if (b.className = "tbw-context-menu-label", b.textContent = o.name, i.appendChild(b), o.shortcut) {
415
+ const r = document.createElement("span");
416
+ r.className = "tbw-context-menu-shortcut", r.textContent = o.shortcut, i.appendChild(r);
407
417
  }
408
418
  if (o.subMenu?.length) {
409
- const l = document.createElement("span");
410
- l.className = "tbw-context-menu-arrow", typeof n == "string" ? l.innerHTML = n : n instanceof HTMLElement && l.appendChild(n.cloneNode(!0)), i.appendChild(l), i.addEventListener("mouseenter", () => {
419
+ const r = document.createElement("span");
420
+ r.className = "tbw-context-menu-arrow", typeof n == "string" ? r.innerHTML = n : n instanceof HTMLElement && r.appendChild(n.cloneNode(!0)), i.appendChild(r), i.addEventListener("mouseenter", () => {
411
421
  if (i.querySelector(".tbw-context-menu") || !o.subMenu) return;
412
- const b = x(o.subMenu, e), d = v(b, e, t, n);
422
+ const h = v(o.subMenu, e), d = y(h, e, t, n);
413
423
  d.classList.add("tbw-context-submenu"), d.style.position = "absolute", d.style.left = "100%", d.style.top = "0", i.style.position = "relative", i.appendChild(d);
414
424
  }), i.addEventListener("mouseleave", () => {
415
425
  const c = i.querySelector(".tbw-context-menu");
416
426
  c && c.remove();
417
427
  });
418
428
  }
419
- !u && o.action && !o.subMenu && i.addEventListener("click", (l) => {
420
- l.stopPropagation(), t(o);
429
+ !a && o.action && !o.subMenu && i.addEventListener("click", (r) => {
430
+ r.stopPropagation(), t(o);
421
431
  }), s.appendChild(i);
422
432
  }
423
433
  return s;
424
434
  }
425
- function C(r, e, t) {
426
- r.style.position = "fixed", r.style.left = `${e}px`, r.style.top = `${t}px`, r.style.visibility = "hidden", r.style.zIndex = "10000";
427
- const n = r.getBoundingClientRect(), s = window.innerWidth, o = window.innerHeight;
428
- let i = e, u = t;
429
- e + n.width > s && (i = e - n.width), t + n.height > o && (u = t - n.height), i = Math.max(0, i), u = Math.max(0, u), r.style.left = `${i}px`, r.style.top = `${u}px`, r.style.visibility = "visible";
435
+ function S(l, e, t) {
436
+ l.style.position = "fixed", l.style.left = `${e}px`, l.style.top = `${t}px`, l.style.visibility = "hidden", l.style.zIndex = "10000";
437
+ const n = l.getBoundingClientRect(), s = window.innerWidth, u = window.innerHeight;
438
+ let o = e, i = t;
439
+ e + n.width > s && (o = e - n.width), t + n.height > u && (i = t - n.height), o = Math.max(0, o), i = Math.max(0, i), l.style.left = `${o}px`, l.style.top = `${i}px`, l.style.visibility = "visible";
430
440
  }
431
- let h = null, f = null, m = null, w = 0;
432
- const p = [
441
+ const M = "getContextMenuItems";
442
+ let f = null, g = null, m = null, w = 0;
443
+ const x = [
433
444
  {
434
445
  id: "copy",
435
446
  name: "Copy",
436
447
  shortcut: "Ctrl+C",
437
- action: (r) => {
438
- r.grid?.plugins?.clipboard?.copy?.();
448
+ action: (l) => {
449
+ l.grid?.plugins?.clipboard?.copy?.();
439
450
  }
440
451
  },
441
452
  { separator: !0, id: "sep1", name: "" },
442
453
  {
443
454
  id: "export-csv",
444
455
  name: "Export CSV",
445
- action: (r) => {
446
- r.grid?.plugins?.export?.exportCsv?.();
456
+ action: (l) => {
457
+ l.grid?.plugins?.export?.exportCsv?.();
447
458
  }
448
459
  }
449
460
  ];
450
- class S extends R {
461
+ class _ extends z {
462
+ /**
463
+ * Plugin manifest - declares queries used by this plugin.
464
+ * @internal
465
+ */
466
+ static manifest = {
467
+ queries: [
468
+ {
469
+ type: M,
470
+ description: "Collects context menu items from other plugins for header right-click menus"
471
+ }
472
+ ]
473
+ };
451
474
  /** @internal */
452
475
  name = "contextMenu";
453
476
  /** @internal */
454
477
  get defaultConfig() {
455
478
  return {
456
- items: p
479
+ items: x
457
480
  };
458
481
  }
459
482
  // #region Internal State
@@ -534,30 +557,80 @@ class S extends R {
534
557
  copyGridStyles(e) {
535
558
  const t = this.gridElement;
536
559
  if (!t) return;
537
- const n = getComputedStyle(t), s = [], o = n.getPropertyValue("color-scheme").trim();
538
- o && s.push(`color-scheme: ${o}`);
539
- for (const i of S.CSS_VARS_TO_COPY) {
540
- const u = n.getPropertyValue(i).trim();
541
- u && s.push(`${i}: ${u}`);
560
+ const n = getComputedStyle(t), s = [], u = n.getPropertyValue("color-scheme").trim();
561
+ u && s.push(`color-scheme: ${u}`);
562
+ for (const o of _.CSS_VARS_TO_COPY) {
563
+ const i = n.getPropertyValue(o).trim();
564
+ i && s.push(`${o}: ${i}`);
542
565
  }
543
566
  if (s.length > 0) {
544
- const i = e.getAttribute("style") || "";
545
- e.setAttribute("style", i + s.join("; ") + ";");
567
+ const o = e.getAttribute("style") || "";
568
+ e.setAttribute("style", o + s.join("; ") + ";");
546
569
  }
547
570
  }
548
571
  installGlobalHandlers() {
549
- !m && typeof document < "u" && typeof g == "string" && g && (m = document.createElement("style"), m.id = "tbw-context-menu-styles", m.textContent = g, document.head.appendChild(m)), h || (h = () => {
572
+ !m && typeof document < "u" && typeof p == "string" && p && (m = document.createElement("style"), m.id = "tbw-context-menu-styles", m.textContent = p, document.head.appendChild(m)), f || (f = () => {
550
573
  document.querySelectorAll(".tbw-context-menu").forEach((t) => t.remove());
551
- }, document.addEventListener("click", h)), f || (f = (e) => {
574
+ }, document.addEventListener("click", f)), g || (g = (e) => {
552
575
  e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((n) => n.remove());
553
- }, document.addEventListener("keydown", f));
576
+ }, document.addEventListener("keydown", g));
554
577
  }
555
578
  /**
556
579
  * Clean up global handlers when the last instance detaches.
557
580
  * Uses reference counting to ensure handlers persist while any grid uses the plugin.
558
581
  */
559
582
  uninstallGlobalHandlers() {
560
- w--, !(w > 0) && (h && (document.removeEventListener("click", h), h = null), f && (document.removeEventListener("keydown", f), f = null), m && (m.remove(), m = null));
583
+ w--, !(w > 0) && (f && (document.removeEventListener("click", f), f = null), g && (document.removeEventListener("keydown", g), g = null), m && (m.remove(), m = null));
584
+ }
585
+ /**
586
+ * Query all plugins for context menu items via the query system.
587
+ * Each plugin that handles `getContextMenuItems` can return an array of HeaderContextMenuItem.
588
+ */
589
+ collectPluginItems(e) {
590
+ if (!this.grid) return [];
591
+ const t = this.grid.query(M, e), n = [];
592
+ for (const s of t)
593
+ Array.isArray(s) && n.push(...s);
594
+ return n.sort((s, u) => (s.order ?? 100) - (u.order ?? 100)), this.insertGroupSeparators(n);
595
+ }
596
+ /**
597
+ * Insert separators between groups of items with different order ranges.
598
+ * Groups are defined by the tens digit (10-19, 20-29, etc.).
599
+ */
600
+ insertGroupSeparators(e) {
601
+ if (e.length <= 1) return e;
602
+ const t = [];
603
+ let n = -1;
604
+ for (const s of e) {
605
+ if (s.separator) {
606
+ t.push(s);
607
+ continue;
608
+ }
609
+ const u = Math.floor((s.order ?? 100) / 10);
610
+ n >= 0 && u !== n && t.push({
611
+ id: `__sep-${n}-${u}`,
612
+ label: "",
613
+ separator: !0,
614
+ action: () => {
615
+ }
616
+ }), n = u, t.push(s);
617
+ }
618
+ return t;
619
+ }
620
+ /**
621
+ * Convert plugin-contributed HeaderContextMenuItems to the internal ContextMenuItem format.
622
+ */
623
+ convertPluginItems(e) {
624
+ return e.map((t) => ({
625
+ id: t.id,
626
+ name: t.label,
627
+ icon: t.icon,
628
+ shortcut: t.shortcut,
629
+ disabled: t.disabled ?? !1,
630
+ action: () => t.action(),
631
+ separator: t.separator,
632
+ cssClass: t.cssClass
633
+ }));
561
634
  }
562
635
  // #endregion
563
636
  // #region Hooks
@@ -569,29 +642,29 @@ class S extends R {
569
642
  t && t.getAttribute("data-context-menu-bound") !== "true" && (t.setAttribute("data-context-menu-bound", "true"), t.addEventListener("contextmenu", (n) => {
570
643
  const s = n;
571
644
  s.preventDefault();
572
- const o = s.target, i = o.closest("[data-row][data-col]"), u = o.closest(".header-cell");
645
+ const u = s.target, o = u.closest("[data-row][data-col]"), i = u.closest('[part~="header-cell"]');
573
646
  let a;
574
- if (i) {
575
- const c = parseInt(i.getAttribute("data-row") ?? "-1", 10), b = parseInt(i.getAttribute("data-col") ?? "-1", 10), d = this.columns[b], y = this.rows[c], M = this.syncSelectionOnContextMenu(c);
647
+ if (o) {
648
+ const c = parseInt(o.getAttribute("data-row") ?? "-1", 10), h = parseInt(o.getAttribute("data-col") ?? "-1", 10), d = this.visibleColumns[h], E = this.rows[c], A = this.syncSelectionOnContextMenu(c);
576
649
  a = {
577
- row: y,
650
+ row: E,
578
651
  rowIndex: c,
579
652
  column: d,
580
- columnIndex: b,
653
+ columnIndex: h,
581
654
  field: d?.field ?? "",
582
- value: y?.[d?.field] ?? null,
655
+ value: E?.[d?.field] ?? null,
583
656
  isHeader: !1,
584
657
  event: s,
585
- selectedRows: M
658
+ selectedRows: A
586
659
  };
587
- } else if (u) {
588
- const c = parseInt(u.getAttribute("data-col") ?? "-1", 10), b = this.columns[c];
660
+ } else if (i) {
661
+ const c = parseInt(i.getAttribute("data-col") ?? "-1", 10), h = this.visibleColumns[c];
589
662
  a = {
590
663
  row: null,
591
664
  rowIndex: -1,
592
- column: b,
665
+ column: h,
593
666
  columnIndex: c,
594
- field: b?.field ?? "",
667
+ field: h?.field ?? "",
595
668
  value: null,
596
669
  isHeader: !0,
597
670
  event: s,
@@ -600,15 +673,20 @@ class S extends R {
600
673
  } else
601
674
  return;
602
675
  this.params = a, this.position = { x: s.clientX, y: s.clientY };
603
- const l = x(this.config.items ?? p, a);
604
- l.length && (this.menuElement && this.menuElement.remove(), this.menuElement = v(
605
- l,
676
+ const b = this.collectPluginItems(a);
677
+ let r = v(this.config.items ?? x, a);
678
+ if (b.length > 0) {
679
+ const c = this.convertPluginItems(b);
680
+ r.length > 0 && c.length > 0 ? r = [...r, { id: "__plugin-sep", name: "", separator: !0 }, ...c] : r = [...r, ...c];
681
+ }
682
+ r = I(r), r.length && (this.menuElement && this.menuElement.remove(), this.menuElement = y(
683
+ r,
606
684
  a,
607
685
  (c) => {
608
686
  c.action && c.action(a), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
609
687
  },
610
688
  this.gridIcons.submenuArrow
611
- ), document.body.appendChild(this.menuElement), this.copyGridStyles(this.menuElement), C(this.menuElement, s.clientX, s.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: a, items: l }));
689
+ ), document.body.appendChild(this.menuElement), this.copyGridStyles(this.menuElement), S(this.menuElement, s.clientX, s.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: a, items: r }));
612
690
  }));
613
691
  }
614
692
  // #endregion
@@ -630,15 +708,20 @@ class S extends R {
630
708
  isHeader: n.isHeader ?? !1,
631
709
  event: n.event ?? new MouseEvent("contextmenu"),
632
710
  selectedRows: n.selectedRows ?? []
633
- }, o = x(this.config.items ?? p, s);
634
- this.menuElement && this.menuElement.remove(), this.menuElement = v(
711
+ }, u = this.collectPluginItems(s);
712
+ let o = v(this.config.items ?? x, s);
713
+ if (u.length > 0) {
714
+ const i = this.convertPluginItems(u);
715
+ o.length > 0 && i.length > 0 ? o = [...o, { id: "__plugin-sep", name: "", separator: !0 }, ...i] : o = [...o, ...i];
716
+ }
717
+ o = I(o), this.menuElement && this.menuElement.remove(), this.menuElement = y(
635
718
  o,
636
719
  s,
637
720
  (i) => {
638
721
  i.action && i.action(s), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
639
722
  },
640
723
  this.gridIcons.submenuArrow
641
- ), document.body.appendChild(this.menuElement), this.copyGridStyles(this.menuElement), C(this.menuElement, e, t), this.isOpen = !0;
724
+ ), document.body.appendChild(this.menuElement), this.copyGridStyles(this.menuElement), S(this.menuElement, e, t), this.isOpen = !0;
642
725
  }
643
726
  /**
644
727
  * Hide the context menu.
@@ -657,6 +740,6 @@ class S extends R {
657
740
  // Styles are injected globally via installGlobalHandlers() since menu renders in document.body
658
741
  }
659
742
  export {
660
- S as ContextMenuPlugin
743
+ _ as ContextMenuPlugin
661
744
  };
662
745
  //# sourceMappingURL=index.js.map