@toolbox-web/grid 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.md +9 -13
  2. package/all.js +1678 -1588
  3. package/all.js.map +1 -1
  4. package/index.js +762 -568
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts +21 -0
  7. package/lib/core/grid.d.ts.map +1 -1
  8. package/lib/core/internal/config-manager.d.ts +1 -0
  9. package/lib/core/internal/config-manager.d.ts.map +1 -1
  10. package/lib/core/internal/dom-builder.d.ts +2 -0
  11. package/lib/core/internal/dom-builder.d.ts.map +1 -1
  12. package/lib/core/internal/header.d.ts.map +1 -1
  13. package/lib/core/internal/keyboard.d.ts.map +1 -1
  14. package/lib/core/internal/resize.d.ts.map +1 -1
  15. package/lib/core/internal/rows.d.ts.map +1 -1
  16. package/lib/core/internal/shell.d.ts +19 -13
  17. package/lib/core/internal/shell.d.ts.map +1 -1
  18. package/lib/core/internal/utils.d.ts +1 -0
  19. package/lib/core/internal/utils.d.ts.map +1 -1
  20. package/lib/core/plugin/base-plugin.d.ts +70 -3
  21. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  22. package/lib/core/plugin/expander-column.d.ts +51 -0
  23. package/lib/core/plugin/expander-column.d.ts.map +1 -0
  24. package/lib/core/plugin/plugin-manager.d.ts +6 -2
  25. package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
  26. package/lib/core/plugin/types.d.ts +117 -1
  27. package/lib/core/plugin/types.d.ts.map +1 -1
  28. package/lib/core/types.d.ts +10 -5
  29. package/lib/core/types.d.ts.map +1 -1
  30. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
  31. package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
  32. package/lib/plugins/clipboard/index.d.ts +1 -1
  33. package/lib/plugins/clipboard/index.d.ts.map +1 -1
  34. package/lib/plugins/clipboard/index.js +295 -190
  35. package/lib/plugins/clipboard/index.js.map +1 -1
  36. package/lib/plugins/clipboard/types.d.ts +72 -2
  37. package/lib/plugins/clipboard/types.d.ts.map +1 -1
  38. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
  39. package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
  40. package/lib/plugins/column-virtualization/index.js +143 -56
  41. package/lib/plugins/column-virtualization/index.js.map +1 -1
  42. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
  43. package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
  44. package/lib/plugins/context-menu/index.js +189 -102
  45. package/lib/plugins/context-menu/index.js.map +1 -1
  46. package/lib/plugins/editing/EditingPlugin.d.ts +2 -7
  47. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  48. package/lib/plugins/editing/index.js +227 -150
  49. package/lib/plugins/editing/index.js.map +1 -1
  50. package/lib/plugins/export/ExportPlugin.d.ts +0 -1
  51. package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
  52. package/lib/plugins/export/index.js +184 -97
  53. package/lib/plugins/export/index.js.map +1 -1
  54. package/lib/plugins/filtering/FilteringPlugin.d.ts +14 -3
  55. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  56. package/lib/plugins/filtering/index.js +296 -176
  57. package/lib/plugins/filtering/index.js.map +1 -1
  58. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
  59. package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
  60. package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
  61. package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
  62. package/lib/plugins/grouping-columns/index.js +169 -61
  63. package/lib/plugins/grouping-columns/index.js.map +1 -1
  64. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
  65. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
  66. package/lib/plugins/grouping-rows/index.js +243 -140
  67. package/lib/plugins/grouping-rows/index.js.map +1 -1
  68. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
  69. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
  70. package/lib/plugins/master-detail/index.js +278 -196
  71. package/lib/plugins/master-detail/index.js.map +1 -1
  72. package/lib/plugins/master-detail/types.d.ts +0 -10
  73. package/lib/plugins/master-detail/types.d.ts.map +1 -1
  74. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
  75. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
  76. package/lib/plugins/multi-sort/index.js +125 -40
  77. package/lib/plugins/multi-sort/index.js.map +1 -1
  78. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
  79. package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
  80. package/lib/plugins/pinned-columns/index.js +156 -75
  81. package/lib/plugins/pinned-columns/index.js.map +1 -1
  82. package/lib/plugins/pinned-columns/pinned-columns.d.ts +2 -2
  83. package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
  84. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
  85. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
  86. package/lib/plugins/pinned-rows/index.js +202 -117
  87. package/lib/plugins/pinned-rows/index.js.map +1 -1
  88. package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
  89. package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
  90. package/lib/plugins/pivot/index.js +413 -314
  91. package/lib/plugins/pivot/index.js.map +1 -1
  92. package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
  93. package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
  94. package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
  95. package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
  96. package/lib/plugins/reorder/index.d.ts +1 -1
  97. package/lib/plugins/reorder/index.d.ts.map +1 -1
  98. package/lib/plugins/reorder/index.js +296 -223
  99. package/lib/plugins/reorder/index.js.map +1 -1
  100. package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
  101. package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
  102. package/lib/plugins/selection/index.d.ts +2 -2
  103. package/lib/plugins/selection/index.d.ts.map +1 -1
  104. package/lib/plugins/selection/index.js +282 -141
  105. package/lib/plugins/selection/index.js.map +1 -1
  106. package/lib/plugins/selection/types.d.ts +24 -0
  107. package/lib/plugins/selection/types.d.ts.map +1 -1
  108. package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
  109. package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
  110. package/lib/plugins/server-side/index.js +96 -9
  111. package/lib/plugins/server-side/index.js.map +1 -1
  112. package/lib/plugins/tree/TreePlugin.d.ts +5 -1
  113. package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
  114. package/lib/plugins/tree/index.js +209 -113
  115. package/lib/plugins/tree/index.js.map +1 -1
  116. package/lib/plugins/tree/types.d.ts +0 -10
  117. package/lib/plugins/tree/types.d.ts.map +1 -1
  118. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
  119. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
  120. package/lib/plugins/undo-redo/index.js +98 -11
  121. package/lib/plugins/undo-redo/index.js.map +1 -1
  122. package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
  123. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  124. package/lib/plugins/visibility/index.js +155 -64
  125. package/lib/plugins/visibility/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/themes/dg-theme-bootstrap.css +55 -53
  128. package/themes/dg-theme-contrast.css +42 -40
  129. package/themes/dg-theme-large.css +38 -37
  130. package/themes/dg-theme-material.css +54 -52
  131. package/themes/dg-theme-standard.css +19 -17
  132. package/themes/dg-theme-vibrant.css +16 -14
  133. package/umd/grid.all.umd.js +23 -24
  134. package/umd/grid.all.umd.js.map +1 -1
  135. package/umd/grid.umd.js +12 -11
  136. package/umd/grid.umd.js.map +1 -1
  137. package/umd/plugins/clipboard.umd.js +5 -7
  138. package/umd/plugins/clipboard.umd.js.map +1 -1
  139. package/umd/plugins/column-virtualization.umd.js +1 -1
  140. package/umd/plugins/column-virtualization.umd.js.map +1 -1
  141. package/umd/plugins/context-menu.umd.js +1 -1
  142. package/umd/plugins/context-menu.umd.js.map +1 -1
  143. package/umd/plugins/editing.umd.js +1 -1
  144. package/umd/plugins/editing.umd.js.map +1 -1
  145. package/umd/plugins/export.umd.js +1 -1
  146. package/umd/plugins/export.umd.js.map +1 -1
  147. package/umd/plugins/filtering.umd.js +1 -1
  148. package/umd/plugins/filtering.umd.js.map +1 -1
  149. package/umd/plugins/grouping-columns.umd.js +1 -1
  150. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  151. package/umd/plugins/grouping-rows.umd.js +1 -1
  152. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  153. package/umd/plugins/master-detail.umd.js +1 -1
  154. package/umd/plugins/master-detail.umd.js.map +1 -1
  155. package/umd/plugins/multi-sort.umd.js +1 -1
  156. package/umd/plugins/multi-sort.umd.js.map +1 -1
  157. package/umd/plugins/pinned-columns.umd.js +1 -1
  158. package/umd/plugins/pinned-columns.umd.js.map +1 -1
  159. package/umd/plugins/pinned-rows.umd.js +1 -1
  160. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  161. package/umd/plugins/pivot.umd.js +1 -1
  162. package/umd/plugins/pivot.umd.js.map +1 -1
  163. package/umd/plugins/reorder.umd.js +1 -1
  164. package/umd/plugins/reorder.umd.js.map +1 -1
  165. package/umd/plugins/selection.umd.js +1 -1
  166. package/umd/plugins/selection.umd.js.map +1 -1
  167. package/umd/plugins/server-side.umd.js +1 -1
  168. package/umd/plugins/server-side.umd.js.map +1 -1
  169. package/umd/plugins/tree.umd.js +1 -1
  170. package/umd/plugins/tree.umd.js.map +1 -1
  171. package/umd/plugins/undo-redo.umd.js +1 -1
  172. package/umd/plugins/undo-redo.umd.js.map +1 -1
  173. package/umd/plugins/visibility.umd.js +1 -1
  174. package/umd/plugins/visibility.umd.js.map +1 -1
  175. package/lib/core/internal/editing.d.ts +0 -76
  176. package/lib/core/internal/editing.d.ts.map +0 -1
package/index.js CHANGED
@@ -1,11 +1,11 @@
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 .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)}: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 = {
1
+ const te = '@layer tbw-base,tbw-plugins,tbw-theme;@layer tbw-base{:root{color-scheme:light dark}tbw-grid{--tbw-base-icon-size: 1em;--tbw-base-radius: .25em;--tbw-font-size: 1em;--tbw-font-size-sm: .9285em;--tbw-font-size-xs: .7857em;--tbw-font-size-2xs: .7142em;--tbw-spacing-xs: .25em;--tbw-spacing-sm: .375em;--tbw-spacing-md: .5em;--tbw-spacing-lg: .75em;--tbw-spacing-xl: 1em;--tbw-icon-size: var(--tbw-base-icon-size);--tbw-icon-size-sm: .875em;--tbw-checkbox-size: var(--tbw-base-icon-size);--tbw-toggle-size: 1.25em;--tbw-border-radius: var(--tbw-base-radius);--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-error: light-dark(hsl(0, 65%, 51%), hsl(0, 65%, 55%));--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, #666666);--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-header: var(--tbw-font-size);--tbw-font-weight-header: bold;--tbw-cell-padding-header: var(--tbw-spacing-xs) var(--tbw-spacing-md);--tbw-cell-padding: var(--tbw-spacing-xs) var(--tbw-spacing-md);--tbw-cell-padding-input: var(--tbw-spacing-xs) var(--tbw-spacing-sm);--tbw-row-height: 1.75em;--tbw-header-height: 1.875em;--tbw-cell-white-space: nowrap;--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: var(--tbw-spacing-sm);--tbw-resize-handle-color: transparent;--tbw-resize-handle-color-hover: var(--tbw-color-accent);--tbw-resize-handle-border-radius: 0;--tbw-resize-indicator-width: 2px;--tbw-resize-indicator-color: var(--tbw-color-accent);--tbw-resize-indicator-opacity: .6;--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-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-density-scale: 1;--tbw-shell-header-height: 2.75em;--tbw-shell-header-bg: var(--tbw-color-panel-bg);--tbw-shell-header-border: var(--tbw-color-border);--tbw-shell-title-font-size: var(--tbw-font-size);--tbw-shell-title-font-weight: 600;--tbw-tool-panel-width: 17.5em;--tbw-tool-panel-bg: var(--tbw-color-panel-bg);--tbw-tool-panel-border: var(--tbw-color-border);--tbw-tool-panel-header-height: 2.5em;--tbw-tool-panel-transition: var(--tbw-animation-duration) var(--tbw-animation-easing);--tbw-toolbar-button-size: 2em;--tbw-toolbar-button-gap: var(--tbw-spacing-xs);--tbw-panel-padding: var(--tbw-spacing-lg);--tbw-panel-gap: var(--tbw-spacing-md);--tbw-menu-item-padding: var(--tbw-spacing-sm) var(--tbw-spacing-lg);--tbw-menu-item-gap: var(--tbw-spacing-md);--tbw-menu-min-width: 10rem;--tbw-button-padding: var(--tbw-spacing-sm) var(--tbw-spacing-lg);--tbw-button-padding-sm: var(--tbw-spacing-xs) var(--tbw-spacing-md);--tbw-input-height: var(--tbw-row-height);--tbw-input-padding: 0 var(--tbw-spacing-md);--tbw-detail-padding: var(--tbw-spacing-xl);--tbw-detail-max-height: 31.25rem;--tbw-indicator-size: var(--tbw-spacing-sm);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;&,*{box-sizing:border-box}.header{display:block;flex-shrink:0;z-index:var(--tbw-z-layer-header, 30);background:var(--tbw-color-header-bg);overflow:visible}.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)}.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));&:not(:last-child){border-right:2px solid var(--tbw-color-border)}}.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);>.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:visible;min-width:0;>span:first-child{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}>span[part~=sort-indicator]{flex-shrink:0;opacity:.6}&:last-child{border-right:0}&.grouped.group-end:not(:last-child){border-right:2px solid var(--tbw-color-border)}&.resizable{position:relative}&.sticky-left,&.sticky-right{background:var(--tbw-color-header-bg);z-index:35}}}.tbw-grid-root{display:flex;flex-direction:column;height:100%;&.has-shell{display:flex;flex-direction:column;height:100%}}.rows-body-wrapper{flex:1;min-height:0;display:flex;flex-direction:row;width:100%;min-width:fit-content}.rows-body{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:visible}.rows-container{display:flex;flex-direction:row;flex:1;min-height:0;overflow:visible}.rows-viewport{flex:1;min-width:0;position:relative;display:block;overflow:clip;.rows{position:absolute;top:0;left:0;min-width:100%;will-change:transform;z-index:var(--tbw-z-layer-rows, 1)}}.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)}.faux-vscroll-spacer{width:1px}.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);&:nth-child(2n){background:var(--tbw-color-row-alt)}&:hover{background:var(--tbw-color-row-hover)}>.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;>*{overflow:hidden;text-overflow:ellipsis;white-space:inherit;min-width:0}&:last-child{border-right:0}&[data-type=boolean]{text-align:center;input[type=checkbox]{margin:0;width:var(--tbw-checkbox-size);height:var(--tbw-checkbox-size);vertical-align:middle}}&.selected:focus-visible,&:focus-visible:not(.cell-focus){outline:none}&.sticky-left,&.sticky-right{background:var(--tbw-color-panel-bg)}}}.selecting .data-grid-row>.cell{user-select:none}.sortable{cursor:pointer;user-select:none}.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);&:after{content:"";position:absolute;top:100%;left:50%;transform:translate(-50%);width:var(--tbw-resize-indicator-width, 2px);height:0;background:var(--tbw-resize-indicator-color, var(--tbw-color-accent));opacity:0;pointer-events:none;transition:opacity .12s ease,height 0s .12s;z-index:1000}&:hover{background:var(--tbw-resize-handle-color-hover);&:after{height:100vh;opacity:var(--tbw-resize-indicator-opacity, .6);transition:opacity .12s ease,height 0s}}}&[data-has-focus]{.cell-focus,.row-focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}}.sticky-left,.sticky-right{position:sticky;z-index:25}.sticky-left{box-shadow:1px 0 0 var(--tbw-color-border)}.sticky-right{box-shadow:-1px 0 0 var(--tbw-color-border)}.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}.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}.tbw-shell-content{flex:1;display:flex;align-items:center;gap:12px;min-width:0;overflow:hidden}.tbw-shell-toolbar{display:flex;align-items:center;gap:var(--tbw-toolbar-button-gap);flex-shrink:0}.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);&:hover{background:var(--tbw-color-row-hover)}&:focus-visible{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}&.active{background:var(--tbw-focus-background);border-color:var(--tbw-color-accent)}&:disabled{opacity:.5;cursor:not-allowed}}.tbw-toolbar-separator{width:1px;height:20px;background:var(--tbw-color-border);margin:0 4px}.tbw-shell-body{position:relative;display:flex;flex:1;min-height:0;overflow:visible}.tbw-grid-content{flex:1;min-width:0;min-height:0;display:flex;flex-direction:row;overflow:hidden}.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}.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);&[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)}&.open{width:var(--tbw-tool-panel-width)}}.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);&[data-handle-position=left]{left:0}&[data-handle-position=right]{right:0}&:hover,&.resizing{background:var(--tbw-color-accent)}}.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}.tbw-tool-panel-title{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.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;&:hover{background:var(--tbw-color-row-hover);color:var(--tbw-color-fg)}}.tbw-tool-panel-content{flex:1;overflow:auto}.tbw-accordion{display:flex;flex-direction:column;gap:0}.tbw-accordion-section{border-bottom:1px solid var(--tbw-tool-panel-border);&:last-child{border-bottom:none}&.single .tbw-accordion-header{cursor:default;&:hover{background:transparent}}&.expanded{.tbw-accordion-chevron{transform:rotate(90deg)}.tbw-accordion-content{display:block}}}.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;&:hover{background:var(--tbw-color-row-hover)}}.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}.tbw-accordion-icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font-size:14px;flex-shrink:0}.tbw-accordion-title{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tbw-accordion-content{display:none}.tbw-expanding{animation:tbw-expand var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}.tbw-collapsing{animation:tbw-collapse var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}&[data-animation-mode=off]{--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}}@media(forced-colors:active){tbw-grid{--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;.cell:focus,.cell.active-cell{outline:2px solid Highlight!important;outline-offset:-2px}.data-grid-row[aria-selected=true]{background:Highlight!important;color:HighlightText!important}}}@media(prefers-reduced-motion:reduce){tbw-grid[data-animation-mode=reduced-motion]{--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}}@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
- }, Me = {
4
+ }, De = {
5
5
  mode: "reduced-motion",
6
6
  duration: 200,
7
7
  easing: "ease-out"
8
- }, L = {
8
+ }, H = {
9
9
  expand: "▶",
10
10
  collapse: "▼",
11
11
  sortAsc: "▲",
@@ -15,7 +15,7 @@ const te = ':root{color-scheme:light dark}:host{--tbw-color-bg: transparent;--tb
15
15
  dragHandle: "⋮⋮",
16
16
  toolPanel: "☰"
17
17
  };
18
- function ze(t) {
18
+ function Me(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;
@@ -34,19 +34,19 @@ function ze(t) {
34
34
  p && (h.__editorName = p), u && (h.__rendererName = u);
35
35
  const g = o.getAttribute("options");
36
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() };
37
+ const [Y, Oe] = v.includes(":") ? v.split(":") : [v.trim(), v.trim()];
38
+ return { value: Y.trim(), label: Oe?.trim() || Y.trim() };
39
39
  }));
40
- const m = o.querySelector("tbw-grid-column-view"), b = o.querySelector("tbw-grid-column-editor"), _ = o.querySelector("tbw-grid-column-header");
41
- m && (h.__viewTemplate = m), b && (h.__editorTemplate = b), _ && (h.__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);
40
+ const b = o.querySelector("tbw-grid-column-view"), C = o.querySelector("tbw-grid-column-editor"), y = o.querySelector("tbw-grid-column-header");
41
+ b && (h.__viewTemplate = b), C && (h.__editorTemplate = C), y && (h.__headerTemplate = y);
42
+ const w = globalThis.DataGridElement?.getAdapters?.() ?? [], _ = b ?? o, R = w.find((v) => v.canHandle(_));
43
+ if (R) {
44
+ const v = R.createRenderer(_);
45
45
  v && (h.viewRenderer = v);
46
46
  }
47
- const U = b ?? o, x = C.find((v) => v.canHandle(U));
48
- if (x) {
49
- const v = x.createEditor(U);
47
+ const $ = C ?? o, A = w.find((v) => v.canHandle($));
48
+ if (A) {
49
+ const v = A.createEditor($);
50
50
  v && (h.editor = v);
51
51
  }
52
52
  return h;
@@ -102,32 +102,32 @@ function ne(t) {
102
102
  }
103
103
  }
104
104
  l > 0 && (n.width = l + 2, n.__autoSized = !0, i = !0);
105
- }), i && I(t), t.__didInitialAutoSize = !0;
105
+ }), i && q(t), t.__didInitialAutoSize = !0;
106
106
  }
107
- function I(t) {
107
+ function q(t) {
108
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 Ne(t) {
114
+ function ze(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 ke(t, e) {
117
+ function Ne(t, e) {
118
118
  const o = t[0] || {}, i = Object.keys(o).map((r) => {
119
- const s = o[r], l = Ne(s);
119
+ const s = o[r], l = ze(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 Ie = /{{\s*([^}]+)\s*}}/g, A = "__DG_EMPTY__", Be = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, qe = /__(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) {
126
+ const ke = /{{\s*([^}]+)\s*}}/g, P = "__DG_EMPTY__", Ie = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, qe = /__(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 Be(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 Ue = /* @__PURE__ */ new Set([
130
+ const We = /* @__PURE__ */ new Set([
131
131
  "script",
132
132
  "iframe",
133
133
  "object",
@@ -152,18 +152,18 @@ const Ue = /* @__PURE__ */ new Set([
152
152
  "plaintext",
153
153
  "xmp",
154
154
  "listing"
155
- ]), re = /^on\w+$/i, $e = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), Ge = /^\s*(javascript|vbscript|data|blob):/i;
156
- function F(t) {
155
+ ]), re = /^on\w+$/i, $e = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), Ue = /^\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, Ve(e.content), e.innerHTML;
160
+ return e.innerHTML = t, Fe(e.content), e.innerHTML;
161
161
  }
162
- function Ve(t) {
162
+ function Fe(t) {
163
163
  const e = [], o = t.querySelectorAll("*");
164
164
  for (const i of o) {
165
165
  const n = i.tagName.toLowerCase();
166
- if (Ue.has(n)) {
166
+ if (We.has(n)) {
167
167
  e.push(i);
168
168
  continue;
169
169
  }
@@ -180,7 +180,7 @@ function Ve(t) {
180
180
  r.push(s.name);
181
181
  continue;
182
182
  }
183
- if ($e.has(l) && Ge.test(s.value)) {
183
+ if ($e.has(l) && Ue.test(s.value)) {
184
184
  r.push(s.name);
185
185
  continue;
186
186
  }
@@ -193,35 +193,35 @@ function Ve(t) {
193
193
  }
194
194
  e.forEach((i) => i.remove());
195
195
  }
196
- function ve(t, e) {
196
+ function we(t, e) {
197
197
  if (!t || t.indexOf("{{") === -1) return t;
198
- const o = [], i = t.replace(Ie, (l, a) => {
199
- const c = Fe(a, e);
198
+ const o = [], i = t.replace(ke, (l, a) => {
199
+ const c = Ve(a, e);
200
200
  return o.push({ expr: a.trim(), result: c }), c;
201
- }), n = Xe(i), r = o.length && o.every((l) => l.result === "" || l.result === A);
201
+ }), n = Ge(i), r = o.length && o.every((l) => l.result === "" || l.result === P);
202
202
  return /Reflect\.|\bProxy\b|ownKeys\(/.test(t) || r ? "" : n;
203
203
  }
204
- function Fe(t, e) {
205
- if (t = (t || "").trim(), !t || /\b(Reflect|Proxy|ownKeys)\b/.test(t)) return A;
206
- if (t === "value") return e.value == null ? A : String(e.value);
204
+ function Ve(t, e) {
205
+ if (t = (t || "").trim(), !t || /\b(Reflect|Proxy|ownKeys)\b/.test(t)) return P;
206
+ if (t === "value") return e.value == null ? P : 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
- return n == null ? A : String(n);
209
+ return n == null ? P : String(n);
210
210
  }
211
- if (t.length > 80 || !Be.test(t) || qe.test(t)) return A;
211
+ if (t.length > 80 || !Ie.test(t) || qe.test(t)) return P;
212
212
  const o = t.match(/\./g);
213
- if (o && o.length > 1) return A;
213
+ if (o && o.length > 1) return P;
214
214
  try {
215
215
  const n = new Function("value", "row", `return (${t});`)(e.value, e.row), r = n == null ? "" : String(n);
216
- return /Reflect|Proxy|ownKeys/.test(r) ? A : r || A;
216
+ return /Reflect|Proxy|ownKeys/.test(r) ? P : r || P;
217
217
  } catch {
218
- return A;
218
+ return P;
219
219
  }
220
220
  }
221
- function Xe(t) {
222
- return t && t.replace(new RegExp(A, "g"), "").replace(/Reflect\.[^<>{}\s]+/g, "").replace(/\bProxy\b/g, "").replace(/ownKeys\([^)]*\)/g, "");
221
+ function Ge(t) {
222
+ return t && t.replace(new RegExp(P, "g"), "").replace(/Reflect\.[^<>{}\s]+/g, "").replace(/\bProxy\b/g, "").replace(/ownKeys\([^)]*\)/g, "");
223
223
  }
224
- function Ye(t) {
224
+ function Xe(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 = "");
@@ -234,11 +234,11 @@ function Ye(t) {
234
234
  }
235
235
  }
236
236
  function se(t) {
237
- const e = /Reflect\.|\bProxy\b|ownKeys\(/.test(t), o = ((i) => e ? "" : ve(t, i));
237
+ const e = /Reflect\.|\bProxy\b|ownKeys\(/.test(t), o = ((i) => e ? "" : we(t, i));
238
238
  return o.__blocked = e, o;
239
239
  }
240
- const je = 100;
241
- class Ke {
240
+ const Ye = 100;
241
+ class je {
242
242
  // ============================================================================
243
243
  // Sources (raw input from user)
244
244
  // ============================================================================
@@ -270,11 +270,11 @@ class Ke {
270
270
  #p = !0;
271
271
  #l = [];
272
272
  #v;
273
- #w;
273
+ #m;
274
274
  #b;
275
275
  #s;
276
276
  // Shell state (Light DOM title)
277
- #m;
277
+ #w;
278
278
  constructor(e) {
279
279
  this.#s = e;
280
280
  }
@@ -315,11 +315,11 @@ class Ke {
315
315
  }
316
316
  /** Get light DOM title */
317
317
  get lightDomTitle() {
318
- return this.#m;
318
+ return this.#w;
319
319
  }
320
320
  /** Set light DOM title */
321
321
  set lightDomTitle(e) {
322
- this.#m = e;
322
+ this.#w = e;
323
323
  }
324
324
  /** Get initial column state */
325
325
  get initialColumnState() {
@@ -403,7 +403,7 @@ class Ke {
403
403
  const e = (this.#u.columns?.length ?? 0) > 0;
404
404
  if (!this.#p && e)
405
405
  return;
406
- const o = this.#_();
406
+ const o = this.#y();
407
407
  this.#p = !1, this.#h = o, Object.freeze(this.#h), this.#h.columns && Object.freeze(this.#h.columns), this.#u = this.#A(this.#h), this.#g();
408
408
  }
409
409
  /**
@@ -445,7 +445,7 @@ class Ke {
445
445
  *
446
446
  * Runtime state (hidden, width) is NOT preserved here - that's in effectiveConfig.
447
447
  */
448
- #_() {
448
+ #y() {
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
  }));
@@ -458,11 +458,11 @@ class Ke {
458
458
  i
459
459
  ));
460
460
  const r = this.#s.getRows();
461
- return n.length === 0 && r.length && (n = ke(r).columns), n.length && (n.forEach((s) => {
461
+ return n.length === 0 && r.length && (n = Ne(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
464
  s.__viewTemplate && !s.__compiledView && (s.__compiledView = se(s.__viewTemplate.innerHTML)), s.__editorTemplate && !s.__compiledEditor && (s.__compiledEditor = se(s.__editorTemplate.innerHTML));
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;
465
+ }), e.columns = n), this.#f && (e.fitMode = this.#f), e.fitMode || (e.fitMode = "stretch"), this.#d && (e.editOn = this.#d), this.#_(e), e.columnState && !this.#b && (this.#b = e.columnState), e;
466
466
  }
467
467
  /**
468
468
  * Merge shell state into base config's shell property.
@@ -471,10 +471,10 @@ class Ke {
471
471
  * IMPORTANT: This method must NOT mutate the original gridConfig.
472
472
  * We shallow-clone the shell hierarchy to avoid side effects.
473
473
  */
474
- #y(e) {
474
+ #_(e) {
475
475
  e.shell = e.shell ? { ...e.shell } : {}, e.shell.header = e.shell.header ? { ...e.shell.header } : {};
476
476
  const o = this.#s.getShellLightDomTitle();
477
- o && (this.#m = o), this.#m && !e.shell.header.title && (e.shell.header.title = this.#m);
477
+ o && (this.#w = o), this.#w && !e.shell.header.title && (e.shell.header.title = this.#w);
478
478
  const i = this.#s.getShellLightDomHeaderContent();
479
479
  i?.length > 0 && (e.shell.header.lightDomContent = i), this.#s.getShellHasToolButtonsContainer() && (e.shell.header.hasToolButtonsContainer = !0);
480
480
  const n = this.#s.getShellToolPanels();
@@ -582,11 +582,11 @@ class Ke {
582
582
  * Request a debounced state change event.
583
583
  */
584
584
  requestStateChange(e) {
585
- this.#w && clearTimeout(this.#w), this.#w = setTimeout(() => {
586
- this.#w = void 0;
585
+ this.#m && clearTimeout(this.#m), this.#m = setTimeout(() => {
586
+ this.#m = void 0;
587
587
  const o = this.collectState(e);
588
588
  this.#s.emit("column-state-change", o);
589
- }, je);
589
+ }, Ye);
590
590
  }
591
591
  // ============================================================================
592
592
  // Column Visibility API
@@ -634,7 +634,8 @@ class Ke {
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 Ke {
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 ? ze(e) : []);
668
+ this.#r || (this.#n = Array.from(e.querySelectorAll("tbw-grid-column")), this.#r = this.#n.length ? Me(e) : []);
668
669
  }
669
670
  /**
670
671
  * Clear the light DOM columns cache.
@@ -764,13 +765,13 @@ class Ke {
764
765
  * Dispose of the ConfigManager and clean up resources.
765
766
  */
766
767
  dispose() {
767
- this.#v?.disconnect(), this.#l = [], this.#w && clearTimeout(this.#w);
768
+ this.#v?.disconnect(), this.#l = [], this.#m && clearTimeout(this.#m);
768
769
  }
769
770
  }
770
- function Ce(t) {
771
+ function ve(t) {
771
772
  return `<span role="checkbox" aria-checked="${t}" aria-label="${t}">${t ? "&#x1F5F9;" : "&#9744;"}</span>`;
772
773
  }
773
- function _e(t) {
774
+ function Ce(t) {
774
775
  if (t == null || t === "") return "";
775
776
  if (t instanceof Date)
776
777
  return isNaN(t.getTime()) ? "" : t.toLocaleDateString();
@@ -783,9 +784,17 @@ function _e(t) {
783
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 Ze(t) {
797
+ function Ke(t) {
789
798
  if (!t) return -1;
790
799
  const e = t.getAttribute("data-col");
791
800
  return e ? parseInt(e, 10) : -1;
@@ -793,25 +802,25 @@ function Ze(t) {
793
802
  function ee(t) {
794
803
  t && t.querySelectorAll(".cell-focus").forEach((e) => e.classList.remove("cell-focus"));
795
804
  }
796
- function Je(t, e) {
797
- const o = ye(e), i = Ze(e);
805
+ function Ze(t, e) {
806
+ const o = ye(e), i = Ke(e);
798
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 Qe(t, e, o) {
809
+ function Je(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") || Je(t, n));
814
+ n && (n.classList.contains("editing") || Ze(t, n));
806
815
  },
807
816
  { signal: o }
808
817
  );
809
818
  }
810
- function et(t, e) {
819
+ function Qe(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 tt(t, e, o) {
814
- const n = o.find((l) => l.field === e.field)?.sortComparator ?? et, { field: r, direction: s } = e;
822
+ function et(t, e, o) {
823
+ const n = o.find((l) => l.field === e.field)?.sortComparator ?? Qe, { field: r, direction: s } = e;
815
824
  return [...t].sort((l, a) => n(l[r], a[r], l, a) * s);
816
825
  }
817
826
  function le(t, e, o, i) {
@@ -828,32 +837,32 @@ function ae(t, e) {
828
837
  }
829
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 ?? tt)(t._rows, i, n);
840
+ const i = { field: e.field, direction: o }, n = t._columns, s = (t.effectiveConfig?.sortHandler ?? et)(t._rows, i, n);
832
841
  s && typeof s.then == "function" ? s.then((l) => {
833
842
  le(t, l, e, o);
834
843
  }) : le(t, s, e, o);
835
844
  }
836
- function ot(t, e) {
845
+ function tt(t, e) {
837
846
  typeof e == "string" ? t.textContent = e : e instanceof HTMLElement && (t.innerHTML = "", t.appendChild(e.cloneNode(!0)));
838
847
  }
839
848
  function X(t) {
840
849
  t._headerRowEl = t.findHeaderRow();
841
850
  const e = t._headerRowEl;
842
- e.innerHTML = "", t._visibleColumns.forEach((o, i) => {
851
+ e && (e.innerHTML = "", t._visibleColumns.forEach((o, i) => {
843
852
  const n = document.createElement("div");
844
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 {
848
- const s = o.header || o.field, l = document.createElement("span");
857
+ const s = o.header ?? o.field, l = document.createElement("span");
849
858
  l.textContent = s, n.appendChild(l);
850
859
  }
851
860
  if (o.sortable) {
852
861
  n.classList.add("sortable"), n.tabIndex = 0;
853
862
  const s = document.createElement("span");
854
863
  ie(s, "sort-indicator");
855
- 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
- ot(s, c), n.appendChild(s), n.setAttribute("aria-sort", l === 0 ? "none" : l === 1 ? "ascending" : "descending"), n.addEventListener("click", (h) => {
864
+ const l = t._sortState?.field === o.field ? t._sortState.direction : 0, a = { ...H, ...t.icons }, c = l === 1 ? a.sortAsc : l === -1 ? a.sortDesc : a.sortNone;
865
+ tt(s, c), n.appendChild(s), n.setAttribute("aria-sort", l === 0 ? "none" : l === 1 ? "ascending" : "descending"), n.addEventListener("click", (h) => {
857
866
  t._resizeController?.isResizing || t._dispatchHeaderClick?.(h, i, n) || ae(t, o);
858
867
  }), n.addEventListener("keydown", (h) => {
859
868
  if (h.key === "Enter" || h.key === " ") {
@@ -874,11 +883,11 @@ function X(t) {
874
883
  e.appendChild(n);
875
884
  }), e.querySelectorAll(".cell.sortable").forEach((o) => {
876
885
  o.getAttribute("aria-sort") || o.setAttribute("aria-sort", "none");
877
- }), e.children.length > 0 ? (e.setAttribute("role", "row"), e.setAttribute("aria-rowindex", "1")) : (e.removeAttribute("role"), e.removeAttribute("aria-rowindex"));
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 Ee = typeof requestIdleCallback == "function";
880
- function it(t, e) {
881
- return Ee ? requestIdleCallback(t, e) : window.setTimeout(() => {
888
+ const _e = typeof requestIdleCallback == "function";
889
+ function ot(t, e) {
890
+ return _e ? requestIdleCallback(t, e) : window.setTimeout(() => {
882
891
  const o = Date.now();
883
892
  t({
884
893
  didTimeout: !1,
@@ -887,33 +896,33 @@ function it(t, e) {
887
896
  }, 1);
888
897
  }
889
898
  function de(t) {
890
- Ee ? cancelIdleCallback(t) : clearTimeout(t);
899
+ _e ? cancelIdleCallback(t) : clearTimeout(t);
891
900
  }
892
- const Se = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])';
901
+ const Ee = 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])';
893
902
  function j(t) {
894
903
  return (t.__editingCellCount ?? 0) > 0;
895
904
  }
896
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 Re = document.createElement("template");
900
- Re.innerHTML = '<div class="cell" role="gridcell" part="cell"></div>';
908
+ const Se = document.createElement("template");
909
+ Se.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 nt() {
904
- return Re.content.firstElementChild.cloneNode(!0);
912
+ function it() {
913
+ return Se.content.firstElementChild.cloneNode(!0);
905
914
  }
906
- function rt() {
915
+ function nt() {
907
916
  return Te.content.firstElementChild.cloneNode(!0);
908
917
  }
909
- function $(t) {
918
+ function U(t) {
910
919
  t.__cellDisplayCache = void 0, t.__cellCacheEpoch = void 0, t.__hasSpecialColumns = void 0;
911
920
  }
912
- function st(t, e, o, i, n) {
921
+ function rt(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
- for (c === void 0 && (c = t.shadowRoot?.querySelector(".header-group-row") ? 2 : 1, t.__cachedHeaderRowCount = c); t._rowPool.length < r; ) {
916
- const d = rt();
924
+ for (c === void 0 && (c = t.querySelector(".header-group-row") ? 2 : 1, t.__cachedHeaderRowCount = c); t._rowPool.length < r; ) {
925
+ const d = nt();
917
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) {
@@ -930,27 +939,27 @@ function st(t, e, o, i, n) {
930
939
  u.__epoch = i, u.__rowDataRef = p, u.parentNode !== s && s.appendChild(u);
931
940
  continue;
932
941
  }
933
- const g = u.__epoch, m = u.__rowDataRef, b = u.children.length, w = g === i && b === a, C = m !== p;
934
- let y = !1;
935
- if (w && C) {
936
- for (let x = 0; x < a; x++)
937
- if (l[x].externalView && !u.querySelector(`.cell[data-col="${x}"] [data-external-view]`)) {
938
- y = !0;
942
+ const g = u.__epoch, b = u.__rowDataRef, C = u.children.length, m = g === i && C === a, w = b !== p;
943
+ let _ = !1;
944
+ if (m && w) {
945
+ for (let A = 0; A < a; A++)
946
+ if (l[A].externalView && !u.querySelector(`.cell[data-col="${A}"] [data-external-view]`)) {
947
+ _ = !0;
939
948
  break;
940
949
  }
941
950
  }
942
- if (!w || y) {
943
- const x = j(u), v = t._activeEditRows === f;
944
- 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
- } else if (C) {
946
- const x = j(u), v = t._activeEditRows === f;
947
- x && !v ? (K(u), B(t, u, p, f), u.__epoch = i, u.__rowDataRef = p) : (Z(t, u, p, f), u.__rowDataRef = p);
951
+ if (!m || _) {
952
+ const A = j(u), v = t._activeEditRows === f;
953
+ A && !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) : A && 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);
954
+ } else if (w) {
955
+ const A = j(u), v = t._activeEditRows === f;
956
+ A && !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 = j(u), v = t._activeEditRows === f;
950
- x && !v ? (K(u), B(t, u, p, f), u.__epoch = i, u.__rowDataRef = p) : Z(t, u, p, f);
958
+ const A = j(u), v = t._activeEditRows === f;
959
+ A && !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, U = u.classList.contains("changed");
953
- S !== U && u.classList.toggle("changed", S), u.parentNode !== s && s.appendChild(u);
961
+ const R = t._changedRowIndices?.has(f) ?? !1, $ = u.classList.contains("changed");
962
+ R !== $ && u.classList.toggle("changed", R), u.parentNode !== s && s.appendChild(u);
954
963
  }
955
964
  }
956
965
  function Z(t, e, o, i) {
@@ -970,10 +979,12 @@ function Z(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 u = n[p], g = o[r[p].field];
982
+ const u = n[p];
983
+ if (u.classList.contains("editing")) continue;
984
+ const g = o[r[p].field];
974
985
  u.textContent = g == null ? "" : String(g), u.getAttribute("data-row") !== f && u.setAttribute("data-row", f);
975
- const m = c === i && h === p, b = u.classList.contains("cell-focus");
976
- m !== b && (u.classList.toggle("cell-focus", m), u.setAttribute("aria-selected", String(m)));
986
+ const b = c === i && h === p, C = u.classList.contains("cell-focus");
987
+ b !== C && (u.classList.toggle("cell-focus", b), u.setAttribute("aria-selected", String(b)));
977
988
  }
978
989
  return;
979
990
  }
@@ -985,55 +996,55 @@ function Z(t, e, o, i) {
985
996
  for (let p = 0; p < a; p++) {
986
997
  const u = r[p], g = n[p];
987
998
  g.getAttribute("data-row") !== f && g.setAttribute("data-row", f);
988
- const m = c === i && h === p, b = g.classList.contains("cell-focus");
989
- if (m !== b && (g.classList.toggle("cell-focus", m), g.setAttribute("aria-selected", String(m))), g.classList.contains("editing")) continue;
990
- const _ = u.renderer || u.viewRenderer;
991
- if (_) {
992
- const y = o[u.field], S = _({ row: o, value: y, field: u.field, column: u, cellEl: g });
993
- typeof S == "string" ? g.innerHTML = F(S) : S instanceof Node ? S.parentElement !== g && (g.innerHTML = "", g.appendChild(S)) : S == null && (g.textContent = y == null ? "" : String(y));
999
+ const b = c === i && h === p, C = g.classList.contains("cell-focus");
1000
+ if (b !== C && (g.classList.toggle("cell-focus", b), g.setAttribute("aria-selected", String(b))), g.classList.contains("editing")) continue;
1001
+ const y = u.renderer || u.viewRenderer;
1002
+ if (y) {
1003
+ const _ = o[u.field], R = y({ row: o, value: _, field: u.field, column: u, cellEl: g });
1004
+ typeof R == "string" ? g.innerHTML = G(R) : R instanceof Node ? R.parentElement !== g && (g.innerHTML = "", g.appendChild(R)) : R == null && (g.textContent = _ == null ? "" : String(_));
994
1005
  continue;
995
1006
  }
996
1007
  if (u.__viewTemplate || u.__compiledView || u.externalView)
997
1008
  continue;
998
- const w = o[u.field];
999
- let C;
1009
+ const m = o[u.field];
1010
+ let w;
1000
1011
  if (u.format)
1001
1012
  try {
1002
- const y = u.format(w, o);
1003
- C = y == null ? "" : String(y);
1004
- } catch (y) {
1005
- console.warn(`[tbw-grid] Format error in column '${u.field}':`, y), C = w == null ? "" : String(w);
1013
+ const _ = u.format(m, o);
1014
+ w = _ == null ? "" : String(_);
1015
+ } catch (_) {
1016
+ console.warn(`[tbw-grid] Format error in column '${u.field}':`, _), w = m == null ? "" : String(m);
1006
1017
  }
1007
- 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);
1018
+ else u.type === "date" ? (w = Ce(m), g.textContent = w) : u.type === "boolean" ? g.innerHTML = ve(!!m) : (w = m == null ? "" : String(m), g.textContent = w);
1008
1019
  }
1009
1020
  }
1010
1021
  function B(t, e, o, i) {
1011
1022
  e.innerHTML = "";
1012
1023
  const n = t._visibleColumns, r = n.length, s = t._focusRow, l = t._focusCol, a = t, c = document.createDocumentFragment();
1013
1024
  for (let h = 0; h < r; h++) {
1014
- const d = n[h], f = nt();
1025
+ const d = n[h], f = it();
1015
1026
  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
1027
  let p = o[d.field];
1017
1028
  if (d.format)
1018
1029
  try {
1019
1030
  p = d.format(p, o);
1020
- } catch (w) {
1021
- console.warn(`[tbw-grid] Format error in column '${d.field}':`, w);
1031
+ } catch (m) {
1032
+ console.warn(`[tbw-grid] Format error in column '${d.field}':`, m);
1022
1033
  }
1023
- const u = d.__compiledView, g = d.__viewTemplate, m = d.renderer || d.viewRenderer, b = d.externalView;
1024
- let _ = !1;
1025
- if (m) {
1026
- const w = m({ row: o, value: p, field: d.field, column: d, cellEl: f });
1027
- typeof w == "string" ? (f.innerHTML = F(w), _ = !0) : w instanceof Node ? w.parentElement !== f && (f.textContent = "", f.appendChild(w)) : w == null && (f.textContent = p == null ? "" : String(p));
1028
- } else if (b) {
1029
- const w = b, C = document.createElement("div");
1030
- C.setAttribute("data-external-view", ""), C.setAttribute("data-field", d.field), f.appendChild(C);
1031
- const y = { row: o, value: p, field: d.field, column: d };
1032
- if (w.mount)
1034
+ const u = d.__compiledView, g = d.__viewTemplate, b = d.renderer || d.viewRenderer, C = d.externalView;
1035
+ let y = !1;
1036
+ if (b) {
1037
+ const m = b({ row: o, value: p, field: d.field, column: d, cellEl: f });
1038
+ typeof m == "string" ? (f.innerHTML = G(m), y = !0) : m instanceof Node ? m.parentElement !== f && (f.textContent = "", f.appendChild(m)) : m == null && (f.textContent = p == null ? "" : String(p));
1039
+ } else if (C) {
1040
+ const m = C, w = document.createElement("div");
1041
+ w.setAttribute("data-external-view", ""), w.setAttribute("data-field", d.field), f.appendChild(w);
1042
+ const _ = { row: o, value: p, field: d.field, column: d };
1043
+ if (m.mount)
1033
1044
  try {
1034
- 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);
1045
+ m.mount({ placeholder: w, context: _, spec: m });
1046
+ } catch (R) {
1047
+ console.warn(`[tbw-grid] External view mount error for column '${d.field}':`, R);
1037
1048
  }
1038
1049
  else
1039
1050
  queueMicrotask(() => {
@@ -1042,26 +1053,26 @@ function B(t, e, o, i) {
1042
1053
  new CustomEvent("mount-external-view", {
1043
1054
  bubbles: !0,
1044
1055
  composed: !0,
1045
- detail: { placeholder: C, spec: w, context: y }
1056
+ detail: { placeholder: w, spec: m, context: _ }
1046
1057
  })
1047
1058
  );
1048
- } catch (S) {
1049
- console.warn(`[tbw-grid] External view event dispatch error for column '${d.field}':`, S);
1059
+ } catch (R) {
1060
+ console.warn(`[tbw-grid] External view event dispatch error for column '${d.field}':`, R);
1050
1061
  }
1051
1062
  });
1052
- C.setAttribute("data-mounted", "");
1063
+ w.setAttribute("data-mounted", "");
1053
1064
  } else if (u) {
1054
- const w = u({ row: o, value: p, field: d.field, column: d }), C = u.__blocked;
1055
- f.innerHTML = C ? "" : F(w), _ = !0, C && (f.textContent = "", f.setAttribute("data-blocked-template", ""));
1065
+ const m = u({ row: o, value: p, field: d.field, column: d }), w = u.__blocked;
1066
+ f.innerHTML = w ? "" : G(m), y = !0, w && (f.textContent = "", f.setAttribute("data-blocked-template", ""));
1056
1067
  } else if (g) {
1057
- const w = g.innerHTML;
1058
- /Reflect\.|\bProxy\b|ownKeys\(/.test(w) ? (f.textContent = "", f.setAttribute("data-blocked-template", "")) : (f.innerHTML = F(ve(w, { row: o, value: p })), _ = !0);
1068
+ const m = g.innerHTML;
1069
+ /Reflect\.|\bProxy\b|ownKeys\(/.test(m) ? (f.textContent = "", f.setAttribute("data-blocked-template", "")) : (f.innerHTML = G(we(m, { row: o, value: p })), y = !0);
1059
1070
  } else
1060
- d.type === "date" ? f.textContent = _e(p) : d.type === "boolean" ? f.innerHTML = Ce(!!p) : f.textContent = p == null ? "" : String(p);
1061
- if (_) {
1062
- Ye(f);
1063
- const w = f.textContent || "";
1064
- /Proxy|Reflect\.ownKeys/.test(w) && (f.textContent = w.replace(/Proxy|Reflect\.ownKeys/g, "").trim(), /Proxy|Reflect\.ownKeys/.test(f.textContent || "") && (f.textContent = ""));
1071
+ d.type === "date" ? f.textContent = Ce(p) : d.type === "boolean" ? f.innerHTML = ve(!!p) : f.textContent = p == null ? "" : String(p);
1072
+ if (y) {
1073
+ Xe(f);
1074
+ const m = f.textContent || "";
1075
+ /Proxy|Reflect\.ownKeys/.test(m) && (f.textContent = m.replace(/Proxy|Reflect\.ownKeys/g, "").trim(), /Proxy|Reflect\.ownKeys/.test(f.textContent || "") && (f.textContent = ""));
1065
1076
  }
1066
1077
  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
1078
  }
@@ -1082,19 +1093,19 @@ function he(t, e, o, i) {
1082
1093
  return;
1083
1094
  const c = t._focusRow !== r || t._focusCol !== a;
1084
1095
  if (t._focusRow = r, t._focusCol = a, l.classList.contains("editing")) {
1085
- c && (ee(t.shadowRoot ?? t._bodyEl), l.classList.add("cell-focus"));
1086
- const h = l.querySelector(Se);
1096
+ c && (ee(t._bodyEl ?? t), l.classList.add("cell-focus"));
1097
+ const h = l.querySelector(Ee);
1087
1098
  try {
1088
1099
  h?.focus({ preventScroll: !0 });
1089
1100
  } catch {
1090
1101
  }
1091
1102
  return;
1092
1103
  }
1093
- q(t);
1104
+ k(t);
1094
1105
  }
1095
1106
  }
1096
1107
  }
1097
- function lt(t, e) {
1108
+ function st(t, e) {
1098
1109
  if (t._dispatchKeyDown?.(e))
1099
1110
  return;
1100
1111
  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) => {
@@ -1105,7 +1116,7 @@ function lt(t, e) {
1105
1116
  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
1117
  switch (e.key) {
1107
1118
  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), q(t);
1119
+ 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
1120
  return;
1110
1121
  }
1111
1122
  case "ArrowDown":
@@ -1121,10 +1132,10 @@ function lt(t, e) {
1121
1132
  t._focusCol = Math.max(0, t._focusCol - 1), e.preventDefault();
1122
1133
  break;
1123
1134
  case "Home":
1124
- (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = 0), t._focusCol = 0, e.preventDefault(), q(t, { forceScrollLeft: !0 });
1135
+ (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = 0), t._focusCol = 0, e.preventDefault(), k(t, { forceScrollLeft: !0 });
1125
1136
  return;
1126
1137
  case "End":
1127
- (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = o), t._focusCol = i, e.preventDefault(), q(t, { forceScrollRight: !0 });
1138
+ (e.ctrlKey || e.metaKey) && (n && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = o), t._focusCol = i, e.preventDefault(), k(t, { forceScrollRight: !0 });
1128
1139
  return;
1129
1140
  case "PageDown":
1130
1141
  t._focusRow = Math.min(o, t._focusRow + 20), e.preventDefault();
@@ -1133,19 +1144,25 @@ function lt(t, e) {
1133
1144
  t._focusRow = Math.max(0, t._focusRow - 20), e.preventDefault();
1134
1145
  break;
1135
1146
  // 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
- );
1147
+ // we dispatch a cancelable activate-cell event for custom handling.
1148
+ case "Enter": {
1149
+ const h = new CustomEvent("activate-cell", {
1150
+ cancelable: !0,
1151
+ detail: { row: t._focusRow, col: t._focusCol }
1152
+ });
1153
+ if (t.dispatchEvent(h), h.defaultPrevented) {
1154
+ e.preventDefault();
1155
+ return;
1156
+ }
1141
1157
  break;
1158
+ }
1142
1159
  default:
1143
1160
  return;
1144
1161
  }
1145
- q(t);
1162
+ k(t);
1146
1163
  }
1147
1164
  }
1148
- function q(t, e) {
1165
+ function k(t, e) {
1149
1166
  if (t._virtualization?.enabled) {
1150
1167
  const { rowHeight: s, container: l, viewportEl: a } = t._virtualization, c = l, h = a?.clientHeight ?? c?.clientHeight ?? 0;
1151
1168
  if (c && h > 0) {
@@ -1159,10 +1176,11 @@ function q(t, e) {
1159
1176
  });
1160
1177
  const i = t._focusRow, n = t._virtualization.start ?? 0, r = t._virtualization.end ?? t._rows.length;
1161
1178
  if (i >= n && i < r) {
1162
- const s = t._bodyEl.querySelectorAll(".data-grid-row")[i - n], l = s?.children[t._focusCol];
1163
- if (l) {
1179
+ const s = t._bodyEl.querySelectorAll(".data-grid-row")[i - n];
1180
+ let l = s?.children[t._focusCol];
1181
+ if ((!l || !l.classList?.contains("cell")) && (l = s?.querySelector(`.cell[data-col="${t._focusCol}"]`) ?? s?.querySelector(".cell[data-col]")), l) {
1164
1182
  l.classList.add("cell-focus"), l.setAttribute("aria-selected", "true");
1165
- const a = t.shadowRoot?.querySelector(".tbw-scroll-area");
1183
+ const a = t.querySelector(".tbw-scroll-area");
1166
1184
  if (a && l && !o)
1167
1185
  if (e?.forceScrollLeft)
1168
1186
  a.scrollLeft = 0;
@@ -1176,7 +1194,7 @@ function q(t, e) {
1176
1194
  }
1177
1195
  }
1178
1196
  if (t._activeEditRows !== void 0 && t._activeEditRows !== -1 && l.classList.contains("editing")) {
1179
- const c = l.querySelector(Se);
1197
+ const c = l.querySelector(Ee);
1180
1198
  if (c && document.activeElement !== c)
1181
1199
  try {
1182
1200
  c.focus({ preventScroll: !0 });
@@ -1192,8 +1210,8 @@ function q(t, e) {
1192
1210
  }
1193
1211
  }
1194
1212
  }
1195
- var R = /* @__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))(R || {});
1196
- class at {
1213
+ 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 || {});
1214
+ class lt {
1197
1215
  #o;
1198
1216
  /** Current pending phase (0 = none pending) */
1199
1217
  #c = 0;
@@ -1272,7 +1290,7 @@ class at {
1272
1290
  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
1291
  }
1274
1292
  }
1275
- function ct(t) {
1293
+ function at(t) {
1276
1294
  let e = null, o = null, i = null, n = null;
1277
1295
  const r = (a) => {
1278
1296
  if (!e) return;
@@ -1296,8 +1314,8 @@ function ct(t) {
1296
1314
  },
1297
1315
  start(a, c, h) {
1298
1316
  a.preventDefault();
1299
- const d = h.getBoundingClientRect();
1300
- 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";
1317
+ const d = t._visibleColumns[c], f = typeof d?.width == "number" ? d.width : void 0, p = d?.__renderedWidth ?? f ?? h.getBoundingClientRect().width;
1318
+ e = { startX: a.clientX, colIndex: c, startWidth: p }, 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
1319
  },
1302
1320
  resetColumn(a) {
1303
1321
  const c = t._visibleColumns[a];
@@ -1310,7 +1328,7 @@ function ct(t) {
1310
1328
  }
1311
1329
  };
1312
1330
  }
1313
- function G(t, e, o) {
1331
+ function F(t, e, o) {
1314
1332
  const i = document.createElement(t);
1315
1333
  if (e)
1316
1334
  for (const n in e) {
@@ -1328,7 +1346,7 @@ function T(t, e) {
1328
1346
  }
1329
1347
  return o;
1330
1348
  }
1331
- function xe(t, e, o) {
1349
+ function Re(t, e, o) {
1332
1350
  const i = document.createElement("button");
1333
1351
  if (t && (i.className = t), e)
1334
1352
  for (const n in e) {
@@ -1337,12 +1355,8 @@ function xe(t, e, o) {
1337
1355
  }
1338
1356
  return i;
1339
1357
  }
1340
- function ue(t) {
1341
- const e = document.createElement("slot");
1342
- return t && (e.name = t), e;
1343
- }
1344
- const Ae = document.createElement("template");
1345
- Ae.innerHTML = `
1358
+ const xe = document.createElement("template");
1359
+ xe.innerHTML = `
1346
1360
  <div class="tbw-scroll-area">
1347
1361
  <div class="rows-body-wrapper">
1348
1362
  <div class="rows-body" role="grid">
@@ -1361,34 +1375,38 @@ Ae.innerHTML = `
1361
1375
  <div class="faux-vscroll-spacer"></div>
1362
1376
  </div>
1363
1377
  `;
1364
- function Pe() {
1365
- return Ae.content.cloneNode(!0);
1378
+ function Ae() {
1379
+ return xe.content.cloneNode(!0);
1366
1380
  }
1367
- function fe(t) {
1381
+ function ue(t) {
1368
1382
  const e = document.createDocumentFragment(), o = T(t.hasShell ? "tbw-grid-root has-shell" : "tbw-grid-root");
1369
1383
  if (t.hasShell && t.shellHeader && t.shellBody)
1370
1384
  o.appendChild(t.shellHeader), o.appendChild(t.shellBody);
1371
1385
  else {
1372
1386
  const i = T("tbw-grid-content");
1373
- i.appendChild(Pe()), o.appendChild(i);
1387
+ i.appendChild(Ae()), o.appendChild(i);
1374
1388
  }
1375
1389
  return e.appendChild(o), e;
1376
1390
  }
1377
- function dt(t) {
1391
+ function ct(t) {
1378
1392
  const e = T("tbw-shell-header", { part: "shell-header", role: "presentation" });
1379
1393
  if (t.title) {
1380
1394
  const r = T("tbw-shell-title");
1381
1395
  r.textContent = t.title, e.appendChild(r);
1382
1396
  }
1383
- const o = T("tbw-shell-content", { part: "shell-content", role: "presentation" });
1384
- o.appendChild(ue("header-content")), e.appendChild(o);
1397
+ const o = T("tbw-shell-content", {
1398
+ part: "shell-content",
1399
+ role: "presentation",
1400
+ "data-light-dom-header-content": ""
1401
+ });
1402
+ e.appendChild(o);
1385
1403
  const i = T("tbw-shell-toolbar", { part: "shell-toolbar", role: "presentation" });
1386
1404
  for (const r of t.configButtons)
1387
1405
  (r.hasElement || r.hasRender) && i.appendChild(T("tbw-toolbar-btn-slot", { "data-btn-slot": r.id }));
1388
1406
  for (const r of t.apiButtons)
1389
1407
  (r.hasElement || r.hasRender) && i.appendChild(T("tbw-toolbar-btn-slot", { "data-btn-slot": r.id }));
1390
- 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) {
1391
- const r = xe(t.isPanelOpen ? "tbw-toolbar-btn active" : "tbw-toolbar-btn", {
1408
+ if (i.appendChild(T("tbw-toolbar-light-dom", { "data-light-dom-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) {
1409
+ const r = Re(t.isPanelOpen ? "tbw-toolbar-btn active" : "tbw-toolbar-btn", {
1392
1410
  "data-panel-toggle": "",
1393
1411
  title: "Settings",
1394
1412
  "aria-label": "Toggle settings panel",
@@ -1399,12 +1417,12 @@ function dt(t) {
1399
1417
  }
1400
1418
  return e.appendChild(i), e;
1401
1419
  }
1402
- function ht(t) {
1420
+ function dt(t) {
1403
1421
  const e = T("tbw-shell-body"), o = t.panels.length > 0, i = t.panels.length === 1, n = T("tbw-grid-content");
1404
- n.appendChild(Pe());
1422
+ n.appendChild(Ae());
1405
1423
  let r = null;
1406
1424
  if (o) {
1407
- r = G("aside", {
1425
+ r = F("aside", {
1408
1426
  class: t.isPanelOpen ? "tbw-tool-panel open" : "tbw-tool-panel",
1409
1427
  part: "tool-panel",
1410
1428
  "data-position": t.position,
@@ -1421,17 +1439,17 @@ function ht(t) {
1421
1439
  );
1422
1440
  const l = T("tbw-tool-panel-content", { role: "presentation" }), a = T("tbw-accordion");
1423
1441
  for (const c of t.panels) {
1424
- const h = `tbw-accordion-section${c.isExpanded ? " expanded" : ""}${i ? " single" : ""}`, d = T(h, { "data-section": c.id }), f = xe("tbw-accordion-header", {
1442
+ const h = `tbw-accordion-section${c.isExpanded ? " expanded" : ""}${i ? " single" : ""}`, d = T(h, { "data-section": c.id }), f = Re("tbw-accordion-header", {
1425
1443
  "aria-expanded": String(c.isExpanded),
1426
1444
  "aria-controls": `tbw-section-${c.id}`
1427
1445
  });
1428
1446
  if (i && f.setAttribute("aria-disabled", "true"), c.icon) {
1429
- const u = G("span", { class: "tbw-accordion-icon" });
1447
+ const u = F("span", { class: "tbw-accordion-icon" });
1430
1448
  u.innerHTML = c.icon, f.appendChild(u);
1431
1449
  }
1432
- const p = G("span", { class: "tbw-accordion-title" });
1450
+ const p = F("span", { class: "tbw-accordion-title" });
1433
1451
  if (p.textContent = c.title, f.appendChild(p), !i) {
1434
- const u = G("span", { class: "tbw-accordion-chevron" });
1452
+ const u = F("span", { class: "tbw-accordion-chevron" });
1435
1453
  u.innerHTML = c.isExpanded ? t.collapseIcon : t.expandIcon, f.appendChild(u);
1436
1454
  }
1437
1455
  d.appendChild(f), d.appendChild(
@@ -1445,10 +1463,10 @@ function ht(t) {
1445
1463
  }
1446
1464
  return t.position === "left" && r ? (e.appendChild(r), e.appendChild(n)) : (e.appendChild(n), r && e.appendChild(r)), e;
1447
1465
  }
1448
- function O(t) {
1466
+ function D(t) {
1449
1467
  return t ? typeof t == "string" ? t : t.outerHTML : "";
1450
1468
  }
1451
- function ut() {
1469
+ function ht() {
1452
1470
  return {
1453
1471
  toolPanels: /* @__PURE__ */ new Map(),
1454
1472
  headerContents: /* @__PURE__ */ new Map(),
@@ -1462,29 +1480,29 @@ function ut() {
1462
1480
  expandedSections: /* @__PURE__ */ new Set(),
1463
1481
  headerContentCleanups: /* @__PURE__ */ new Map(),
1464
1482
  panelCleanups: /* @__PURE__ */ new Map(),
1465
- toolbarButtonCleanups: /* @__PURE__ */ new Map()
1483
+ toolbarButtonCleanups: /* @__PURE__ */ new Map(),
1484
+ lightDomContentMoved: !1,
1485
+ lightDomToolButtonsMoved: !1
1466
1486
  };
1467
1487
  }
1468
- function Le(t) {
1488
+ function Pe(t) {
1469
1489
  return !!(t?.header?.title || t?.header?.toolbarButtons?.length || t?.toolPanels?.length || t?.headerContents?.length || t?.header?.lightDomContent?.length || t?.header?.hasToolButtonsContainer);
1470
1490
  }
1471
- function pe(t, e, o = "☰") {
1472
- 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));
1491
+ function fe(t, e, o = "☰") {
1492
+ const i = t?.header?.title ?? e.lightDomTitle ?? "", n = !!i, r = D(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, b) => (g.order ?? 100) - (b.order ?? 100)), p = [...e.toolbarButtons.values()].sort((g, b) => (g.order ?? 100) - (b.order ?? 100));
1473
1493
  let u = "";
1474
1494
  for (const g of f)
1475
1495
  (g.element || g.render) && (u += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${g.id}"></div>`);
1476
1496
  for (const g of p)
1477
1497
  (g.element || g.render) && (u += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${g.id}"></div>`);
1478
- if (u += '<slot name="toolbar"></slot>', d && (u += '<div class="tbw-toolbar-separator"></div>'), c) {
1498
+ if (u += '<div class="tbw-toolbar-light-dom" data-light-dom-toolbar></div>', d && (u += '<div class="tbw-toolbar-separator"></div>'), c) {
1479
1499
  const g = e.isPanelOpen;
1480
1500
  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
1501
  }
1482
1502
  return `
1483
1503
  <div class="tbw-shell-header" part="shell-header" role="presentation">
1484
- ${n ? `<div class="tbw-shell-title">${We(i)}</div>` : ""}
1485
- <div class="tbw-shell-content" part="shell-content" role="presentation">
1486
- <slot name="header-content"></slot>
1487
- </div>
1504
+ ${n ? `<div class="tbw-shell-title">${Be(i)}</div>` : ""}
1505
+ <div class="tbw-shell-content" part="shell-content" role="presentation" data-light-dom-header-content></div>
1488
1506
  <div class="tbw-shell-toolbar" part="shell-toolbar" role="presentation">
1489
1507
  ${u}
1490
1508
  </div>
@@ -1499,13 +1517,11 @@ function M(t, e) {
1499
1517
  n && (e.lightDomTitle = n);
1500
1518
  }
1501
1519
  const i = o.querySelectorAll("tbw-grid-header-content");
1502
- i.length > 0 && e.lightDomHeaderContent.length === 0 && (e.lightDomHeaderContent = Array.from(i), e.lightDomHeaderContent.forEach((n) => {
1503
- n.setAttribute("slot", "header-content");
1504
- })), o.style.display = "none";
1520
+ i.length > 0 && e.lightDomHeaderContent.length === 0 && (e.lightDomHeaderContent = Array.from(i)), o.style.display = "none";
1505
1521
  }
1506
1522
  function z(t, e) {
1507
1523
  const o = t.querySelector(":scope > tbw-grid-tool-buttons");
1508
- o && (e.hasToolButtonsContainer = !0, o.setAttribute("slot", "toolbar"));
1524
+ o && (e.hasToolButtonsContainer = !0, o.style.display = "none");
1509
1525
  }
1510
1526
  function N(t, e, o) {
1511
1527
  t.querySelectorAll(":scope > tbw-grid-tool-panel").forEach((n) => {
@@ -1523,9 +1539,9 @@ function N(t, e, o) {
1523
1539
  d = f;
1524
1540
  else {
1525
1541
  const g = r.innerHTML.trim();
1526
- d = (m) => {
1527
- const b = document.createElement("div");
1528
- return b.innerHTML = g, m.appendChild(b), () => b.remove();
1542
+ d = (b) => {
1543
+ const C = document.createElement("div");
1544
+ return C.innerHTML = g, b.appendChild(C), () => C.remove();
1529
1545
  };
1530
1546
  }
1531
1547
  const p = e.toolPanels.get(s);
@@ -1548,7 +1564,7 @@ function N(t, e, o) {
1548
1564
  e.toolPanels.set(s, u), e.lightDomToolPanelIds.add(s), r.style.display = "none";
1549
1565
  });
1550
1566
  }
1551
- function ft(t, e, o, i) {
1567
+ function ut(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;
@@ -1571,7 +1587,7 @@ function ft(t, e, o, i) {
1571
1587
  }
1572
1588
  });
1573
1589
  }
1574
- function pt(t, e, o) {
1590
+ function ft(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 () => {
@@ -1581,8 +1597,8 @@ function pt(t, e, o) {
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(h, Math.max(l, c + m));
1585
- i.style.width = `${b}px`;
1600
+ const b = s === "left" ? g.clientX - a : a - g.clientX, C = Math.min(h, Math.max(l, c + b));
1601
+ i.style.width = `${C}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 = "";
@@ -1595,36 +1611,52 @@ function pt(t, e, o) {
1595
1611
  n.removeEventListener("mousedown", u), document.removeEventListener("mousemove", f), document.removeEventListener("mouseup", p);
1596
1612
  };
1597
1613
  }
1598
- function gt(t, e, o) {
1599
- const i = [...e?.header?.toolbarButtons ?? [], ...o.toolbarButtons.values()];
1600
- for (const n of i) {
1601
- const r = t.querySelector(`[data-btn-slot="${n.id}"]`);
1602
- if (!r) continue;
1603
- const s = o.toolbarButtonCleanups.get(n.id);
1604
- if (s && (s(), o.toolbarButtonCleanups.delete(n.id)), n.element)
1605
- r.appendChild(n.element);
1606
- else if (n.render) {
1607
- const l = n.render(r);
1608
- l && o.toolbarButtonCleanups.set(n.id, l);
1614
+ function pt(t, e, o, i) {
1615
+ const n = [...e?.header?.toolbarButtons ?? [], ...o.toolbarButtons.values()];
1616
+ for (const r of n) {
1617
+ if (r.element?.parentNode || o.toolbarButtonCleanups.has(r.id)) continue;
1618
+ const s = t.querySelector(`[data-btn-slot="${r.id}"]`);
1619
+ if (s) {
1620
+ if (r.element)
1621
+ s.appendChild(r.element);
1622
+ else if (r.render) {
1623
+ const l = r.render(s);
1624
+ l && o.toolbarButtonCleanups.set(r.id, l);
1625
+ }
1626
+ }
1627
+ }
1628
+ if (i && o.hasToolButtonsContainer && !o.lightDomToolButtonsMoved) {
1629
+ const r = t.querySelector("[data-light-dom-toolbar]"), s = i.querySelector(":scope > tbw-grid-tool-buttons");
1630
+ if (r && s && s.firstChild) {
1631
+ for (; s.firstChild; )
1632
+ r.appendChild(s.firstChild);
1633
+ o.lightDomToolButtonsMoved = !0;
1609
1634
  }
1610
1635
  }
1611
1636
  }
1612
- function He(t, e) {
1613
- const o = t.querySelector(".tbw-shell-content");
1614
- if (!o) return;
1615
- const i = [...e.headerContents.values()].sort((r, s) => (r.order ?? 100) - (s.order ?? 100)), n = o.querySelector('slot[name="header-content"]');
1616
- for (const r of i) {
1617
- const s = e.headerContentCleanups.get(r.id);
1618
- s && (s(), e.headerContentCleanups.delete(r.id));
1619
- let l = o.querySelector(`[data-header-content="${r.id}"]`);
1620
- l || (l = document.createElement("div"), l.setAttribute("data-header-content", r.id), n ? o.insertBefore(l, n) : o.appendChild(l));
1621
- const a = r.render(l);
1622
- a && e.headerContentCleanups.set(r.id, a);
1637
+ function Le(t, e) {
1638
+ const o = e.lightDomHeaderContent.length > 0 && !e.lightDomContentMoved, i = e.headerContents.size > 0;
1639
+ if (!o && !i) return;
1640
+ const n = t.querySelector(".tbw-shell-content");
1641
+ if (!n) return;
1642
+ if (o) {
1643
+ for (const s of e.lightDomHeaderContent)
1644
+ s.style.display = "", n.appendChild(s);
1645
+ e.lightDomContentMoved = !0;
1646
+ }
1647
+ const r = [...e.headerContents.values()].sort((s, l) => (s.order ?? 100) - (l.order ?? 100));
1648
+ for (const s of r) {
1649
+ const l = e.headerContentCleanups.get(s.id);
1650
+ l && (l(), e.headerContentCleanups.delete(s.id));
1651
+ let a = n.querySelector(`[data-header-content="${s.id}"]`);
1652
+ a || (a = document.createElement("div"), a.setAttribute("data-header-content", s.id), n.appendChild(a));
1653
+ const c = s.render(a);
1654
+ c && e.headerContentCleanups.set(s.id, c);
1623
1655
  }
1624
1656
  }
1625
- function wt(t, e, o) {
1657
+ function gt(t, e, o) {
1626
1658
  if (!e.isPanelOpen) return;
1627
- const i = O(o?.expand ?? L.expand), n = O(o?.collapse ?? L.collapse);
1659
+ const i = D(o?.expand ?? H.expand), n = D(o?.collapse ?? H.collapse);
1628
1660
  for (const [r, s] of e.toolPanels) {
1629
1661
  const l = e.expandedSections.has(r), a = t.querySelector(`[data-section="${r}"]`), c = a?.querySelector(".tbw-accordion-content");
1630
1662
  if (!a || !c) continue;
@@ -1643,15 +1675,15 @@ function wt(t, e, o) {
1643
1675
  }
1644
1676
  }
1645
1677
  }
1646
- function ge(t, e) {
1678
+ function pe(t, e) {
1647
1679
  const o = t.querySelector("[data-panel-toggle]");
1648
1680
  o && (o.classList.toggle("active", e.isPanelOpen), o.setAttribute("aria-pressed", String(e.isPanelOpen)));
1649
1681
  }
1650
- function we(t, e) {
1682
+ function ge(t, e) {
1651
1683
  const o = t.querySelector(".tbw-tool-panel");
1652
1684
  o && (o.classList.toggle("open", e.isPanelOpen), e.isPanelOpen || (o.style.width = ""));
1653
1685
  }
1654
- function bt(t, e) {
1686
+ function mt(t, e) {
1655
1687
  const o = [];
1656
1688
  for (const i of t?.header?.toolbarButtons ?? [])
1657
1689
  o.push({
@@ -1674,7 +1706,7 @@ function bt(t, e) {
1674
1706
  });
1675
1707
  return o;
1676
1708
  }
1677
- function mt(t) {
1709
+ function bt(t) {
1678
1710
  for (const e of t.headerContentCleanups.values())
1679
1711
  e();
1680
1712
  t.headerContentCleanups.clear();
@@ -1686,9 +1718,9 @@ function mt(t) {
1686
1718
  if (t.toolbarButtonCleanups.clear(), t.isPanelOpen)
1687
1719
  for (const e of t.expandedSections)
1688
1720
  t.toolPanels.get(e)?.onClose?.();
1689
- t.isPanelOpen = !1, t.expandedSections.clear(), t.toolPanels.clear(), t.headerContents.clear(), t.toolbarButtons.clear(), t.lightDomHeaderContent = [];
1721
+ t.isPanelOpen = !1, t.expandedSections.clear(), t.toolPanels.clear(), t.headerContents.clear(), t.toolbarButtons.clear(), t.lightDomHeaderContent = [], t.lightDomContentMoved = !1, t.lightDomToolButtonsMoved = !1;
1690
1722
  }
1691
- function vt(t, e) {
1723
+ function wt(t, e) {
1692
1724
  let o = !1;
1693
1725
  const i = {
1694
1726
  get isInitialized() {
@@ -1717,7 +1749,7 @@ function vt(t, e) {
1717
1749
  s && t.expandedSections.add(s.id);
1718
1750
  }
1719
1751
  const n = e.getShadow();
1720
- ge(n, t), we(n, t), wt(n, t, e.getAccordionIcons()), e.emit("tool-panel-open", { sections: i.expandedSections });
1752
+ pe(n, t), ge(n, t), gt(n, t, e.getAccordionIcons()), e.emit("tool-panel-open", { sections: i.expandedSections });
1721
1753
  },
1722
1754
  closeToolPanel() {
1723
1755
  if (!t.isPanelOpen) return;
@@ -1728,7 +1760,7 @@ function vt(t, e) {
1728
1760
  r.onClose?.();
1729
1761
  t.isPanelOpen = !1;
1730
1762
  const n = e.getShadow();
1731
- ge(n, t), we(n, t), e.emit("tool-panel-close", {});
1763
+ pe(n, t), ge(n, t), e.emit("tool-panel-close", {});
1732
1764
  },
1733
1765
  toggleToolPanel() {
1734
1766
  t.isPanelOpen ? i.closeToolPanel() : i.openToolPanel();
@@ -1753,7 +1785,7 @@ function vt(t, e) {
1753
1785
  const d = s.querySelector(`[data-section="${a}"] .tbw-accordion-content`);
1754
1786
  d && (d.innerHTML = "");
1755
1787
  }
1756
- t.expandedSections.add(n), J(s, n, !0), Ct(s, t, n);
1788
+ t.expandedSections.add(n), J(s, n, !0), vt(s, t, n);
1757
1789
  }
1758
1790
  e.emit("tool-panel-section-toggle", { id: n, expanded: !l });
1759
1791
  },
@@ -1782,14 +1814,14 @@ function vt(t, e) {
1782
1814
  console.warn(`[tbw-grid] Header content "${n.id}" already registered`);
1783
1815
  return;
1784
1816
  }
1785
- t.headerContents.set(n.id, n), o && He(e.getShadow(), t);
1817
+ t.headerContents.set(n.id, n), o && Le(e.getShadow(), t);
1786
1818
  },
1787
1819
  unregisterHeaderContent(n) {
1788
1820
  const r = t.headerContentCleanups.get(n);
1789
1821
  r && (r(), t.headerContentCleanups.delete(n)), t.headerContents.get(n)?.onDestroy?.(), t.headerContents.delete(n), e.getShadow().querySelector(`[data-header-content="${n}"]`)?.remove();
1790
1822
  },
1791
1823
  getToolbarButtons() {
1792
- return bt(e.getShellConfig(), t);
1824
+ return mt(e.getShellConfig(), t);
1793
1825
  },
1794
1826
  registerToolbarButton(n) {
1795
1827
  if (t.toolbarButtons.has(n.id)) {
@@ -1817,7 +1849,7 @@ function J(t, e, o) {
1817
1849
  const i = t.querySelector(`[data-section="${e}"]`);
1818
1850
  i && i.classList.toggle("expanded", o);
1819
1851
  }
1820
- function Ct(t, e, o) {
1852
+ function vt(t, e, o) {
1821
1853
  const i = e.toolPanels.get(o);
1822
1854
  if (!i?.render) return;
1823
1855
  const n = t.querySelector(`[data-section="${o}"] .tbw-accordion-content`);
@@ -1825,42 +1857,47 @@ function Ct(t, e, o) {
1825
1857
  const r = i.render(n);
1826
1858
  r && e.panelCleanups.set(o, r);
1827
1859
  }
1828
- function _t(t, e, o, i) {
1829
- const n = Le(e);
1830
- if (t.replaceChildren(), n) {
1831
- 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 = {
1860
+ function Ct(t, e, o, i) {
1861
+ const n = Pe(e), r = [], s = ["tbw-grid-header", "tbw-grid-tool-buttons", "tbw-grid-tool-panel", "tbw-grid-column"];
1862
+ for (const l of s)
1863
+ t.querySelectorAll(`:scope > ${l}`).forEach((c) => r.push(c));
1864
+ t.replaceChildren();
1865
+ for (const l of r)
1866
+ t.appendChild(l);
1867
+ if (n) {
1868
+ const l = D(i?.toolPanel ?? H.toolPanel), a = D(i?.expand ?? H.expand), c = D(i?.collapse ?? H.collapse), d = [...e?.header?.toolbarButtons ?? []].sort((m, w) => (m.order ?? 100) - (w.order ?? 100)), p = [...e?.toolPanels ?? []].sort((m, w) => (m.order ?? 100) - (w.order ?? 100)), u = {
1832
1869
  title: e?.header?.title ?? void 0,
1833
- hasPanels: d.length > 0,
1870
+ hasPanels: p.length > 0,
1834
1871
  isPanelOpen: o.isPanelOpen,
1835
- toolPanelIcon: r,
1872
+ toolPanelIcon: l,
1836
1873
  // All buttons are now in config (no more separate config vs API distinction for rendering)
1837
- configButtons: c.map((b) => ({
1838
- id: b.id,
1839
- hasElement: !!b.element,
1840
- hasRender: !!b.render
1874
+ configButtons: d.map((m) => ({
1875
+ id: m.id,
1876
+ hasElement: !!m.element,
1877
+ hasRender: !!m.render
1841
1878
  })),
1842
1879
  apiButtons: []
1843
1880
  // No longer needed - all buttons merged into configButtons
1844
- }, p = {
1881
+ }, g = {
1845
1882
  position: e?.toolPanel?.position ?? "right",
1846
1883
  isPanelOpen: o.isPanelOpen,
1847
- expandIcon: s,
1848
- collapseIcon: l,
1849
- panels: d.map((b) => ({
1850
- id: b.id,
1851
- title: b.title,
1852
- icon: O(b.icon),
1853
- isExpanded: o.expandedSections.has(b.id)
1884
+ expandIcon: a,
1885
+ collapseIcon: c,
1886
+ panels: p.map((m) => ({
1887
+ id: m.id,
1888
+ title: m.title,
1889
+ icon: D(m.icon),
1890
+ isExpanded: o.expandedSections.has(m.id)
1854
1891
  }))
1855
- }, u = dt(f), g = ht(p), m = fe({
1892
+ }, b = ct(u), C = dt(g), y = ue({
1856
1893
  hasShell: !0,
1857
- shellHeader: u,
1858
- shellBody: g
1894
+ shellHeader: b,
1895
+ shellBody: C
1859
1896
  });
1860
- t.appendChild(m);
1897
+ t.appendChild(y);
1861
1898
  } else {
1862
- const r = fe({ hasShell: !1 });
1863
- t.appendChild(r);
1899
+ const l = ue({ hasShell: !1 });
1900
+ t.appendChild(l);
1864
1901
  }
1865
1902
  return n;
1866
1903
  }
@@ -1878,19 +1915,19 @@ function yt() {
1878
1915
  momentumRaf: 0
1879
1916
  };
1880
1917
  }
1881
- function Et(t) {
1918
+ function _t(t) {
1882
1919
  t.startY = null, t.startX = null, t.scrollTop = null, t.scrollLeft = null, t.lastY = null, t.lastX = null, t.lastTime = null;
1883
1920
  }
1884
- function Oe(t) {
1921
+ function He(t) {
1885
1922
  t.momentumRaf && (cancelAnimationFrame(t.momentumRaf), t.momentumRaf = 0);
1886
1923
  }
1887
- function St(t, e, o) {
1924
+ function Et(t, e, o) {
1888
1925
  if (t.touches.length !== 1) return;
1889
- Oe(e);
1926
+ He(e);
1890
1927
  const i = t.touches[0];
1891
1928
  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
1929
  }
1893
- function Rt(t, e, o) {
1930
+ function St(t, e, o) {
1894
1931
  if (t.touches.length !== 1 || e.startY === null || e.startX === null || e.scrollTop === null || e.scrollLeft === null)
1895
1932
  return !1;
1896
1933
  const i = t.touches[0], n = i.clientY, r = i.clientX, s = performance.now(), l = e.startY - n, a = e.startX - r;
@@ -1902,15 +1939,15 @@ function Rt(t, e, o) {
1902
1939
  const { scrollTop: c, scrollHeight: h, clientHeight: d } = o.fauxScrollbar, f = h - d, p = l > 0 && c < f || l < 0 && c > 0;
1903
1940
  let u = !1;
1904
1941
  if (o.scrollArea) {
1905
- const { scrollLeft: g, scrollWidth: m, clientWidth: b } = o.scrollArea, _ = m - b;
1906
- u = a > 0 && g < _ || a < 0 && g > 0;
1942
+ const { scrollLeft: g, scrollWidth: b, clientWidth: C } = o.scrollArea, y = b - C;
1943
+ u = a > 0 && g < y || a < 0 && g > 0;
1907
1944
  }
1908
1945
  return p && (o.fauxScrollbar.scrollTop = e.scrollTop + l), u && o.scrollArea && (o.scrollArea.scrollLeft = e.scrollLeft + a), p || u;
1909
1946
  }
1910
1947
  function Tt(t, e) {
1911
- (Math.abs(t.velocityY) > 0.1 || Math.abs(t.velocityX) > 0.1) && xt(t, e), Et(t);
1948
+ (Math.abs(t.velocityY) > 0.1 || Math.abs(t.velocityX) > 0.1) && Rt(t, e), _t(t);
1912
1949
  }
1913
- function xt(t, e) {
1950
+ function Rt(t, e) {
1914
1951
  const n = () => {
1915
1952
  t.velocityY *= 0.95, t.velocityX *= 0.95;
1916
1953
  const r = t.velocityY * 16, s = t.velocityX * 16;
@@ -1918,19 +1955,19 @@ function xt(t, e) {
1918
1955
  };
1919
1956
  t.momentumRaf = requestAnimationFrame(n);
1920
1957
  }
1921
- function At(t, e, o, i) {
1922
- t.addEventListener("touchstart", (n) => St(n, e, o), {
1958
+ function xt(t, e, o, i) {
1959
+ t.addEventListener("touchstart", (n) => Et(n, e, o), {
1923
1960
  passive: !0,
1924
1961
  signal: i
1925
1962
  }), t.addEventListener(
1926
1963
  "touchmove",
1927
1964
  (n) => {
1928
- Rt(n, e, o) && n.preventDefault();
1965
+ St(n, e, o) && n.preventDefault();
1929
1966
  },
1930
1967
  { passive: !1, signal: i }
1931
1968
  ), t.addEventListener("touchend", () => Tt(e, o), { passive: !0, signal: i });
1932
1969
  }
1933
- const Pt = [
1970
+ const At = [
1934
1971
  // EditingPlugin
1935
1972
  {
1936
1973
  property: "editable",
@@ -1960,7 +1997,7 @@ const Pt = [
1960
1997
  importHint: "import { PinnedColumnsPlugin } from '@toolbox-web/grid/plugins/pinned-columns';",
1961
1998
  isUsed: (t) => t === "left" || t === "right"
1962
1999
  }
1963
- ], Lt = [
2000
+ ], Pt = [
1964
2001
  // GroupingColumnsPlugin
1965
2002
  {
1966
2003
  property: "columnGroups",
@@ -1970,29 +2007,29 @@ const Pt = [
1970
2007
  isUsed: (t) => Array.isArray(t) && t.length > 0
1971
2008
  }
1972
2009
  ];
1973
- function H(t) {
2010
+ function O(t) {
1974
2011
  return t.charAt(0).toUpperCase() + t.slice(1);
1975
2012
  }
1976
- function be(t, e) {
2013
+ function me(t, e) {
1977
2014
  return t.some((o) => o.name === e);
1978
2015
  }
1979
- function Ht(t, e) {
2016
+ function Lt(t, e) {
1980
2017
  const o = /* @__PURE__ */ new Map();
1981
2018
  function i(r, s, l, a, c = !1) {
1982
2019
  o.has(r) || o.set(r, { description: s, importHint: l, fields: [], isConfigProperty: c });
1983
2020
  const h = o.get(r);
1984
2021
  h.fields.includes(a) || h.fields.push(a);
1985
2022
  }
1986
- for (const r of Lt) {
2023
+ for (const r of Pt) {
1987
2024
  const s = t[r.property];
1988
- (r.isUsed ? r.isUsed(s) : s !== void 0) && !be(e, r.pluginName) && i(r.pluginName, r.description, r.importHint, r.property, !0);
2025
+ (r.isUsed ? r.isUsed(s) : s !== void 0) && !me(e, r.pluginName) && i(r.pluginName, r.description, r.importHint, r.property, !0);
1989
2026
  }
1990
2027
  const n = t.columns;
1991
2028
  if (n && n.length > 0)
1992
2029
  for (const r of n)
1993
- for (const s of Pt) {
2030
+ for (const s of At) {
1994
2031
  const l = r[s.property];
1995
- if ((s.isUsed ? s.isUsed(l) : l !== void 0) && !be(e, s.pluginName)) {
2032
+ if ((s.isUsed ? s.isUsed(l) : l !== void 0) && !me(e, s.pluginName)) {
1996
2033
  const c = r.field || "<unknown>";
1997
2034
  i(s.pluginName, s.description, s.importHint, c);
1998
2035
  }
@@ -2027,7 +2064,7 @@ This validation helps catch misconfigurations early. The properties listed above
2027
2064
  );
2028
2065
  }
2029
2066
  }
2030
- const Ot = {
2067
+ const Ht = {
2031
2068
  editing: "import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';",
2032
2069
  selection: "import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';",
2033
2070
  reorder: "import { ReorderPlugin } from '@toolbox-web/grid/plugins/reorder';",
@@ -2048,32 +2085,32 @@ const Ot = {
2048
2085
  serverSide: "import { ServerSidePlugin } from '@toolbox-web/grid/plugins/server-side';",
2049
2086
  columnVirtualization: "import { ColumnVirtualizationPlugin } from '@toolbox-web/grid/plugins/column-virtualization';"
2050
2087
  };
2051
- function Dt(t) {
2052
- return Ot[t] ?? `import { ${H(t)}Plugin } from '@toolbox-web/grid/plugins/${t}';`;
2088
+ function Ot(t) {
2089
+ return Ht[t] ?? `import { ${O(t)}Plugin } from '@toolbox-web/grid/plugins/${t}';`;
2053
2090
  }
2054
- function Mt(t, e) {
2091
+ function Dt(t, e) {
2055
2092
  const o = t.name, n = t.constructor.dependencies ?? [];
2056
2093
  for (const r of n) {
2057
2094
  const s = r.name, l = r.required ?? !0, a = r.reason;
2058
2095
  if (!e.some((h) => h.name === s)) {
2059
- const h = a ?? `${H(o)}Plugin requires ${H(s)}Plugin`, d = Dt(s);
2096
+ const h = a ?? `${O(o)}Plugin requires ${O(s)}Plugin`, d = Ot(s);
2060
2097
  if (l)
2061
2098
  throw new Error(
2062
2099
  `[tbw-grid] Plugin dependency error:
2063
2100
 
2064
2101
  ${h}.
2065
2102
 
2066
- → Add the plugin to your gridConfig.plugins array BEFORE ${H(o)}Plugin:
2103
+ → Add the plugin to your gridConfig.plugins array BEFORE ${O(o)}Plugin:
2067
2104
  ${d}
2068
- plugins: [new ${H(s)}Plugin(), new ${H(o)}Plugin()]`
2105
+ plugins: [new ${O(s)}Plugin(), new ${O(o)}Plugin()]`
2069
2106
  );
2070
2107
  console.info(
2071
- `[tbw-grid] ${H(o)}Plugin: Optional "${s}" plugin not found. Some features may be unavailable.`
2108
+ `[tbw-grid] ${O(o)}Plugin: Optional "${s}" plugin not found. Some features may be unavailable.`
2072
2109
  );
2073
2110
  }
2074
2111
  }
2075
2112
  }
2076
- class zt {
2113
+ class Mt {
2077
2114
  constructor(e) {
2078
2115
  this.grid = e;
2079
2116
  }
@@ -2103,7 +2140,7 @@ class zt {
2103
2140
  * Validates dependencies and notifies other plugins of the new attachment.
2104
2141
  */
2105
2142
  attach(e) {
2106
- if (Mt(e, this.plugins), this.pluginMap.set(e.constructor, e), this.plugins.push(e), e.cellRenderers)
2143
+ if (Dt(e, this.plugins), this.pluginMap.set(e.constructor, e), this.plugins.push(e), e.cellRenderers)
2107
2144
  for (const [o, i] of Object.entries(e.cellRenderers))
2108
2145
  this.cellRenderers.set(o, i);
2109
2146
  if (e.headerRenderers)
@@ -2177,11 +2214,11 @@ class zt {
2177
2214
  return this.cellEditors.get(e);
2178
2215
  }
2179
2216
  /**
2180
- * Get all CSS styles from all plugins.
2217
+ * Get all CSS styles from all plugins as structured data.
2218
+ * Returns an array of { name, styles } for each plugin with styles.
2181
2219
  */
2182
- getAllStyles() {
2183
- return this.plugins.filter((e) => e.styles).map((e) => e.styles).join(`
2184
- `);
2220
+ getPluginStyles() {
2221
+ return this.plugins.filter((e) => e.styles).map((e) => ({ name: e.name, styles: e.styles }));
2185
2222
  }
2186
2223
  // #region Hook execution methods
2187
2224
  /**
@@ -2407,10 +2444,10 @@ class zt {
2407
2444
  }
2408
2445
  // #endregion
2409
2446
  }
2410
- class D extends HTMLElement {
2447
+ class x extends HTMLElement {
2411
2448
  // TODO: Rename to 'data-grid' when migration is complete
2412
2449
  static tagName = "tbw-grid";
2413
- static version = "0.4.1";
2450
+ static version = "0.5.0";
2414
2451
  // ---------------- Framework Adapters ----------------
2415
2452
  /**
2416
2453
  * Registry of framework adapters that handle converting light DOM elements
@@ -2451,7 +2488,26 @@ class D extends HTMLElement {
2451
2488
  static get observedAttributes() {
2452
2489
  return ["rows", "columns", "grid-config", "fit-mode", "edit-on"];
2453
2490
  }
2454
- #o;
2491
+ /**
2492
+ * The render root for the grid. Without Shadow DOM, this is the element itself.
2493
+ * This abstraction allows internal code to work the same way regardless of DOM mode.
2494
+ */
2495
+ get #o() {
2496
+ return this;
2497
+ }
2498
+ /**
2499
+ * Access the grid's ShadowRoot.
2500
+ *
2501
+ * Note: The grid renders into its light DOM and does not attach a shadow root,
2502
+ * so this getter returns `null`. Use `grid.querySelector()` directly for DOM queries.
2503
+ *
2504
+ * @deprecated This property returns `null` since Shadow DOM was removed.
2505
+ * Use `grid.querySelector()` or `grid.querySelectorAll()` directly.
2506
+ * @returns null (no shadow root is attached)
2507
+ */
2508
+ get shadowRoot() {
2509
+ return super.shadowRoot;
2510
+ }
2455
2511
  #c = !1;
2456
2512
  // ---------------- Ready Promise ----------------
2457
2513
  #f;
@@ -2482,16 +2538,16 @@ class D extends HTMLElement {
2482
2538
  // Centralizes all rendering through a single RAF-based pipeline
2483
2539
  #l;
2484
2540
  #v = 0;
2485
- #w = null;
2541
+ #m = null;
2486
2542
  #b = !1;
2487
2543
  // Cached flag for plugin scroll handlers
2488
2544
  #s;
2489
2545
  // Cached hook to avoid closures
2490
- #m = !1;
2546
+ #w = !1;
2491
2547
  #A = yt();
2492
2548
  #g;
2493
- #_;
2494
2549
  #y;
2550
+ #_;
2495
2551
  // Watches first row for size changes (CSS loading, custom renderers)
2496
2552
  #C;
2497
2553
  // Handle for cancelling deferred idle work
@@ -2518,7 +2574,7 @@ class D extends HTMLElement {
2518
2574
  // ---------------- Config Manager ----------------
2519
2575
  #t;
2520
2576
  // ---------------- Shell State ----------------
2521
- #e = ut();
2577
+ #e = ht();
2522
2578
  #a;
2523
2579
  #D;
2524
2580
  // #endregion
@@ -2527,7 +2583,7 @@ class D extends HTMLElement {
2527
2583
  _rows = [];
2528
2584
  // _baseColumns: columns before plugin transformation (analogous to #rows for row processing)
2529
2585
  // This is the source of truth for processColumns - plugins transform these
2530
- #z = [];
2586
+ #k = [];
2531
2587
  // _columns is a getter/setter that operates on effectiveConfig.columns
2532
2588
  // This ensures effectiveConfig.columns is the single source of truth for columns
2533
2589
  // _columns always contains ALL columns (including hidden)
@@ -2563,6 +2619,8 @@ class D extends HTMLElement {
2563
2619
  // Focus & navigation
2564
2620
  _focusRow = 0;
2565
2621
  _focusCol = 0;
2622
+ /** Flag to restore focus styling after next render. @internal */
2623
+ _restoreFocusAfterRender = !1;
2566
2624
  // Sort state
2567
2625
  _sortState = null;
2568
2626
  // Layout
@@ -2663,50 +2721,50 @@ class D extends HTMLElement {
2663
2721
  }
2664
2722
  // #endregion
2665
2723
  constructor() {
2666
- super(), this.#o = this.attachShadow({ mode: "open" }), this.#J(), this.#f = new Promise((e) => this.#d = e), this.#l = new at({
2724
+ super(), this.#ie(), this.#f = new Promise((e) => this.#d = e), this.#l = new lt({
2667
2725
  mergeConfig: () => {
2668
- this.#t.parseLightDomColumns(this), this.#t.merge(), this.#V(), Ht(this.#n, this.#i?.getPlugins() ?? []), this.#z = [...this._columns];
2726
+ this.#t.parseLightDomColumns(this), this.#t.merge(), this.#K(), Lt(this.#n, this.#i?.getPlugins() ?? []), this.#k = [...this._columns];
2669
2727
  },
2670
- processColumns: () => this.#de(),
2671
- processRows: () => this.#he(),
2728
+ processColumns: () => this.#ge(),
2729
+ processRows: () => this.#me(),
2672
2730
  renderHeader: () => X(this),
2673
- updateTemplate: () => I(this),
2731
+ updateTemplate: () => q(this),
2674
2732
  renderVirtualWindow: () => this.refreshVirtualWindow(!0),
2675
2733
  afterRender: () => {
2676
- this.#i?.afterRender(), this.#n.fitMode === "fixed" && !this.__didInitialAutoSize && (this.__didInitialAutoSize = !0, ne(this));
2734
+ 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.#N && this.#se();
2677
2735
  },
2678
2736
  isConnected: () => this.isConnected && this.#h
2679
- }), this.#l.setInitialReadyResolver(() => this.#d?.()), this.#a = vt(this.#e, {
2737
+ }), this.#l.setInitialReadyResolver(() => this.#d?.()), this.#a = wt(this.#e, {
2680
2738
  getShadow: () => this.#o,
2681
2739
  getShellConfig: () => this.#n?.shell,
2682
2740
  getAccordionIcons: () => ({
2683
- expand: this.#n?.icons?.expand ?? L.expand,
2684
- collapse: this.#n?.icons?.collapse ?? L.collapse
2741
+ expand: this.#n?.icons?.expand ?? H.expand,
2742
+ collapse: this.#n?.icons?.collapse ?? H.collapse
2685
2743
  }),
2686
- emit: (e, o) => this.#Y(e, o),
2744
+ emit: (e, o) => this.#J(e, o),
2687
2745
  refreshShellHeader: () => this.refreshShellHeader()
2688
- }), this.#t = new Ke({
2746
+ }), this.#t = new je({
2689
2747
  getRows: () => this.#r,
2690
2748
  getSortState: () => this._sortState,
2691
2749
  setSortState: (e) => {
2692
2750
  this._sortState = e;
2693
2751
  },
2694
2752
  onConfigChange: () => {
2695
- this.#l.requestPhase(R.FULL, "configChange");
2753
+ this.#l.requestPhase(S.FULL, "configChange");
2696
2754
  },
2697
- emit: (e, o) => this.#Y(e, o),
2755
+ emit: (e, o) => this.#J(e, o),
2698
2756
  clearRowPool: () => {
2699
2757
  this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++;
2700
2758
  },
2701
- setup: () => this.#T(),
2759
+ setup: () => this.#x(),
2702
2760
  renderHeader: () => X(this),
2703
- updateTemplate: () => I(this),
2704
- refreshVirtualWindow: () => this.#l.requestPhase(R.VIRTUALIZATION, "configManager"),
2761
+ updateTemplate: () => q(this),
2762
+ refreshVirtualWindow: () => this.#l.requestPhase(S.VIRTUALIZATION, "configManager"),
2705
2763
  getVirtualization: () => this._virtualization,
2706
2764
  setRowHeight: (e) => {
2707
2765
  this._virtualization.rowHeight = e;
2708
2766
  },
2709
- applyAnimationConfig: (e) => this.#ue(e),
2767
+ applyAnimationConfig: (e) => this.#be(e),
2710
2768
  getShellLightDomTitle: () => this.#e.lightDomTitle,
2711
2769
  getShellToolPanels: () => this.#e.toolPanels,
2712
2770
  getShellHeaderContents: () => this.#e.headerContents,
@@ -2715,33 +2773,64 @@ class D extends HTMLElement {
2715
2773
  getShellHasToolButtonsContainer: () => this.#e.hasToolButtonsContainer
2716
2774
  });
2717
2775
  }
2718
- async #J() {
2719
- const e = new CSSStyleSheet();
2720
- if (te.length > 0) {
2721
- e.replaceSync(te), this.#o.adoptedStyleSheets = [e];
2722
- return;
2723
- }
2724
- await new Promise((o) => setTimeout(o, 50));
2725
- try {
2726
- let o = "";
2727
- for (const i of Array.from(document.styleSheets))
2728
- try {
2729
- const r = Array.from(i.cssRules || []).map((s) => s.cssText).join(`
2776
+ /** ID for the consolidated grid stylesheet in document.head */
2777
+ static #Y = "tbw-grid-styles";
2778
+ /** Track injected base styles CSS text */
2779
+ static #M = "";
2780
+ /** Track injected plugin styles by plugin name (accumulates across all grid instances) */
2781
+ static #I = /* @__PURE__ */ new Map();
2782
+ /**
2783
+ * Get or create the consolidated style element in document.head.
2784
+ * All grid and plugin styles are combined into this single element.
2785
+ */
2786
+ static #oe() {
2787
+ let e = document.getElementById(this.#Y);
2788
+ return e || (e = document.createElement("style"), e.id = this.#Y, e.setAttribute("data-tbw-grid", "true"), document.head.appendChild(e)), e;
2789
+ }
2790
+ /**
2791
+ * Update the consolidated stylesheet with current base + plugin styles.
2792
+ */
2793
+ static #q() {
2794
+ const e = this.#oe(), o = Array.from(this.#I.values()).join(`
2795
+ `);
2796
+ e.textContent = `${this.#M}
2797
+
2798
+ /* Plugin Styles */
2799
+ ${o}`;
2800
+ }
2801
+ /**
2802
+ * Inject grid styles into the document.
2803
+ * All styles go into a single <style id="tbw-grid-styles"> element in document.head.
2804
+ * Uses a singleton pattern to avoid duplicate injection across multiple grid instances.
2805
+ */
2806
+ async #ie() {
2807
+ if (!x.#M) {
2808
+ if (te.length > 0) {
2809
+ x.#M = te, x.#q();
2810
+ return;
2811
+ }
2812
+ await new Promise((e) => setTimeout(e, 50));
2813
+ try {
2814
+ let e = "";
2815
+ for (const o of Array.from(document.styleSheets))
2816
+ try {
2817
+ const n = Array.from(o.cssRules || []).map((r) => r.cssText).join(`
2730
2818
  `);
2731
- if (r.includes(".tbw-grid-root") && r.includes(":host")) {
2732
- o = r;
2733
- break;
2819
+ if (n.includes(".tbw-grid-root") && n.includes("tbw-grid")) {
2820
+ e = n;
2821
+ break;
2822
+ }
2823
+ } catch {
2824
+ continue;
2734
2825
  }
2735
- } catch {
2736
- continue;
2737
- }
2738
- o ? (e.replaceSync(o), this.#o.adoptedStyleSheets = [e]) : (typeof process > "u" || process.env?.NODE_ENV !== "test") && console.warn(
2739
- "[tbw-grid] Could not find grid.css in document.styleSheets. Grid styling will not work.",
2740
- "Available stylesheets:",
2741
- Array.from(document.styleSheets).map((i) => i.href || "(inline)")
2742
- );
2743
- } catch (o) {
2744
- console.warn("[tbw-grid] Failed to extract grid.css from document stylesheets:", o);
2826
+ e ? (x.#M = e, x.#q()) : (typeof process > "u" || process.env?.NODE_ENV !== "test") && console.warn(
2827
+ "[tbw-grid] Could not find grid.css in document.styleSheets. Grid styling will not work.",
2828
+ "Available stylesheets:",
2829
+ Array.from(document.styleSheets).map((o) => o.href || "(inline)")
2830
+ );
2831
+ } catch (e) {
2832
+ console.warn("[tbw-grid] Failed to extract grid.css from document stylesheets:", e);
2833
+ }
2745
2834
  }
2746
2835
  }
2747
2836
  // ---------------- Plugin System ----------------
@@ -2768,7 +2857,16 @@ class D extends HTMLElement {
2768
2857
  * @internal Plugin API
2769
2858
  */
2770
2859
  requestRender() {
2771
- this.#l.requestPhase(R.ROWS, "plugin:requestRender");
2860
+ this.#l.requestPhase(S.ROWS, "plugin:requestRender");
2861
+ }
2862
+ /**
2863
+ * Request a full re-render and restore focus styling afterward.
2864
+ * Use this when a plugin action (like expand/collapse) triggers a render
2865
+ * but needs to maintain keyboard navigation focus.
2866
+ * @internal Plugin API
2867
+ */
2868
+ requestRenderWithFocus() {
2869
+ this._restoreFocusAfterRender = !0, this.#l.requestPhase(S.ROWS, "plugin:requestRenderWithFocus");
2772
2870
  }
2773
2871
  /**
2774
2872
  * Update the grid's column template CSS.
@@ -2776,7 +2874,7 @@ class D extends HTMLElement {
2776
2874
  * @internal
2777
2875
  */
2778
2876
  updateTemplate() {
2779
- I(this);
2877
+ q(this);
2780
2878
  }
2781
2879
  /**
2782
2880
  * Request a lightweight style update without rebuilding DOM.
@@ -2785,34 +2883,35 @@ class D extends HTMLElement {
2785
2883
  * @internal Plugin API
2786
2884
  */
2787
2885
  requestAfterRender() {
2788
- this.#l.requestPhase(R.STYLE, "plugin:requestAfterRender");
2886
+ this.#l.requestPhase(S.STYLE, "plugin:requestAfterRender");
2789
2887
  }
2790
2888
  /**
2791
2889
  * Initialize plugin system with instances from config.
2792
2890
  * Plugins are class instances passed in gridConfig.plugins[].
2793
2891
  */
2794
- #G() {
2795
- this.#i = new zt(this);
2892
+ #j() {
2893
+ this.#i = new Mt(this);
2796
2894
  const e = this.#n?.plugins, o = Array.isArray(e) ? e : [];
2797
2895
  this.#i.attachAll(o);
2798
2896
  }
2799
2897
  /**
2800
- * Inject all plugin styles into the shadow DOM.
2801
- * Must be called after #render() since innerHTML wipes existing content.
2898
+ * Inject all plugin styles into the consolidated style element.
2899
+ * Plugin styles are appended after base grid styles in the same <style> element.
2900
+ * Uses a Map to accumulate styles from all grid instances on the page.
2802
2901
  */
2803
- #M() {
2804
- const e = this.#i?.getAllStyles() ?? "";
2805
- if (e) {
2806
- const o = document.createElement("style");
2807
- o.setAttribute("data-plugin", "all"), o.textContent = e, this.#o.appendChild(o);
2808
- }
2902
+ #z() {
2903
+ const e = this.#i?.getPluginStyles() ?? [];
2904
+ let o = !1;
2905
+ for (const { name: i, styles: n } of e)
2906
+ x.#I.has(i) || (x.#I.set(i, n), o = !0);
2907
+ o && x.#q();
2809
2908
  }
2810
2909
  /**
2811
2910
  * Update plugins when grid config changes.
2812
2911
  * With class-based plugins, we need to detach old and attach new.
2813
2912
  * Skips re-initialization if the plugins array hasn't changed.
2814
2913
  */
2815
- #V() {
2914
+ #K() {
2816
2915
  const e = this.#n?.plugins, o = Array.isArray(e) ? e : [];
2817
2916
  if (this.#E !== o) {
2818
2917
  if (this.#E && this.#E.length === o.length && this.#E.every((i, n) => i === o[n])) {
@@ -2831,20 +2930,20 @@ class D extends HTMLElement {
2831
2930
  const n = this.#e.headerContentCleanups.get(i);
2832
2931
  n && (n(), this.#e.headerContentCleanups.delete(i)), this.#e.headerContents.delete(i);
2833
2932
  }
2834
- this.#G(), this.#M(), this.#E = o, this.#F(), this.#b = this.#i?.getAll().some((i) => i.onScroll) ?? !1;
2933
+ this.#j(), this.#z(), this.#E = o, this.#Z(), this.#b = this.#i?.getAll().some((i) => i.onScroll) ?? !1;
2835
2934
  }
2836
2935
  }
2837
2936
  /**
2838
2937
  * Clean up plugin states when grid disconnects.
2839
2938
  */
2840
- #Q() {
2939
+ #ne() {
2841
2940
  this.#i?.detachAll();
2842
2941
  }
2843
2942
  /**
2844
2943
  * Collect tool panels and header content from all plugins.
2845
2944
  * Called after plugins are attached but before render.
2846
2945
  */
2847
- #F() {
2946
+ #Z() {
2848
2947
  if (!this.#i) return;
2849
2948
  const e = this.#i.getToolPanels();
2850
2949
  for (const { panel: i } of e)
@@ -2858,7 +2957,7 @@ class D extends HTMLElement {
2858
2957
  * Returns a factory function that tries each adapter in order until one handles the element.
2859
2958
  */
2860
2959
  #R() {
2861
- const e = D.getAdapters();
2960
+ const e = x.getAdapters();
2862
2961
  if (e.length === 0 && !this.__frameworkAdapter) return;
2863
2962
  const o = this.__frameworkAdapter;
2864
2963
  return (i) => {
@@ -2875,17 +2974,17 @@ class D extends HTMLElement {
2875
2974
  }
2876
2975
  // ---------------- Lifecycle ----------------
2877
2976
  connectedCallback() {
2878
- 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.#G();
2977
+ this.hasAttribute("tabindex") || (this.tabIndex = 0), this.hasAttribute("version") || this.setAttribute("version", x.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.#j();
2879
2978
  const e = this.#n?.plugins;
2880
- this.#E = Array.isArray(e) ? e : [], this.#F(), this.#c || (this.#U(), this.#M(), this.#c = !0), this.#N(), this.#C = it(
2979
+ this.#E = Array.isArray(e) ? e : [], this.#Z(), this.#c || (this.#G(), this.#z(), this.#c = !0), this.#B(), this.#C = ot(
2881
2980
  () => {
2882
- this.#me();
2981
+ this.#Ee();
2883
2982
  },
2884
2983
  { timeout: 100 }
2885
2984
  );
2886
2985
  }
2887
2986
  disconnectedCallback() {
2888
- 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.#k = !1), $(this), this.#x.clear(), this.#E = void 0;
2987
+ this.#C && (de(this.#C), this.#C = void 0), this.#ne(), 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.#y && (this.#y.disconnect(), this.#y = void 0), this.#_ && (this.#_.disconnect(), this.#_ = void 0, this.#N = !1), U(this), this.#T.clear(), this.#E = void 0;
2889
2988
  for (const e of this._rowPool)
2890
2989
  e.remove();
2891
2990
  this._rowPool.length = 0, this.__rowsBodyEl = null, this.#h = !1;
@@ -2906,26 +3005,26 @@ class D extends HTMLElement {
2906
3005
  }
2907
3006
  else e === "fit-mode" ? this.fitMode = i : e === "edit-on" && (this.editOn = i);
2908
3007
  }
2909
- #N() {
3008
+ #B() {
2910
3009
  const o = this.#o.querySelector(".tbw-grid-content") ?? this.#o.querySelector(".tbw-grid-root");
2911
3010
  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) {
2912
- He(this.#o, this.#e), gt(this.#o, this.#n?.shell, this.#e);
3011
+ Le(this.#o, this.#e), pt(this.#o, this.#n?.shell, this.#e, this);
2913
3012
  const r = this.#n?.shell?.toolPanel?.defaultOpen;
2914
3013
  r && this.#e.toolPanels.has(r) && (this.openToolPanel(), this.#e.expandedSections.add(r));
2915
3014
  }
2916
- if (this.setAttribute("data-upgraded", ""), this.#h = !0, this._resizeController = ct(this), this.#T(), this.#ee(o), this.#O)
3015
+ if (this.setAttribute("data-upgraded", ""), this.#h = !0, this._resizeController = at(this), this.#x(), this.#re(o), this.#O)
2917
3016
  return;
2918
3017
  this.#O = !0;
2919
3018
  const i = this.disconnectSignal;
2920
- 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 });
3019
+ this.addEventListener("keydown", (r) => st(this, r), { signal: i }), this.#o.addEventListener("mousedown", (r) => this.#ve(r), { signal: i }), document.addEventListener("mousemove", (r) => this.#Ce(r), { signal: i }), document.addEventListener("mouseup", (r) => this.#ye(r), { signal: i });
2921
3020
  const n = this.#n.rowHeight;
2922
- n && n > 0 ? this._virtualization.rowHeight = n : requestAnimationFrame(() => this.#X()), queueMicrotask(() => this.#oe()), this.#l.requestPhase(R.FULL, "afterConnect");
3021
+ n && n > 0 ? this._virtualization.rowHeight = n : requestAnimationFrame(() => this.#W()), queueMicrotask(() => this.#le()), this.#l.requestPhase(S.FULL, "afterConnect");
2923
3022
  }
2924
3023
  /**
2925
3024
  * Measure actual row height from DOM.
2926
3025
  * Finds the tallest cell to account for custom renderers that may push height.
2927
3026
  */
2928
- #X() {
3027
+ #W() {
2929
3028
  const e = this._bodyEl?.querySelector(".data-grid-row");
2930
3029
  if (!e) return;
2931
3030
  const o = e.querySelectorAll(".cell");
@@ -2935,14 +3034,14 @@ class D extends HTMLElement {
2935
3034
  l > i && (i = l);
2936
3035
  });
2937
3036
  const n = e.getBoundingClientRect(), r = Math.max(n.height, i);
2938
- r > 0 && r !== this._virtualization.rowHeight && (this._virtualization.rowHeight = r, this.#l.requestPhase(R.VIRTUALIZATION, "measureRowHeight"));
3037
+ r > 0 && r !== this._virtualization.rowHeight && (this._virtualization.rowHeight = r, this.#l.requestPhase(S.VIRTUALIZATION, "measureRowHeight"));
2939
3038
  }
2940
3039
  /**
2941
3040
  * Set up scroll-related event listeners on DOM elements.
2942
3041
  * These need to be re-attached when the DOM is recreated (e.g., shell toggle).
2943
3042
  * Uses a separate AbortController that is recreated each time.
2944
3043
  */
2945
- #ee(e) {
3044
+ #re(e) {
2946
3045
  this.#P?.abort(), this.#P = new AbortController();
2947
3046
  const o = this.#P.signal, i = e?.querySelector(".faux-vscroll"), n = e?.querySelector(".rows");
2948
3047
  if (this._virtualization.container = i ?? this, this.#b = this.#i?.getAll().some((r) => r.onScroll) ?? !1, i && n) {
@@ -2957,8 +3056,8 @@ class D extends HTMLElement {
2957
3056
  const c = Math.floor(l / a), h = c - c % 2, d = -(l - h * a);
2958
3057
  n.style.transform = `translateY(${d}px)`;
2959
3058
  }
2960
- this.#w = l, this.#v || (this.#v = requestAnimationFrame(() => {
2961
- this.#v = 0, this.#w !== null && (this.#fe(this.#w), this.#w = null);
3059
+ this.#m = l, this.#v || (this.#v = requestAnimationFrame(() => {
3060
+ this.#v = 0, this.#m !== null && (this.#we(this.#m), this.#m = null);
2962
3061
  }));
2963
3062
  },
2964
3063
  { passive: !0, signal: o }
@@ -2977,35 +3076,47 @@ class D extends HTMLElement {
2977
3076
  }
2978
3077
  },
2979
3078
  { passive: !1, signal: o }
2980
- ), At(r, this.#A, { fauxScrollbar: i, scrollArea: s }, o));
3079
+ ), xt(r, this.#A, { fauxScrollbar: i, scrollArea: s }, o));
2981
3080
  }
2982
- this._bodyEl && Qe(this, this._bodyEl, o), this.#_?.disconnect(), this._virtualization.viewportEl && (this.#_ = new ResizeObserver(() => {
2983
- this.#l.requestPhase(R.VIRTUALIZATION, "resize-observer");
2984
- }), this.#_.observe(this._virtualization.viewportEl)), this._virtualization.enabled && (this.#l.requestPhase(R.VIRTUALIZATION, "init-virtualization"), queueMicrotask(() => this.#te()));
3081
+ this._bodyEl && Je(this, this._bodyEl, o), this.#y?.disconnect(), this._virtualization.viewportEl && (this.#y = new ResizeObserver(() => {
3082
+ this.#l.requestPhase(S.VIRTUALIZATION, "resize-observer");
3083
+ }), this.#y.observe(this._virtualization.viewportEl)), this._virtualization.enabled && this.#l.requestPhase(S.VIRTUALIZATION, "init-virtualization"), this.#o.addEventListener(
3084
+ "focusin",
3085
+ () => {
3086
+ this.dataset.hasFocus = "";
3087
+ },
3088
+ { signal: o }
3089
+ ), this.#o.addEventListener(
3090
+ "focusout",
3091
+ (r) => {
3092
+ const s = r.relatedTarget;
3093
+ (!s || !this.#o.contains(s)) && delete this.dataset.hasFocus;
3094
+ },
3095
+ { signal: o }
3096
+ );
2985
3097
  }
2986
3098
  /**
2987
- * Set up ResizeObserver on first row's cells to detect height changes.
2988
- * Called after rows are rendered to observe the actual content cells.
2989
- * Handles dynamic CSS loading, lazy images, font loading, etc.
3099
+ * Set up ResizeObserver on first row to detect height changes.
3100
+ * Called after rows are rendered to observe the actual content.
3101
+ * Handles dynamic CSS loading, lazy images, font loading, column virtualization, etc.
2990
3102
  */
2991
- #k = !1;
3103
+ #N = !1;
2992
3104
  // Only set up once per lifecycle
2993
- #te() {
2994
- if (this.#k) return;
3105
+ #se() {
3106
+ if (this.#N) return;
2995
3107
  const e = this._bodyEl?.querySelector(".data-grid-row");
2996
- if (!e) return;
2997
- this.#k = !0, this.#y?.disconnect();
2998
- const o = e.querySelectorAll(".cell");
2999
- o.length > 0 && (this.#y = new ResizeObserver(() => {
3000
- this.#X();
3001
- }), o.forEach((i) => this.#y.observe(i)));
3108
+ e && (this.#N = !0, this.#_?.disconnect(), this.#_ = new ResizeObserver(() => {
3109
+ this.#W();
3110
+ }), this.#_.observe(e), requestAnimationFrame(() => {
3111
+ this.#W();
3112
+ }));
3002
3113
  }
3003
3114
  // ---------------- Event Emitters ----------------
3004
- #Y(e, o) {
3115
+ #J(e, o) {
3005
3116
  this.dispatchEvent(new CustomEvent(e, { detail: o, bubbles: !0, composed: !0 }));
3006
3117
  }
3007
3118
  /** Update ARIA selection attributes on rendered rows/cells */
3008
- #oe() {
3119
+ #le() {
3009
3120
  this._bodyEl?.querySelectorAll(".data-grid-row")?.forEach((o, i) => {
3010
3121
  const n = i === this._focusRow;
3011
3122
  o.setAttribute("aria-selected", String(n)), o.querySelectorAll(".cell").forEach((r, s) => {
@@ -3021,13 +3132,13 @@ class D extends HTMLElement {
3021
3132
  * All updates queued within the same microtask are batched together.
3022
3133
  */
3023
3134
  #H(e) {
3024
- this.#p[e] = !0, !this.#u && (this.#u = !0, queueMicrotask(() => this.#ie()));
3135
+ this.#p[e] = !0, !this.#u && (this.#u = !0, queueMicrotask(() => this.#ae()));
3025
3136
  }
3026
3137
  /**
3027
3138
  * Process all pending updates in optimal order.
3028
3139
  * Priority: gridConfig first (may affect all), then columns, rows, fitMode, editMode
3029
3140
  */
3030
- #ie() {
3141
+ #ae() {
3031
3142
  if (!this.#u || !this.#h) {
3032
3143
  this.#u = !1;
3033
3144
  return;
@@ -3040,42 +3151,42 @@ class D extends HTMLElement {
3040
3151
  fitMode: !1,
3041
3152
  editMode: !1
3042
3153
  }, e.gridConfig) {
3043
- this.#ae();
3154
+ this.#fe();
3044
3155
  return;
3045
3156
  }
3046
- e.columns && this.#re(), e.rows && this.#ne(), e.fitMode && this.#se(), e.editMode && this.#le();
3157
+ e.columns && this.#de(), e.rows && this.#ce(), e.fitMode && this.#he(), e.editMode && this.#ue();
3047
3158
  }
3048
3159
  // Individual update applicators - these do the actual work
3049
- #ne() {
3050
- this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#l.requestPhase(R.ROWS, "applyRowsUpdate");
3160
+ #ce() {
3161
+ this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#l.requestPhase(S.ROWS, "applyRowsUpdate");
3051
3162
  }
3052
- #re() {
3053
- $(this), this.#t.merge(), this.#T();
3163
+ #de() {
3164
+ U(this), this.#t.merge(), this.#x();
3054
3165
  }
3055
- #se() {
3166
+ #he() {
3056
3167
  this.#t.merge(), this.#n.fitMode === "fixed" ? (this.__didInitialAutoSize = !1, ne(this)) : (this._columns.forEach((o) => {
3057
3168
  !o.__userResized && o.__autoSized && delete o.width;
3058
- }), I(this));
3169
+ }), q(this));
3059
3170
  }
3060
- #le() {
3061
- this.#t.merge(), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.#l.requestPhase(R.VIRTUALIZATION, "applyEditModeUpdate");
3171
+ #ue() {
3172
+ this.#t.merge(), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.#l.requestPhase(S.VIRTUALIZATION, "applyEditModeUpdate");
3062
3173
  }
3063
- #ae() {
3174
+ #fe() {
3064
3175
  M(this, this.#e), z(this, this.#e);
3065
3176
  const e = !!this.#o.querySelector(".has-shell"), o = !!this.#o.querySelector(".tbw-tool-panel"), i = this.#o.querySelectorAll(".tbw-accordion-section").length;
3066
- this.#t.parseLightDomColumns(this), this.#t.merge(), this.#V(), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge();
3067
- const n = Le(this.#n?.shell), r = (this.#n?.shell?.toolPanels?.length ?? 0) > 0, s = (this.#n?.shell?.toolPanels?.length ?? 0) !== i;
3177
+ this.#t.parseLightDomColumns(this), this.#t.merge(), this.#K(), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge();
3178
+ const n = Pe(this.#n?.shell), r = (this.#n?.shell?.toolPanels?.length ?? 0) > 0, s = (this.#n?.shell?.toolPanels?.length ?? 0) !== i;
3068
3179
  if (e !== n || !e && n || !o && r || o && s) {
3069
- this.#U(), this.#M(), this.#N();
3180
+ this.#G(), this.#z(), this.#B();
3070
3181
  return;
3071
3182
  }
3072
- e && this.#ce(), this.#l.requestPhase(R.COLUMNS, "applyGridConfigUpdate");
3183
+ e && this.#pe(), this.#l.requestPhase(S.COLUMNS, "applyGridConfigUpdate");
3073
3184
  }
3074
3185
  /**
3075
3186
  * Update the shell header DOM in place without a full re-render.
3076
3187
  * Handles title, toolbar buttons, and other shell header changes.
3077
3188
  */
3078
- #ce() {
3189
+ #pe() {
3079
3190
  const e = this.#o.querySelector(".tbw-shell-header");
3080
3191
  if (!e) return;
3081
3192
  const o = this.#n.shell?.header?.title ?? this.#e.lightDomTitle;
@@ -3086,28 +3197,20 @@ class D extends HTMLElement {
3086
3197
  // The #queueUpdate() method schedules updates which are processed by #flushPendingUpdates()
3087
3198
  // and individual #apply*Update() methods. This coalesces rapid property changes
3088
3199
  // (e.g., setting rows, columns, gridConfig in quick succession) into a single update cycle.
3089
- #de() {
3200
+ #ge() {
3090
3201
  if (this.#i) {
3091
- 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]);
3202
+ const e = this.#k.length > 0 ? this.#k : this._columns, o = e.filter((r) => !r.hidden), i = e.filter((r) => r.hidden), n = this.#i.processColumns([...o]);
3092
3203
  if (n !== o) {
3093
- const r = new Map(n.map((l, a) => [l.field, { col: l, order: a }]));
3094
- if (!o.some((l) => r.has(l.field)) && n.length > 0)
3095
- this._columns = [...n, ...i];
3096
- else {
3097
- const l = e.map((a) => {
3098
- if (a.hidden) return a;
3099
- const c = r.get(a.field);
3100
- return c ? c.col : a;
3101
- });
3102
- this._columns = l;
3103
- }
3204
+ new Set(o.map((l) => l.field));
3205
+ const r = new Set(n.map((l) => l.field));
3206
+ !o.some((l) => r.has(l.field)) && n.length > 0 ? this._columns = [...n, ...i] : this._columns = [...n, ...i];
3104
3207
  } else
3105
3208
  this._columns = [...e];
3106
3209
  }
3107
3210
  }
3108
3211
  /** Recompute row model via plugin hooks. */
3109
- #he() {
3110
- $(this);
3212
+ #me() {
3213
+ U(this);
3111
3214
  const e = Array.isArray(this.#r) ? [...this.#r] : [], o = this.#i?.processRows(e) ?? e;
3112
3215
  this._rows = o;
3113
3216
  }
@@ -3116,31 +3219,31 @@ class D extends HTMLElement {
3116
3219
  * This makes the grid's animation settings available to plugins via CSS variables.
3117
3220
  * Called by ConfigManager after merge.
3118
3221
  */
3119
- #ue(e) {
3222
+ #be(e) {
3120
3223
  const o = {
3121
- ...Me,
3224
+ ...De,
3122
3225
  ...e.animation
3123
3226
  }, i = o.mode ?? "reduced-motion";
3124
3227
  let n = 1;
3125
3228
  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;
3126
3229
  }
3127
3230
  // ---------------- Delegate Wrappers ----------------
3128
- #I(e, o, i = this.__rowRenderEpoch) {
3129
- this.#s || (this.#s = (n, r, s) => this.#i?.renderRow(n, r, s) ?? !1), st(this, e, o, i, this.#s);
3231
+ #$(e, o, i = this.__rowRenderEpoch) {
3232
+ this.#s || (this.#s = (n, r, s) => this.#i?.renderRow(n, r, s) ?? !1), rt(this, e, o, i, this.#s);
3130
3233
  }
3131
3234
  // Cache for ARIA counts to avoid redundant DOM writes on scroll (hot path)
3132
- #B = -1;
3133
- #j = -1;
3235
+ #U = -1;
3236
+ #Q = -1;
3134
3237
  /**
3135
3238
  * Updates ARIA row/col counts on the grid container.
3136
3239
  * Also sets role="rowgroup" on .rows container only when there are rows.
3137
3240
  * Uses caching to avoid redundant DOM writes on every scroll frame.
3138
3241
  */
3139
- #K(e, o) {
3140
- if (e === this.#B && o === this.#j)
3242
+ #ee(e, o) {
3243
+ if (e === this.#U && o === this.#Q)
3141
3244
  return;
3142
- const i = this.#B;
3143
- this.#B = e, this.#j = o, this.__rowsBodyEl && (this.__rowsBodyEl.setAttribute("aria-rowcount", String(e)), this.__rowsBodyEl.setAttribute("aria-colcount", String(o))), e !== i && this._bodyEl && (e > 0 ? this._bodyEl.setAttribute("role", "rowgroup") : this._bodyEl.removeAttribute("role"));
3245
+ const i = this.#U;
3246
+ this.#U = e, this.#Q = o, this.__rowsBodyEl && (this.__rowsBodyEl.setAttribute("aria-rowcount", String(e)), this.__rowsBodyEl.setAttribute("aria-colcount", String(o))), e !== i && this._bodyEl && (e > 0 ? this._bodyEl.setAttribute("role", "rowgroup") : this._bodyEl.removeAttribute("role"));
3144
3247
  }
3145
3248
  // ---------------- Core Helpers ----------------
3146
3249
  /**
@@ -3151,7 +3254,7 @@ class D extends HTMLElement {
3151
3254
  * Previously this method executed rendering synchronously, but that caused race
3152
3255
  * conditions with framework adapters that also schedule their own render work.
3153
3256
  */
3154
- #T() {
3257
+ #x() {
3155
3258
  if (this.isConnected && !(!this._headerRowEl || !this._bodyEl)) {
3156
3259
  if (this.#t.parseLightDomColumns(this), this.#L) {
3157
3260
  const e = this.#L;
@@ -3159,10 +3262,10 @@ class D extends HTMLElement {
3159
3262
  const o = this.#i?.getAll() ?? [];
3160
3263
  this.#t.applyState(e, o);
3161
3264
  }
3162
- this._bodyEl && (this._bodyEl.style.display = "", this._bodyEl.style.gridTemplateColumns = ""), this.#l.requestPhase(R.FULL, "setup");
3265
+ this._bodyEl && (this._bodyEl.style.display = "", this._bodyEl.style.gridTemplateColumns = ""), this.#l.requestPhase(S.FULL, "setup");
3163
3266
  }
3164
3267
  }
3165
- #fe(e) {
3268
+ #we(e) {
3166
3269
  if (this.refreshVirtualWindow(!1), this.#i?.onScrollRender(), this.#b) {
3167
3270
  const o = this._virtualization.container, i = this.#S;
3168
3271
  i.scrollTop = e, i.scrollLeft = o?.scrollLeft ?? 0, i.scrollHeight = o?.scrollHeight ?? 0, i.scrollWidth = o?.scrollWidth ?? 0, i.clientHeight = o?.clientHeight ?? 0, i.clientWidth = o?.clientWidth ?? 0, this.#i?.onScroll(i);
@@ -3269,11 +3372,11 @@ class D extends HTMLElement {
3269
3372
  * Build a CellMouseEvent from a native MouseEvent.
3270
3373
  * Extracts cell/row information from the event target.
3271
3374
  */
3272
- #q(e, o) {
3375
+ #F(e, o) {
3273
3376
  let i = null;
3274
3377
  const n = e.composedPath?.();
3275
3378
  if (n && n.length > 0 ? i = n[0] : i = e.target, i && !this.#o.contains(i)) {
3276
- const u = this.#o.elementFromPoint(e.clientX, e.clientY);
3379
+ const u = document.elementFromPoint(e.clientX, e.clientY);
3277
3380
  u && (i = u);
3278
3381
  }
3279
3382
  const r = i?.closest?.("[data-col]"), s = i?.closest?.(".data-grid-row"), l = i?.closest?.(".header-row");
@@ -3296,31 +3399,31 @@ class D extends HTMLElement {
3296
3399
  /**
3297
3400
  * Handle mousedown events and dispatch to plugin system.
3298
3401
  */
3299
- #pe(e) {
3300
- const o = this.#q(e, "mousedown");
3301
- (this.#i?.onCellMouseDown(o) ?? !1) && (this.#m = !0);
3402
+ #ve(e) {
3403
+ const o = this.#F(e, "mousedown");
3404
+ (this.#i?.onCellMouseDown(o) ?? !1) && (this.#w = !0);
3302
3405
  }
3303
3406
  /**
3304
3407
  * Handle mousemove events (only when dragging).
3305
3408
  */
3306
- #ge(e) {
3307
- if (!this.#m) return;
3308
- const o = this.#q(e, "mousemove");
3409
+ #Ce(e) {
3410
+ if (!this.#w) return;
3411
+ const o = this.#F(e, "mousemove");
3309
3412
  this.#i?.onCellMouseMove(o);
3310
3413
  }
3311
3414
  /**
3312
3415
  * Handle mouseup events.
3313
3416
  */
3314
- #we(e) {
3315
- if (!this.#m) return;
3316
- const o = this.#q(e, "mouseup");
3317
- this.#i?.onCellMouseUp(o), this.#m = !1;
3417
+ #ye(e) {
3418
+ if (!this.#w) return;
3419
+ const o = this.#F(e, "mouseup");
3420
+ this.#i?.onCellMouseUp(o), this.#w = !1;
3318
3421
  }
3319
3422
  async ready() {
3320
3423
  return this.#f;
3321
3424
  }
3322
3425
  async forceLayout() {
3323
- return this.#l.requestPhase(R.FULL, "forceLayout"), this.#l.whenReady();
3426
+ return this.#l.requestPhase(S.FULL, "forceLayout"), this.#l.whenReady();
3324
3427
  }
3325
3428
  /**
3326
3429
  * Trim the internal row pool to match the current visible window size.
@@ -3372,7 +3475,7 @@ class D extends HTMLElement {
3372
3475
  * Use this to restore previously saved column state.
3373
3476
  */
3374
3477
  set columnState(e) {
3375
- e && (this.#L = e, this.#t.initialColumnState = e, this.#c && this.#be(e));
3478
+ e && (this.#L = e, this.#t.initialColumnState = e, this.#c && this.#_e(e));
3376
3479
  }
3377
3480
  /**
3378
3481
  * Get the current column state.
@@ -3383,9 +3486,9 @@ class D extends HTMLElement {
3383
3486
  /**
3384
3487
  * Apply column state internally.
3385
3488
  */
3386
- #be(e) {
3489
+ #_e(e) {
3387
3490
  const o = this.#i?.getAll() ?? [];
3388
- this.#t.applyState(e, o), this.#T();
3491
+ this.#t.applyState(e, o), this.#x();
3389
3492
  }
3390
3493
  /**
3391
3494
  * Request a state change event to be emitted.
@@ -3405,7 +3508,7 @@ class D extends HTMLElement {
3405
3508
  resetColumnState() {
3406
3509
  this.#L = void 0, this.__originalOrder = [];
3407
3510
  const e = this.#i?.getAll() ?? [];
3408
- this.#t.resetState(e), this.#t.merge(), this.#T();
3511
+ this.#t.resetState(e), this.#t.merge(), this.#x();
3409
3512
  }
3410
3513
  // ---------------- Shell / Tool Panel API ----------------
3411
3514
  // These methods delegate to ShellController for implementation.
@@ -3487,11 +3590,11 @@ class D extends HTMLElement {
3487
3590
  * Call this after dynamically modifying <tbw-grid-header> children.
3488
3591
  */
3489
3592
  refreshShellHeader() {
3490
- M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge(), this.#U(), this.#M(), this.#N();
3593
+ M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge(), this.#G(), this.#z(), this.#B();
3491
3594
  }
3492
3595
  // #region Custom Styles API
3493
3596
  /** Map of registered custom stylesheets by ID - uses adoptedStyleSheets which survive DOM rebuilds */
3494
- #x = /* @__PURE__ */ new Map();
3597
+ #T = /* @__PURE__ */ new Map();
3495
3598
  /**
3496
3599
  * Register custom CSS styles to be injected into the grid's shadow DOM.
3497
3600
  * Use this to style custom cell renderers, editors, or detail panels.
@@ -3517,28 +3620,31 @@ class D extends HTMLElement {
3517
3620
  * ```
3518
3621
  */
3519
3622
  registerStyles(e, o) {
3520
- let i = this.#x.get(e);
3521
- i || (i = new CSSStyleSheet(), this.#x.set(e, i)), i.replaceSync(o), this.#Z();
3623
+ let i = this.#T.get(e);
3624
+ i || (i = new CSSStyleSheet(), this.#T.set(e, i)), i.replaceSync(o), this.#te();
3522
3625
  }
3523
3626
  /**
3524
3627
  * Remove previously registered custom styles.
3525
3628
  * @param id - The ID used when registering the styles
3526
3629
  */
3527
3630
  unregisterStyles(e) {
3528
- this.#x.delete(e) && this.#Z();
3631
+ this.#T.delete(e) && this.#te();
3529
3632
  }
3530
3633
  /**
3531
3634
  * Get list of registered custom style IDs.
3532
3635
  */
3533
3636
  getRegisteredStyles() {
3534
- return Array.from(this.#x.keys());
3637
+ return Array.from(this.#T.keys());
3535
3638
  }
3536
3639
  /**
3537
- * Update the shadow root's adoptedStyleSheets to include base + custom sheets.
3640
+ * Update document.adoptedStyleSheets to include custom sheets.
3641
+ * Without Shadow DOM, all custom styles go into the document.
3538
3642
  */
3539
- #Z() {
3540
- const e = this.#o.adoptedStyleSheets[0], o = Array.from(this.#x.values());
3541
- this.#o.adoptedStyleSheets = e ? [e, ...o] : o;
3643
+ #te() {
3644
+ const e = Array.from(this.#T.values()), o = document.adoptedStyleSheets.filter(
3645
+ (i) => !Array.from(this.#T.values()).includes(i)
3646
+ );
3647
+ document.adoptedStyleSheets = [...o, ...e];
3542
3648
  }
3543
3649
  // #endregion
3544
3650
  /**
@@ -3551,7 +3657,7 @@ class D extends HTMLElement {
3551
3657
  * This separation allows plugins to register their own Light DOM elements
3552
3658
  * and handle parsing themselves.
3553
3659
  */
3554
- #me() {
3660
+ #Ee() {
3555
3661
  const e = () => {
3556
3662
  const i = this.#e.lightDomTitle, n = this.#e.hasToolButtonsContainer;
3557
3663
  M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R());
@@ -3560,18 +3666,18 @@ class D extends HTMLElement {
3560
3666
  this.#t.markSourcesChanged(), this.#t.merge();
3561
3667
  const l = this.#o.querySelector(".tbw-shell-header");
3562
3668
  if (l) {
3563
- const a = pe(
3669
+ const a = fe(
3564
3670
  this.#n.shell,
3565
3671
  this.#e,
3566
3672
  this.#n.icons?.toolPanel
3567
3673
  ), c = document.createElement("div");
3568
3674
  c.innerHTML = a;
3569
3675
  const h = c.firstElementChild;
3570
- h && (l.replaceWith(h), this.#$());
3676
+ h && (l.replaceWith(h), this.#X());
3571
3677
  }
3572
3678
  }
3573
3679
  }, o = () => {
3574
- this.__lightDomColumnsCache = void 0, this.#T();
3680
+ this.__lightDomColumnsCache = void 0, this.#x();
3575
3681
  };
3576
3682
  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);
3577
3683
  }
@@ -3582,7 +3688,7 @@ class D extends HTMLElement {
3582
3688
  * @internal Used by framework integration libraries (Angular, React, Vue)
3583
3689
  */
3584
3690
  refreshColumns() {
3585
- this.__lightDomColumnsCache = void 0, $(this), this.#t.parseLightDomColumns(this);
3691
+ this.__lightDomColumnsCache = void 0, U(this), this.#t.parseLightDomColumns(this);
3586
3692
  const e = this.#e.lightDomTitle, o = this.#e.hasToolButtonsContainer;
3587
3693
  M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R());
3588
3694
  const i = this.#e.lightDomTitle, n = this.#e.hasToolButtonsContainer;
@@ -3590,24 +3696,24 @@ class D extends HTMLElement {
3590
3696
  this.#t.markSourcesChanged(), this.#t.merge();
3591
3697
  const s = this.#o.querySelector(".tbw-shell-header");
3592
3698
  if (s) {
3593
- const l = pe(
3699
+ const l = fe(
3594
3700
  this.#n.shell,
3595
3701
  this.#e,
3596
3702
  this.#n.icons?.toolPanel
3597
3703
  ), a = document.createElement("div");
3598
3704
  a.innerHTML = l;
3599
3705
  const c = a.firstElementChild;
3600
- c && (s.replaceWith(c), this.#$());
3706
+ c && (s.replaceWith(c), this.#X());
3601
3707
  }
3602
3708
  }
3603
- this.#l.requestPhase(R.COLUMNS, "refreshColumns");
3709
+ this.#l.requestPhase(S.COLUMNS, "refreshColumns");
3604
3710
  }
3605
3711
  // ---------------- Virtual Window ----------------
3606
3712
  /**
3607
3713
  * Calculate total height for the faux scrollbar spacer element.
3608
3714
  * Used by both bypass and virtualized rendering paths to ensure consistent scroll behavior.
3609
3715
  */
3610
- #W(e) {
3716
+ #V(e) {
3611
3717
  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);
3612
3718
  return e * o + d + f + p;
3613
3719
  }
@@ -3620,20 +3726,20 @@ class D extends HTMLElement {
3620
3726
  if (!this._bodyEl) return;
3621
3727
  const o = this._rows.length;
3622
3728
  if (!this._virtualization.enabled) {
3623
- this.#I(0, o), this.#i?.afterRender();
3729
+ this.#$(0, o), this.#i?.afterRender();
3624
3730
  return;
3625
3731
  }
3626
3732
  if (this._rows.length <= this._virtualization.bypassThreshold) {
3627
- 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();
3733
+ this._virtualization.start = 0, this._virtualization.end = o, e && (this._bodyEl.style.transform = "translateY(0px)"), this.#$(0, o, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${this.#V(o)}px`), this.#ee(o, this._visibleColumns.length), this.#i?.afterRender();
3628
3734
  return;
3629
3735
  }
3630
3736
  const i = this._virtualization.container ?? this, n = this._virtualization.viewportEl ?? i, r = n.clientHeight, s = this._virtualization.rowHeight, l = i.scrollTop;
3631
3737
  let a = Math.floor(l / s), c = 0;
3632
3738
  const h = 10;
3633
3739
  for (; c < h; ) {
3634
- const _ = this.#i?.getExtraHeightBefore?.(a) ?? 0, w = Math.floor((l - _) / s);
3635
- if (w >= a || w < 0) break;
3636
- a = w, c++;
3740
+ const y = this.#i?.getExtraHeightBefore?.(a) ?? 0, m = Math.floor((l - y) / s);
3741
+ if (m >= a || m < 0) break;
3742
+ a = m, c++;
3637
3743
  }
3638
3744
  a = a - a % 2, a < 0 && (a = 0);
3639
3745
  const d = this.#i?.adjustVirtualStart(a, l, s);
@@ -3641,39 +3747,39 @@ class D extends HTMLElement {
3641
3747
  const f = Math.ceil(r / s) + 3;
3642
3748
  let p = a + f;
3643
3749
  if (p > o && (p = o), this._virtualization.start = a, this._virtualization.end = p, i.clientHeight === 0 && r > 0) {
3644
- this.#l.requestPhase(R.VIRTUALIZATION, "stale-refs-retry");
3750
+ this.#l.requestPhase(S.VIRTUALIZATION, "stale-refs-retry");
3645
3751
  return;
3646
3752
  }
3647
- const g = this.#W(o);
3753
+ const g = this.#V(o);
3648
3754
  this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${g}px`);
3649
- const m = this.#i?.getExtraHeightBefore?.(a) ?? 0, b = -(l - a * s - m);
3650
- 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(() => {
3651
- const _ = i.clientHeight, w = n.clientHeight;
3652
- if (_ === 0 && w > 0) return;
3653
- const C = this.#W(o);
3654
- this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${C}px`);
3755
+ const b = this.#i?.getExtraHeightBefore?.(a) ?? 0, C = -(l - a * s - b);
3756
+ this._bodyEl.style.transform = `translateY(${C}px)`, this.#$(a, p, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this.#ee(o, this._visibleColumns.length), e && (this.#i?.afterRender(), queueMicrotask(() => {
3757
+ const y = i.clientHeight, m = n.clientHeight;
3758
+ if (y === 0 && m > 0) return;
3759
+ const w = this.#V(o);
3760
+ this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${w}px`);
3655
3761
  }));
3656
3762
  }
3657
3763
  // ---------------- Render ----------------
3658
- #U() {
3764
+ #G() {
3659
3765
  M(this, this.#e), z(this, this.#e), N(this, this.#e, this.#R()), this.#t.markSourcesChanged(), this.#t.merge();
3660
3766
  const e = this.#n?.shell;
3661
- _t(
3767
+ Ct(
3662
3768
  this.#o,
3663
3769
  e,
3664
3770
  { isPanelOpen: this.#e.isPanelOpen, expandedSections: this.#e.expandedSections },
3665
3771
  this.#n?.icons
3666
- ) && (this.#$(), this.#a.setInitialized(!0));
3772
+ ) && (this.#X(), this.#a.setInitialized(!0));
3667
3773
  }
3668
3774
  /**
3669
3775
  * Set up shell event listeners after render.
3670
3776
  */
3671
- #$() {
3672
- ft(this.#o, this.#n?.shell, this.#e, {
3777
+ #X() {
3778
+ ut(this.#o, this.#n?.shell, this.#e, {
3673
3779
  onPanelToggle: () => this.toggleToolPanel(),
3674
3780
  onSectionToggle: (e) => this.toggleToolPanelSection(e),
3675
- onToolbarButtonClick: (e) => this.#ve(e)
3676
- }), this.#D?.(), this.#D = pt(this.#o, this.#n?.shell, (e) => {
3781
+ onToolbarButtonClick: (e) => this.#Se(e)
3782
+ }), this.#D?.(), this.#D = ft(this.#o, this.#n?.shell, (e) => {
3677
3783
  this.style.setProperty("--tbw-tool-panel-width", `${e}px`);
3678
3784
  });
3679
3785
  }
@@ -3683,18 +3789,18 @@ class D extends HTMLElement {
3683
3789
  * This method is kept for backwards compatibility but may emit an event in the future.
3684
3790
  */
3685
3791
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3686
- #ve(e) {
3792
+ #Se(e) {
3687
3793
  }
3688
3794
  }
3689
- customElements.get(D.tagName) || customElements.define(D.tagName, D);
3690
- globalThis.DataGridElement = D;
3691
- const kt = {
3795
+ customElements.get(x.tagName) || customElements.define(x.tagName, x);
3796
+ globalThis.DataGridElement = x;
3797
+ const Nt = {
3692
3798
  /** Ask if a column can be moved. Context: ColumnConfig. Response: boolean | undefined */
3693
3799
  CAN_MOVE_COLUMN: "canMoveColumn",
3694
3800
  /** Get context menu items. Context: ContextMenuParams. Response: ContextMenuItem[] */
3695
3801
  GET_CONTEXT_MENU_ITEMS: "getContextMenuItems"
3696
3802
  };
3697
- class It {
3803
+ class kt {
3698
3804
  /**
3699
3805
  * Plugin dependencies - declare other plugins this one requires.
3700
3806
  *
@@ -3711,8 +3817,11 @@ class It {
3711
3817
  * ```
3712
3818
  */
3713
3819
  static dependencies;
3714
- /** Plugin version - override in subclass if needed */
3715
- version = "1.0.0";
3820
+ /**
3821
+ * Plugin version - defaults to grid version for built-in plugins.
3822
+ * Third-party plugins can override with their own semver.
3823
+ */
3824
+ version = "0.5.0";
3716
3825
  /** CSS styles to inject into the grid's shadow DOM */
3717
3826
  styles;
3718
3827
  /** Custom cell renderers keyed by type name */
@@ -3799,12 +3908,28 @@ class It {
3799
3908
  emit(e, o) {
3800
3909
  this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: o, bubbles: !0 }));
3801
3910
  }
3911
+ /**
3912
+ * Emit a cancelable custom event from the grid.
3913
+ * @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
3914
+ */
3915
+ emitCancelable(e, o) {
3916
+ const i = new CustomEvent(e, { detail: o, bubbles: !0, cancelable: !0 });
3917
+ return this.grid?.dispatchEvent?.(i), i.defaultPrevented;
3918
+ }
3802
3919
  /**
3803
3920
  * Request a re-render of the grid.
3804
3921
  */
3805
3922
  requestRender() {
3806
3923
  this.grid?.requestRender?.();
3807
3924
  }
3925
+ /**
3926
+ * Request a re-render and restore focus styling afterward.
3927
+ * Use this when a plugin action (like expand/collapse) triggers a render
3928
+ * but needs to maintain keyboard navigation focus.
3929
+ */
3930
+ requestRenderWithFocus() {
3931
+ this.grid?.requestRenderWithFocus?.();
3932
+ }
3808
3933
  /**
3809
3934
  * Request a lightweight style update without rebuilding DOM.
3810
3935
  * Use this instead of requestRender() when only CSS classes need updating.
@@ -3839,10 +3964,34 @@ class It {
3839
3964
  return this.grid?._visibleColumns ?? [];
3840
3965
  }
3841
3966
  /**
3842
- * Get the shadow root of the grid.
3967
+ * Get the grid as an HTMLElement for direct DOM operations.
3968
+ * Use sparingly - prefer the typed GridElementRef API when possible.
3969
+ *
3970
+ * @example
3971
+ * ```ts
3972
+ * const width = this.gridElement.clientWidth;
3973
+ * this.gridElement.classList.add('my-plugin-active');
3974
+ * ```
3975
+ */
3976
+ get gridElement() {
3977
+ return this.grid;
3978
+ }
3979
+ /**
3980
+ * Get the render root of the grid for DOM queries.
3981
+ * @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
3982
+ *
3983
+ * With Shadow DOM removed, the grid element itself is the render root.
3984
+ * All new code should use `this.gridElement` for DOM queries.
3985
+ *
3986
+ * @example
3987
+ * // OLD (deprecated)
3988
+ * const rows = this.shadowRoot?.querySelector('.rows');
3989
+ *
3990
+ * // NEW (preferred)
3991
+ * const rows = this.gridElement.querySelector('.rows');
3843
3992
  */
3844
3993
  get shadowRoot() {
3845
- return this.grid?.shadowRoot ?? null;
3994
+ return this.gridElement;
3846
3995
  }
3847
3996
  /**
3848
3997
  * Get the disconnect signal for event listener cleanup.
@@ -3870,8 +4019,53 @@ class It {
3870
4019
  */
3871
4020
  get gridIcons() {
3872
4021
  const e = this.grid?.gridConfig?.icons ?? {};
3873
- return { ...L, ...e };
4022
+ return { ...H, ...e };
4023
+ }
4024
+ // #region Animation Helpers
4025
+ /**
4026
+ * Check if animations are enabled at the grid level.
4027
+ * Respects gridConfig.animation.mode and the CSS variable set by the grid.
4028
+ *
4029
+ * Plugins should use this to skip animations when:
4030
+ * - Animation mode is 'off' or `false`
4031
+ * - User prefers reduced motion and mode is 'reduced-motion' (default)
4032
+ *
4033
+ * @example
4034
+ * ```ts
4035
+ * private get animationStyle(): 'slide' | 'fade' | false {
4036
+ * if (!this.isAnimationEnabled) return false;
4037
+ * return this.config.animation ?? 'slide';
4038
+ * }
4039
+ * ```
4040
+ */
4041
+ get isAnimationEnabled() {
4042
+ const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
4043
+ if (e === !1 || e === "off") return !1;
4044
+ if (e === !0 || e === "on") return !0;
4045
+ const o = this.gridElement;
4046
+ return o ? getComputedStyle(o).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
4047
+ }
4048
+ /**
4049
+ * Get the animation duration in milliseconds from CSS variable.
4050
+ * Falls back to 200ms if not set.
4051
+ *
4052
+ * Plugins can use this for their animation timing to stay consistent
4053
+ * with the grid-level animation.duration setting.
4054
+ *
4055
+ * @example
4056
+ * ```ts
4057
+ * element.animate(keyframes, { duration: this.animationDuration });
4058
+ * ```
4059
+ */
4060
+ get animationDuration() {
4061
+ const e = this.gridElement;
4062
+ if (e) {
4063
+ const o = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), i = parseInt(o, 10);
4064
+ if (!isNaN(i)) return i;
4065
+ }
4066
+ return 200;
3874
4067
  }
4068
+ // #endregion
3875
4069
  /**
3876
4070
  * Resolve an icon value to string or HTMLElement.
3877
4071
  * Checks plugin config first, then grid-level icons, then defaults.
@@ -3961,7 +4155,7 @@ const E = {
3961
4155
  // TreePlugin
3962
4156
  STICKY: "data-sticky"
3963
4157
  // PinnedColumnsPlugin
3964
- }, Bt = {
4158
+ }, It = {
3965
4159
  ROOT: `.${E.ROOT}`,
3966
4160
  HEADER: `.${E.HEADER}`,
3967
4161
  HEADER_ROW: `.${E.HEADER_ROW}`,
@@ -4000,7 +4194,7 @@ const E = {
4000
4194
  // Borders
4001
4195
  BORDER_RADIUS: "--tbw-border-radius",
4002
4196
  FOCUS_OUTLINE: "--tbw-focus-outline"
4003
- }, Wt = {
4197
+ }, Bt = {
4004
4198
  CELL_COMMIT: "cell-commit",
4005
4199
  ROW_COMMIT: "row-commit",
4006
4200
  CHANGED_ROWS_RESET: "changed-rows-reset",
@@ -4011,7 +4205,7 @@ const E = {
4011
4205
  ACTIVATE_CELL: "activate-cell",
4012
4206
  GROUP_TOGGLE: "group-toggle",
4013
4207
  COLUMN_STATE_CHANGE: "column-state-change"
4014
- }, Ut = {
4208
+ }, Wt = {
4015
4209
  // Selection plugin
4016
4210
  SELECTION_CHANGE: "selection-change",
4017
4211
  // Tree plugin
@@ -4053,25 +4247,25 @@ const E = {
4053
4247
  max: (t, e) => Math.max(...t.map((o) => Number(o[e]) || -1 / 0)),
4054
4248
  first: (t, e) => t[0]?.[e],
4055
4249
  last: (t, e) => t[t.length - 1]?.[e]
4056
- }, k = /* @__PURE__ */ new Map(), P = {
4250
+ }, I = /* @__PURE__ */ new Map(), L = {
4057
4251
  /**
4058
4252
  * Register a custom aggregator function.
4059
4253
  */
4060
4254
  register(t, e) {
4061
- k.set(t, e);
4255
+ I.set(t, e);
4062
4256
  },
4063
4257
  /**
4064
4258
  * Unregister a custom aggregator function.
4065
4259
  */
4066
4260
  unregister(t) {
4067
- k.delete(t);
4261
+ I.delete(t);
4068
4262
  },
4069
4263
  /**
4070
4264
  * Get an aggregator function by reference.
4071
4265
  */
4072
4266
  get(t) {
4073
4267
  if (t !== void 0)
4074
- return typeof t == "function" ? t : k.get(t) ?? Q[t];
4268
+ return typeof t == "function" ? t : I.get(t) ?? Q[t];
4075
4269
  },
4076
4270
  /**
4077
4271
  * Run an aggregator on a set of rows.
@@ -4084,15 +4278,15 @@ const E = {
4084
4278
  * Check if an aggregator exists.
4085
4279
  */
4086
4280
  has(t) {
4087
- return k.has(t) || t in Q;
4281
+ return I.has(t) || t in Q;
4088
4282
  },
4089
4283
  /**
4090
4284
  * List all available aggregator names.
4091
4285
  */
4092
4286
  list() {
4093
- return [...Object.keys(Q), ...k.keys()];
4287
+ return [...Object.keys(Q), ...I.keys()];
4094
4288
  }
4095
- }, me = {
4289
+ }, be = {
4096
4290
  sum: (t) => t.reduce((e, o) => e + o, 0),
4097
4291
  avg: (t) => t.length ? t.reduce((e, o) => e + o, 0) / t.length : 0,
4098
4292
  count: (t) => t.length,
@@ -4101,43 +4295,43 @@ const E = {
4101
4295
  first: (t) => t[0] ?? 0,
4102
4296
  last: (t) => t[t.length - 1] ?? 0
4103
4297
  };
4104
- function Nt(t) {
4105
- return me[t] ?? me.sum;
4298
+ function zt(t) {
4299
+ return be[t] ?? be.sum;
4106
4300
  }
4107
4301
  function $t(t, e) {
4108
- return Nt(t)(e);
4302
+ return zt(t)(e);
4109
4303
  }
4110
- const Gt = P.register.bind(P), Vt = P.unregister.bind(P), Ft = P.get.bind(P), Xt = P.run.bind(P), Yt = P.list.bind(P);
4304
+ const Ut = L.register.bind(L), Ft = L.unregister.bind(L), Vt = L.get.bind(L), Gt = L.run.bind(L), Xt = L.list.bind(L);
4111
4305
  export {
4112
- It as BaseGridPlugin,
4113
- Me as DEFAULT_ANIMATION_CONFIG,
4114
- L as DEFAULT_GRID_ICONS,
4115
- Wt as DGEvents,
4116
- D as DataGridElement,
4306
+ kt as BaseGridPlugin,
4307
+ De as DEFAULT_ANIMATION_CONFIG,
4308
+ H as DEFAULT_GRID_ICONS,
4309
+ Bt as DGEvents,
4310
+ x as DataGridElement,
4117
4311
  W as FitModeEnum,
4118
4312
  qt as GridCSSVars,
4119
4313
  E as GridClasses,
4120
4314
  V as GridDataAttrs,
4121
- D as GridElement,
4122
- Bt as GridSelectors,
4123
- kt as PLUGIN_QUERIES,
4124
- Ut as PluginEvents,
4125
- zt as PluginManager,
4126
- R as RenderPhase,
4127
- q as a,
4128
- P as aggregatorRegistry,
4129
- tt as builtInSort,
4315
+ x as GridElement,
4316
+ It as GridSelectors,
4317
+ Nt as PLUGIN_QUERIES,
4318
+ Wt as PluginEvents,
4319
+ Mt as PluginManager,
4320
+ S as RenderPhase,
4321
+ k as a,
4322
+ L as aggregatorRegistry,
4323
+ et as builtInSort,
4130
4324
  ee as c,
4131
- et as defaultComparator,
4132
- ve as e,
4325
+ Qe as defaultComparator,
4326
+ we as e,
4133
4327
  ye as g,
4134
- Ft as getAggregator,
4135
- Nt as getValueAggregator,
4136
- Yt as listAggregators,
4137
- Gt as registerAggregator,
4138
- Xt as runAggregator,
4328
+ Vt as getAggregator,
4329
+ zt as getValueAggregator,
4330
+ Xt as listAggregators,
4331
+ Ut as registerAggregator,
4332
+ Gt as runAggregator,
4139
4333
  $t as runValueAggregator,
4140
- F as s,
4141
- Vt as unregisterAggregator
4334
+ G as s,
4335
+ Ft as unregisterAggregator
4142
4336
  };
4143
4337
  //# sourceMappingURL=index.js.map