@toolbox-web/grid 1.26.2 → 1.27.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 (114) hide show
  1. package/all.js +2 -2
  2. package/all.js.map +1 -1
  3. package/index.js +1 -1
  4. package/index.js.map +1 -1
  5. package/lib/core/grid.d.ts +64 -1
  6. package/lib/core/internal/diagnostics.d.ts +4 -3
  7. package/lib/core/internal/row-manager.d.ts +3 -1
  8. package/lib/core/plugin/base-plugin.d.ts +2 -2
  9. package/lib/core/types.d.ts +59 -3
  10. package/lib/features/registry.js.map +1 -1
  11. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +1 -1
  12. package/lib/plugins/clipboard/index.js.map +1 -1
  13. package/lib/plugins/column-virtualization/index.js.map +1 -1
  14. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +24 -5
  15. package/lib/plugins/context-menu/index.js.map +1 -1
  16. package/lib/plugins/editing/EditingPlugin.d.ts +1 -1
  17. package/lib/plugins/editing/index.js.map +1 -1
  18. package/lib/plugins/export/ExportPlugin.d.ts +1 -1
  19. package/lib/plugins/export/index.js.map +1 -1
  20. package/lib/plugins/filtering/index.d.ts +2 -2
  21. package/lib/plugins/filtering/index.js +1 -1
  22. package/lib/plugins/filtering/index.js.map +1 -1
  23. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
  24. package/lib/plugins/grouping-columns/grouping-columns.d.ts +18 -3
  25. package/lib/plugins/grouping-columns/index.d.ts +0 -1
  26. package/lib/plugins/grouping-columns/index.js +1 -1
  27. package/lib/plugins/grouping-columns/index.js.map +1 -1
  28. package/lib/plugins/grouping-columns/types.d.ts +1 -7
  29. package/lib/plugins/grouping-rows/index.d.ts +2 -1
  30. package/lib/plugins/grouping-rows/index.js +1 -1
  31. package/lib/plugins/grouping-rows/index.js.map +1 -1
  32. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +2 -0
  33. package/lib/plugins/master-detail/index.js +1 -1
  34. package/lib/plugins/master-detail/index.js.map +1 -1
  35. package/lib/plugins/master-detail/types.d.ts +20 -1
  36. package/lib/plugins/multi-sort/index.js.map +1 -1
  37. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +8 -1
  38. package/lib/plugins/pinned-columns/index.js +1 -1
  39. package/lib/plugins/pinned-columns/index.js.map +1 -1
  40. package/lib/plugins/pinned-columns/pinned-columns.d.ts +11 -1
  41. package/lib/plugins/pinned-rows/index.d.ts +1 -1
  42. package/lib/plugins/pinned-rows/index.js +1 -1
  43. package/lib/plugins/pinned-rows/index.js.map +1 -1
  44. package/lib/plugins/pinned-rows/types.d.ts +10 -3
  45. package/lib/plugins/pivot/PivotPlugin.d.ts +107 -1
  46. package/lib/plugins/pivot/index.d.ts +2 -1
  47. package/lib/plugins/pivot/index.js +1 -1
  48. package/lib/plugins/pivot/index.js.map +1 -1
  49. package/lib/plugins/print/index.js.map +1 -1
  50. package/lib/plugins/print/types.d.ts +0 -3
  51. package/lib/plugins/reorder-columns/ReorderPlugin.d.ts +19 -2
  52. package/lib/plugins/reorder-columns/index.js +1 -1
  53. package/lib/plugins/reorder-columns/index.js.map +1 -1
  54. package/lib/plugins/reorder-rows/index.d.ts +1 -1
  55. package/lib/plugins/reorder-rows/index.js.map +1 -1
  56. package/lib/plugins/responsive/ResponsivePlugin.d.ts +1 -1
  57. package/lib/plugins/responsive/index.js +1 -1
  58. package/lib/plugins/responsive/index.js.map +1 -1
  59. package/lib/plugins/selection/SelectionPlugin.d.ts +1 -1
  60. package/lib/plugins/selection/index.js +1 -1
  61. package/lib/plugins/selection/index.js.map +1 -1
  62. package/lib/plugins/selection/types.d.ts +3 -3
  63. package/lib/plugins/server-side/ServerSidePlugin.d.ts +6 -1
  64. package/lib/plugins/server-side/index.js +1 -1
  65. package/lib/plugins/server-side/index.js.map +1 -1
  66. package/lib/plugins/tree/TreePlugin.d.ts +116 -0
  67. package/lib/plugins/tree/index.d.ts +1 -1
  68. package/lib/plugins/tree/index.js +1 -1
  69. package/lib/plugins/tree/index.js.map +1 -1
  70. package/lib/plugins/tree/types.d.ts +16 -1
  71. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +1 -1
  72. package/lib/plugins/undo-redo/index.js.map +1 -1
  73. package/lib/plugins/undo-redo/types.d.ts +15 -3
  74. package/lib/plugins/visibility/VisibilityPlugin.d.ts +18 -5
  75. package/lib/plugins/visibility/index.js +1 -1
  76. package/lib/plugins/visibility/index.js.map +1 -1
  77. package/package.json +1 -1
  78. package/public.d.ts +2 -4
  79. package/themes/dg-theme-material.css +16 -4
  80. package/umd/grid.all.umd.js +1 -1
  81. package/umd/grid.all.umd.js.map +1 -1
  82. package/umd/grid.umd.js +1 -1
  83. package/umd/grid.umd.js.map +1 -1
  84. package/umd/plugins/clipboard.umd.js.map +1 -1
  85. package/umd/plugins/context-menu.umd.js.map +1 -1
  86. package/umd/plugins/editing.umd.js.map +1 -1
  87. package/umd/plugins/export.umd.js.map +1 -1
  88. package/umd/plugins/filtering.umd.js +1 -1
  89. package/umd/plugins/filtering.umd.js.map +1 -1
  90. package/umd/plugins/grouping-columns.umd.js +1 -1
  91. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  92. package/umd/plugins/grouping-rows.umd.js +1 -1
  93. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  94. package/umd/plugins/master-detail.umd.js +1 -1
  95. package/umd/plugins/master-detail.umd.js.map +1 -1
  96. package/umd/plugins/pinned-columns.umd.js +1 -1
  97. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  98. package/umd/plugins/pinned-rows.umd.js +1 -1
  99. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  100. package/umd/plugins/pivot.umd.js +1 -1
  101. package/umd/plugins/pivot.umd.js.map +1 -1
  102. package/umd/plugins/reorder-columns.umd.js +1 -1
  103. package/umd/plugins/reorder-columns.umd.js.map +1 -1
  104. package/umd/plugins/responsive.umd.js +1 -1
  105. package/umd/plugins/responsive.umd.js.map +1 -1
  106. package/umd/plugins/selection.umd.js +1 -1
  107. package/umd/plugins/selection.umd.js.map +1 -1
  108. package/umd/plugins/server-side.umd.js +1 -1
  109. package/umd/plugins/server-side.umd.js.map +1 -1
  110. package/umd/plugins/tree.umd.js +1 -1
  111. package/umd/plugins/tree.umd.js.map +1 -1
  112. package/umd/plugins/undo-redo.umd.js.map +1 -1
  113. package/umd/plugins/visibility.umd.js +1 -1
  114. package/umd/plugins/visibility.umd.js.map +1 -1
@@ -132,14 +132,130 @@ export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
132
132
  onHeaderClick(event: HeaderClickEvent): boolean;
133
133
  /** @internal */
134
134
  afterRender(): void;
135
+ /**
136
+ * Expand a specific tree node, revealing its children.
137
+ *
138
+ * If the node is already expanded, this is a no-op.
139
+ * Does **not** emit a `tree-expand` event (use {@link toggle} for event emission).
140
+ *
141
+ * @param key - The unique key of the node to expand (from {@link FlattenedTreeRow.key})
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * const tree = grid.getPluginByName('tree');
146
+ * tree.expand('documents'); // Expand a root node
147
+ * tree.expand('documents||reports'); // Expand a nested node
148
+ * ```
149
+ */
135
150
  expand(key: string): void;
151
+ /**
152
+ * Collapse a specific tree node, hiding its children.
153
+ *
154
+ * If the node is already collapsed, this is a no-op.
155
+ * Does **not** emit a `tree-expand` event (use {@link toggle} for event emission).
156
+ *
157
+ * @param key - The unique key of the node to collapse (from {@link FlattenedTreeRow.key})
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * const tree = grid.getPluginByName('tree');
162
+ * tree.collapse('documents');
163
+ * ```
164
+ */
136
165
  collapse(key: string): void;
166
+ /**
167
+ * Toggle the expanded state of a tree node.
168
+ *
169
+ * If the node is expanded it will be collapsed, and vice versa.
170
+ * Emits a `tree-state-change` plugin event with the updated expanded keys.
171
+ *
172
+ * @param key - The unique key of the node to toggle (from {@link FlattenedTreeRow.key})
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * const tree = grid.getPluginByName('tree');
177
+ * tree.toggle('documents'); // Expand if collapsed, collapse if expanded
178
+ * ```
179
+ */
137
180
  toggle(key: string): void;
181
+ /**
182
+ * Expand all tree nodes recursively.
183
+ *
184
+ * Every node with children will be expanded, revealing the full tree hierarchy.
185
+ * Emits a `tree-state-change` plugin event.
186
+ *
187
+ * @example
188
+ * ```ts
189
+ * const tree = grid.getPluginByName('tree');
190
+ * tree.expandAll();
191
+ * ```
192
+ */
138
193
  expandAll(): void;
194
+ /**
195
+ * Collapse all tree nodes.
196
+ *
197
+ * Every node will be collapsed, showing only root-level rows.
198
+ * Emits a `tree-state-change` plugin event.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * const tree = grid.getPluginByName('tree');
203
+ * tree.collapseAll();
204
+ * ```
205
+ */
139
206
  collapseAll(): void;
207
+ /**
208
+ * Check whether a specific tree node is currently expanded.
209
+ *
210
+ * @param key - The unique key of the node to check
211
+ * @returns `true` if the node is expanded, `false` otherwise
212
+ */
140
213
  isExpanded(key: string): boolean;
214
+ /**
215
+ * Get the keys of all currently expanded nodes.
216
+ *
217
+ * Returns a snapshot copy — mutating the returned array does not affect the tree state.
218
+ *
219
+ * @returns Array of expanded node keys
220
+ *
221
+ * @example
222
+ * ```ts
223
+ * const tree = grid.getPluginByName('tree');
224
+ * const keys = tree.getExpandedKeys();
225
+ * localStorage.setItem('treeState', JSON.stringify(keys));
226
+ * ```
227
+ */
141
228
  getExpandedKeys(): string[];
229
+ /**
230
+ * Get the flattened row model used for rendering.
231
+ *
232
+ * Returns a snapshot copy of the internal flattened tree rows, including
233
+ * hierarchy metadata (depth, hasChildren, isExpanded, parentKey).
234
+ *
235
+ * @returns Array of {@link FlattenedTreeRow} objects
236
+ */
142
237
  getFlattenedRows(): FlattenedTreeRow[];
238
+ /**
239
+ * Look up an original row data object by its tree key.
240
+ *
241
+ * @param key - The unique key of the node
242
+ * @returns The original row data, or `undefined` if not found
243
+ */
143
244
  getRowByKey(key: string): TreeRow | undefined;
245
+ /**
246
+ * Expand all ancestor nodes of the target key, revealing it in the tree.
247
+ *
248
+ * Useful for "scroll to node" or search-and-reveal scenarios where a deeply
249
+ * nested node needs to be made visible.
250
+ *
251
+ * @param key - The unique key of the node to reveal
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * const tree = grid.getPluginByName('tree');
256
+ * // Reveal a deeply nested node by expanding all its parents
257
+ * tree.expandToKey('root||child||grandchild');
258
+ * ```
259
+ */
144
260
  expandToKey(key: string): void;
145
261
  }
@@ -5,4 +5,4 @@
5
5
  * @module Plugins/Tree
6
6
  */
7
7
  export { TreePlugin } from './TreePlugin';
8
- export type { TreeConfig, TreeExpandDetail } from './types';
8
+ export type { FlattenedTreeRow, TreeConfig, TreeExpandDetail, TreeRow } from './types';
@@ -1,2 +1,2 @@
1
- function e(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function t(t,n,i,r){return`${e(i,r)} ${t}: ${n}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(t)}`}const n='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',i={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:n,filterActive:n,print:"🖨️"};class r{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(n),n.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}requestVirtualRefresh(){this.grid?.requestVirtualRefresh?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid?._hostElement}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...i,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),n=parseInt(t,10);if(!isNaN(n))return n}return 200}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}setIcon(e,t){"string"==typeof t?e.innerHTML=t:t instanceof HTMLElement&&(e.innerHTML="",e.appendChild(t.cloneNode(!0)))}warn(n,i){void 0!==i?console.warn(t(n,i,this.gridElement.id,this.name)):console.warn(`${e(this.gridElement.id,this.name)} ${n}`)}throwDiagnostic(e,n){throw new Error(t(e,n,this.gridElement.id,this.name))}}function s(e,t,n){return void 0!==e.id?String(e.id):n?`${n}-${t}`:String(t)}function a(e,t){const n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}function o(e,t,n=null,i=0){const r=t.childrenField??"children",a=/* @__PURE__ */new Set;for(let d=0;d<e.length;d++){const l=e[d],h=s(l,d,n),c=l[r];if(Array.isArray(c)&&c.length>0){a.add(h);const e=o(c,t,h,i+1);for(const t of e)a.add(t)}}return a}function d(e,t,n,i=null,r=0){const a=n.childrenField??"children";for(let o=0;o<e.length;o++){const l=e[o],h=s(l,o,i);if(h===t)return[h];const c=l[a];if(Array.isArray(c)&&c.length>0){const e=d(c,t,n,h,r+1);if(e)return[h,...e]}}return null}function l(e,t,n,i){const r=d(e,t,n);if(!r)return i;const s=new Set(i);for(let a=0;a<r.length-1;a++)s.add(r[a]);return s}function h(e,t="children"){if(!Array.isArray(e)||0===e.length)return!1;for(const n of e){if(!n)continue;const e=n[t];if(Array.isArray(e)&&e.length>0)return!0}return!1}class c extends r{static manifest={events:[{type:"tree-state-change",description:"Emitted when tree expansion state changes (toggle, expand all, collapse all)"}],queries:[{type:"canMoveRow",description:"Returns false for rows with children (parent nodes cannot be reordered)"}]};name="tree";styles="@layer tbw-plugins{tbw-grid .cell[data-field=__tbw_expander]{border-inline-end: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-inline-start: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}}}";get defaultConfig(){return{childrenField:"children",autoDetect:!0,defaultExpanded:!1,indentWidth:20,showExpandIcons:!0,animation:"slide"}}expandedKeys=/* @__PURE__ */new Set;initialExpansionDone=!1;flattenedRows=[];rowKeyMap=/* @__PURE__ */new Map;previousVisibleKeys=/* @__PURE__ */new Set;keysToAnimate=/* @__PURE__ */new Set;sortState=null;detach(){this.expandedKeys.clear(),this.initialExpansionDone=!1,this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),this.keysToAnimate.clear(),this.sortState=null}handleQuery(e){if("canMoveRow"===e.type){const t=e.context,n=this.config.childrenField??"children",i=t?.[n];if(Array.isArray(i)&&i.length>0)return!1}}get animationStyle(){return!!this.isAnimationEnabled&&(this.config.animation??"slide")}detect(e){if(!this.config.autoDetect)return!1;const t=e,n=this.config.childrenField??function(e){if(!Array.isArray(e)||0===e.length)return null;const t=["children","items","nodes","subRows","nested"];for(const n of e)if(n&&"object"==typeof n)for(const e of t){const t=n[e];if(Array.isArray(t)&&t.length>0)return e}return null}(t)??"children";return h(t,n)}processRows(e){const t=e;if(!h(t,this.config.childrenField??"children"))return this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),[...e];let n=this.withStableKeys(t);this.sortState&&(n=this.sortTree(n,this.sortState.field,this.sortState.direction)),this.config.defaultExpanded&&!this.initialExpansionDone&&(this.expandedKeys=o(n,this.config),this.initialExpansionDone=!0),this.flattenedRows=this.flattenTree(n,this.expandedKeys),this.rowKeyMap.clear(),this.keysToAnimate.clear();const i=/* @__PURE__ */new Set;for(const r of this.flattenedRows)this.rowKeyMap.set(r.key,r),i.add(r.key),!this.previousVisibleKeys.has(r.key)&&r.depth>0&&this.keysToAnimate.add(r.key);return this.previousVisibleKeys=i,this.flattenedRows.map(e=>({...e.data,__treeKey:e.key,__treeDepth:e.depth,__treeHasChildren:e.hasChildren,__treeExpanded:e.isExpanded}))}withStableKeys(e,t=null){const n=this.config.childrenField??"children";return e.map((e,i)=>{const r=e.__stableKey,s=void 0!==e.id?String(e.id):r??(t?`${t}-${i}`:String(i)),a=e[n],o=Array.isArray(a)&&a.length>0;return{...e,__stableKey:s,...o?{[n]:this.withStableKeys(a,s)}:{}}})}flattenTree(e,t,n=0){const i=this.config.childrenField??"children",r=[];for(const s of e){const e=s.__stableKey??String(s.id??"?"),a=s[i],o=Array.isArray(a)&&a.length>0,d=t.has(e);r.push({key:e,data:s,depth:n,hasChildren:o,isExpanded:d,parentKey:n>0&&e.substring(0,e.lastIndexOf("-"))||null}),o&&d&&r.push(...this.flattenTree(a,t,n+1))}return r}sortTree(e,t,n){const i=this.config.childrenField??"children";return[...e].sort((e,i)=>{const r=e[t],s=i[t];return null==r&&null==s?0:null==r?-1:null==s?1:r>s?n:r<s?-n:0}).map(e=>{const r=e[i];return Array.isArray(r)&&r.length>0?{...e,[i]:this.sortTree(r,t,n)}:e})}processColumns(e){if(0===this.flattenedRows.length)return[...e];const t=[...e];if(0===t.length)return t;const n=t[0],i=n.viewRenderer,r=()=>this.config,s=this.setIcon.bind(this),a=this.resolveIcon.bind(this);return t[0]={...n,viewRenderer:e=>{const{row:t,value:n}=e,{showExpandIcons:o=!0,indentWidth:d}=r(),l=t,h=l.__treeDepth??0,c=document.createElement("span");if(c.className="tree-cell-wrapper",c.style.setProperty("--tbw-tree-depth",String(h)),void 0!==d&&c.style.setProperty("--tbw-tree-indent-width",`${d}px`),o)if(l.__treeHasChildren){const e=document.createElement("span");e.className="tree-toggle"+(l.__treeExpanded?" expanded":""),s(e,a(l.__treeExpanded?"collapse":"expand")),e.setAttribute("data-tree-key",String(l.__treeKey??"")),c.appendChild(e)}else{const e=document.createElement("span");e.className="tree-spacer",c.appendChild(e)}const u=document.createElement("span");if(u.className="tree-content",i){const t=i(e);t instanceof Node?u.appendChild(t):"string"==typeof t&&(u.innerHTML=t)}else u.textContent=null!=n?String(n):"";return c.appendChild(u),c}},t}onCellClick(e){const t=e.originalEvent?.target;if(!t?.classList.contains("tree-toggle"))return!1;const n=t.getAttribute("data-tree-key");if(!n)return!1;const i=this.rowKeyMap.get(n);return!!i&&(this.expandedKeys=a(this.expandedKeys,n),this.emit("tree-expand",{key:n,row:i.data,expanded:this.expandedKeys.has(n),depth:i.depth}),this.requestRender(),!0)}onKeyDown(e){if(" "!==e.key)return;const t=this.grid._focusRow,n=this.flattenedRows[t];return n?.hasChildren?(e.preventDefault(),this.expandedKeys=a(this.expandedKeys,n.key),this.emit("tree-expand",{key:n.key,row:n.data,expanded:this.expandedKeys.has(n.key),depth:n.depth}),this.requestRenderWithFocus(),!0):void 0}onHeaderClick(e){if(0===this.flattenedRows.length||!e.column.sortable)return!1;const{field:t}=e.column;this.sortState&&this.sortState.field===t?1===this.sortState.direction?this.sortState={field:t,direction:-1}:this.sortState=null:this.sortState={field:t,direction:1};const n=this.grid;return void 0!==n._sortState&&(n._sortState=this.sortState?{...this.sortState}:null),this.emit("sort-change",{field:t,direction:this.sortState?.direction??0}),this.requestRender(),!0}afterRender(){const e=this.gridElement?.querySelector(".rows");if(!e)return;const t=this.animationStyle,n=!1!==t&&this.keysToAnimate.size>0,i="fade"===t?"tbw-tree-fade-in":"tbw-tree-slide-in";for(const r of e.querySelectorAll(".data-grid-row")){const e=r.querySelector(".cell[data-row]"),t=e?parseInt(e.getAttribute("data-row")??"-1",10):-1,s=this.flattenedRows[t];s?.hasChildren&&r.setAttribute("aria-expanded",String(s.isExpanded)),n&&s?.key&&this.keysToAnimate.has(s.key)&&(r.classList.add(i),r.addEventListener("animationend",()=>r.classList.remove(i),{once:!0}))}this.keysToAnimate.clear()}expand(e){this.expandedKeys.add(e),this.requestRender()}collapse(e){this.expandedKeys.delete(e),this.requestRender()}toggle(e){this.expandedKeys=a(this.expandedKeys,e),this.emitPluginEvent("tree-state-change",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}expandAll(){this.expandedKeys=o(this.rows,this.config),this.emitPluginEvent("tree-state-change",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}collapseAll(){this.expandedKeys=/* @__PURE__ */new Set,this.emitPluginEvent("tree-state-change",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}isExpanded(e){return this.expandedKeys.has(e)}getExpandedKeys(){return[...this.expandedKeys]}getFlattenedRows(){return[...this.flattenedRows]}getRowByKey(e){return this.rowKeyMap.get(e)?.data}expandToKey(e){this.expandedKeys=l(this.rows,e,this.config,this.expandedKeys),this.requestRender()}}export{c as TreePlugin};
1
+ function e(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function t(t,n,i,r){return`${e(i,r)} ${t}: ${n}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(t)}`}const n='<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>',i={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:n,filterActive:n,print:"🖨️"};class r{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const n=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(n),n.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}requestVirtualRefresh(){this.grid?.requestVirtualRefresh?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid?._hostElement}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...i,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),n=parseInt(t,10);if(!isNaN(n))return n}return 200}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}setIcon(e,t){"string"==typeof t?e.innerHTML=t:t instanceof HTMLElement&&(e.innerHTML="",e.appendChild(t.cloneNode(!0)))}warn(n,i){void 0!==i?console.warn(t(n,i,this.gridElement.id,this.name)):console.warn(`${e(this.gridElement.id,this.name)} ${n}`)}throwDiagnostic(e,n){throw new Error(t(e,n,this.gridElement.id,this.name))}}function s(e,t,n){return void 0!==e.id?String(e.id):n?`${n}-${t}`:String(t)}function a(e,t){const n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}function o(e,t,n=null,i=0){const r=t.childrenField??"children",a=/* @__PURE__ */new Set;for(let d=0;d<e.length;d++){const l=e[d],h=s(l,d,n),c=l[r];if(Array.isArray(c)&&c.length>0){a.add(h);const e=o(c,t,h,i+1);for(const t of e)a.add(t)}}return a}function d(e,t,n,i=null,r=0){const a=n.childrenField??"children";for(let o=0;o<e.length;o++){const l=e[o],h=s(l,o,i);if(h===t)return[h];const c=l[a];if(Array.isArray(c)&&c.length>0){const e=d(c,t,n,h,r+1);if(e)return[h,...e]}}return null}function l(e,t,n,i){const r=d(e,t,n);if(!r)return i;const s=new Set(i);for(let a=0;a<r.length-1;a++)s.add(r[a]);return s}function h(e,t="children"){if(!Array.isArray(e)||0===e.length)return!1;for(const n of e){if(!n)continue;const e=n[t];if(Array.isArray(e)&&e.length>0)return!0}return!1}class c extends r{static manifest={incompatibleWith:[{name:"groupingRows",reason:"Both plugins transform the entire row model. TreePlugin flattens nested hierarchies while GroupingRowsPlugin groups flat rows with synthetic headers. Use one approach per grid."},{name:"pivot",reason:"PivotPlugin replaces the entire row and column structure with aggregated pivot data. Tree hierarchy cannot coexist with pivot aggregation."},{name:"serverSide",reason:"TreePlugin requires the full hierarchy to flatten and manage expansion state. ServerSidePlugin lazy-loads rows in blocks and cannot provide nested children on demand."}],events:[{type:"tree-state-change",description:"Emitted when tree expansion state changes (toggle, expand all, collapse all)"}],queries:[{type:"canMoveRow",description:"Returns false for rows with children (parent nodes cannot be reordered)"}]};name="tree";styles="@layer tbw-plugins{tbw-grid .cell[data-field=__tbw_expander]{border-inline-end: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-inline-start: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}}}";get defaultConfig(){return{childrenField:"children",autoDetect:!0,defaultExpanded:!1,indentWidth:20,showExpandIcons:!0,animation:"slide"}}expandedKeys=/* @__PURE__ */new Set;initialExpansionDone=!1;flattenedRows=[];rowKeyMap=/* @__PURE__ */new Map;previousVisibleKeys=/* @__PURE__ */new Set;keysToAnimate=/* @__PURE__ */new Set;sortState=null;detach(){this.expandedKeys.clear(),this.initialExpansionDone=!1,this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),this.keysToAnimate.clear(),this.sortState=null}handleQuery(e){if("canMoveRow"===e.type){const t=e.context,n=this.config.childrenField??"children",i=t?.[n];if(Array.isArray(i)&&i.length>0)return!1}}get animationStyle(){return!!this.isAnimationEnabled&&(this.config.animation??"slide")}detect(e){if(!this.config.autoDetect)return!1;const t=e,n=this.config.childrenField??function(e){if(!Array.isArray(e)||0===e.length)return null;const t=["children","items","nodes","subRows","nested"];for(const n of e)if(n&&"object"==typeof n)for(const e of t){const t=n[e];if(Array.isArray(t)&&t.length>0)return e}return null}(t)??"children";return h(t,n)}processRows(e){const t=e;if(!h(t,this.config.childrenField??"children"))return this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),[...e];let n=this.withStableKeys(t);this.sortState&&(n=this.sortTree(n,this.sortState.field,this.sortState.direction)),this.config.defaultExpanded&&!this.initialExpansionDone&&(this.expandedKeys=o(n,this.config),this.initialExpansionDone=!0),this.flattenedRows=this.flattenTree(n,this.expandedKeys),this.rowKeyMap.clear(),this.keysToAnimate.clear();const i=/* @__PURE__ */new Set;for(const r of this.flattenedRows)this.rowKeyMap.set(r.key,r),i.add(r.key),!this.previousVisibleKeys.has(r.key)&&r.depth>0&&this.keysToAnimate.add(r.key);return this.previousVisibleKeys=i,this.flattenedRows.map(e=>({...e.data,__treeKey:e.key,__treeDepth:e.depth,__treeHasChildren:e.hasChildren,__treeExpanded:e.isExpanded}))}withStableKeys(e,t=null){const n=this.config.childrenField??"children";return e.map((e,i)=>{const r=e.__stableKey,s=void 0!==e.id?String(e.id):r??(t?`${t}-${i}`:String(i)),a=e[n],o=Array.isArray(a)&&a.length>0;return{...e,__stableKey:s,...o?{[n]:this.withStableKeys(a,s)}:{}}})}flattenTree(e,t,n=0){const i=this.config.childrenField??"children",r=[];for(const s of e){const e=s.__stableKey??String(s.id??"?"),a=s[i],o=Array.isArray(a)&&a.length>0,d=t.has(e);r.push({key:e,data:s,depth:n,hasChildren:o,isExpanded:d,parentKey:n>0&&e.substring(0,e.lastIndexOf("-"))||null}),o&&d&&r.push(...this.flattenTree(a,t,n+1))}return r}sortTree(e,t,n){const i=this.config.childrenField??"children";return[...e].sort((e,i)=>{const r=e[t],s=i[t];return null==r&&null==s?0:null==r?-1:null==s?1:r>s?n:r<s?-n:0}).map(e=>{const r=e[i];return Array.isArray(r)&&r.length>0?{...e,[i]:this.sortTree(r,t,n)}:e})}processColumns(e){if(0===this.flattenedRows.length)return[...e];const t=[...e];if(0===t.length)return t;const n=t[0],i=n.viewRenderer,r=()=>this.config,s=this.setIcon.bind(this),a=this.resolveIcon.bind(this);return t[0]={...n,viewRenderer:e=>{const{row:t,value:n}=e,{showExpandIcons:o=!0,indentWidth:d}=r(),l=t,h=l.__treeDepth??0,c=document.createElement("span");if(c.className="tree-cell-wrapper",c.style.setProperty("--tbw-tree-depth",String(h)),void 0!==d&&c.style.setProperty("--tbw-tree-indent-width",`${d}px`),o)if(l.__treeHasChildren){const e=document.createElement("span");e.className="tree-toggle"+(l.__treeExpanded?" expanded":""),s(e,a(l.__treeExpanded?"collapse":"expand")),e.setAttribute("data-tree-key",String(l.__treeKey??"")),c.appendChild(e)}else{const e=document.createElement("span");e.className="tree-spacer",c.appendChild(e)}const u=document.createElement("span");if(u.className="tree-content",i){const t=i(e);t instanceof Node?u.appendChild(t):"string"==typeof t&&(u.innerHTML=t)}else u.textContent=null!=n?String(n):"";return c.appendChild(u),c}},t}onCellClick(e){const t=e.originalEvent?.target;if(!t?.classList.contains("tree-toggle"))return!1;const n=t.getAttribute("data-tree-key");if(!n)return!1;const i=this.rowKeyMap.get(n);return!!i&&(this.expandedKeys=a(this.expandedKeys,n),this.emit("tree-expand",{key:n,row:i.data,expanded:this.expandedKeys.has(n),depth:i.depth}),this.requestRender(),!0)}onKeyDown(e){if(" "!==e.key)return;const t=this.grid._focusRow,n=this.flattenedRows[t];return n?.hasChildren?(e.preventDefault(),this.expandedKeys=a(this.expandedKeys,n.key),this.emit("tree-expand",{key:n.key,row:n.data,expanded:this.expandedKeys.has(n.key),depth:n.depth}),this.requestRenderWithFocus(),!0):void 0}onHeaderClick(e){if(0===this.flattenedRows.length||!e.column.sortable)return!1;const{field:t}=e.column;this.sortState&&this.sortState.field===t?1===this.sortState.direction?this.sortState={field:t,direction:-1}:this.sortState=null:this.sortState={field:t,direction:1};const n=this.grid;return void 0!==n._sortState&&(n._sortState=this.sortState?{...this.sortState}:null),this.emit("sort-change",{field:t,direction:this.sortState?.direction??0}),this.requestRender(),!0}afterRender(){const e=this.gridElement?.querySelector(".rows");if(!e)return;const t=this.animationStyle,n=!1!==t&&this.keysToAnimate.size>0,i="fade"===t?"tbw-tree-fade-in":"tbw-tree-slide-in";for(const r of e.querySelectorAll(".data-grid-row")){const e=r.querySelector(".cell[data-row]"),t=e?parseInt(e.getAttribute("data-row")??"-1",10):-1,s=this.flattenedRows[t];s?.hasChildren&&r.setAttribute("aria-expanded",String(s.isExpanded)),n&&s?.key&&this.keysToAnimate.has(s.key)&&(r.classList.add(i),r.addEventListener("animationend",()=>r.classList.remove(i),{once:!0}))}this.keysToAnimate.clear()}expand(e){this.expandedKeys.add(e),this.requestRender()}collapse(e){this.expandedKeys.delete(e),this.requestRender()}toggle(e){this.expandedKeys=a(this.expandedKeys,e),this.emitPluginEvent("tree-state-change",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}expandAll(){this.expandedKeys=o(this.rows,this.config),this.emitPluginEvent("tree-state-change",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}collapseAll(){this.expandedKeys=/* @__PURE__ */new Set,this.emitPluginEvent("tree-state-change",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}isExpanded(e){return this.expandedKeys.has(e)}getExpandedKeys(){return[...this.expandedKeys]}getFlattenedRows(){return[...this.flattenedRows]}getRowByKey(e){return this.rowKeyMap.get(e)?.data}expandToKey(e){this.expandedKeys=l(this.rows,e,this.config,this.expandedKeys),this.requestRender()}}export{c as TreePlugin};
2
2
  //# sourceMappingURL=index.js.map