@toolbox-web/grid 2.3.0 → 2.4.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 (102) hide show
  1. package/all.d.ts +1 -0
  2. package/all.js +2 -2
  3. package/all.js.map +1 -1
  4. package/index.js +1 -1
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts +2 -1
  7. package/lib/core/internal/diagnostics.d.ts +5 -1
  8. package/lib/core/internal/dom-builder.d.ts +0 -25
  9. package/lib/core/internal/drag-drop-registry.d.ts +66 -0
  10. package/lib/core/internal/render-scheduler.d.ts +9 -8
  11. package/lib/core/plugin/base-plugin.d.ts +23 -0
  12. package/lib/core/plugin/plugin-manager.d.ts +9 -0
  13. package/lib/core/types.d.ts +67 -46
  14. package/lib/features/registry.js.map +1 -1
  15. package/lib/features/reorder-rows.d.ts +3 -3
  16. package/lib/features/reorder-rows.js +1 -1
  17. package/lib/features/reorder-rows.js.map +1 -1
  18. package/lib/features/row-drag-drop.d.ts +9 -0
  19. package/lib/features/row-drag-drop.js +2 -0
  20. package/lib/features/row-drag-drop.js.map +1 -0
  21. package/lib/features/server-side.js.map +1 -1
  22. package/lib/plugins/clipboard/index.js +1 -1
  23. package/lib/plugins/clipboard/index.js.map +1 -1
  24. package/lib/plugins/column-virtualization/index.js +1 -1
  25. package/lib/plugins/column-virtualization/index.js.map +1 -1
  26. package/lib/plugins/context-menu/index.js +1 -1
  27. package/lib/plugins/context-menu/index.js.map +1 -1
  28. package/lib/plugins/editing/index.js +1 -1
  29. package/lib/plugins/editing/index.js.map +1 -1
  30. package/lib/plugins/export/ExportPlugin.d.ts +89 -0
  31. package/lib/plugins/export/index.d.ts +3 -2
  32. package/lib/plugins/export/index.js +1 -1
  33. package/lib/plugins/export/index.js.map +1 -1
  34. package/lib/plugins/export/types.d.ts +30 -0
  35. package/lib/plugins/filtering/index.js +1 -1
  36. package/lib/plugins/filtering/index.js.map +1 -1
  37. package/lib/plugins/grouping-columns/index.js +1 -1
  38. package/lib/plugins/grouping-columns/index.js.map +1 -1
  39. package/lib/plugins/grouping-rows/index.js +2 -2
  40. package/lib/plugins/grouping-rows/index.js.map +1 -1
  41. package/lib/plugins/master-detail/index.js +1 -1
  42. package/lib/plugins/master-detail/index.js.map +1 -1
  43. package/lib/plugins/multi-sort/index.js +1 -1
  44. package/lib/plugins/multi-sort/index.js.map +1 -1
  45. package/lib/plugins/pinned-columns/index.js +1 -1
  46. package/lib/plugins/pinned-columns/index.js.map +1 -1
  47. package/lib/plugins/pinned-rows/index.js +1 -1
  48. package/lib/plugins/pinned-rows/index.js.map +1 -1
  49. package/lib/plugins/pivot/index.js +1 -1
  50. package/lib/plugins/pivot/index.js.map +1 -1
  51. package/lib/plugins/print/index.js +1 -1
  52. package/lib/plugins/print/index.js.map +1 -1
  53. package/lib/plugins/reorder-columns/index.js +1 -1
  54. package/lib/plugins/reorder-columns/index.js.map +1 -1
  55. package/lib/plugins/reorder-rows/RowReorderPlugin.d.ts +14 -156
  56. package/lib/plugins/reorder-rows/index.d.ts +10 -4
  57. package/lib/plugins/reorder-rows/index.js +1 -1
  58. package/lib/plugins/reorder-rows/index.js.map +1 -1
  59. package/lib/plugins/reorder-rows/types.d.ts +9 -86
  60. package/lib/plugins/responsive/index.js +1 -1
  61. package/lib/plugins/responsive/index.js.map +1 -1
  62. package/lib/plugins/row-drag-drop/RowDragDropPlugin.d.ts +106 -0
  63. package/lib/plugins/row-drag-drop/index.d.ts +9 -0
  64. package/lib/plugins/row-drag-drop/index.js +2 -0
  65. package/lib/plugins/row-drag-drop/index.js.map +1 -0
  66. package/lib/plugins/row-drag-drop/types.d.ts +255 -0
  67. package/lib/plugins/selection/index.js +1 -1
  68. package/lib/plugins/selection/index.js.map +1 -1
  69. package/lib/plugins/server-side/ServerSidePlugin.d.ts +13 -0
  70. package/lib/plugins/server-side/datasource-types.d.ts +54 -7
  71. package/lib/plugins/server-side/datasource.d.ts +10 -2
  72. package/lib/plugins/server-side/index.d.ts +1 -1
  73. package/lib/plugins/server-side/index.js +1 -1
  74. package/lib/plugins/server-side/index.js.map +1 -1
  75. package/lib/plugins/server-side/types.d.ts +1 -1
  76. package/lib/plugins/shared/drag-drop-protocol.d.ts +98 -0
  77. package/lib/plugins/tooltip/index.js +1 -1
  78. package/lib/plugins/tooltip/index.js.map +1 -1
  79. package/lib/plugins/tree/TreePlugin.d.ts +19 -6
  80. package/lib/plugins/tree/index.js +1 -1
  81. package/lib/plugins/tree/index.js.map +1 -1
  82. package/lib/plugins/undo-redo/index.js +1 -1
  83. package/lib/plugins/undo-redo/index.js.map +1 -1
  84. package/lib/plugins/visibility/index.js +1 -1
  85. package/lib/plugins/visibility/index.js.map +1 -1
  86. package/package.json +1 -1
  87. package/umd/grid.all.umd.js +1 -1
  88. package/umd/grid.all.umd.js.map +1 -1
  89. package/umd/grid.umd.js +1 -1
  90. package/umd/grid.umd.js.map +1 -1
  91. package/umd/plugins/export.umd.js +1 -1
  92. package/umd/plugins/export.umd.js.map +1 -1
  93. package/umd/plugins/reorder-rows.umd.js +1 -1
  94. package/umd/plugins/reorder-rows.umd.js.map +1 -1
  95. package/umd/plugins/row-drag-drop.umd.js +2 -0
  96. package/umd/plugins/row-drag-drop.umd.js.map +1 -0
  97. package/umd/plugins/selection.umd.js +1 -1
  98. package/umd/plugins/selection.umd.js.map +1 -1
  99. package/umd/plugins/server-side.umd.js +1 -1
  100. package/umd/plugins/server-side.umd.js.map +1 -1
  101. package/umd/plugins/tree.umd.js +1 -1
  102. package/umd/plugins/tree.umd.js.map +1 -1
@@ -65,6 +65,7 @@ import { FlattenedTreeRow, TreeConfig, TreeRow } from './types';
65
65
  * @internal Extends BaseGridPlugin
66
66
  */
67
67
  export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
68
+ #private;
68
69
  static readonly manifest: PluginManifest;
69
70
  /**
70
71
  * Optional dependency on MultiSort for coordinated sorting.
@@ -112,10 +113,6 @@ export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
112
113
  detect(rows: readonly unknown[]): boolean;
113
114
  /** @internal */
114
115
  processRows(rows: readonly unknown[]): TreeRow[];
115
- /** Assign stable keys to rows (preserves key across sort operations) */
116
- private withStableKeys;
117
- /** Flatten tree using stable keys */
118
- private flattenTree;
119
116
  /**
120
117
  * Request lazy children for a node via ServerSide's `datasource:fetch-children` query.
121
118
  * Called when expanding a node whose children are not yet embedded (lazy indicator only).
@@ -128,8 +125,6 @@ export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
128
125
  * This follows the same pattern as GroupingRowsPlugin.resolveGroupSortDirections.
129
126
  */
130
127
  private resolveEffectiveSortState;
131
- /** Sort tree recursively, keeping children with parents */
132
- private sortTree;
133
128
  /** @internal */
134
129
  processColumns(columns: readonly ColumnConfig[]): ColumnConfig[];
135
130
  /** @internal */
@@ -243,6 +238,24 @@ export declare class TreePlugin extends BaseGridPlugin<TreeConfig> {
243
238
  * @returns Array of {@link FlattenedTreeRow} objects
244
239
  */
245
240
  getFlattenedRows(): FlattenedTreeRow[];
241
+ /**
242
+ * Get tree metadata (depth, key, hasChildren, isExpanded, parentKey) for a
243
+ * specific row reference. Returns `undefined` if the row is not part of the
244
+ * currently-flattened tree (e.g. collapsed under a parent or never processed).
245
+ *
246
+ * Tree metadata lives in a parallel WeakMap keyed by row identity \u2014 it is
247
+ * NOT stored on the row object itself. This preserves the invariant that
248
+ * `_rows[i]` IS the user's source row reference, so `grid.updateRow(s)`
249
+ * mutations survive the next ROWS-phase rebuild.
250
+ *
251
+ * @example
252
+ * ```ts
253
+ * const tree = grid.getPluginByName('tree');
254
+ * const meta = tree.getRowMeta(grid.rows[0]);
255
+ * console.log(meta?.depth, meta?.hasChildren);
256
+ * ```
257
+ */
258
+ getRowMeta(row: TreeRow): FlattenedTreeRow | undefined;
246
259
  /**
247
260
  * Look up an original row data object by its tree key.
248
261
  *
@@ -1,2 +1,2 @@
1
- const e="expanded",t="tree-toggle";function r(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function n(e,t,n,i){return`${r(n,i)} ${e}: ${t}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(e)}`}const i="__otorp__|__retteGenifed__|__retteSenifed__|rotcurtsnoc|wodniw|sihTlabolg|labolg|ssecorp|noitcnuF|tropmi|lave|tcelfeR|yxorP|rorrE|stnemugra|tnemucod|noitacol|eikooc|egarotSlacol|egarotSnoisses|BDdexedni|hctef|tseuqeRpttHLMX|tekcoSbeW|rekroW|rekroWderahS|rekroWecivreS|renepo|tnerap|pot|semarf|fles".split("|").map(e=>e.split("").reverse().join(""));new RegExp(`__(proto|defineGetter|defineSetter)|${i.slice(3).join("|")}|this\\b`);const s=new Set("script|iframe|object|embed|form|input|button|textarea|select|link|meta|base|style|template|slot|portal|frame|frameset|applet|noscript|noembed|plaintext|xmp|listing".split("|")),o=/^on\w+$/i,a=new Set("href|src|action|formaction|data|srcdoc|xlink:href|poster|srcset".split("|")),d=/^\s*(javascript|vbscript|data|blob):/i;function l(e){if(!e||"string"!=typeof e)return"";if(-1===e.indexOf("<"))return e;const t=document.createElement("template");return t.innerHTML=e,function(e){const t=[],r=e.querySelectorAll("*");for(const n of r){const e=n.tagName.toLowerCase();if(s.has(e)){t.push(n);continue}if("svg"===e||"http://www.w3.org/2000/svg"===n.namespaceURI){if(Array.from(n.attributes).some(e=>o.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(n);continue}}const r=[];for(const t of n.attributes){const e=t.name.toLowerCase();o.test(e)?r.push(t.name):(a.has(e)&&d.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&r.push(t.name)}r.forEach(e=>n.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}const c='<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>',h={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:c,filterActive:c,print:"🖨️"};class u{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 r=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(r),r.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)}broadcast(e,t){this.emitPluginEvent(e,t),this.emit(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{...h,...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(),r=parseInt(t,10);if(!isNaN(r))return r}return 200}setIcon(e,t,r){e.dataset.icon=t.replace(/([A-Z])/g,"-$1").toLowerCase(),"collapse"===t?e.dataset.expanded="":"expand"===t&&delete e.dataset.expanded;const n=this.#t(t,r);void 0!==n?"string"==typeof n?e.innerHTML=l(n):n instanceof HTMLElement&&(e.innerHTML="",e.appendChild(n.cloneNode(!0))):e.innerHTML=""}#t(e,t){return void 0!==t?t:this.grid?.gridConfig?.icons?.[e]}updateSortIndicator(e,t){e.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();const r=document.createElement("span");r.setAttribute("part","sort-indicator"),r.className="sort-indicator",t?(e.setAttribute("aria-sort","asc"===t?"ascending":"descending"),e.setAttribute("data-sort",t),this.setIcon(r,"asc"===t?"sortAsc":"sortDesc")):(e.setAttribute("aria-sort","none"),e.removeAttribute("data-sort"),this.setIcon(r,"sortNone"));const n=e.querySelector(".tbw-filter-btn")??e.querySelector(".resize-handle");return n?e.insertBefore(r,n):e.appendChild(r),r}warn(e,t){void 0!==t?console.warn(n(e,t,this.gridElement.id,this.name)):console.warn(`${r(this.gridElement.id,this.name)} ${e}`)}throwDiagnostic(e,t){throw new Error(n(e,t,this.gridElement.id,this.name))}}function p(e,t,r){return void 0!==e.id?String(e.id):r?`${r}-${t}`:String(t)}function g(e,t){const r=new Set(e);return r.has(t)?r.delete(t):r.add(t),r}function f(e,t,r=null,n=0){const i=t.childrenField??"children",s=/* @__PURE__ */new Set;for(let o=0;o<e.length;o++){const a=e[o],d=p(a,o,r),l=a[i];if(Array.isArray(l)&&l.length>0){s.add(d);const e=f(l,t,d,n+1);for(const t of e)s.add(t)}}return s}function y(e,t,r,n=null,i=0){const s=r.childrenField??"children";for(let o=0;o<e.length;o++){const a=e[o],d=p(a,o,n);if(d===t)return[d];const l=a[s];if(Array.isArray(l)&&l.length>0){const e=y(l,t,r,d,i+1);if(e)return[d,...e]}}return null}function w(e,t,r,n){const i=y(e,t,r);if(!i)return n;const s=new Set(n);for(let o=0;o<i.length-1;o++)s.add(i[o]);return s}function m(e,t){const r=Math.min(t,e.length-1);if(r<0)return 0;let n=r;for(;n>0&&e[n].depth>0;)n--;let i=0;for(let s=0;s<=n;s++)0===e[s].depth&&i++;return i-1}function b(e,t="children"){if(!Array.isArray(e)||0===e.length)return!1;for(const r of e){if(!r)continue;const e=r[t];if(Array.isArray(e)&&e.length>0)return!0;if(null!=e&&!Array.isArray(e)&&e)return!0}return!1}class x extends u{static manifest={modifiesRowStructure:!0,hookPriority:{processRows:10},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."}],events:[{type:"tree-expand",description:"Emitted when tree expansion state changes (toggle, expand all, collapse all). Broadcast to both DOM consumers and plugin bus."}],queries:[{type:"canMoveRow",description:"Returns false for rows with children (parent nodes cannot be reordered)"},{type:"datasource:viewport-mapping",description:"Translates flat viewport row indices to top-level node indices for ServerSide pagination."}]};static dependencies=[{name:"multiSort",required:!1,reason:"Queries sort model for coordinated tree sorting"},{name:"serverSide",required:!1,reason:"Consumes datasource events for lazy-loaded tree data"}];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;vertical-align:middle;overflow:visible;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);height: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}}tbw-grid.tbw-tree-loading .rows-viewport:after{content:"";display:block;height:2px;background:linear-gradient(90deg,transparent,var(--tbw-color-accent, #2563eb),transparent);animation:tbw-tree-loading-bar 1s ease-in-out infinite;position:sticky;bottom:0;left:0;right:0}@keyframes tbw-tree-loading-bar{0%{transform:translate(-100%)}to{transform:translate(100%)}}}';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;loadingKeys=/* @__PURE__ */new Set;originalTreeColumnRenderer;wrappedTreeColumnField;detach(){this.expandedKeys.clear(),this.initialExpansionDone=!1,this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),this.keysToAnimate.clear(),this.sortState=null,this.loadingKeys.clear(),this.originalTreeColumnRenderer=void 0,this.wrappedTreeColumnField=void 0}handleQuery(e){if("canMoveRow"===e.type){const t=e.context,r=this.config.childrenField??"children",n=t?.[r];if(Array.isArray(n)&&n.length>0)return!1}if("datasource:viewport-mapping"===e.type){const{viewportStart:t,viewportEnd:r}=e.context;if(0===this.flattenedRows.length)return;return{startNode:m(this.flattenedRows,t),endNode:m(this.flattenedRows,r)+1,totalLoadedNodes:function(e){let t=0;for(const r of e)0===r.depth&&t++;return t}(this.flattenedRows)}}}attach(e){super.attach(e),this.on("datasource:data",e=>{const t=e;t.claimed||(t.claimed=!0)}),this.on("datasource:children",e=>{const t=e;if("tree"!==t.context?.source)return;t.claimed=!0;const r=t.context.parentNode;if(r){r[this.config.childrenField??"children"]=t.rows;const e=r.__stableKey??String(r.id??"?");this.loadingKeys.delete(e),this.requestRender()}})}get animationStyle(){return!!this.isAnimationEnabled&&(this.config.animation??"slide")}detect(e){if(!this.config.autoDetect)return!1;const t=e,r=this.config.childrenField??function(e){if(!Array.isArray(e)||0===e.length)return null;const t=["children","items","nodes","subRows","nested"];for(const r of e)if(r&&"object"==typeof r)for(const e of t){const t=r[e];if(Array.isArray(t)&&t.length>0)return e}return null}(t)??"children";return b(t,r)}processRows(e){const t=this.config.childrenField??"children",r=e;if(0===r.length||!b(r,t))return this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),[...e];let n=this.withStableKeys(r);const i=this.resolveEffectiveSortState();i&&(n=this.sortTree(n,i.field,i.direction)),this.config.defaultExpanded&&!this.initialExpansionDone&&(this.expandedKeys=f(n,this.config),this.initialExpansionDone=!0),this.flattenedRows=this.flattenTree(n,this.expandedKeys),this.rowKeyMap.clear(),this.keysToAnimate.clear();const s=/* @__PURE__ */new Set;for(const o of this.flattenedRows)this.rowKeyMap.set(o.key,o),s.add(o.key),!this.previousVisibleKeys.has(o.key)&&o.depth>0&&this.keysToAnimate.add(o.key);return this.previousVisibleKeys=s,this.flattenedRows.map(e=>({...e.data,__treeKey:e.key,__treeDepth:e.depth,__treeHasChildren:e.hasChildren,__treeExpanded:e.isExpanded}))}withStableKeys(e,t=null){const r=this.config.childrenField??"children";return e.map((e,n)=>{const i=e.__stableKey,s=void 0!==e.id?String(e.id):i??(t?`${t}-${n}`:String(n)),o=e[r],a=Array.isArray(o)&&o.length>0;return{...e,__stableKey:s,...a?{[r]:this.withStableKeys(o,s)}:{}}})}flattenTree(e,t,r=0){const n=this.config.childrenField??"children",i=[];for(const s of e){const e=s.__stableKey??String(s.id??"?"),o=s[n],a=Array.isArray(o)&&o.length>0,d=null!=o&&!Array.isArray(o)&&!!o,l=a||d,c=t.has(e);i.push({key:e,data:s,depth:r,hasChildren:l,isExpanded:c,parentKey:r>0&&e.substring(0,e.lastIndexOf("-"))||null}),a&&c&&i.push(...this.flattenTree(o,t,r+1))}return i}requestLazyChildren(e){if(this.loadingKeys.has(e.key))return;const t=this.config.childrenField??"children",r=e.data[t];if(Array.isArray(r)&&r.length>0)return;const n=this.grid?.query?.("datasource:is-active",null);n&&(this.loadingKeys.add(e.key),this.grid.query("datasource:fetch-children",{context:{source:"tree",parentNode:e.data,nodePath:[e.key]}}))}resolveEffectiveSortState(){const e=this.grid?.query?.("sort:get-model",null);if(Array.isArray(e)&&e.length>0){const t=e[0];if(Array.isArray(t)&&t.length>0)return{field:t[0].field,direction:"desc"===t[0].direction?-1:1}}return this.sortState}sortTree(e,t,r){const n=this.config.childrenField??"children";return[...e].sort((e,n)=>{const i=e[t],s=n[t];return null==i&&null==s?0:null==i?-1:null==s?1:i>s?r:i<s?-r:0}).map(e=>{const i=e[n];return Array.isArray(i)&&i.length>0?{...e,[n]:this.sortTree(i,t,r)}:e})}processColumns(r){if(0===this.flattenedRows.length)return[...r];const n=[...r];if(0===n.length)return n;const{treeColumn:i}=this.config;let s=0;if(i){const e=n.findIndex(e=>e.field===i);e>=0&&(s=e)}const o=n[s],a=o.field;this.wrappedTreeColumnField!==a&&(this.originalTreeColumnRenderer=o.viewRenderer,this.wrappedTreeColumnField=a);const d=this.originalTreeColumnRenderer,l=()=>this.config,c=this.setIcon.bind(this);return n[s]={...o,viewRenderer:r=>{const{row:n,value:i}=r,{showExpandIcons:s=!0,indentWidth:o}=l(),a=n,h=a.__treeDepth??0,u=document.createElement("span");if(u.className="tree-cell-wrapper",u.style.setProperty("--tbw-tree-depth",String(h)),void 0!==o&&u.style.setProperty("--tbw-tree-indent-width",`${o}px`),s)if(a.__treeHasChildren){const r=document.createElement("span");r.className=`${t}${a.__treeExpanded?` ${e}`:""}`,c(r,a.__treeExpanded?"collapse":"expand"),r.setAttribute("data-tree-key",String(a.__treeKey??"")),u.appendChild(r)}else{const e=document.createElement("span");e.className="tree-spacer",u.appendChild(e)}const p=document.createElement("span");if(p.className="tree-content",d){const e=d(r);e instanceof Node?p.appendChild(e):"string"==typeof e&&(p.innerHTML=e)}else p.textContent=null!=i?String(i):"";return u.appendChild(p),u}},n}onCellClick(e){const r=e.originalEvent?.target;if(!r?.classList.contains(t))return!1;const n=r.getAttribute("data-tree-key");if(!n)return!1;const i=this.rowKeyMap.get(n);return!!i&&(this.expandedKeys=g(this.expandedKeys,n),this.expandedKeys.has(n)&&this.requestLazyChildren(i),this.broadcast("tree-expand",{key:n,row:i.data,expanded:this.expandedKeys.has(n),depth:i.depth,expandedKeys:[...this.expandedKeys]}),this.requestRender(),!0)}onKeyDown(e){if(" "!==e.key)return;const t=this.grid._focusRow,r=this.flattenedRows[t];return r?.hasChildren?(e.preventDefault(),this.expandedKeys=g(this.expandedKeys,r.key),this.expandedKeys.has(r.key)&&this.requestLazyChildren(r),this.broadcast("tree-expand",{key:r.key,row:r.data,expanded:this.expandedKeys.has(r.key),depth:r.depth,expandedKeys:[...this.expandedKeys]}),this.requestRenderWithFocus(),!0):void 0}onHeaderClick(e){if(0===this.flattenedRows.length||!e.column.sortable)return!1;const t=this.grid?.query?.("sort:get-model",null);if(Array.isArray(t)&&t.length>0)return!1;const{field:r}=e.column;this.sortState&&this.sortState.field===r?1===this.sortState.direction?this.sortState={field:r,direction:-1}:this.sortState=null:this.sortState={field:r,direction:1};const n=this.grid;return void 0!==n._sortState&&(n._sortState=this.sortState?{...this.sortState}:null),this.broadcast("sort-change",{field:r,direction:this.sortState?.direction??0}),this.requestRender(),!0}afterRender(){const e=this.gridElement?.querySelector(".rows");if(!e)return;const t=this.animationStyle,r=!1!==t&&this.keysToAnimate.size>0,n="fade"===t?"tbw-tree-fade-in":"tbw-tree-slide-in";for(const i of e.querySelectorAll(".data-grid-row")){const e=i.querySelector(".cell[data-row]"),t=e?parseInt(e.getAttribute("data-row")??"-1",10):-1,s=this.flattenedRows[t];s?.hasChildren&&i.setAttribute("aria-expanded",String(s.isExpanded)),r&&s?.key&&this.keysToAnimate.has(s.key)&&(i.classList.add(n),i.addEventListener("animationend",()=>i.classList.remove(n),{once:!0}))}this.keysToAnimate.clear()}expand(e){this.expandedKeys.add(e);const t=this.rowKeyMap.get(e);t&&this.requestLazyChildren(t),this.requestRender()}collapse(e){this.expandedKeys.delete(e),this.requestRender()}toggle(e){this.expandedKeys=g(this.expandedKeys,e);const t=this.rowKeyMap.get(e);t?(this.expandedKeys.has(e)&&this.requestLazyChildren(t),this.broadcast("tree-expand",{key:e,row:t.data,expanded:this.expandedKeys.has(e),depth:t.depth,expandedKeys:[...this.expandedKeys]})):this.emitPluginEvent("tree-expand",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}expandAll(){this.expandedKeys=f(this.rows,this.config),this.emitPluginEvent("tree-expand",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}collapseAll(){this.expandedKeys=/* @__PURE__ */new Set,this.emitPluginEvent("tree-expand",{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=w(this.rows,e,this.config,this.expandedKeys),this.requestRender()}}export{x as TreePlugin};
1
+ const e="expanded",t="tree-toggle",n={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:"",filterActive:"",print:"🖨️"};function r(e,t){return`[tbw-grid${e?`#${e}`:""}${t?`:${t}`:""}]`}function i(e,t,n,i){return`${r(n,i)} ${e}: ${t}\n\n → More info: ${function(e){return`https://toolboxjs.com/grid/errors#${e.toLowerCase()}`}(e)}`}const s="__otorp__|__retteGenifed__|__retteSenifed__|rotcurtsnoc|wodniw|sihTlabolg|labolg|ssecorp|noitcnuF|tropmi|lave|tcelfeR|yxorP|rorrE|stnemugra|tnemucod|noitacol|eikooc|egarotSlacol|egarotSnoisses|BDdexedni|hctef|tseuqeRpttHLMX|tekcoSbeW|rekroW|rekroWderahS|rekroWecivreS|renepo|tnerap|pot|semarf|fles".split("|").map(e=>e.split("").reverse().join(""));new RegExp(`__(proto|defineGetter|defineSetter)|${s.slice(3).join("|")}|this\\b`);const o=new Set("script|iframe|object|embed|form|input|button|textarea|select|link|meta|base|style|template|slot|portal|frame|frameset|applet|noscript|noembed|plaintext|xmp|listing".split("|")),a=/^on\w+$/i,d=new Set("href|src|action|formaction|data|srcdoc|xlink:href|poster|srcset".split("|")),l=/^\s*(javascript|vbscript|data|blob):/i;function c(e){if(!e||"string"!=typeof e)return"";if(-1===e.indexOf("<"))return e;const t=document.createElement("template");return t.innerHTML=e,function(e){const t=[],n=e.querySelectorAll("*");for(const r of n){const e=r.tagName.toLowerCase();if(o.has(e)){t.push(r);continue}if("svg"===e||"http://www.w3.org/2000/svg"===r.namespaceURI){if(Array.from(r.attributes).some(e=>a.test(e.name)||"href"===e.name||"xlink:href"===e.name)){t.push(r);continue}}const n=[];for(const t of r.attributes){const e=t.name.toLowerCase();a.test(e)?n.push(t.name):(d.has(e)&&l.test(t.value)||"style"===e&&/expression\s*\(|javascript:|behavior\s*:/i.test(t.value))&&n.push(t.name)}n.forEach(e=>r.removeAttribute(e))}t.forEach(e=>e.remove())}(t.content),t.innerHTML}class h{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}mergeConfigsFrom(e){if(0===e.length)return;const t={...this.userConfig},n={};for(const r of Object.keys(t))n[r]=this;for(const r of e){const e=r.userConfig;for(const[s,o]of Object.entries(e)){if(void 0===o)continue;if(!(s in t)){t[s]=o,n[s]=r;continue}if(t[s]===o)continue;const e=n[s]?.constructor.name??this.constructor.name,a=r.constructor.name,d=i("TBW025",`Cannot merge plugin configs for "${this.name}": conflicting value for "${s}" supplied by both ${e} and ${a}. Pass the option on a single instance, or remove the duplicate.`,void 0,this.name);throw new Error(d)}}Object.assign(this.userConfig,t)}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)}broadcast(e,t){this.emitPluginEvent(e,t),this.emit(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{...n,...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}setIcon(e,t,n){e.dataset.icon=t.replace(/([A-Z])/g,"-$1").toLowerCase(),"collapse"===t?e.dataset.expanded="":"expand"===t&&delete e.dataset.expanded;const r=this.#t(t,n);void 0!==r?"string"==typeof r?e.innerHTML=c(r):r instanceof HTMLElement&&(e.innerHTML="",e.appendChild(r.cloneNode(!0))):e.innerHTML=""}#t(e,t){return void 0!==t?t:this.grid?.gridConfig?.icons?.[e]}updateSortIndicator(e,t){e.querySelector('[part~="sort-indicator"], .sort-indicator')?.remove();const n=document.createElement("span");n.setAttribute("part","sort-indicator"),n.className="sort-indicator",t?(e.setAttribute("aria-sort","asc"===t?"ascending":"descending"),e.setAttribute("data-sort",t),this.setIcon(n,"asc"===t?"sortAsc":"sortDesc")):(e.setAttribute("aria-sort","none"),e.removeAttribute("data-sort"),this.setIcon(n,"sortNone"));const r=e.querySelector(".tbw-filter-btn")??e.querySelector(".resize-handle");return r?e.insertBefore(n,r):e.appendChild(n),n}warn(e,t){void 0!==t?console.warn(i(e,t,this.gridElement.id,this.name)):console.warn(`${r(this.gridElement.id,this.name)} ${e}`)}throwDiagnostic(e,t){throw new Error(i(e,t,this.gridElement.id,this.name))}}const u=/* @__PURE__ */new WeakMap;function f(e,t,n=-1){if(!t.valueAccessor)return e?.[t.field];if("object"!=typeof e||null===e)return t.valueAccessor({row:e,column:t,rowIndex:n});const r=t.field;let i=u.get(e);if(i){if(i.has(r))return i.get(r)}else i=/* @__PURE__ */new Map,u.set(e,i);const s=t.valueAccessor({row:e,column:t,rowIndex:n});return i.set(r,s),s}function p(e,t,n){const r=n.find(e=>e.field===t.field),i=r?.sortComparator,{field:s,direction:o}=t,a=[...e];return i?r?.valueAccessor?a.sort((e,t)=>i(f(e,r),f(t,r),e,t)*o):a.sort((e,t)=>i(e[s],t[s],e,t)*o):r?.valueAccessor?function(e,t,n){e.sort((e,r)=>{const i=g(e,r);if(0!==i)return i;const s=f(e,t),o=f(r,t);return null==s&&null==o?0:null==s?-n:null==o||s>o?n:s<o?-n:0})}(a,r,o):function(e,t,n){e.sort((e,r)=>{const i=g(e,r);if(0!==i)return i;const s=e[t],o=r[t];return null==s&&null==o?0:null==s?-n:null==o||s>o?n:s<o?-n:0})}(a,s,o),a}function g(e,t){const n=!0===e?.__loading;return n===(!0===t?.__loading)?0:n?1:-1}function y(e,t,n){return void 0!==e.id?String(e.id):n?`${n}-${t}`:String(t)}function w(e,t){const n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}function m(e,t,n=null,r=0){const i=t.childrenField??"children",s=/* @__PURE__ */new Set;for(let o=0;o<e.length;o++){const a=e[o],d=y(a,o,n),l=a[i];if(Array.isArray(l)&&l.length>0){s.add(d);const e=m(l,t,d,r+1);for(const t of e)s.add(t)}}return s}function b(e,t,n,r=null,i=0){const s=n.childrenField??"children";for(let o=0;o<e.length;o++){const a=e[o],d=y(a,o,r);if(d===t)return[d];const l=a[s];if(Array.isArray(l)&&l.length>0){const e=b(l,t,n,d,i+1);if(e)return[d,...e]}}return null}function x(e,t,n,r){const i=b(e,t,n);if(!i)return r;const s=new Set(r);for(let o=0;o<i.length-1;o++)s.add(i[o]);return s}function v(e,t){const n=Math.min(t,e.length-1);if(n<0)return 0;let r=n;for(;r>0&&e[r].depth>0;)r--;let i=0;for(let s=0;s<=r;s++)0===e[s].depth&&i++;return i-1}function S(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;if(null!=e&&!Array.isArray(e)&&e)return!0}return!1}class R extends h{static manifest={modifiesRowStructure:!0,hookPriority:{processRows:10},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."}],events:[{type:"tree-expand",description:"Emitted when tree expansion state changes (toggle, expand all, collapse all). Broadcast to both DOM consumers and plugin bus."}],queries:[{type:"canMoveRow",description:"Returns false for rows with children (parent nodes cannot be reordered)"},{type:"datasource:viewport-mapping",description:"Translates flat viewport row indices to top-level node indices for ServerSide pagination."}]};static dependencies=[{name:"multiSort",required:!1,reason:"Queries sort model for coordinated tree sorting"},{name:"serverSide",required:!1,reason:"Consumes datasource events for lazy-loaded tree data"}];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;vertical-align:middle;overflow:visible;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);height: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}}tbw-grid.tbw-tree-loading .rows-viewport:after{content:"";display:block;height:2px;background:linear-gradient(90deg,transparent,var(--tbw-color-accent, #2563eb),transparent);animation:tbw-tree-loading-bar 1s ease-in-out infinite;position:sticky;bottom:0;left:0;right:0}@keyframes tbw-tree-loading-bar{0%{transform:translate(-100%)}to{transform:translate(100%)}}}';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;loadingKeys=/* @__PURE__ */new Set;#n=/* @__PURE__ */new WeakMap;#r=/* @__PURE__ */new WeakMap;originalTreeColumnRenderer;wrappedTreeColumnField;detach(){this.expandedKeys.clear(),this.initialExpansionDone=!1,this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),this.keysToAnimate.clear(),this.sortState=null,this.loadingKeys.clear(),this.originalTreeColumnRenderer=void 0,this.wrappedTreeColumnField=void 0}handleQuery(e){if("canMoveRow"===e.type){const t=e.context,n=this.config.childrenField??"children",r=t?.[n];if(Array.isArray(r)&&r.length>0)return!1}if("datasource:viewport-mapping"===e.type){const{viewportStart:t,viewportEnd:n}=e.context;if(0===this.flattenedRows.length)return;return{startNode:v(this.flattenedRows,t),endNode:v(this.flattenedRows,n)+1,totalLoadedNodes:function(e){let t=0;for(const n of e)0===n.depth&&t++;return t}(this.flattenedRows)}}}attach(e){super.attach(e),this.on("datasource:data",e=>{const t=e;t.claimed||(t.claimed=!0)}),this.on("datasource:children",e=>{const t=e;if("tree"!==t.context?.source)return;t.claimed=!0;const n=t.context.parentNode;if(n){n[this.config.childrenField??"children"]=t.rows;const e=this.#n.get(n)??String(n.id??"?");this.loadingKeys.delete(e),this.requestRender()}})}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 S(t,n)}processRows(e){const t=this.config.childrenField??"children",n=e;if(0===n.length||!S(n,t))return this.flattenedRows=[],this.rowKeyMap.clear(),this.previousVisibleKeys.clear(),[...e];const r=this.resolveEffectiveSortState();this.config.defaultExpanded&&!this.initialExpansionDone&&(this.expandedKeys=m(n,this.config),this.initialExpansionDone=!0),this.flattenedRows=this.#i(n,this.expandedKeys,r,null,0),this.#r=/* @__PURE__ */new WeakMap,this.rowKeyMap.clear(),this.keysToAnimate.clear();const i=/* @__PURE__ */new Set;for(const s of this.flattenedRows)this.rowKeyMap.set(s.key,s),this.#r.set(s.data,s),i.add(s.key),!this.previousVisibleKeys.has(s.key)&&s.depth>0&&this.keysToAnimate.add(s.key);return this.previousVisibleKeys=i,this.flattenedRows.map(e=>e.data)}#s(e,t,n){if(void 0!==e.id){const t=String(e.id);return this.#n.set(e,t),t}const r=this.#n.get(e);if(void 0!==r)return r;const i=n?`${n}-${t}`:String(t);return this.#n.set(e,i),i}#i(e,t,n,r,i){const s=this.config.childrenField??"children";for(let d=0;d<e.length;d++)this.#s(e[d],d,r);const o=n?this.#o(e,n.field,n.direction):e,a=[];for(let d=0;d<o.length;d++){const e=o[d],l=this.#s(e,d,r),c=e[s],h=Array.isArray(c)&&c.length>0,u=null!=c&&!Array.isArray(c)&&!!c,f=h||u,p=t.has(l);a.push({key:l,data:e,depth:i,hasChildren:f,isExpanded:p,parentKey:r}),h&&p&&a.push(...this.#i(c,t,n,l,i+1))}return a}#o(e,t,n){const r=this.grid,i=r?._columns??[],s={field:t,direction:n},o=[...e],a=(r?.effectiveConfig?.sortHandler??p)(o,s,i);return a&&"function"==typeof a.then?(a.catch(()=>{}),p(o,s,i)):a}requestLazyChildren(e){if(this.loadingKeys.has(e.key))return;const t=this.config.childrenField??"children",n=e.data[t];if(Array.isArray(n)&&n.length>0)return;const r=this.grid?.query?.("datasource:is-active",null);r&&(this.loadingKeys.add(e.key),this.grid.query("datasource:fetch-children",{context:{source:"tree",parentNode:e.data,nodePath:[e.key]}}))}resolveEffectiveSortState(){const e=this.grid?.query?.("sort:get-model",null);if(Array.isArray(e)&&e.length>0){const t=e[0];if(Array.isArray(t)&&t.length>0)return{field:t[0].field,direction:"desc"===t[0].direction?-1:1}}return this.sortState}processColumns(n){if(0===this.flattenedRows.length)return[...n];const r=[...n];if(0===r.length)return r;const{treeColumn:i}=this.config;let s=0;if(i){const e=r.findIndex(e=>e.field===i);e>=0&&(s=e)}const o=r[s],a=o.field;this.wrappedTreeColumnField!==a&&(this.originalTreeColumnRenderer=o.viewRenderer,this.wrappedTreeColumnField=a);const d=this.originalTreeColumnRenderer,l=()=>this.config,c=this.setIcon.bind(this);return r[s]={...o,viewRenderer:n=>{const{row:r,value:i}=n,{showExpandIcons:s=!0,indentWidth:o}=l(),a=this.#r.get(r),h=a?.depth??0,u=document.createElement("span");if(u.className="tree-cell-wrapper",u.style.setProperty("--tbw-tree-depth",String(h)),void 0!==o&&u.style.setProperty("--tbw-tree-indent-width",`${o}px`),s)if(a&&a.hasChildren){const n=document.createElement("span");n.className=`${t}${a.isExpanded?` ${e}`:""}`,c(n,a.isExpanded?"collapse":"expand"),n.setAttribute("data-tree-key",a.key),u.appendChild(n)}else{const e=document.createElement("span");e.className="tree-spacer",u.appendChild(e)}const f=document.createElement("span");if(f.className="tree-content",d){const e=d(n);e instanceof Node?f.appendChild(e):"string"==typeof e&&(f.innerHTML=e)}else f.textContent=null!=i?String(i):"";return u.appendChild(f),u}},r}onCellClick(e){const n=e.originalEvent?.target;if(!n?.classList.contains(t))return!1;const r=n.getAttribute("data-tree-key");if(!r)return!1;const i=this.rowKeyMap.get(r);return!!i&&(this.expandedKeys=w(this.expandedKeys,r),this.expandedKeys.has(r)&&this.requestLazyChildren(i),this.broadcast("tree-expand",{key:r,row:i.data,expanded:this.expandedKeys.has(r),depth:i.depth,expandedKeys:[...this.expandedKeys]}),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=w(this.expandedKeys,n.key),this.expandedKeys.has(n.key)&&this.requestLazyChildren(n),this.broadcast("tree-expand",{key:n.key,row:n.data,expanded:this.expandedKeys.has(n.key),depth:n.depth,expandedKeys:[...this.expandedKeys]}),this.requestRenderWithFocus(),!0):void 0}onHeaderClick(e){if(0===this.flattenedRows.length||!e.column.sortable)return!1;const t=this.grid?.query?.("sort:get-model",null);if(Array.isArray(t)&&t.length>0)return!1;const{field:n}=e.column;this.sortState&&this.sortState.field===n?1===this.sortState.direction?this.sortState={field:n,direction:-1}:this.sortState=null:this.sortState={field:n,direction:1};const r=this.grid;return void 0!==r._sortState&&(r._sortState=this.sortState?{...this.sortState}:null),this.broadcast("sort-change",{field:n,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,r="fade"===t?"tbw-tree-fade-in":"tbw-tree-slide-in";for(const i of e.querySelectorAll(".data-grid-row")){const e=i.querySelector(".cell[data-row]"),t=e?parseInt(e.getAttribute("data-row")??"-1",10):-1,s=this.flattenedRows[t];s?.hasChildren&&i.setAttribute("aria-expanded",String(s.isExpanded)),n&&s?.key&&this.keysToAnimate.has(s.key)&&(i.classList.add(r),i.addEventListener("animationend",()=>i.classList.remove(r),{once:!0}))}this.keysToAnimate.clear()}expand(e){this.expandedKeys.add(e);const t=this.rowKeyMap.get(e);t&&this.requestLazyChildren(t),this.requestRender()}collapse(e){this.expandedKeys.delete(e),this.requestRender()}toggle(e){this.expandedKeys=w(this.expandedKeys,e);const t=this.rowKeyMap.get(e);t?(this.expandedKeys.has(e)&&this.requestLazyChildren(t),this.broadcast("tree-expand",{key:e,row:t.data,expanded:this.expandedKeys.has(e),depth:t.depth,expandedKeys:[...this.expandedKeys]})):this.emitPluginEvent("tree-expand",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}expandAll(){this.expandedKeys=m(this.rows,this.config),this.emitPluginEvent("tree-expand",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}collapseAll(){this.expandedKeys=/* @__PURE__ */new Set,this.emitPluginEvent("tree-expand",{expandedKeys:[...this.expandedKeys]}),this.requestRender()}isExpanded(e){return this.expandedKeys.has(e)}getExpandedKeys(){return[...this.expandedKeys]}getFlattenedRows(){return[...this.flattenedRows]}getRowMeta(e){return this.#r.get(e)}getRowByKey(e){return this.rowKeyMap.get(e)?.data}expandToKey(e){this.expandedKeys=x(this.rows,e,this.config,this.expandedKeys),this.requestRender()}}export{R as TreePlugin};
2
2
  //# sourceMappingURL=index.js.map