@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
@@ -11,7 +11,6 @@ import { FlattenedTreeRow, TreeConfig, TreeRow } from './types';
11
11
  */
12
12
  export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
13
13
  readonly name = "tree";
14
- readonly version = "1.0.0";
15
14
  readonly styles: string;
16
15
  protected get defaultConfig(): Partial<TreeConfig>;
17
16
  private expandedKeys;
@@ -22,6 +21,10 @@ export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
22
21
  private keysToAnimate;
23
22
  private sortState;
24
23
  detach(): void;
24
+ /**
25
+ * Get expand/collapse animation style from plugin config.
26
+ * Uses base class isAnimationEnabled to respect grid-level settings.
27
+ */
25
28
  private get animationStyle();
26
29
  detect(rows: readonly unknown[]): boolean;
27
30
  processRows(rows: readonly unknown[]): TreeRow[];
@@ -33,6 +36,7 @@ export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
33
36
  private sortTree;
34
37
  processColumns(columns: readonly ColumnConfig[]): ColumnConfig[];
35
38
  onCellClick(event: CellClickEvent): boolean;
39
+ onKeyDown(event: KeyboardEvent): boolean | void;
36
40
  onHeaderClick(event: HeaderClickEvent): boolean;
37
41
  afterRender(): void;
38
42
  expand(key: string): void;
@@ -1 +1 @@
1
- {"version":3,"file":"TreePlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/tree/TreePlugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,KAAK,EAAE,YAAY,EAAc,MAAM,kBAAkB,CAAC;AAIjE,OAAO,KAAK,EAEV,gBAAgB,EAChB,UAAU,EAEV,OAAO,EAER,MAAM,SAAS,CAAC;AAOjB;;;;;;;GAOG;AACH,qBAAa,UAAW,SAAQ,cAAc,CAAC,UAAU,CAAC;IACxD,QAAQ,CAAC,IAAI,UAAU;IACvB,SAAkB,OAAO,WAAW;IACpC,SAAkB,MAAM,SAAU;IAElC,cAAuB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAS1D;IAID,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAAqD;IAE7D,MAAM,IAAI,IAAI;IAcvB,OAAO,KAAK,cAAc,GAYzB;IAMD,MAAM,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO;IAWhC,WAAW,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE;IA+CzD,wEAAwE;IACxE,OAAO,CAAC,cAAc;IAetB,qCAAqC;IACrC,OAAO,CAAC,WAAW;IA2BnB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ;IAkBP,cAAc,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,EAAE;IA6DhE,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO;IAmB3C,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAuB/C,WAAW,IAAI,IAAI;IAyB5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB,SAAS,IAAI,IAAI;IAKjB,WAAW,IAAI,IAAI;IAKnB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC,eAAe,IAAI,MAAM,EAAE;IAI3B,gBAAgB,IAAI,gBAAgB,EAAE;IAItC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI7C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAM/B"}
1
+ {"version":3,"file":"TreePlugin.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/tree/TreePlugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,KAAK,EAAE,YAAY,EAAsB,MAAM,kBAAkB,CAAC;AAIzE,OAAO,KAAK,EAA2B,gBAAgB,EAAE,UAAU,EAAoB,OAAO,EAAE,MAAM,SAAS,CAAC;AAMhH;;;;;;;GAOG;AACH,qBAAa,UAAW,SAAQ,cAAc,CAAC,UAAU,CAAC;IACxD,QAAQ,CAAC,IAAI,UAAU;IACvB,SAAkB,MAAM,SAAU;IAElC,cAAuB,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC,CAS1D;IAID,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,SAAS,CAAuC;IACxD,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,SAAS,CAAqD;IAE7D,MAAM,IAAI,IAAI;IAcvB;;;OAGG;IACH,OAAO,KAAK,cAAc,GAGzB;IAMD,MAAM,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO;IAWhC,WAAW,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,EAAE;IA+CzD,wEAAwE;IACxE,OAAO,CAAC,cAAc;IAetB,qCAAqC;IACrC,OAAO,CAAC,WAAW;IA2BnB,2DAA2D;IAC3D,OAAO,CAAC,QAAQ;IAkBP,cAAc,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,YAAY,EAAE;IAoEhE,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO;IAqB3C,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,GAAG,IAAI;IAoB/C,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAuB/C,WAAW,IAAI,IAAI;IAyB5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAK3B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB,SAAS,IAAI,IAAI;IAKjB,WAAW,IAAI,IAAI;IAKnB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIhC,eAAe,IAAI,MAAM,EAAE;IAI3B,gBAAgB,IAAI,gBAAgB,EAAE;IAItC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI7C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAM/B"}
@@ -1,4 +1,4 @@
1
- const S = {
1
+ const _ = {
2
2
  expand: "▶",
3
3
  collapse: "▼",
4
4
  sortAsc: "▲",
@@ -8,9 +8,28 @@ const S = {
8
8
  dragHandle: "⋮⋮",
9
9
  toolPanel: "☰"
10
10
  };
11
- class R {
12
- /** Plugin version - override in subclass if needed */
13
- version = "1.0.0";
11
+ class S {
12
+ /**
13
+ * Plugin dependencies - declare other plugins this one requires.
14
+ *
15
+ * Dependencies are validated when the plugin is attached.
16
+ * Required dependencies throw an error if missing.
17
+ * Optional dependencies log an info message if missing.
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * static readonly dependencies: PluginDependency[] = [
22
+ * { name: 'editing', required: true, reason: 'Tracks cell edits for undo/redo' },
23
+ * { name: 'selection', required: false, reason: 'Enables selection-based undo' },
24
+ * ];
25
+ * ```
26
+ */
27
+ static dependencies;
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";
14
33
  /** CSS styles to inject into the grid's shadow DOM */
15
34
  styles;
16
35
  /** Custom cell renderers keyed by type name */
@@ -97,12 +116,28 @@ class R {
97
116
  emit(e, t) {
98
117
  this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
99
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
+ }
100
127
  /**
101
128
  * Request a re-render of the grid.
102
129
  */
103
130
  requestRender() {
104
131
  this.grid?.requestRender?.();
105
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
+ }
106
141
  /**
107
142
  * Request a lightweight style update without rebuilding DOM.
108
143
  * Use this instead of requestRender() when only CSS classes need updating.
@@ -136,6 +171,19 @@ class R {
136
171
  get visibleColumns() {
137
172
  return this.grid?._visibleColumns ?? [];
138
173
  }
174
+ /**
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
+ }
139
187
  /**
140
188
  * Get the shadow root of the grid.
141
189
  */
@@ -168,8 +216,53 @@ class R {
168
216
  */
169
217
  get gridIcons() {
170
218
  const e = this.grid?.gridConfig?.icons ?? {};
171
- return { ...S, ...e };
219
+ return { ..._, ...e };
172
220
  }
221
+ // #region Animation Helpers
222
+ /**
223
+ * Check if animations are enabled at the grid level.
224
+ * Respects gridConfig.animation.mode and the CSS variable set by the grid.
225
+ *
226
+ * Plugins should use this to skip animations when:
227
+ * - Animation mode is 'off' or `false`
228
+ * - User prefers reduced motion and mode is 'reduced-motion' (default)
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * private get animationStyle(): 'slide' | 'fade' | false {
233
+ * if (!this.isAnimationEnabled) return false;
234
+ * return this.config.animation ?? 'slide';
235
+ * }
236
+ * ```
237
+ */
238
+ get isAnimationEnabled() {
239
+ const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
240
+ if (e === !1 || e === "off") return !1;
241
+ if (e === !0 || e === "on") return !0;
242
+ const t = this.shadowRoot?.host;
243
+ return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
244
+ }
245
+ /**
246
+ * Get the animation duration in milliseconds from CSS variable.
247
+ * Falls back to 200ms if not set.
248
+ *
249
+ * Plugins can use this for their animation timing to stay consistent
250
+ * with the grid-level animation.duration setting.
251
+ *
252
+ * @example
253
+ * ```ts
254
+ * element.animate(keyframes, { duration: this.animationDuration });
255
+ * ```
256
+ */
257
+ get animationDuration() {
258
+ const e = this.shadowRoot?.host;
259
+ if (e) {
260
+ const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), n = parseInt(t, 10);
261
+ if (!isNaN(n)) return n;
262
+ }
263
+ return 200;
264
+ }
265
+ // #endregion
173
266
  /**
174
267
  * Resolve an icon value to string or HTMLElement.
175
268
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -199,54 +292,54 @@ class R {
199
292
  }
200
293
  // #endregion
201
294
  }
202
- function x(i, e, t) {
203
- return i.id !== void 0 ? String(i.id) : t ? `${t}-${e}` : String(e);
295
+ function b(s, e, t) {
296
+ return s.id !== void 0 ? String(s.id) : t ? `${t}-${e}` : String(e);
204
297
  }
205
- function m(i, e) {
206
- const t = new Set(i);
298
+ function y(s, e) {
299
+ const t = new Set(s);
207
300
  return t.has(e) ? t.delete(e) : t.add(e), t;
208
301
  }
209
- function p(i, e, t = null, n = 0) {
210
- const s = e.childrenField ?? "children", o = /* @__PURE__ */ new Set();
211
- for (let r = 0; r < i.length; r++) {
212
- const d = i[r], a = x(d, r, t), l = d[s];
213
- if (Array.isArray(l) && l.length > 0) {
302
+ function w(s, e, t = null, n = 0) {
303
+ const i = e.childrenField ?? "children", o = /* @__PURE__ */ new Set();
304
+ for (let r = 0; r < s.length; r++) {
305
+ const l = s[r], a = b(l, r, t), d = l[i];
306
+ if (Array.isArray(d) && d.length > 0) {
214
307
  o.add(a);
215
- const h = p(l, e, a, n + 1);
216
- for (const f of h) o.add(f);
308
+ const h = w(d, e, a, n + 1);
309
+ for (const u of h) o.add(u);
217
310
  }
218
311
  }
219
312
  return o;
220
313
  }
221
- function C() {
314
+ function v() {
222
315
  return /* @__PURE__ */ new Set();
223
316
  }
224
- function A(i, e, t, n = null, s = 0) {
317
+ function x(s, e, t, n = null, i = 0) {
225
318
  const o = t.childrenField ?? "children";
226
- for (let r = 0; r < i.length; r++) {
227
- const d = i[r], a = x(d, r, n);
319
+ for (let r = 0; r < s.length; r++) {
320
+ const l = s[r], a = b(l, r, n);
228
321
  if (a === e)
229
322
  return [a];
230
- const l = d[o];
231
- if (Array.isArray(l) && l.length > 0) {
232
- const h = A(l, e, t, a, s + 1);
323
+ const d = l[o];
324
+ if (Array.isArray(d) && d.length > 0) {
325
+ const h = x(d, e, t, a, i + 1);
233
326
  if (h)
234
327
  return [a, ...h];
235
328
  }
236
329
  }
237
330
  return null;
238
331
  }
239
- function v(i, e, t, n) {
240
- const s = A(i, e, t);
241
- if (!s) return n;
332
+ function C(s, e, t, n) {
333
+ const i = x(s, e, t);
334
+ if (!i) return n;
242
335
  const o = new Set(n);
243
- for (let r = 0; r < s.length - 1; r++)
244
- o.add(s[r]);
336
+ for (let r = 0; r < i.length - 1; r++)
337
+ o.add(i[r]);
245
338
  return o;
246
339
  }
247
- function b(i, e = "children") {
248
- if (!Array.isArray(i) || i.length === 0) return !1;
249
- for (const t of i) {
340
+ function m(s, e = "children") {
341
+ if (!Array.isArray(s) || s.length === 0) return !1;
342
+ for (const t of s) {
250
343
  if (!t) continue;
251
344
  const n = t[e];
252
345
  if (Array.isArray(n) && n.length > 0)
@@ -254,47 +347,46 @@ function b(i, e = "children") {
254
347
  }
255
348
  return !1;
256
349
  }
257
- function _(i) {
258
- if (!Array.isArray(i) || i.length === 0) return null;
350
+ function E(s) {
351
+ if (!Array.isArray(s) || s.length === 0) return null;
259
352
  const e = ["children", "items", "nodes", "subRows", "nested"];
260
- for (const t of i)
353
+ for (const t of s)
261
354
  if (!(!t || typeof t != "object"))
262
355
  for (const n of e) {
263
- const s = t[n];
264
- if (Array.isArray(s) && s.length > 0)
356
+ const i = t[n];
357
+ if (Array.isArray(i) && i.length > 0)
265
358
  return n;
266
359
  }
267
360
  return null;
268
361
  }
269
- function E(i, e = "children", t = 0) {
270
- if (!Array.isArray(i) || i.length === 0) return t;
362
+ function k(s, e = "children", t = 0) {
363
+ if (!Array.isArray(s) || s.length === 0) return t;
271
364
  let n = t;
272
- for (const s of i) {
273
- if (!s) continue;
274
- const o = s[e];
365
+ for (const i of s) {
366
+ if (!i) continue;
367
+ const o = i[e];
275
368
  if (Array.isArray(o) && o.length > 0) {
276
- const r = E(o, e, t + 1);
369
+ const r = k(o, e, t + 1);
277
370
  r > n && (n = r);
278
371
  }
279
372
  }
280
373
  return n;
281
374
  }
282
- function k(i, e = "children") {
283
- if (!Array.isArray(i)) return 0;
375
+ function T(s, e = "children") {
376
+ if (!Array.isArray(s)) return 0;
284
377
  let t = 0;
285
- for (const n of i) {
378
+ for (const n of s) {
286
379
  if (!n) continue;
287
380
  t++;
288
- const s = n[e];
289
- Array.isArray(s) && (t += k(s, e));
381
+ const i = n[e];
382
+ Array.isArray(i) && (t += T(i, e));
290
383
  }
291
384
  return t;
292
385
  }
293
- 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}}";
294
- class F extends R {
386
+ const I = ".cell[data-field=__tbw_expander]{border-right:none!important;padding:0;display:flex;align-items:center;justify-content:flex-start}.header-row .cell[data-field=__tbw_expander]{visibility:hidden;border:none!important;padding:0;overflow:hidden}.header-row .cell[data-field=__tbw_expander]+.cell{margin-left:-32px;padding-left:calc(var(--tbw-cell-padding, 8px) + 32px)}.tree-expander{display:flex;align-items:center;justify-content:flex-start;width:100%;height:100%;box-sizing:border-box}.tree-toggle{cursor:pointer;-webkit-user-select:none;user-select:none;display:inline-flex;align-items:center;justify-content:center}.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}}";
387
+ class F extends S {
295
388
  name = "tree";
296
- version = "1.0.0";
297
- styles = T;
389
+ styles = I;
298
390
  get defaultConfig() {
299
391
  return {
300
392
  childrenField: "children",
@@ -318,31 +410,28 @@ class F extends R {
318
410
  }
319
411
  // #endregion
320
412
  // #region Animation
413
+ /**
414
+ * Get expand/collapse animation style from plugin config.
415
+ * Uses base class isAnimationEnabled to respect grid-level settings.
416
+ */
321
417
  get animationStyle() {
322
- const t = this.grid.effectiveConfig?.animation?.mode ?? "reduced-motion";
323
- if (t === !1 || t === "off") return !1;
324
- if (t !== !0 && t !== "on") {
325
- const n = this.shadowRoot?.host;
326
- if (n && getComputedStyle(n).getPropertyValue("--tbw-animation-enabled").trim() === "0")
327
- return !1;
328
- }
329
- return this.config.animation ?? "slide";
418
+ return this.isAnimationEnabled ? this.config.animation ?? "slide" : !1;
330
419
  }
331
420
  // #endregion
332
421
  // #region Auto-Detection
333
422
  detect(e) {
334
423
  if (!this.config.autoDetect) return !1;
335
- const t = e, n = this.config.childrenField ?? _(t) ?? "children";
336
- return b(t, n);
424
+ const t = e, n = this.config.childrenField ?? E(t) ?? "children";
425
+ return m(t, n);
337
426
  }
338
427
  // #endregion
339
428
  // #region Data Processing
340
429
  processRows(e) {
341
430
  const t = this.config.childrenField ?? "children", n = e;
342
- if (!b(n, t))
431
+ if (!m(n, t))
343
432
  return this.flattenedRows = [], this.rowKeyMap.clear(), this.previousVisibleKeys.clear(), [...e];
344
- let s = this.withStableKeys(n);
345
- 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();
433
+ let i = this.withStableKeys(n);
434
+ 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();
346
435
  const o = /* @__PURE__ */ new Set();
347
436
  for (const r of this.flattenedRows)
348
437
  this.rowKeyMap.set(r.key, r), o.add(r.key), !this.previousVisibleKeys.has(r.key) && r.depth > 0 && this.keysToAnimate.add(r.key);
@@ -357,80 +446,92 @@ class F extends R {
357
446
  /** Assign stable keys to rows (preserves key across sort operations) */
358
447
  withStableKeys(e, t = null) {
359
448
  const n = this.config.childrenField ?? "children";
360
- return e.map((s, o) => {
361
- 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;
449
+ return e.map((i, o) => {
450
+ 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;
362
451
  return {
363
- ...s,
364
- __stableKey: d,
365
- ...l ? { [n]: this.withStableKeys(a, d) } : {}
452
+ ...i,
453
+ __stableKey: l,
454
+ ...d ? { [n]: this.withStableKeys(a, l) } : {}
366
455
  };
367
456
  });
368
457
  }
369
458
  /** Flatten tree using stable keys */
370
459
  flattenTree(e, t, n = 0) {
371
- const s = this.config.childrenField ?? "children", o = [];
460
+ const i = this.config.childrenField ?? "children", o = [];
372
461
  for (const r of e) {
373
- const a = r.__stableKey ?? String(r.id ?? "?"), l = r[s], h = Array.isArray(l) && l.length > 0, f = t.has(a);
462
+ const a = r.__stableKey ?? String(r.id ?? "?"), d = r[i], h = Array.isArray(d) && d.length > 0, u = t.has(a);
374
463
  o.push({
375
464
  key: a,
376
465
  data: r,
377
466
  depth: n,
378
467
  hasChildren: h,
379
- isExpanded: f,
468
+ isExpanded: u,
380
469
  parentKey: n > 0 && a.substring(0, a.lastIndexOf("-")) || null
381
- }), h && f && o.push(...this.flattenTree(l, t, n + 1));
470
+ }), h && u && o.push(...this.flattenTree(d, t, n + 1));
382
471
  }
383
472
  return o;
384
473
  }
385
474
  /** Sort tree recursively, keeping children with parents */
386
475
  sortTree(e, t, n) {
387
- const s = this.config.childrenField ?? "children";
388
- return [...e].sort((r, d) => {
389
- const a = r[t], l = d[t];
390
- return a == null && l == null ? 0 : a == null ? -1 : l == null ? 1 : a > l ? n : a < l ? -n : 0;
476
+ const i = this.config.childrenField ?? "children";
477
+ return [...e].sort((r, l) => {
478
+ const a = r[t], d = l[t];
479
+ return a == null && d == null ? 0 : a == null ? -1 : d == null ? 1 : a > d ? n : a < d ? -n : 0;
391
480
  }).map((r) => {
392
- const d = r[s];
393
- return Array.isArray(d) && d.length > 0 ? { ...r, [s]: this.sortTree(d, t, n) } : r;
481
+ const l = r[i];
482
+ return Array.isArray(l) && l.length > 0 ? { ...r, [i]: this.sortTree(l, t, n) } : r;
394
483
  });
395
484
  }
396
485
  processColumns(e) {
397
486
  if (this.flattenedRows.length === 0) return [...e];
398
487
  const t = [...e];
399
488
  if (t.length === 0) return t;
400
- const n = { ...t[0] }, s = n.viewRenderer;
401
- if (s?.__treeWrapped) return t;
402
- const o = () => this.config, r = this.setIcon.bind(this), d = this.resolveIcon.bind(this), a = (l) => {
403
- const { value: h, row: f } = l, { indentWidth: K = 20, showExpandIcons: w = !0 } = o(), g = f, u = document.createElement("span");
404
- 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) {
405
- const c = document.createElement("span");
406
- 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);
407
- } else if (w) {
408
- const c = document.createElement("span");
409
- c.className = "tree-spacer", u.appendChild(c);
410
- }
411
- const y = document.createElement("span");
412
- if (s) {
413
- const c = s(l);
414
- c instanceof Node ? y.appendChild(c) : y.textContent = String(c ?? h ?? "");
489
+ const n = t[0], i = n.viewRenderer, o = () => this.config, r = this.setIcon.bind(this), l = this.resolveIcon.bind(this), a = (d) => {
490
+ const { row: h, value: u } = d, { indentWidth: R = 20, showExpandIcons: A = !0 } = o(), p = h, K = p.__treeDepth ?? 0, f = document.createElement("span");
491
+ if (f.className = "tree-cell-wrapper", f.style.paddingLeft = `${Number(K) * R}px`, A)
492
+ if (p.__treeHasChildren) {
493
+ const c = document.createElement("span");
494
+ c.className = `tree-toggle${p.__treeExpanded ? " expanded" : ""}`, r(c, l(p.__treeExpanded ? "collapse" : "expand")), c.setAttribute("data-tree-key", String(p.__treeKey ?? "")), f.appendChild(c);
495
+ } else {
496
+ const c = document.createElement("span");
497
+ c.className = "tree-spacer", f.appendChild(c);
498
+ }
499
+ const g = document.createElement("span");
500
+ if (g.className = "tree-content", i) {
501
+ const c = i(d);
502
+ c instanceof Node ? g.appendChild(c) : typeof c == "string" && (g.innerHTML = c);
415
503
  } else
416
- y.textContent = String(h ?? "");
417
- return u.appendChild(y), u;
504
+ g.textContent = u != null ? String(u) : "";
505
+ return f.appendChild(g), f;
418
506
  };
419
- return a.__treeWrapped = !0, n.viewRenderer = a, t[0] = n, t;
507
+ return t[0] = { ...n, viewRenderer: a }, t;
420
508
  }
421
509
  // #endregion
422
510
  // #region Event Handlers
423
511
  onCellClick(e) {
424
512
  const t = e.originalEvent?.target;
425
513
  if (!t?.classList.contains("tree-toggle")) return !1;
426
- const n = t.getAttribute("data-tree-key"), s = n ? this.rowKeyMap.get(n) : null;
427
- return s ? (this.expandedKeys = m(this.expandedKeys, n), this.emit("tree-expand", {
514
+ const n = t.getAttribute("data-tree-key");
515
+ if (!n) return !1;
516
+ const i = this.rowKeyMap.get(n);
517
+ return i ? (this.expandedKeys = y(this.expandedKeys, n), this.emit("tree-expand", {
428
518
  key: n,
429
- row: s.data,
519
+ row: i.data,
430
520
  expanded: this.expandedKeys.has(n),
431
- depth: s.depth
521
+ depth: i.depth
432
522
  }), this.requestRender(), !0) : !1;
433
523
  }
524
+ onKeyDown(e) {
525
+ if (e.key !== " ") return;
526
+ const t = this.grid._focusRow, n = this.flattenedRows[t];
527
+ if (n?.hasChildren)
528
+ return e.preventDefault(), this.expandedKeys = y(this.expandedKeys, n.key), this.emit("tree-expand", {
529
+ key: n.key,
530
+ row: n.data,
531
+ expanded: this.expandedKeys.has(n.key),
532
+ depth: n.depth
533
+ }), this.requestRenderWithFocus(), !0;
534
+ }
434
535
  onHeaderClick(e) {
435
536
  if (this.flattenedRows.length === 0 || !e.column.sortable) return !1;
436
537
  const { field: t } = e.column;
@@ -444,9 +545,9 @@ class F extends R {
444
545
  const t = this.shadowRoot?.querySelector(".rows");
445
546
  if (!t) return;
446
547
  const n = e === "fade" ? "tbw-tree-fade-in" : "tbw-tree-slide-in";
447
- for (const s of t.querySelectorAll(".data-grid-row")) {
448
- const o = s.querySelector(".cell[data-row]"), r = o ? parseInt(o.getAttribute("data-row") ?? "-1", 10) : -1, d = this.flattenedRows[r]?.key;
449
- d && this.keysToAnimate.has(d) && (s.classList.add(n), s.addEventListener("animationend", () => s.classList.remove(n), { once: !0 }));
548
+ for (const i of t.querySelectorAll(".data-grid-row")) {
549
+ const o = i.querySelector(".cell[data-row]"), r = o ? parseInt(o.getAttribute("data-row") ?? "-1", 10) : -1, l = this.flattenedRows[r]?.key;
550
+ l && this.keysToAnimate.has(l) && (i.classList.add(n), i.addEventListener("animationend", () => i.classList.remove(n), { once: !0 }));
450
551
  }
451
552
  this.keysToAnimate.clear();
452
553
  }
@@ -459,13 +560,13 @@ class F extends R {
459
560
  this.expandedKeys.delete(e), this.requestRender();
460
561
  }
461
562
  toggle(e) {
462
- this.expandedKeys = m(this.expandedKeys, e), this.requestRender();
563
+ this.expandedKeys = y(this.expandedKeys, e), this.requestRender();
463
564
  }
464
565
  expandAll() {
465
- this.expandedKeys = p(this.rows, this.config), this.requestRender();
566
+ this.expandedKeys = w(this.rows, this.config), this.requestRender();
466
567
  }
467
568
  collapseAll() {
468
- this.expandedKeys = C(), this.requestRender();
569
+ this.expandedKeys = v(), this.requestRender();
469
570
  }
470
571
  isExpanded(e) {
471
572
  return this.expandedKeys.has(e);
@@ -480,15 +581,15 @@ class F extends R {
480
581
  return this.rowKeyMap.get(e)?.data;
481
582
  }
482
583
  expandToKey(e) {
483
- this.expandedKeys = v(this.rows, e, this.config, this.expandedKeys), this.requestRender();
584
+ this.expandedKeys = C(this.rows, e, this.config, this.expandedKeys), this.requestRender();
484
585
  }
485
586
  // #endregion
486
587
  }
487
588
  export {
488
589
  F as TreePlugin,
489
- k as countNodes,
490
- b as detectTreeStructure,
491
- E as getMaxDepth,
492
- _ as inferChildrenField
590
+ T as countNodes,
591
+ m as detectTreeStructure,
592
+ k as getMaxDepth,
593
+ E as inferChildrenField
493
594
  };
494
595
  //# sourceMappingURL=index.js.map