@toolbox-web/grid 0.4.1 → 0.5.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 (176) hide show
  1. package/README.md +9 -13
  2. package/all.js +1678 -1588
  3. package/all.js.map +1 -1
  4. package/index.js +762 -568
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts +21 -0
  7. package/lib/core/grid.d.ts.map +1 -1
  8. package/lib/core/internal/config-manager.d.ts +1 -0
  9. package/lib/core/internal/config-manager.d.ts.map +1 -1
  10. package/lib/core/internal/dom-builder.d.ts +2 -0
  11. package/lib/core/internal/dom-builder.d.ts.map +1 -1
  12. package/lib/core/internal/header.d.ts.map +1 -1
  13. package/lib/core/internal/keyboard.d.ts.map +1 -1
  14. package/lib/core/internal/resize.d.ts.map +1 -1
  15. package/lib/core/internal/rows.d.ts.map +1 -1
  16. package/lib/core/internal/shell.d.ts +19 -13
  17. package/lib/core/internal/shell.d.ts.map +1 -1
  18. package/lib/core/internal/utils.d.ts +1 -0
  19. package/lib/core/internal/utils.d.ts.map +1 -1
  20. package/lib/core/plugin/base-plugin.d.ts +70 -3
  21. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  22. package/lib/core/plugin/expander-column.d.ts +51 -0
  23. package/lib/core/plugin/expander-column.d.ts.map +1 -0
  24. package/lib/core/plugin/plugin-manager.d.ts +6 -2
  25. package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
  26. package/lib/core/plugin/types.d.ts +117 -1
  27. package/lib/core/plugin/types.d.ts.map +1 -1
  28. package/lib/core/types.d.ts +10 -5
  29. package/lib/core/types.d.ts.map +1 -1
  30. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
  31. package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
  32. package/lib/plugins/clipboard/index.d.ts +1 -1
  33. package/lib/plugins/clipboard/index.d.ts.map +1 -1
  34. package/lib/plugins/clipboard/index.js +295 -190
  35. package/lib/plugins/clipboard/index.js.map +1 -1
  36. package/lib/plugins/clipboard/types.d.ts +72 -2
  37. package/lib/plugins/clipboard/types.d.ts.map +1 -1
  38. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
  39. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
  40. package/lib/plugins/column-virtualization/index.js +143 -56
  41. package/lib/plugins/column-virtualization/index.js.map +1 -1
  42. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
  43. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  44. package/lib/plugins/context-menu/index.js +189 -102
  45. package/lib/plugins/context-menu/index.js.map +1 -1
  46. package/lib/plugins/editing/EditingPlugin.d.ts +2 -7
  47. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  48. package/lib/plugins/editing/index.js +227 -150
  49. package/lib/plugins/editing/index.js.map +1 -1
  50. package/lib/plugins/export/ExportPlugin.d.ts +0 -1
  51. package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
  52. package/lib/plugins/export/index.js +184 -97
  53. package/lib/plugins/export/index.js.map +1 -1
  54. package/lib/plugins/filtering/FilteringPlugin.d.ts +14 -3
  55. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  56. package/lib/plugins/filtering/index.js +296 -176
  57. package/lib/plugins/filtering/index.js.map +1 -1
  58. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
  59. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  60. package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
  61. package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
  62. package/lib/plugins/grouping-columns/index.js +169 -61
  63. package/lib/plugins/grouping-columns/index.js.map +1 -1
  64. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
  65. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
  66. package/lib/plugins/grouping-rows/index.js +243 -140
  67. package/lib/plugins/grouping-rows/index.js.map +1 -1
  68. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
  69. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
  70. package/lib/plugins/master-detail/index.js +278 -196
  71. package/lib/plugins/master-detail/index.js.map +1 -1
  72. package/lib/plugins/master-detail/types.d.ts +0 -10
  73. package/lib/plugins/master-detail/types.d.ts.map +1 -1
  74. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
  75. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
  76. package/lib/plugins/multi-sort/index.js +125 -40
  77. package/lib/plugins/multi-sort/index.js.map +1 -1
  78. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
  79. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  80. package/lib/plugins/pinned-columns/index.js +156 -75
  81. package/lib/plugins/pinned-columns/index.js.map +1 -1
  82. package/lib/plugins/pinned-columns/pinned-columns.d.ts +2 -2
  83. package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
  84. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
  85. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
  86. package/lib/plugins/pinned-rows/index.js +202 -117
  87. package/lib/plugins/pinned-rows/index.js.map +1 -1
  88. package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
  89. package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
  90. package/lib/plugins/pivot/index.js +413 -314
  91. package/lib/plugins/pivot/index.js.map +1 -1
  92. package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
  93. package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
  94. package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
  95. package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
  96. package/lib/plugins/reorder/index.d.ts +1 -1
  97. package/lib/plugins/reorder/index.d.ts.map +1 -1
  98. package/lib/plugins/reorder/index.js +296 -223
  99. package/lib/plugins/reorder/index.js.map +1 -1
  100. package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
  101. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  102. package/lib/plugins/selection/index.d.ts +2 -2
  103. package/lib/plugins/selection/index.d.ts.map +1 -1
  104. package/lib/plugins/selection/index.js +282 -141
  105. package/lib/plugins/selection/index.js.map +1 -1
  106. package/lib/plugins/selection/types.d.ts +24 -0
  107. package/lib/plugins/selection/types.d.ts.map +1 -1
  108. package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
  109. package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
  110. package/lib/plugins/server-side/index.js +96 -9
  111. package/lib/plugins/server-side/index.js.map +1 -1
  112. package/lib/plugins/tree/TreePlugin.d.ts +5 -1
  113. package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
  114. package/lib/plugins/tree/index.js +209 -113
  115. package/lib/plugins/tree/index.js.map +1 -1
  116. package/lib/plugins/tree/types.d.ts +0 -10
  117. package/lib/plugins/tree/types.d.ts.map +1 -1
  118. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
  119. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
  120. package/lib/plugins/undo-redo/index.js +98 -11
  121. package/lib/plugins/undo-redo/index.js.map +1 -1
  122. package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
  123. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  124. package/lib/plugins/visibility/index.js +155 -64
  125. package/lib/plugins/visibility/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/themes/dg-theme-bootstrap.css +55 -53
  128. package/themes/dg-theme-contrast.css +42 -40
  129. package/themes/dg-theme-large.css +38 -37
  130. package/themes/dg-theme-material.css +54 -52
  131. package/themes/dg-theme-standard.css +19 -17
  132. package/themes/dg-theme-vibrant.css +16 -14
  133. package/umd/grid.all.umd.js +23 -24
  134. package/umd/grid.all.umd.js.map +1 -1
  135. package/umd/grid.umd.js +12 -11
  136. package/umd/grid.umd.js.map +1 -1
  137. package/umd/plugins/clipboard.umd.js +5 -7
  138. package/umd/plugins/clipboard.umd.js.map +1 -1
  139. package/umd/plugins/column-virtualization.umd.js +1 -1
  140. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  141. package/umd/plugins/context-menu.umd.js +1 -1
  142. package/umd/plugins/context-menu.umd.js.map +1 -1
  143. package/umd/plugins/editing.umd.js +1 -1
  144. package/umd/plugins/editing.umd.js.map +1 -1
  145. package/umd/plugins/export.umd.js +1 -1
  146. package/umd/plugins/export.umd.js.map +1 -1
  147. package/umd/plugins/filtering.umd.js +1 -1
  148. package/umd/plugins/filtering.umd.js.map +1 -1
  149. package/umd/plugins/grouping-columns.umd.js +1 -1
  150. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  151. package/umd/plugins/grouping-rows.umd.js +1 -1
  152. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  153. package/umd/plugins/master-detail.umd.js +1 -1
  154. package/umd/plugins/master-detail.umd.js.map +1 -1
  155. package/umd/plugins/multi-sort.umd.js +1 -1
  156. package/umd/plugins/multi-sort.umd.js.map +1 -1
  157. package/umd/plugins/pinned-columns.umd.js +1 -1
  158. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  159. package/umd/plugins/pinned-rows.umd.js +1 -1
  160. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  161. package/umd/plugins/pivot.umd.js +1 -1
  162. package/umd/plugins/pivot.umd.js.map +1 -1
  163. package/umd/plugins/reorder.umd.js +1 -1
  164. package/umd/plugins/reorder.umd.js.map +1 -1
  165. package/umd/plugins/selection.umd.js +1 -1
  166. package/umd/plugins/selection.umd.js.map +1 -1
  167. package/umd/plugins/server-side.umd.js +1 -1
  168. package/umd/plugins/server-side.umd.js.map +1 -1
  169. package/umd/plugins/tree.umd.js +1 -1
  170. package/umd/plugins/tree.umd.js.map +1 -1
  171. package/umd/plugins/undo-redo.umd.js +1 -1
  172. package/umd/plugins/undo-redo.umd.js.map +1 -1
  173. package/umd/plugins/visibility.umd.js +1 -1
  174. package/umd/plugins/visibility.umd.js.map +1 -1
  175. package/lib/core/internal/editing.d.ts +0 -76
  176. package/lib/core/internal/editing.d.ts.map +0 -1
@@ -1,12 +1,49 @@
1
- function w(s) {
1
+ function x(r, e, t, s) {
2
+ const n = new Set(r.selected);
3
+ let o = r.anchor;
4
+ if (t === "single")
5
+ n.clear(), n.add(e), o = e;
6
+ else if (t === "multiple") {
7
+ const i = s.ctrlKey || s.metaKey;
8
+ if (s.shiftKey && r.anchor !== null) {
9
+ const c = Math.min(r.anchor, e), a = Math.max(r.anchor, e);
10
+ for (let d = c; d <= a; d++)
11
+ n.add(d);
12
+ } else i ? (n.has(e) ? n.delete(e) : n.add(e), o = e) : (n.clear(), n.add(e), o = e);
13
+ }
14
+ return { selected: n, lastSelected: e, anchor: o };
15
+ }
16
+ function _(r) {
17
+ const e = /* @__PURE__ */ new Set();
18
+ for (let t = 0; t < r; t++)
19
+ e.add(t);
20
+ return e;
21
+ }
22
+ function D(r, e) {
23
+ const t = [], s = [];
24
+ for (const n of e)
25
+ r.has(n) || t.push(n);
26
+ for (const n of r)
27
+ e.has(n) || s.push(n);
28
+ return { added: t, removed: s };
29
+ }
30
+ function b(r) {
31
+ if (!r) return -1;
32
+ const e = r.getAttribute("data-row");
33
+ if (e) return parseInt(e, 10);
34
+ const t = r.closest(".data-grid-row");
35
+ if (!t) return -1;
36
+ const s = t.parentElement;
2
37
  if (!s) return -1;
3
- const e = s.getAttribute("data-row");
4
- return e ? parseInt(e, 10) : -1;
38
+ const n = s.querySelectorAll(":scope > .data-grid-row");
39
+ for (let o = 0; o < n.length; o++)
40
+ if (n[o] === t) return o;
41
+ return -1;
5
42
  }
6
- function d(s) {
7
- s && s.querySelectorAll(".cell-focus").forEach((e) => e.classList.remove("cell-focus"));
43
+ function w(r) {
44
+ r && r.querySelectorAll(".cell-focus").forEach((e) => e.classList.remove("cell-focus"));
8
45
  }
9
- const R = {
46
+ const p = {
10
47
  expand: "▶",
11
48
  collapse: "▼",
12
49
  sortAsc: "▲",
@@ -16,7 +53,7 @@ const R = {
16
53
  dragHandle: "⋮⋮",
17
54
  toolPanel: "☰"
18
55
  };
19
- class C {
56
+ class y {
20
57
  /**
21
58
  * Plugin dependencies - declare other plugins this one requires.
22
59
  *
@@ -33,8 +70,11 @@ class C {
33
70
  * ```
34
71
  */
35
72
  static dependencies;
36
- /** Plugin version - override in subclass if needed */
37
- version = "1.0.0";
73
+ /**
74
+ * Plugin version - defaults to grid version for built-in plugins.
75
+ * Third-party plugins can override with their own semver.
76
+ */
77
+ version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
38
78
  /** CSS styles to inject into the grid's shadow DOM */
39
79
  styles;
40
80
  /** Custom cell renderers keyed by type name */
@@ -121,12 +161,28 @@ class C {
121
161
  emit(e, t) {
122
162
  this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
123
163
  }
164
+ /**
165
+ * Emit a cancelable custom event from the grid.
166
+ * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
167
+ */
168
+ emitCancelable(e, t) {
169
+ const s = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
170
+ return this.grid?.dispatchEvent?.(s), s.defaultPrevented;
171
+ }
124
172
  /**
125
173
  * Request a re-render of the grid.
126
174
  */
127
175
  requestRender() {
128
176
  this.grid?.requestRender?.();
129
177
  }
178
+ /**
179
+ * Request a re-render and restore focus styling afterward.
180
+ * Use this when a plugin action (like expand/collapse) triggers a render
181
+ * but needs to maintain keyboard navigation focus.
182
+ */
183
+ requestRenderWithFocus() {
184
+ this.grid?.requestRenderWithFocus?.();
185
+ }
130
186
  /**
131
187
  * Request a lightweight style update without rebuilding DOM.
132
188
  * Use this instead of requestRender() when only CSS classes need updating.
@@ -161,10 +217,34 @@ class C {
161
217
  return this.grid?._visibleColumns ?? [];
162
218
  }
163
219
  /**
164
- * Get the shadow root of the grid.
220
+ * Get the grid as an HTMLElement for direct DOM operations.
221
+ * Use sparingly - prefer the typed GridElementRef API when possible.
222
+ *
223
+ * @example
224
+ * ```ts
225
+ * const width = this.gridElement.clientWidth;
226
+ * this.gridElement.classList.add('my-plugin-active');
227
+ * ```
228
+ */
229
+ get gridElement() {
230
+ return this.grid;
231
+ }
232
+ /**
233
+ * Get the render root of the grid for DOM queries.
234
+ * @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
235
+ *
236
+ * With Shadow DOM removed, the grid element itself is the render root.
237
+ * All new code should use `this.gridElement` for DOM queries.
238
+ *
239
+ * @example
240
+ * // OLD (deprecated)
241
+ * const rows = this.shadowRoot?.querySelector('.rows');
242
+ *
243
+ * // NEW (preferred)
244
+ * const rows = this.gridElement.querySelector('.rows');
165
245
  */
166
246
  get shadowRoot() {
167
- return this.grid?.shadowRoot ?? null;
247
+ return this.gridElement;
168
248
  }
169
249
  /**
170
250
  * Get the disconnect signal for event listener cleanup.
@@ -192,8 +272,53 @@ class C {
192
272
  */
193
273
  get gridIcons() {
194
274
  const e = this.grid?.gridConfig?.icons ?? {};
195
- return { ...R, ...e };
275
+ return { ...p, ...e };
276
+ }
277
+ // #region Animation Helpers
278
+ /**
279
+ * Check if animations are enabled at the grid level.
280
+ * Respects gridConfig.animation.mode and the CSS variable set by the grid.
281
+ *
282
+ * Plugins should use this to skip animations when:
283
+ * - Animation mode is 'off' or `false`
284
+ * - User prefers reduced motion and mode is 'reduced-motion' (default)
285
+ *
286
+ * @example
287
+ * ```ts
288
+ * private get animationStyle(): 'slide' | 'fade' | false {
289
+ * if (!this.isAnimationEnabled) return false;
290
+ * return this.config.animation ?? 'slide';
291
+ * }
292
+ * ```
293
+ */
294
+ get isAnimationEnabled() {
295
+ const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
296
+ if (e === !1 || e === "off") return !1;
297
+ if (e === !0 || e === "on") return !0;
298
+ const t = this.gridElement;
299
+ return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
196
300
  }
301
+ /**
302
+ * Get the animation duration in milliseconds from CSS variable.
303
+ * Falls back to 200ms if not set.
304
+ *
305
+ * Plugins can use this for their animation timing to stay consistent
306
+ * with the grid-level animation.duration setting.
307
+ *
308
+ * @example
309
+ * ```ts
310
+ * element.animate(keyframes, { duration: this.animationDuration });
311
+ * ```
312
+ */
313
+ get animationDuration() {
314
+ const e = this.gridElement;
315
+ if (e) {
316
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), s = parseInt(t, 10);
317
+ if (!isNaN(s)) return s;
318
+ }
319
+ return 200;
320
+ }
321
+ // #endregion
197
322
  /**
198
323
  * Resolve an icon value to string or HTMLElement.
199
324
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -223,58 +348,61 @@ class C {
223
348
  }
224
349
  // #endregion
225
350
  }
226
- function h(s) {
351
+ function h(r) {
352
+ return r.meta?.utility === !0;
353
+ }
354
+ function g(r) {
227
355
  return {
228
- startRow: Math.min(s.startRow, s.endRow),
229
- startCol: Math.min(s.startCol, s.endCol),
230
- endRow: Math.max(s.startRow, s.endRow),
231
- endCol: Math.max(s.startCol, s.endCol)
356
+ startRow: Math.min(r.startRow, r.endRow),
357
+ startCol: Math.min(r.startCol, r.endCol),
358
+ endRow: Math.max(r.startRow, r.endRow),
359
+ endCol: Math.max(r.startCol, r.endCol)
232
360
  };
233
361
  }
234
- function m(s) {
235
- const e = h(s);
362
+ function A(r) {
363
+ const e = g(r);
236
364
  return {
237
365
  from: { row: e.startRow, col: e.startCol },
238
366
  to: { row: e.endRow, col: e.endCol }
239
367
  };
240
368
  }
241
- function u(s) {
242
- return s.map(m);
369
+ function R(r) {
370
+ return r.map(A);
243
371
  }
244
- function b(s, e, t) {
245
- const r = h(t);
246
- return s >= r.startRow && s <= r.endRow && e >= r.startCol && e <= r.endCol;
372
+ function v(r, e, t) {
373
+ const s = g(t);
374
+ return r >= s.startRow && r <= s.endRow && e >= s.startCol && e <= s.endCol;
247
375
  }
248
- function f(s, e, t) {
249
- return t.some((r) => b(s, e, r));
376
+ function m(r, e, t) {
377
+ return t.some((s) => v(r, e, s));
250
378
  }
251
- function p(s) {
252
- const e = [], t = h(s);
253
- for (let r = t.startRow; r <= t.endRow; r++)
379
+ function S(r) {
380
+ const e = [], t = g(r);
381
+ for (let s = t.startRow; s <= t.endRow; s++)
254
382
  for (let n = t.startCol; n <= t.endCol; n++)
255
- e.push({ row: r, col: n });
383
+ e.push({ row: s, col: n });
256
384
  return e;
257
385
  }
258
- function A(s) {
386
+ function E(r) {
259
387
  const e = /* @__PURE__ */ new Map();
260
- for (const t of s)
261
- for (const r of p(t))
262
- e.set(`${r.row},${r.col}`, r);
388
+ for (const t of r)
389
+ for (const s of S(t))
390
+ e.set(`${s.row},${s.col}`, s);
263
391
  return [...e.values()];
264
392
  }
265
- function g(s, e) {
393
+ function u(r, e) {
266
394
  return {
267
- startRow: s.row,
268
- startCol: s.col,
395
+ startRow: r.row,
396
+ startCol: r.col,
269
397
  endRow: e.row,
270
398
  endCol: e.col
271
399
  };
272
400
  }
273
- const y = ':host .selecting .data-grid-row>.cell{-webkit-user-select:none;user-select:none}:host .data-grid-row.row-focus{background-color:var(--tbw-focus-background, rgba(from var(--tbw-color-accent) r g b / 12%))}:host([data-selection-mode="row"]) .cell-focus{outline:none}:host .data-grid-row>.cell.selected{background-color:var(--tbw-range-selection-bg)}:host .data-grid-row>.cell.selected.top{border-top:2px solid var(--tbw-range-border-color)}:host .data-grid-row>.cell.selected.bottom{border-bottom:2px solid var(--tbw-range-border-color)}:host .data-grid-row>.cell.selected.first{border-left:2px solid var(--tbw-range-border-color)}:host .data-grid-row>.cell.selected.last{border-right:2px solid var(--tbw-range-border-color)}:host .tbw-selection-summary{font-size:13px;color:var(--tbw-color-fg-muted);white-space:nowrap}';
274
- function v(s, e, t) {
275
- if (s === "cell" && e.selectedCell)
401
+ const I = "@layer tbw-plugins{tbw-grid.selecting .data-grid-row>.cell{-webkit-user-select:none;user-select:none}tbw-grid[data-has-focus] .data-grid-row.row-focus{background-color:var(--tbw-focus-background, rgba(from var(--tbw-color-accent) r g b / 12%))}tbw-grid[data-selection-mode=row] .cell-focus{outline:none}tbw-grid .data-grid-row>.cell.selected{background-color:var(--tbw-range-selection-bg)}tbw-grid .data-grid-row>.cell.selected.top{border-top:2px solid var(--tbw-range-border-color)}tbw-grid .data-grid-row>.cell.selected.bottom{border-bottom:2px solid var(--tbw-range-border-color)}tbw-grid .data-grid-row>.cell.selected.first{border-left:2px solid var(--tbw-range-border-color)}tbw-grid .data-grid-row>.cell.selected.last{border-right:2px solid var(--tbw-range-border-color)}tbw-grid .tbw-selection-summary{font-size:var(--tbw-font-size-sm, .8125rem);color:var(--tbw-color-fg-muted);white-space:nowrap}}";
402
+ function K(r, e, t) {
403
+ if (r === "cell" && e.selectedCell)
276
404
  return {
277
- mode: s,
405
+ mode: r,
278
406
  ranges: [
279
407
  {
280
408
  from: { row: e.selectedCell.row, col: e.selectedCell.col },
@@ -282,18 +410,18 @@ function v(s, e, t) {
282
410
  }
283
411
  ]
284
412
  };
285
- if (s === "row" && e.selected.size > 0) {
286
- const r = [...e.selected].map((n) => ({
413
+ if (r === "row" && e.selected.size > 0) {
414
+ const s = [...e.selected].map((n) => ({
287
415
  from: { row: n, col: 0 },
288
416
  to: { row: n, col: t - 1 }
289
417
  }));
290
- return { mode: s, ranges: r };
418
+ return { mode: r, ranges: s };
291
419
  }
292
- return s === "range" && e.ranges.length > 0 ? { mode: s, ranges: u(e.ranges) } : { mode: s, ranges: [] };
420
+ return r === "range" && e.ranges.length > 0 ? { mode: r, ranges: R(e.ranges) } : { mode: r, ranges: [] };
293
421
  }
294
- class q extends C {
422
+ class M extends y {
295
423
  name = "selection";
296
- version = "1.0.0";
424
+ styles = I;
297
425
  get defaultConfig() {
298
426
  return {
299
427
  mode: "cell"
@@ -321,32 +449,34 @@ class q extends C {
321
449
  // #endregion
322
450
  // #region Event Handlers
323
451
  onCellClick(e) {
324
- const { rowIndex: t, colIndex: r, originalEvent: n } = e, { mode: o } = this.config;
452
+ const { rowIndex: t, colIndex: s, originalEvent: n } = e, { mode: o } = this.config, i = this.columns[s], c = i && h(i);
325
453
  if (o === "cell")
326
- return this.selectedCell = { row: t, col: r }, this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
454
+ return c || (this.selectedCell = { row: t, col: s }, this.emit("selection-change", this.#e()), this.requestAfterRender()), !1;
327
455
  if (o === "row")
328
456
  return this.selected.clear(), this.selected.add(t), this.lastSelected = t, this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
329
457
  if (o === "range") {
330
- const c = n.shiftKey, l = n.ctrlKey || n.metaKey;
331
- if (c && this.cellAnchor) {
332
- const i = g(this.cellAnchor, { row: t, col: r });
333
- l ? this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = i : this.ranges.push(i) : this.ranges = [i], this.activeRange = i;
334
- } else if (l) {
335
- const i = {
458
+ if (c)
459
+ return !1;
460
+ const a = n.shiftKey, d = n.ctrlKey || n.metaKey;
461
+ if (a && this.cellAnchor) {
462
+ const l = u(this.cellAnchor, { row: t, col: s });
463
+ d ? this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = l : this.ranges.push(l) : this.ranges = [l], this.activeRange = l;
464
+ } else if (d) {
465
+ const l = {
336
466
  startRow: t,
337
- startCol: r,
467
+ startCol: s,
338
468
  endRow: t,
339
- endCol: r
469
+ endCol: s
340
470
  };
341
- this.ranges.push(i), this.activeRange = i, this.cellAnchor = { row: t, col: r };
471
+ this.ranges.push(l), this.activeRange = l, this.cellAnchor = { row: t, col: s };
342
472
  } else {
343
- const i = {
473
+ const l = {
344
474
  startRow: t,
345
- startCol: r,
475
+ startCol: s,
346
476
  endRow: t,
347
- endCol: r
477
+ endCol: s
348
478
  };
349
- this.ranges = [i], this.activeRange = i, this.cellAnchor = { row: t, col: r };
479
+ this.ranges = [l], this.activeRange = l, this.cellAnchor = { row: t, col: s };
350
480
  }
351
481
  return this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
352
482
  }
@@ -365,41 +495,49 @@ class q extends C {
365
495
  this.selected.clear(), this.selected.add(this.grid._focusRow), this.lastSelected = this.grid._focusRow, this.emit("selection-change", this.#e()), this.requestAfterRender();
366
496
  }), !1;
367
497
  if (t === "range" && n) {
368
- const o = e.key === "Tab", c = e.shiftKey && !o;
369
- return c && !this.cellAnchor && (this.cellAnchor = { row: this.grid._focusRow, col: this.grid._focusCol }), this.pendingKeyboardUpdate = { shiftKey: c }, queueMicrotask(() => this.requestAfterRender()), !1;
498
+ const o = e.key === "Tab", i = e.shiftKey && !o;
499
+ return i && !this.cellAnchor && (this.cellAnchor = { row: this.grid._focusRow, col: this.grid._focusCol }), this.pendingKeyboardUpdate = { shiftKey: i }, queueMicrotask(() => this.requestAfterRender()), !1;
370
500
  }
371
501
  if (t === "range" && e.key === "a" && (e.ctrlKey || e.metaKey)) {
372
- const o = this.rows.length, c = this.columns.length;
373
- if (o > 0 && c > 0) {
374
- const l = {
502
+ const o = this.rows.length, i = this.columns.length;
503
+ if (o > 0 && i > 0) {
504
+ const c = {
375
505
  startRow: 0,
376
506
  startCol: 0,
377
507
  endRow: o - 1,
378
- endCol: c - 1
508
+ endCol: i - 1
379
509
  };
380
- return this.ranges = [l], this.activeRange = l, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
510
+ return this.ranges = [c], this.activeRange = c, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
381
511
  }
382
512
  }
383
513
  return !1;
384
514
  }
385
515
  onCellMouseDown(e) {
386
- if (this.config.mode !== "range" || e.rowIndex === void 0 || e.colIndex === void 0 || e.rowIndex < 0 || e.originalEvent.shiftKey && this.cellAnchor)
516
+ if (this.config.mode !== "range" || e.rowIndex === void 0 || e.colIndex === void 0 || e.rowIndex < 0) return;
517
+ const t = this.columns[e.colIndex];
518
+ if (t && h(t) || e.originalEvent.shiftKey && this.cellAnchor)
387
519
  return;
388
520
  this.isDragging = !0;
389
- const t = e.rowIndex, r = e.colIndex;
390
- this.cellAnchor = { row: t, col: r }, e.originalEvent.ctrlKey || e.originalEvent.metaKey || (this.ranges = []);
391
- const o = {
392
- startRow: t,
393
- startCol: r,
394
- endRow: t,
395
- endCol: r
521
+ const s = e.rowIndex, n = e.colIndex;
522
+ this.cellAnchor = { row: s, col: n }, e.originalEvent.ctrlKey || e.originalEvent.metaKey || (this.ranges = []);
523
+ const i = {
524
+ startRow: s,
525
+ startCol: n,
526
+ endRow: s,
527
+ endCol: n
396
528
  };
397
- return this.ranges.push(o), this.activeRange = o, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
529
+ return this.ranges.push(i), this.activeRange = i, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
398
530
  }
399
531
  onCellMouseMove(e) {
400
532
  if (this.config.mode !== "range" || !this.isDragging || !this.cellAnchor || e.rowIndex === void 0 || e.colIndex === void 0 || e.rowIndex < 0) return;
401
- const t = g(this.cellAnchor, { row: e.rowIndex, col: e.colIndex });
402
- return this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = t : this.ranges.push(t), this.activeRange = t, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
533
+ let t = e.colIndex;
534
+ const s = this.columns[t];
535
+ if (s && h(s)) {
536
+ const o = this.columns.findIndex((i) => !h(i));
537
+ o >= 0 && (t = o);
538
+ }
539
+ const n = u(this.cellAnchor, { row: e.rowIndex, col: t });
540
+ return this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] = n : this.ranges.push(n), this.activeRange = n, this.emit("selection-change", this.#e()), this.requestAfterRender(), !0;
403
541
  }
404
542
  onCellMouseUp(e) {
405
543
  if (this.config.mode === "range" && this.isDragging)
@@ -410,7 +548,7 @@ class q extends C {
410
548
  * Shared by afterRender and onScrollRender.
411
549
  */
412
550
  #t() {
413
- const e = this.shadowRoot;
551
+ const e = this.gridElement;
414
552
  if (!e) return;
415
553
  const { mode: t } = this.config;
416
554
  e.querySelectorAll(".cell").forEach((o) => {
@@ -419,34 +557,42 @@ class q extends C {
419
557
  const n = e.querySelectorAll(".data-grid-row");
420
558
  if (n.forEach((o) => {
421
559
  o.classList.remove("selected", "row-focus");
422
- }), t === "row" && (d(e), n.forEach((o) => {
423
- const c = o.querySelector(".cell[data-row]"), l = w(c);
424
- l >= 0 && this.selected.has(l) && o.classList.add("selected", "row-focus");
560
+ }), t === "row" && (w(e), n.forEach((o) => {
561
+ const i = o.querySelector(".cell[data-row]"), c = b(i);
562
+ c >= 0 && this.selected.has(c) && o.classList.add("selected", "row-focus");
425
563
  })), t === "range" && this.ranges.length > 0) {
426
- d(e);
427
- const o = this.activeRange ? h(this.activeRange) : null;
428
- e.querySelectorAll(".cell[data-row][data-col]").forEach((l) => {
429
- const i = parseInt(l.getAttribute("data-row") ?? "-1", 10), a = parseInt(l.getAttribute("data-col") ?? "-1", 10);
430
- i >= 0 && a >= 0 && f(i, a, this.ranges) && (l.classList.add("selected"), o && (i === o.startRow && l.classList.add("top"), i === o.endRow && l.classList.add("bottom"), a === o.startCol && l.classList.add("first"), a === o.endCol && l.classList.add("last")));
564
+ w(e);
565
+ const o = this.activeRange ? g(this.activeRange) : null, i = this.columns.findIndex((a) => !h(a));
566
+ this.columns.length - 1, e.querySelectorAll(".cell[data-row][data-col]").forEach((a) => {
567
+ const d = parseInt(a.getAttribute("data-row") ?? "-1", 10), l = parseInt(a.getAttribute("data-col") ?? "-1", 10);
568
+ if (d >= 0 && l >= 0) {
569
+ const f = this.columns[l];
570
+ if (f && h(f))
571
+ return;
572
+ if (m(d, l, this.ranges) && (a.classList.add("selected"), o)) {
573
+ d === o.startRow && a.classList.add("top"), d === o.endRow && a.classList.add("bottom");
574
+ const C = Math.max(o.startCol, i);
575
+ l === C && a.classList.add("first"), l === o.endCol && a.classList.add("last");
576
+ }
577
+ }
431
578
  });
432
579
  }
433
- t === "cell" && this.selectedCell && d(e);
434
580
  }
435
581
  afterRender() {
436
- const e = this.shadowRoot;
582
+ const e = this.gridElement;
437
583
  if (!e) return;
438
- const t = e.children[0], { mode: r } = this.config;
439
- if (this.pendingKeyboardUpdate && r === "range") {
584
+ const t = e.children[0], { mode: s } = this.config;
585
+ if (this.pendingKeyboardUpdate && s === "range") {
440
586
  const { shiftKey: n } = this.pendingKeyboardUpdate;
441
587
  this.pendingKeyboardUpdate = null;
442
- const o = this.grid._focusRow, c = this.grid._focusCol;
588
+ const o = this.grid._focusRow, i = this.grid._focusCol;
443
589
  if (n && this.cellAnchor) {
444
- const l = g(this.cellAnchor, { row: o, col: c });
445
- this.ranges = [l], this.activeRange = l;
446
- } else n || (this.ranges = [], this.activeRange = null, this.cellAnchor = { row: o, col: c });
590
+ const c = u(this.cellAnchor, { row: o, col: i });
591
+ this.ranges = [c], this.activeRange = c;
592
+ } else n || (this.ranges = [], this.activeRange = null, this.cellAnchor = { row: o, col: i });
447
593
  this.emit("selection-change", this.#e());
448
594
  }
449
- this.grid.setAttribute("data-selection-mode", r), t && t.classList.toggle("selecting", this.isDragging), this.#t();
595
+ this.grid.setAttribute("data-selection-mode", s), t && t.classList.toggle("selecting", this.isDragging), this.#t();
450
596
  }
451
597
  /**
452
598
  * Called after scroll-triggered row rendering.
@@ -457,35 +603,62 @@ class q extends C {
457
603
  }
458
604
  // #endregion
459
605
  // #region Public API
606
+ /**
607
+ * Get the current selection as a unified result.
608
+ * Works for all selection modes and always returns ranges.
609
+ *
610
+ * @example
611
+ * ```ts
612
+ * const selection = plugin.getSelection();
613
+ * if (selection.ranges.length > 0) {
614
+ * const { from, to } = selection.ranges[0];
615
+ * // For cell mode: from === to (single cell)
616
+ * // For row mode: from.col = 0, to.col = lastCol (full row)
617
+ * // For range mode: rectangular selection
618
+ * }
619
+ * ```
620
+ */
621
+ getSelection() {
622
+ return {
623
+ mode: this.config.mode,
624
+ ranges: this.#e().ranges,
625
+ anchor: this.cellAnchor
626
+ };
627
+ }
460
628
  /**
461
629
  * Get the selected cell (cell mode only).
630
+ * @deprecated Use `getSelection()` instead for a unified API across all modes.
462
631
  */
463
632
  getSelectedCell() {
464
- return this.selectedCell;
633
+ const { mode: e, ranges: t } = this.getSelection();
634
+ return e === "cell" && t.length > 0 ? t[0].from : null;
465
635
  }
466
636
  /**
467
637
  * Get all selected row indices (row mode).
638
+ * @deprecated Use `getSelection().ranges` instead - each range represents a full row.
468
639
  */
469
640
  getSelectedRows() {
470
- return [...this.selected];
641
+ const { mode: e, ranges: t } = this.getSelection();
642
+ return e === "row" ? t.map((s) => s.from.row) : [];
471
643
  }
472
644
  /**
473
645
  * Get all selected cell ranges in public format.
646
+ * @deprecated Use `getSelection().ranges` instead.
474
647
  */
475
648
  getRanges() {
476
- return u(this.ranges);
649
+ return this.getSelection().ranges;
477
650
  }
478
651
  /**
479
652
  * Get all selected cells across all ranges.
480
653
  */
481
654
  getSelectedCells() {
482
- return A(this.ranges);
655
+ return E(this.ranges);
483
656
  }
484
657
  /**
485
658
  * Check if a specific cell is in range selection.
486
659
  */
487
660
  isCellSelected(e, t) {
488
- return f(e, t, this.ranges);
661
+ return m(e, t, this.ranges);
489
662
  }
490
663
  /**
491
664
  * Clear all selection.
@@ -504,13 +677,13 @@ class q extends C {
504
677
  endCol: t.to.col
505
678
  })), this.activeRange = this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] : null, this.emit("selection-change", {
506
679
  mode: this.config.mode,
507
- ranges: u(this.ranges)
680
+ ranges: R(this.ranges)
508
681
  }), this.requestAfterRender();
509
682
  }
510
683
  // #endregion
511
684
  // #region Private Helpers
512
685
  #e() {
513
- return v(
686
+ return K(
514
687
  this.config.mode,
515
688
  {
516
689
  selectedCell: this.selectedCell,
@@ -521,43 +694,11 @@ class q extends C {
521
694
  );
522
695
  }
523
696
  // #endregion
524
- // #region Styles
525
- styles = y;
526
- // #endregion
527
- }
528
- function S(s, e, t, r) {
529
- const n = new Set(s.selected);
530
- let o = s.anchor;
531
- if (t === "single")
532
- n.clear(), n.add(e), o = e;
533
- else if (t === "multiple") {
534
- const c = r.ctrlKey || r.metaKey;
535
- if (r.shiftKey && s.anchor !== null) {
536
- const l = Math.min(s.anchor, e), i = Math.max(s.anchor, e);
537
- for (let a = l; a <= i; a++)
538
- n.add(a);
539
- } else c ? (n.has(e) ? n.delete(e) : n.add(e), o = e) : (n.clear(), n.add(e), o = e);
540
- }
541
- return { selected: n, lastSelected: e, anchor: o };
542
- }
543
- function x(s) {
544
- const e = /* @__PURE__ */ new Set();
545
- for (let t = 0; t < s; t++)
546
- e.add(t);
547
- return e;
548
- }
549
- function I(s, e) {
550
- const t = [], r = [];
551
- for (const n of e)
552
- s.has(n) || t.push(n);
553
- for (const n of s)
554
- e.has(n) || r.push(n);
555
- return { added: t, removed: r };
556
697
  }
557
698
  export {
558
- q as SelectionPlugin,
559
- I as computeSelectionDiff,
560
- S as handleRowClick,
561
- x as selectAll
699
+ M as SelectionPlugin,
700
+ D as computeSelectionDiff,
701
+ x as handleRowClick,
702
+ _ as selectAll
562
703
  };
563
704
  //# sourceMappingURL=index.js.map