@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
@@ -8,7 +8,7 @@ const S = {
8
8
  dragHandle: "⋮⋮",
9
9
  toolPanel: "☰"
10
10
  };
11
- class R {
11
+ class _ {
12
12
  /**
13
13
  * Plugin dependencies - declare other plugins this one requires.
14
14
  *
@@ -25,8 +25,11 @@ class R {
25
25
  * ```
26
26
  */
27
27
  static dependencies;
28
- /** Plugin version - override in subclass if needed */
29
- version = "1.0.0";
28
+ /**
29
+ * Plugin version - defaults to grid version for built-in plugins.
30
+ * Third-party plugins can override with their own semver.
31
+ */
32
+ version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
30
33
  /** CSS styles to inject into the grid's shadow DOM */
31
34
  styles;
32
35
  /** Custom cell renderers keyed by type name */
@@ -113,12 +116,28 @@ class R {
113
116
  emit(e, t) {
114
117
  this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
115
118
  }
119
+ /**
120
+ * Emit a cancelable custom event from the grid.
121
+ * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
122
+ */
123
+ emitCancelable(e, t) {
124
+ const n = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
125
+ return this.grid?.dispatchEvent?.(n), n.defaultPrevented;
126
+ }
116
127
  /**
117
128
  * Request a re-render of the grid.
118
129
  */
119
130
  requestRender() {
120
131
  this.grid?.requestRender?.();
121
132
  }
133
+ /**
134
+ * Request a re-render and restore focus styling afterward.
135
+ * Use this when a plugin action (like expand/collapse) triggers a render
136
+ * but needs to maintain keyboard navigation focus.
137
+ */
138
+ requestRenderWithFocus() {
139
+ this.grid?.requestRenderWithFocus?.();
140
+ }
122
141
  /**
123
142
  * Request a lightweight style update without rebuilding DOM.
124
143
  * Use this instead of requestRender() when only CSS classes need updating.
@@ -153,10 +172,34 @@ class R {
153
172
  return this.grid?._visibleColumns ?? [];
154
173
  }
155
174
  /**
156
- * Get the shadow root of the grid.
175
+ * Get the grid as an HTMLElement for direct DOM operations.
176
+ * Use sparingly - prefer the typed GridElementRef API when possible.
177
+ *
178
+ * @example
179
+ * ```ts
180
+ * const width = this.gridElement.clientWidth;
181
+ * this.gridElement.classList.add('my-plugin-active');
182
+ * ```
183
+ */
184
+ get gridElement() {
185
+ return this.grid;
186
+ }
187
+ /**
188
+ * Get the render root of the grid for DOM queries.
189
+ * @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
190
+ *
191
+ * With Shadow DOM removed, the grid element itself is the render root.
192
+ * All new code should use `this.gridElement` for DOM queries.
193
+ *
194
+ * @example
195
+ * // OLD (deprecated)
196
+ * const rows = this.shadowRoot?.querySelector('.rows');
197
+ *
198
+ * // NEW (preferred)
199
+ * const rows = this.gridElement.querySelector('.rows');
157
200
  */
158
201
  get shadowRoot() {
159
- return this.grid?.shadowRoot ?? null;
202
+ return this.gridElement;
160
203
  }
161
204
  /**
162
205
  * Get the disconnect signal for event listener cleanup.
@@ -186,6 +229,51 @@ class R {
186
229
  const e = this.grid?.gridConfig?.icons ?? {};
187
230
  return { ...S, ...e };
188
231
  }
232
+ // #region Animation Helpers
233
+ /**
234
+ * Check if animations are enabled at the grid level.
235
+ * Respects gridConfig.animation.mode and the CSS variable set by the grid.
236
+ *
237
+ * Plugins should use this to skip animations when:
238
+ * - Animation mode is 'off' or `false`
239
+ * - User prefers reduced motion and mode is 'reduced-motion' (default)
240
+ *
241
+ * @example
242
+ * ```ts
243
+ * private get animationStyle(): 'slide' | 'fade' | false {
244
+ * if (!this.isAnimationEnabled) return false;
245
+ * return this.config.animation ?? 'slide';
246
+ * }
247
+ * ```
248
+ */
249
+ get isAnimationEnabled() {
250
+ const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
251
+ if (e === !1 || e === "off") return !1;
252
+ if (e === !0 || e === "on") return !0;
253
+ const t = this.gridElement;
254
+ return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
255
+ }
256
+ /**
257
+ * Get the animation duration in milliseconds from CSS variable.
258
+ * Falls back to 200ms if not set.
259
+ *
260
+ * Plugins can use this for their animation timing to stay consistent
261
+ * with the grid-level animation.duration setting.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * element.animate(keyframes, { duration: this.animationDuration });
266
+ * ```
267
+ */
268
+ get animationDuration() {
269
+ const e = this.gridElement;
270
+ if (e) {
271
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(t, 10);
272
+ if (!isNaN(n)) return n;
273
+ }
274
+ return 200;
275
+ }
276
+ // #endregion
189
277
  /**
190
278
  * Resolve an icon value to string or HTMLElement.
191
279
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -215,54 +303,54 @@ class R {
215
303
  }
216
304
  // #endregion
217
305
  }
218
- function x(i, e, t) {
219
- return i.id !== void 0 ? String(i.id) : t ? `${t}-${e}` : String(e);
306
+ function x(s, e, t) {
307
+ return s.id !== void 0 ? String(s.id) : t ? `${t}-${e}` : String(e);
220
308
  }
221
- function m(i, e) {
222
- const t = new Set(i);
309
+ function y(s, e) {
310
+ const t = new Set(s);
223
311
  return t.has(e) ? t.delete(e) : t.add(e), t;
224
312
  }
225
- function p(i, e, t = null, n = 0) {
226
- const s = e.childrenField ?? "children", o = /* @__PURE__ */ new Set();
227
- for (let r = 0; r < i.length; r++) {
228
- const d = i[r], a = x(d, r, t), l = d[s];
229
- if (Array.isArray(l) && l.length > 0) {
313
+ function w(s, e, t = null, n = 0) {
314
+ const i = e.childrenField ?? "children", o = /* @__PURE__ */ new Set();
315
+ for (let r = 0; r < s.length; r++) {
316
+ const l = s[r], a = x(l, r, t), d = l[i];
317
+ if (Array.isArray(d) && d.length > 0) {
230
318
  o.add(a);
231
- const h = p(l, e, a, n + 1);
232
- for (const f of h) o.add(f);
319
+ const h = w(d, e, a, n + 1);
320
+ for (const u of h) o.add(u);
233
321
  }
234
322
  }
235
323
  return o;
236
324
  }
237
- function C() {
325
+ function v() {
238
326
  return /* @__PURE__ */ new Set();
239
327
  }
240
- function A(i, e, t, n = null, s = 0) {
328
+ function R(s, e, t, n = null, i = 0) {
241
329
  const o = t.childrenField ?? "children";
242
- for (let r = 0; r < i.length; r++) {
243
- const d = i[r], a = x(d, r, n);
330
+ for (let r = 0; r < s.length; r++) {
331
+ const l = s[r], a = x(l, r, n);
244
332
  if (a === e)
245
333
  return [a];
246
- const l = d[o];
247
- if (Array.isArray(l) && l.length > 0) {
248
- const h = A(l, e, t, a, s + 1);
334
+ const d = l[o];
335
+ if (Array.isArray(d) && d.length > 0) {
336
+ const h = R(d, e, t, a, i + 1);
249
337
  if (h)
250
338
  return [a, ...h];
251
339
  }
252
340
  }
253
341
  return null;
254
342
  }
255
- function v(i, e, t, n) {
256
- const s = A(i, e, t);
257
- if (!s) return n;
343
+ function E(s, e, t, n) {
344
+ const i = R(s, e, t);
345
+ if (!i) return n;
258
346
  const o = new Set(n);
259
- for (let r = 0; r < s.length - 1; r++)
260
- o.add(s[r]);
347
+ for (let r = 0; r < i.length - 1; r++)
348
+ o.add(i[r]);
261
349
  return o;
262
350
  }
263
- function b(i, e = "children") {
264
- if (!Array.isArray(i) || i.length === 0) return !1;
265
- for (const t of i) {
351
+ function m(s, e = "children") {
352
+ if (!Array.isArray(s) || s.length === 0) return !1;
353
+ for (const t of s) {
266
354
  if (!t) continue;
267
355
  const n = t[e];
268
356
  if (Array.isArray(n) && n.length > 0)
@@ -270,47 +358,46 @@ function b(i, e = "children") {
270
358
  }
271
359
  return !1;
272
360
  }
273
- function _(i) {
274
- if (!Array.isArray(i) || i.length === 0) return null;
361
+ function C(s) {
362
+ if (!Array.isArray(s) || s.length === 0) return null;
275
363
  const e = ["children", "items", "nodes", "subRows", "nested"];
276
- for (const t of i)
364
+ for (const t of s)
277
365
  if (!(!t || typeof t != "object"))
278
366
  for (const n of e) {
279
- const s = t[n];
280
- if (Array.isArray(s) && s.length > 0)
367
+ const i = t[n];
368
+ if (Array.isArray(i) && i.length > 0)
281
369
  return n;
282
370
  }
283
371
  return null;
284
372
  }
285
- function E(i, e = "children", t = 0) {
286
- if (!Array.isArray(i) || i.length === 0) return t;
373
+ function k(s, e = "children", t = 0) {
374
+ if (!Array.isArray(s) || s.length === 0) return t;
287
375
  let n = t;
288
- for (const s of i) {
289
- if (!s) continue;
290
- const o = s[e];
376
+ for (const i of s) {
377
+ if (!i) continue;
378
+ const o = i[e];
291
379
  if (Array.isArray(o) && o.length > 0) {
292
- const r = E(o, e, t + 1);
380
+ const r = k(o, e, t + 1);
293
381
  r > n && (n = r);
294
382
  }
295
383
  }
296
384
  return n;
297
385
  }
298
- function k(i, e = "children") {
299
- if (!Array.isArray(i)) return 0;
386
+ function T(s, e = "children") {
387
+ if (!Array.isArray(s)) return 0;
300
388
  let t = 0;
301
- for (const n of i) {
389
+ for (const n of s) {
302
390
  if (!n) continue;
303
391
  t++;
304
- const s = n[e];
305
- Array.isArray(s) && (t += k(s, e));
392
+ const i = n[e];
393
+ Array.isArray(i) && (t += T(i, e));
306
394
  }
307
395
  return t;
308
396
  }
309
- const T = ".tree-cell{display:flex;align-items:center;padding-left:calc(var(--tree-depth, 0) * var(--tbw-tree-indent, 20px))}.tree-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;display:inline-flex;align-items:center;justify-content:center;margin-right:4px}.tree-toggle:hover{color:var(--tbw-tree-accent, var(--tbw-color-accent))}.tree-spacer{width:14px;display:inline-block}.data-grid-row.tbw-tree-slide-in{animation:tbw-tree-slide-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-tree-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}.data-grid-row.tbw-tree-fade-in{animation:tbw-tree-fade-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-tree-fade-in{0%{opacity:0}to{opacity:1}}";
310
- class F extends R {
397
+ const I = "@layer tbw-plugins{tbw-grid .cell[data-field=__tbw_expander]{border-right:none!important;padding:0;display:flex;align-items:center;justify-content:flex-start}tbw-grid .header-row .cell[data-field=__tbw_expander]{display:none}tbw-grid .header-row .cell[data-field=__tbw_expander]+.cell{grid-column:1 / 3}tbw-grid .tree-cell-wrapper{display:inline-flex;align-items:center;padding-left:calc(var(--tbw-tree-depth, 0) * var(--tbw-tree-indent-width, var(--tbw-tree-toggle-size, 1.25em)))}tbw-grid .tree-expander{display:flex;align-items:center;justify-content:flex-start;width:100%;height:100%;box-sizing:border-box}tbw-grid .tree-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;display:inline-flex;align-items:center;justify-content:center;width:var(--tbw-tree-toggle-size, 1.25em);height:var(--tbw-tree-toggle-size, 1.25em);flex-shrink:0}tbw-grid .tree-toggle:hover{color:var(--tbw-tree-accent, var(--tbw-color-accent))}tbw-grid .tree-spacer{width:var(--tbw-tree-toggle-size, 1.25em);display:inline-block;flex-shrink:0}tbw-grid .data-grid-row.tbw-tree-slide-in{animation:tbw-tree-slide-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}tbw-grid .data-grid-row.tbw-tree-fade-in{animation:tbw-tree-fade-in var(--tbw-animation-duration, .2s) var(--tbw-animation-easing, ease-out) forwards}@keyframes tbw-tree-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}@keyframes tbw-tree-fade-in{0%{opacity:0}to{opacity:1}}}";
398
+ class F extends _ {
311
399
  name = "tree";
312
- version = "1.0.0";
313
- styles = T;
400
+ styles = I;
314
401
  get defaultConfig() {
315
402
  return {
316
403
  childrenField: "children",
@@ -334,31 +421,28 @@ class F extends R {
334
421
  }
335
422
  // #endregion
336
423
  // #region Animation
424
+ /**
425
+ * Get expand/collapse animation style from plugin config.
426
+ * Uses base class isAnimationEnabled to respect grid-level settings.
427
+ */
337
428
  get animationStyle() {
338
- const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
339
- if (t === !1 || t === "off") return !1;
340
- if (t !== !0 && t !== "on") {
341
- const n = this.shadowRoot?.host;
342
- if (n && getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() === "0")
343
- return !1;
344
- }
345
- return this.config.animation ?? "slide";
429
+ return this.isAnimationEnabled ? this.config.animation ?? "slide" : !1;
346
430
  }
347
431
  // #endregion
348
432
  // #region Auto-Detection
349
433
  detect(e) {
350
434
  if (!this.config.autoDetect) return !1;
351
- const t = e, n = this.config.childrenField ?? _(t) ?? "children";
352
- return b(t, n);
435
+ const t = e, n = this.config.childrenField ?? C(t) ?? "children";
436
+ return m(t, n);
353
437
  }
354
438
  // #endregion
355
439
  // #region Data Processing
356
440
  processRows(e) {
357
441
  const t = this.config.childrenField ?? "children", n = e;
358
- if (!b(n, t))
442
+ if (!m(n, t))
359
443
  return this.flattenedRows = [], this.rowKeyMap.clear(), this.previousVisibleKeys.clear(), [...e];
360
- let s = this.withStableKeys(n);
361
- this.sortState && (s = this.sortTree(s, this.sortState.field, this.sortState.direction)), this.config.defaultExpanded && !this.initialExpansionDone && (this.expandedKeys = p(s, this.config), this.initialExpansionDone = !0), this.flattenedRows = this.flattenTree(s, this.expandedKeys), this.rowKeyMap.clear(), this.keysToAnimate.clear();
444
+ let i = this.withStableKeys(n);
445
+ this.sortState && (i = this.sortTree(i, this.sortState.field, this.sortState.direction)), this.config.defaultExpanded && !this.initialExpansionDone && (this.expandedKeys = w(i, this.config), this.initialExpansionDone = !0), this.flattenedRows = this.flattenTree(i, this.expandedKeys), this.rowKeyMap.clear(), this.keysToAnimate.clear();
362
446
  const o = /* @__PURE__ */ new Set();
363
447
  for (const r of this.flattenedRows)
364
448
  this.rowKeyMap.set(r.key, r), o.add(r.key), !this.previousVisibleKeys.has(r.key) && r.depth > 0 && this.keysToAnimate.add(r.key);
@@ -373,80 +457,92 @@ class F extends R {
373
457
  /** Assign stable keys to rows (preserves key across sort operations) */
374
458
  withStableKeys(e, t = null) {
375
459
  const n = this.config.childrenField ?? "children";
376
- return e.map((s, o) => {
377
- const r = s.__stableKey, d = s.id !== void 0 ? String(s.id) : r ?? (t ? `${t}-${o}` : String(o)), a = s[n], l = Array.isArray(a) && a.length > 0;
460
+ return e.map((i, o) => {
461
+ const r = i.__stableKey, l = i.id !== void 0 ? String(i.id) : r ?? (t ? `${t}-${o}` : String(o)), a = i[n], d = Array.isArray(a) && a.length > 0;
378
462
  return {
379
- ...s,
380
- __stableKey: d,
381
- ...l ? { [n]: this.withStableKeys(a, d) } : {}
463
+ ...i,
464
+ __stableKey: l,
465
+ ...d ? { [n]: this.withStableKeys(a, l) } : {}
382
466
  };
383
467
  });
384
468
  }
385
469
  /** Flatten tree using stable keys */
386
470
  flattenTree(e, t, n = 0) {
387
- const s = this.config.childrenField ?? "children", o = [];
471
+ const i = this.config.childrenField ?? "children", o = [];
388
472
  for (const r of e) {
389
- const a = r.__stableKey ?? String(r.id ?? "?"), l = r[s], h = Array.isArray(l) && l.length > 0, f = t.has(a);
473
+ const a = r.__stableKey ?? String(r.id ?? "?"), d = r[i], h = Array.isArray(d) && d.length > 0, u = t.has(a);
390
474
  o.push({
391
475
  key: a,
392
476
  data: r,
393
477
  depth: n,
394
478
  hasChildren: h,
395
- isExpanded: f,
479
+ isExpanded: u,
396
480
  parentKey: n > 0 && a.substring(0, a.lastIndexOf("-")) || null
397
- }), h && f && o.push(...this.flattenTree(l, t, n + 1));
481
+ }), h && u && o.push(...this.flattenTree(d, t, n + 1));
398
482
  }
399
483
  return o;
400
484
  }
401
485
  /** Sort tree recursively, keeping children with parents */
402
486
  sortTree(e, t, n) {
403
- const s = this.config.childrenField ?? "children";
404
- return [...e].sort((r, d) => {
405
- const a = r[t], l = d[t];
406
- return a == null && l == null ? 0 : a == null ? -1 : l == null ? 1 : a > l ? n : a < l ? -n : 0;
487
+ const i = this.config.childrenField ?? "children";
488
+ return [...e].sort((r, l) => {
489
+ const a = r[t], d = l[t];
490
+ return a == null && d == null ? 0 : a == null ? -1 : d == null ? 1 : a > d ? n : a < d ? -n : 0;
407
491
  }).map((r) => {
408
- const d = r[s];
409
- return Array.isArray(d) && d.length > 0 ? { ...r, [s]: this.sortTree(d, t, n) } : r;
492
+ const l = r[i];
493
+ return Array.isArray(l) && l.length > 0 ? { ...r, [i]: this.sortTree(l, t, n) } : r;
410
494
  });
411
495
  }
412
496
  processColumns(e) {
413
497
  if (this.flattenedRows.length === 0) return [...e];
414
498
  const t = [...e];
415
499
  if (t.length === 0) return t;
416
- const n = { ...t[0] }, s = n.viewRenderer;
417
- if (s?.__treeWrapped) return t;
418
- const o = () => this.config, r = this.setIcon.bind(this), d = this.resolveIcon.bind(this), a = (l) => {
419
- const { value: h, row: f } = l, { indentWidth: K = 20, showExpandIcons: w = !0 } = o(), g = f, u = document.createElement("span");
420
- if (u.className = "tree-cell", u.style.setProperty("--tree-depth", String(g.__treeDepth ?? 0)), u.style.setProperty("--tbw-tree-indent", `${K}px`), g.__treeHasChildren && w) {
421
- const c = document.createElement("span");
422
- c.className = `tree-toggle${g.__treeExpanded ? " expanded" : ""}`, r(c, d(g.__treeExpanded ? "collapse" : "expand")), c.setAttribute("data-tree-key", String(g.__treeKey ?? "")), u.appendChild(c);
423
- } else if (w) {
424
- const c = document.createElement("span");
425
- c.className = "tree-spacer", u.appendChild(c);
426
- }
427
- const y = document.createElement("span");
428
- if (s) {
429
- const c = s(l);
430
- c instanceof Node ? y.appendChild(c) : y.textContent = String(c ?? h ?? "");
500
+ const n = t[0], i = n.viewRenderer, o = () => this.config, r = this.setIcon.bind(this), l = this.resolveIcon.bind(this), a = (d) => {
501
+ const { row: h, value: u } = d, { showExpandIcons: A = !0, indentWidth: b } = o(), g = h, K = g.__treeDepth ?? 0, f = document.createElement("span");
502
+ if (f.className = "tree-cell-wrapper", f.style.setProperty("--tbw-tree-depth", String(K)), b !== void 0 && f.style.setProperty("--tbw-tree-indent-width", `${b}px`), A)
503
+ if (g.__treeHasChildren) {
504
+ const c = document.createElement("span");
505
+ c.className = `tree-toggle${g.__treeExpanded ? " expanded" : ""}`, r(c, l(g.__treeExpanded ? "collapse" : "expand")), c.setAttribute("data-tree-key", String(g.__treeKey ?? "")), f.appendChild(c);
506
+ } else {
507
+ const c = document.createElement("span");
508
+ c.className = "tree-spacer", f.appendChild(c);
509
+ }
510
+ const p = document.createElement("span");
511
+ if (p.className = "tree-content", i) {
512
+ const c = i(d);
513
+ c instanceof Node ? p.appendChild(c) : typeof c == "string" && (p.innerHTML = c);
431
514
  } else
432
- y.textContent = String(h ?? "");
433
- return u.appendChild(y), u;
515
+ p.textContent = u != null ? String(u) : "";
516
+ return f.appendChild(p), f;
434
517
  };
435
- return a.__treeWrapped = !0, n.viewRenderer = a, t[0] = n, t;
518
+ return t[0] = { ...n, viewRenderer: a }, t;
436
519
  }
437
520
  // #endregion
438
521
  // #region Event Handlers
439
522
  onCellClick(e) {
440
523
  const t = e.originalEvent?.target;
441
524
  if (!t?.classList.contains("tree-toggle")) return !1;
442
- const n = t.getAttribute("data-tree-key"), s = n ? this.rowKeyMap.get(n) : null;
443
- return s ? (this.expandedKeys = m(this.expandedKeys, n), this.emit("tree-expand", {
525
+ const n = t.getAttribute("data-tree-key");
526
+ if (!n) return !1;
527
+ const i = this.rowKeyMap.get(n);
528
+ return i ? (this.expandedKeys = y(this.expandedKeys, n), this.emit("tree-expand", {
444
529
  key: n,
445
- row: s.data,
530
+ row: i.data,
446
531
  expanded: this.expandedKeys.has(n),
447
- depth: s.depth
532
+ depth: i.depth
448
533
  }), this.requestRender(), !0) : !1;
449
534
  }
535
+ onKeyDown(e) {
536
+ if (e.key !== " ") return;
537
+ const t = this.grid._focusRow, n = this.flattenedRows[t];
538
+ if (n?.hasChildren)
539
+ return e.preventDefault(), this.expandedKeys = y(this.expandedKeys, n.key), this.emit("tree-expand", {
540
+ key: n.key,
541
+ row: n.data,
542
+ expanded: this.expandedKeys.has(n.key),
543
+ depth: n.depth
544
+ }), this.requestRenderWithFocus(), !0;
545
+ }
450
546
  onHeaderClick(e) {
451
547
  if (this.flattenedRows.length === 0 || !e.column.sortable) return !1;
452
548
  const { field: t } = e.column;
@@ -457,12 +553,12 @@ class F extends R {
457
553
  afterRender() {
458
554
  const e = this.animationStyle;
459
555
  if (e === !1 || this.keysToAnimate.size === 0) return;
460
- const t = this.shadowRoot?.querySelector(".rows");
556
+ const t = this.gridElement?.querySelector(".rows");
461
557
  if (!t) return;
462
558
  const n = e === "fade" ? "tbw-tree-fade-in" : "tbw-tree-slide-in";
463
- for (const s of t.querySelectorAll(".data-grid-row")) {
464
- const o = s.querySelector(".cell[data-row]"), r = o ? parseInt(o.getAttribute("data-row") ?? "-1", 10) : -1, d = this.flattenedRows[r]?.key;
465
- d && this.keysToAnimate.has(d) && (s.classList.add(n), s.addEventListener("animationend", () => s.classList.remove(n), { once: !0 }));
559
+ for (const i of t.querySelectorAll(".data-grid-row")) {
560
+ const o = i.querySelector(".cell[data-row]"), r = o ? parseInt(o.getAttribute("data-row") ?? "-1", 10) : -1, l = this.flattenedRows[r]?.key;
561
+ l && this.keysToAnimate.has(l) && (i.classList.add(n), i.addEventListener("animationend", () => i.classList.remove(n), { once: !0 }));
466
562
  }
467
563
  this.keysToAnimate.clear();
468
564
  }
@@ -475,13 +571,13 @@ class F extends R {
475
571
  this.expandedKeys.delete(e), this.requestRender();
476
572
  }
477
573
  toggle(e) {
478
- this.expandedKeys = m(this.expandedKeys, e), this.requestRender();
574
+ this.expandedKeys = y(this.expandedKeys, e), this.requestRender();
479
575
  }
480
576
  expandAll() {
481
- this.expandedKeys = p(this.rows, this.config), this.requestRender();
577
+ this.expandedKeys = w(this.rows, this.config), this.requestRender();
482
578
  }
483
579
  collapseAll() {
484
- this.expandedKeys = C(), this.requestRender();
580
+ this.expandedKeys = v(), this.requestRender();
485
581
  }
486
582
  isExpanded(e) {
487
583
  return this.expandedKeys.has(e);
@@ -496,15 +592,15 @@ class F extends R {
496
592
  return this.rowKeyMap.get(e)?.data;
497
593
  }
498
594
  expandToKey(e) {
499
- this.expandedKeys = v(this.rows, e, this.config, this.expandedKeys), this.requestRender();
595
+ this.expandedKeys = E(this.rows, e, this.config, this.expandedKeys), this.requestRender();
500
596
  }
501
597
  // #endregion
502
598
  }
503
599
  export {
504
600
  F as TreePlugin,
505
- k as countNodes,
506
- b as detectTreeStructure,
507
- E as getMaxDepth,
508
- _ as inferChildrenField
601
+ T as countNodes,
602
+ m as detectTreeStructure,
603
+ k as getMaxDepth,
604
+ C as inferChildrenField
509
605
  };
510
606
  //# sourceMappingURL=index.js.map