@toolbox-web/grid 0.4.0 → 0.4.2

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