@toolbox-web/grid 0.0.4 → 0.0.6

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 (64) hide show
  1. package/README.md +24 -0
  2. package/all.d.ts +1709 -135
  3. package/all.js +745 -645
  4. package/all.js.map +1 -1
  5. package/index.d.ts +161 -1
  6. package/index.js +1050 -913
  7. package/index.js.map +1 -1
  8. package/lib/plugins/clipboard/index.js +110 -52
  9. package/lib/plugins/clipboard/index.js.map +1 -1
  10. package/lib/plugins/column-virtualization/index.js +78 -20
  11. package/lib/plugins/column-virtualization/index.js.map +1 -1
  12. package/lib/plugins/context-menu/index.js +163 -95
  13. package/lib/plugins/context-menu/index.js.map +1 -1
  14. package/lib/plugins/export/index.js +93 -35
  15. package/lib/plugins/export/index.js.map +1 -1
  16. package/lib/plugins/filtering/index.js +188 -133
  17. package/lib/plugins/filtering/index.js.map +1 -1
  18. package/lib/plugins/grouping-columns/index.js +69 -11
  19. package/lib/plugins/grouping-columns/index.js.map +1 -1
  20. package/lib/plugins/grouping-rows/index.js +111 -55
  21. package/lib/plugins/grouping-rows/index.js.map +1 -1
  22. package/lib/plugins/master-detail/index.js +196 -51
  23. package/lib/plugins/master-detail/index.js.map +1 -1
  24. package/lib/plugins/multi-sort/index.js +104 -46
  25. package/lib/plugins/multi-sort/index.js.map +1 -1
  26. package/lib/plugins/pinned-columns/index.js +74 -16
  27. package/lib/plugins/pinned-columns/index.js.map +1 -1
  28. package/lib/plugins/pinned-rows/index.js +65 -7
  29. package/lib/plugins/pinned-rows/index.js.map +1 -1
  30. package/lib/plugins/pivot/index.js +117 -59
  31. package/lib/plugins/pivot/index.js.map +1 -1
  32. package/lib/plugins/reorder/index.js +103 -45
  33. package/lib/plugins/reorder/index.js.map +1 -1
  34. package/lib/plugins/selection/index.js +139 -81
  35. package/lib/plugins/selection/index.js.map +1 -1
  36. package/lib/plugins/server-side/index.js +96 -38
  37. package/lib/plugins/server-side/index.js.map +1 -1
  38. package/lib/plugins/tree/index.js +108 -47
  39. package/lib/plugins/tree/index.js.map +1 -1
  40. package/lib/plugins/undo-redo/index.js +70 -12
  41. package/lib/plugins/undo-redo/index.js.map +1 -1
  42. package/lib/plugins/visibility/index.js +82 -24
  43. package/lib/plugins/visibility/index.js.map +1 -1
  44. package/package.json +1 -1
  45. package/umd/grid.all.umd.js +31 -31
  46. package/umd/grid.all.umd.js.map +1 -1
  47. package/umd/grid.umd.js +15 -15
  48. package/umd/grid.umd.js.map +1 -1
  49. package/umd/plugins/context-menu.umd.js +2 -2
  50. package/umd/plugins/context-menu.umd.js.map +1 -1
  51. package/umd/plugins/filtering.umd.js +3 -3
  52. package/umd/plugins/filtering.umd.js.map +1 -1
  53. package/umd/plugins/grouping-rows.umd.js +2 -2
  54. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  55. package/umd/plugins/master-detail.umd.js +2 -2
  56. package/umd/plugins/master-detail.umd.js.map +1 -1
  57. package/umd/plugins/multi-sort.umd.js +1 -1
  58. package/umd/plugins/multi-sort.umd.js.map +1 -1
  59. package/umd/plugins/reorder.umd.js +1 -1
  60. package/umd/plugins/reorder.umd.js.map +1 -1
  61. package/umd/plugins/tree.umd.js +2 -2
  62. package/umd/plugins/tree.umd.js.map +1 -1
  63. package/umd/plugins/visibility.umd.js +1 -1
  64. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -1,4 +1,13 @@
1
- class f {
1
+ const f = {
2
+ expand: "▶",
3
+ collapse: "▼",
4
+ sortAsc: "▲",
5
+ sortDesc: "▼",
6
+ sortNone: "⇅",
7
+ submenuArrow: "▶",
8
+ dragHandle: "⋮⋮"
9
+ };
10
+ class w {
2
11
  /** Plugin version - override in subclass if needed */
3
12
  version = "1.0.0";
4
13
  /** CSS styles to inject into the grid's shadow DOM */
@@ -97,6 +106,55 @@ class f {
97
106
  get shadowRoot() {
98
107
  return this.grid?.shadowRoot ?? null;
99
108
  }
109
+ /**
110
+ * Get the disconnect signal for event listener cleanup.
111
+ * This signal is aborted when the grid disconnects from the DOM.
112
+ * Use this when adding event listeners that should be cleaned up automatically.
113
+ *
114
+ * Best for:
115
+ * - Document/window-level listeners added in attach()
116
+ * - Listeners on the grid element itself
117
+ * - Any listener that should persist across renders
118
+ *
119
+ * Not needed for:
120
+ * - Listeners on elements created in afterRender() (removed with element)
121
+ *
122
+ * @example
123
+ * element.addEventListener('click', handler, { signal: this.disconnectSignal });
124
+ * document.addEventListener('keydown', handler, { signal: this.disconnectSignal });
125
+ */
126
+ get disconnectSignal() {
127
+ return this.grid?.disconnectSignal;
128
+ }
129
+ /**
130
+ * Get the grid-level icons configuration.
131
+ * Returns merged icons (user config + defaults).
132
+ */
133
+ get gridIcons() {
134
+ const e = this.grid?.gridConfig?.icons ?? {};
135
+ return { ...f, ...e };
136
+ }
137
+ /**
138
+ * Resolve an icon value to string or HTMLElement.
139
+ * Checks plugin config first, then grid-level icons, then defaults.
140
+ *
141
+ * @param iconKey - The icon key in GridIcons (e.g., 'expand', 'collapse')
142
+ * @param pluginOverride - Optional plugin-level override
143
+ * @returns The resolved icon value
144
+ */
145
+ resolveIcon(e, t) {
146
+ return t !== void 0 ? t : this.gridIcons[e];
147
+ }
148
+ /**
149
+ * Set an icon value on an element.
150
+ * Handles both string (text/HTML) and HTMLElement values.
151
+ *
152
+ * @param element - The element to set the icon on
153
+ * @param icon - The icon value (string or HTMLElement)
154
+ */
155
+ setIcon(e, t) {
156
+ typeof t == "string" ? e.innerHTML = t : t instanceof HTMLElement && (e.innerHTML = "", e.appendChild(t.cloneNode(!0)));
157
+ }
100
158
  /**
101
159
  * Log a warning message.
102
160
  */
@@ -104,7 +162,7 @@ class f {
104
162
  console.warn(`[tbw-grid:${this.name}] ${e}`);
105
163
  }
106
164
  }
107
- function h(s) {
165
+ function d(s) {
108
166
  return {
109
167
  startRow: Math.min(s.startRow, s.endRow),
110
168
  startCol: Math.min(s.startCol, s.endCol),
@@ -112,35 +170,35 @@ function h(s) {
112
170
  endCol: Math.max(s.startCol, s.endCol)
113
171
  };
114
172
  }
115
- function w(s) {
116
- const e = h(s);
173
+ function R(s) {
174
+ const e = d(s);
117
175
  return {
118
176
  from: { row: e.startRow, col: e.startCol },
119
177
  to: { row: e.endRow, col: e.endCol }
120
178
  };
121
179
  }
122
- function d(s) {
123
- return s.map(w);
180
+ function h(s) {
181
+ return s.map(R);
124
182
  }
125
- function R(s, e, t) {
126
- const l = h(t);
127
- return s >= l.startRow && s <= l.endRow && e >= l.startCol && e <= l.endCol;
183
+ function C(s, e, t) {
184
+ const r = d(t);
185
+ return s >= r.startRow && s <= r.endRow && e >= r.startCol && e <= r.endCol;
128
186
  }
129
187
  function g(s, e, t) {
130
- return t.some((l) => R(s, e, l));
188
+ return t.some((r) => C(s, e, r));
131
189
  }
132
- function C(s) {
133
- const e = [], t = h(s);
134
- for (let l = t.startRow; l <= t.endRow; l++)
135
- for (let r = t.startCol; r <= t.endCol; r++)
136
- e.push({ row: l, col: r });
190
+ function m(s) {
191
+ const e = [], t = d(s);
192
+ for (let r = t.startRow; r <= t.endRow; r++)
193
+ for (let n = t.startCol; n <= t.endCol; n++)
194
+ e.push({ row: r, col: n });
137
195
  return e;
138
196
  }
139
- function m(s) {
197
+ function b(s) {
140
198
  const e = /* @__PURE__ */ new Map();
141
199
  for (const t of s)
142
- for (const l of C(t))
143
- e.set(`${l.row},${l.col}`, l);
200
+ for (const r of m(t))
201
+ e.set(`${r.row},${r.col}`, r);
144
202
  return [...e.values()];
145
203
  }
146
204
  function u(s, e) {
@@ -151,7 +209,7 @@ function u(s, e) {
151
209
  endCol: e.col
152
210
  };
153
211
  }
154
- function b(s, e, t) {
212
+ function A(s, e, t) {
155
213
  if (s === "cell" && e.selectedCell)
156
214
  return {
157
215
  mode: s,
@@ -163,15 +221,15 @@ function b(s, e, t) {
163
221
  ]
164
222
  };
165
223
  if (s === "row" && e.selected.size > 0) {
166
- const l = [...e.selected].map((r) => ({
167
- from: { row: r, col: 0 },
168
- to: { row: r, col: t - 1 }
224
+ const r = [...e.selected].map((n) => ({
225
+ from: { row: n, col: 0 },
226
+ to: { row: n, col: t - 1 }
169
227
  }));
170
- return { mode: s, ranges: l };
228
+ return { mode: s, ranges: r };
171
229
  }
172
- return s === "range" && e.ranges.length > 0 ? { mode: s, ranges: d(e.ranges) } : { mode: s, ranges: [] };
230
+ return s === "range" && e.ranges.length > 0 ? { mode: s, ranges: h(e.ranges) } : { mode: s, ranges: [] };
173
231
  }
174
- class v extends f {
232
+ class v extends w {
175
233
  name = "selection";
176
234
  version = "1.0.0";
177
235
  get defaultConfig() {
@@ -197,32 +255,32 @@ class v extends f {
197
255
  }
198
256
  // ===== Event Handlers =====
199
257
  onCellClick(e) {
200
- const { rowIndex: t, colIndex: l, originalEvent: r } = e, { mode: o } = this.config;
258
+ const { rowIndex: t, colIndex: r, originalEvent: n } = e, { mode: o } = this.config;
201
259
  if (o === "cell")
202
- return this.selectedCell = { row: t, col: l }, this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
260
+ return this.selectedCell = { row: t, col: r }, this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
203
261
  if (o === "row")
204
262
  return this.selected.clear(), this.selected.add(t), this.lastSelected = t, this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
205
263
  if (o === "range") {
206
- const a = r.shiftKey, i = r.ctrlKey || r.metaKey;
264
+ const a = n.shiftKey, i = n.ctrlKey || n.metaKey;
207
265
  if (a && this.cellAnchor) {
208
- const n = u(this.cellAnchor, { row: t, col: l });
209
- i ? this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = n : this.ranges.push(n) : this.ranges = [n], this.activeRange = n;
266
+ const l = u(this.cellAnchor, { row: t, col: r });
267
+ i ? this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = l : this.ranges.push(l) : this.ranges = [l], this.activeRange = l;
210
268
  } else if (i) {
211
- const n = {
269
+ const l = {
212
270
  startRow: t,
213
- startCol: l,
271
+ startCol: r,
214
272
  endRow: t,
215
- endCol: l
273
+ endCol: r
216
274
  };
217
- this.ranges.push(n), this.activeRange = n, this.cellAnchor = { row: t, col: l };
275
+ this.ranges.push(l), this.activeRange = l, this.cellAnchor = { row: t, col: r };
218
276
  } else {
219
- const n = {
277
+ const l = {
220
278
  startRow: t,
221
- startCol: l,
279
+ startCol: r,
222
280
  endRow: t,
223
- endCol: l
281
+ endCol: r
224
282
  };
225
- this.ranges = [n], this.activeRange = n, this.cellAnchor = { row: t, col: l };
283
+ this.ranges = [l], this.activeRange = l, this.cellAnchor = { row: t, col: r };
226
284
  }
227
285
  return this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
228
286
  }
@@ -233,13 +291,13 @@ class v extends f {
233
291
  if (e.key === "Escape")
234
292
  return t === "cell" ? this.selectedCell = null : t === "row" ? (this.selected.clear(), this.anchor = null) : t === "range" && (this.ranges = [], this.activeRange = null, this.cellAnchor = null), this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
235
293
  if (t === "range" && e.key === "a" && (e.ctrlKey || e.metaKey)) {
236
- const l = this.rows.length, r = this.columns.length;
237
- if (l > 0 && r > 0) {
294
+ const r = this.rows.length, n = this.columns.length;
295
+ if (r > 0 && n > 0) {
238
296
  const o = {
239
297
  startRow: 0,
240
298
  startCol: 0,
241
- endRow: l - 1,
242
- endCol: r - 1
299
+ endRow: r - 1,
300
+ endCol: n - 1
243
301
  };
244
302
  return this.ranges = [o], this.activeRange = o, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
245
303
  }
@@ -250,13 +308,13 @@ class v extends f {
250
308
  if (this.config.mode !== "range" || e.rowIndex === void 0 || e.colIndex === void 0 || e.rowIndex < 0 || e.originalEvent.shiftKey && this.cellAnchor)
251
309
  return;
252
310
  this.isDragging = !0;
253
- const t = e.rowIndex, l = e.colIndex;
254
- this.cellAnchor = { row: t, col: l }, e.originalEvent.ctrlKey || e.originalEvent.metaKey || (this.ranges = []);
311
+ const t = e.rowIndex, r = e.colIndex;
312
+ this.cellAnchor = { row: t, col: r }, e.originalEvent.ctrlKey || e.originalEvent.metaKey || (this.ranges = []);
255
313
  const o = {
256
314
  startRow: t,
257
- startCol: l,
315
+ startCol: r,
258
316
  endRow: t,
259
- endCol: l
317
+ endCol: r
260
318
  };
261
319
  return this.ranges.push(o), this.activeRange = o, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
262
320
  }
@@ -280,17 +338,17 @@ class v extends f {
280
338
  e.querySelectorAll(".cell").forEach((o) => {
281
339
  o.classList.remove("selected", "top", "bottom", "first", "last");
282
340
  });
283
- const r = e.querySelectorAll(".data-grid-row");
284
- if (r.forEach((o) => {
341
+ const n = e.querySelectorAll(".data-grid-row");
342
+ if (n.forEach((o) => {
285
343
  o.classList.remove("selected", "row-focus");
286
- }), t === "row" && r.forEach((o) => {
344
+ }), t === "row" && n.forEach((o) => {
287
345
  const a = o.querySelector(".cell[data-row]"), i = parseInt(a?.getAttribute("data-row") ?? "-1", 10);
288
- i >= 0 && this.selected.has(i) && (o.classList.add("selected", "row-focus"), o.querySelectorAll(".cell-focus").forEach((n) => n.classList.remove("cell-focus")));
346
+ i >= 0 && this.selected.has(i) && (o.classList.add("selected", "row-focus"), o.querySelectorAll(".cell-focus").forEach((l) => l.classList.remove("cell-focus")));
289
347
  }), t === "range" && this.ranges.length > 0) {
290
- const o = this.activeRange ? h(this.activeRange) : null;
348
+ const o = this.activeRange ? d(this.activeRange) : null;
291
349
  e.querySelectorAll(".cell[data-row][data-col]").forEach((i) => {
292
- const n = parseInt(i.getAttribute("data-row") ?? "-1", 10), c = parseInt(i.getAttribute("data-col") ?? "-1", 10);
293
- n >= 0 && c >= 0 && g(n, c, this.ranges) && (i.classList.add("selected"), i.classList.remove("cell-focus"), o && (n === o.startRow && i.classList.add("top"), n === o.endRow && i.classList.add("bottom"), c === o.startCol && i.classList.add("first"), c === o.endCol && i.classList.add("last")));
350
+ const l = parseInt(i.getAttribute("data-row") ?? "-1", 10), c = parseInt(i.getAttribute("data-col") ?? "-1", 10);
351
+ l >= 0 && c >= 0 && g(l, c, this.ranges) && (i.classList.add("selected"), i.classList.remove("cell-focus"), o && (l === o.startRow && i.classList.add("top"), l === o.endRow && i.classList.add("bottom"), c === o.startCol && i.classList.add("first"), c === o.endCol && i.classList.add("last")));
294
352
  });
295
353
  }
296
354
  t === "cell" && this.selectedCell && e.querySelectorAll(".cell-focus").forEach((o) => o.classList.remove("cell-focus"));
@@ -298,8 +356,8 @@ class v extends f {
298
356
  afterRender() {
299
357
  const e = this.shadowRoot;
300
358
  if (!e) return;
301
- const t = e.children[0], { mode: l } = this.config;
302
- this.grid.setAttribute("data-selection-mode", l), t && t.classList.toggle("selecting", this.isDragging), this.#t();
359
+ const t = e.children[0], { mode: r } = this.config;
360
+ this.grid.setAttribute("data-selection-mode", r), t && t.classList.toggle("selecting", this.isDragging), this.#t();
303
361
  }
304
362
  /**
305
363
  * Called after scroll-triggered row rendering.
@@ -325,13 +383,13 @@ class v extends f {
325
383
  * Get all selected cell ranges in public format.
326
384
  */
327
385
  getRanges() {
328
- return d(this.ranges);
386
+ return h(this.ranges);
329
387
  }
330
388
  /**
331
389
  * Get all selected cells across all ranges.
332
390
  */
333
391
  getSelectedCells() {
334
- return m(this.ranges);
392
+ return b(this.ranges);
335
393
  }
336
394
  /**
337
395
  * Check if a specific cell is in range selection.
@@ -356,12 +414,12 @@ class v extends f {
356
414
  endCol: t.to.col
357
415
  })), this.activeRange = this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] : null, this.emit("selection-change", {
358
416
  mode: this.config.mode,
359
- ranges: d(this.ranges)
417
+ ranges: h(this.ranges)
360
418
  }), this.requestAfterRender();
361
419
  }
362
420
  // ===== Private Helpers =====
363
421
  #e() {
364
- return b(
422
+ return A(
365
423
  this.config.mode,
366
424
  {
367
425
  selectedCell: this.selectedCell,
@@ -406,39 +464,39 @@ class v extends f {
406
464
  }
407
465
  `;
408
466
  }
409
- function p(s, e, t, l) {
410
- const r = new Set(s.selected);
467
+ function y(s, e, t, r) {
468
+ const n = new Set(s.selected);
411
469
  let o = s.anchor;
412
470
  if (t === "single")
413
- r.clear(), r.add(e), o = e;
471
+ n.clear(), n.add(e), o = e;
414
472
  else if (t === "multiple") {
415
- const a = l.ctrlKey || l.metaKey;
416
- if (l.shiftKey && s.anchor !== null) {
417
- const i = Math.min(s.anchor, e), n = Math.max(s.anchor, e);
418
- for (let c = i; c <= n; c++)
419
- r.add(c);
420
- } else a ? (r.has(e) ? r.delete(e) : r.add(e), o = e) : (r.clear(), r.add(e), o = e);
421
- }
422
- return { selected: r, lastSelected: e, anchor: o };
473
+ const a = r.ctrlKey || r.metaKey;
474
+ if (r.shiftKey && s.anchor !== null) {
475
+ const i = Math.min(s.anchor, e), l = Math.max(s.anchor, e);
476
+ for (let c = i; c <= l; c++)
477
+ n.add(c);
478
+ } else a ? (n.has(e) ? n.delete(e) : n.add(e), o = e) : (n.clear(), n.add(e), o = e);
479
+ }
480
+ return { selected: n, lastSelected: e, anchor: o };
423
481
  }
424
- function y(s) {
482
+ function S(s) {
425
483
  const e = /* @__PURE__ */ new Set();
426
484
  for (let t = 0; t < s; t++)
427
485
  e.add(t);
428
486
  return e;
429
487
  }
430
- function S(s, e) {
431
- const t = [], l = [];
432
- for (const r of e)
433
- s.has(r) || t.push(r);
434
- for (const r of s)
435
- e.has(r) || l.push(r);
436
- return { added: t, removed: l };
488
+ function I(s, e) {
489
+ const t = [], r = [];
490
+ for (const n of e)
491
+ s.has(n) || t.push(n);
492
+ for (const n of s)
493
+ e.has(n) || r.push(n);
494
+ return { added: t, removed: r };
437
495
  }
438
496
  export {
439
497
  v as SelectionPlugin,
440
- S as computeSelectionDiff,
441
- p as handleRowClick,
442
- y as selectAll
498
+ I as computeSelectionDiff,
499
+ y as handleRowClick,
500
+ S as selectAll
443
501
  };
444
502
  //# sourceMappingURL=index.js.map