@toolbox-web/grid 0.0.7 → 0.1.1

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 (87) hide show
  1. package/README.md +1 -1
  2. package/all.d.ts +156 -95
  3. package/all.js +1561 -1502
  4. package/all.js.map +1 -1
  5. package/custom-elements.json +89 -7
  6. package/index.d.ts +68 -23
  7. package/index.js +1617 -1388
  8. package/index.js.map +1 -1
  9. package/lib/plugins/clipboard/index.js +48 -49
  10. package/lib/plugins/clipboard/index.js.map +1 -1
  11. package/lib/plugins/column-virtualization/index.js +6 -6
  12. package/lib/plugins/column-virtualization/index.js.map +1 -1
  13. package/lib/plugins/context-menu/index.js +64 -109
  14. package/lib/plugins/context-menu/index.js.map +1 -1
  15. package/lib/plugins/export/index.js +7 -7
  16. package/lib/plugins/export/index.js.map +1 -1
  17. package/lib/plugins/filtering/index.js +5 -38
  18. package/lib/plugins/filtering/index.js.map +1 -1
  19. package/lib/plugins/grouping-columns/index.js +4 -32
  20. package/lib/plugins/grouping-columns/index.js.map +1 -1
  21. package/lib/plugins/grouping-rows/index.js +8 -45
  22. package/lib/plugins/grouping-rows/index.js.map +1 -1
  23. package/lib/plugins/master-detail/index.js +7 -31
  24. package/lib/plugins/master-detail/index.js.map +1 -1
  25. package/lib/plugins/multi-sort/index.js +19 -42
  26. package/lib/plugins/multi-sort/index.js.map +1 -1
  27. package/lib/plugins/pinned-columns/index.js +5 -6
  28. package/lib/plugins/pinned-columns/index.js.map +1 -1
  29. package/lib/plugins/pinned-rows/index.js +14 -88
  30. package/lib/plugins/pinned-rows/index.js.map +1 -1
  31. package/lib/plugins/pivot/index.js +673 -145
  32. package/lib/plugins/pivot/index.js.map +1 -1
  33. package/lib/plugins/reorder/index.js +22 -51
  34. package/lib/plugins/reorder/index.js.map +1 -1
  35. package/lib/plugins/selection/index.js +76 -83
  36. package/lib/plugins/selection/index.js.map +1 -1
  37. package/lib/plugins/server-side/index.js +2 -2
  38. package/lib/plugins/server-side/index.js.map +1 -1
  39. package/lib/plugins/tree/index.js +6 -14
  40. package/lib/plugins/tree/index.js.map +1 -1
  41. package/lib/plugins/undo-redo/index.js +2 -3
  42. package/lib/plugins/undo-redo/index.js.map +1 -1
  43. package/lib/plugins/visibility/index.js +13 -105
  44. package/lib/plugins/visibility/index.js.map +1 -1
  45. package/package.json +1 -1
  46. package/themes/dg-theme-bootstrap.css +73 -0
  47. package/themes/dg-theme-material.css +71 -0
  48. package/umd/grid.all.umd.js +43 -469
  49. package/umd/grid.all.umd.js.map +1 -1
  50. package/umd/grid.umd.js +35 -66
  51. package/umd/grid.umd.js.map +1 -1
  52. package/umd/plugins/clipboard.umd.js +4 -4
  53. package/umd/plugins/clipboard.umd.js.map +1 -1
  54. package/umd/plugins/column-virtualization.umd.js +1 -1
  55. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  56. package/umd/plugins/context-menu.umd.js +1 -52
  57. package/umd/plugins/context-menu.umd.js.map +1 -1
  58. package/umd/plugins/export.umd.js +1 -1
  59. package/umd/plugins/export.umd.js.map +1 -1
  60. package/umd/plugins/filtering.umd.js +2 -34
  61. package/umd/plugins/filtering.umd.js.map +1 -1
  62. package/umd/plugins/grouping-columns.umd.js +1 -28
  63. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  64. package/umd/plugins/grouping-rows.umd.js +1 -39
  65. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  66. package/umd/plugins/master-detail.umd.js +1 -26
  67. package/umd/plugins/master-detail.umd.js.map +1 -1
  68. package/umd/plugins/multi-sort.umd.js +1 -25
  69. package/umd/plugins/multi-sort.umd.js.map +1 -1
  70. package/umd/plugins/pinned-columns.umd.js +1 -1
  71. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  72. package/umd/plugins/pinned-rows.umd.js +1 -72
  73. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  74. package/umd/plugins/pivot.umd.js +1 -7
  75. package/umd/plugins/pivot.umd.js.map +1 -1
  76. package/umd/plugins/reorder.umd.js +1 -30
  77. package/umd/plugins/reorder.umd.js.map +1 -1
  78. package/umd/plugins/selection.umd.js +1 -33
  79. package/umd/plugins/selection.umd.js.map +1 -1
  80. package/umd/plugins/server-side.umd.js +1 -1
  81. package/umd/plugins/server-side.umd.js.map +1 -1
  82. package/umd/plugins/tree.umd.js +1 -10
  83. package/umd/plugins/tree.umd.js.map +1 -1
  84. package/umd/plugins/undo-redo.umd.js +1 -1
  85. package/umd/plugins/undo-redo.umd.js.map +1 -1
  86. package/umd/plugins/visibility.umd.js +1 -93
  87. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,13 +1,14 @@
1
- const v = {
1
+ const y = {
2
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
5
5
  sortDesc: "▼",
6
6
  sortNone: "⇅",
7
7
  submenuArrow: "▶",
8
- dragHandle: "⋮⋮"
8
+ dragHandle: "⋮⋮",
9
+ toolPanel: "☰"
9
10
  };
10
- class y {
11
+ class C {
11
12
  /** Plugin version - override in subclass if needed */
12
13
  version = "1.0.0";
13
14
  /** CSS styles to inject into the grid's shadow DOM */
@@ -132,7 +133,7 @@ class y {
132
133
  */
133
134
  get gridIcons() {
134
135
  const e = this.grid?.gridConfig?.icons ?? {};
135
- return { ...v, ...e };
136
+ return { ...y, ...e };
136
137
  }
137
138
  /**
138
139
  * Resolve an icon value to string or HTMLElement.
@@ -162,109 +163,59 @@ class y {
162
163
  console.warn(`[tbw-grid:${this.name}] ${e}`);
163
164
  }
164
165
  }
165
- function b(s, e) {
166
+ const I = ".tbw-context-menu{position:fixed;background:light-dark(#f5f5f5,#2a2a2a);color:light-dark(#222,#eee);border:1px solid light-dark(#d0d0d4,#454545);border-radius:4px;box-shadow:0 2px 10px #00000026;min-width:160px;padding:4px 0;z-index:10000;font-size:13px;font-family:system-ui,sans-serif}.tbw-context-menu-item{display:flex;align-items:center;padding:6px 12px;cursor:pointer;gap:8px}.tbw-context-menu-item:hover:not(.disabled){background:light-dark(#e8e8e8,#3a3a3a)}.tbw-context-menu-item.disabled{opacity:.5;cursor:default}.tbw-context-menu-item.danger{color:light-dark(#c00,#f66)}.tbw-context-menu-icon{width:16px;text-align:center}.tbw-context-menu-label{flex:1}.tbw-context-menu-shortcut{color:light-dark(#888,#888);font-size:11px}.tbw-context-menu-arrow{font-size:10px;color:light-dark(#888,#888)}.tbw-context-menu-separator{height:1px;background:light-dark(#d0d0d4,#454545);margin:4px 0}";
167
+ function x(s, e) {
166
168
  return (typeof s == "function" ? s(e) : s).filter((i) => !(i.hidden === !0 || typeof i.hidden == "function" && i.hidden(e)));
167
169
  }
168
- function C(s, e) {
170
+ function M(s, e) {
169
171
  return s.disabled === !0 ? !0 : typeof s.disabled == "function" ? s.disabled(e) : !1;
170
172
  }
171
- function x(s, e, n, i = v.submenuArrow) {
172
- const l = document.createElement("div");
173
- l.className = "tbw-context-menu", l.setAttribute("role", "menu");
173
+ function w(s, e, n, i = y.submenuArrow) {
174
+ const r = document.createElement("div");
175
+ r.className = "tbw-context-menu", r.setAttribute("role", "menu");
174
176
  for (const o of s) {
175
177
  if (o.separator) {
176
- const r = document.createElement("div");
177
- r.className = "tbw-context-menu-separator", r.setAttribute("role", "separator"), l.appendChild(r);
178
+ const l = document.createElement("div");
179
+ l.className = "tbw-context-menu-separator", l.setAttribute("role", "separator"), r.appendChild(l);
178
180
  continue;
179
181
  }
180
182
  const t = document.createElement("div");
181
183
  t.className = "tbw-context-menu-item", o.cssClass && t.classList.add(o.cssClass), t.setAttribute("role", "menuitem"), t.setAttribute("data-id", o.id);
182
- const c = C(o, e);
184
+ const c = M(o, e);
183
185
  if (c && (t.classList.add("disabled"), t.setAttribute("aria-disabled", "true")), o.icon) {
184
- const r = document.createElement("span");
185
- r.className = "tbw-context-menu-icon", r.innerHTML = o.icon, t.appendChild(r);
186
+ const l = document.createElement("span");
187
+ l.className = "tbw-context-menu-icon", l.innerHTML = o.icon, t.appendChild(l);
186
188
  }
187
189
  const d = document.createElement("span");
188
190
  if (d.className = "tbw-context-menu-label", d.textContent = o.name, t.appendChild(d), o.shortcut) {
189
- const r = document.createElement("span");
190
- r.className = "tbw-context-menu-shortcut", r.textContent = o.shortcut, t.appendChild(r);
191
+ const l = document.createElement("span");
192
+ l.className = "tbw-context-menu-shortcut", l.textContent = o.shortcut, t.appendChild(l);
191
193
  }
192
194
  if (o.subMenu?.length) {
193
- const r = document.createElement("span");
194
- r.className = "tbw-context-menu-arrow", typeof i == "string" ? r.innerHTML = i : i instanceof HTMLElement && r.appendChild(i.cloneNode(!0)), t.appendChild(r), t.addEventListener("mouseenter", () => {
195
+ const l = document.createElement("span");
196
+ l.className = "tbw-context-menu-arrow", typeof i == "string" ? l.innerHTML = i : i instanceof HTMLElement && l.appendChild(i.cloneNode(!0)), t.appendChild(l), t.addEventListener("mouseenter", () => {
195
197
  if (t.querySelector(".tbw-context-menu") || !o.subMenu) return;
196
- const m = b(o.subMenu, e), a = x(m, e, n, i);
198
+ const h = x(o.subMenu, e), a = w(h, e, n, i);
197
199
  a.classList.add("tbw-context-submenu"), a.style.position = "absolute", a.style.left = "100%", a.style.top = "0", t.style.position = "relative", t.appendChild(a);
198
200
  }), t.addEventListener("mouseleave", () => {
199
201
  const u = t.querySelector(".tbw-context-menu");
200
202
  u && u.remove();
201
203
  });
202
204
  }
203
- !c && o.action && !o.subMenu && t.addEventListener("click", (r) => {
204
- r.stopPropagation(), n(o);
205
- }), l.appendChild(t);
205
+ !c && o.action && !o.subMenu && t.addEventListener("click", (l) => {
206
+ l.stopPropagation(), n(o);
207
+ }), r.appendChild(t);
206
208
  }
207
- return l;
209
+ return r;
208
210
  }
209
211
  function E(s, e, n) {
210
212
  s.style.position = "fixed", s.style.left = `${e}px`, s.style.top = `${n}px`, s.style.visibility = "hidden", s.style.zIndex = "10000";
211
- const i = s.getBoundingClientRect(), l = window.innerWidth, o = window.innerHeight;
213
+ const i = s.getBoundingClientRect(), r = window.innerWidth, o = window.innerHeight;
212
214
  let t = e, c = n;
213
- e + i.width > l && (t = e - i.width), n + i.height > o && (c = n - i.height), t = Math.max(0, t), c = Math.max(0, c), s.style.left = `${t}px`, s.style.top = `${c}px`, s.style.visibility = "visible";
215
+ e + i.width > r && (t = e - i.width), n + i.height > o && (c = n - i.height), t = Math.max(0, t), c = Math.max(0, c), s.style.left = `${t}px`, s.style.top = `${c}px`, s.style.visibility = "visible";
214
216
  }
215
- let f = null, p = null, h = null;
216
- const I = `
217
- .tbw-context-menu {
218
- position: fixed;
219
- background: light-dark(#f5f5f5, #2a2a2a);
220
- color: light-dark(#222, #eee);
221
- border: 1px solid light-dark(#d0d0d4, #454545);
222
- border-radius: 4px;
223
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
224
- min-width: 160px;
225
- padding: 4px 0;
226
- z-index: 10000;
227
- font-size: 13px;
228
- font-family: system-ui, sans-serif;
229
- }
230
- .tbw-context-menu-item {
231
- display: flex;
232
- align-items: center;
233
- padding: 6px 12px;
234
- cursor: pointer;
235
- gap: 8px;
236
- }
237
- .tbw-context-menu-item:hover:not(.disabled) {
238
- background: light-dark(#e8e8e8, #3a3a3a);
239
- }
240
- .tbw-context-menu-item.disabled {
241
- opacity: 0.5;
242
- cursor: default;
243
- }
244
- .tbw-context-menu-item.danger {
245
- color: light-dark(#c00, #f66);
246
- }
247
- .tbw-context-menu-icon {
248
- width: 16px;
249
- text-align: center;
250
- }
251
- .tbw-context-menu-label {
252
- flex: 1;
253
- }
254
- .tbw-context-menu-shortcut {
255
- color: light-dark(#888, #888);
256
- font-size: 11px;
257
- }
258
- .tbw-context-menu-arrow {
259
- font-size: 10px;
260
- color: light-dark(#888, #888);
261
- }
262
- .tbw-context-menu-separator {
263
- height: 1px;
264
- background: light-dark(#d0d0d4, #454545);
265
- margin: 4px 0;
266
- }
267
- `, g = [
217
+ let f = null, p = null, m = null, g = 0;
218
+ const b = [
268
219
  {
269
220
  id: "copy",
270
221
  name: "Copy",
@@ -282,13 +233,12 @@ const I = `
282
233
  }
283
234
  }
284
235
  ];
285
- class M extends y {
236
+ class H extends C {
286
237
  name = "contextMenu";
287
238
  version = "1.0.0";
288
239
  get defaultConfig() {
289
240
  return {
290
- enabled: !0,
291
- items: g
241
+ items: b
292
242
  };
293
243
  }
294
244
  // ===== Internal State =====
@@ -298,67 +248,72 @@ class M extends y {
298
248
  menuElement = null;
299
249
  // ===== Lifecycle =====
300
250
  attach(e) {
301
- super.attach(e), this.installGlobalHandlers();
251
+ super.attach(e), this.installGlobalHandlers(), g++;
302
252
  }
303
253
  detach() {
304
- this.menuElement && (this.menuElement.remove(), this.menuElement = null), this.isOpen = !1, this.params = null;
254
+ this.menuElement && (this.menuElement.remove(), this.menuElement = null), this.isOpen = !1, this.params = null, this.uninstallGlobalHandlers();
305
255
  }
306
256
  // ===== Private Methods =====
307
257
  installGlobalHandlers() {
308
- !h && typeof document < "u" && (h = document.createElement("style"), h.id = "tbw-context-menu-styles", h.textContent = I, document.head.appendChild(h)), f || (f = () => {
258
+ !m && typeof document < "u" && (m = document.createElement("style"), m.id = "tbw-context-menu-styles", m.textContent = I, document.head.appendChild(m)), f || (f = () => {
309
259
  document.querySelectorAll(".tbw-context-menu").forEach((n) => n.remove());
310
260
  }, document.addEventListener("click", f)), p || (p = (e) => {
311
261
  e.key === "Escape" && document.querySelectorAll(".tbw-context-menu").forEach((i) => i.remove());
312
262
  }, document.addEventListener("keydown", p));
313
263
  }
264
+ /**
265
+ * Clean up global handlers when the last instance detaches.
266
+ * Uses reference counting to ensure handlers persist while any grid uses the plugin.
267
+ */
268
+ uninstallGlobalHandlers() {
269
+ g--, !(g > 0) && (f && (document.removeEventListener("click", f), f = null), p && (document.removeEventListener("keydown", p), p = null), m && (m.remove(), m = null));
270
+ }
314
271
  // ===== Hooks =====
315
272
  afterRender() {
316
- if (!this.config.enabled) return;
317
273
  const e = this.shadowRoot;
318
274
  if (!e) return;
319
275
  const n = e.children[0];
320
276
  n && n.getAttribute("data-context-menu-bound") !== "true" && (n.setAttribute("data-context-menu-bound", "true"), n.addEventListener("contextmenu", (i) => {
321
- if (!this.config.enabled) return;
322
- const l = i;
323
- l.preventDefault();
324
- const o = l.target, t = o.closest("[data-row][data-col]"), c = o.closest(".header-cell");
277
+ const r = i;
278
+ r.preventDefault();
279
+ const o = r.target, t = o.closest("[data-row][data-col]"), c = o.closest(".header-cell");
325
280
  let d;
326
281
  if (t) {
327
- const u = parseInt(t.getAttribute("data-row") ?? "-1", 10), m = parseInt(t.getAttribute("data-col") ?? "-1", 10), a = this.columns[m], w = this.rows[u];
282
+ const u = parseInt(t.getAttribute("data-row") ?? "-1", 10), h = parseInt(t.getAttribute("data-col") ?? "-1", 10), a = this.columns[h], v = this.rows[u];
328
283
  d = {
329
- row: w,
284
+ row: v,
330
285
  rowIndex: u,
331
286
  column: a,
332
- columnIndex: m,
287
+ columnIndex: h,
333
288
  field: a?.field ?? "",
334
- value: w?.[a?.field] ?? null,
289
+ value: v?.[a?.field] ?? null,
335
290
  isHeader: !1,
336
- event: l
291
+ event: r
337
292
  };
338
293
  } else if (c) {
339
- const u = parseInt(c.getAttribute("data-col") ?? "-1", 10), m = this.columns[u];
294
+ const u = parseInt(c.getAttribute("data-col") ?? "-1", 10), h = this.columns[u];
340
295
  d = {
341
296
  row: null,
342
297
  rowIndex: -1,
343
- column: m,
298
+ column: h,
344
299
  columnIndex: u,
345
- field: m?.field ?? "",
300
+ field: h?.field ?? "",
346
301
  value: null,
347
302
  isHeader: !0,
348
- event: l
303
+ event: r
349
304
  };
350
305
  } else
351
306
  return;
352
- this.params = d, this.position = { x: l.clientX, y: l.clientY };
353
- const r = b(this.config.items ?? g, d);
354
- r.length && (this.menuElement && this.menuElement.remove(), this.menuElement = x(
355
- r,
307
+ this.params = d, this.position = { x: r.clientX, y: r.clientY };
308
+ const l = x(this.config.items ?? b, d);
309
+ l.length && (this.menuElement && this.menuElement.remove(), this.menuElement = w(
310
+ l,
356
311
  d,
357
312
  (u) => {
358
313
  u.action && u.action(d), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
359
314
  },
360
315
  this.gridIcons.submenuArrow
361
- ), document.body.appendChild(this.menuElement), E(this.menuElement, l.clientX, l.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: d, items: r }));
316
+ ), document.body.appendChild(this.menuElement), E(this.menuElement, r.clientX, r.clientY), this.isOpen = !0, this.emit("context-menu-open", { params: d, items: l }));
362
317
  }));
363
318
  }
364
319
  // ===== Public API =====
@@ -369,7 +324,7 @@ class M extends y {
369
324
  * @param params - Partial context menu parameters
370
325
  */
371
326
  showMenu(e, n, i) {
372
- const l = {
327
+ const r = {
373
328
  row: i.row ?? null,
374
329
  rowIndex: i.rowIndex ?? -1,
375
330
  column: i.column ?? null,
@@ -378,12 +333,12 @@ class M extends y {
378
333
  value: i.value ?? null,
379
334
  isHeader: i.isHeader ?? !1,
380
335
  event: i.event ?? new MouseEvent("contextmenu")
381
- }, o = b(this.config.items ?? g, l);
382
- this.menuElement && this.menuElement.remove(), this.menuElement = x(
336
+ }, o = x(this.config.items ?? b, r);
337
+ this.menuElement && this.menuElement.remove(), this.menuElement = w(
383
338
  o,
384
- l,
339
+ r,
385
340
  (t) => {
386
- t.action && t.action(l), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
341
+ t.action && t.action(r), this.menuElement?.remove(), this.menuElement = null, this.isOpen = !1;
387
342
  },
388
343
  this.gridIcons.submenuArrow
389
344
  ), document.body.appendChild(this.menuElement), E(this.menuElement, e, n), this.isOpen = !0;
@@ -404,6 +359,6 @@ class M extends y {
404
359
  // Styles are injected globally via installGlobalHandlers() since menu renders in document.body
405
360
  }
406
361
  export {
407
- M as ContextMenuPlugin
362
+ H as ContextMenuPlugin
408
363
  };
409
364
  //# sourceMappingURL=index.js.map