@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
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
- const ee = ':root{color-scheme:light dark}:host{--tbw-color-bg: transparent;--tbw-color-panel-bg: light-dark(#eeeeee, #222222);--tbw-color-fg: light-dark(#222222, #eeeeee);--tbw-color-fg-muted: light-dark(#555555, #aaaaaa);--tbw-color-accent: light-dark(#3b82f6, #3b82f6);--tbw-color-accent-fg: light-dark(#ffffff, #000000);--tbw-color-success: light-dark(hsl(122, 39%, 40%), hsl(122, 39%, 49%));--tbw-color-selection: light-dark(#fff7d6, #333333);--tbw-color-row-alt: var(--tbw-color-bg);--tbw-color-row-hover: light-dark(#f0f6ff, #1c1c1c);--tbw-color-header-bg: color-mix(in hsl, var(--tbw-color-panel-bg) 85%, var(--tbw-color-fg));--tbw-color-header-fg: color-mix(in hsl, var(--tbw-color-fg) 75%, var(--tbw-color-panel-bg));--tbw-color-border: light-dark(#d0d0d4, #454545);--tbw-color-border-strong: light-dark(#777777, #adacac);--tbw-color-border-cell: var(--tbw-color-border);--tbw-color-border-header: var(--tbw-color-border);--tbw-color-shadow: light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3));--tbw-font-family: inherit;--tbw-font-size: inherit;--tbw-font-size-header: var(--tbw-font-size);--tbw-font-weight-header: bold;--tbw-cell-padding-header: 2px 8px;--tbw-cell-padding: 2px 8px;--tbw-cell-padding-input: 2px 6px;--tbw-row-height: 28px;--tbw-header-height: 30px;--tbw-cell-white-space: nowrap;--tbw-border-radius: 4px;--tbw-border-input: 1px solid var(--tbw-color-border-strong);--tbw-border-header: 1px solid var(--tbw-color-border-header);--tbw-row-divider: 1px solid var(--tbw-color-border-cell);--tbw-row-hover-outline: 0;--tbw-color-active-row-bg: var(--tbw-color-selection);--tbw-active-row-outline: 0;--tbw-focus-outline: 2px solid var(--tbw-color-accent);--tbw-focus-outline-offset: -2px;--tbw-focus-background: rgba(from var(--tbw-color-accent) r g b / 12%);--tbw-range-border-color: var(--tbw-color-accent);--tbw-range-selection-bg: rgba(from var(--tbw-range-border-color) r g b / 12%);--tbw-resize-handle-width: 6px;--tbw-resize-handle-color: transparent;--tbw-resize-handle-color-hover: var(--tbw-color-accent);--tbw-resize-handle-border-radius: 0;--tbw-scrollbar-thumb: var(--tbw-color-border-strong);--tbw-scrollbar-track: var(--tbw-color-bg);--tbw-transition-duration: .12s;--tbw-transition-ease: ease;--tbw-animation-duration: .2s;--tbw-animation-easing: ease-out;--tbw-animation-enabled: 1;--tbw-editing-bg: var(--tbw-color-selection);--tbw-editing-border: var(--tbw-border-input, 1px solid var(--tbw-color-border-strong));--tbw-padding-editing-input: var(--tbw-cell-padding-input, 2px 6px);--tbw-font-size-editor: inherit;--tbw-editing-row-bg: var(--tbw-editing-bg);--tbw-editing-row-outline-color: var(--tbw-color-accent);--tbw-editing-row-outline-width: 1px;--tbw-sort-indicator-color: var(--tbw-color-fg-muted);--tbw-sort-indicator-active-color: var(--tbw-color-accent);--tbw-header-text-transform: none;--tbw-header-letter-spacing: normal;--tbw-color-header-separator: var(--tbw-color-border-cell);--tbw-checkbox-size: 16px;--tbw-density-scale: 1}:host{position:relative;display:block;width:100%;height:100%;min-height:0;contain:content;font-family:var(--tbw-font-family);font-size:var(--tbw-font-size);background:var(--tbw-color-bg);color:var(--tbw-color-fg);border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);overflow:clip;outline:none}:host,:host *{box-sizing:border-box}:host .header{display:block;flex-shrink:0;z-index:var(--tbw-z-layer-header, 30);background:var(--tbw-color-header-bg);overflow:visible}:host .header-group-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-color-header-bg);z-index:var(--tbw-z-layer-header, 30)}:host .header-group-cell{display:flex;align-items:center;justify-content:flex-start;padding:var(--tbw-cell-padding-header, 2px 8px);color:var(--tbw-color-header-group-fg, var(--tbw-color-header-fg));font-weight:var(--tbw-font-weight-header-group, var(--tbw-font-weight-header));justify-content:var(--tbw-align-header-group, var(--tbw-align-header, flex-start))}:host .header-row{display:grid;grid-template-columns:var(--tbw-column-template);color:var(--tbw-color-header-fg);font-size:var(--tbw-font-size-header);min-height:var(--tbw-header-height);border-bottom:var(--tbw-border-header);z-index:var(--tbw-z-layer-header, 30)}:host .header-row>.cell{display:flex;align-items:center;gap:4px;padding:var(--tbw-cell-padding-header, 2px 8px);background-color:var(--tbw-color-header-bg);font-weight:var(--tbw-font-weight-header);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}:host .header-row>.cell>span:first-child{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .header-row>.cell>span[part~=sort-indicator]{flex-shrink:0;opacity:.6}:host .header-row>.cell:last-child{border-right:0}:host .header-group-cell:not(:last-child),:host .header-row>.cell.grouped.group-end:not(:last-child){border-right:2px solid var(--tbw-color-border)}:host .tbw-grid-root{display:flex;flex-direction:column;height:100%}:host .rows-body-wrapper{flex:1;min-height:0;display:flex;flex-direction:row;width:100%;min-width:fit-content}:host .rows-body{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:visible}:host .rows-container{display:flex;flex-direction:row;flex:1;min-height:0;overflow:visible}:host .rows-viewport{flex:1;min-width:0;position:relative;display:block;overflow:clip}:host .faux-vscroll{position:sticky;inset-inline-end:0;flex-shrink:0;width:auto;overflow-y:auto;overflow-x:hidden;z-index:var(--tbw-z-layer-header, 30)}:host .faux-vscroll-spacer{width:1px}:host .rows-viewport .rows{position:absolute;top:0;left:0;min-width:100%;will-change:transform;z-index:var(--tbw-z-layer-rows, 1)}:host .data-grid-row{display:grid;grid-template-columns:var(--tbw-column-template);contain:layout style;content-visibility:auto;contain-intrinsic-size:auto var(--tbw-row-height)}:host .data-grid-row:has(.editing){background:var(--tbw-editing-row-bg);outline:var(--tbw-editing-row-outline-width) solid var(--tbw-editing-row-outline-color);outline-offset:calc(-1 * var(--tbw-editing-row-outline-width))}:host .selecting .data-grid-row>.cell{user-select:none}:host .data-grid-row>.cell.selected:focus-visible,:host .data-grid-row>.cell:focus-visible:not(.cell-focus){outline:none}:host .data-grid-row>.cell{display:block;padding:var(--tbw-cell-padding, 2px 8px);border-bottom:var(--tbw-row-divider);min-height:var(--tbw-row-height);line-height:calc(var(--tbw-row-height) - 5px);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0;white-space:var(--tbw-cell-white-space, nowrap);text-overflow:ellipsis}:host .data-grid-row>.cell>*{overflow:hidden;text-overflow:ellipsis;white-space:inherit;min-width:0}:host .data-grid-row>.cell:last-child{border-right:0}:host .data-grid-row>.cell[data-type=boolean]{text-align:center}:host .data-grid-row>.cell[data-type=boolean] input[type=checkbox]{margin:0;width:var(--tbw-checkbox-size);height:var(--tbw-checkbox-size);vertical-align:middle}:host .data-grid-row>.cell.editing{overflow:hidden;padding:0;display:flex;min-height:calc(var(--tbw-row-height) + 2px)}:host .data-grid-row>.cell.editing input:not([type=checkbox]),:host .data-grid-row>.cell.editing select,:host .data-grid-row>.cell.editing textarea{width:100%;height:100%;flex:1 1 auto;min-width:0;border:var(--tbw-editing-border);padding:var(--tbw-padding-editing-input);font-size:var(--tbw-font-size-editor)}:host .data-grid-row:nth-child(2n){background:var(--tbw-color-row-alt)}:host .data-grid-row:hover{background:var(--tbw-color-row-hover)}:host .sortable{cursor:pointer;user-select:none}:host .resize-handle{position:absolute;top:0;right:calc(var(--tbw-resize-handle-width) / -2);width:var(--tbw-resize-handle-width);height:100%;cursor:e-resize;user-select:none;touch-action:none;z-index:20;background:var(--tbw-resize-handle-color);transition:background .12s ease;border-radius:var(--tbw-resize-handle-border-radius)}:host .resize-handle:hover{background:var(--tbw-resize-handle-color-hover)}:host .cell-focus,:host .row-focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}:host .sticky-left,:host .sticky-right{position:sticky;z-index:25}:host .header-row>.cell.sticky-left,:host .header-row>.cell.sticky-right{background:var(--tbw-color-header-bg);z-index:35}:host .data-grid-row>.cell.sticky-left,:host .data-grid-row>.cell.sticky-right{background:var(--tbw-color-panel-bg)}:host .sticky-left{box-shadow:1px 0 0 var(--tbw-color-border)}:host .sticky-right{box-shadow:-1px 0 0 var(--tbw-color-border)}.grid-container{position:relative;width:100%;height:100%}.grid-placeholder{padding:2rem;text-align:center;color:var(--tbw-color-fg);opacity:.6}:host{--tbw-shell-header-height: 44px;--tbw-shell-header-bg: var(--tbw-color-panel-bg);--tbw-shell-header-border: var(--tbw-color-border);--tbw-shell-title-font-size: 14px;--tbw-shell-title-font-weight: 600;--tbw-tool-panel-width: 280px;--tbw-tool-panel-bg: var(--tbw-color-panel-bg);--tbw-tool-panel-border: var(--tbw-color-border);--tbw-tool-panel-header-height: 40px;--tbw-tool-panel-transition: var(--tbw-animation-duration) var(--tbw-animation-easing);--tbw-toolbar-button-size: 32px;--tbw-toolbar-button-gap: 4px}:host .tbw-grid-root.has-shell{display:flex;flex-direction:column;height:100%}:host .tbw-shell-header{display:flex;align-items:center;gap:8px;min-height:var(--tbw-shell-header-height);padding:0 8px;background:var(--tbw-shell-header-bg);border-bottom:1px solid var(--tbw-shell-header-border);flex-shrink:0}:host .tbw-shell-title{font-size:var(--tbw-shell-title-font-size);font-weight:var(--tbw-shell-title-font-weight);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .tbw-shell-content{flex:1;display:flex;align-items:center;gap:12px;min-width:0;overflow:hidden}:host .tbw-shell-toolbar{display:flex;align-items:center;gap:var(--tbw-toolbar-button-gap);flex-shrink:0}:host .tbw-toolbar-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--tbw-toolbar-button-size);height:var(--tbw-toolbar-button-size);padding:0;border:1px solid transparent;border-radius:var(--tbw-border-radius);background:transparent;color:var(--tbw-color-fg);cursor:pointer;font-size:16px;transition:background var(--tbw-transition-duration) var(--tbw-transition-ease),border-color var(--tbw-transition-duration) var(--tbw-transition-ease)}:host .tbw-toolbar-btn:hover{background:var(--tbw-color-row-hover)}:host .tbw-toolbar-btn:focus-visible{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}:host .tbw-toolbar-btn.active{background:var(--tbw-focus-background);border-color:var(--tbw-color-accent)}:host .tbw-toolbar-btn:disabled{opacity:.5;cursor:not-allowed}:host .tbw-toolbar-separator{width:1px;height:20px;background:var(--tbw-color-border);margin:0 4px}:host .tbw-shell-body{position:relative;display:flex;flex:1;min-height:0;overflow:visible}:host .tbw-grid-content{flex:1;min-width:0;min-height:0;display:flex;flex-direction:row;overflow:hidden}:host .tbw-scroll-area{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow-x:auto;overflow-y:hidden;overflow-anchor:none}:host .tbw-tool-panel{position:absolute;top:0;bottom:0;right:0;width:0;overflow:hidden;background:var(--tbw-tool-panel-bg);border-left:1px solid var(--tbw-tool-panel-border);transition:width var(--tbw-tool-panel-transition);display:flex;flex-direction:column;z-index:30;box-shadow:-2px 0 8px var(--tbw-color-shadow)}:host .tbw-tool-panel[data-position=left]{right:auto;left:0;border-left:none;border-right:1px solid var(--tbw-tool-panel-border);box-shadow:2px 0 8px var(--tbw-color-shadow)}:host .tbw-tool-panel.open{width:var(--tbw-tool-panel-width)}:host .tbw-tool-panel-resize{position:absolute;top:0;bottom:0;width:6px;cursor:col-resize;background:transparent;z-index:10;transition:background var(--tbw-transition-duration) var(--tbw-transition-ease)}:host .tbw-tool-panel-resize[data-handle-position=left]{left:0}:host .tbw-tool-panel-resize[data-handle-position=right]{right:0}:host .tbw-tool-panel-resize:hover,:host .tbw-tool-panel-resize.resizing{background:var(--tbw-color-accent)}:host .tbw-tool-panel-header{display:flex;align-items:center;justify-content:space-between;min-height:var(--tbw-tool-panel-header-height);padding:0 12px;border-bottom:1px solid var(--tbw-tool-panel-border);flex-shrink:0}:host .tbw-tool-panel-title{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .tbw-tool-panel-close{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:var(--tbw-border-radius);background:transparent;color:var(--tbw-color-fg-muted);cursor:pointer;font-size:14px}:host .tbw-tool-panel-close:hover{background:var(--tbw-color-row-hover);color:var(--tbw-color-fg)}:host .tbw-tool-panel-content{flex:1;overflow:auto}:host .tbw-accordion{display:flex;flex-direction:column;gap:0}:host .tbw-accordion-section{border-bottom:1px solid var(--tbw-tool-panel-border)}:host .tbw-accordion-section:last-child{border-bottom:none}:host .tbw-accordion-header{display:flex;align-items:center;gap:8px;width:100%;padding:10px 12px;border:none;background:transparent;color:var(--tbw-color-fg);font-size:13px;font-weight:600;text-align:left;cursor:pointer;user-select:none}:host .tbw-accordion-header:hover{background:var(--tbw-color-row-hover)}:host .tbw-accordion-section.single .tbw-accordion-header{cursor:default}:host .tbw-accordion-section.single .tbw-accordion-header:hover{background:transparent}:host .tbw-accordion-chevron{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:10px;color:var(--tbw-color-fg-muted);transition:transform .15s ease;flex-shrink:0}:host .tbw-accordion-section.expanded .tbw-accordion-chevron{transform:rotate(90deg)}:host .tbw-accordion-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:14px;flex-shrink:0}:host .tbw-accordion-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .tbw-accordion-content{display:none}:host .tbw-accordion-section.expanded .tbw-accordion-content{display:block}@media(forced-colors:active){:host{--tbw-color-border: CanvasText;--tbw-color-border-strong: CanvasText;--tbw-color-border-cell: CanvasText;--tbw-color-border-header: CanvasText;--tbw-color-fg: CanvasText;--tbw-color-bg: Canvas;--tbw-color-panel-bg: Canvas;--tbw-color-header-bg: Canvas;--tbw-color-header-fg: CanvasText;--tbw-color-accent: Highlight;--tbw-color-accent-fg: HighlightText;--tbw-color-selection: Highlight;--tbw-color-row-hover: Highlight;--tbw-focus-outline: 2px solid Highlight;--tbw-range-border-color: Highlight}:host .cell:focus,:host .cell.active-cell{outline:2px solid Highlight!important;outline-offset:-2px}:host .data-grid-row[aria-selected=true]{background:Highlight!important;color:HighlightText!important}}@media(prefers-reduced-motion:reduce){:host([data-animation-mode="reduced-motion"]){--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}}:host([data-animation-mode="off"]){--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}:host .tbw-expanding{animation:tbw-expand var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}:host .tbw-collapsing{animation:tbw-collapse var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}@keyframes tbw-expand{0%{opacity:0;max-height:0;transform:translateY(-8px)}to{opacity:1;max-height:500px;transform:translateY(0)}}@keyframes tbw-collapse{0%{opacity:1;max-height:500px;transform:translateY(0)}to{opacity:0;max-height:0;transform:translateY(-8px)}}:host .tbw-fade-in{animation:tbw-fade-in var(--tbw-animation-duration) var(--tbw-animation-easing) forwards}:host .tbw-fade-out{animation:tbw-fade-out var(--tbw-animation-duration) var(--tbw-animation-easing) forwards}@keyframes tbw-fade-in{0%{opacity:0}to{opacity:1}}@keyframes tbw-fade-out{0%{opacity:1}to{opacity:0}}@keyframes tbw-slide-in{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}:host .tbw-slide-in{animation:tbw-slide-in var(--tbw-animation-duration) var(--tbw-animation-easing) forwards}:host .tbw-dragging{opacity:.5;cursor:grabbing}:host .tbw-toggle-btn{cursor:pointer;user-select:none;display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;padding:0;font:inherit;color:inherit}:host .tbw-floating-panel{position:fixed;background:var(--tbw-color-panel-bg);color:var(--tbw-color-fg);border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);box-shadow:0 4px 16px var(--tbw-color-shadow);z-index:10000;font-size:13px}:host .tbw-drop-before:before,:host .tbw-drop-after:after{content:"";position:absolute;background:var(--tbw-drop-indicator-color, var(--tbw-color-accent));pointer-events:none}:host .tbw-drop-before-v:before{left:0;top:0;bottom:0;width:2px}:host .tbw-drop-after-v:after{right:0;top:0;bottom:0;width:2px}:host .tbw-drop-before-h:before{left:0;right:0;top:0;height:2px}:host .tbw-drop-after-h:after{left:0;right:0;bottom:0;height:2px}:host .tbw-flip-animating{will-change:transform;z-index:1}:host .tbw-toggle-icon{display:inline-flex;align-items:center;justify-content:center;transition:transform var(--tbw-animation-duration) var(--tbw-animation-easing)}:host .tbw-toggle-icon.tbw-expanded{transform:rotate(90deg)}', q = {
1
+ const te = ':root{color-scheme:light dark}:host{--tbw-color-bg: transparent;--tbw-color-panel-bg: light-dark(#eeeeee, #222222);--tbw-color-fg: light-dark(#222222, #eeeeee);--tbw-color-fg-muted: light-dark(#555555, #aaaaaa);--tbw-color-accent: light-dark(#3b82f6, #3b82f6);--tbw-color-accent-fg: light-dark(#ffffff, #000000);--tbw-color-success: light-dark(hsl(122, 39%, 40%), hsl(122, 39%, 49%));--tbw-color-selection: light-dark(#fff7d6, #333333);--tbw-color-row-alt: var(--tbw-color-bg);--tbw-color-row-hover: light-dark(#f0f6ff, #1c1c1c);--tbw-color-header-bg: color-mix(in hsl, var(--tbw-color-panel-bg) 85%, var(--tbw-color-fg));--tbw-color-header-fg: color-mix(in hsl, var(--tbw-color-fg) 75%, var(--tbw-color-panel-bg));--tbw-color-border: light-dark(#d0d0d4, #454545);--tbw-color-border-strong: light-dark(#777777, #adacac);--tbw-color-border-cell: var(--tbw-color-border);--tbw-color-border-header: var(--tbw-color-border);--tbw-color-shadow: light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3));--tbw-font-family: inherit;--tbw-font-size: inherit;--tbw-font-size-header: var(--tbw-font-size);--tbw-font-weight-header: bold;--tbw-cell-padding-header: 2px 8px;--tbw-cell-padding: 2px 8px;--tbw-cell-padding-input: 2px 6px;--tbw-row-height: 28px;--tbw-header-height: 30px;--tbw-cell-white-space: nowrap;--tbw-border-radius: 4px;--tbw-border-input: 1px solid var(--tbw-color-border-strong);--tbw-border-header: 1px solid var(--tbw-color-border-header);--tbw-row-divider: 1px solid var(--tbw-color-border-cell);--tbw-row-hover-outline: 0;--tbw-color-active-row-bg: var(--tbw-color-selection);--tbw-active-row-outline: 0;--tbw-focus-outline: 2px solid var(--tbw-color-accent);--tbw-focus-outline-offset: -2px;--tbw-focus-background: rgba(from var(--tbw-color-accent) r g b / 12%);--tbw-range-border-color: var(--tbw-color-accent);--tbw-range-selection-bg: rgba(from var(--tbw-range-border-color) r g b / 12%);--tbw-resize-handle-width: 6px;--tbw-resize-handle-color: transparent;--tbw-resize-handle-color-hover: var(--tbw-color-accent);--tbw-resize-handle-border-radius: 0;--tbw-scrollbar-thumb: var(--tbw-color-border-strong);--tbw-scrollbar-track: var(--tbw-color-bg);--tbw-transition-duration: .12s;--tbw-transition-ease: ease;--tbw-animation-duration: .2s;--tbw-animation-easing: ease-out;--tbw-animation-enabled: 1;--tbw-editing-bg: var(--tbw-color-selection);--tbw-editing-border: var(--tbw-border-input, 1px solid var(--tbw-color-border-strong));--tbw-padding-editing-input: var(--tbw-cell-padding-input, 2px 6px);--tbw-font-size-editor: inherit;--tbw-editing-row-bg: var(--tbw-editing-bg);--tbw-editing-row-outline-color: var(--tbw-color-accent);--tbw-editing-row-outline-width: 1px;--tbw-sort-indicator-color: var(--tbw-color-fg-muted);--tbw-sort-indicator-active-color: var(--tbw-color-accent);--tbw-header-text-transform: none;--tbw-header-letter-spacing: normal;--tbw-color-header-separator: var(--tbw-color-border-cell);--tbw-checkbox-size: 16px;--tbw-density-scale: 1}:host{position:relative;display:block;width:100%;height:100%;min-height:0;contain:content;font-family:var(--tbw-font-family);font-size:var(--tbw-font-size);background:var(--tbw-color-bg);color:var(--tbw-color-fg);border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);overflow:clip;outline:none}:host,:host *{box-sizing:border-box}:host .header{display:block;flex-shrink:0;z-index:var(--tbw-z-layer-header, 30);background:var(--tbw-color-header-bg);overflow:visible}:host .header-group-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-color-header-bg);z-index:var(--tbw-z-layer-header, 30)}:host .header-group-cell{display:flex;align-items:center;justify-content:flex-start;padding:var(--tbw-cell-padding-header, 2px 8px);color:var(--tbw-color-header-group-fg, var(--tbw-color-header-fg));font-weight:var(--tbw-font-weight-header-group, var(--tbw-font-weight-header));justify-content:var(--tbw-align-header-group, var(--tbw-align-header, flex-start))}:host .header-row{display:grid;grid-template-columns:var(--tbw-column-template);color:var(--tbw-color-header-fg);font-size:var(--tbw-font-size-header);min-height:var(--tbw-header-height);border-bottom:var(--tbw-border-header);z-index:var(--tbw-z-layer-header, 30)}:host .header-row>.cell{display:flex;align-items:center;gap:4px;padding:var(--tbw-cell-padding-header, 2px 8px);background-color:var(--tbw-color-header-bg);font-weight:var(--tbw-font-weight-header);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0}:host .header-row>.cell>span:first-child{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .header-row>.cell>span[part~=sort-indicator]{flex-shrink:0;opacity:.6}:host .header-row>.cell:last-child{border-right:0}:host .header-group-cell:not(:last-child),:host .header-row>.cell.grouped.group-end:not(:last-child){border-right:2px solid var(--tbw-color-border)}:host .tbw-grid-root{display:flex;flex-direction:column;height:100%}:host .rows-body-wrapper{flex:1;min-height:0;display:flex;flex-direction:row;width:100%;min-width:fit-content}:host .rows-body{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:visible}:host .rows-container{display:flex;flex-direction:row;flex:1;min-height:0;overflow:visible}:host .rows-viewport{flex:1;min-width:0;position:relative;display:block;overflow:clip}:host .faux-vscroll{position:sticky;inset-inline-end:0;flex-shrink:0;width:auto;overflow-y:auto;overflow-x:hidden;z-index:var(--tbw-z-layer-header, 30)}:host .faux-vscroll-spacer{width:1px}:host .rows-viewport .rows{position:absolute;top:0;left:0;min-width:100%;will-change:transform;z-index:var(--tbw-z-layer-rows, 1)}:host .data-grid-row{display:grid;grid-template-columns:var(--tbw-column-template);contain:layout style;content-visibility:auto;contain-intrinsic-size:auto var(--tbw-row-height)}:host .data-grid-row:has(.editing){background:var(--tbw-editing-row-bg);outline:var(--tbw-editing-row-outline-width) solid var(--tbw-editing-row-outline-color);outline-offset:calc(-1 * var(--tbw-editing-row-outline-width))}:host .selecting .data-grid-row>.cell{user-select:none}:host .data-grid-row>.cell.selected:focus-visible,:host .data-grid-row>.cell:focus-visible:not(.cell-focus){outline:none}:host .data-grid-row>.cell{display:block;padding:var(--tbw-cell-padding, 2px 8px);border-bottom:var(--tbw-row-divider);min-height:var(--tbw-row-height);line-height:calc(var(--tbw-row-height) - 5px);border-right:1px solid var(--tbw-color-border-cell);overflow:hidden;min-width:0;white-space:var(--tbw-cell-white-space, nowrap);text-overflow:ellipsis}:host .data-grid-row>.cell>*{overflow:hidden;text-overflow:ellipsis;white-space:inherit;min-width:0}:host .data-grid-row>.cell:last-child{border-right:0}:host .data-grid-row>.cell[data-type=boolean]{text-align:center}:host .data-grid-row>.cell[data-type=boolean] input[type=checkbox]{margin:0;width:var(--tbw-checkbox-size);height:var(--tbw-checkbox-size);vertical-align:middle}:host .data-grid-row>.cell.editing{overflow:hidden;padding:0;display:flex;min-height:calc(var(--tbw-row-height) + 2px)}:host .data-grid-row>.cell.editing input:not([type=checkbox]),:host .data-grid-row>.cell.editing select,:host .data-grid-row>.cell.editing textarea{width:100%;height:100%;flex:1 1 auto;min-width:0;border:var(--tbw-editing-border);padding:var(--tbw-padding-editing-input);font-size:var(--tbw-font-size-editor)}:host .data-grid-row:nth-child(2n){background:var(--tbw-color-row-alt)}:host .data-grid-row:hover{background:var(--tbw-color-row-hover)}:host .sortable{cursor:pointer;user-select:none}:host .header-row>.cell.resizable{position:relative}:host .tbw-editor-host{display:contents}:host .resize-handle{position:absolute;top:0;right:calc(var(--tbw-resize-handle-width) / -2);width:var(--tbw-resize-handle-width);height:100%;cursor:e-resize;user-select:none;touch-action:none;z-index:20;background:var(--tbw-resize-handle-color);transition:background .12s ease;border-radius:var(--tbw-resize-handle-border-radius)}:host .resize-handle:hover{background:var(--tbw-resize-handle-color-hover)}:host([data-has-focus]) .cell-focus,:host([data-has-focus]) .row-focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}:host .sticky-left,:host .sticky-right{position:sticky;z-index:25}:host .header-row>.cell.sticky-left,:host .header-row>.cell.sticky-right{background:var(--tbw-color-header-bg);z-index:35}:host .data-grid-row>.cell.sticky-left,:host .data-grid-row>.cell.sticky-right{background:var(--tbw-color-panel-bg)}:host .sticky-left{box-shadow:1px 0 0 var(--tbw-color-border)}:host .sticky-right{box-shadow:-1px 0 0 var(--tbw-color-border)}:host{--tbw-shell-header-height: 44px;--tbw-shell-header-bg: var(--tbw-color-panel-bg);--tbw-shell-header-border: var(--tbw-color-border);--tbw-shell-title-font-size: 14px;--tbw-shell-title-font-weight: 600;--tbw-tool-panel-width: 280px;--tbw-tool-panel-bg: var(--tbw-color-panel-bg);--tbw-tool-panel-border: var(--tbw-color-border);--tbw-tool-panel-header-height: 40px;--tbw-tool-panel-transition: var(--tbw-animation-duration) var(--tbw-animation-easing);--tbw-toolbar-button-size: 32px;--tbw-toolbar-button-gap: 4px}:host .tbw-grid-root.has-shell{display:flex;flex-direction:column;height:100%}:host .tbw-shell-header{display:flex;align-items:center;gap:8px;min-height:var(--tbw-shell-header-height);padding:0 8px;background:var(--tbw-shell-header-bg);border-bottom:1px solid var(--tbw-shell-header-border);flex-shrink:0}:host .tbw-shell-title{font-size:var(--tbw-shell-title-font-size);font-weight:var(--tbw-shell-title-font-weight);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .tbw-shell-content{flex:1;display:flex;align-items:center;gap:12px;min-width:0;overflow:hidden}:host .tbw-shell-toolbar{display:flex;align-items:center;gap:var(--tbw-toolbar-button-gap);flex-shrink:0}:host .tbw-toolbar-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--tbw-toolbar-button-size);height:var(--tbw-toolbar-button-size);padding:0;border:1px solid transparent;border-radius:var(--tbw-border-radius);background:transparent;color:var(--tbw-color-fg);cursor:pointer;font-size:16px;transition:background var(--tbw-transition-duration) var(--tbw-transition-ease),border-color var(--tbw-transition-duration) var(--tbw-transition-ease)}:host .tbw-toolbar-btn:hover{background:var(--tbw-color-row-hover)}:host .tbw-toolbar-btn:focus-visible{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}:host .tbw-toolbar-btn.active{background:var(--tbw-focus-background);border-color:var(--tbw-color-accent)}:host .tbw-toolbar-btn:disabled{opacity:.5;cursor:not-allowed}:host .tbw-toolbar-separator{width:1px;height:20px;background:var(--tbw-color-border);margin:0 4px}:host .tbw-shell-body{position:relative;display:flex;flex:1;min-height:0;overflow:visible}:host .tbw-grid-content{flex:1;min-width:0;min-height:0;display:flex;flex-direction:row;overflow:hidden}:host .tbw-scroll-area{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow-x:auto;overflow-y:hidden;overflow-anchor:none}:host .tbw-tool-panel{position:absolute;top:0;bottom:0;right:0;width:0;overflow:hidden;background:var(--tbw-tool-panel-bg);border-left:1px solid var(--tbw-tool-panel-border);transition:width var(--tbw-tool-panel-transition);display:flex;flex-direction:column;z-index:30;box-shadow:-2px 0 8px var(--tbw-color-shadow)}:host .tbw-tool-panel[data-position=left]{right:auto;left:0;border-left:none;border-right:1px solid var(--tbw-tool-panel-border);box-shadow:2px 0 8px var(--tbw-color-shadow)}:host .tbw-tool-panel.open{width:var(--tbw-tool-panel-width)}:host .tbw-tool-panel-resize{position:absolute;top:0;bottom:0;width:6px;cursor:col-resize;background:transparent;z-index:10;transition:background var(--tbw-transition-duration) var(--tbw-transition-ease)}:host .tbw-tool-panel-resize[data-handle-position=left]{left:0}:host .tbw-tool-panel-resize[data-handle-position=right]{right:0}:host .tbw-tool-panel-resize:hover,:host .tbw-tool-panel-resize.resizing{background:var(--tbw-color-accent)}:host .tbw-tool-panel-header{display:flex;align-items:center;justify-content:space-between;min-height:var(--tbw-tool-panel-header-height);padding:0 12px;border-bottom:1px solid var(--tbw-tool-panel-border);flex-shrink:0}:host .tbw-tool-panel-title{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .tbw-tool-panel-close{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:none;border-radius:var(--tbw-border-radius);background:transparent;color:var(--tbw-color-fg-muted);cursor:pointer;font-size:14px}:host .tbw-tool-panel-close:hover{background:var(--tbw-color-row-hover);color:var(--tbw-color-fg)}:host .tbw-tool-panel-content{flex:1;overflow:auto}:host .tbw-accordion{display:flex;flex-direction:column;gap:0}:host .tbw-accordion-section{border-bottom:1px solid var(--tbw-tool-panel-border)}:host .tbw-accordion-section:last-child{border-bottom:none}:host .tbw-accordion-header{display:flex;align-items:center;gap:8px;width:100%;padding:10px 12px;border:none;background:transparent;color:var(--tbw-color-fg);font-size:13px;font-weight:600;text-align:left;cursor:pointer;user-select:none}:host .tbw-accordion-header:hover{background:var(--tbw-color-row-hover)}:host .tbw-accordion-section.single .tbw-accordion-header{cursor:default}:host .tbw-accordion-section.single .tbw-accordion-header:hover{background:transparent}:host .tbw-accordion-chevron{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:10px;color:var(--tbw-color-fg-muted);transition:transform .15s ease;flex-shrink:0}:host .tbw-accordion-section.expanded .tbw-accordion-chevron{transform:rotate(90deg)}:host .tbw-accordion-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:14px;flex-shrink:0}:host .tbw-accordion-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .tbw-accordion-content{display:none}:host .tbw-accordion-section.expanded .tbw-accordion-content{display:block}@media(forced-colors:active){:host{--tbw-color-border: CanvasText;--tbw-color-border-strong: CanvasText;--tbw-color-border-cell: CanvasText;--tbw-color-border-header: CanvasText;--tbw-color-fg: CanvasText;--tbw-color-bg: Canvas;--tbw-color-panel-bg: Canvas;--tbw-color-header-bg: Canvas;--tbw-color-header-fg: CanvasText;--tbw-color-accent: Highlight;--tbw-color-accent-fg: HighlightText;--tbw-color-selection: Highlight;--tbw-color-row-hover: Highlight;--tbw-focus-outline: 2px solid Highlight;--tbw-range-border-color: Highlight}:host .cell:focus,:host .cell.active-cell{outline:2px solid Highlight!important;outline-offset:-2px}:host .data-grid-row[aria-selected=true]{background:Highlight!important;color:HighlightText!important}}@media(prefers-reduced-motion:reduce){:host([data-animation-mode="reduced-motion"]){--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}}:host([data-animation-mode="off"]){--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}:host .tbw-expanding{animation:tbw-expand var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}:host .tbw-collapsing{animation:tbw-collapse var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}@keyframes tbw-expand{0%{opacity:0;max-height:0;transform:translateY(-8px)}to{opacity:1;max-height:500px;transform:translateY(0)}}@keyframes tbw-collapse{0%{opacity:1;max-height:500px;transform:translateY(0)}to{opacity:0;max-height:0;transform:translateY(-8px)}}', W = {
2
2
  STRETCH: "stretch",
3
3
  FIXED: "fixed"
4
- }, De = {
4
+ }, Me = {
5
5
  mode: "reduced-motion",
6
6
  duration: 200,
7
7
  easing: "ease-out"
@@ -15,44 +15,44 @@ const ee = ':root{color-scheme:light dark}:host{--tbw-color-bg: transparent;--tb
15
15
  dragHandle: "⋮⋮",
16
16
  toolPanel: "☰"
17
17
  };
18
- function Me(t) {
18
+ function ze(t) {
19
19
  return Array.from(t.querySelectorAll("tbw-grid-column")).map((o) => {
20
20
  const i = o.getAttribute("field") || "";
21
21
  if (!i) return null;
22
- const n = o.getAttribute("type") || void 0, s = n && (/* @__PURE__ */ new Set(["number", "string", "date", "boolean", "select", "typeahead"])).has(n) ? n : void 0, l = o.getAttribute("header") || void 0, a = o.hasAttribute("sortable"), c = o.hasAttribute("editable"), u = { field: i, type: s, header: l, sortable: a, editable: c }, d = o.getAttribute("width");
22
+ const n = o.getAttribute("type") || void 0, s = n && (/* @__PURE__ */ new Set(["number", "string", "date", "boolean", "select", "typeahead"])).has(n) ? n : void 0, l = o.getAttribute("header") || void 0, a = o.hasAttribute("sortable"), c = o.hasAttribute("editable"), h = { field: i, type: s, header: l, sortable: a, editable: c }, d = o.getAttribute("width");
23
23
  if (d) {
24
24
  const v = parseFloat(d);
25
- !isNaN(v) && /^\d+(\.\d+)?$/.test(d.trim()) ? u.width = v : u.width = d;
25
+ !isNaN(v) && /^\d+(\.\d+)?$/.test(d.trim()) ? h.width = v : h.width = d;
26
26
  }
27
27
  const f = o.getAttribute("minWidth") || o.getAttribute("min-width");
28
28
  if (f) {
29
29
  const v = parseFloat(f);
30
- isNaN(v) || (u.minWidth = v);
30
+ isNaN(v) || (h.minWidth = v);
31
31
  }
32
- o.hasAttribute("resizable") && (u.resizable = !0), o.hasAttribute("sizable") && (u.resizable = !0);
33
- const p = o.getAttribute("editor"), h = o.getAttribute("renderer");
34
- p && (u.__editorName = p), h && (u.__rendererName = h);
32
+ o.hasAttribute("resizable") && (h.resizable = !0), o.hasAttribute("sizable") && (h.resizable = !0);
33
+ const p = o.getAttribute("editor"), u = o.getAttribute("renderer");
34
+ p && (h.__editorName = p), u && (h.__rendererName = u);
35
35
  const g = o.getAttribute("options");
36
- g && (u.options = g.split(",").map((v) => {
37
- const [X, Oe] = v.includes(":") ? v.split(":") : [v.trim(), v.trim()];
38
- return { value: X.trim(), label: Oe?.trim() || X.trim() };
36
+ g && (h.options = g.split(",").map((v) => {
37
+ const [Y, De] = v.includes(":") ? v.split(":") : [v.trim(), v.trim()];
38
+ return { value: Y.trim(), label: De?.trim() || Y.trim() };
39
39
  }));
40
40
  const m = o.querySelector("tbw-grid-column-view"), b = o.querySelector("tbw-grid-column-editor"), _ = o.querySelector("tbw-grid-column-header");
41
- m && (u.__viewTemplate = m), b && (u.__editorTemplate = b), _ && (u.__headerTemplate = _);
42
- const C = globalThis.DataGridElement?.getAdapters?.() ?? [], y = m ?? o, S = C.find((v) => v.canHandle(y));
43
- if (S) {
44
- const v = S.createRenderer(y);
45
- v && (u.viewRenderer = v);
41
+ m && (h.__viewTemplate = m), b && (h.__editorTemplate = b), _ && (h.__headerTemplate = _);
42
+ const C = globalThis.DataGridElement?.getAdapters?.() ?? [], y = m ?? o, R = C.find((v) => v.canHandle(y));
43
+ if (R) {
44
+ const v = R.createRenderer(y);
45
+ v && (h.viewRenderer = v);
46
46
  }
47
- const W = b ?? o, x = C.find((v) => v.canHandle(W));
47
+ const U = b ?? o, x = C.find((v) => v.canHandle(U));
48
48
  if (x) {
49
- const v = x.createEditor(W);
50
- v && (u.editor = v);
49
+ const v = x.createEditor(U);
50
+ v && (h.editor = v);
51
51
  }
52
- return u;
52
+ return h;
53
53
  }).filter((o) => !!o);
54
54
  }
55
- function te(t, e) {
55
+ function oe(t, e) {
56
56
  if ((!t || !t.length) && (!e || !e.length)) return [];
57
57
  if (!t || !t.length) return e || [];
58
58
  if (!e || !e.length) return t;
@@ -76,7 +76,7 @@ function te(t, e) {
76
76
  });
77
77
  return Object.keys(o).forEach((n) => i.push(o[n])), i;
78
78
  }
79
- function oe(t, e) {
79
+ function ie(t, e) {
80
80
  try {
81
81
  t.part?.add?.(e);
82
82
  } catch {
@@ -84,9 +84,9 @@ function oe(t, e) {
84
84
  const o = t.getAttribute("part");
85
85
  o ? o.split(/\s+/).includes(e) || t.setAttribute("part", o + " " + e) : t.setAttribute("part", e);
86
86
  }
87
- function ie(t) {
88
- const e = t.effectiveConfig?.fitMode || t.fitMode || q.STRETCH;
89
- if (e !== q.STRETCH && e !== q.FIXED || t.__didInitialAutoSize || !t.isConnected) return;
87
+ function ne(t) {
88
+ const e = t.effectiveConfig?.fitMode || t.fitMode || W.STRETCH;
89
+ if (e !== W.STRETCH && e !== W.FIXED || t.__didInitialAutoSize || !t.isConnected) return;
90
90
  const o = Array.from(t._headerRowEl?.children || []);
91
91
  if (!o.length) return;
92
92
  let i = !1;
@@ -97,37 +97,37 @@ function ie(t) {
97
97
  for (const a of t._rowPool) {
98
98
  const c = a.children[r];
99
99
  if (c) {
100
- const u = c.scrollWidth;
101
- u > l && (l = u);
100
+ const h = c.scrollWidth;
101
+ h > l && (l = h);
102
102
  }
103
103
  }
104
104
  l > 0 && (n.width = l + 2, n.__autoSized = !0, i = !0);
105
- }), i && k(t), t.__didInitialAutoSize = !0;
105
+ }), i && q(t), t.__didInitialAutoSize = !0;
106
106
  }
107
- function k(t) {
108
- (t.effectiveConfig?.fitMode || t.fitMode || q.STRETCH) === q.STRETCH ? t._gridTemplate = t._visibleColumns.map((o) => {
107
+ function q(t) {
108
+ (t.effectiveConfig?.fitMode || t.fitMode || W.STRETCH) === W.STRETCH ? t._gridTemplate = t._visibleColumns.map((o) => {
109
109
  if (o.width) return `${o.width}px`;
110
110
  const i = o.minWidth;
111
111
  return i != null ? `minmax(${i}px, 1fr)` : "1fr";
112
112
  }).join(" ").trim() : t._gridTemplate = t._visibleColumns.map((o) => o.width ? `${o.width}px` : "max-content").join(" "), t.style.setProperty("--tbw-column-template", t._gridTemplate);
113
113
  }
114
- function ze(t) {
114
+ function Ne(t) {
115
115
  return t == null ? "string" : typeof t == "number" ? "number" : typeof t == "boolean" ? "boolean" : t instanceof Date || typeof t == "string" && /\d{4}-\d{2}-\d{2}/.test(t) && !isNaN(Date.parse(t)) ? "date" : "string";
116
116
  }
117
- function Ne(t, e) {
117
+ function ke(t, e) {
118
118
  const o = t[0] || {}, i = Object.keys(o).map((r) => {
119
- const s = o[r], l = ze(s);
119
+ const s = o[r], l = Ne(s);
120
120
  return { field: r, header: r.charAt(0).toUpperCase() + r.slice(1), type: l };
121
121
  }), n = {};
122
122
  return i.forEach((r) => {
123
123
  n[r.field] = r.type || "string";
124
124
  }), { columns: i, typeMap: n };
125
125
  }
126
- const ke = /{{\s*([^}]+)\s*}}/g, A = "__DG_EMPTY__", Ie = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, Be = /__(proto|defineGetter|defineSetter)|constructor|window|globalThis|global|process|Function|import|eval|Reflect|Proxy|Error|arguments|document|location|cookie|localStorage|sessionStorage|indexedDB|fetch|XMLHttpRequest|WebSocket|Worker|SharedWorker|ServiceWorker|opener|parent|top|frames|self|this\b/;
127
- function qe(t) {
126
+ const Ie = /{{\s*([^}]+)\s*}}/g, A = "__DG_EMPTY__", qe = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, Be = /__(proto|defineGetter|defineSetter)|constructor|window|globalThis|global|process|Function|import|eval|Reflect|Proxy|Error|arguments|document|location|cookie|localStorage|sessionStorage|indexedDB|fetch|XMLHttpRequest|WebSocket|Worker|SharedWorker|ServiceWorker|opener|parent|top|frames|self|this\b/;
127
+ function We(t) {
128
128
  return !t || typeof t != "string" ? "" : t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
129
129
  }
130
- const We = /* @__PURE__ */ new Set([
130
+ const Ue = /* @__PURE__ */ new Set([
131
131
  "script",
132
132
  "iframe",
133
133
  "object",
@@ -152,23 +152,23 @@ const We = /* @__PURE__ */ new Set([
152
152
  "plaintext",
153
153
  "xmp",
154
154
  "listing"
155
- ]), ne = /^on\w+$/i, Ue = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), $e = /^\s*(javascript|vbscript|data|blob):/i;
156
- function V(t) {
155
+ ]), re = /^on\w+$/i, $e = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), Fe = /^\s*(javascript|vbscript|data|blob):/i;
156
+ function G(t) {
157
157
  if (!t || typeof t != "string") return "";
158
158
  if (t.indexOf("<") === -1) return t;
159
159
  const e = document.createElement("template");
160
- return e.innerHTML = t, Ge(e.content), e.innerHTML;
160
+ return e.innerHTML = t, Ve(e.content), e.innerHTML;
161
161
  }
162
- function Ge(t) {
162
+ function Ve(t) {
163
163
  const e = [], o = t.querySelectorAll("*");
164
164
  for (const i of o) {
165
165
  const n = i.tagName.toLowerCase();
166
- if (We.has(n)) {
166
+ if (Ue.has(n)) {
167
167
  e.push(i);
168
168
  continue;
169
169
  }
170
170
  if ((n === "svg" || i.namespaceURI === "http://www.w3.org/2000/svg") && Array.from(i.attributes).some(
171
- (l) => ne.test(l.name) || l.name === "href" || l.name === "xlink:href"
171
+ (l) => re.test(l.name) || l.name === "href" || l.name === "xlink:href"
172
172
  )) {
173
173
  e.push(i);
174
174
  continue;
@@ -176,11 +176,11 @@ function Ge(t) {
176
176
  const r = [];
177
177
  for (const s of i.attributes) {
178
178
  const l = s.name.toLowerCase();
179
- if (ne.test(l)) {
179
+ if (re.test(l)) {
180
180
  r.push(s.name);
181
181
  continue;
182
182
  }
183
- if (Ue.has(l) && $e.test(s.value)) {
183
+ if ($e.has(l) && Fe.test(s.value)) {
184
184
  r.push(s.name);
185
185
  continue;
186
186
  }
@@ -193,22 +193,22 @@ function Ge(t) {
193
193
  }
194
194
  e.forEach((i) => i.remove());
195
195
  }
196
- function me(t, e) {
196
+ function ve(t, e) {
197
197
  if (!t || t.indexOf("{{") === -1) return t;
198
- const o = [], i = t.replace(ke, (l, a) => {
199
- const c = Ve(a, e);
198
+ const o = [], i = t.replace(Ie, (l, a) => {
199
+ const c = Ge(a, e);
200
200
  return o.push({ expr: a.trim(), result: c }), c;
201
- }), n = Fe(i), r = o.length && o.every((l) => l.result === "" || l.result === A);
201
+ }), n = Xe(i), r = o.length && o.every((l) => l.result === "" || l.result === A);
202
202
  return /Reflect\.|\bProxy\b|ownKeys\(/.test(t) || r ? "" : n;
203
203
  }
204
- function Ve(t, e) {
204
+ function Ge(t, e) {
205
205
  if (t = (t || "").trim(), !t || /\b(Reflect|Proxy|ownKeys)\b/.test(t)) return A;
206
206
  if (t === "value") return e.value == null ? A : String(e.value);
207
207
  if (t.startsWith("row.") && !/[()?]/.test(t) && !t.includes(":")) {
208
208
  const i = t.slice(4), n = e.row ? e.row[i] : void 0;
209
209
  return n == null ? A : String(n);
210
210
  }
211
- if (t.length > 80 || !Ie.test(t) || Be.test(t)) return A;
211
+ if (t.length > 80 || !qe.test(t) || Be.test(t)) return A;
212
212
  const o = t.match(/\./g);
213
213
  if (o && o.length > 1) return A;
214
214
  try {
@@ -218,10 +218,10 @@ function Ve(t, e) {
218
218
  return A;
219
219
  }
220
220
  }
221
- function Fe(t) {
221
+ function Xe(t) {
222
222
  return t && t.replace(new RegExp(A, "g"), "").replace(/Reflect\.[^<>{}\s]+/g, "").replace(/\bProxy\b/g, "").replace(/ownKeys\([^)]*\)/g, "");
223
223
  }
224
- function Xe(t) {
224
+ function Ye(t) {
225
225
  if (/Reflect|Proxy|ownKeys/.test(t.textContent || "")) {
226
226
  if (Array.from(t.childNodes).forEach((e) => {
227
227
  e.nodeType === Node.TEXT_NODE && /Reflect|Proxy|ownKeys/.test(e.textContent || "") && (e.textContent = "");
@@ -233,12 +233,12 @@ function Xe(t) {
233
233
  (t.textContent || "").trim().length === 0 && (t.textContent = "");
234
234
  }
235
235
  }
236
- function re(t) {
237
- const e = /Reflect\.|\bProxy\b|ownKeys\(/.test(t), o = ((i) => e ? "" : me(t, i));
236
+ function se(t) {
237
+ const e = /Reflect\.|\bProxy\b|ownKeys\(/.test(t), o = ((i) => e ? "" : ve(t, i));
238
238
  return o.__blocked = e, o;
239
239
  }
240
- const Ye = 100;
241
- class je {
240
+ const je = 100;
241
+ class Ke {
242
242
  // ============================================================================
243
243
  // Sources (raw input from user)
244
244
  // ============================================================================
@@ -449,19 +449,19 @@ class je {
449
449
  const e = this.#o ? { ...this.#o } : {}, o = Array.isArray(e.columns) ? [...e.columns] : [], i = (this.#r ?? []).map((s) => ({
450
450
  ...s
451
451
  }));
452
- let n = te(
452
+ let n = oe(
453
453
  o,
454
454
  i
455
455
  );
456
- this.#c && this.#c.length && (n = te(
456
+ this.#c && this.#c.length && (n = oe(
457
457
  this.#c,
458
458
  i
459
459
  ));
460
460
  const r = this.#s.getRows();
461
- return n.length === 0 && r.length && (n = Ne(r).columns), n.length && (n.forEach((s) => {
461
+ return n.length === 0 && r.length && (n = ke(r).columns), n.length && (n.forEach((s) => {
462
462
  s.sortable === void 0 && (s.sortable = !0), s.resizable === void 0 && (s.resizable = !0), s.__originalWidth === void 0 && typeof s.width == "number" && (s.__originalWidth = s.width);
463
463
  }), n.forEach((s) => {
464
- s.__viewTemplate && !s.__compiledView && (s.__compiledView = re(s.__viewTemplate.innerHTML)), s.__editorTemplate && !s.__compiledEditor && (s.__compiledEditor = re(s.__editorTemplate.innerHTML));
464
+ s.__viewTemplate && !s.__compiledView && (s.__compiledView = se(s.__viewTemplate.innerHTML)), s.__editorTemplate && !s.__compiledEditor && (s.__compiledEditor = se(s.__editorTemplate.innerHTML));
465
465
  }), e.columns = n), this.#f && (e.fitMode = this.#f), e.fitMode || (e.fitMode = "stretch"), this.#d && (e.editOn = this.#d), this.#y(e), e.columnState && !this.#b && (this.#b = e.columnState), e;
466
466
  }
467
467
  /**
@@ -487,10 +487,10 @@ class je {
487
487
  const d = Array.from(r.values());
488
488
  d.sort((f, p) => (f.order ?? 100) - (p.order ?? 100)), e.shell.headerContents = d;
489
489
  }
490
- const s = this.#s.getShellToolbarButtons(), l = Array.from(s.values()), a = this.#o?.shell?.header?.toolbarButtons ?? [], c = new Set(a.map((d) => d.id)), u = [...a];
490
+ const s = this.#s.getShellToolbarButtons(), l = Array.from(s.values()), a = this.#o?.shell?.header?.toolbarButtons ?? [], c = new Set(a.map((d) => d.id)), h = [...a];
491
491
  for (const d of l)
492
- c.has(d.id) || u.push(d);
493
- u.sort((d, f) => (d.order ?? 100) - (f.order ?? 100)), e.shell.header.toolbarButtons = u;
492
+ c.has(d.id) || h.push(d);
493
+ h.sort((d, f) => (d.order ?? 100) - (f.order ?? 100)), e.shell.header.toolbarButtons = h;
494
494
  }
495
495
  // ============================================================================
496
496
  // State Persistence (Replaces column-state.ts)
@@ -513,8 +513,8 @@ class je {
513
513
  a && (s.sort = a);
514
514
  for (const c of e)
515
515
  if (c.getColumnState) {
516
- const u = c.getColumnState(n.field);
517
- u && Object.assign(s, u);
516
+ const h = c.getColumnState(n.field);
517
+ h && Object.assign(s, h);
518
518
  }
519
519
  return s;
520
520
  })
@@ -532,8 +532,8 @@ class je {
532
532
  return a.width !== void 0 && (c.width = a.width, c.__renderedWidth = a.width), a.visible !== void 0 && (c.hidden = !a.visible), c;
533
533
  });
534
534
  r.sort((l, a) => {
535
- const c = n.get(l.field)?.order ?? 1 / 0, u = n.get(a.field)?.order ?? 1 / 0;
536
- return c - u;
535
+ const c = n.get(l.field)?.order ?? 1 / 0, h = n.get(a.field)?.order ?? 1 / 0;
536
+ return c - h;
537
537
  }), this.columns = r;
538
538
  const s = e.columns.filter((l) => l.sort !== void 0).sort((l, a) => (l.sort?.priority ?? 0) - (a.sort?.priority ?? 0));
539
539
  if (s.length > 0) {
@@ -586,7 +586,7 @@ class je {
586
586
  this.#w = void 0;
587
587
  const o = this.collectState(e);
588
588
  this.#s.emit("column-state-change", o);
589
- }, Ye);
589
+ }, je);
590
590
  }
591
591
  // ============================================================================
592
592
  // Column Visibility API
@@ -634,7 +634,8 @@ class je {
634
634
  field: e.field,
635
635
  header: e.header || e.field,
636
636
  visible: !e.hidden,
637
- lockVisible: e.lockVisible
637
+ lockVisible: e.lockVisible,
638
+ utility: e.meta?.utility === !0
638
639
  }));
639
640
  }
640
641
  /**
@@ -664,7 +665,7 @@ class je {
664
665
  * Parse light DOM columns from host element.
665
666
  */
666
667
  parseLightDomColumns(e) {
667
- this.#r || (this.#n = Array.from(e.querySelectorAll("tbw-grid-column")), this.#r = this.#n.length ? Me(e) : []);
668
+ this.#r || (this.#n = Array.from(e.querySelectorAll("tbw-grid-column")), this.#r = this.#n.length ? ze(e) : []);
668
669
  }
669
670
  /**
670
671
  * Clear the light DOM columns cache.
@@ -767,10 +768,10 @@ class je {
767
768
  this.#v?.disconnect(), this.#l = [], this.#w && clearTimeout(this.#w);
768
769
  }
769
770
  }
770
- function ve(t) {
771
+ function Ce(t) {
771
772
  return `<span role="checkbox" aria-checked="${t}" aria-label="${t}">${t ? "&#x1F5F9;" : "&#9744;"}</span>`;
772
773
  }
773
- function Ce(t) {
774
+ function _e(t) {
774
775
  if (t == null || t === "") return "";
775
776
  if (t instanceof Date)
776
777
  return isNaN(t.getTime()) ? "" : t.toLocaleDateString();
@@ -780,68 +781,76 @@ function Ce(t) {
780
781
  }
781
782
  return "";
782
783
  }
783
- function _e(t) {
784
+ function ye(t) {
784
785
  if (!t) return -1;
785
786
  const e = t.getAttribute("data-row");
786
- return e ? parseInt(e, 10) : -1;
787
+ if (e) return parseInt(e, 10);
788
+ const o = t.closest(".data-grid-row");
789
+ if (!o) return -1;
790
+ const i = o.parentElement;
791
+ if (!i) return -1;
792
+ const n = i.querySelectorAll(":scope > .data-grid-row");
793
+ for (let r = 0; r < n.length; r++)
794
+ if (n[r] === o) return r;
795
+ return -1;
787
796
  }
788
- function Ke(t) {
797
+ function Ze(t) {
789
798
  if (!t) return -1;
790
799
  const e = t.getAttribute("data-col");
791
800
  return e ? parseInt(e, 10) : -1;
792
801
  }
793
- function Q(t) {
802
+ function ee(t) {
794
803
  t && t.querySelectorAll(".cell-focus").forEach((e) => e.classList.remove("cell-focus"));
795
804
  }
796
- function Ze(t, e) {
797
- const o = _e(e), i = Ke(e);
798
- o < 0 || i < 0 || (t._focusRow = o, t._focusCol = i, Q(t._bodyEl), e.classList.add("cell-focus"), e.setAttribute("aria-selected", "true"));
805
+ function Je(t, e) {
806
+ const o = ye(e), i = Ze(e);
807
+ o < 0 || i < 0 || (t._focusRow = o, t._focusCol = i, ee(t._bodyEl), e.classList.add("cell-focus"), e.setAttribute("aria-selected", "true"));
799
808
  }
800
- function Je(t, e, o) {
809
+ function Qe(t, e, o) {
801
810
  e.addEventListener(
802
811
  "mousedown",
803
812
  (i) => {
804
813
  const n = i.target.closest(".cell[data-col]");
805
- n && (n.classList.contains("editing") || Ze(t, n));
814
+ n && (n.classList.contains("editing") || Je(t, n));
806
815
  },
807
816
  { signal: o }
808
817
  );
809
818
  }
810
- function Qe(t, e) {
819
+ function et(t, e) {
811
820
  return t == null && e == null ? 0 : t == null ? -1 : e == null || t > e ? 1 : t < e ? -1 : 0;
812
821
  }
813
- function et(t, e, o) {
814
- const n = o.find((l) => l.field === e.field)?.sortComparator ?? Qe, { field: r, direction: s } = e;
822
+ function tt(t, e, o) {
823
+ const n = o.find((l) => l.field === e.field)?.sortComparator ?? et, { field: r, direction: s } = e;
815
824
  return [...t].sort((l, a) => n(l[r], a[r], l, a) * s);
816
825
  }
817
- function se(t, e, o, i) {
818
- t._rows = e, t.__rowRenderEpoch++, t._rowPool.forEach((n) => n.__epoch = -1), F(t), t.refreshVirtualWindow(!0), t.dispatchEvent(
826
+ function le(t, e, o, i) {
827
+ t._rows = e, t.__rowRenderEpoch++, t._rowPool.forEach((n) => n.__epoch = -1), X(t), t.refreshVirtualWindow(!0), t.dispatchEvent(
819
828
  new CustomEvent("sort-change", { detail: { field: o.field, direction: i } })
820
829
  ), t.requestStateChange?.();
821
830
  }
822
- function le(t, e) {
823
- !t._sortState || t._sortState.field !== e.field ? (t._sortState || (t.__originalOrder = t._rows.slice()), ae(t, e, 1)) : t._sortState.direction === 1 ? ae(t, e, -1) : (t._sortState = null, t.__rowRenderEpoch++, t._rowPool.forEach((i) => i.__epoch = -1), t._rows = t.__originalOrder.slice(), F(t), t._headerRowEl?.querySelectorAll('[role="columnheader"].sortable')?.forEach((i) => {
831
+ function ae(t, e) {
832
+ !t._sortState || t._sortState.field !== e.field ? (t._sortState || (t.__originalOrder = t._rows.slice()), ce(t, e, 1)) : t._sortState.direction === 1 ? ce(t, e, -1) : (t._sortState = null, t.__rowRenderEpoch++, t._rowPool.forEach((i) => i.__epoch = -1), t._rows = t.__originalOrder.slice(), X(t), t._headerRowEl?.querySelectorAll('[role="columnheader"].sortable')?.forEach((i) => {
824
833
  i.getAttribute("aria-sort") ? (i.getAttribute("aria-sort") === "ascending" || i.getAttribute("aria-sort") === "descending") && (t._sortState || i.setAttribute("aria-sort", "none")) : i.setAttribute("aria-sort", "none");
825
834
  }), t.refreshVirtualWindow(!0), t.dispatchEvent(
826
835
  new CustomEvent("sort-change", { detail: { field: e.field, direction: 0 } })
827
836
  ), t.requestStateChange?.());
828
837
  }
829
- function ae(t, e, o) {
838
+ function ce(t, e, o) {
830
839
  t._sortState = { field: e.field, direction: o };
831
- const i = { field: e.field, direction: o }, n = t._columns, s = (t.effectiveConfig?.sortHandler ?? et)(t._rows, i, n);
840
+ const i = { field: e.field, direction: o }, n = t._columns, s = (t.effectiveConfig?.sortHandler ?? tt)(t._rows, i, n);
832
841
  s && typeof s.then == "function" ? s.then((l) => {
833
- se(t, l, e, o);
834
- }) : se(t, s, e, o);
842
+ le(t, l, e, o);
843
+ }) : le(t, s, e, o);
835
844
  }
836
- function tt(t, e) {
845
+ function ot(t, e) {
837
846
  typeof e == "string" ? t.textContent = e : e instanceof HTMLElement && (t.innerHTML = "", t.appendChild(e.cloneNode(!0)));
838
847
  }
839
- function F(t) {
848
+ function X(t) {
840
849
  t._headerRowEl = t.findHeaderRow();
841
850
  const e = t._headerRowEl;
842
851
  e.innerHTML = "", t._visibleColumns.forEach((o, i) => {
843
852
  const n = document.createElement("div");
844
- n.className = "cell", oe(n, "header-cell"), n.setAttribute("role", "columnheader"), n.setAttribute("aria-colindex", String(i + 1)), n.setAttribute("data-field", o.field), n.setAttribute("data-col", String(i));
853
+ n.className = "cell", ie(n, "header-cell"), n.setAttribute("role", "columnheader"), n.setAttribute("aria-colindex", String(i + 1)), n.setAttribute("data-field", o.field), n.setAttribute("data-col", String(i));
845
854
  const r = o.__headerTemplate;
846
855
  if (r) Array.from(r.childNodes).forEach((s) => n.appendChild(s.cloneNode(!0)));
847
856
  else {
@@ -851,19 +860,19 @@ function F(t) {
851
860
  if (o.sortable) {
852
861
  n.classList.add("sortable"), n.tabIndex = 0;
853
862
  const s = document.createElement("span");
854
- oe(s, "sort-indicator");
863
+ ie(s, "sort-indicator");
855
864
  const l = t._sortState?.field === o.field ? t._sortState.direction : 0, a = { ...L, ...t.icons }, c = l === 1 ? a.sortAsc : l === -1 ? a.sortDesc : a.sortNone;
856
- tt(s, c), n.appendChild(s), n.setAttribute("aria-sort", l === 0 ? "none" : l === 1 ? "ascending" : "descending"), n.addEventListener("click", (u) => {
857
- t._resizeController?.isResizing || t._dispatchHeaderClick?.(u, i, n) || le(t, o);
858
- }), n.addEventListener("keydown", (u) => {
859
- if (u.key === "Enter" || u.key === " ") {
860
- if (u.preventDefault(), t._dispatchHeaderClick?.(u, i, n)) return;
861
- le(t, o);
865
+ ot(s, c), n.appendChild(s), n.setAttribute("aria-sort", l === 0 ? "none" : l === 1 ? "ascending" : "descending"), n.addEventListener("click", (h) => {
866
+ t._resizeController?.isResizing || t._dispatchHeaderClick?.(h, i, n) || ae(t, o);
867
+ }), n.addEventListener("keydown", (h) => {
868
+ if (h.key === "Enter" || h.key === " ") {
869
+ if (h.preventDefault(), t._dispatchHeaderClick?.(h, i, n)) return;
870
+ ae(t, o);
862
871
  }
863
872
  });
864
873
  }
865
874
  if (o.resizable) {
866
- n.style.position = "relative";
875
+ n.classList.add("resizable");
867
876
  const s = document.createElement("div");
868
877
  s.className = "resize-handle", s.setAttribute("aria-hidden", "true"), s.addEventListener("mousedown", (l) => {
869
878
  l.stopPropagation(), l.preventDefault(), t._resizeController.start(l, i, n);
@@ -876,9 +885,9 @@ function F(t) {
876
885
  o.getAttribute("aria-sort") || o.setAttribute("aria-sort", "none");
877
886
  }), e.children.length > 0 ? (e.setAttribute("role", "row"), e.setAttribute("aria-rowindex", "1")) : (e.removeAttribute("role"), e.removeAttribute("aria-rowindex"));
878
887
  }
879
- const ye = typeof requestIdleCallback == "function";
880
- function ot(t, e) {
881
- return ye ? requestIdleCallback(t, e) : window.setTimeout(() => {
888
+ const Ee = typeof requestIdleCallback == "function";
889
+ function it(t, e) {
890
+ return Ee ? requestIdleCallback(t, e) : window.setTimeout(() => {
882
891
  const o = Date.now();
883
892
  t({
884
893
  didTimeout: !1,
@@ -886,35 +895,35 @@ function ot(t, e) {
886
895
  });
887
896
  }, 1);
888
897
  }
889
- function ce(t) {
890
- ye ? cancelIdleCallback(t) : clearTimeout(t);
898
+ function de(t) {
899
+ Ee ? cancelIdleCallback(t) : clearTimeout(t);
891
900
  }
892
- const Ee = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])';
893
- function Y(t) {
901
+ const Se = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])';
902
+ function j(t) {
894
903
  return (t.__editingCellCount ?? 0) > 0;
895
904
  }
896
- function j(t) {
905
+ function K(t) {
897
906
  t.__editingCellCount = 0, t.removeAttribute("data-has-editing"), t.querySelectorAll(".cell.editing").forEach((o) => o.classList.remove("editing"));
898
907
  }
899
- const Se = document.createElement("template");
900
- Se.innerHTML = '<div class="cell" role="gridcell" part="cell"></div>';
908
+ const Re = document.createElement("template");
909
+ Re.innerHTML = '<div class="cell" role="gridcell" part="cell"></div>';
901
910
  const Te = document.createElement("template");
902
911
  Te.innerHTML = '<div class="data-grid-row" role="row" part="row"></div>';
903
- function it() {
904
- return Se.content.firstElementChild.cloneNode(!0);
905
- }
906
912
  function nt() {
913
+ return Re.content.firstElementChild.cloneNode(!0);
914
+ }
915
+ function rt() {
907
916
  return Te.content.firstElementChild.cloneNode(!0);
908
917
  }
909
- function U(t) {
918
+ function $(t) {
910
919
  t.__cellDisplayCache = void 0, t.__cellCacheEpoch = void 0, t.__hasSpecialColumns = void 0;
911
920
  }
912
- function rt(t, e, o, i, n) {
921
+ function st(t, e, o, i, n) {
913
922
  const r = Math.max(0, o - e), s = t._bodyEl, l = t._visibleColumns, a = l.length;
914
923
  let c = t.__cachedHeaderRowCount;
915
924
  for (c === void 0 && (c = t.shadowRoot?.querySelector(".header-group-row") ? 2 : 1, t.__cachedHeaderRowCount = c); t._rowPool.length < r; ) {
916
- const d = nt();
917
- d.addEventListener("click", (f) => de(t, f, d)), d.addEventListener("dblclick", (f) => de(t, f, d)), t._rowPool.push(d);
925
+ const d = rt();
926
+ d.addEventListener("click", (f) => he(t, f, d)), d.addEventListener("dblclick", (f) => he(t, f, d)), t._rowPool.push(d);
918
927
  }
919
928
  if (t._rowPool.length > r) {
920
929
  for (let d = r; d < t._rowPool.length; d++) {
@@ -923,44 +932,44 @@ function rt(t, e, o, i, n) {
923
932
  }
924
933
  t._rowPool.length = r;
925
934
  }
926
- const u = n && t.__hasRenderRowPlugins !== !1;
935
+ const h = n && t.__hasRenderRowPlugins !== !1;
927
936
  for (let d = 0; d < r; d++) {
928
- const f = e + d, p = t._rows[f], h = t._rowPool[d];
929
- if (h.setAttribute("aria-rowindex", String(f + c + 1)), u && n(p, h, f)) {
930
- h.__epoch = i, h.__rowDataRef = p, h.parentNode !== s && s.appendChild(h);
937
+ const f = e + d, p = t._rows[f], u = t._rowPool[d];
938
+ if (u.setAttribute("aria-rowindex", String(f + c + 1)), h && n(p, u, f)) {
939
+ u.__epoch = i, u.__rowDataRef = p, u.parentNode !== s && s.appendChild(u);
931
940
  continue;
932
941
  }
933
- const g = h.__epoch, m = h.__rowDataRef, b = h.children.length, w = g === i && b === a, C = m !== p;
942
+ const g = u.__epoch, m = u.__rowDataRef, b = u.children.length, w = g === i && b === a, C = m !== p;
934
943
  let y = !1;
935
944
  if (w && C) {
936
945
  for (let x = 0; x < a; x++)
937
- if (l[x].externalView && !h.querySelector(`.cell[data-col="${x}"] [data-external-view]`)) {
946
+ if (l[x].externalView && !u.querySelector(`.cell[data-col="${x}"] [data-external-view]`)) {
938
947
  y = !0;
939
948
  break;
940
949
  }
941
950
  }
942
951
  if (!w || y) {
943
- const x = Y(h), v = t._activeEditRows === f;
944
- x && !v ? (h.__isCustomRow && (h.className = "data-grid-row", h.setAttribute("role", "row"), h.__isCustomRow = !1), j(h), I(t, h, p, f), h.__epoch = i, h.__rowDataRef = p) : x && v ? (K(t, h, p, f), h.__rowDataRef = p) : (h.__isCustomRow && (h.className = "data-grid-row", h.setAttribute("role", "row"), h.__isCustomRow = !1), I(t, h, p, f), h.__epoch = i, h.__rowDataRef = p);
952
+ const x = j(u), v = t._activeEditRows === f;
953
+ x && !v ? (u.__isCustomRow && (u.className = "data-grid-row", u.setAttribute("role", "row"), u.__isCustomRow = !1), K(u), B(t, u, p, f), u.__epoch = i, u.__rowDataRef = p) : x && v ? (Z(t, u, p, f), u.__rowDataRef = p) : (u.__isCustomRow && (u.className = "data-grid-row", u.setAttribute("role", "row"), u.__isCustomRow = !1), B(t, u, p, f), u.__epoch = i, u.__rowDataRef = p);
945
954
  } else if (C) {
946
- const x = Y(h), v = t._activeEditRows === f;
947
- x && !v ? (j(h), I(t, h, p, f), h.__epoch = i, h.__rowDataRef = p) : (K(t, h, p, f), h.__rowDataRef = p);
955
+ const x = j(u), v = t._activeEditRows === f;
956
+ x && !v ? (K(u), B(t, u, p, f), u.__epoch = i, u.__rowDataRef = p) : (Z(t, u, p, f), u.__rowDataRef = p);
948
957
  } else {
949
- const x = Y(h), v = t._activeEditRows === f;
950
- x && !v ? (j(h), I(t, h, p, f), h.__epoch = i, h.__rowDataRef = p) : K(t, h, p, f);
958
+ const x = j(u), v = t._activeEditRows === f;
959
+ x && !v ? (K(u), B(t, u, p, f), u.__epoch = i, u.__rowDataRef = p) : Z(t, u, p, f);
951
960
  }
952
- const S = t._changedRowIndices?.has(f) ?? !1, W = h.classList.contains("changed");
953
- S !== W && h.classList.toggle("changed", S), h.parentNode !== s && s.appendChild(h);
961
+ const R = t._changedRowIndices?.has(f) ?? !1, U = u.classList.contains("changed");
962
+ R !== U && u.classList.toggle("changed", R), u.parentNode !== s && s.appendChild(u);
954
963
  }
955
964
  }
956
- function K(t, e, o, i) {
957
- const n = e.children, r = t._visibleColumns, s = r.length, l = n.length, a = s < l ? s : l, c = t._focusRow, u = t._focusCol;
965
+ function Z(t, e, o, i) {
966
+ const n = e.children, r = t._visibleColumns, s = r.length, l = n.length, a = s < l ? s : l, c = t._focusRow, h = t._focusCol;
958
967
  let d = t.__hasSpecialColumns;
959
968
  if (d === void 0) {
960
969
  d = !1;
961
970
  for (let p = 0; p < s; p++) {
962
- const h = r[p];
963
- if (h.__viewTemplate || h.__compiledView || h.renderer || h.viewRenderer || h.externalView || h.format || h.type === "date" || h.type === "boolean") {
971
+ const u = r[p];
972
+ if (u.__viewTemplate || u.__compiledView || u.renderer || u.viewRenderer || u.externalView || u.format || u.type === "date" || u.type === "boolean") {
964
973
  d = !0;
965
974
  break;
966
975
  }
@@ -970,49 +979,49 @@ function K(t, e, o, i) {
970
979
  const f = String(i);
971
980
  if (!d) {
972
981
  for (let p = 0; p < a; p++) {
973
- const h = n[p], g = o[r[p].field];
974
- h.textContent = g == null ? "" : String(g), h.getAttribute("data-row") !== f && h.setAttribute("data-row", f);
975
- const m = c === i && u === p, b = h.classList.contains("cell-focus");
976
- m !== b && (h.classList.toggle("cell-focus", m), h.setAttribute("aria-selected", String(m)));
982
+ const u = n[p], g = o[r[p].field];
983
+ u.textContent = g == null ? "" : String(g), u.getAttribute("data-row") !== f && u.setAttribute("data-row", f);
984
+ const m = c === i && h === p, b = u.classList.contains("cell-focus");
985
+ m !== b && (u.classList.toggle("cell-focus", m), u.setAttribute("aria-selected", String(m)));
977
986
  }
978
987
  return;
979
988
  }
980
989
  for (let p = 0; p < a; p++)
981
990
  if (r[p].externalView && !n[p].querySelector("[data-external-view]")) {
982
- I(t, e, o, i);
991
+ B(t, e, o, i);
983
992
  return;
984
993
  }
985
994
  for (let p = 0; p < a; p++) {
986
- const h = r[p], g = n[p];
995
+ const u = r[p], g = n[p];
987
996
  g.getAttribute("data-row") !== f && g.setAttribute("data-row", f);
988
- const m = c === i && u === p, b = g.classList.contains("cell-focus");
997
+ const m = c === i && h === p, b = g.classList.contains("cell-focus");
989
998
  if (m !== b && (g.classList.toggle("cell-focus", m), g.setAttribute("aria-selected", String(m))), g.classList.contains("editing")) continue;
990
- const _ = h.renderer || h.viewRenderer;
999
+ const _ = u.renderer || u.viewRenderer;
991
1000
  if (_) {
992
- const y = o[h.field], S = _({ row: o, value: y, field: h.field, column: h, cellEl: g });
993
- typeof S == "string" ? g.innerHTML = V(S) : S instanceof Node ? S.parentElement !== g && (g.innerHTML = "", g.appendChild(S)) : S == null && (g.textContent = y == null ? "" : String(y));
1001
+ const y = o[u.field], R = _({ row: o, value: y, field: u.field, column: u, cellEl: g });
1002
+ typeof R == "string" ? g.innerHTML = G(R) : R instanceof Node ? R.parentElement !== g && (g.innerHTML = "", g.appendChild(R)) : R == null && (g.textContent = y == null ? "" : String(y));
994
1003
  continue;
995
1004
  }
996
- if (h.__viewTemplate || h.__compiledView || h.externalView)
1005
+ if (u.__viewTemplate || u.__compiledView || u.externalView)
997
1006
  continue;
998
- const w = o[h.field];
1007
+ const w = o[u.field];
999
1008
  let C;
1000
- if (h.format)
1009
+ if (u.format)
1001
1010
  try {
1002
- const y = h.format(w, o);
1011
+ const y = u.format(w, o);
1003
1012
  C = y == null ? "" : String(y);
1004
1013
  } catch (y) {
1005
- console.warn(`[tbw-grid] Format error in column '${h.field}':`, y), C = w == null ? "" : String(w);
1014
+ console.warn(`[tbw-grid] Format error in column '${u.field}':`, y), C = w == null ? "" : String(w);
1006
1015
  }
1007
- else h.type === "date" ? (C = Ce(w), g.textContent = C) : h.type === "boolean" ? g.innerHTML = ve(!!w) : (C = w == null ? "" : String(w), g.textContent = C);
1016
+ else u.type === "date" ? (C = _e(w), g.textContent = C) : u.type === "boolean" ? g.innerHTML = Ce(!!w) : (C = w == null ? "" : String(w), g.textContent = C);
1008
1017
  }
1009
1018
  }
1010
- function I(t, e, o, i) {
1019
+ function B(t, e, o, i) {
1011
1020
  e.innerHTML = "";
1012
1021
  const n = t._visibleColumns, r = n.length, s = t._focusRow, l = t._focusCol, a = t, c = document.createDocumentFragment();
1013
- for (let u = 0; u < r; u++) {
1014
- const d = n[u], f = it();
1015
- f.setAttribute("aria-colindex", String(u + 1)), f.setAttribute("data-col", String(u)), f.setAttribute("data-row", String(i)), f.setAttribute("data-field", d.field), d.type && f.setAttribute("data-type", d.type);
1022
+ for (let h = 0; h < r; h++) {
1023
+ const d = n[h], f = nt();
1024
+ f.setAttribute("aria-colindex", String(h + 1)), f.setAttribute("data-col", String(h)), f.setAttribute("data-row", String(i)), f.setAttribute("data-field", d.field), d.type && f.setAttribute("data-type", d.type);
1016
1025
  let p = o[d.field];
1017
1026
  if (d.format)
1018
1027
  try {
@@ -1020,11 +1029,11 @@ function I(t, e, o, i) {
1020
1029
  } catch (w) {
1021
1030
  console.warn(`[tbw-grid] Format error in column '${d.field}':`, w);
1022
1031
  }
1023
- const h = d.__compiledView, g = d.__viewTemplate, m = d.renderer || d.viewRenderer, b = d.externalView;
1032
+ const u = d.__compiledView, g = d.__viewTemplate, m = d.renderer || d.viewRenderer, b = d.externalView;
1024
1033
  let _ = !1;
1025
1034
  if (m) {
1026
1035
  const w = m({ row: o, value: p, field: d.field, column: d, cellEl: f });
1027
- typeof w == "string" ? (f.innerHTML = V(w), _ = !0) : w instanceof Node ? w.parentElement !== f && (f.textContent = "", f.appendChild(w)) : w == null && (f.textContent = p == null ? "" : String(p));
1036
+ typeof w == "string" ? (f.innerHTML = G(w), _ = !0) : w instanceof Node ? w.parentElement !== f && (f.textContent = "", f.appendChild(w)) : w == null && (f.textContent = p == null ? "" : String(p));
1028
1037
  } else if (b) {
1029
1038
  const w = b, C = document.createElement("div");
1030
1039
  C.setAttribute("data-external-view", ""), C.setAttribute("data-field", d.field), f.appendChild(C);
@@ -1032,8 +1041,8 @@ function I(t, e, o, i) {
1032
1041
  if (w.mount)
1033
1042
  try {
1034
1043
  w.mount({ placeholder: C, context: y, spec: w });
1035
- } catch (S) {
1036
- console.warn(`[tbw-grid] External view mount error for column '${d.field}':`, S);
1044
+ } catch (R) {
1045
+ console.warn(`[tbw-grid] External view mount error for column '${d.field}':`, R);
1037
1046
  }
1038
1047
  else
1039
1048
  queueMicrotask(() => {
@@ -1045,31 +1054,31 @@ function I(t, e, o, i) {
1045
1054
  detail: { placeholder: C, spec: w, context: y }
1046
1055
  })
1047
1056
  );
1048
- } catch (S) {
1049
- console.warn(`[tbw-grid] External view event dispatch error for column '${d.field}':`, S);
1057
+ } catch (R) {
1058
+ console.warn(`[tbw-grid] External view event dispatch error for column '${d.field}':`, R);
1050
1059
  }
1051
1060
  });
1052
1061
  C.setAttribute("data-mounted", "");
1053
- } else if (h) {
1054
- const w = h({ row: o, value: p, field: d.field, column: d }), C = h.__blocked;
1055
- f.innerHTML = C ? "" : V(w), _ = !0, C && (f.textContent = "", f.setAttribute("data-blocked-template", ""));
1062
+ } else if (u) {
1063
+ const w = u({ row: o, value: p, field: d.field, column: d }), C = u.__blocked;
1064
+ f.innerHTML = C ? "" : G(w), _ = !0, C && (f.textContent = "", f.setAttribute("data-blocked-template", ""));
1056
1065
  } else if (g) {
1057
1066
  const w = g.innerHTML;
1058
- /Reflect\.|\bProxy\b|ownKeys\(/.test(w) ? (f.textContent = "", f.setAttribute("data-blocked-template", "")) : (f.innerHTML = V(me(w, { row: o, value: p })), _ = !0);
1067
+ /Reflect\.|\bProxy\b|ownKeys\(/.test(w) ? (f.textContent = "", f.setAttribute("data-blocked-template", "")) : (f.innerHTML = G(ve(w, { row: o, value: p })), _ = !0);
1059
1068
  } else
1060
- d.type === "date" ? f.textContent = Ce(p) : d.type === "boolean" ? f.innerHTML = ve(!!p) : f.textContent = p == null ? "" : String(p);
1069
+ d.type === "date" ? f.textContent = _e(p) : d.type === "boolean" ? f.innerHTML = Ce(!!p) : f.textContent = p == null ? "" : String(p);
1061
1070
  if (_) {
1062
- Xe(f);
1071
+ Ye(f);
1063
1072
  const w = f.textContent || "";
1064
1073
  /Proxy|Reflect\.ownKeys/.test(w) && (f.textContent = w.replace(/Proxy|Reflect\.ownKeys/g, "").trim(), /Proxy|Reflect\.ownKeys/.test(f.textContent || "") && (f.textContent = ""));
1065
1074
  }
1066
- f.hasAttribute("data-blocked-template") && (f.textContent || "").trim().length && (f.textContent = ""), d.editable ? f.tabIndex = 0 : d.type === "boolean" && (f.hasAttribute("tabindex") || (f.tabIndex = 0)), s === i && l === u ? (f.classList.add("cell-focus"), f.setAttribute("aria-selected", "true")) : f.setAttribute("aria-selected", "false"), c.appendChild(f);
1075
+ f.hasAttribute("data-blocked-template") && (f.textContent || "").trim().length && (f.textContent = ""), d.editable ? f.tabIndex = 0 : d.type === "boolean" && (f.hasAttribute("tabindex") || (f.tabIndex = 0)), s === i && l === h ? (f.classList.add("cell-focus"), f.setAttribute("aria-selected", "true")) : f.setAttribute("aria-selected", "false"), c.appendChild(f);
1067
1076
  }
1068
1077
  e.appendChild(c);
1069
1078
  }
1070
- function de(t, e, o, i) {
1079
+ function he(t, e, o, i) {
1071
1080
  if (e.target?.closest(".resize-handle")) return;
1072
- const n = o.querySelector(".cell[data-row]"), r = _e(n);
1081
+ const n = o.querySelector(".cell[data-row]"), r = ye(n);
1073
1082
  if (r < 0) return;
1074
1083
  const s = t._rows[r];
1075
1084
  if (!s || t._dispatchRowClick?.(e, r, s, o))
@@ -1082,30 +1091,30 @@ function de(t, e, o, i) {
1082
1091
  return;
1083
1092
  const c = t._focusRow !== r || t._focusCol !== a;
1084
1093
  if (t._focusRow = r, t._focusCol = a, l.classList.contains("editing")) {
1085
- c && (Q(t.shadowRoot ?? t._bodyEl), l.classList.add("cell-focus"));
1086
- const u = l.querySelector(Ee);
1094
+ c && (ee(t.shadowRoot ?? t._bodyEl), l.classList.add("cell-focus"));
1095
+ const h = l.querySelector(Se);
1087
1096
  try {
1088
- u?.focus({ preventScroll: !0 });
1097
+ h?.focus({ preventScroll: !0 });
1089
1098
  } catch {
1090
1099
  }
1091
1100
  return;
1092
1101
  }
1093
- B(t);
1102
+ k(t);
1094
1103
  }
1095
1104
  }
1096
1105
  }
1097
- function st(t, e) {
1106
+ function lt(t, e) {
1098
1107
  if (t._dispatchKeyDown?.(e))
1099
1108
  return;
1100
- const o = t._rows.length - 1, i = t._visibleColumns.length - 1, n = t._activeEditRows !== void 0 && t._activeEditRows !== -1, s = t._visibleColumns[t._focusCol]?.type, l = e.composedPath?.() ?? [], a = l.length ? l[0] : e.target, c = (u) => {
1101
- if (!u) return !1;
1102
- const d = u.tagName;
1103
- return !!(d === "INPUT" || d === "SELECT" || d === "TEXTAREA" || u.isContentEditable);
1109
+ const o = t._rows.length - 1, i = t._visibleColumns.length - 1, n = t._activeEditRows !== void 0 && t._activeEditRows !== -1, s = t._visibleColumns[t._focusCol]?.type, l = e.composedPath?.() ?? [], a = l.length ? l[0] : e.target, c = (h) => {
1110
+ if (!h) return !1;
1111
+ const d = h.tagName;
1112
+ return !!(d === "INPUT" || d === "SELECT" || d === "TEXTAREA" || h.isContentEditable);
1104
1113
  };
1105
1114
  if (!(c(a) && (e.key === "Home" || e.key === "End")) && !(c(a) && (e.key === "ArrowUp" || e.key === "ArrowDown") && a.tagName === "INPUT" && a.type === "number") && !(c(a) && (e.key === "ArrowLeft" || e.key === "ArrowRight")) && !(c(a) && (e.key === "Enter" || e.key === "Escape")) && !(n && (s === "select" || s === "typeahead") && (e.key === "ArrowDown" || e.key === "ArrowUp"))) {
1106
1115
  switch (e.key) {
1107
1116
  case "Tab": {
1108
- e.preventDefault(), !e.shiftKey ? t._focusCol < i ? t._focusCol += 1 : (typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow < o && (t._focusRow += 1, t._focusCol = 0)) : t._focusCol > 0 ? t._focusCol -= 1 : t._focusRow > 0 && (typeof t.commitActiveRowEdit == "function" && t._activeEditRows === t._focusRow && t.commitActiveRowEdit(), t._focusRow -= 1, t._focusCol = i), B(t);
1117
+ e.preventDefault(), !e.shiftKey ? t._focusCol < i ? t._focusCol += 1 : (typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow < o && (t._focusRow += 1, t._focusCol = 0)) : t._focusCol > 0 ? t._focusCol -= 1 : t._focusRow > 0 && (typeof t.commitActiveRowEdit == "function" && t._activeEditRows === t._focusRow && t.commitActiveRowEdit(), t._focusRow -= 1, t._focusCol = i), k(t);
1109
1118
  return;
1110
1119
  }
1111
1120
  case "ArrowDown":
@@ -1121,10 +1130,10 @@ function st(t, e) {
1121
1130
  t._focusCol = Math.max(0, t._focusCol - 1), e.preventDefault();
1122
1131
  break;
1123
1132
  case "Home":
1124
- (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = 0), t._focusCol = 0, e.preventDefault(), B(t, { forceScrollLeft: !0 });
1133
+ (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = 0), t._focusCol = 0, e.preventDefault(), k(t, { forceScrollLeft: !0 });
1125
1134
  return;
1126
1135
  case "End":
1127
- (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = o), t._focusCol = i, e.preventDefault(), B(t, { forceScrollRight: !0 });
1136
+ (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = o), t._focusCol = i, e.preventDefault(), k(t, { forceScrollRight: !0 });
1128
1137
  return;
1129
1138
  case "PageDown":
1130
1139
  t._focusRow = Math.min(o, t._focusRow + 20), e.preventDefault();
@@ -1133,34 +1142,41 @@ function st(t, e) {
1133
1142
  t._focusRow = Math.max(0, t._focusRow - 20), e.preventDefault();
1134
1143
  break;
1135
1144
  // NOTE: Enter key is handled by EditingPlugin. If no plugin handles it,
1136
- // we dispatch an activate-cell event for custom handling but don't block navigation.
1137
- case "Enter":
1138
- t.dispatchEvent(
1139
- new CustomEvent("activate-cell", { detail: { row: t._focusRow, col: t._focusCol } })
1140
- );
1145
+ // we dispatch a cancelable activate-cell event for custom handling.
1146
+ case "Enter": {
1147
+ const h = new CustomEvent("activate-cell", {
1148
+ cancelable: !0,
1149
+ detail: { row: t._focusRow, col: t._focusCol }
1150
+ });
1151
+ if (t.dispatchEvent(h), h.defaultPrevented) {
1152
+ e.preventDefault();
1153
+ return;
1154
+ }
1141
1155
  break;
1156
+ }
1142
1157
  default:
1143
1158
  return;
1144
1159
  }
1145
- B(t);
1160
+ k(t);
1146
1161
  }
1147
1162
  }
1148
- function B(t, e) {
1163
+ function k(t, e) {
1149
1164
  if (t._virtualization?.enabled) {
1150
- const { rowHeight: s, container: l, viewportEl: a } = t._virtualization, c = l, u = a?.clientHeight ?? c?.clientHeight ?? 0;
1151
- if (c && u > 0) {
1165
+ const { rowHeight: s, container: l, viewportEl: a } = t._virtualization, c = l, h = a?.clientHeight ?? c?.clientHeight ?? 0;
1166
+ if (c && h > 0) {
1152
1167
  const d = t._focusRow * s;
1153
- d < c.scrollTop ? c.scrollTop = d : d + s > c.scrollTop + u && (c.scrollTop = d - u + s);
1168
+ d < c.scrollTop ? c.scrollTop = d : d + s > c.scrollTop + h && (c.scrollTop = d - h + s);
1154
1169
  }
1155
1170
  }
1156
1171
  const o = t._activeEditRows !== void 0 && t._activeEditRows !== -1;
1157
- o || t.refreshVirtualWindow(!1), Q(t._bodyEl), Array.from(t._bodyEl.querySelectorAll('[aria-selected="true"]')).forEach((s) => {
1172
+ o || t.refreshVirtualWindow(!1), ee(t._bodyEl), Array.from(t._bodyEl.querySelectorAll('[aria-selected="true"]')).forEach((s) => {
1158
1173
  s.setAttribute("aria-selected", "false");
1159
1174
  });
1160
1175
  const i = t._focusRow, n = t._virtualization.start ?? 0, r = t._virtualization.end ?? t._rows.length;
1161
1176
  if (i >= n && i < r) {
1162
- const s = t._bodyEl.querySelectorAll(".data-grid-row")[i - n], l = s?.children[t._focusCol];
1163
- if (l) {
1177
+ const s = t._bodyEl.querySelectorAll(".data-grid-row")[i - n];
1178
+ let l = s?.children[t._focusCol];
1179
+ if ((!l || !l.classList?.contains("cell")) && (l = s?.querySelector(`.cell[data-col="${t._focusCol}"]`) ?? s?.querySelector(".cell[data-col]")), l) {
1164
1180
  l.classList.add("cell-focus"), l.setAttribute("aria-selected", "true");
1165
1181
  const a = t.shadowRoot?.querySelector(".tbw-scroll-area");
1166
1182
  if (a && l && !o)
@@ -1171,12 +1187,12 @@ function B(t, e) {
1171
1187
  else {
1172
1188
  const c = t._getHorizontalScrollOffsets?.(s ?? void 0, l) ?? { left: 0, right: 0 };
1173
1189
  if (!c.skipScroll) {
1174
- const u = l.getBoundingClientRect(), d = a.getBoundingClientRect(), f = u.left - d.left + a.scrollLeft, p = f + u.width, h = a.scrollLeft + c.left, g = a.scrollLeft + a.clientWidth - c.right;
1175
- f < h ? a.scrollLeft = f - c.left : p > g && (a.scrollLeft = p - a.clientWidth + c.right);
1190
+ const h = l.getBoundingClientRect(), d = a.getBoundingClientRect(), f = h.left - d.left + a.scrollLeft, p = f + h.width, u = a.scrollLeft + c.left, g = a.scrollLeft + a.clientWidth - c.right;
1191
+ f < u ? a.scrollLeft = f - c.left : p > g && (a.scrollLeft = p - a.clientWidth + c.right);
1176
1192
  }
1177
1193
  }
1178
1194
  if (t._activeEditRows !== void 0 && t._activeEditRows !== -1 && l.classList.contains("editing")) {
1179
- const c = l.querySelector(Ee);
1195
+ const c = l.querySelector(Se);
1180
1196
  if (c && document.activeElement !== c)
1181
1197
  try {
1182
1198
  c.focus({ preventScroll: !0 });
@@ -1192,8 +1208,8 @@ function B(t, e) {
1192
1208
  }
1193
1209
  }
1194
1210
  }
1195
- var T = /* @__PURE__ */ ((t) => (t[t.STYLE = 1] = "STYLE", t[t.VIRTUALIZATION = 2] = "VIRTUALIZATION", t[t.HEADER = 3] = "HEADER", t[t.ROWS = 4] = "ROWS", t[t.COLUMNS = 5] = "COLUMNS", t[t.FULL = 6] = "FULL", t))(T || {});
1196
- class lt {
1211
+ var S = /* @__PURE__ */ ((t) => (t[t.STYLE = 1] = "STYLE", t[t.VIRTUALIZATION = 2] = "VIRTUALIZATION", t[t.HEADER = 3] = "HEADER", t[t.ROWS = 4] = "ROWS", t[t.COLUMNS = 5] = "COLUMNS", t[t.FULL = 6] = "FULL", t))(S || {});
1212
+ class at {
1197
1213
  #o;
1198
1214
  /** Current pending phase (0 = none pending) */
1199
1215
  #c = 0;
@@ -1272,15 +1288,15 @@ class lt {
1272
1288
  this.#c = 0, e >= 5 && this.#o.mergeConfig(), e >= 4 && this.#o.processRows(), e >= 5 && (this.#o.processColumns(), this.#o.updateTemplate()), e >= 3 && this.#o.renderHeader(), e >= 2 && this.#o.renderVirtualWindow(), e >= 1 && this.#o.afterRender(), !this.#h && this.#n && (this.#h = !0, this.#n()), this.#r && (this.#r(), this.#r = null, this.#d = null);
1273
1289
  }
1274
1290
  }
1275
- function at(t) {
1291
+ function ct(t) {
1276
1292
  let e = null, o = null, i = null, n = null;
1277
1293
  const r = (a) => {
1278
1294
  if (!e) return;
1279
- const c = a.clientX - e.startX, u = Math.max(40, e.startWidth + c), d = t._visibleColumns[e.colIndex];
1280
- d.width = u, d.__userResized = !0, d.__renderedWidth = u, o == null && (o = requestAnimationFrame(() => {
1295
+ const c = a.clientX - e.startX, h = Math.max(40, e.startWidth + c), d = t._visibleColumns[e.colIndex];
1296
+ d.width = h, d.__userResized = !0, d.__renderedWidth = h, o == null && (o = requestAnimationFrame(() => {
1281
1297
  o = null, t.updateTemplate?.();
1282
1298
  })), t.dispatchEvent(
1283
- new CustomEvent("column-resize", { detail: { field: d.field, width: u } })
1299
+ new CustomEvent("column-resize", { detail: { field: d.field, width: h } })
1284
1300
  );
1285
1301
  };
1286
1302
  let s = !1;
@@ -1294,9 +1310,9 @@ function at(t) {
1294
1310
  get isResizing() {
1295
1311
  return e !== null || s;
1296
1312
  },
1297
- start(a, c, u) {
1313
+ start(a, c, h) {
1298
1314
  a.preventDefault();
1299
- const d = u.getBoundingClientRect();
1315
+ const d = h.getBoundingClientRect();
1300
1316
  e = { startX: a.clientX, colIndex: c, startWidth: d.width }, window.addEventListener("mousemove", r), window.addEventListener("mouseup", l), i === null && (i = document.documentElement.style.cursor), document.documentElement.style.cursor = "e-resize", n === null && (n = document.body.style.userSelect), document.body.style.userSelect = "none";
1301
1317
  },
1302
1318
  resetColumn(a) {
@@ -1310,7 +1326,7 @@ function at(t) {
1310
1326
  }
1311
1327
  };
1312
1328
  }
1313
- function $(t, e, o) {
1329
+ function F(t, e, o) {
1314
1330
  const i = document.createElement(t);
1315
1331
  if (e)
1316
1332
  for (const n in e) {
@@ -1319,7 +1335,7 @@ function $(t, e, o) {
1319
1335
  }
1320
1336
  return i;
1321
1337
  }
1322
- function R(t, e) {
1338
+ function T(t, e) {
1323
1339
  const o = document.createElement("div");
1324
1340
  if (t && (o.className = t), e)
1325
1341
  for (const i in e) {
@@ -1328,7 +1344,7 @@ function R(t, e) {
1328
1344
  }
1329
1345
  return o;
1330
1346
  }
1331
- function Re(t, e, o) {
1347
+ function xe(t, e, o) {
1332
1348
  const i = document.createElement("button");
1333
1349
  if (t && (i.className = t), e)
1334
1350
  for (const n in e) {
@@ -1337,12 +1353,12 @@ function Re(t, e, o) {
1337
1353
  }
1338
1354
  return i;
1339
1355
  }
1340
- function he(t) {
1356
+ function ue(t) {
1341
1357
  const e = document.createElement("slot");
1342
1358
  return t && (e.name = t), e;
1343
1359
  }
1344
- const xe = document.createElement("template");
1345
- xe.innerHTML = `
1360
+ const Ae = document.createElement("template");
1361
+ Ae.innerHTML = `
1346
1362
  <div class="tbw-scroll-area">
1347
1363
  <div class="rows-body-wrapper">
1348
1364
  <div class="rows-body" role="grid">
@@ -1361,34 +1377,34 @@ xe.innerHTML = `
1361
1377
  <div class="faux-vscroll-spacer"></div>
1362
1378
  </div>
1363
1379
  `;
1364
- function Ae() {
1365
- return xe.content.cloneNode(!0);
1380
+ function Pe() {
1381
+ return Ae.content.cloneNode(!0);
1366
1382
  }
1367
- function ue(t) {
1368
- const e = document.createDocumentFragment(), o = R(t.hasShell ? "tbw-grid-root has-shell" : "tbw-grid-root");
1383
+ function fe(t) {
1384
+ const e = document.createDocumentFragment(), o = T(t.hasShell ? "tbw-grid-root has-shell" : "tbw-grid-root");
1369
1385
  if (t.hasShell && t.shellHeader && t.shellBody)
1370
1386
  o.appendChild(t.shellHeader), o.appendChild(t.shellBody);
1371
1387
  else {
1372
- const i = R("tbw-grid-content");
1373
- i.appendChild(Ae()), o.appendChild(i);
1388
+ const i = T("tbw-grid-content");
1389
+ i.appendChild(Pe()), o.appendChild(i);
1374
1390
  }
1375
1391
  return e.appendChild(o), e;
1376
1392
  }
1377
- function ct(t) {
1378
- const e = R("tbw-shell-header", { part: "shell-header", role: "presentation" });
1393
+ function dt(t) {
1394
+ const e = T("tbw-shell-header", { part: "shell-header", role: "presentation" });
1379
1395
  if (t.title) {
1380
- const r = R("tbw-shell-title");
1396
+ const r = T("tbw-shell-title");
1381
1397
  r.textContent = t.title, e.appendChild(r);
1382
1398
  }
1383
- const o = R("tbw-shell-content", { part: "shell-content", role: "presentation" });
1384
- o.appendChild(he("header-content")), e.appendChild(o);
1385
- const i = R("tbw-shell-toolbar", { part: "shell-toolbar", role: "presentation" });
1399
+ const o = T("tbw-shell-content", { part: "shell-content", role: "presentation" });
1400
+ o.appendChild(ue("header-content")), e.appendChild(o);
1401
+ const i = T("tbw-shell-toolbar", { part: "shell-toolbar", role: "presentation" });
1386
1402
  for (const r of t.configButtons)
1387
- (r.hasElement || r.hasRender) && i.appendChild(R("tbw-toolbar-btn-slot", { "data-btn-slot": r.id }));
1403
+ (r.hasElement || r.hasRender) && i.appendChild(T("tbw-toolbar-btn-slot", { "data-btn-slot": r.id }));
1388
1404
  for (const r of t.apiButtons)
1389
- (r.hasElement || r.hasRender) && i.appendChild(R("tbw-toolbar-btn-slot", { "data-btn-slot": r.id }));
1390
- if (i.appendChild(he("toolbar")), (t.configButtons.some((r) => r.hasElement || r.hasRender) || t.apiButtons.some((r) => r.hasElement || r.hasRender)) && t.hasPanels && i.appendChild(R("tbw-toolbar-separator")), t.hasPanels) {
1391
- const r = Re(t.isPanelOpen ? "tbw-toolbar-btn active" : "tbw-toolbar-btn", {
1405
+ (r.hasElement || r.hasRender) && i.appendChild(T("tbw-toolbar-btn-slot", { "data-btn-slot": r.id }));
1406
+ if (i.appendChild(ue("toolbar")), (t.configButtons.some((r) => r.hasElement || r.hasRender) || t.apiButtons.some((r) => r.hasElement || r.hasRender)) && t.hasPanels && i.appendChild(T("tbw-toolbar-separator")), t.hasPanels) {
1407
+ const r = xe(t.isPanelOpen ? "tbw-toolbar-btn active" : "tbw-toolbar-btn", {
1392
1408
  "data-panel-toggle": "",
1393
1409
  title: "Settings",
1394
1410
  "aria-label": "Toggle settings panel",
@@ -1399,12 +1415,12 @@ function ct(t) {
1399
1415
  }
1400
1416
  return e.appendChild(i), e;
1401
1417
  }
1402
- function dt(t) {
1403
- const e = R("tbw-shell-body"), o = t.panels.length > 0, i = t.panels.length === 1, n = R("tbw-grid-content");
1404
- n.appendChild(Ae());
1418
+ function ht(t) {
1419
+ const e = T("tbw-shell-body"), o = t.panels.length > 0, i = t.panels.length === 1, n = T("tbw-grid-content");
1420
+ n.appendChild(Pe());
1405
1421
  let r = null;
1406
1422
  if (o) {
1407
- r = $("aside", {
1423
+ r = F("aside", {
1408
1424
  class: t.isPanelOpen ? "tbw-tool-panel open" : "tbw-tool-panel",
1409
1425
  part: "tool-panel",
1410
1426
  "data-position": t.position,
@@ -1413,29 +1429,29 @@ function dt(t) {
1413
1429
  });
1414
1430
  const s = t.position === "left" ? "right" : "left";
1415
1431
  r.appendChild(
1416
- R("tbw-tool-panel-resize", {
1432
+ T("tbw-tool-panel-resize", {
1417
1433
  "data-resize-handle": "",
1418
1434
  "data-handle-position": s,
1419
1435
  "aria-hidden": "true"
1420
1436
  })
1421
1437
  );
1422
- const l = R("tbw-tool-panel-content", { role: "presentation" }), a = R("tbw-accordion");
1438
+ const l = T("tbw-tool-panel-content", { role: "presentation" }), a = T("tbw-accordion");
1423
1439
  for (const c of t.panels) {
1424
- const u = `tbw-accordion-section${c.isExpanded ? " expanded" : ""}${i ? " single" : ""}`, d = R(u, { "data-section": c.id }), f = Re("tbw-accordion-header", {
1440
+ const h = `tbw-accordion-section${c.isExpanded ? " expanded" : ""}${i ? " single" : ""}`, d = T(h, { "data-section": c.id }), f = xe("tbw-accordion-header", {
1425
1441
  "aria-expanded": String(c.isExpanded),
1426
1442
  "aria-controls": `tbw-section-${c.id}`
1427
1443
  });
1428
1444
  if (i && f.setAttribute("aria-disabled", "true"), c.icon) {
1429
- const h = $("span", { class: "tbw-accordion-icon" });
1430
- h.innerHTML = c.icon, f.appendChild(h);
1445
+ const u = F("span", { class: "tbw-accordion-icon" });
1446
+ u.innerHTML = c.icon, f.appendChild(u);
1431
1447
  }
1432
- const p = $("span", { class: "tbw-accordion-title" });
1448
+ const p = F("span", { class: "tbw-accordion-title" });
1433
1449
  if (p.textContent = c.title, f.appendChild(p), !i) {
1434
- const h = $("span", { class: "tbw-accordion-chevron" });
1435
- h.innerHTML = c.isExpanded ? t.collapseIcon : t.expandIcon, f.appendChild(h);
1450
+ const u = F("span", { class: "tbw-accordion-chevron" });
1451
+ u.innerHTML = c.isExpanded ? t.collapseIcon : t.expandIcon, f.appendChild(u);
1436
1452
  }
1437
1453
  d.appendChild(f), d.appendChild(
1438
- R("tbw-accordion-content", {
1454
+ T("tbw-accordion-content", {
1439
1455
  id: `tbw-section-${c.id}`,
1440
1456
  role: "presentation"
1441
1457
  })
@@ -1445,10 +1461,10 @@ function dt(t) {
1445
1461
  }
1446
1462
  return t.position === "left" && r ? (e.appendChild(r), e.appendChild(n)) : (e.appendChild(n), r && e.appendChild(r)), e;
1447
1463
  }
1448
- function H(t) {
1464
+ function O(t) {
1449
1465
  return t ? typeof t == "string" ? t : t.outerHTML : "";
1450
1466
  }
1451
- function ht() {
1467
+ function ut() {
1452
1468
  return {
1453
1469
  toolPanels: /* @__PURE__ */ new Map(),
1454
1470
  headerContents: /* @__PURE__ */ new Map(),
@@ -1465,33 +1481,33 @@ function ht() {
1465
1481
  toolbarButtonCleanups: /* @__PURE__ */ new Map()
1466
1482
  };
1467
1483
  }
1468
- function Pe(t) {
1484
+ function Le(t) {
1469
1485
  return !!(t?.header?.title || t?.header?.toolbarButtons?.length || t?.toolPanels?.length || t?.headerContents?.length || t?.header?.lightDomContent?.length || t?.header?.hasToolButtonsContainer);
1470
1486
  }
1471
- function fe(t, e, o = "☰") {
1472
- const i = t?.header?.title ?? e.lightDomTitle ?? "", n = !!i, r = H(o), s = t?.header?.toolbarButtons ?? [], l = s.some((g) => g.element || g.render), a = [...e.toolbarButtons.values()].some((g) => g.element || g.render), c = e.toolPanels.size > 0, d = (l || a) && c, f = [...s].sort((g, m) => (g.order ?? 100) - (m.order ?? 100)), p = [...e.toolbarButtons.values()].sort((g, m) => (g.order ?? 100) - (m.order ?? 100));
1473
- let h = "";
1487
+ function pe(t, e, o = "☰") {
1488
+ const i = t?.header?.title ?? e.lightDomTitle ?? "", n = !!i, r = O(o), s = t?.header?.toolbarButtons ?? [], l = s.some((g) => g.element || g.render), a = [...e.toolbarButtons.values()].some((g) => g.element || g.render), c = e.toolPanels.size > 0, d = (l || a) && c, f = [...s].sort((g, m) => (g.order ?? 100) - (m.order ?? 100)), p = [...e.toolbarButtons.values()].sort((g, m) => (g.order ?? 100) - (m.order ?? 100));
1489
+ let u = "";
1474
1490
  for (const g of f)
1475
- (g.element || g.render) && (h += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${g.id}"></div>`);
1491
+ (g.element || g.render) && (u += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${g.id}"></div>`);
1476
1492
  for (const g of p)
1477
- (g.element || g.render) && (h += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${g.id}"></div>`);
1478
- if (h += '<slot name="toolbar"></slot>', d && (h += '<div class="tbw-toolbar-separator"></div>'), c) {
1493
+ (g.element || g.render) && (u += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${g.id}"></div>`);
1494
+ if (u += '<slot name="toolbar"></slot>', d && (u += '<div class="tbw-toolbar-separator"></div>'), c) {
1479
1495
  const g = e.isPanelOpen;
1480
- h += `<button class="${g ? "tbw-toolbar-btn active" : "tbw-toolbar-btn"}" data-panel-toggle title="Settings" aria-label="Toggle settings panel" aria-pressed="${g}" aria-controls="tbw-tool-panel">${r}</button>`;
1496
+ u += `<button class="${g ? "tbw-toolbar-btn active" : "tbw-toolbar-btn"}" data-panel-toggle title="Settings" aria-label="Toggle settings panel" aria-pressed="${g}" aria-controls="tbw-tool-panel">${r}</button>`;
1481
1497
  }
1482
1498
  return `
1483
1499
  <div class="tbw-shell-header" part="shell-header" role="presentation">
1484
- ${n ? `<div class="tbw-shell-title">${qe(i)}</div>` : ""}
1500
+ ${n ? `<div class="tbw-shell-title">${We(i)}</div>` : ""}
1485
1501
  <div class="tbw-shell-content" part="shell-content" role="presentation">
1486
1502
  <slot name="header-content"></slot>
1487
1503
  </div>
1488
1504
  <div class="tbw-shell-toolbar" part="shell-toolbar" role="presentation">
1489
- ${h}
1505
+ ${u}
1490
1506
  </div>
1491
1507
  </div>
1492
1508
  `;
1493
1509
  }
1494
- function D(t, e) {
1510
+ function M(t, e) {
1495
1511
  const o = t.querySelector("tbw-grid-header");
1496
1512
  if (!o) return;
1497
1513
  if (!e.lightDomTitle) {
@@ -1503,11 +1519,11 @@ function D(t, e) {
1503
1519
  n.setAttribute("slot", "header-content");
1504
1520
  })), o.style.display = "none";
1505
1521
  }
1506
- function M(t, e) {
1522
+ function z(t, e) {
1507
1523
  const o = t.querySelector(":scope > tbw-grid-tool-buttons");
1508
1524
  o && (e.hasToolButtonsContainer = !0, o.setAttribute("slot", "toolbar"));
1509
1525
  }
1510
- function z(t, e, o) {
1526
+ function N(t, e, o) {
1511
1527
  t.querySelectorAll(":scope > tbw-grid-tool-panel").forEach((n) => {
1512
1528
  const r = n, s = r.getAttribute("id"), l = r.getAttribute("title");
1513
1529
  if (!s || !l) {
@@ -1516,7 +1532,7 @@ function z(t, e, o) {
1516
1532
  );
1517
1533
  return;
1518
1534
  }
1519
- const a = r.getAttribute("icon") ?? void 0, c = r.getAttribute("tooltip") ?? void 0, u = parseInt(r.getAttribute("order") ?? "100", 10);
1535
+ const a = r.getAttribute("icon") ?? void 0, c = r.getAttribute("tooltip") ?? void 0, h = parseInt(r.getAttribute("order") ?? "100", 10);
1520
1536
  let d;
1521
1537
  const f = o?.(r);
1522
1538
  if (f)
@@ -1531,24 +1547,24 @@ function z(t, e, o) {
1531
1547
  const p = e.toolPanels.get(s);
1532
1548
  if (p) {
1533
1549
  if (f) {
1534
- p.render = d, p.order = u, p.icon = a, p.tooltip = c;
1550
+ p.render = d, p.order = h, p.icon = a, p.tooltip = c;
1535
1551
  const g = e.panelCleanups.get(s);
1536
1552
  g && (g(), e.panelCleanups.delete(s));
1537
1553
  }
1538
1554
  return;
1539
1555
  }
1540
- const h = {
1556
+ const u = {
1541
1557
  id: s,
1542
1558
  title: l,
1543
1559
  icon: a,
1544
1560
  tooltip: c,
1545
- order: u,
1561
+ order: h,
1546
1562
  render: d
1547
1563
  };
1548
- e.toolPanels.set(s, h), e.lightDomToolPanelIds.add(s), r.style.display = "none";
1564
+ e.toolPanels.set(s, u), e.lightDomToolPanelIds.add(s), r.style.display = "none";
1549
1565
  });
1550
1566
  }
1551
- function ut(t, e, o, i) {
1567
+ function ft(t, e, o, i) {
1552
1568
  const n = t.querySelector(".tbw-shell-toolbar");
1553
1569
  n && n.addEventListener("click", (s) => {
1554
1570
  const l = s.target;
@@ -1558,44 +1574,44 @@ function ut(t, e, o, i) {
1558
1574
  }
1559
1575
  const c = l.closest("[data-btn]");
1560
1576
  if (c) {
1561
- const u = c.getAttribute("data-btn");
1562
- u && i.onToolbarButtonClick(u);
1577
+ const h = c.getAttribute("data-btn");
1578
+ h && i.onToolbarButtonClick(h);
1563
1579
  }
1564
1580
  });
1565
1581
  const r = t.querySelector(".tbw-accordion");
1566
1582
  r && r.addEventListener("click", (s) => {
1567
1583
  const a = s.target.closest(".tbw-accordion-header");
1568
1584
  if (a) {
1569
- const u = a.closest("[data-section]")?.getAttribute("data-section");
1570
- u && i.onSectionToggle(u);
1585
+ const h = a.closest("[data-section]")?.getAttribute("data-section");
1586
+ h && i.onSectionToggle(h);
1571
1587
  }
1572
1588
  });
1573
1589
  }
1574
- function ft(t, e, o) {
1590
+ function pt(t, e, o) {
1575
1591
  const i = t.querySelector(".tbw-tool-panel"), n = t.querySelector("[data-resize-handle]"), r = t.querySelector(".tbw-shell-body");
1576
1592
  if (!i || !n || !r)
1577
1593
  return () => {
1578
1594
  };
1579
1595
  const s = e?.toolPanel?.position ?? "right", l = 200;
1580
- let a = 0, c = 0, u = 0, d = !1;
1596
+ let a = 0, c = 0, h = 0, d = !1;
1581
1597
  const f = (g) => {
1582
1598
  if (!d) return;
1583
1599
  g.preventDefault();
1584
- const m = s === "left" ? g.clientX - a : a - g.clientX, b = Math.min(u, Math.max(l, c + m));
1600
+ const m = s === "left" ? g.clientX - a : a - g.clientX, b = Math.min(h, Math.max(l, c + m));
1585
1601
  i.style.width = `${b}px`;
1586
1602
  }, p = () => {
1587
1603
  if (!d) return;
1588
1604
  d = !1, n.classList.remove("resizing"), i.style.transition = "", document.body.style.cursor = "", document.body.style.userSelect = "";
1589
1605
  const g = i.getBoundingClientRect().width;
1590
1606
  o(g), document.removeEventListener("mousemove", f), document.removeEventListener("mouseup", p);
1591
- }, h = (g) => {
1592
- g.preventDefault(), d = !0, a = g.clientX, c = i.getBoundingClientRect().width, u = r.getBoundingClientRect().width - 20, n.classList.add("resizing"), i.style.transition = "none", document.body.style.cursor = "col-resize", document.body.style.userSelect = "none", document.addEventListener("mousemove", f), document.addEventListener("mouseup", p);
1607
+ }, u = (g) => {
1608
+ g.preventDefault(), d = !0, a = g.clientX, c = i.getBoundingClientRect().width, h = r.getBoundingClientRect().width - 20, n.classList.add("resizing"), i.style.transition = "none", document.body.style.cursor = "col-resize", document.body.style.userSelect = "none", document.addEventListener("mousemove", f), document.addEventListener("mouseup", p);
1593
1609
  };
1594
- return n.addEventListener("mousedown", h), () => {
1595
- n.removeEventListener("mousedown", h), document.removeEventListener("mousemove", f), document.removeEventListener("mouseup", p);
1610
+ return n.addEventListener("mousedown", u), () => {
1611
+ n.removeEventListener("mousedown", u), document.removeEventListener("mousemove", f), document.removeEventListener("mouseup", p);
1596
1612
  };
1597
1613
  }
1598
- function pt(t, e, o) {
1614
+ function gt(t, e, o) {
1599
1615
  const i = [...e?.header?.toolbarButtons ?? [], ...o.toolbarButtons.values()];
1600
1616
  for (const n of i) {
1601
1617
  const r = t.querySelector(`[data-btn-slot="${n.id}"]`);
@@ -1609,7 +1625,7 @@ function pt(t, e, o) {
1609
1625
  }
1610
1626
  }
1611
1627
  }
1612
- function Le(t, e) {
1628
+ function He(t, e) {
1613
1629
  const o = t.querySelector(".tbw-shell-content");
1614
1630
  if (!o) return;
1615
1631
  const i = [...e.headerContents.values()].sort((r, s) => (r.order ?? 100) - (s.order ?? 100)), n = o.querySelector('slot[name="header-content"]');
@@ -1622,15 +1638,15 @@ function Le(t, e) {
1622
1638
  a && e.headerContentCleanups.set(r.id, a);
1623
1639
  }
1624
1640
  }
1625
- function gt(t, e, o) {
1641
+ function wt(t, e, o) {
1626
1642
  if (!e.isPanelOpen) return;
1627
- const i = H(o?.expand ?? L.expand), n = H(o?.collapse ?? L.collapse);
1643
+ const i = O(o?.expand ?? L.expand), n = O(o?.collapse ?? L.collapse);
1628
1644
  for (const [r, s] of e.toolPanels) {
1629
1645
  const l = e.expandedSections.has(r), a = t.querySelector(`[data-section="${r}"]`), c = a?.querySelector(".tbw-accordion-content");
1630
1646
  if (!a || !c) continue;
1631
1647
  a.classList.toggle("expanded", l);
1632
- const u = a.querySelector(".tbw-accordion-header");
1633
- u && u.setAttribute("aria-expanded", String(l));
1648
+ const h = a.querySelector(".tbw-accordion-header");
1649
+ h && h.setAttribute("aria-expanded", String(l));
1634
1650
  const d = a.querySelector(".tbw-accordion-chevron");
1635
1651
  if (d && (d.innerHTML = l ? n : i), l) {
1636
1652
  if (c.children.length === 0) {
@@ -1643,15 +1659,15 @@ function gt(t, e, o) {
1643
1659
  }
1644
1660
  }
1645
1661
  }
1646
- function pe(t, e) {
1662
+ function ge(t, e) {
1647
1663
  const o = t.querySelector("[data-panel-toggle]");
1648
1664
  o && (o.classList.toggle("active", e.isPanelOpen), o.setAttribute("aria-pressed", String(e.isPanelOpen)));
1649
1665
  }
1650
- function ge(t, e) {
1666
+ function we(t, e) {
1651
1667
  const o = t.querySelector(".tbw-tool-panel");
1652
1668
  o && (o.classList.toggle("open", e.isPanelOpen), e.isPanelOpen || (o.style.width = ""));
1653
1669
  }
1654
- function wt(t, e) {
1670
+ function bt(t, e) {
1655
1671
  const o = [];
1656
1672
  for (const i of t?.header?.toolbarButtons ?? [])
1657
1673
  o.push({
@@ -1674,7 +1690,7 @@ function wt(t, e) {
1674
1690
  });
1675
1691
  return o;
1676
1692
  }
1677
- function bt(t) {
1693
+ function mt(t) {
1678
1694
  for (const e of t.headerContentCleanups.values())
1679
1695
  e();
1680
1696
  t.headerContentCleanups.clear();
@@ -1688,7 +1704,7 @@ function bt(t) {
1688
1704
  t.toolPanels.get(e)?.onClose?.();
1689
1705
  t.isPanelOpen = !1, t.expandedSections.clear(), t.toolPanels.clear(), t.headerContents.clear(), t.toolbarButtons.clear(), t.lightDomHeaderContent = [];
1690
1706
  }
1691
- function mt(t, e) {
1707
+ function vt(t, e) {
1692
1708
  let o = !1;
1693
1709
  const i = {
1694
1710
  get isInitialized() {
@@ -1717,7 +1733,7 @@ function mt(t, e) {
1717
1733
  s && t.expandedSections.add(s.id);
1718
1734
  }
1719
1735
  const n = e.getShadow();
1720
- pe(n, t), ge(n, t), gt(n, t, e.getAccordionIcons()), e.emit("tool-panel-open", { sections: i.expandedSections });
1736
+ ge(n, t), we(n, t), wt(n, t, e.getAccordionIcons()), e.emit("tool-panel-open", { sections: i.expandedSections });
1721
1737
  },
1722
1738
  closeToolPanel() {
1723
1739
  if (!t.isPanelOpen) return;
@@ -1728,7 +1744,7 @@ function mt(t, e) {
1728
1744
  r.onClose?.();
1729
1745
  t.isPanelOpen = !1;
1730
1746
  const n = e.getShadow();
1731
- pe(n, t), ge(n, t), e.emit("tool-panel-close", {});
1747
+ ge(n, t), we(n, t), e.emit("tool-panel-close", {});
1732
1748
  },
1733
1749
  toggleToolPanel() {
1734
1750
  t.isPanelOpen ? i.closeToolPanel() : i.openToolPanel();
@@ -1744,16 +1760,16 @@ function mt(t, e) {
1744
1760
  const s = e.getShadow(), l = t.expandedSections.has(n);
1745
1761
  if (l) {
1746
1762
  const a = t.panelCleanups.get(n);
1747
- a && (a(), t.panelCleanups.delete(n)), r.onClose?.(), t.expandedSections.delete(n), Z(s, n, !1);
1763
+ a && (a(), t.panelCleanups.delete(n)), r.onClose?.(), t.expandedSections.delete(n), J(s, n, !1);
1748
1764
  } else {
1749
1765
  for (const [a, c] of t.toolPanels)
1750
1766
  if (a !== n && t.expandedSections.has(a)) {
1751
- const u = t.panelCleanups.get(a);
1752
- u && (u(), t.panelCleanups.delete(a)), c.onClose?.(), t.expandedSections.delete(a), Z(s, a, !1);
1767
+ const h = t.panelCleanups.get(a);
1768
+ h && (h(), t.panelCleanups.delete(a)), c.onClose?.(), t.expandedSections.delete(a), J(s, a, !1);
1753
1769
  const d = s.querySelector(`[data-section="${a}"] .tbw-accordion-content`);
1754
1770
  d && (d.innerHTML = "");
1755
1771
  }
1756
- t.expandedSections.add(n), Z(s, n, !0), vt(s, t, n);
1772
+ t.expandedSections.add(n), J(s, n, !0), Ct(s, t, n);
1757
1773
  }
1758
1774
  e.emit("tool-panel-section-toggle", { id: n, expanded: !l });
1759
1775
  },
@@ -1782,14 +1798,14 @@ function mt(t, e) {
1782
1798
  console.warn(`[tbw-grid] Header content "${n.id}" already registered`);
1783
1799
  return;
1784
1800
  }
1785
- t.headerContents.set(n.id, n), o && Le(e.getShadow(), t);
1801
+ t.headerContents.set(n.id, n), o && He(e.getShadow(), t);
1786
1802
  },
1787
1803
  unregisterHeaderContent(n) {
1788
1804
  const r = t.headerContentCleanups.get(n);
1789
1805
  r && (r(), t.headerContentCleanups.delete(n)), t.headerContents.get(n)?.onDestroy?.(), t.headerContents.delete(n), e.getShadow().querySelector(`[data-header-content="${n}"]`)?.remove();
1790
1806
  },
1791
1807
  getToolbarButtons() {
1792
- return wt(e.getShellConfig(), t);
1808
+ return bt(e.getShellConfig(), t);
1793
1809
  },
1794
1810
  registerToolbarButton(n) {
1795
1811
  if (t.toolbarButtons.has(n.id)) {
@@ -1813,11 +1829,11 @@ function mt(t, e) {
1813
1829
  };
1814
1830
  return i;
1815
1831
  }
1816
- function Z(t, e, o) {
1832
+ function J(t, e, o) {
1817
1833
  const i = t.querySelector(`[data-section="${e}"]`);
1818
1834
  i && i.classList.toggle("expanded", o);
1819
1835
  }
1820
- function vt(t, e, o) {
1836
+ function Ct(t, e, o) {
1821
1837
  const i = e.toolPanels.get(o);
1822
1838
  if (!i?.render) return;
1823
1839
  const n = t.querySelector(`[data-section="${o}"] .tbw-accordion-content`);
@@ -1825,10 +1841,10 @@ function vt(t, e, o) {
1825
1841
  const r = i.render(n);
1826
1842
  r && e.panelCleanups.set(o, r);
1827
1843
  }
1828
- function Ct(t, e, o, i) {
1829
- const n = Pe(e);
1844
+ function _t(t, e, o, i) {
1845
+ const n = Le(e);
1830
1846
  if (t.replaceChildren(), n) {
1831
- const r = H(i?.toolPanel ?? L.toolPanel), s = H(i?.expand ?? L.expand), l = H(i?.collapse ?? L.collapse), c = [...e?.header?.toolbarButtons ?? []].sort((b, _) => (b.order ?? 100) - (_.order ?? 100)), d = [...e?.toolPanels ?? []].sort((b, _) => (b.order ?? 100) - (_.order ?? 100)), f = {
1847
+ const r = O(i?.toolPanel ?? L.toolPanel), s = O(i?.expand ?? L.expand), l = O(i?.collapse ?? L.collapse), c = [...e?.header?.toolbarButtons ?? []].sort((b, _) => (b.order ?? 100) - (_.order ?? 100)), d = [...e?.toolPanels ?? []].sort((b, _) => (b.order ?? 100) - (_.order ?? 100)), f = {
1832
1848
  title: e?.header?.title ?? void 0,
1833
1849
  hasPanels: d.length > 0,
1834
1850
  isPanelOpen: o.isPanelOpen,
@@ -1849,22 +1865,22 @@ function Ct(t, e, o, i) {
1849
1865
  panels: d.map((b) => ({
1850
1866
  id: b.id,
1851
1867
  title: b.title,
1852
- icon: H(b.icon),
1868
+ icon: O(b.icon),
1853
1869
  isExpanded: o.expandedSections.has(b.id)
1854
1870
  }))
1855
- }, h = ct(f), g = dt(p), m = ue({
1871
+ }, u = dt(f), g = ht(p), m = fe({
1856
1872
  hasShell: !0,
1857
- shellHeader: h,
1873
+ shellHeader: u,
1858
1874
  shellBody: g
1859
1875
  });
1860
1876
  t.appendChild(m);
1861
1877
  } else {
1862
- const r = ue({ hasShell: !1 });
1878
+ const r = fe({ hasShell: !1 });
1863
1879
  t.appendChild(r);
1864
1880
  }
1865
1881
  return n;
1866
1882
  }
1867
- function _t() {
1883
+ function yt() {
1868
1884
  return {
1869
1885
  startY: null,
1870
1886
  startX: null,
@@ -1878,19 +1894,19 @@ function _t() {
1878
1894
  momentumRaf: 0
1879
1895
  };
1880
1896
  }
1881
- function yt(t) {
1897
+ function Et(t) {
1882
1898
  t.startY = null, t.startX = null, t.scrollTop = null, t.scrollLeft = null, t.lastY = null, t.lastX = null, t.lastTime = null;
1883
1899
  }
1884
- function He(t) {
1900
+ function Oe(t) {
1885
1901
  t.momentumRaf && (cancelAnimationFrame(t.momentumRaf), t.momentumRaf = 0);
1886
1902
  }
1887
- function Et(t, e, o) {
1903
+ function St(t, e, o) {
1888
1904
  if (t.touches.length !== 1) return;
1889
- He(e);
1905
+ Oe(e);
1890
1906
  const i = t.touches[0];
1891
1907
  e.startY = i.clientY, e.startX = i.clientX, e.lastY = i.clientY, e.lastX = i.clientX, e.lastTime = performance.now(), e.scrollTop = o.fauxScrollbar.scrollTop, e.scrollLeft = o.scrollArea?.scrollLeft ?? 0, e.velocityY = 0, e.velocityX = 0;
1892
1908
  }
1893
- function St(t, e, o) {
1909
+ function Rt(t, e, o) {
1894
1910
  if (t.touches.length !== 1 || e.startY === null || e.startX === null || e.scrollTop === null || e.scrollLeft === null)
1895
1911
  return !1;
1896
1912
  const i = t.touches[0], n = i.clientY, r = i.clientX, s = performance.now(), l = e.startY - n, a = e.startX - r;
@@ -1899,18 +1915,18 @@ function St(t, e, o) {
1899
1915
  g > 0 && (e.velocityY = (e.lastY - n) / g, e.velocityX = (e.lastX - r) / g);
1900
1916
  }
1901
1917
  e.lastY = n, e.lastX = r, e.lastTime = s;
1902
- const { scrollTop: c, scrollHeight: u, clientHeight: d } = o.fauxScrollbar, f = u - d, p = l > 0 && c < f || l < 0 && c > 0;
1903
- let h = !1;
1918
+ const { scrollTop: c, scrollHeight: h, clientHeight: d } = o.fauxScrollbar, f = h - d, p = l > 0 && c < f || l < 0 && c > 0;
1919
+ let u = !1;
1904
1920
  if (o.scrollArea) {
1905
1921
  const { scrollLeft: g, scrollWidth: m, clientWidth: b } = o.scrollArea, _ = m - b;
1906
- h = a > 0 && g < _ || a < 0 && g > 0;
1922
+ u = a > 0 && g < _ || a < 0 && g > 0;
1907
1923
  }
1908
- return p && (o.fauxScrollbar.scrollTop = e.scrollTop + l), h && o.scrollArea && (o.scrollArea.scrollLeft = e.scrollLeft + a), p || h;
1924
+ return p && (o.fauxScrollbar.scrollTop = e.scrollTop + l), u && o.scrollArea && (o.scrollArea.scrollLeft = e.scrollLeft + a), p || u;
1909
1925
  }
1910
1926
  function Tt(t, e) {
1911
- (Math.abs(t.velocityY) > 0.1 || Math.abs(t.velocityX) > 0.1) && Rt(t, e), yt(t);
1927
+ (Math.abs(t.velocityY) > 0.1 || Math.abs(t.velocityX) > 0.1) && xt(t, e), Et(t);
1912
1928
  }
1913
- function Rt(t, e) {
1929
+ function xt(t, e) {
1914
1930
  const n = () => {
1915
1931
  t.velocityY *= 0.95, t.velocityX *= 0.95;
1916
1932
  const r = t.velocityY * 16, s = t.velocityX * 16;
@@ -1918,19 +1934,19 @@ function Rt(t, e) {
1918
1934
  };
1919
1935
  t.momentumRaf = requestAnimationFrame(n);
1920
1936
  }
1921
- function xt(t, e, o, i) {
1922
- t.addEventListener("touchstart", (n) => Et(n, e, o), {
1937
+ function At(t, e, o, i) {
1938
+ t.addEventListener("touchstart", (n) => St(n, e, o), {
1923
1939
  passive: !0,
1924
1940
  signal: i
1925
1941
  }), t.addEventListener(
1926
1942
  "touchmove",
1927
1943
  (n) => {
1928
- St(n, e, o) && n.preventDefault();
1944
+ Rt(n, e, o) && n.preventDefault();
1929
1945
  },
1930
1946
  { passive: !1, signal: i }
1931
1947
  ), t.addEventListener("touchend", () => Tt(e, o), { passive: !0, signal: i });
1932
1948
  }
1933
- const At = [
1949
+ const Pt = [
1934
1950
  // EditingPlugin
1935
1951
  {
1936
1952
  property: "editable",
@@ -1960,7 +1976,7 @@ const At = [
1960
1976
  importHint: "import { PinnedColumnsPlugin } from '@toolbox-web/grid/plugins/pinned-columns';",
1961
1977
  isUsed: (t) => t === "left" || t === "right"
1962
1978
  }
1963
- ], Pt = [
1979
+ ], Lt = [
1964
1980
  // GroupingColumnsPlugin
1965
1981
  {
1966
1982
  property: "columnGroups",
@@ -1970,34 +1986,37 @@ const At = [
1970
1986
  isUsed: (t) => Array.isArray(t) && t.length > 0
1971
1987
  }
1972
1988
  ];
1973
- function we(t, e) {
1989
+ function H(t) {
1990
+ return t.charAt(0).toUpperCase() + t.slice(1);
1991
+ }
1992
+ function be(t, e) {
1974
1993
  return t.some((o) => o.name === e);
1975
1994
  }
1976
- function Lt(t, e) {
1995
+ function Ht(t, e) {
1977
1996
  const o = /* @__PURE__ */ new Map();
1978
1997
  function i(r, s, l, a, c = !1) {
1979
1998
  o.has(r) || o.set(r, { description: s, importHint: l, fields: [], isConfigProperty: c });
1980
- const u = o.get(r);
1981
- u.fields.includes(a) || u.fields.push(a);
1999
+ const h = o.get(r);
2000
+ h.fields.includes(a) || h.fields.push(a);
1982
2001
  }
1983
- for (const r of Pt) {
2002
+ for (const r of Lt) {
1984
2003
  const s = t[r.property];
1985
- (r.isUsed ? r.isUsed(s) : s !== void 0) && !we(e, r.pluginName) && i(r.pluginName, r.description, r.importHint, r.property, !0);
2004
+ (r.isUsed ? r.isUsed(s) : s !== void 0) && !be(e, r.pluginName) && i(r.pluginName, r.description, r.importHint, r.property, !0);
1986
2005
  }
1987
2006
  const n = t.columns;
1988
2007
  if (n && n.length > 0)
1989
2008
  for (const r of n)
1990
- for (const s of At) {
2009
+ for (const s of Pt) {
1991
2010
  const l = r[s.property];
1992
- if ((s.isUsed ? s.isUsed(l) : l !== void 0) && !we(e, s.pluginName)) {
2011
+ if ((s.isUsed ? s.isUsed(l) : l !== void 0) && !be(e, s.pluginName)) {
1993
2012
  const c = r.field || "<unknown>";
1994
2013
  i(s.pluginName, s.description, s.importHint, c);
1995
2014
  }
1996
2015
  }
1997
2016
  if (o.size > 0) {
1998
2017
  const r = [];
1999
- for (const [s, { description: l, importHint: a, fields: c, isConfigProperty: u }] of o)
2000
- if (u)
2018
+ for (const [s, { description: l, importHint: a, fields: c, isConfigProperty: h }] of o)
2019
+ if (h)
2001
2020
  r.push(
2002
2021
  `Config uses ${l}, but the required plugin is not loaded.
2003
2022
  → Add the plugin to your gridConfig.plugins array:
@@ -2024,7 +2043,53 @@ This validation helps catch misconfigurations early. The properties listed above
2024
2043
  );
2025
2044
  }
2026
2045
  }
2027
- class Ht {
2046
+ const Ot = {
2047
+ editing: "import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';",
2048
+ selection: "import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';",
2049
+ reorder: "import { ReorderPlugin } from '@toolbox-web/grid/plugins/reorder';",
2050
+ clipboard: "import { ClipboardPlugin } from '@toolbox-web/grid/plugins/clipboard';",
2051
+ filtering: "import { FilteringPlugin } from '@toolbox-web/grid/plugins/filtering';",
2052
+ multiSort: "import { MultiSortPlugin } from '@toolbox-web/grid/plugins/multi-sort';",
2053
+ groupingRows: "import { GroupingRowsPlugin } from '@toolbox-web/grid/plugins/grouping-rows';",
2054
+ groupingColumns: "import { GroupingColumnsPlugin } from '@toolbox-web/grid/plugins/grouping-columns';",
2055
+ tree: "import { TreePlugin } from '@toolbox-web/grid/plugins/tree';",
2056
+ masterDetail: "import { MasterDetailPlugin } from '@toolbox-web/grid/plugins/master-detail';",
2057
+ pinnedColumns: "import { PinnedColumnsPlugin } from '@toolbox-web/grid/plugins/pinned-columns';",
2058
+ pinnedRows: "import { PinnedRowsPlugin } from '@toolbox-web/grid/plugins/pinned-rows';",
2059
+ visibility: "import { VisibilityPlugin } from '@toolbox-web/grid/plugins/visibility';",
2060
+ undoRedo: "import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';",
2061
+ export: "import { ExportPlugin } from '@toolbox-web/grid/plugins/export';",
2062
+ contextMenu: "import { ContextMenuPlugin } from '@toolbox-web/grid/plugins/context-menu';",
2063
+ pivot: "import { PivotPlugin } from '@toolbox-web/grid/plugins/pivot';",
2064
+ serverSide: "import { ServerSidePlugin } from '@toolbox-web/grid/plugins/server-side';",
2065
+ columnVirtualization: "import { ColumnVirtualizationPlugin } from '@toolbox-web/grid/plugins/column-virtualization';"
2066
+ };
2067
+ function Dt(t) {
2068
+ return Ot[t] ?? `import { ${H(t)}Plugin } from '@toolbox-web/grid/plugins/${t}';`;
2069
+ }
2070
+ function Mt(t, e) {
2071
+ const o = t.name, n = t.constructor.dependencies ?? [];
2072
+ for (const r of n) {
2073
+ const s = r.name, l = r.required ?? !0, a = r.reason;
2074
+ if (!e.some((h) => h.name === s)) {
2075
+ const h = a ?? `${H(o)}Plugin requires ${H(s)}Plugin`, d = Dt(s);
2076
+ if (l)
2077
+ throw new Error(
2078
+ `[tbw-grid] Plugin dependency error:
2079
+
2080
+ ${h}.
2081
+
2082
+ → Add the plugin to your gridConfig.plugins array BEFORE ${H(o)}Plugin:
2083
+ ${d}
2084
+ plugins: [new ${H(s)}Plugin(), new ${H(o)}Plugin()]`
2085
+ );
2086
+ console.info(
2087
+ `[tbw-grid] ${H(o)}Plugin: Optional "${s}" plugin not found. Some features may be unavailable.`
2088
+ );
2089
+ }
2090
+ }
2091
+ }
2092
+ class zt {
2028
2093
  constructor(e) {
2029
2094
  this.grid = e;
2030
2095
  }
@@ -2051,10 +2116,10 @@ class Ht {
2051
2116
  }
2052
2117
  /**
2053
2118
  * Attach a plugin to this grid.
2054
- * Notifies other plugins of the new attachment via onPluginAttached hook.
2119
+ * Validates dependencies and notifies other plugins of the new attachment.
2055
2120
  */
2056
2121
  attach(e) {
2057
- if (this.pluginMap.set(e.constructor, e), this.plugins.push(e), e.cellRenderers)
2122
+ if (Mt(e, this.plugins), this.pluginMap.set(e.constructor, e), this.plugins.push(e), e.cellRenderers)
2058
2123
  for (const [o, i] of Object.entries(e.cellRenderers))
2059
2124
  this.cellRenderers.set(o, i);
2060
2125
  if (e.headerRenderers)
@@ -2358,10 +2423,10 @@ class Ht {
2358
2423
  }
2359
2424
  // #endregion
2360
2425
  }
2361
- class O extends HTMLElement {
2426
+ class D extends HTMLElement {
2362
2427
  // TODO: Rename to 'data-grid' when migration is complete
2363
2428
  static tagName = "tbw-grid";
2364
- static version = "0.4.0";
2429
+ static version = "0.4.2";
2365
2430
  // ---------------- Framework Adapters ----------------
2366
2431
  /**
2367
2432
  * Registry of framework adapters that handle converting light DOM elements
@@ -2439,7 +2504,7 @@ class O extends HTMLElement {
2439
2504
  #s;
2440
2505
  // Cached hook to avoid closures
2441
2506
  #m = !1;
2442
- #A = _t();
2507
+ #A = yt();
2443
2508
  #g;
2444
2509
  #_;
2445
2510
  #y;
@@ -2469,7 +2534,7 @@ class O extends HTMLElement {
2469
2534
  // ---------------- Config Manager ----------------
2470
2535
  #t;
2471
2536
  // ---------------- Shell State ----------------
2472
- #e = ht();
2537
+ #e = ut();
2473
2538
  #a;
2474
2539
  #D;
2475
2540
  // #endregion
@@ -2478,7 +2543,7 @@ class O extends HTMLElement {
2478
2543
  _rows = [];
2479
2544
  // _baseColumns: columns before plugin transformation (analogous to #rows for row processing)
2480
2545
  // This is the source of truth for processColumns - plugins transform these
2481
- #z = [];
2546
+ #N = [];
2482
2547
  // _columns is a getter/setter that operates on effectiveConfig.columns
2483
2548
  // This ensures effectiveConfig.columns is the single source of truth for columns
2484
2549
  // _columns always contains ALL columns (including hidden)
@@ -2514,6 +2579,8 @@ class O extends HTMLElement {
2514
2579
  // Focus & navigation
2515
2580
  _focusRow = 0;
2516
2581
  _focusCol = 0;
2582
+ /** Flag to restore focus styling after next render. @internal */
2583
+ _restoreFocusAfterRender = !1;
2517
2584
  // Sort state
2518
2585
  _sortState = null;
2519
2586
  // Layout
@@ -2614,20 +2681,20 @@ class O extends HTMLElement {
2614
2681
  }
2615
2682
  // #endregion
2616
2683
  constructor() {
2617
- super(), this.#o = this.attachShadow({ mode: "open" }), this.#J(), this.#f = new Promise((e) => this.#d = e), this.#l = new lt({
2684
+ super(), this.#o = this.attachShadow({ mode: "open" }), this.#J(), this.#f = new Promise((e) => this.#d = e), this.#l = new at({
2618
2685
  mergeConfig: () => {
2619
- this.#t.parseLightDomColumns(this), this.#t.merge(), this.#V(), Lt(this.#n, this.#i?.getPlugins() ?? []), this.#z = [...this._columns];
2686
+ this.#t.parseLightDomColumns(this), this.#t.merge(), this.#G(), Ht(this.#n, this.#i?.getPlugins() ?? []), this.#N = [...this._columns];
2620
2687
  },
2621
2688
  processColumns: () => this.#de(),
2622
2689
  processRows: () => this.#he(),
2623
- renderHeader: () => F(this),
2624
- updateTemplate: () => k(this),
2690
+ renderHeader: () => X(this),
2691
+ updateTemplate: () => q(this),
2625
2692
  renderVirtualWindow: () => this.refreshVirtualWindow(!0),
2626
2693
  afterRender: () => {
2627
- this.#i?.afterRender(), this.#n.fitMode === "fixed" && !this.__didInitialAutoSize && (this.__didInitialAutoSize = !0, ie(this));
2694
+ this.#i?.afterRender(), this.#n.fitMode === "fixed" && !this.__didInitialAutoSize && (this.__didInitialAutoSize = !0, ne(this)), this._restoreFocusAfterRender && (this._restoreFocusAfterRender = !1, k(this)), this._virtualization.enabled && !this.#z && this.#te();
2628
2695
  },
2629
2696
  isConnected: () => this.isConnected && this.#h
2630
- }), this.#l.setInitialReadyResolver(() => this.#d?.()), this.#a = mt(this.#e, {
2697
+ }), this.#l.setInitialReadyResolver(() => this.#d?.()), this.#a = vt(this.#e, {
2631
2698
  getShadow: () => this.#o,
2632
2699
  getShellConfig: () => this.#n?.shell,
2633
2700
  getAccordionIcons: () => ({
@@ -2636,23 +2703,23 @@ class O extends HTMLElement {
2636
2703
  }),
2637
2704
  emit: (e, o) => this.#Y(e, o),
2638
2705
  refreshShellHeader: () => this.refreshShellHeader()
2639
- }), this.#t = new je({
2706
+ }), this.#t = new Ke({
2640
2707
  getRows: () => this.#r,
2641
2708
  getSortState: () => this._sortState,
2642
2709
  setSortState: (e) => {
2643
2710
  this._sortState = e;
2644
2711
  },
2645
2712
  onConfigChange: () => {
2646
- this.#l.requestPhase(T.FULL, "configChange");
2713
+ this.#l.requestPhase(S.FULL, "configChange");
2647
2714
  },
2648
2715
  emit: (e, o) => this.#Y(e, o),
2649
2716
  clearRowPool: () => {
2650
2717
  this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++;
2651
2718
  },
2652
- setup: () => this.#R(),
2653
- renderHeader: () => F(this),
2654
- updateTemplate: () => k(this),
2655
- refreshVirtualWindow: () => this.#l.requestPhase(T.VIRTUALIZATION, "configManager"),
2719
+ setup: () => this.#T(),
2720
+ renderHeader: () => X(this),
2721
+ updateTemplate: () => q(this),
2722
+ refreshVirtualWindow: () => this.#l.requestPhase(S.VIRTUALIZATION, "configManager"),
2656
2723
  getVirtualization: () => this._virtualization,
2657
2724
  setRowHeight: (e) => {
2658
2725
  this._virtualization.rowHeight = e;
@@ -2668,8 +2735,8 @@ class O extends HTMLElement {
2668
2735
  }
2669
2736
  async #J() {
2670
2737
  const e = new CSSStyleSheet();
2671
- if (ee.length > 0) {
2672
- e.replaceSync(ee), this.#o.adoptedStyleSheets = [e];
2738
+ if (te.length > 0) {
2739
+ e.replaceSync(te), this.#o.adoptedStyleSheets = [e];
2673
2740
  return;
2674
2741
  }
2675
2742
  await new Promise((o) => setTimeout(o, 50));
@@ -2719,7 +2786,16 @@ class O extends HTMLElement {
2719
2786
  * @internal Plugin API
2720
2787
  */
2721
2788
  requestRender() {
2722
- this.#l.requestPhase(T.ROWS, "plugin:requestRender");
2789
+ this.#l.requestPhase(S.ROWS, "plugin:requestRender");
2790
+ }
2791
+ /**
2792
+ * Request a full re-render and restore focus styling afterward.
2793
+ * Use this when a plugin action (like expand/collapse) triggers a render
2794
+ * but needs to maintain keyboard navigation focus.
2795
+ * @internal Plugin API
2796
+ */
2797
+ requestRenderWithFocus() {
2798
+ this._restoreFocusAfterRender = !0, this.#l.requestPhase(S.ROWS, "plugin:requestRenderWithFocus");
2723
2799
  }
2724
2800
  /**
2725
2801
  * Update the grid's column template CSS.
@@ -2727,7 +2803,7 @@ class O extends HTMLElement {
2727
2803
  * @internal
2728
2804
  */
2729
2805
  updateTemplate() {
2730
- k(this);
2806
+ q(this);
2731
2807
  }
2732
2808
  /**
2733
2809
  * Request a lightweight style update without rebuilding DOM.
@@ -2736,14 +2812,14 @@ class O extends HTMLElement {
2736
2812
  * @internal Plugin API
2737
2813
  */
2738
2814
  requestAfterRender() {
2739
- this.#l.requestPhase(T.STYLE, "plugin:requestAfterRender");
2815
+ this.#l.requestPhase(S.STYLE, "plugin:requestAfterRender");
2740
2816
  }
2741
2817
  /**
2742
2818
  * Initialize plugin system with instances from config.
2743
2819
  * Plugins are class instances passed in gridConfig.plugins[].
2744
2820
  */
2745
- #G() {
2746
- this.#i = new Ht(this);
2821
+ #V() {
2822
+ this.#i = new zt(this);
2747
2823
  const e = this.#n?.plugins, o = Array.isArray(e) ? e : [];
2748
2824
  this.#i.attachAll(o);
2749
2825
  }
@@ -2763,7 +2839,7 @@ class O extends HTMLElement {
2763
2839
  * With class-based plugins, we need to detach old and attach new.
2764
2840
  * Skips re-initialization if the plugins array hasn't changed.
2765
2841
  */
2766
- #V() {
2842
+ #G() {
2767
2843
  const e = this.#n?.plugins, o = Array.isArray(e) ? e : [];
2768
2844
  if (this.#E !== o) {
2769
2845
  if (this.#E && this.#E.length === o.length && this.#E.every((i, n) => i === o[n])) {
@@ -2782,7 +2858,7 @@ class O extends HTMLElement {
2782
2858
  const n = this.#e.headerContentCleanups.get(i);
2783
2859
  n && (n(), this.#e.headerContentCleanups.delete(i)), this.#e.headerContents.delete(i);
2784
2860
  }
2785
- this.#G(), this.#M(), this.#E = o, this.#F(), this.#b = this.#i?.getAll().some((i) => i.onScroll) ?? !1;
2861
+ this.#V(), this.#M(), this.#E = o, this.#X(), this.#b = this.#i?.getAll().some((i) => i.onScroll) ?? !1;
2786
2862
  }
2787
2863
  }
2788
2864
  /**
@@ -2795,7 +2871,7 @@ class O extends HTMLElement {
2795
2871
  * Collect tool panels and header content from all plugins.
2796
2872
  * Called after plugins are attached but before render.
2797
2873
  */
2798
- #F() {
2874
+ #X() {
2799
2875
  if (!this.#i) return;
2800
2876
  const e = this.#i.getToolPanels();
2801
2877
  for (const { panel: i } of e)
@@ -2808,8 +2884,8 @@ class O extends HTMLElement {
2808
2884
  * Gets a renderer factory for tool panels from registered framework adapters.
2809
2885
  * Returns a factory function that tries each adapter in order until one handles the element.
2810
2886
  */
2811
- #T() {
2812
- const e = O.getAdapters();
2887
+ #R() {
2888
+ const e = D.getAdapters();
2813
2889
  if (e.length === 0 && !this.__frameworkAdapter) return;
2814
2890
  const o = this.__frameworkAdapter;
2815
2891
  return (i) => {
@@ -2826,9 +2902,9 @@ class O extends HTMLElement {
2826
2902
  }
2827
2903
  // ---------------- Lifecycle ----------------
2828
2904
  connectedCallback() {
2829
- this.hasAttribute("tabindex") || (this.tabIndex = 0), this.hasAttribute("version") || this.setAttribute("version", O.version), this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#g && (this.#g.abort(), this.#O = !1), this.#g = new AbortController(), this.#C && (ce(this.#C), this.#C = void 0), D(this, this.#e), M(this, this.#e), z(this, this.#e, this.#T()), this.#t.parseLightDomColumns(this), this.#t.merge(), this.#G();
2905
+ this.hasAttribute("tabindex") || (this.tabIndex = 0), this.hasAttribute("version") || this.setAttribute("version", D.version), this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#g && (this.#g.abort(), this.#O = !1), this.#g = new AbortController(), this.#C && (de(this.#C), this.#C = void 0), M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R()), this.#t.parseLightDomColumns(this), this.#t.merge(), this.#V();
2830
2906
  const e = this.#n?.plugins;
2831
- this.#E = Array.isArray(e) ? e : [], this.#F(), this.#c || (this.#U(), this.#M(), this.#c = !0), this.#N(), this.#C = ot(
2907
+ this.#E = Array.isArray(e) ? e : [], this.#X(), this.#c || (this.#$(), this.#M(), this.#c = !0), this.#k(), this.#C = it(
2832
2908
  () => {
2833
2909
  this.#me();
2834
2910
  },
@@ -2836,7 +2912,7 @@ class O extends HTMLElement {
2836
2912
  );
2837
2913
  }
2838
2914
  disconnectedCallback() {
2839
- this.#C && (ce(this.#C), this.#C = void 0), this.#Q(), bt(this.#e), this.#a.setInitialized(!1), this.#D?.(), this.#D = void 0, He(this.#A), this.#g && (this.#g.abort(), this.#g = void 0), this.#P?.abort(), this.#P = void 0, this.#O = !1, this._resizeController && this._resizeController.dispose(), this.#_ && (this.#_.disconnect(), this.#_ = void 0), this.#y && (this.#y.disconnect(), this.#y = void 0, this.#k = !1), U(this), this.#x.clear(), this.#E = void 0;
2915
+ this.#C && (de(this.#C), this.#C = void 0), this.#Q(), mt(this.#e), this.#a.setInitialized(!1), this.#D?.(), this.#D = void 0, Oe(this.#A), this.#g && (this.#g.abort(), this.#g = void 0), this.#P?.abort(), this.#P = void 0, this.#O = !1, this._resizeController && this._resizeController.dispose(), this.#_ && (this.#_.disconnect(), this.#_ = void 0), this.#y && (this.#y.disconnect(), this.#y = void 0, this.#z = !1), $(this), this.#x.clear(), this.#E = void 0;
2840
2916
  for (const e of this._rowPool)
2841
2917
  e.remove();
2842
2918
  this._rowPool.length = 0, this.__rowsBodyEl = null, this.#h = !1;
@@ -2857,26 +2933,26 @@ class O extends HTMLElement {
2857
2933
  }
2858
2934
  else e === "fit-mode" ? this.fitMode = i : e === "edit-on" && (this.editOn = i);
2859
2935
  }
2860
- #N() {
2936
+ #k() {
2861
2937
  const o = this.#o.querySelector(".tbw-grid-content") ?? this.#o.querySelector(".tbw-grid-root");
2862
2938
  if (this._headerRowEl = o?.querySelector(".header-row"), this._virtualization.totalHeightEl = o?.querySelector(".faux-vscroll-spacer"), this._virtualization.viewportEl = o?.querySelector(".rows-viewport"), this._bodyEl = o?.querySelector(".rows"), this.__rowsBodyEl = o?.querySelector(".rows-body"), this.#a.isInitialized) {
2863
- Le(this.#o, this.#e), pt(this.#o, this.#n?.shell, this.#e);
2939
+ He(this.#o, this.#e), gt(this.#o, this.#n?.shell, this.#e);
2864
2940
  const r = this.#n?.shell?.toolPanel?.defaultOpen;
2865
2941
  r && this.#e.toolPanels.has(r) && (this.openToolPanel(), this.#e.expandedSections.add(r));
2866
2942
  }
2867
- if (this.setAttribute("data-upgraded", ""), this.#h = !0, this._resizeController = at(this), this.#R(), this.#ee(o), this.#O)
2943
+ if (this.setAttribute("data-upgraded", ""), this.#h = !0, this._resizeController = ct(this), this.#T(), this.#ee(o), this.#O)
2868
2944
  return;
2869
2945
  this.#O = !0;
2870
2946
  const i = this.disconnectSignal;
2871
- this.addEventListener("keydown", (r) => st(this, r), { signal: i }), this.#o.addEventListener("mousedown", (r) => this.#pe(r), { signal: i }), document.addEventListener("mousemove", (r) => this.#ge(r), { signal: i }), document.addEventListener("mouseup", (r) => this.#we(r), { signal: i });
2947
+ this.addEventListener("keydown", (r) => lt(this, r), { signal: i }), this.#o.addEventListener("mousedown", (r) => this.#pe(r), { signal: i }), document.addEventListener("mousemove", (r) => this.#ge(r), { signal: i }), document.addEventListener("mouseup", (r) => this.#we(r), { signal: i });
2872
2948
  const n = this.#n.rowHeight;
2873
- n && n > 0 ? this._virtualization.rowHeight = n : requestAnimationFrame(() => this.#X()), queueMicrotask(() => this.#oe()), this.#l.requestPhase(T.FULL, "afterConnect");
2949
+ n && n > 0 ? this._virtualization.rowHeight = n : requestAnimationFrame(() => this.#I()), queueMicrotask(() => this.#oe()), this.#l.requestPhase(S.FULL, "afterConnect");
2874
2950
  }
2875
2951
  /**
2876
2952
  * Measure actual row height from DOM.
2877
2953
  * Finds the tallest cell to account for custom renderers that may push height.
2878
2954
  */
2879
- #X() {
2955
+ #I() {
2880
2956
  const e = this._bodyEl?.querySelector(".data-grid-row");
2881
2957
  if (!e) return;
2882
2958
  const o = e.querySelectorAll(".cell");
@@ -2886,7 +2962,7 @@ class O extends HTMLElement {
2886
2962
  l > i && (i = l);
2887
2963
  });
2888
2964
  const n = e.getBoundingClientRect(), r = Math.max(n.height, i);
2889
- r > 0 && r !== this._virtualization.rowHeight && (this._virtualization.rowHeight = r, this.#l.requestPhase(T.VIRTUALIZATION, "measureRowHeight"));
2965
+ r > 0 && r !== this._virtualization.rowHeight && (this._virtualization.rowHeight = r, this.#l.requestPhase(S.VIRTUALIZATION, "measureRowHeight"));
2890
2966
  }
2891
2967
  /**
2892
2968
  * Set up scroll-related event listeners on DOM elements.
@@ -2905,7 +2981,7 @@ class O extends HTMLElement {
2905
2981
  if (this._rows.length <= this._virtualization.bypassThreshold)
2906
2982
  n.style.transform = `translateY(${-l}px)`;
2907
2983
  else {
2908
- const c = Math.floor(l / a), u = c - c % 2, d = -(l - u * a);
2984
+ const c = Math.floor(l / a), h = c - c % 2, d = -(l - h * a);
2909
2985
  n.style.transform = `translateY(${d}px)`;
2910
2986
  }
2911
2987
  this.#w = l, this.#v || (this.#v = requestAnimationFrame(() => {
@@ -2920,36 +2996,48 @@ class O extends HTMLElement {
2920
2996
  (l) => {
2921
2997
  const a = l.shiftKey || Math.abs(l.deltaX) > Math.abs(l.deltaY);
2922
2998
  if (a && s) {
2923
- const c = l.shiftKey ? l.deltaY : l.deltaX, { scrollLeft: u, scrollWidth: d, clientWidth: f } = s;
2924
- (c > 0 && u < d - f || c < 0 && u > 0) && (l.preventDefault(), s.scrollLeft += c);
2999
+ const c = l.shiftKey ? l.deltaY : l.deltaX, { scrollLeft: h, scrollWidth: d, clientWidth: f } = s;
3000
+ (c > 0 && h < d - f || c < 0 && h > 0) && (l.preventDefault(), s.scrollLeft += c);
2925
3001
  } else if (!a) {
2926
- const { scrollTop: c, scrollHeight: u, clientHeight: d } = i;
2927
- (l.deltaY > 0 && c < u - d || l.deltaY < 0 && c > 0) && (l.preventDefault(), i.scrollTop += l.deltaY);
3002
+ const { scrollTop: c, scrollHeight: h, clientHeight: d } = i;
3003
+ (l.deltaY > 0 && c < h - d || l.deltaY < 0 && c > 0) && (l.preventDefault(), i.scrollTop += l.deltaY);
2928
3004
  }
2929
3005
  },
2930
3006
  { passive: !1, signal: o }
2931
- ), xt(r, this.#A, { fauxScrollbar: i, scrollArea: s }, o));
3007
+ ), At(r, this.#A, { fauxScrollbar: i, scrollArea: s }, o));
2932
3008
  }
2933
- this._bodyEl && Je(this, this._bodyEl, o), this.#_?.disconnect(), this._virtualization.viewportEl && (this.#_ = new ResizeObserver(() => {
2934
- this.#l.requestPhase(T.VIRTUALIZATION, "resize-observer");
2935
- }), this.#_.observe(this._virtualization.viewportEl)), this._virtualization.enabled && (this.#l.requestPhase(T.VIRTUALIZATION, "init-virtualization"), queueMicrotask(() => this.#te()));
3009
+ this._bodyEl && Qe(this, this._bodyEl, o), this.#_?.disconnect(), this._virtualization.viewportEl && (this.#_ = new ResizeObserver(() => {
3010
+ this.#l.requestPhase(S.VIRTUALIZATION, "resize-observer");
3011
+ }), this.#_.observe(this._virtualization.viewportEl)), this._virtualization.enabled && this.#l.requestPhase(S.VIRTUALIZATION, "init-virtualization"), this.#o.addEventListener(
3012
+ "focusin",
3013
+ () => {
3014
+ this.dataset.hasFocus = "";
3015
+ },
3016
+ { signal: o }
3017
+ ), this.#o.addEventListener(
3018
+ "focusout",
3019
+ (r) => {
3020
+ const s = r.relatedTarget;
3021
+ (!s || !this.#o.contains(s)) && delete this.dataset.hasFocus;
3022
+ },
3023
+ { signal: o }
3024
+ );
2936
3025
  }
2937
3026
  /**
2938
- * Set up ResizeObserver on first row's cells to detect height changes.
2939
- * Called after rows are rendered to observe the actual content cells.
2940
- * Handles dynamic CSS loading, lazy images, font loading, etc.
3027
+ * Set up ResizeObserver on first row to detect height changes.
3028
+ * Called after rows are rendered to observe the actual content.
3029
+ * Handles dynamic CSS loading, lazy images, font loading, column virtualization, etc.
2941
3030
  */
2942
- #k = !1;
3031
+ #z = !1;
2943
3032
  // Only set up once per lifecycle
2944
3033
  #te() {
2945
- if (this.#k) return;
3034
+ if (this.#z) return;
2946
3035
  const e = this._bodyEl?.querySelector(".data-grid-row");
2947
- if (!e) return;
2948
- this.#k = !0, this.#y?.disconnect();
2949
- const o = e.querySelectorAll(".cell");
2950
- o.length > 0 && (this.#y = new ResizeObserver(() => {
2951
- this.#X();
2952
- }), o.forEach((i) => this.#y.observe(i)));
3036
+ e && (this.#z = !0, this.#y?.disconnect(), this.#y = new ResizeObserver(() => {
3037
+ this.#I();
3038
+ }), this.#y.observe(e), requestAnimationFrame(() => {
3039
+ this.#I();
3040
+ }));
2953
3041
  }
2954
3042
  // ---------------- Event Emitters ----------------
2955
3043
  #Y(e, o) {
@@ -2998,29 +3086,29 @@ class O extends HTMLElement {
2998
3086
  }
2999
3087
  // Individual update applicators - these do the actual work
3000
3088
  #ne() {
3001
- this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#l.requestPhase(T.ROWS, "applyRowsUpdate");
3089
+ this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#l.requestPhase(S.ROWS, "applyRowsUpdate");
3002
3090
  }
3003
3091
  #re() {
3004
- U(this), this.#t.merge(), this.#R();
3092
+ $(this), this.#t.merge(), this.#T();
3005
3093
  }
3006
3094
  #se() {
3007
- this.#t.merge(), this.#n.fitMode === "fixed" ? (this.__didInitialAutoSize = !1, ie(this)) : (this._columns.forEach((o) => {
3095
+ this.#t.merge(), this.#n.fitMode === "fixed" ? (this.__didInitialAutoSize = !1, ne(this)) : (this._columns.forEach((o) => {
3008
3096
  !o.__userResized && o.__autoSized && delete o.width;
3009
- }), k(this));
3097
+ }), q(this));
3010
3098
  }
3011
3099
  #le() {
3012
- this.#t.merge(), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.#l.requestPhase(T.VIRTUALIZATION, "applyEditModeUpdate");
3100
+ this.#t.merge(), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.#l.requestPhase(S.VIRTUALIZATION, "applyEditModeUpdate");
3013
3101
  }
3014
3102
  #ae() {
3015
- D(this, this.#e), M(this, this.#e);
3103
+ M(this, this.#e), z(this, this.#e);
3016
3104
  const e = !!this.#o.querySelector(".has-shell"), o = !!this.#o.querySelector(".tbw-tool-panel"), i = this.#o.querySelectorAll(".tbw-accordion-section").length;
3017
- this.#t.parseLightDomColumns(this), this.#t.merge(), this.#V(), z(this, this.#e, this.#T()), this.#t.markSourcesChanged(), this.#t.merge();
3018
- const n = Pe(this.#n?.shell), r = (this.#n?.shell?.toolPanels?.length ?? 0) > 0, s = (this.#n?.shell?.toolPanels?.length ?? 0) !== i;
3105
+ this.#t.parseLightDomColumns(this), this.#t.merge(), this.#G(), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge();
3106
+ const n = Le(this.#n?.shell), r = (this.#n?.shell?.toolPanels?.length ?? 0) > 0, s = (this.#n?.shell?.toolPanels?.length ?? 0) !== i;
3019
3107
  if (e !== n || !e && n || !o && r || o && s) {
3020
- this.#U(), this.#M(), this.#N();
3108
+ this.#$(), this.#M(), this.#k();
3021
3109
  return;
3022
3110
  }
3023
- e && this.#ce(), this.#l.requestPhase(T.COLUMNS, "applyGridConfigUpdate");
3111
+ e && this.#ce(), this.#l.requestPhase(S.COLUMNS, "applyGridConfigUpdate");
3024
3112
  }
3025
3113
  /**
3026
3114
  * Update the shell header DOM in place without a full re-render.
@@ -3039,26 +3127,18 @@ class O extends HTMLElement {
3039
3127
  // (e.g., setting rows, columns, gridConfig in quick succession) into a single update cycle.
3040
3128
  #de() {
3041
3129
  if (this.#i) {
3042
- const e = this.#z.length > 0 ? this.#z : this._columns, o = e.filter((r) => !r.hidden), i = e.filter((r) => r.hidden), n = this.#i.processColumns([...o]);
3130
+ const e = this.#N.length > 0 ? this.#N : this._columns, o = e.filter((r) => !r.hidden), i = e.filter((r) => r.hidden), n = this.#i.processColumns([...o]);
3043
3131
  if (n !== o) {
3044
- const r = new Map(n.map((l, a) => [l.field, { col: l, order: a }]));
3045
- if (!o.some((l) => r.has(l.field)) && n.length > 0)
3046
- this._columns = [...n, ...i];
3047
- else {
3048
- const l = e.map((a) => {
3049
- if (a.hidden) return a;
3050
- const c = r.get(a.field);
3051
- return c ? c.col : a;
3052
- });
3053
- this._columns = l;
3054
- }
3132
+ new Set(o.map((l) => l.field));
3133
+ const r = new Set(n.map((l) => l.field));
3134
+ !o.some((l) => r.has(l.field)) && n.length > 0 ? this._columns = [...n, ...i] : this._columns = [...n, ...i];
3055
3135
  } else
3056
3136
  this._columns = [...e];
3057
3137
  }
3058
3138
  }
3059
3139
  /** Recompute row model via plugin hooks. */
3060
3140
  #he() {
3061
- U(this);
3141
+ $(this);
3062
3142
  const e = Array.isArray(this.#r) ? [...this.#r] : [], o = this.#i?.processRows(e) ?? e;
3063
3143
  this._rows = o;
3064
3144
  }
@@ -3069,15 +3149,15 @@ class O extends HTMLElement {
3069
3149
  */
3070
3150
  #ue(e) {
3071
3151
  const o = {
3072
- ...De,
3152
+ ...Me,
3073
3153
  ...e.animation
3074
3154
  }, i = o.mode ?? "reduced-motion";
3075
3155
  let n = 1;
3076
3156
  i === !1 || i === "off" ? n = 0 : (i === !0 || i === "on") && (n = 1), this.style.setProperty("--tbw-animation-duration", `${o.duration}ms`), this.style.setProperty("--tbw-animation-easing", o.easing ?? "ease-out"), this.style.setProperty("--tbw-animation-enabled", String(n)), this.dataset.animationMode = typeof i == "boolean" ? i ? "on" : "off" : i;
3077
3157
  }
3078
3158
  // ---------------- Delegate Wrappers ----------------
3079
- #I(e, o, i = this.__rowRenderEpoch) {
3080
- this.#s || (this.#s = (n, r, s) => this.#i?.renderRow(n, r, s) ?? !1), rt(this, e, o, i, this.#s);
3159
+ #q(e, o, i = this.__rowRenderEpoch) {
3160
+ this.#s || (this.#s = (n, r, s) => this.#i?.renderRow(n, r, s) ?? !1), st(this, e, o, i, this.#s);
3081
3161
  }
3082
3162
  // Cache for ARIA counts to avoid redundant DOM writes on scroll (hot path)
3083
3163
  #B = -1;
@@ -3102,7 +3182,7 @@ class O extends HTMLElement {
3102
3182
  * Previously this method executed rendering synchronously, but that caused race
3103
3183
  * conditions with framework adapters that also schedule their own render work.
3104
3184
  */
3105
- #R() {
3185
+ #T() {
3106
3186
  if (this.isConnected && !(!this._headerRowEl || !this._bodyEl)) {
3107
3187
  if (this.#t.parseLightDomColumns(this), this.#L) {
3108
3188
  const e = this.#L;
@@ -3110,7 +3190,7 @@ class O extends HTMLElement {
3110
3190
  const o = this.#i?.getAll() ?? [];
3111
3191
  this.#t.applyState(e, o);
3112
3192
  }
3113
- this._bodyEl && (this._bodyEl.style.display = "", this._bodyEl.style.gridTemplateColumns = ""), this.#l.requestPhase(T.FULL, "setup");
3193
+ this._bodyEl && (this._bodyEl.style.display = "", this._bodyEl.style.gridTemplateColumns = ""), this.#l.requestPhase(S.FULL, "setup");
3114
3194
  }
3115
3195
  }
3116
3196
  #fe(e) {
@@ -3220,18 +3300,18 @@ class O extends HTMLElement {
3220
3300
  * Build a CellMouseEvent from a native MouseEvent.
3221
3301
  * Extracts cell/row information from the event target.
3222
3302
  */
3223
- #q(e, o) {
3303
+ #W(e, o) {
3224
3304
  let i = null;
3225
3305
  const n = e.composedPath?.();
3226
3306
  if (n && n.length > 0 ? i = n[0] : i = e.target, i && !this.#o.contains(i)) {
3227
- const h = this.#o.elementFromPoint(e.clientX, e.clientY);
3228
- h && (i = h);
3307
+ const u = this.#o.elementFromPoint(e.clientX, e.clientY);
3308
+ u && (i = u);
3229
3309
  }
3230
3310
  const r = i?.closest?.("[data-col]"), s = i?.closest?.(".data-grid-row"), l = i?.closest?.(".header-row");
3231
- let a, c, u, d, f, p;
3232
- return r && (a = parseInt(r.getAttribute("data-row") ?? "-1", 10), c = parseInt(r.getAttribute("data-col") ?? "-1", 10), a >= 0 && c >= 0 && (u = this._rows[a], p = this._columns[c], d = p?.field, f = u && d ? u[d] : void 0)), {
3311
+ let a, c, h, d, f, p;
3312
+ return r && (a = parseInt(r.getAttribute("data-row") ?? "-1", 10), c = parseInt(r.getAttribute("data-col") ?? "-1", 10), a >= 0 && c >= 0 && (h = this._rows[a], p = this._columns[c], d = p?.field, f = h && d ? h[d] : void 0)), {
3233
3313
  type: o,
3234
- row: u,
3314
+ row: h,
3235
3315
  rowIndex: a !== void 0 && a >= 0 ? a : void 0,
3236
3316
  colIndex: c !== void 0 && c >= 0 ? c : void 0,
3237
3317
  field: d,
@@ -3248,7 +3328,7 @@ class O extends HTMLElement {
3248
3328
  * Handle mousedown events and dispatch to plugin system.
3249
3329
  */
3250
3330
  #pe(e) {
3251
- const o = this.#q(e, "mousedown");
3331
+ const o = this.#W(e, "mousedown");
3252
3332
  (this.#i?.onCellMouseDown(o) ?? !1) && (this.#m = !0);
3253
3333
  }
3254
3334
  /**
@@ -3256,7 +3336,7 @@ class O extends HTMLElement {
3256
3336
  */
3257
3337
  #ge(e) {
3258
3338
  if (!this.#m) return;
3259
- const o = this.#q(e, "mousemove");
3339
+ const o = this.#W(e, "mousemove");
3260
3340
  this.#i?.onCellMouseMove(o);
3261
3341
  }
3262
3342
  /**
@@ -3264,14 +3344,14 @@ class O extends HTMLElement {
3264
3344
  */
3265
3345
  #we(e) {
3266
3346
  if (!this.#m) return;
3267
- const o = this.#q(e, "mouseup");
3347
+ const o = this.#W(e, "mouseup");
3268
3348
  this.#i?.onCellMouseUp(o), this.#m = !1;
3269
3349
  }
3270
3350
  async ready() {
3271
3351
  return this.#f;
3272
3352
  }
3273
3353
  async forceLayout() {
3274
- return this.#l.requestPhase(T.FULL, "forceLayout"), this.#l.whenReady();
3354
+ return this.#l.requestPhase(S.FULL, "forceLayout"), this.#l.whenReady();
3275
3355
  }
3276
3356
  /**
3277
3357
  * Trim the internal row pool to match the current visible window size.
@@ -3336,7 +3416,7 @@ class O extends HTMLElement {
3336
3416
  */
3337
3417
  #be(e) {
3338
3418
  const o = this.#i?.getAll() ?? [];
3339
- this.#t.applyState(e, o), this.#R();
3419
+ this.#t.applyState(e, o), this.#T();
3340
3420
  }
3341
3421
  /**
3342
3422
  * Request a state change event to be emitted.
@@ -3356,7 +3436,7 @@ class O extends HTMLElement {
3356
3436
  resetColumnState() {
3357
3437
  this.#L = void 0, this.__originalOrder = [];
3358
3438
  const e = this.#i?.getAll() ?? [];
3359
- this.#t.resetState(e), this.#t.merge(), this.#R();
3439
+ this.#t.resetState(e), this.#t.merge(), this.#T();
3360
3440
  }
3361
3441
  // ---------------- Shell / Tool Panel API ----------------
3362
3442
  // These methods delegate to ShellController for implementation.
@@ -3438,7 +3518,7 @@ class O extends HTMLElement {
3438
3518
  * Call this after dynamically modifying <tbw-grid-header> children.
3439
3519
  */
3440
3520
  refreshShellHeader() {
3441
- D(this, this.#e), M(this, this.#e), z(this, this.#e, this.#T()), this.#t.markSourcesChanged(), this.#t.merge(), this.#U(), this.#M(), this.#N();
3521
+ M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge(), this.#$(), this.#M(), this.#k();
3442
3522
  }
3443
3523
  // #region Custom Styles API
3444
3524
  /** Map of registered custom stylesheets by ID - uses adoptedStyleSheets which survive DOM rebuilds */
@@ -3505,24 +3585,24 @@ class O extends HTMLElement {
3505
3585
  #me() {
3506
3586
  const e = () => {
3507
3587
  const i = this.#e.lightDomTitle, n = this.#e.hasToolButtonsContainer;
3508
- D(this, this.#e), M(this, this.#e), z(this, this.#e, this.#T());
3588
+ M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R());
3509
3589
  const r = this.#e.lightDomTitle, s = this.#e.hasToolButtonsContainer;
3510
3590
  if (r && !i || s && !n) {
3511
3591
  this.#t.markSourcesChanged(), this.#t.merge();
3512
3592
  const l = this.#o.querySelector(".tbw-shell-header");
3513
3593
  if (l) {
3514
- const a = fe(
3594
+ const a = pe(
3515
3595
  this.#n.shell,
3516
3596
  this.#e,
3517
3597
  this.#n.icons?.toolPanel
3518
3598
  ), c = document.createElement("div");
3519
3599
  c.innerHTML = a;
3520
- const u = c.firstElementChild;
3521
- u && (l.replaceWith(u), this.#$());
3600
+ const h = c.firstElementChild;
3601
+ h && (l.replaceWith(h), this.#F());
3522
3602
  }
3523
3603
  }
3524
3604
  }, o = () => {
3525
- this.__lightDomColumnsCache = void 0, this.#R();
3605
+ this.__lightDomColumnsCache = void 0, this.#T();
3526
3606
  };
3527
3607
  this.#t.registerLightDomHandler("tbw-grid-header", e), this.#t.registerLightDomHandler("tbw-grid-tool-buttons", e), this.#t.registerLightDomHandler("tbw-grid-tool-panel", e), this.#t.registerLightDomHandler("tbw-grid-column", o), this.#t.registerLightDomHandler("tbw-grid-detail", o), this.#t.observeLightDOM(this);
3528
3608
  }
@@ -3533,32 +3613,32 @@ class O extends HTMLElement {
3533
3613
  * @internal Used by framework integration libraries (Angular, React, Vue)
3534
3614
  */
3535
3615
  refreshColumns() {
3536
- this.__lightDomColumnsCache = void 0, U(this), this.#t.parseLightDomColumns(this);
3616
+ this.__lightDomColumnsCache = void 0, $(this), this.#t.parseLightDomColumns(this);
3537
3617
  const e = this.#e.lightDomTitle, o = this.#e.hasToolButtonsContainer;
3538
- D(this, this.#e), M(this, this.#e), z(this, this.#e, this.#T());
3618
+ M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R());
3539
3619
  const i = this.#e.lightDomTitle, n = this.#e.hasToolButtonsContainer;
3540
3620
  if (i && !e || n && !o) {
3541
3621
  this.#t.markSourcesChanged(), this.#t.merge();
3542
3622
  const s = this.#o.querySelector(".tbw-shell-header");
3543
3623
  if (s) {
3544
- const l = fe(
3624
+ const l = pe(
3545
3625
  this.#n.shell,
3546
3626
  this.#e,
3547
3627
  this.#n.icons?.toolPanel
3548
3628
  ), a = document.createElement("div");
3549
3629
  a.innerHTML = l;
3550
3630
  const c = a.firstElementChild;
3551
- c && (s.replaceWith(c), this.#$());
3631
+ c && (s.replaceWith(c), this.#F());
3552
3632
  }
3553
3633
  }
3554
- this.#l.requestPhase(T.COLUMNS, "refreshColumns");
3634
+ this.#l.requestPhase(S.COLUMNS, "refreshColumns");
3555
3635
  }
3556
3636
  // ---------------- Virtual Window ----------------
3557
3637
  /**
3558
3638
  * Calculate total height for the faux scrollbar spacer element.
3559
3639
  * Used by both bypass and virtualized rendering paths to ensure consistent scroll behavior.
3560
3640
  */
3561
- #W(e) {
3641
+ #U(e) {
3562
3642
  const o = this._virtualization.rowHeight, i = this._virtualization.container ?? this, n = this._virtualization.viewportEl ?? i, r = i.clientHeight, s = n.clientHeight, a = this.shadowRoot?.querySelector(".tbw-scroll-area"), c = a ? a.clientHeight : r, d = c - s, f = this.#i?.getExtraHeight() ?? 0, p = Math.max(0, r - c);
3563
3643
  return e * o + d + f + p;
3564
3644
  }
@@ -3571,17 +3651,17 @@ class O extends HTMLElement {
3571
3651
  if (!this._bodyEl) return;
3572
3652
  const o = this._rows.length;
3573
3653
  if (!this._virtualization.enabled) {
3574
- this.#I(0, o), this.#i?.afterRender();
3654
+ this.#q(0, o), this.#i?.afterRender();
3575
3655
  return;
3576
3656
  }
3577
3657
  if (this._rows.length <= this._virtualization.bypassThreshold) {
3578
- this._virtualization.start = 0, this._virtualization.end = o, e && (this._bodyEl.style.transform = "translateY(0px)"), this.#I(0, o, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${this.#W(o)}px`), this.#K(o, this._visibleColumns.length), this.#i?.afterRender();
3658
+ this._virtualization.start = 0, this._virtualization.end = o, e && (this._bodyEl.style.transform = "translateY(0px)"), this.#q(0, o, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${this.#U(o)}px`), this.#K(o, this._visibleColumns.length), this.#i?.afterRender();
3579
3659
  return;
3580
3660
  }
3581
3661
  const i = this._virtualization.container ?? this, n = this._virtualization.viewportEl ?? i, r = n.clientHeight, s = this._virtualization.rowHeight, l = i.scrollTop;
3582
3662
  let a = Math.floor(l / s), c = 0;
3583
- const u = 10;
3584
- for (; c < u; ) {
3663
+ const h = 10;
3664
+ for (; c < h; ) {
3585
3665
  const _ = this.#i?.getExtraHeightBefore?.(a) ?? 0, w = Math.floor((l - _) / s);
3586
3666
  if (w >= a || w < 0) break;
3587
3667
  a = w, c++;
@@ -3592,39 +3672,39 @@ class O extends HTMLElement {
3592
3672
  const f = Math.ceil(r / s) + 3;
3593
3673
  let p = a + f;
3594
3674
  if (p > o && (p = o), this._virtualization.start = a, this._virtualization.end = p, i.clientHeight === 0 && r > 0) {
3595
- this.#l.requestPhase(T.VIRTUALIZATION, "stale-refs-retry");
3675
+ this.#l.requestPhase(S.VIRTUALIZATION, "stale-refs-retry");
3596
3676
  return;
3597
3677
  }
3598
- const g = this.#W(o);
3678
+ const g = this.#U(o);
3599
3679
  this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${g}px`);
3600
3680
  const m = this.#i?.getExtraHeightBefore?.(a) ?? 0, b = -(l - a * s - m);
3601
- this._bodyEl.style.transform = `translateY(${b}px)`, this.#I(a, p, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this.#K(o, this._visibleColumns.length), e && (this.#i?.afterRender(), queueMicrotask(() => {
3681
+ this._bodyEl.style.transform = `translateY(${b}px)`, this.#q(a, p, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this.#K(o, this._visibleColumns.length), e && (this.#i?.afterRender(), queueMicrotask(() => {
3602
3682
  const _ = i.clientHeight, w = n.clientHeight;
3603
3683
  if (_ === 0 && w > 0) return;
3604
- const C = this.#W(o);
3684
+ const C = this.#U(o);
3605
3685
  this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${C}px`);
3606
3686
  }));
3607
3687
  }
3608
3688
  // ---------------- Render ----------------
3609
- #U() {
3610
- D(this, this.#e), M(this, this.#e), z(this, this.#e, this.#T()), this.#t.markSourcesChanged(), this.#t.merge();
3689
+ #$() {
3690
+ M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge();
3611
3691
  const e = this.#n?.shell;
3612
- Ct(
3692
+ _t(
3613
3693
  this.#o,
3614
3694
  e,
3615
3695
  { isPanelOpen: this.#e.isPanelOpen, expandedSections: this.#e.expandedSections },
3616
3696
  this.#n?.icons
3617
- ) && (this.#$(), this.#a.setInitialized(!0));
3697
+ ) && (this.#F(), this.#a.setInitialized(!0));
3618
3698
  }
3619
3699
  /**
3620
3700
  * Set up shell event listeners after render.
3621
3701
  */
3622
- #$() {
3623
- ut(this.#o, this.#n?.shell, this.#e, {
3702
+ #F() {
3703
+ ft(this.#o, this.#n?.shell, this.#e, {
3624
3704
  onPanelToggle: () => this.toggleToolPanel(),
3625
3705
  onSectionToggle: (e) => this.toggleToolPanelSection(e),
3626
3706
  onToolbarButtonClick: (e) => this.#ve(e)
3627
- }), this.#D?.(), this.#D = ft(this.#o, this.#n?.shell, (e) => {
3707
+ }), this.#D?.(), this.#D = pt(this.#o, this.#n?.shell, (e) => {
3628
3708
  this.style.setProperty("--tbw-tool-panel-width", `${e}px`);
3629
3709
  });
3630
3710
  }
@@ -3637,17 +3717,36 @@ class O extends HTMLElement {
3637
3717
  #ve(e) {
3638
3718
  }
3639
3719
  }
3640
- customElements.get(O.tagName) || customElements.define(O.tagName, O);
3641
- globalThis.DataGridElement = O;
3642
- const Dt = {
3720
+ customElements.get(D.tagName) || customElements.define(D.tagName, D);
3721
+ globalThis.DataGridElement = D;
3722
+ const kt = {
3643
3723
  /** Ask if a column can be moved. Context: ColumnConfig. Response: boolean | undefined */
3644
3724
  CAN_MOVE_COLUMN: "canMoveColumn",
3645
3725
  /** Get context menu items. Context: ContextMenuParams. Response: ContextMenuItem[] */
3646
3726
  GET_CONTEXT_MENU_ITEMS: "getContextMenuItems"
3647
3727
  };
3648
- class Mt {
3649
- /** Plugin version - override in subclass if needed */
3650
- version = "1.0.0";
3728
+ class It {
3729
+ /**
3730
+ * Plugin dependencies - declare other plugins this one requires.
3731
+ *
3732
+ * Dependencies are validated when the plugin is attached.
3733
+ * Required dependencies throw an error if missing.
3734
+ * Optional dependencies log an info message if missing.
3735
+ *
3736
+ * @example
3737
+ * ```typescript
3738
+ * static readonly dependencies: PluginDependency[] = [
3739
+ * { name: 'editing', required: true, reason: 'Tracks cell edits for undo/redo' },
3740
+ * { name: 'selection', required: false, reason: 'Enables selection-based undo' },
3741
+ * ];
3742
+ * ```
3743
+ */
3744
+ static dependencies;
3745
+ /**
3746
+ * Plugin version - defaults to grid version for built-in plugins.
3747
+ * Third-party plugins can override with their own semver.
3748
+ */
3749
+ version = "0.4.2";
3651
3750
  /** CSS styles to inject into the grid's shadow DOM */
3652
3751
  styles;
3653
3752
  /** Custom cell renderers keyed by type name */
@@ -3734,12 +3833,28 @@ class Mt {
3734
3833
  emit(e, o) {
3735
3834
  this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: o, bubbles: !0 }));
3736
3835
  }
3836
+ /**
3837
+ * Emit a cancelable custom event from the grid.
3838
+ * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
3839
+ */
3840
+ emitCancelable(e, o) {
3841
+ const i = new CustomEvent(e, { detail: o, bubbles: !0, cancelable: !0 });
3842
+ return this.grid?.dispatchEvent?.(i), i.defaultPrevented;
3843
+ }
3737
3844
  /**
3738
3845
  * Request a re-render of the grid.
3739
3846
  */
3740
3847
  requestRender() {
3741
3848
  this.grid?.requestRender?.();
3742
3849
  }
3850
+ /**
3851
+ * Request a re-render and restore focus styling afterward.
3852
+ * Use this when a plugin action (like expand/collapse) triggers a render
3853
+ * but needs to maintain keyboard navigation focus.
3854
+ */
3855
+ requestRenderWithFocus() {
3856
+ this.grid?.requestRenderWithFocus?.();
3857
+ }
3743
3858
  /**
3744
3859
  * Request a lightweight style update without rebuilding DOM.
3745
3860
  * Use this instead of requestRender() when only CSS classes need updating.
@@ -3773,6 +3888,19 @@ class Mt {
3773
3888
  get visibleColumns() {
3774
3889
  return this.grid?._visibleColumns ?? [];
3775
3890
  }
3891
+ /**
3892
+ * Get the grid as an HTMLElement for direct DOM operations.
3893
+ * Use sparingly - prefer the typed GridElementRef API when possible.
3894
+ *
3895
+ * @example
3896
+ * ```ts
3897
+ * const width = this.gridElement.clientWidth;
3898
+ * this.gridElement.classList.add('my-plugin-active');
3899
+ * ```
3900
+ */
3901
+ get gridElement() {
3902
+ return this.grid;
3903
+ }
3776
3904
  /**
3777
3905
  * Get the shadow root of the grid.
3778
3906
  */
@@ -3807,6 +3935,51 @@ class Mt {
3807
3935
  const e = this.grid?.gridConfig?.icons ?? {};
3808
3936
  return { ...L, ...e };
3809
3937
  }
3938
+ // #region Animation Helpers
3939
+ /**
3940
+ * Check if animations are enabled at the grid level.
3941
+ * Respects gridConfig.animation.mode and the CSS variable set by the grid.
3942
+ *
3943
+ * Plugins should use this to skip animations when:
3944
+ * - Animation mode is 'off' or `false`
3945
+ * - User prefers reduced motion and mode is 'reduced-motion' (default)
3946
+ *
3947
+ * @example
3948
+ * ```ts
3949
+ * private get animationStyle(): 'slide' | 'fade' | false {
3950
+ * if (!this.isAnimationEnabled) return false;
3951
+ * return this.config.animation ?? 'slide';
3952
+ * }
3953
+ * ```
3954
+ */
3955
+ get isAnimationEnabled() {
3956
+ const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
3957
+ if (e === !1 || e === "off") return !1;
3958
+ if (e === !0 || e === "on") return !0;
3959
+ const o = this.shadowRoot?.host;
3960
+ return o ? getComputedStyle(o).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
3961
+ }
3962
+ /**
3963
+ * Get the animation duration in milliseconds from CSS variable.
3964
+ * Falls back to 200ms if not set.
3965
+ *
3966
+ * Plugins can use this for their animation timing to stay consistent
3967
+ * with the grid-level animation.duration setting.
3968
+ *
3969
+ * @example
3970
+ * ```ts
3971
+ * element.animate(keyframes, { duration: this.animationDuration });
3972
+ * ```
3973
+ */
3974
+ get animationDuration() {
3975
+ const e = this.shadowRoot?.host;
3976
+ if (e) {
3977
+ const o = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), i = parseInt(o, 10);
3978
+ if (!isNaN(i)) return i;
3979
+ }
3980
+ return 200;
3981
+ }
3982
+ // #endregion
3810
3983
  /**
3811
3984
  * Resolve an icon value to string or HTMLElement.
3812
3985
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -3884,7 +4057,7 @@ const E = {
3884
4057
  // Selection (SelectionPlugin applies, core CSS styles)
3885
4058
  RANGE_SELECTION: "range-selection",
3886
4059
  SELECTION_OVERLAY: "selection-overlay"
3887
- }, G = {
4060
+ }, V = {
3888
4061
  // ─── Core Attributes ──────────────────────────────────────────────
3889
4062
  ROW_INDEX: "data-row-index",
3890
4063
  COL_INDEX: "data-col-index",
@@ -3896,7 +4069,7 @@ const E = {
3896
4069
  // TreePlugin
3897
4070
  STICKY: "data-sticky"
3898
4071
  // PinnedColumnsPlugin
3899
- }, zt = {
4072
+ }, qt = {
3900
4073
  ROOT: `.${E.ROOT}`,
3901
4074
  HEADER: `.${E.HEADER}`,
3902
4075
  HEADER_ROW: `.${E.HEADER_ROW}`,
@@ -3907,13 +4080,13 @@ const E = {
3907
4080
  DATA_CELL: `.${E.DATA_CELL}`,
3908
4081
  GROUP_ROW: `.${E.GROUP_ROW}`,
3909
4082
  // By data attribute
3910
- ROW_BY_INDEX: (t) => `.${E.DATA_ROW}[${G.ROW_INDEX}="${t}"]`,
3911
- CELL_BY_FIELD: (t) => `.${E.DATA_CELL}[${G.FIELD}="${t}"]`,
3912
- CELL_AT: (t, e) => `.${E.DATA_ROW}[${G.ROW_INDEX}="${t}"] .${E.DATA_CELL}[${G.COL_INDEX}="${e}"]`,
4083
+ ROW_BY_INDEX: (t) => `.${E.DATA_ROW}[${V.ROW_INDEX}="${t}"]`,
4084
+ CELL_BY_FIELD: (t) => `.${E.DATA_CELL}[${V.FIELD}="${t}"]`,
4085
+ CELL_AT: (t, e) => `.${E.DATA_ROW}[${V.ROW_INDEX}="${t}"] .${E.DATA_CELL}[${V.COL_INDEX}="${e}"]`,
3913
4086
  // State selectors
3914
4087
  SELECTED_ROWS: `.${E.DATA_ROW}.${E.SELECTED}`,
3915
4088
  EDITING_CELL: `.${E.DATA_CELL}.${E.EDITING}`
3916
- }, Nt = {
4089
+ }, Bt = {
3917
4090
  // Colors
3918
4091
  COLOR_BG: "--tbw-color-bg",
3919
4092
  COLOR_FG: "--tbw-color-fg",
@@ -3935,7 +4108,7 @@ const E = {
3935
4108
  // Borders
3936
4109
  BORDER_RADIUS: "--tbw-border-radius",
3937
4110
  FOCUS_OUTLINE: "--tbw-focus-outline"
3938
- }, kt = {
4111
+ }, Wt = {
3939
4112
  CELL_COMMIT: "cell-commit",
3940
4113
  ROW_COMMIT: "row-commit",
3941
4114
  CHANGED_ROWS_RESET: "changed-rows-reset",
@@ -3946,7 +4119,7 @@ const E = {
3946
4119
  ACTIVATE_CELL: "activate-cell",
3947
4120
  GROUP_TOGGLE: "group-toggle",
3948
4121
  COLUMN_STATE_CHANGE: "column-state-change"
3949
- }, It = {
4122
+ }, Ut = {
3950
4123
  // Selection plugin
3951
4124
  SELECTION_CHANGE: "selection-change",
3952
4125
  // Tree plugin
@@ -3977,7 +4150,7 @@ const E = {
3977
4150
  DETAIL_EXPAND: "detail-expand",
3978
4151
  // Grouping rows plugin
3979
4152
  GROUP_EXPAND: "group-expand"
3980
- }, J = {
4153
+ }, Q = {
3981
4154
  sum: (t, e) => t.reduce((o, i) => o + (Number(i[e]) || 0), 0),
3982
4155
  avg: (t, e) => {
3983
4156
  const o = t.reduce((i, n) => i + (Number(n[e]) || 0), 0);
@@ -3988,25 +4161,25 @@ const E = {
3988
4161
  max: (t, e) => Math.max(...t.map((o) => Number(o[e]) || -1 / 0)),
3989
4162
  first: (t, e) => t[0]?.[e],
3990
4163
  last: (t, e) => t[t.length - 1]?.[e]
3991
- }, N = /* @__PURE__ */ new Map(), P = {
4164
+ }, I = /* @__PURE__ */ new Map(), P = {
3992
4165
  /**
3993
4166
  * Register a custom aggregator function.
3994
4167
  */
3995
4168
  register(t, e) {
3996
- N.set(t, e);
4169
+ I.set(t, e);
3997
4170
  },
3998
4171
  /**
3999
4172
  * Unregister a custom aggregator function.
4000
4173
  */
4001
4174
  unregister(t) {
4002
- N.delete(t);
4175
+ I.delete(t);
4003
4176
  },
4004
4177
  /**
4005
4178
  * Get an aggregator function by reference.
4006
4179
  */
4007
4180
  get(t) {
4008
4181
  if (t !== void 0)
4009
- return typeof t == "function" ? t : N.get(t) ?? J[t];
4182
+ return typeof t == "function" ? t : I.get(t) ?? Q[t];
4010
4183
  },
4011
4184
  /**
4012
4185
  * Run an aggregator on a set of rows.
@@ -4019,15 +4192,15 @@ const E = {
4019
4192
  * Check if an aggregator exists.
4020
4193
  */
4021
4194
  has(t) {
4022
- return N.has(t) || t in J;
4195
+ return I.has(t) || t in Q;
4023
4196
  },
4024
4197
  /**
4025
4198
  * List all available aggregator names.
4026
4199
  */
4027
4200
  list() {
4028
- return [...Object.keys(J), ...N.keys()];
4201
+ return [...Object.keys(Q), ...I.keys()];
4029
4202
  }
4030
- }, be = {
4203
+ }, me = {
4031
4204
  sum: (t) => t.reduce((e, o) => e + o, 0),
4032
4205
  avg: (t) => t.length ? t.reduce((e, o) => e + o, 0) / t.length : 0,
4033
4206
  count: (t) => t.length,
@@ -4036,43 +4209,43 @@ const E = {
4036
4209
  first: (t) => t[0] ?? 0,
4037
4210
  last: (t) => t[t.length - 1] ?? 0
4038
4211
  };
4039
- function Ot(t) {
4040
- return be[t] ?? be.sum;
4212
+ function Nt(t) {
4213
+ return me[t] ?? me.sum;
4041
4214
  }
4042
- function Bt(t, e) {
4043
- return Ot(t)(e);
4215
+ function $t(t, e) {
4216
+ return Nt(t)(e);
4044
4217
  }
4045
- const qt = P.register.bind(P), Wt = P.unregister.bind(P), Ut = P.get.bind(P), $t = P.run.bind(P), Gt = P.list.bind(P);
4218
+ const Ft = P.register.bind(P), Vt = P.unregister.bind(P), Gt = P.get.bind(P), Xt = P.run.bind(P), Yt = P.list.bind(P);
4046
4219
  export {
4047
- Mt as BaseGridPlugin,
4048
- De as DEFAULT_ANIMATION_CONFIG,
4220
+ It as BaseGridPlugin,
4221
+ Me as DEFAULT_ANIMATION_CONFIG,
4049
4222
  L as DEFAULT_GRID_ICONS,
4050
- kt as DGEvents,
4051
- O as DataGridElement,
4052
- q as FitModeEnum,
4053
- Nt as GridCSSVars,
4223
+ Wt as DGEvents,
4224
+ D as DataGridElement,
4225
+ W as FitModeEnum,
4226
+ Bt as GridCSSVars,
4054
4227
  E as GridClasses,
4055
- G as GridDataAttrs,
4056
- O as GridElement,
4057
- zt as GridSelectors,
4058
- Dt as PLUGIN_QUERIES,
4059
- It as PluginEvents,
4060
- Ht as PluginManager,
4061
- T as RenderPhase,
4062
- B as a,
4228
+ V as GridDataAttrs,
4229
+ D as GridElement,
4230
+ qt as GridSelectors,
4231
+ kt as PLUGIN_QUERIES,
4232
+ Ut as PluginEvents,
4233
+ zt as PluginManager,
4234
+ S as RenderPhase,
4235
+ k as a,
4063
4236
  P as aggregatorRegistry,
4064
- et as builtInSort,
4065
- Q as c,
4066
- Qe as defaultComparator,
4067
- me as e,
4068
- _e as g,
4069
- Ut as getAggregator,
4070
- Ot as getValueAggregator,
4071
- Gt as listAggregators,
4072
- qt as registerAggregator,
4073
- $t as runAggregator,
4074
- Bt as runValueAggregator,
4075
- V as s,
4076
- Wt as unregisterAggregator
4237
+ tt as builtInSort,
4238
+ ee as c,
4239
+ et as defaultComparator,
4240
+ ve as e,
4241
+ ye as g,
4242
+ Gt as getAggregator,
4243
+ Nt as getValueAggregator,
4244
+ Yt as listAggregators,
4245
+ Ft as registerAggregator,
4246
+ Xt as runAggregator,
4247
+ $t as runValueAggregator,
4248
+ G as s,
4249
+ Vt as unregisterAggregator
4077
4250
  };
4078
4251
  //# sourceMappingURL=index.js.map