@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 { 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,116 @@ 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 kbd{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 c = 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 d = H(o, e);
406
+ if (d && (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 (c) {
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
+ if (r.className = "tbw-context-menu-shortcut", Array.isArray(o.shortcut))
417
+ o.shortcut.forEach((u, m) => {
418
+ m > 0 && r.appendChild(document.createTextNode("+"));
419
+ const a = document.createElement("kbd");
420
+ a.textContent = u, r.appendChild(a);
421
+ });
422
+ else {
423
+ const u = document.createElement("kbd");
424
+ u.textContent = o.shortcut, r.appendChild(u);
425
+ }
426
+ i.appendChild(r);
407
427
  }
408
428
  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", () => {
429
+ const r = document.createElement("span");
430
+ 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
431
  if (i.querySelector(".tbw-context-menu") || !o.subMenu) return;
412
- const b = x(o.subMenu, e), d = v(b, e, t, n);
413
- 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);
432
+ const m = v(o.subMenu, e), a = y(m, e, t, n);
433
+ a.classList.add("tbw-context-submenu"), a.style.position = "absolute", a.style.left = "100%", a.style.top = "0", i.style.position = "relative", i.appendChild(a);
414
434
  }), i.addEventListener("mouseleave", () => {
415
- const c = i.querySelector(".tbw-context-menu");
416
- c && c.remove();
435
+ const u = i.querySelector(".tbw-context-menu");
436
+ u && u.remove();
417
437
  });
418
438
  }
419
- !u && o.action && !o.subMenu && i.addEventListener("click", (l) => {
420
- l.stopPropagation(), t(o);
439
+ !d && o.action && !o.subMenu && i.addEventListener("click", (r) => {
440
+ r.stopPropagation(), t(o);
421
441
  }), s.appendChild(i);
422
442
  }
423
443
  return s;
424
444
  }
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";
445
+ function S(l, e, t) {
446
+ l.style.position = "fixed", l.style.left = `${e}px`, l.style.top = `${t}px`, l.style.visibility = "hidden", l.style.zIndex = "10000";
447
+ const n = l.getBoundingClientRect(), s = window.innerWidth, c = window.innerHeight;
448
+ let o = e, i = t;
449
+ e + n.width > s && (o = e - n.width), t + n.height > c && (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
450
  }
431
- let h = null, f = null, m = null, w = 0;
432
- const p = [
451
+ const M = "getContextMenuItems";
452
+ let f = null, g = null, h = null, w = 0;
453
+ const x = [
433
454
  {
434
455
  id: "copy",
435
456
  name: "Copy",
436
457
  shortcut: "Ctrl+C",
437
- action: (r) => {
438
- r.grid?.plugins?.clipboard?.copy?.();
458
+ action: (l) => {
459
+ l.grid?.plugins?.clipboard?.copy?.();
439
460
  }
440
461
  },
441
462
  { separator: !0, id: "sep1", name: "" },
442
463
  {
443
464
  id: "export-csv",
444
465
  name: "Export CSV",
445
- action: (r) => {
446
- r.grid?.plugins?.export?.exportCsv?.();
466
+ action: (l) => {
467
+ l.grid?.plugins?.export?.exportCsv?.();
447
468
  }
448
469
  }
449
470
  ];
450
- class S extends R {
471
+ class _ extends z {
472
+ /**
473
+ * Plugin manifest - declares queries used by this plugin.
474
+ * @internal
475
+ */
476
+ static manifest = {
477
+ queries: [
478
+ {
479
+ type: M,
480
+ description: "Collects context menu items from other plugins for header right-click menus"
481
+ }
482
+ ]
483
+ };
451
484
  /** @internal */
452
485
  name = "contextMenu";
453
486
  /** @internal */
454
487
  get defaultConfig() {
455
488
  return {
456
- items: p
489
+ items: x
457
490
  };
458
491
  }
459
492
  // #region Internal State
@@ -534,30 +567,80 @@ class S extends R {
534
567
  copyGridStyles(e) {
535
568
  const t = this.gridElement;
536
569
  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}`);
570
+ const n = getComputedStyle(t), s = [], c = n.getPropertyValue("color-scheme").trim();
571
+ c && s.push(`color-scheme: ${c}`);
572
+ for (const o of _.CSS_VARS_TO_COPY) {
573
+ const i = n.getPropertyValue(o).trim();
574
+ i && s.push(`${o}: ${i}`);
542
575
  }
543
576
  if (s.length > 0) {
544
- const i = e.getAttribute("style") || "";
545
- e.setAttribute("style", i + s.join("; ") + ";");
577
+ const o = e.getAttribute("style") || "";
578
+ e.setAttribute("style", o + s.join("; ") + ";");
546
579
  }
547
580
  }
548
581
  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 = () => {
582
+ !h && typeof document < "u" && typeof p == "string" && p && (h = document.createElement("style"), h.id = "tbw-context-menu-styles", h.textContent = p, document.head.appendChild(h)), f || (f = () => {
550
583
  document.querySelectorAll(".tbw-context-menu").forEach((t) => t.remove());
551
- }, document.addEventListener("click", h)), f || (f = (e) => {
584
+ }, document.addEventListener("click", f)), g || (g = (e) => {
552
585
  e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((n) => n.remove());
553
- }, document.addEventListener("keydown", f));
586
+ }, document.addEventListener("keydown", g));
554
587
  }
555
588
  /**
556
589
  * Clean up global handlers when the last instance detaches.
557
590
  * Uses reference counting to ensure handlers persist while any grid uses the plugin.
558
591
  */
559
592
  uninstallGlobalHandlers() {
560
- w--, !(w > 0) && (h && (document.removeEventListener("click", h), h = null), f && (document.removeEventListener("keydown", f), f = null), m && (m.remove(), m = null));
593
+ w--, !(w > 0) && (f && (document.removeEventListener("click", f), f = null), g && (document.removeEventListener("keydown", g), g = null), h && (h.remove(), h = null));
594
+ }
595
+ /**
596
+ * Query all plugins for context menu items via the query system.
597
+ * Each plugin that handles `getContextMenuItems` can return an array of HeaderContextMenuItem.
598
+ */
599
+ collectPluginItems(e) {
600
+ if (!this.grid) return [];
601
+ const t = this.grid.query(M, e), n = [];
602
+ for (const s of t)
603
+ Array.isArray(s) && n.push(...s);
604
+ return n.sort((s, c) => (s.order ?? 100) - (c.order ?? 100)), this.insertGroupSeparators(n);
605
+ }
606
+ /**
607
+ * Insert separators between groups of items with different order ranges.
608
+ * Groups are defined by the tens digit (10-19, 20-29, etc.).
609
+ */
610
+ insertGroupSeparators(e) {
611
+ if (e.length <= 1) return e;
612
+ const t = [];
613
+ let n = -1;
614
+ for (const s of e) {
615
+ if (s.separator) {
616
+ t.push(s);
617
+ continue;
618
+ }
619
+ const c = Math.floor((s.order ?? 100) / 10);
620
+ n >= 0 && c !== n && t.push({
621
+ id: `__sep-${n}-${c}`,
622
+ label: "",
623
+ separator: !0,
624
+ action: () => {
625
+ }
626
+ }), n = c, t.push(s);
627
+ }
628
+ return t;
629
+ }
630
+ /**
631
+ * Convert plugin-contributed HeaderContextMenuItems to the internal ContextMenuItem format.
632
+ */
633
+ convertPluginItems(e) {
634
+ return e.map((t) => ({
635
+ id: t.id,
636
+ name: t.label,
637
+ icon: t.icon,
638
+ shortcut: t.shortcut,
639
+ disabled: t.disabled ?? !1,
640
+ action: () => t.action(),
641
+ separator: t.separator,
642
+ cssClass: t.cssClass
643
+ }));
561
644
  }
562
645
  // #endregion
563
646
  // #region Hooks
@@ -569,29 +652,29 @@ class S extends R {
569
652
  t && t.getAttribute("data-context-menu-bound") !== "true" && (t.setAttribute("data-context-menu-bound", "true"), t.addEventListener("contextmenu", (n) => {
570
653
  const s = n;
571
654
  s.preventDefault();
572
- const o = s.target, i = o.closest("[data-row][data-col]"), u = o.closest(".header-cell");
573
- 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);
576
- a = {
577
- row: y,
578
- rowIndex: c,
579
- column: d,
580
- columnIndex: b,
581
- field: d?.field ?? "",
582
- value: y?.[d?.field] ?? null,
655
+ const c = s.target, o = c.closest("[data-row][data-col]"), i = c.closest('[part~="header-cell"]');
656
+ let d;
657
+ if (o) {
658
+ const u = parseInt(o.getAttribute("data-row") ?? "-1", 10), m = parseInt(o.getAttribute("data-col") ?? "-1", 10), a = this.visibleColumns[m], E = this.rows[u], A = this.syncSelectionOnContextMenu(u);
659
+ d = {
660
+ row: E,
661
+ rowIndex: u,
662
+ column: a,
663
+ columnIndex: m,
664
+ field: a?.field ?? "",
665
+ value: E?.[a?.field] ?? null,
583
666
  isHeader: !1,
584
667
  event: s,
585
- selectedRows: M
668
+ selectedRows: A
586
669
  };
587
- } else if (u) {
588
- const c = parseInt(u.getAttribute("data-col") ?? "-1", 10), b = this.columns[c];
589
- a = {
670
+ } else if (i) {
671
+ const u = parseInt(i.getAttribute("data-col") ?? "-1", 10), m = this.visibleColumns[u];
672
+ d = {
590
673
  row: null,
591
674
  rowIndex: -1,
592
- column: b,
593
- columnIndex: c,
594
- field: b?.field ?? "",
675
+ column: m,
676
+ columnIndex: u,
677
+ field: m?.field ?? "",
595
678
  value: null,
596
679
  isHeader: !0,
597
680
  event: s,
@@ -599,16 +682,21 @@ class S extends R {
599
682
  };
600
683
  } else
601
684
  return;
602
- 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,
606
- a,
607
- (c) => {
608
- c.action && c.action(a), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
685
+ this.params = d, this.position = { x: s.clientX, y: s.clientY };
686
+ const b = this.collectPluginItems(d);
687
+ let r = v(this.config.items ?? x, d);
688
+ if (b.length > 0) {
689
+ const u = this.convertPluginItems(b);
690
+ r.length > 0 && u.length > 0 ? r = [...r, { id: "__plugin-sep", name: "", separator: !0 }, ...u] : r = [...r, ...u];
691
+ }
692
+ r = I(r), r.length && (this.menuElement && this.menuElement.remove(), this.menuElement = y(
693
+ r,
694
+ d,
695
+ (u) => {
696
+ u.action && u.action(d), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
609
697
  },
610
698
  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 }));
699
+ ), 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: d, items: r }));
612
700
  }));
613
701
  }
614
702
  // #endregion
@@ -630,15 +718,20 @@ class S extends R {
630
718
  isHeader: n.isHeader ?? !1,
631
719
  event: n.event ?? new MouseEvent("contextmenu"),
632
720
  selectedRows: n.selectedRows ?? []
633
- }, o = x(this.config.items ?? p, s);
634
- this.menuElement && this.menuElement.remove(), this.menuElement = v(
721
+ }, c = this.collectPluginItems(s);
722
+ let o = v(this.config.items ?? x, s);
723
+ if (c.length > 0) {
724
+ const i = this.convertPluginItems(c);
725
+ o.length > 0 && i.length > 0 ? o = [...o, { id: "__plugin-sep", name: "", separator: !0 }, ...i] : o = [...o, ...i];
726
+ }
727
+ o = I(o), this.menuElement && this.menuElement.remove(), this.menuElement = y(
635
728
  o,
636
729
  s,
637
730
  (i) => {
638
731
  i.action && i.action(s), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
639
732
  },
640
733
  this.gridIcons.submenuArrow
641
- ), document.body.appendChild(this.menuElement), this.copyGridStyles(this.menuElement), C(this.menuElement, e, t), this.isOpen = !0;
734
+ ), document.body.appendChild(this.menuElement), this.copyGridStyles(this.menuElement), S(this.menuElement, e, t), this.isOpen = !0;
642
735
  }
643
736
  /**
644
737
  * Hide the context menu.
@@ -657,6 +750,6 @@ class S extends R {
657
750
  // Styles are injected globally via installGlobalHandlers() since menu renders in document.body
658
751
  }
659
752
  export {
660
- S as ContextMenuPlugin
753
+ _ as ContextMenuPlugin
661
754
  };
662
755
  //# sourceMappingURL=index.js.map