@toolbox-web/grid 0.4.1 → 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 (157) hide show
  1. package/README.md +10 -13
  2. package/all.js +1101 -1048
  3. package/all.js.map +1 -1
  4. package/index.js +245 -137
  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/plugin/base-plugin.d.ts +57 -1
  14. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  15. package/lib/core/plugin/expander-column.d.ts +51 -0
  16. package/lib/core/plugin/expander-column.d.ts.map +1 -0
  17. package/lib/core/plugin/types.d.ts +117 -1
  18. package/lib/core/plugin/types.d.ts.map +1 -1
  19. package/lib/core/types.d.ts +4 -2
  20. package/lib/core/types.d.ts.map +1 -1
  21. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
  22. package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
  23. package/lib/plugins/clipboard/index.d.ts +1 -1
  24. package/lib/plugins/clipboard/index.d.ts.map +1 -1
  25. package/lib/plugins/clipboard/index.js +282 -188
  26. package/lib/plugins/clipboard/index.js.map +1 -1
  27. package/lib/plugins/clipboard/types.d.ts +72 -2
  28. package/lib/plugins/clipboard/types.d.ts.map +1 -1
  29. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
  30. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
  31. package/lib/plugins/column-virtualization/index.js +102 -26
  32. package/lib/plugins/column-virtualization/index.js.map +1 -1
  33. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
  34. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  35. package/lib/plugins/context-menu/index.js +154 -78
  36. package/lib/plugins/context-menu/index.js.map +1 -1
  37. package/lib/plugins/editing/EditingPlugin.d.ts +1 -7
  38. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  39. package/lib/plugins/editing/index.js +200 -136
  40. package/lib/plugins/editing/index.js.map +1 -1
  41. package/lib/plugins/export/ExportPlugin.d.ts +0 -1
  42. package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
  43. package/lib/plugins/export/index.js +175 -99
  44. package/lib/plugins/export/index.js.map +1 -1
  45. package/lib/plugins/filtering/FilteringPlugin.d.ts +5 -2
  46. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  47. package/lib/plugins/filtering/index.js +129 -43
  48. package/lib/plugins/filtering/index.js.map +1 -1
  49. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +1 -2
  50. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  51. package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
  52. package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
  53. package/lib/plugins/grouping-columns/index.js +144 -66
  54. package/lib/plugins/grouping-columns/index.js.map +1 -1
  55. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
  56. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
  57. package/lib/plugins/grouping-rows/index.js +230 -138
  58. package/lib/plugins/grouping-rows/index.js.map +1 -1
  59. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
  60. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
  61. package/lib/plugins/master-detail/index.js +265 -196
  62. package/lib/plugins/master-detail/index.js.map +1 -1
  63. package/lib/plugins/master-detail/types.d.ts +0 -10
  64. package/lib/plugins/master-detail/types.d.ts.map +1 -1
  65. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
  66. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
  67. package/lib/plugins/multi-sort/index.js +105 -31
  68. package/lib/plugins/multi-sort/index.js.map +1 -1
  69. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
  70. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  71. package/lib/plugins/pinned-columns/index.js +128 -52
  72. package/lib/plugins/pinned-columns/index.js.map +1 -1
  73. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
  74. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
  75. package/lib/plugins/pinned-rows/index.js +162 -88
  76. package/lib/plugins/pinned-rows/index.js.map +1 -1
  77. package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
  78. package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
  79. package/lib/plugins/pivot/index.js +398 -310
  80. package/lib/plugins/pivot/index.js.map +1 -1
  81. package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
  82. package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
  83. package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
  84. package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
  85. package/lib/plugins/reorder/index.js +288 -226
  86. package/lib/plugins/reorder/index.js.map +1 -1
  87. package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
  88. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  89. package/lib/plugins/selection/index.d.ts +2 -2
  90. package/lib/plugins/selection/index.d.ts.map +1 -1
  91. package/lib/plugins/selection/index.js +276 -145
  92. package/lib/plugins/selection/index.js.map +1 -1
  93. package/lib/plugins/selection/types.d.ts +24 -0
  94. package/lib/plugins/selection/types.d.ts.map +1 -1
  95. package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
  96. package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
  97. package/lib/plugins/server-side/index.js +83 -7
  98. package/lib/plugins/server-side/index.js.map +1 -1
  99. package/lib/plugins/tree/TreePlugin.d.ts +5 -1
  100. package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
  101. package/lib/plugins/tree/index.js +197 -112
  102. package/lib/plugins/tree/index.js.map +1 -1
  103. package/lib/plugins/tree/types.d.ts +0 -10
  104. package/lib/plugins/tree/types.d.ts.map +1 -1
  105. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
  106. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
  107. package/lib/plugins/undo-redo/index.js +93 -17
  108. package/lib/plugins/undo-redo/index.js.map +1 -1
  109. package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
  110. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  111. package/lib/plugins/visibility/index.js +144 -65
  112. package/lib/plugins/visibility/index.js.map +1 -1
  113. package/package.json +1 -1
  114. package/umd/grid.all.umd.js +17 -19
  115. package/umd/grid.all.umd.js.map +1 -1
  116. package/umd/grid.umd.js +7 -7
  117. package/umd/grid.umd.js.map +1 -1
  118. package/umd/plugins/clipboard.umd.js +5 -7
  119. package/umd/plugins/clipboard.umd.js.map +1 -1
  120. package/umd/plugins/column-virtualization.umd.js +1 -1
  121. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  122. package/umd/plugins/context-menu.umd.js +1 -1
  123. package/umd/plugins/context-menu.umd.js.map +1 -1
  124. package/umd/plugins/editing.umd.js +1 -1
  125. package/umd/plugins/editing.umd.js.map +1 -1
  126. package/umd/plugins/export.umd.js +1 -1
  127. package/umd/plugins/export.umd.js.map +1 -1
  128. package/umd/plugins/filtering.umd.js +1 -1
  129. package/umd/plugins/filtering.umd.js.map +1 -1
  130. package/umd/plugins/grouping-columns.umd.js +1 -1
  131. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  132. package/umd/plugins/grouping-rows.umd.js +1 -1
  133. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  134. package/umd/plugins/master-detail.umd.js +1 -1
  135. package/umd/plugins/master-detail.umd.js.map +1 -1
  136. package/umd/plugins/multi-sort.umd.js +1 -1
  137. package/umd/plugins/multi-sort.umd.js.map +1 -1
  138. package/umd/plugins/pinned-columns.umd.js +1 -1
  139. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  140. package/umd/plugins/pinned-rows.umd.js +1 -1
  141. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  142. package/umd/plugins/pivot.umd.js +1 -1
  143. package/umd/plugins/pivot.umd.js.map +1 -1
  144. package/umd/plugins/reorder.umd.js +1 -1
  145. package/umd/plugins/reorder.umd.js.map +1 -1
  146. package/umd/plugins/selection.umd.js +1 -1
  147. package/umd/plugins/selection.umd.js.map +1 -1
  148. package/umd/plugins/server-side.umd.js +1 -1
  149. package/umd/plugins/server-side.umd.js.map +1 -1
  150. package/umd/plugins/tree.umd.js +1 -1
  151. package/umd/plugins/tree.umd.js.map +1 -1
  152. package/umd/plugins/undo-redo.umd.js +1 -1
  153. package/umd/plugins/undo-redo.umd.js.map +1 -1
  154. package/umd/plugins/visibility.umd.js +1 -1
  155. package/umd/plugins/visibility.umd.js.map +1 -1
  156. package/lib/core/internal/editing.d.ts +0 -76
  157. package/lib/core/internal/editing.d.ts.map +0 -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,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.
@@ -160,6 +216,19 @@ class C {
160
216
  get visibleColumns() {
161
217
  return this.grid?._visibleColumns ?? [];
162
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
+ }
163
232
  /**
164
233
  * Get the shadow root of the grid.
165
234
  */
@@ -192,8 +261,53 @@ class C {
192
261
  */
193
262
  get gridIcons() {
194
263
  const e = this.grid?.gridConfig?.icons ?? {};
195
- 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;
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;
196
309
  }
310
+ // #endregion
197
311
  /**
198
312
  * Resolve an icon value to string or HTMLElement.
199
313
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -223,58 +337,61 @@ class C {
223
337
  }
224
338
  // #endregion
225
339
  }
226
- function h(s) {
340
+ function d(n) {
341
+ return n.meta?.utility === !0;
342
+ }
343
+ function u(n) {
227
344
  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)
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)
232
349
  };
233
350
  }
234
- function m(s) {
235
- const e = h(s);
351
+ function A(n) {
352
+ const e = u(n);
236
353
  return {
237
354
  from: { row: e.startRow, col: e.startCol },
238
355
  to: { row: e.endRow, col: e.endCol }
239
356
  };
240
357
  }
241
- function u(s) {
242
- return s.map(m);
358
+ function m(n) {
359
+ return n.map(A);
243
360
  }
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;
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;
247
364
  }
248
- function f(s, e, t) {
249
- return t.some((r) => b(s, e, r));
365
+ function R(n, e, t) {
366
+ return t.some((s) => v(n, e, s));
250
367
  }
251
- function p(s) {
252
- const e = [], t = h(s);
253
- for (let r = t.startRow; r <= t.endRow; r++)
254
- for (let n = t.startCol; n <= t.endCol; n++)
255
- 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 });
256
373
  return e;
257
374
  }
258
- function A(s) {
375
+ function I(n) {
259
376
  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);
377
+ for (const t of n)
378
+ for (const s of S(t))
379
+ e.set(`${s.row},${s.col}`, s);
263
380
  return [...e.values()];
264
381
  }
265
- function g(s, e) {
382
+ function f(n, e) {
266
383
  return {
267
- startRow: s.row,
268
- startCol: s.col,
384
+ startRow: n.row,
385
+ startCol: n.col,
269
386
  endRow: e.row,
270
387
  endCol: e.col
271
388
  };
272
389
  }
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)
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)
276
393
  return {
277
- mode: s,
394
+ mode: n,
278
395
  ranges: [
279
396
  {
280
397
  from: { row: e.selectedCell.row, col: e.selectedCell.col },
@@ -282,18 +399,18 @@ function v(s, e, t) {
282
399
  }
283
400
  ]
284
401
  };
285
- if (s === "row" && e.selected.size > 0) {
286
- const r = [...e.selected].map((n) => ({
287
- from: { row: n, col: 0 },
288
- 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 }
289
406
  }));
290
- return { mode: s, ranges: r };
407
+ return { mode: n, ranges: s };
291
408
  }
292
- 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: [] };
293
410
  }
294
- class q extends C {
411
+ class M extends y {
295
412
  name = "selection";
296
- version = "1.0.0";
413
+ styles = K;
297
414
  get defaultConfig() {
298
415
  return {
299
416
  mode: "cell"
@@ -321,42 +438,44 @@ class q extends C {
321
438
  // #endregion
322
439
  // #region Event Handlers
323
440
  onCellClick(e) {
324
- 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);
325
442
  if (o === "cell")
326
- 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;
327
444
  if (o === "row")
328
445
  return this.selected.clear(), this.selected.add(t), this.lastSelected = t, this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
329
446
  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 = {
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 = {
336
455
  startRow: t,
337
- startCol: r,
456
+ startCol: s,
338
457
  endRow: t,
339
- endCol: r
458
+ endCol: s
340
459
  };
341
- 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 };
342
461
  } else {
343
- const i = {
462
+ const l = {
344
463
  startRow: t,
345
- startCol: r,
464
+ startCol: s,
346
465
  endRow: t,
347
- endCol: r
466
+ endCol: s
348
467
  };
349
- 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 };
350
469
  }
351
470
  return this.emit("selection-change", this.#e()), this.requestAfterRender(), !1;
352
471
  }
353
472
  return !1;
354
473
  }
355
474
  onKeyDown(e) {
356
- 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);
357
476
  if (e.key === "Escape")
358
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;
359
- if (t === "cell" && n)
478
+ if (t === "cell" && r)
360
479
  return queueMicrotask(() => {
361
480
  this.selectedCell = { row: this.grid._focusRow, col: this.grid._focusCol }, this.emit("selection-change", this.#e()), this.requestAfterRender();
362
481
  }), !1;
@@ -364,42 +483,50 @@ class q extends C {
364
483
  return queueMicrotask(() => {
365
484
  this.selected.clear(), this.selected.add(this.grid._focusRow), this.lastSelected = this.grid._focusRow, this.emit("selection-change", this.#e()), this.requestAfterRender();
366
485
  }), !1;
367
- 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;
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;
370
489
  }
371
490
  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 = {
491
+ const o = this.rows.length, i = this.columns.length;
492
+ if (o > 0 && i > 0) {
493
+ const c = {
375
494
  startRow: 0,
376
495
  startCol: 0,
377
496
  endRow: o - 1,
378
- endCol: c - 1
497
+ endCol: i - 1
379
498
  };
380
- 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;
381
500
  }
382
501
  }
383
502
  return !1;
384
503
  }
385
504
  onCellMouseDown(e) {
386
- 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)
387
508
  return;
388
509
  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,
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,
393
514
  startCol: r,
394
- endRow: t,
515
+ endRow: s,
395
516
  endCol: r
396
517
  };
397
- 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;
398
519
  }
399
520
  onCellMouseMove(e) {
400
521
  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;
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;
403
530
  }
404
531
  onCellMouseUp(e) {
405
532
  if (this.config.mode === "range" && this.isDragging)
@@ -416,37 +543,46 @@ class q extends C {
416
543
  e.querySelectorAll(".cell").forEach((o) => {
417
544
  o.classList.remove("selected", "top", "bottom", "first", "last");
418
545
  });
419
- const n = e.querySelectorAll(".data-grid-row");
420
- if (n.forEach((o) => {
546
+ const r = e.querySelectorAll(".data-grid-row");
547
+ if (r.forEach((o) => {
421
548
  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");
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");
425
552
  })), 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")));
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
+ }
431
567
  });
432
568
  }
433
- t === "cell" && this.selectedCell && d(e);
569
+ t === "cell" && this.selectedCell && g(e);
434
570
  }
435
571
  afterRender() {
436
572
  const e = this.shadowRoot;
437
573
  if (!e) return;
438
- const t = e.children[0], { mode: r } = this.config;
439
- if (this.pendingKeyboardUpdate && r === "range") {
440
- 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;
441
577
  this.pendingKeyboardUpdate = null;
442
- const o = this.grid._focusRow, c = this.grid._focusCol;
443
- 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 });
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 });
447
583
  this.emit("selection-change", this.#e());
448
584
  }
449
- 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();
450
586
  }
451
587
  /**
452
588
  * Called after scroll-triggered row rendering.
@@ -457,35 +593,62 @@ class q extends C {
457
593
  }
458
594
  // #endregion
459
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
+ }
460
618
  /**
461
619
  * Get the selected cell (cell mode only).
620
+ * @deprecated Use `getSelection()` instead for a unified API across all modes.
462
621
  */
463
622
  getSelectedCell() {
464
- return this.selectedCell;
623
+ const { mode: e, ranges: t } = this.getSelection();
624
+ return e === "cell" && t.length > 0 ? t[0].from : null;
465
625
  }
466
626
  /**
467
627
  * Get all selected row indices (row mode).
628
+ * @deprecated Use `getSelection().ranges` instead - each range represents a full row.
468
629
  */
469
630
  getSelectedRows() {
470
- return [...this.selected];
631
+ const { mode: e, ranges: t } = this.getSelection();
632
+ return e === "row" ? t.map((s) => s.from.row) : [];
471
633
  }
472
634
  /**
473
635
  * Get all selected cell ranges in public format.
636
+ * @deprecated Use `getSelection().ranges` instead.
474
637
  */
475
638
  getRanges() {
476
- return u(this.ranges);
639
+ return this.getSelection().ranges;
477
640
  }
478
641
  /**
479
642
  * Get all selected cells across all ranges.
480
643
  */
481
644
  getSelectedCells() {
482
- return A(this.ranges);
645
+ return I(this.ranges);
483
646
  }
484
647
  /**
485
648
  * Check if a specific cell is in range selection.
486
649
  */
487
650
  isCellSelected(e, t) {
488
- return f(e, t, this.ranges);
651
+ return R(e, t, this.ranges);
489
652
  }
490
653
  /**
491
654
  * Clear all selection.
@@ -504,13 +667,13 @@ class q extends C {
504
667
  endCol: t.to.col
505
668
  })), this.activeRange = this.ranges.length > 0 ? this.ranges[this.ranges.length - 1] : null, this.emit("selection-change", {
506
669
  mode: this.config.mode,
507
- ranges: u(this.ranges)
670
+ ranges: m(this.ranges)
508
671
  }), this.requestAfterRender();
509
672
  }
510
673
  // #endregion
511
674
  // #region Private Helpers
512
675
  #e() {
513
- return v(
676
+ return q(
514
677
  this.config.mode,
515
678
  {
516
679
  selectedCell: this.selectedCell,
@@ -521,43 +684,11 @@ class q extends C {
521
684
  );
522
685
  }
523
686
  // #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
687
  }
557
688
  export {
558
- q as SelectionPlugin,
559
- I as computeSelectionDiff,
560
- S as handleRowClick,
561
- x as selectAll
689
+ M as SelectionPlugin,
690
+ D as computeSelectionDiff,
691
+ x as handleRowClick,
692
+ _ as selectAll
562
693
  };
563
694
  //# sourceMappingURL=index.js.map