@toolbox-web/grid 0.2.6 → 0.2.7

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 (52) hide show
  1. package/all.d.ts +434 -61
  2. package/all.js +844 -541
  3. package/all.js.map +1 -1
  4. package/index-DG2CZ_Zo.js +3229 -0
  5. package/index-DG2CZ_Zo.js.map +1 -0
  6. package/index.d.ts +210 -6
  7. package/index.js +25 -3194
  8. package/index.js.map +1 -1
  9. package/lib/plugins/clipboard/index.js.map +1 -1
  10. package/lib/plugins/column-virtualization/index.js.map +1 -1
  11. package/lib/plugins/context-menu/index.js.map +1 -1
  12. package/lib/plugins/export/index.js.map +1 -1
  13. package/lib/plugins/filtering/index.js +183 -148
  14. package/lib/plugins/filtering/index.js.map +1 -1
  15. package/lib/plugins/grouping-columns/index.js.map +1 -1
  16. package/lib/plugins/grouping-rows/index.js +116 -82
  17. package/lib/plugins/grouping-rows/index.js.map +1 -1
  18. package/lib/plugins/master-detail/index.js +139 -81
  19. package/lib/plugins/master-detail/index.js.map +1 -1
  20. package/lib/plugins/multi-sort/index.js +17 -17
  21. package/lib/plugins/multi-sort/index.js.map +1 -1
  22. package/lib/plugins/pinned-columns/index.js.map +1 -1
  23. package/lib/plugins/pinned-rows/index.js.map +1 -1
  24. package/lib/plugins/pivot/index.js +369 -337
  25. package/lib/plugins/pivot/index.js.map +1 -1
  26. package/lib/plugins/reorder/index.js +264 -91
  27. package/lib/plugins/reorder/index.js.map +1 -1
  28. package/lib/plugins/selection/index.js.map +1 -1
  29. package/lib/plugins/server-side/index.js.map +1 -1
  30. package/lib/plugins/tree/index.js +180 -169
  31. package/lib/plugins/tree/index.js.map +1 -1
  32. package/lib/plugins/undo-redo/index.js.map +1 -1
  33. package/lib/plugins/visibility/index.js.map +1 -1
  34. package/package.json +1 -1
  35. package/umd/grid.all.umd.js +21 -21
  36. package/umd/grid.all.umd.js.map +1 -1
  37. package/umd/grid.umd.js +12 -12
  38. package/umd/grid.umd.js.map +1 -1
  39. package/umd/plugins/filtering.umd.js +1 -1
  40. package/umd/plugins/filtering.umd.js.map +1 -1
  41. package/umd/plugins/grouping-rows.umd.js +1 -1
  42. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  43. package/umd/plugins/master-detail.umd.js +1 -1
  44. package/umd/plugins/master-detail.umd.js.map +1 -1
  45. package/umd/plugins/multi-sort.umd.js +1 -1
  46. package/umd/plugins/multi-sort.umd.js.map +1 -1
  47. package/umd/plugins/pivot.umd.js +1 -1
  48. package/umd/plugins/pivot.umd.js.map +1 -1
  49. package/umd/plugins/reorder.umd.js +1 -1
  50. package/umd/plugins/reorder.umd.js.map +1 -1
  51. package/umd/plugins/tree.umd.js +1 -1
  52. package/umd/plugins/tree.umd.js.map +1 -1
@@ -0,0 +1,3229 @@
1
+ const pe = ':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-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}:host .data-grid-row:has(.editing){background:var(--tbw-editing-bg)}: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}: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%;max-width:100%;flex:1 1 auto;min-width:0;border:var(--tbw-editing-border);padding:var(--tbw-padding-editing-input);font-size:var(--tbw-font-size-editor)}:host .data-grid-row:nth-child(2n){background:var(--tbw-color-row-alt)}:host .data-grid-row:hover{background:var(--tbw-color-row-hover)}:host .sortable{cursor:pointer;user-select:none}:host .resize-handle{position:absolute;top:0;right:calc(var(--tbw-resize-handle-width) / -2);width:var(--tbw-resize-handle-width);height:100%;cursor:e-resize;user-select:none;touch-action:none;z-index:20;background:var(--tbw-resize-handle-color);transition:background .12s ease;border-radius:var(--tbw-resize-handle-border-radius)}:host .resize-handle:hover{background:var(--tbw-resize-handle-color-hover)}:host .cell-focus,:host .row-focus{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}:host .group-row{display:grid;grid-template-columns:var(--tbw-column-template);background:var(--tbw-color-row-alt);font-weight:500;border-bottom:var(--tbw-row-divider);min-height:var(--tbw-row-height)}:host .group-row .cell{display:flex;align-items:center;padding:var(--tbw-cell-padding, 2px 8px)}:host .group-row .group-toggle{background:none;border:0;cursor:pointer;padding:0 4px 0 0;font:inherit}:host .group-row .group-count{margin-left:4px;opacity:.7}:host .sticky-left,:host .sticky-right{position:sticky;z-index:25}:host .header-row>.cell.sticky-left,:host .header-row>.cell.sticky-right{background:var(--tbw-color-header-bg);z-index:35}:host .data-grid-row>.cell.sticky-left,:host .data-grid-row>.cell.sticky-right{background:var(--tbw-color-panel-bg)}:host .sticky-left{box-shadow:1px 0 0 var(--tbw-color-border)}:host .sticky-right{box-shadow:-1px 0 0 var(--tbw-color-border)}.grid-container{position:relative;width:100%;height:100%}.grid-placeholder{padding:2rem;text-align:center;color:var(--tbw-color-fg);opacity:.6}:host{--tbw-shell-header-height: 44px;--tbw-shell-header-bg: var(--tbw-color-panel-bg);--tbw-shell-header-border: var(--tbw-color-border);--tbw-shell-title-font-size: 14px;--tbw-shell-title-font-weight: 600;--tbw-tool-panel-width: 280px;--tbw-tool-panel-bg: var(--tbw-color-panel-bg);--tbw-tool-panel-border: var(--tbw-color-border);--tbw-tool-panel-header-height: 40px;--tbw-tool-panel-transition: var(--tbw-animation-duration) var(--tbw-animation-easing);--tbw-toolbar-button-size: 32px;--tbw-toolbar-button-gap: 4px}:host .tbw-grid-root.has-shell{display:flex;flex-direction:column;height:100%}:host .tbw-shell-header{display:flex;align-items:center;gap:8px;min-height:var(--tbw-shell-header-height);padding:0 8px;background:var(--tbw-shell-header-bg);border-bottom:1px solid var(--tbw-shell-header-border);flex-shrink:0}:host .tbw-shell-title{font-size:var(--tbw-shell-title-font-size);font-weight:var(--tbw-shell-title-font-weight);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host .tbw-shell-content{flex:1;display:flex;align-items:center;gap:12px;min-width:0;overflow:hidden}:host .tbw-shell-toolbar{display:flex;align-items:center;gap:var(--tbw-toolbar-button-gap);flex-shrink:0}:host .tbw-toolbar-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--tbw-toolbar-button-size);height:var(--tbw-toolbar-button-size);padding:0;border:1px solid transparent;border-radius:var(--tbw-border-radius);background:transparent;color:var(--tbw-color-fg);cursor:pointer;font-size:16px;transition:background var(--tbw-transition-duration) var(--tbw-transition-ease),border-color var(--tbw-transition-duration) var(--tbw-transition-ease)}:host .tbw-toolbar-btn:hover{background:var(--tbw-color-row-hover)}:host .tbw-toolbar-btn:focus-visible{outline:var(--tbw-focus-outline);outline-offset:var(--tbw-focus-outline-offset)}:host .tbw-toolbar-btn.active{background:var(--tbw-focus-background);border-color:var(--tbw-color-accent)}:host .tbw-toolbar-btn:disabled{opacity:.5;cursor:not-allowed}:host .tbw-toolbar-separator{width:1px;height:20px;background:var(--tbw-color-border);margin:0 4px}:host .tbw-shell-body{position:relative;display:flex;flex:1;min-height:0;overflow:visible}:host .tbw-grid-content{flex:1;min-width:0;min-height:0;display:flex;flex-direction:row;overflow:hidden}:host .tbw-scroll-area{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow-x:auto;overflow-y:hidden}: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}:host .tbw-quick-filter-input{flex:1;max-width:300px;height:28px;padding:0 8px;border:1px solid var(--tbw-color-border);border-radius:var(--tbw-border-radius);background:var(--tbw-color-bg);color:var(--tbw-color-fg);font-size:13px}:host .tbw-quick-filter-input:focus{outline:none;border-color:var(--tbw-color-accent)}:host .tbw-selection-summary{font-size:13px;color:var(--tbw-color-fg-muted);white-space:nowrap}@media(prefers-reduced-motion:reduce){:host([data-animation-mode="reduced-motion"]){--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}}:host([data-animation-mode="off"]){--tbw-animation-enabled: 0;--tbw-animation-duration: 0ms}:host .tbw-expanding{animation:tbw-expand var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}:host .tbw-collapsing{animation:tbw-collapse var(--tbw-animation-duration) var(--tbw-animation-easing) forwards;overflow:hidden}@keyframes tbw-expand{0%{opacity:0;max-height:0;transform:translateY(-8px)}to{opacity:1;max-height:500px;transform:translateY(0)}}@keyframes tbw-collapse{0%{opacity:1;max-height:500px;transform:translateY(0)}to{opacity:0;max-height:0;transform:translateY(-8px)}}:host .tbw-fade-in{animation:tbw-fade-in var(--tbw-animation-duration) var(--tbw-animation-easing) forwards}:host .tbw-fade-out{animation:tbw-fade-out var(--tbw-animation-duration) var(--tbw-animation-easing) forwards}@keyframes tbw-fade-in{0%{opacity:0}to{opacity:1}}@keyframes tbw-fade-out{0%{opacity:1}to{opacity:0}}:host .tbw-flip-animating{will-change:transform;z-index:1}:host .tbw-toggle-icon{display:inline-flex;align-items:center;justify-content:center;transition:transform var(--tbw-animation-duration) var(--tbw-animation-easing)}:host .tbw-toggle-icon.tbw-expanded{transform:rotate(90deg)}';
2
+ function be(t) {
3
+ const e = /* @__PURE__ */ new Map();
4
+ return t._sortState && e.set(t._sortState.field, {
5
+ direction: t._sortState.direction === 1 ? "asc" : "desc",
6
+ priority: 0
7
+ }), e;
8
+ }
9
+ function de(t, e) {
10
+ const o = t._columns, n = be(t);
11
+ return {
12
+ columns: o.map((i, s) => {
13
+ const r = {
14
+ field: i.field,
15
+ order: s,
16
+ visible: !0
17
+ // If it's in _columns, it's visible (hidden columns are filtered out)
18
+ }, l = i;
19
+ l.__renderedWidth !== void 0 ? r.width = l.__renderedWidth : i.width !== void 0 && (r.width = typeof i.width == "string" ? parseFloat(i.width) : i.width);
20
+ const a = n.get(i.field);
21
+ a && (r.sort = a);
22
+ for (const d of e)
23
+ if (d.getColumnState) {
24
+ const f = d.getColumnState(i.field);
25
+ f && Object.assign(r, f);
26
+ }
27
+ return r;
28
+ })
29
+ };
30
+ }
31
+ function we(t, e, o, n) {
32
+ if (!e.columns || e.columns.length === 0) return;
33
+ const i = new Map(e.columns.map((l) => [l.field, l])), s = o.map((l) => {
34
+ const a = i.get(l.field);
35
+ if (!a) return l;
36
+ const d = { ...l };
37
+ return a.width !== void 0 && (d.width = a.width, d.__renderedWidth = a.width), a.visible !== void 0 && (d.hidden = !a.visible), d;
38
+ });
39
+ s.sort((l, a) => {
40
+ const d = i.get(l.field)?.order ?? 1 / 0, f = i.get(a.field)?.order ?? 1 / 0;
41
+ return d - f;
42
+ }), t._columns = s;
43
+ const r = e.columns.filter((l) => l.sort !== void 0).sort((l, a) => (l.sort?.priority ?? 0) - (a.sort?.priority ?? 0));
44
+ if (r.length > 0) {
45
+ const l = r[0];
46
+ l.sort && (t._sortState = {
47
+ field: l.field,
48
+ direction: l.sort.direction === "asc" ? 1 : -1
49
+ });
50
+ } else
51
+ t._sortState = null;
52
+ for (const l of n)
53
+ if (l.applyColumnState)
54
+ for (const a of e.columns)
55
+ l.applyColumnState(a.field, a);
56
+ }
57
+ function ge(t, e, o) {
58
+ let n = null;
59
+ return () => {
60
+ n !== null && clearTimeout(n), n = setTimeout(() => {
61
+ n = null;
62
+ const i = de(t, e());
63
+ o(i);
64
+ }, 100);
65
+ };
66
+ }
67
+ const $ = {
68
+ STRETCH: "stretch",
69
+ FIXED: "fixed"
70
+ }, me = {
71
+ mode: "reduced-motion",
72
+ duration: 200,
73
+ easing: "ease-out"
74
+ }, H = {
75
+ expand: "▶",
76
+ collapse: "▼",
77
+ sortAsc: "▲",
78
+ sortDesc: "▼",
79
+ sortNone: "⇅",
80
+ submenuArrow: "▶",
81
+ dragHandle: "⋮⋮",
82
+ toolPanel: "☰"
83
+ };
84
+ function ve(t) {
85
+ 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";
86
+ }
87
+ function ue(t, e) {
88
+ if (e && e.length) {
89
+ const s = {};
90
+ return e.forEach((r) => {
91
+ r.type && (s[r.field] = r.type);
92
+ }), { columns: e, typeMap: s };
93
+ }
94
+ const o = t[0] || {}, n = Object.keys(o).map((s) => {
95
+ const r = o[s], l = ve(r);
96
+ return { field: s, header: s.charAt(0).toUpperCase() + s.slice(1), type: l };
97
+ }), i = {};
98
+ return n.forEach((s) => {
99
+ i[s.field] = s.type || "string";
100
+ }), { columns: n, typeMap: i };
101
+ }
102
+ const _e = /{{\s*([^}]+)\s*}}/g, L = "__DG_EMPTY__", Ee = /^[\w$. '?+\-*/%:()!<>=,&|]+$/, Ce = /__(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/, ye = /* @__PURE__ */ new Set([
103
+ "script",
104
+ "iframe",
105
+ "object",
106
+ "embed",
107
+ "form",
108
+ "input",
109
+ "button",
110
+ "textarea",
111
+ "select",
112
+ "link",
113
+ "meta",
114
+ "base",
115
+ "style",
116
+ "template",
117
+ "slot",
118
+ "portal",
119
+ "frame",
120
+ "frameset",
121
+ "applet",
122
+ "noscript",
123
+ "noembed",
124
+ "plaintext",
125
+ "xmp",
126
+ "listing"
127
+ ]), Q = /^on\w+$/i, Se = /* @__PURE__ */ new Set(["href", "src", "action", "formaction", "data", "srcdoc", "xlink:href", "poster", "srcset"]), Re = /^\s*(javascript|vbscript|data|blob):/i;
128
+ function F(t) {
129
+ if (!t || typeof t != "string") return "";
130
+ if (t.indexOf("<") === -1) return t;
131
+ const e = document.createElement("template");
132
+ return e.innerHTML = t, xe(e.content), e.innerHTML;
133
+ }
134
+ function xe(t) {
135
+ const e = [], o = t.querySelectorAll("*");
136
+ for (const n of o) {
137
+ const i = n.tagName.toLowerCase();
138
+ if (ye.has(i)) {
139
+ e.push(n);
140
+ continue;
141
+ }
142
+ if ((i === "svg" || n.namespaceURI === "http://www.w3.org/2000/svg") && Array.from(n.attributes).some(
143
+ (l) => Q.test(l.name) || l.name === "href" || l.name === "xlink:href"
144
+ )) {
145
+ e.push(n);
146
+ continue;
147
+ }
148
+ const s = [];
149
+ for (const r of n.attributes) {
150
+ const l = r.name.toLowerCase();
151
+ if (Q.test(l)) {
152
+ s.push(r.name);
153
+ continue;
154
+ }
155
+ if (Se.has(l) && Re.test(r.value)) {
156
+ s.push(r.name);
157
+ continue;
158
+ }
159
+ if (l === "style" && /expression\s*\(|javascript:|behavior\s*:/i.test(r.value)) {
160
+ s.push(r.name);
161
+ continue;
162
+ }
163
+ }
164
+ s.forEach((r) => n.removeAttribute(r));
165
+ }
166
+ e.forEach((n) => n.remove());
167
+ }
168
+ function he(t, e) {
169
+ if (!t || t.indexOf("{{") === -1) return t;
170
+ const o = [], n = t.replace(_e, (l, a) => {
171
+ const d = Ae(a, e);
172
+ return o.push({ expr: a.trim(), result: d }), d;
173
+ }), i = Te(n), s = o.length && o.every((l) => l.result === "" || l.result === L);
174
+ return /Reflect\.|\bProxy\b|ownKeys\(/.test(t) || s ? "" : i;
175
+ }
176
+ function Ae(t, e) {
177
+ if (t = (t || "").trim(), !t || /\b(Reflect|Proxy|ownKeys)\b/.test(t)) return L;
178
+ if (t === "value") return e.value == null ? L : String(e.value);
179
+ if (t.startsWith("row.") && !/[()?]/.test(t) && !t.includes(":")) {
180
+ const n = t.slice(4), i = e.row ? e.row[n] : void 0;
181
+ return i == null ? L : String(i);
182
+ }
183
+ if (t.length > 80 || !Ee.test(t) || Ce.test(t)) return L;
184
+ const o = t.match(/\./g);
185
+ if (o && o.length > 1) return L;
186
+ try {
187
+ const i = new Function("value", "row", `return (${t});`)(e.value, e.row), s = i == null ? "" : String(i);
188
+ return /Reflect|Proxy|ownKeys/.test(s) ? L : s || L;
189
+ } catch {
190
+ return L;
191
+ }
192
+ }
193
+ function Te(t) {
194
+ return t && t.replace(new RegExp(L, "g"), "").replace(/Reflect\.[^<>{}\s]+/g, "").replace(/\bProxy\b/g, "").replace(/ownKeys\([^)]*\)/g, "");
195
+ }
196
+ function Le(t) {
197
+ if (/Reflect|Proxy|ownKeys/.test(t.textContent || "")) {
198
+ if (Array.from(t.childNodes).forEach((e) => {
199
+ e.nodeType === Node.TEXT_NODE && /Reflect|Proxy|ownKeys/.test(e.textContent || "") && (e.textContent = "");
200
+ }), /Reflect|Proxy|ownKeys/.test(t.textContent || "")) {
201
+ if (/Reflect|Proxy|ownKeys/.test(t.textContent || ""))
202
+ for (; t.firstChild; ) t.removeChild(t.firstChild);
203
+ t.textContent = (t.textContent || "").replace(/Reflect|Proxy|ownKeys/g, "");
204
+ }
205
+ (t.textContent || "").trim().length === 0 && (t.textContent = "");
206
+ }
207
+ }
208
+ function ee(t) {
209
+ const e = /Reflect\.|\bProxy\b|ownKeys\(/.test(t), o = (n) => e ? "" : he(t, n);
210
+ return o.__blocked = e, o;
211
+ }
212
+ function Pe(t) {
213
+ return Array.from(t.querySelectorAll("tbw-grid-column")).map((o) => {
214
+ const n = o.getAttribute("field") || "";
215
+ if (!n) return null;
216
+ const i = o.getAttribute("type") || void 0, r = i && (/* @__PURE__ */ new Set(["number", "string", "date", "boolean", "select", "typeahead"])).has(i) ? i : void 0, l = o.getAttribute("header") || void 0, a = o.hasAttribute("sortable"), d = o.hasAttribute("editable"), f = { field: n, type: r, header: l, sortable: a, editable: d };
217
+ o.hasAttribute("resizable") && (f.resizable = !0), o.hasAttribute("sizable") && (f.resizable = !0);
218
+ const h = o.getAttribute("options");
219
+ h && (f.options = h.split(",").map((b) => {
220
+ const [w, v] = b.includes(":") ? b.split(":") : [b.trim(), b.trim()];
221
+ return { value: w.trim(), label: v?.trim() || w.trim() };
222
+ }));
223
+ const p = o.querySelector("tbw-grid-column-view"), c = o.querySelector("tbw-grid-column-editor"), u = o.querySelector("tbw-grid-column-header");
224
+ return p && (f.__viewTemplate = p), c && (f.__editorTemplate = c), u && (f.__headerTemplate = u), f;
225
+ }).filter((o) => !!o);
226
+ }
227
+ function He(t, e) {
228
+ if ((!t || !t.length) && (!e || !e.length)) return [];
229
+ if (!t || !t.length) return e || [];
230
+ if (!e || !e.length) return t;
231
+ const o = {};
232
+ e.forEach((i) => o[i.field] = i);
233
+ const n = t.map((i) => {
234
+ const s = o[i.field];
235
+ if (!s) return i;
236
+ const r = { ...i };
237
+ return s.header && !r.header && (r.header = s.header), s.type && !r.type && (r.type = s.type), r.sortable = i.sortable || s.sortable, (i.resizable === !0 || s.resizable === !0) && (r.resizable = !0), r.editable = i.editable || s.editable, s.__viewTemplate && (r.__viewTemplate = s.__viewTemplate), s.__editorTemplate && (r.__editorTemplate = s.__editorTemplate), s.__headerTemplate && (r.__headerTemplate = s.__headerTemplate), delete o[i.field], r;
238
+ });
239
+ return Object.keys(o).forEach((i) => n.push(o[i])), n;
240
+ }
241
+ function j(t, e) {
242
+ try {
243
+ t.part?.add?.(e);
244
+ } catch {
245
+ }
246
+ const o = t.getAttribute("part");
247
+ o ? o.split(/\s+/).includes(e) || t.setAttribute("part", o + " " + e) : t.setAttribute("part", e);
248
+ }
249
+ function ke(t) {
250
+ t.__lightDomColumnsCache || (t.__originalColumnNodes = Array.from(
251
+ t.querySelectorAll("tbw-grid-column")
252
+ ), t.__lightDomColumnsCache = t.__originalColumnNodes.length ? Pe(t) : []);
253
+ const e = t.__lightDomColumnsCache, o = He(t._columns, e);
254
+ o.forEach((i) => {
255
+ i.__viewTemplate && !i.__compiledView && (i.__compiledView = ee(i.__viewTemplate.innerHTML)), i.__editorTemplate && !i.__compiledEditor && (i.__compiledEditor = ee(i.__editorTemplate.innerHTML));
256
+ });
257
+ const { columns: n } = ue(t._rows, o);
258
+ t._columns = n;
259
+ }
260
+ function te(t) {
261
+ const e = t.effectiveConfig?.fitMode || t.fitMode || $.STRETCH;
262
+ if (e !== $.STRETCH && e !== $.FIXED || t.__didInitialAutoSize || !t.isConnected) return;
263
+ const o = t._headerRowEl?.children || [];
264
+ if (!o.length) return;
265
+ let n = !1;
266
+ t._visibleColumns.forEach((i, s) => {
267
+ if (i.width) return;
268
+ const r = o[s];
269
+ let l = r ? r.scrollWidth : 0;
270
+ for (const a of t._rowPool) {
271
+ const d = a.children[s];
272
+ if (d) {
273
+ const f = d.scrollWidth;
274
+ f > l && (l = f);
275
+ }
276
+ }
277
+ l > 0 && (i.width = l + 2, i.__autoSized = !0, n = !0);
278
+ }), n && z(t), t.__didInitialAutoSize = !0;
279
+ }
280
+ function z(t) {
281
+ (t.effectiveConfig?.fitMode || t.fitMode || $.STRETCH) === $.STRETCH ? t._gridTemplate = t._visibleColumns.map((o) => {
282
+ if (o.width) return `${o.width}px`;
283
+ const n = o.minWidth;
284
+ return n != null ? `minmax(${n}px, 1fr)` : "1fr";
285
+ }).join(" ").trim() : t._gridTemplate = t._visibleColumns.map((o) => o.width ? `${o.width}px` : "max-content").join(" "), t.style.setProperty("--tbw-column-template", t._gridTemplate);
286
+ }
287
+ function Oe(t) {
288
+ switch (t.type) {
289
+ case "number":
290
+ return (e) => {
291
+ const o = document.createElement("input");
292
+ return o.type = "number", o.value = e.value != null ? String(e.value) : "", o.addEventListener("blur", () => e.commit(o.value === "" ? null : Number(o.value))), o.addEventListener("keydown", (n) => {
293
+ n.key === "Enter" && e.commit(o.value === "" ? null : Number(o.value)), n.key === "Escape" && e.cancel();
294
+ }), o.focus(), o;
295
+ };
296
+ case "boolean":
297
+ return (e) => {
298
+ const o = document.createElement("input");
299
+ return o.type = "checkbox", o.checked = !!e.value, o.addEventListener("change", () => e.commit(o.checked)), o.focus(), o;
300
+ };
301
+ case "date":
302
+ return (e) => {
303
+ const o = document.createElement("input");
304
+ return o.type = "date", e.value instanceof Date && (o.valueAsDate = e.value), o.addEventListener("change", () => e.commit(o.valueAsDate)), o.addEventListener("keydown", (n) => {
305
+ n.key === "Escape" && e.cancel();
306
+ }), o.focus(), o;
307
+ };
308
+ case "select":
309
+ case "typeahead":
310
+ return (e) => {
311
+ const o = document.createElement("select");
312
+ e.column.multi && (o.multiple = !0), (typeof e.column.options == "function" ? e.column.options() : e.column.options || []).forEach((s) => {
313
+ const r = document.createElement("option");
314
+ r.value = String(s.value), r.textContent = s.label, (e.column.multi && Array.isArray(e.value) && e.value.includes(s.value) || !e.column.multi && e.value === s.value) && (r.selected = !0), o.appendChild(r);
315
+ });
316
+ const i = () => {
317
+ if (e.column.multi) {
318
+ const s = [];
319
+ Array.from(o.selectedOptions).forEach((r) => {
320
+ s.push(r.value);
321
+ }), e.commit(s);
322
+ } else
323
+ e.commit(o.value);
324
+ };
325
+ return o.addEventListener("change", i), o.addEventListener("blur", i), o.addEventListener("keydown", (s) => {
326
+ s.key === "Escape" && e.cancel();
327
+ }), o.focus(), o;
328
+ };
329
+ default:
330
+ return (e) => {
331
+ const o = document.createElement("input");
332
+ return o.type = "text", o.value = e.value != null ? String(e.value) : "", o.addEventListener("blur", () => e.commit(o.value)), o.addEventListener("keydown", (n) => {
333
+ n.key === "Enter" && e.commit(o.value), n.key === "Escape" && e.cancel();
334
+ }), o.focus(), o;
335
+ };
336
+ }
337
+ }
338
+ function Me(t, e) {
339
+ if (t._dispatchKeyDown?.(e))
340
+ return;
341
+ const o = t._rows.length - 1, n = t._visibleColumns.length - 1, i = t._activeEditRows !== void 0 && t._activeEditRows !== -1, r = t._visibleColumns[t._focusCol]?.type, l = e.composedPath ? e.composedPath() : [], a = l && l.length ? l[0] : e.target, d = (f) => {
342
+ if (!f) return !1;
343
+ const h = f.tagName;
344
+ return !!(h === "INPUT" || h === "SELECT" || h === "TEXTAREA" || f.isContentEditable);
345
+ };
346
+ if (!(d(a) && (e.key === "Home" || e.key === "End")) && !(d(a) && (e.key === "ArrowUp" || e.key === "ArrowDown") && a.tagName === "INPUT" && a.type === "number") && !(d(a) && (e.key === "ArrowLeft" || e.key === "ArrowRight")) && !(d(a) && (e.key === "Enter" || e.key === "Escape")) && !(i && (r === "select" || r === "typeahead") && (e.key === "ArrowDown" || e.key === "ArrowUp"))) {
347
+ switch (e.key) {
348
+ case "Tab": {
349
+ e.preventDefault(), !e.shiftKey ? t._focusCol < n ? 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 = n), M(t);
350
+ return;
351
+ }
352
+ case "ArrowDown":
353
+ i && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = Math.min(o, t._focusRow + 1), e.preventDefault();
354
+ break;
355
+ case "ArrowUp":
356
+ i && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = Math.max(0, t._focusRow - 1), e.preventDefault();
357
+ break;
358
+ case "ArrowRight":
359
+ t._focusCol = Math.min(n, t._focusCol + 1), e.preventDefault();
360
+ break;
361
+ case "ArrowLeft":
362
+ t._focusCol = Math.max(0, t._focusCol - 1), e.preventDefault();
363
+ break;
364
+ case "Home":
365
+ (e.ctrlKey || e.metaKey) && (i && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = 0), t._focusCol = 0, e.preventDefault(), M(t, { forceScrollLeft: !0 });
366
+ return;
367
+ case "End":
368
+ (e.ctrlKey || e.metaKey) && (i && typeof t.commitActiveRowEdit == "function" && t.commitActiveRowEdit(), t._focusRow = o), t._focusCol = n, e.preventDefault(), M(t, { forceScrollRight: !0 });
369
+ return;
370
+ case "PageDown":
371
+ t._focusRow = Math.min(o, t._focusRow + 20), e.preventDefault();
372
+ break;
373
+ case "PageUp":
374
+ t._focusRow = Math.max(0, t._focusRow - 20), e.preventDefault();
375
+ break;
376
+ case "Enter":
377
+ return typeof t.beginBulkEdit == "function" ? t.beginBulkEdit(t._focusRow) : t.dispatchEvent(
378
+ new CustomEvent("activate-cell", { detail: { row: t._focusRow, col: t._focusCol } })
379
+ ), M(t);
380
+ default:
381
+ return;
382
+ }
383
+ M(t);
384
+ }
385
+ }
386
+ function M(t, e) {
387
+ if (t._virtualization?.enabled) {
388
+ const { rowHeight: r, container: l, viewportEl: a } = t._virtualization, d = l, f = a?.clientHeight ?? d?.clientHeight ?? 0;
389
+ if (d && f > 0) {
390
+ const h = t._focusRow * r;
391
+ h < d.scrollTop ? d.scrollTop = h : h + r > d.scrollTop + f && (d.scrollTop = h - f + r);
392
+ }
393
+ }
394
+ t._activeEditRows !== void 0 && t._activeEditRows !== -1 || t.refreshVirtualWindow(!1), Array.from(t._bodyEl.querySelectorAll(".cell-focus")).forEach((r) => r.classList.remove("cell-focus")), Array.from(t._bodyEl.querySelectorAll('[aria-selected="true"]')).forEach((r) => {
395
+ r.setAttribute("aria-selected", "false");
396
+ });
397
+ const n = t._focusRow, i = t._virtualization.start ?? 0, s = t._virtualization.end ?? t._rows.length;
398
+ if (n >= i && n < s) {
399
+ const r = t._bodyEl.querySelectorAll(".data-grid-row")[n - i], l = r?.children[t._focusCol];
400
+ if (l) {
401
+ l.classList.add("cell-focus"), l.setAttribute("aria-selected", "true");
402
+ const a = t.shadowRoot?.querySelector(".tbw-scroll-area");
403
+ if (a && l)
404
+ if (e?.forceScrollLeft)
405
+ a.scrollLeft = 0;
406
+ else if (e?.forceScrollRight)
407
+ a.scrollLeft = a.scrollWidth - a.clientWidth;
408
+ else {
409
+ const d = t._getHorizontalScrollOffsets?.(r ?? void 0, l) ?? { left: 0, right: 0 };
410
+ if (!d.skipScroll) {
411
+ const f = l.getBoundingClientRect(), h = a.getBoundingClientRect(), p = f.left - h.left + a.scrollLeft, c = p + f.width, u = a.scrollLeft + d.left, b = a.scrollLeft + a.clientWidth - d.right;
412
+ p < u ? a.scrollLeft = p - d.left : c > b && (a.scrollLeft = c - a.clientWidth + d.right);
413
+ }
414
+ }
415
+ if (t._activeEditRows !== void 0 && t._activeEditRows !== -1 && l.classList.contains("editing")) {
416
+ const d = l.querySelector(
417
+ 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])'
418
+ );
419
+ if (d && document.activeElement !== d)
420
+ try {
421
+ d.focus();
422
+ } catch {
423
+ }
424
+ } else if (!l.contains(document.activeElement)) {
425
+ l.hasAttribute("tabindex") || l.setAttribute("tabindex", "-1");
426
+ try {
427
+ l.focus({ preventScroll: !0 });
428
+ } catch {
429
+ }
430
+ }
431
+ }
432
+ }
433
+ }
434
+ const ze = "__cellDisplayCache", De = "__cellCacheEpoch";
435
+ function K(t) {
436
+ t[ze] = void 0, t[De] = void 0, t.__hasSpecialColumns = void 0;
437
+ }
438
+ function Ne(t, e, o, n, i) {
439
+ const s = Math.max(0, o - e), r = t._bodyEl, l = t._visibleColumns, a = l.length;
440
+ let d = t.__cachedHeaderRowCount;
441
+ for (d === void 0 && (d = t.shadowRoot?.querySelector(".header-group-row") ? 2 : 1, t.__cachedHeaderRowCount = d); t._rowPool.length < s; ) {
442
+ const h = document.createElement("div");
443
+ h.className = "data-grid-row", h.setAttribute("role", "row"), h.addEventListener("click", (p) => oe(t, p, h, !1)), h.addEventListener("dblclick", (p) => oe(t, p, h, !0)), t._rowPool.push(h);
444
+ }
445
+ if (t._rowPool.length > s) {
446
+ for (let h = s; h < t._rowPool.length; h++) {
447
+ const p = t._rowPool[h];
448
+ p.parentNode === r && p.remove();
449
+ }
450
+ t._rowPool.length = s;
451
+ }
452
+ const f = i && t.__hasRenderRowPlugins !== !1;
453
+ for (let h = 0; h < s; h++) {
454
+ const p = e + h, c = t._rows[p], u = t._rowPool[h];
455
+ if (u.setAttribute("aria-rowindex", String(p + d + 1)), f && i(c, u, p)) {
456
+ u.__epoch = n, u.__rowDataRef = c, u.parentNode !== r && r.appendChild(u);
457
+ continue;
458
+ }
459
+ const b = u.__epoch, w = u.__rowDataRef, v = u.children.length, R = b === n && v === a, E = w !== c;
460
+ let g = !1;
461
+ if (R && E) {
462
+ for (let _ = 0; _ < a; _++)
463
+ if (l[_].externalView && !u.querySelector(`.cell[data-col="${_}"] [data-external-view]`)) {
464
+ g = !0;
465
+ break;
466
+ }
467
+ }
468
+ if (!R || g) {
469
+ const _ = u.querySelector(".cell.editing"), y = t._activeEditRows === p;
470
+ if (_ && !y)
471
+ u.__isCustomRow && (u.className = "data-grid-row", u.setAttribute("role", "row"), u.__isCustomRow = !1), N(t, u, c, p), u.__epoch = n, u.__rowDataRef = c;
472
+ else if (_ && y)
473
+ U(t, u, c, p), u.__rowDataRef = c;
474
+ else if (u.__isCustomRow && (u.className = "data-grid-row", u.setAttribute("role", "row"), u.__isCustomRow = !1), N(t, u, c, p), u.__epoch = n, u.__rowDataRef = c, y) {
475
+ const x = u.children;
476
+ for (let A = 0; A < x.length; A++) {
477
+ const P = t._visibleColumns[A];
478
+ P && P.editable && k(t, c, p, P, x[A]);
479
+ }
480
+ }
481
+ } else if (E) {
482
+ const _ = u.querySelector(".cell.editing"), y = t._activeEditRows === p;
483
+ if (_ && !y)
484
+ N(t, u, c, p), u.__epoch = n, u.__rowDataRef = c;
485
+ else if (U(t, u, c, p), u.__rowDataRef = c, y && !_) {
486
+ const x = u.children;
487
+ for (let A = 0; A < x.length; A++) {
488
+ const P = t._visibleColumns[A];
489
+ P && P.editable && k(t, c, p, P, x[A]);
490
+ }
491
+ }
492
+ } else {
493
+ const _ = u.querySelector(".cell.editing"), y = t._activeEditRows === p;
494
+ if (_ && !y)
495
+ N(t, u, c, p), u.__epoch = n, u.__rowDataRef = c;
496
+ else if (U(t, u, c, p), y && !_) {
497
+ const x = u.children;
498
+ for (let A = 0; A < x.length; A++) {
499
+ const P = t._visibleColumns[A];
500
+ P && P.editable && k(t, c, p, P, x[A]);
501
+ }
502
+ }
503
+ }
504
+ const m = t._changedRowIndices.has(p), C = u.classList.contains("changed");
505
+ m !== C && u.classList.toggle("changed", m), u.parentNode !== r && r.appendChild(u);
506
+ }
507
+ }
508
+ function U(t, e, o, n) {
509
+ const i = e.children, s = t._visibleColumns, r = s.length, l = i.length, a = r < l ? r : l, d = t._focusRow, f = t._focusCol;
510
+ let h = t.__hasSpecialColumns;
511
+ if (h === void 0) {
512
+ h = !1;
513
+ for (let c = 0; c < r; c++) {
514
+ const u = s[c];
515
+ if (u.__viewTemplate || u.__compiledView || u.viewRenderer || u.externalView || u.format || u.type === "date" || u.type === "boolean") {
516
+ h = !0;
517
+ break;
518
+ }
519
+ }
520
+ t.__hasSpecialColumns = h;
521
+ }
522
+ const p = String(n);
523
+ if (!h) {
524
+ for (let c = 0; c < a; c++) {
525
+ const u = i[c], b = o[s[c].field];
526
+ u.textContent = b == null ? "" : String(b), u.getAttribute("data-row") !== p && u.setAttribute("data-row", p);
527
+ const w = d === n && f === c, v = u.classList.contains("cell-focus");
528
+ w !== v && (u.classList.toggle("cell-focus", w), u.setAttribute("aria-selected", String(w)));
529
+ }
530
+ return;
531
+ }
532
+ for (let c = 0; c < a; c++)
533
+ if (s[c].externalView && !i[c].querySelector("[data-external-view]")) {
534
+ N(t, e, o, n);
535
+ return;
536
+ }
537
+ for (let c = 0; c < a; c++) {
538
+ const u = s[c], b = i[c];
539
+ b.getAttribute("data-row") !== p && b.setAttribute("data-row", p);
540
+ const w = d === n && f === c, v = b.classList.contains("cell-focus");
541
+ if (w !== v && (b.classList.toggle("cell-focus", w), b.setAttribute("aria-selected", String(w))), b.classList.contains("editing")) continue;
542
+ if (u.viewRenderer) {
543
+ const E = o[u.field], g = u.viewRenderer({ row: o, value: E, field: u.field, column: u });
544
+ typeof g == "string" ? b.innerHTML = F(g) : g ? (b.innerHTML = "", b.appendChild(g)) : b.textContent = E == null ? "" : String(E);
545
+ continue;
546
+ }
547
+ if (u.__viewTemplate || u.__compiledView || u.externalView)
548
+ continue;
549
+ const S = o[u.field];
550
+ let R;
551
+ if (u.format)
552
+ try {
553
+ const E = u.format(S, o);
554
+ R = E == null ? "" : String(E);
555
+ } catch {
556
+ R = S == null ? "" : String(S);
557
+ }
558
+ else if (u.type === "date") {
559
+ if (S == null || S === "")
560
+ R = "";
561
+ else if (S instanceof Date)
562
+ R = isNaN(S.getTime()) ? "" : S.toLocaleDateString();
563
+ else {
564
+ const E = new Date(S);
565
+ R = isNaN(E.getTime()) ? "" : E.toLocaleDateString();
566
+ }
567
+ b.textContent = R;
568
+ } else if (u.type === "boolean") {
569
+ const E = !!S;
570
+ b.innerHTML = `<span role="checkbox" aria-checked="${E}" aria-label="${E}">${E ? "&#x1F5F9;" : "&#9744;"}</span>`;
571
+ } else
572
+ R = S == null ? "" : String(S), b.textContent = R;
573
+ }
574
+ }
575
+ function N(t, e, o, n) {
576
+ e.innerHTML = "";
577
+ const i = t._visibleColumns, s = i.length, r = t._focusRow, l = t._focusCol, a = t.effectiveConfig?.editOn || t.editOn, d = t, f = document.createDocumentFragment();
578
+ for (let h = 0; h < s; h++) {
579
+ const p = i[h], c = document.createElement("div");
580
+ c.className = "cell", j(c, "cell"), c.setAttribute("role", "gridcell"), c.setAttribute("aria-colindex", String(h + 1)), c.setAttribute("data-col", String(h)), c.setAttribute("data-row", String(n)), c.setAttribute("data-field", p.field), p.type, p.type && c.setAttribute("data-type", p.type);
581
+ let u = o[p.field];
582
+ const b = p.format;
583
+ if (b)
584
+ try {
585
+ u = b(u, o);
586
+ } catch {
587
+ }
588
+ const w = p.__compiledView, v = p.__viewTemplate, S = p.viewRenderer, R = p.externalView;
589
+ let E = !1;
590
+ if (S) {
591
+ const g = S({ row: o, value: u, field: p.field, column: p });
592
+ typeof g == "string" ? (c.innerHTML = F(g), E = !0) : g ? c.appendChild(g) : c.textContent = u == null ? "" : String(u);
593
+ } else if (R) {
594
+ const g = R, m = document.createElement("div");
595
+ m.setAttribute("data-external-view", ""), m.setAttribute("data-field", p.field), c.appendChild(m);
596
+ const C = { row: o, value: u, field: p.field, column: p };
597
+ if (g.mount)
598
+ try {
599
+ g.mount({ placeholder: m, context: C, spec: g });
600
+ } catch {
601
+ }
602
+ else
603
+ queueMicrotask(() => {
604
+ try {
605
+ d.dispatchEvent(
606
+ new CustomEvent("mount-external-view", {
607
+ bubbles: !0,
608
+ composed: !0,
609
+ detail: { placeholder: m, spec: g, context: C }
610
+ })
611
+ );
612
+ } catch {
613
+ }
614
+ });
615
+ m.setAttribute("data-mounted", "");
616
+ } else if (w) {
617
+ const g = w({ row: o, value: u, field: p.field, column: p }), m = w.__blocked;
618
+ c.innerHTML = m ? "" : F(g), E = !0, m && (c.textContent = "", c.setAttribute("data-blocked-template", ""));
619
+ } else if (v) {
620
+ const g = v.innerHTML;
621
+ /Reflect\.|\bProxy\b|ownKeys\(/.test(g) ? (c.textContent = "", c.setAttribute("data-blocked-template", "")) : (c.innerHTML = F(he(g, { row: o, value: u })), E = !0);
622
+ } else if (p.type === "date")
623
+ if (u == null || u === "")
624
+ c.textContent = "";
625
+ else {
626
+ let g = null;
627
+ if (u instanceof Date) g = u;
628
+ else if (typeof u == "number" || typeof u == "string") {
629
+ const m = new Date(u);
630
+ isNaN(m.getTime()) || (g = m);
631
+ }
632
+ c.textContent = g ? g.toLocaleDateString() : "";
633
+ }
634
+ else if (p.type === "boolean") {
635
+ const g = !!u;
636
+ c.innerHTML = `<span role="checkbox" aria-checked="${g}" aria-label="${g}">${g ? "&#x1F5F9;" : "&#9744;"}</span>`;
637
+ } else
638
+ c.textContent = u == null ? "" : String(u);
639
+ if (E) {
640
+ Le(c);
641
+ const g = c.textContent || "";
642
+ /Proxy|Reflect\.ownKeys/.test(g) && (c.textContent = g.replace(/Proxy|Reflect\.ownKeys/g, "").trim(), /Proxy|Reflect\.ownKeys/.test(c.textContent || "") && (c.textContent = ""));
643
+ }
644
+ c.hasAttribute("data-blocked-template") && (c.textContent || "").trim().length && (c.textContent = ""), p.editable ? (c.tabIndex = 0, c.addEventListener("mousedown", () => {
645
+ if (c.classList.contains("editing")) return;
646
+ const g = Number(c.getAttribute("data-row")), m = Number(c.getAttribute("data-col"));
647
+ isNaN(g) || isNaN(m) || (t._focusRow = g, t._focusCol = m, M(t));
648
+ }), a === "click" ? c.addEventListener("click", (g) => {
649
+ if (c.classList.contains("editing")) return;
650
+ g.stopPropagation();
651
+ const m = Number(c.getAttribute("data-row")), C = Number(c.getAttribute("data-col"));
652
+ if (isNaN(m) || isNaN(C)) return;
653
+ const _ = t._rows[m], y = t._visibleColumns[C];
654
+ !_ || !y || (t._focusRow = m, t._focusCol = C, k(t, _, m, y, c));
655
+ }) : c.addEventListener("dblclick", (g) => {
656
+ g.stopPropagation();
657
+ const m = Number(c.getAttribute("data-row"));
658
+ if (isNaN(m)) return;
659
+ const C = t._rows[m];
660
+ if (!C) return;
661
+ B(t, m, C);
662
+ const _ = t.findRenderedRowElement?.(m);
663
+ if (_) {
664
+ const y = _.children;
665
+ for (let x = 0; x < y.length; x++) {
666
+ const A = t._visibleColumns[x];
667
+ A && A.editable && k(t, C, m, A, y[x]);
668
+ }
669
+ }
670
+ }), c.addEventListener("keydown", (g) => {
671
+ const m = Number(c.getAttribute("data-row")), C = Number(c.getAttribute("data-col"));
672
+ if (isNaN(m) || isNaN(C)) return;
673
+ const _ = t._rows[m], y = t._visibleColumns[C];
674
+ if (!(!_ || !y)) {
675
+ if ((y.type === "select" || y.type === "typeahead") && !c.classList.contains("editing") && g.key === "Enter") {
676
+ g.preventDefault(), t._activeEditRows !== m && B(t, m, _), k(t, _, m, y, c), setTimeout(() => {
677
+ const x = c.querySelector("select");
678
+ try {
679
+ x?.showPicker?.();
680
+ } catch {
681
+ }
682
+ x?.focus();
683
+ }, 0);
684
+ return;
685
+ }
686
+ if (y.type === "boolean" && g.key === " " && !c.classList.contains("editing")) {
687
+ g.preventDefault(), t._activeEditRows !== m && B(t, m, _);
688
+ const x = !_[y.field];
689
+ J(t, m, y, x, _), c.innerHTML = `<span role="checkbox" aria-checked="${x}" aria-label="${x}">${x ? "&#x1F5F9;" : "&#9744;"}</span>`;
690
+ return;
691
+ }
692
+ if (g.key === "Enter" && !c.classList.contains("editing")) {
693
+ g.preventDefault(), g.stopPropagation(), t._focusRow = m, t._focusCol = C, typeof t.beginBulkEdit == "function" ? t.beginBulkEdit(m) : k(t, _, m, y, c);
694
+ return;
695
+ }
696
+ if (g.key === "F2" && !c.classList.contains("editing")) {
697
+ g.preventDefault(), k(t, _, m, y, c);
698
+ return;
699
+ }
700
+ }
701
+ })) : p.type === "boolean" && (c.hasAttribute("tabindex") || (c.tabIndex = 0)), r === n && l === h ? (c.classList.add("cell-focus"), c.setAttribute("aria-selected", "true")) : c.setAttribute("aria-selected", "false"), f.appendChild(c);
702
+ }
703
+ e.appendChild(f);
704
+ }
705
+ function oe(t, e, o, n) {
706
+ if (e.target?.closest(".resize-handle")) return;
707
+ const i = o.querySelector(".cell[data-row]");
708
+ if (!i) return;
709
+ const s = Number(i.getAttribute("data-row"));
710
+ if (isNaN(s)) return;
711
+ const r = t._rows[s];
712
+ if (!r || t._dispatchRowClick?.(e, s, r, o))
713
+ return;
714
+ const l = e.target?.closest(".cell[data-col]");
715
+ if (l) {
716
+ if (l.classList.contains("editing")) return;
717
+ const d = Number(l.getAttribute("data-col"));
718
+ if (!isNaN(d)) {
719
+ if (t._dispatchCellClick?.(e, s, d, l))
720
+ return;
721
+ t._focusRow = s, t._focusCol = d, M(t);
722
+ }
723
+ }
724
+ if (o.querySelector(".cell.editing")) {
725
+ const d = o.querySelectorAll(".cell.editing");
726
+ if (!n) return;
727
+ d.forEach((f) => f.classList.remove("editing"));
728
+ }
729
+ const a = t.effectiveConfig?.editOn || t.editOn || "doubleClick";
730
+ if (a === "click" || a === "doubleClick" && n) B(t, s, r);
731
+ else return;
732
+ Array.from(o.children).forEach((d, f) => {
733
+ const h = t._visibleColumns[f];
734
+ h && h.editable && k(t, r, s, h, d);
735
+ }), l && queueMicrotask(() => {
736
+ const d = o.querySelector(`.cell[data-col="${t._focusCol}"]`);
737
+ if (d?.classList.contains("editing")) {
738
+ const f = d.querySelector(
739
+ 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])'
740
+ );
741
+ try {
742
+ f?.focus();
743
+ } catch {
744
+ }
745
+ }
746
+ });
747
+ }
748
+ function Z(t) {
749
+ return !(t === "__proto__" || t === "constructor" || t === "prototype");
750
+ }
751
+ function B(t, e, o) {
752
+ t._activeEditRows !== e && (t._rowEditSnapshots.set(e, { ...o }), t._activeEditRows = e);
753
+ }
754
+ function D(t, e, o) {
755
+ if (t._activeEditRows !== e) return;
756
+ const n = t._rowEditSnapshots.get(e), i = t._rows[e], s = t.findRenderedRowElement?.(e);
757
+ if (!o && s && i && s.querySelectorAll(".cell.editing").forEach((l) => {
758
+ const a = Number(l.getAttribute("data-col"));
759
+ if (isNaN(a)) return;
760
+ const d = t._visibleColumns[a];
761
+ if (!d) return;
762
+ const f = l.querySelector("input,textarea,select");
763
+ if (f) {
764
+ let h;
765
+ f instanceof HTMLInputElement && f.type === "checkbox" ? h = f.checked : (h = f.value, d.type === "number" && h !== "" && (h = Number(h))), i[d.field] !== h && J(t, e, d, h, i);
766
+ }
767
+ }), o && n && i)
768
+ Object.keys(n).forEach((r) => i[r] = n[r]), t._changedRowIndices.delete(e), K(t);
769
+ else if (!o) {
770
+ const r = t._changedRowIndices.has(e);
771
+ t.dispatchEvent(
772
+ new CustomEvent("row-commit", {
773
+ detail: {
774
+ rowIndex: e,
775
+ row: i,
776
+ changed: r,
777
+ changedRows: t.changedRows,
778
+ changedRowIndices: t.changedRowIndices
779
+ }
780
+ })
781
+ );
782
+ }
783
+ t._rowEditSnapshots.delete(e), t._activeEditRows = -1, s && (N(t, s, t._rows[e], e), t._changedRowIndices.has(e) ? s.classList.add("changed") : s.classList.remove("changed")), queueMicrotask(() => {
784
+ try {
785
+ const r = t._focusRow, l = t._focusCol, a = t.findRenderedRowElement?.(r);
786
+ if (a) {
787
+ Array.from(t._bodyEl.querySelectorAll(".cell-focus")).forEach(
788
+ (f) => f.classList.remove("cell-focus")
789
+ );
790
+ const d = a.querySelector(`.cell[data-row="${r}"][data-col="${l}"]`);
791
+ d && (d.classList.add("cell-focus"), d.setAttribute("aria-selected", "true"), d.hasAttribute("tabindex") || d.setAttribute("tabindex", "-1"), d.focus({ preventScroll: !0 }));
792
+ }
793
+ } catch {
794
+ }
795
+ });
796
+ }
797
+ function J(t, e, o, n, i) {
798
+ const s = o.field;
799
+ if (!Z(s) || i[s] === n) return;
800
+ i[s] = n;
801
+ const l = !t._changedRowIndices.has(e);
802
+ t._changedRowIndices.add(e);
803
+ const a = t.findRenderedRowElement?.(e);
804
+ a && a.classList.add("changed"), t.dispatchEvent(
805
+ new CustomEvent("cell-commit", {
806
+ detail: {
807
+ row: i,
808
+ field: s,
809
+ value: n,
810
+ rowIndex: e,
811
+ changedRows: t.changedRows,
812
+ changedRowIndices: t.changedRowIndices,
813
+ firstTimeForRow: l
814
+ }
815
+ })
816
+ );
817
+ }
818
+ function k(t, e, o, n, i) {
819
+ if (!n.editable || (t._activeEditRows !== o && B(t, o, e), i.classList.contains("editing"))) return;
820
+ const s = Z(n.field) ? e[n.field] : void 0;
821
+ i.classList.add("editing");
822
+ let r = !1;
823
+ const l = (c) => {
824
+ r || t._activeEditRows === -1 || J(t, o, n, c, e);
825
+ }, a = () => {
826
+ r = !0, e[n.field] = Z(n.field) ? s : void 0;
827
+ const c = i.querySelector("input,textarea,select");
828
+ c && (typeof HTMLInputElement < "u" && c instanceof HTMLInputElement && c.type === "checkbox" ? c.checked = !!s : "value" in c && (c.value = s ?? ""));
829
+ }, d = document.createElement("div");
830
+ d.style.display = "contents", i.innerHTML = "", i.appendChild(d), d.addEventListener("keydown", (c) => {
831
+ c.key === "Enter" && (c.stopPropagation(), c.preventDefault(), r = !0, D(t, o, !1)), c.key === "Escape" && (c.stopPropagation(), c.preventDefault(), a(), D(t, o, !0));
832
+ });
833
+ const f = n.__editorTemplate, h = n.editor || (f ? "template" : Oe(n)), p = s;
834
+ if (h === "template" && f) {
835
+ const c = f.cloneNode(!0), u = n.__compiledEditor;
836
+ u ? c.innerHTML = u({ row: e, value: s, field: n.field, column: n }) : c.querySelectorAll("*").forEach((w) => {
837
+ w.childNodes.length === 1 && w.firstChild?.nodeType === Node.TEXT_NODE && (w.textContent = w.textContent?.replace(/{{\s*value\s*}}/g, s == null ? "" : String(s)).replace(/{{\s*row\.([a-zA-Z0-9_]+)\s*}}/g, (v, S) => {
838
+ const R = e[S];
839
+ return R == null ? "" : String(R);
840
+ }) || "");
841
+ });
842
+ const b = c.querySelector("input,textarea,select");
843
+ if (b) {
844
+ const w = typeof HTMLInputElement < "u";
845
+ w && b instanceof HTMLInputElement && b.type === "checkbox" ? b.checked = !!s : "value" in b && (b.value = s ?? ""), b.addEventListener("blur", () => {
846
+ const v = w && b instanceof HTMLInputElement && b.type === "checkbox" ? b.checked : b.value;
847
+ l(v);
848
+ }), b.addEventListener("keydown", (v) => {
849
+ if (v.key === "Enter") {
850
+ v.stopPropagation(), v.preventDefault(), r = !0;
851
+ const S = w && b instanceof HTMLInputElement && b.type === "checkbox" ? b.checked : b.value;
852
+ l(S), D(t, o, !1);
853
+ }
854
+ v.key === "Escape" && (v.stopPropagation(), v.preventDefault(), a(), D(t, o, !0));
855
+ }), w && b instanceof HTMLInputElement && b.type === "checkbox" && b.addEventListener("change", () => {
856
+ const v = b.checked;
857
+ l(v);
858
+ }), setTimeout(() => b.focus(), 0);
859
+ }
860
+ d.appendChild(c);
861
+ } else if (typeof h == "string") {
862
+ const c = document.createElement(h);
863
+ c.value = p, c.addEventListener("change", () => l(c.value)), d.appendChild(c);
864
+ } else if (typeof h == "function") {
865
+ const c = h({ row: e, value: p, field: n.field, column: n, commit: l, cancel: a });
866
+ typeof c == "string" ? d.innerHTML = c : d.appendChild(c);
867
+ } else if (h && typeof h == "object") {
868
+ const c = document.createElement("div");
869
+ c.setAttribute("data-external-editor", ""), c.setAttribute("data-field", n.field), d.appendChild(c);
870
+ const u = { row: e, value: p, field: n.field, column: n, commit: l, cancel: a };
871
+ if (h.mount)
872
+ try {
873
+ h.mount({ placeholder: c, context: u, spec: h });
874
+ } catch {
875
+ }
876
+ else
877
+ t.dispatchEvent(
878
+ new CustomEvent("mount-external-editor", { detail: { placeholder: c, spec: h, context: u } })
879
+ );
880
+ }
881
+ }
882
+ function qe(t, e) {
883
+ return t == null && e == null ? 0 : t == null ? -1 : e == null || t > e ? 1 : t < e ? -1 : 0;
884
+ }
885
+ function Be(t, e, o) {
886
+ const i = o.find((l) => l.field === e.field)?.sortComparator ?? qe, { field: s, direction: r } = e;
887
+ return [...t].sort((l, a) => i(l[s], a[s], l, a) * r);
888
+ }
889
+ function ne(t, e, o, n) {
890
+ t._rows = e, t.__rowRenderEpoch++, t._rowPool.forEach((i) => i.__epoch = -1), q(t), t.refreshVirtualWindow(!0), t.dispatchEvent(
891
+ new CustomEvent("sort-change", { detail: { field: o.field, direction: n } })
892
+ ), t.requestStateChange?.();
893
+ }
894
+ function ie(t, e) {
895
+ !t._sortState || t._sortState.field !== e.field ? (t._sortState || (t.__originalOrder = t._rows.slice()), se(t, e, 1)) : t._sortState.direction === 1 ? se(t, e, -1) : (t._sortState = null, t.__rowRenderEpoch++, t._rowPool.forEach((n) => n.__epoch = -1), t._rows = t.__originalOrder.slice(), q(t), t._headerRowEl?.querySelectorAll('[role="columnheader"].sortable')?.forEach((n) => {
896
+ n.getAttribute("aria-sort") ? (n.getAttribute("aria-sort") === "ascending" || n.getAttribute("aria-sort") === "descending") && (t._sortState || n.setAttribute("aria-sort", "none")) : n.setAttribute("aria-sort", "none");
897
+ }), t.refreshVirtualWindow(!0), t.dispatchEvent(
898
+ new CustomEvent("sort-change", { detail: { field: e.field, direction: 0 } })
899
+ ), t.requestStateChange?.());
900
+ }
901
+ function se(t, e, o) {
902
+ t._sortState = { field: e.field, direction: o };
903
+ const n = { field: e.field, direction: o }, i = t._columns, r = (t.effectiveConfig?.sortHandler ?? Be)(t._rows, n, i);
904
+ r && typeof r.then == "function" ? r.then((l) => {
905
+ ne(t, l, e, o);
906
+ }) : ne(t, r, e, o);
907
+ }
908
+ function Ie(t, e) {
909
+ typeof e == "string" ? t.textContent = e : e instanceof HTMLElement && (t.innerHTML = "", t.appendChild(e.cloneNode(!0)));
910
+ }
911
+ function q(t) {
912
+ t._headerRowEl = t.findHeaderRow();
913
+ const e = t._headerRowEl;
914
+ e.innerHTML = "", t._visibleColumns.forEach((o, n) => {
915
+ const i = document.createElement("div");
916
+ i.className = "cell", j(i, "header-cell"), i.setAttribute("role", "columnheader"), i.setAttribute("aria-colindex", String(n + 1)), i.setAttribute("data-field", o.field), i.setAttribute("data-col", String(n));
917
+ const s = o.__headerTemplate;
918
+ if (s) Array.from(s.childNodes).forEach((r) => i.appendChild(r.cloneNode(!0)));
919
+ else {
920
+ const r = o.header || o.field, l = document.createElement("span");
921
+ l.textContent = r, i.appendChild(l);
922
+ }
923
+ if (o.sortable) {
924
+ i.classList.add("sortable"), i.tabIndex = 0;
925
+ const r = document.createElement("span");
926
+ j(r, "sort-indicator");
927
+ const l = t._sortState?.field === o.field ? t._sortState.direction : 0, a = { ...H, ...t.icons }, d = l === 1 ? a.sortAsc : l === -1 ? a.sortDesc : a.sortNone;
928
+ Ie(r, d), i.appendChild(r), i.setAttribute("aria-sort", l === 0 ? "none" : l === 1 ? "ascending" : "descending"), i.addEventListener("click", (f) => {
929
+ t._resizeController?.isResizing || t._dispatchHeaderClick?.(f, n, i) || ie(t, o);
930
+ }), i.addEventListener("keydown", (f) => {
931
+ if (f.key === "Enter" || f.key === " ") {
932
+ if (f.preventDefault(), t._dispatchHeaderClick?.(f, n, i)) return;
933
+ ie(t, o);
934
+ }
935
+ });
936
+ }
937
+ if (o.resizable) {
938
+ i.style.position = "relative";
939
+ const r = document.createElement("div");
940
+ r.className = "resize-handle", r.setAttribute("aria-hidden", "true"), r.addEventListener("mousedown", (l) => {
941
+ l.stopPropagation(), l.preventDefault(), t._resizeController.start(l, n, i);
942
+ }), r.addEventListener("dblclick", (l) => {
943
+ l.stopPropagation(), l.preventDefault(), t._resizeController.resetColumn(n);
944
+ }), i.appendChild(r);
945
+ }
946
+ e.appendChild(i);
947
+ }), e.querySelectorAll(".cell.sortable").forEach((o) => {
948
+ o.getAttribute("aria-sort") || o.setAttribute("aria-sort", "none");
949
+ }), e.children.length > 0 ? (e.setAttribute("role", "row"), e.setAttribute("aria-rowindex", "1")) : (e.removeAttribute("role"), e.removeAttribute("aria-rowindex"));
950
+ }
951
+ function $e(t) {
952
+ let e = null, o = null, n = null, i = null;
953
+ const s = (a) => {
954
+ if (!e) return;
955
+ const d = a.clientX - e.startX, f = Math.max(40, e.startWidth + d), h = t._visibleColumns[e.colIndex];
956
+ h.width = f, h.__userResized = !0, h.__renderedWidth = f, o == null && (o = requestAnimationFrame(() => {
957
+ o = null, t.updateTemplate?.();
958
+ })), t.dispatchEvent(
959
+ new CustomEvent("column-resize", { detail: { field: h.field, width: f } })
960
+ );
961
+ };
962
+ let r = !1;
963
+ const l = () => {
964
+ const a = e !== null;
965
+ a && (r = !0, requestAnimationFrame(() => {
966
+ r = !1;
967
+ })), window.removeEventListener("mousemove", s), window.removeEventListener("mouseup", l), n !== null && (document.documentElement.style.cursor = n, n = null), i !== null && (document.body.style.userSelect = i, i = null), e = null, a && t.requestStateChange && t.requestStateChange();
968
+ };
969
+ return {
970
+ get isResizing() {
971
+ return e !== null || r;
972
+ },
973
+ start(a, d, f) {
974
+ a.preventDefault();
975
+ const h = f.getBoundingClientRect();
976
+ e = { startX: a.clientX, colIndex: d, startWidth: h.width }, window.addEventListener("mousemove", s), window.addEventListener("mouseup", l), n === null && (n = document.documentElement.style.cursor), document.documentElement.style.cursor = "e-resize", i === null && (i = document.body.style.userSelect), document.body.style.userSelect = "none";
977
+ },
978
+ resetColumn(a) {
979
+ const d = t._visibleColumns[a];
980
+ d && (d.__userResized = !1, d.__renderedWidth = void 0, d.width = d.__originalWidth, t.updateTemplate?.(), t.requestStateChange?.(), t.dispatchEvent(
981
+ new CustomEvent("column-resize-reset", { detail: { field: d.field, width: d.width } })
982
+ ));
983
+ },
984
+ dispose() {
985
+ l();
986
+ }
987
+ };
988
+ }
989
+ function V(t) {
990
+ return t ? typeof t == "string" ? t : t.outerHTML : "";
991
+ }
992
+ function We() {
993
+ return {
994
+ toolPanels: /* @__PURE__ */ new Map(),
995
+ headerContents: /* @__PURE__ */ new Map(),
996
+ toolbarButtons: /* @__PURE__ */ new Map(),
997
+ lightDomButtons: [],
998
+ lightDomHeaderContent: [],
999
+ isPanelOpen: !1,
1000
+ expandedSections: /* @__PURE__ */ new Set(),
1001
+ headerContentCleanups: /* @__PURE__ */ new Map(),
1002
+ panelCleanups: /* @__PURE__ */ new Map(),
1003
+ toolbarButtonCleanups: /* @__PURE__ */ new Map(),
1004
+ // Deprecated - kept for backward compatibility
1005
+ activePanel: null,
1006
+ activePanelCleanup: null
1007
+ };
1008
+ }
1009
+ function Ve(t, e) {
1010
+ return !!(t?.header?.title || t?.header?.toolbarButtons?.length || e.toolPanels.size > 0 || e.headerContents.size > 0 || e.toolbarButtons.size > 0 || e.lightDomButtons.length > 0 || e.lightDomHeaderContent.length > 0);
1011
+ }
1012
+ function Ge(t, e, o = "☰") {
1013
+ const n = t?.header?.title ?? "", i = !!n, s = V(o), r = t?.header?.toolbarButtons ?? [], l = r.length > 0, a = e.toolbarButtons.size > 0, d = e.lightDomButtons.length > 0, f = e.toolPanels.size > 0, p = (l || a || d) && f, c = [...r].sort((w, v) => (w.order ?? 100) - (v.order ?? 100)), u = [...e.toolbarButtons.values()].sort((w, v) => (w.order ?? 100) - (v.order ?? 100));
1014
+ let b = "";
1015
+ for (const w of c)
1016
+ w.icon && w.action && (b += `<button class="tbw-toolbar-btn" data-btn="${w.id}" title="${w.label}" aria-label="${w.label}"${w.disabled ? " disabled" : ""}>${w.icon}</button>`);
1017
+ for (const w of u)
1018
+ w.icon && w.action && (b += `<button class="tbw-toolbar-btn" data-btn="${w.id}" title="${w.label}" aria-label="${w.label}"${w.disabled ? " disabled" : ""}>${w.icon}</button>`);
1019
+ for (const w of c)
1020
+ (w.element || w.render) && (b += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${w.id}"></div>`);
1021
+ for (const w of u)
1022
+ (w.element || w.render) && (b += `<div class="tbw-toolbar-btn-slot" data-btn-slot="${w.id}"></div>`);
1023
+ if (d && (b += '<slot name="toolbar"></slot>'), p && (b += '<div class="tbw-toolbar-separator"></div>'), f) {
1024
+ const w = e.isPanelOpen;
1025
+ b += `<button class="tbw-toolbar-btn${w ? " active" : ""}" data-panel-toggle title="Settings" aria-label="Toggle settings panel" aria-pressed="${w}" aria-controls="tbw-tool-panel">${s}</button>`;
1026
+ }
1027
+ return `
1028
+ <div class="tbw-shell-header" part="shell-header" role="presentation">
1029
+ ${i ? `<div class="tbw-shell-title">${n}</div>` : ""}
1030
+ <div class="tbw-shell-content" part="shell-content" role="presentation">
1031
+ <slot name="header-content"></slot>
1032
+ </div>
1033
+ <div class="tbw-shell-toolbar" part="shell-toolbar" role="presentation">
1034
+ ${b}
1035
+ </div>
1036
+ </div>
1037
+ `;
1038
+ }
1039
+ function Fe(t, e, o, n) {
1040
+ const i = t?.toolPanel?.position ?? "right", s = e.toolPanels.size > 0, r = e.isPanelOpen, l = V(n?.expand ?? H.expand), a = V(n?.collapse ?? H.collapse), d = [...e.toolPanels.values()].sort((u, b) => (u.order ?? 100) - (b.order ?? 100)), f = d.length === 1;
1041
+ let h = "";
1042
+ for (const u of d) {
1043
+ const b = e.expandedSections.has(u.id), w = u.icon ? `<span class="tbw-accordion-icon">${u.icon}</span>` : "", v = f ? "" : `<span class="tbw-accordion-chevron">${b ? a : l}</span>`;
1044
+ h += `
1045
+ <div class="${`tbw-accordion-section${b ? " expanded" : ""}${f ? " single" : ""}`}" data-section="${u.id}">
1046
+ <button class="tbw-accordion-header" aria-expanded="${b}" aria-controls="tbw-section-${u.id}"${f ? ' aria-disabled="true"' : ""}>
1047
+ ${w}
1048
+ <span class="tbw-accordion-title">${u.title}</span>
1049
+ ${v}
1050
+ </button>
1051
+ <div class="tbw-accordion-content" id="tbw-section-${u.id}" role="presentation"></div>
1052
+ </div>
1053
+ `;
1054
+ }
1055
+ const c = s ? `
1056
+ <aside class="tbw-tool-panel${r ? " open" : ""}" part="tool-panel" data-position="${i}" role="presentation" id="tbw-tool-panel">
1057
+ <div class="tbw-tool-panel-resize" data-resize-handle data-handle-position="${i === "left" ? "right" : "left"}" aria-hidden="true"></div>
1058
+ <div class="tbw-tool-panel-content" role="presentation">
1059
+ <div class="tbw-accordion">
1060
+ ${h}
1061
+ </div>
1062
+ </div>
1063
+ </aside>
1064
+ ` : "";
1065
+ return i === "left" ? `
1066
+ <div class="tbw-shell-body">
1067
+ ${c}
1068
+ <div class="tbw-grid-content">
1069
+ ${o}
1070
+ </div>
1071
+ </div>
1072
+ ` : `
1073
+ <div class="tbw-shell-body">
1074
+ <div class="tbw-grid-content">
1075
+ ${o}
1076
+ </div>
1077
+ ${c}
1078
+ </div>
1079
+ `;
1080
+ }
1081
+ function re(t, e) {
1082
+ const o = t.querySelector("tbw-grid-header");
1083
+ if (!o) return;
1084
+ o.style.display = "none";
1085
+ const n = o.querySelectorAll("tbw-grid-header-content");
1086
+ e.lightDomHeaderContent = Array.from(n), e.lightDomHeaderContent.forEach((s) => {
1087
+ s.setAttribute("slot", "header-content");
1088
+ });
1089
+ const i = o.querySelectorAll("tbw-grid-tool-button");
1090
+ e.lightDomButtons = Array.from(i), e.lightDomButtons.sort((s, r) => {
1091
+ const l = parseInt(s.getAttribute("order") ?? "100", 10), a = parseInt(r.getAttribute("order") ?? "100", 10);
1092
+ return l - a;
1093
+ }), e.lightDomButtons.forEach((s) => {
1094
+ s.setAttribute("slot", "toolbar");
1095
+ });
1096
+ }
1097
+ function Ue(t, e, o, n) {
1098
+ const i = t.querySelector(".tbw-shell-toolbar");
1099
+ i && i.addEventListener("click", (r) => {
1100
+ const l = r.target;
1101
+ if (l.closest("[data-panel-toggle]")) {
1102
+ n.onPanelToggle();
1103
+ return;
1104
+ }
1105
+ const d = l.closest("[data-btn]");
1106
+ if (d) {
1107
+ const f = d.getAttribute("data-btn");
1108
+ f && n.onToolbarButtonClick(f);
1109
+ }
1110
+ });
1111
+ const s = t.querySelector(".tbw-accordion");
1112
+ s && s.addEventListener("click", (r) => {
1113
+ const a = r.target.closest(".tbw-accordion-header");
1114
+ if (a) {
1115
+ const f = a.closest("[data-section]")?.getAttribute("data-section");
1116
+ f && n.onSectionToggle(f);
1117
+ }
1118
+ });
1119
+ }
1120
+ function Xe(t, e, o) {
1121
+ const n = t.querySelector(".tbw-tool-panel"), i = t.querySelector("[data-resize-handle]"), s = t.querySelector(".tbw-shell-body");
1122
+ if (!n || !i || !s)
1123
+ return () => {
1124
+ };
1125
+ const r = e?.toolPanel?.position ?? "right", l = 200;
1126
+ let a = 0, d = 0, f = 0, h = !1;
1127
+ const p = (b) => {
1128
+ if (!h) return;
1129
+ b.preventDefault();
1130
+ const w = r === "left" ? b.clientX - a : a - b.clientX, v = Math.min(f, Math.max(l, d + w));
1131
+ n.style.width = `${v}px`;
1132
+ }, c = () => {
1133
+ if (!h) return;
1134
+ h = !1, i.classList.remove("resizing"), n.style.transition = "", document.body.style.cursor = "", document.body.style.userSelect = "";
1135
+ const b = n.getBoundingClientRect().width;
1136
+ o(b), document.removeEventListener("mousemove", p), document.removeEventListener("mouseup", c);
1137
+ }, u = (b) => {
1138
+ b.preventDefault(), h = !0, a = b.clientX, d = n.getBoundingClientRect().width, f = s.getBoundingClientRect().width - 20, i.classList.add("resizing"), n.style.transition = "none", document.body.style.cursor = "col-resize", document.body.style.userSelect = "none", document.addEventListener("mousemove", p), document.addEventListener("mouseup", c);
1139
+ };
1140
+ return i.addEventListener("mousedown", u), () => {
1141
+ i.removeEventListener("mousedown", u), document.removeEventListener("mousemove", p), document.removeEventListener("mouseup", c);
1142
+ };
1143
+ }
1144
+ function Ye(t, e, o) {
1145
+ const n = [...e?.header?.toolbarButtons ?? [], ...o.toolbarButtons.values()];
1146
+ for (const i of n) {
1147
+ const s = t.querySelector(`[data-btn-slot="${i.id}"]`);
1148
+ if (!s) continue;
1149
+ const r = o.toolbarButtonCleanups.get(i.id);
1150
+ if (r && (r(), o.toolbarButtonCleanups.delete(i.id)), i.element)
1151
+ s.appendChild(i.element);
1152
+ else if (i.render) {
1153
+ const l = i.render(s);
1154
+ l && o.toolbarButtonCleanups.set(i.id, l);
1155
+ }
1156
+ }
1157
+ }
1158
+ function fe(t, e) {
1159
+ const o = t.querySelector(".tbw-shell-content");
1160
+ if (!o) return;
1161
+ const n = [...e.headerContents.values()].sort((s, r) => (s.order ?? 100) - (r.order ?? 100)), i = o.querySelector('slot[name="header-content"]');
1162
+ for (const s of n) {
1163
+ const r = e.headerContentCleanups.get(s.id);
1164
+ r && (r(), e.headerContentCleanups.delete(s.id));
1165
+ let l = o.querySelector(`[data-header-content="${s.id}"]`);
1166
+ l || (l = document.createElement("div"), l.setAttribute("data-header-content", s.id), i ? o.insertBefore(l, i) : o.appendChild(l));
1167
+ const a = s.render(l);
1168
+ a && e.headerContentCleanups.set(s.id, a);
1169
+ }
1170
+ }
1171
+ function je(t, e, o) {
1172
+ if (!e.isPanelOpen) return;
1173
+ const n = V(o?.expand ?? H.expand), i = V(o?.collapse ?? H.collapse);
1174
+ for (const [s, r] of e.toolPanels) {
1175
+ const l = e.expandedSections.has(s), a = t.querySelector(`[data-section="${s}"]`), d = a?.querySelector(".tbw-accordion-content");
1176
+ if (!a || !d) continue;
1177
+ a.classList.toggle("expanded", l);
1178
+ const f = a.querySelector(".tbw-accordion-header");
1179
+ f && f.setAttribute("aria-expanded", String(l));
1180
+ const h = a.querySelector(".tbw-accordion-chevron");
1181
+ if (h && (h.innerHTML = l ? i : n), l) {
1182
+ if (d.children.length === 0) {
1183
+ const p = r.render(d);
1184
+ p && e.panelCleanups.set(s, p);
1185
+ }
1186
+ } else {
1187
+ const p = e.panelCleanups.get(s);
1188
+ p && (p(), e.panelCleanups.delete(s)), d.innerHTML = "";
1189
+ }
1190
+ }
1191
+ }
1192
+ function le(t, e) {
1193
+ const o = t.querySelector("[data-panel-toggle]");
1194
+ o && (o.classList.toggle("active", e.isPanelOpen), o.setAttribute("aria-pressed", String(e.isPanelOpen)));
1195
+ }
1196
+ function ae(t, e) {
1197
+ const o = t.querySelector(".tbw-tool-panel");
1198
+ o && (o.classList.toggle("open", e.isPanelOpen), e.isPanelOpen || (o.style.width = ""));
1199
+ }
1200
+ function Ke(t, e) {
1201
+ const o = [];
1202
+ for (const n of t?.header?.toolbarButtons ?? [])
1203
+ o.push({
1204
+ id: n.id,
1205
+ label: n.label,
1206
+ disabled: n.disabled ?? !1,
1207
+ source: "config"
1208
+ });
1209
+ for (const n of e.toolbarButtons.values())
1210
+ o.push({
1211
+ id: n.id,
1212
+ label: n.label,
1213
+ disabled: n.disabled ?? !1,
1214
+ source: "config"
1215
+ });
1216
+ for (let n = 0; n < e.lightDomButtons.length; n++) {
1217
+ const s = e.lightDomButtons[n].querySelector("button");
1218
+ o.push({
1219
+ id: `light-dom-${n}`,
1220
+ label: s?.getAttribute("title") ?? s?.getAttribute("aria-label") ?? "",
1221
+ disabled: s?.disabled ?? !1,
1222
+ source: "light-dom"
1223
+ });
1224
+ }
1225
+ for (const n of e.toolPanels.values())
1226
+ o.push({
1227
+ id: `panel-toggle-${n.id}`,
1228
+ label: n.tooltip ?? n.title,
1229
+ disabled: !1,
1230
+ source: "panel-toggle",
1231
+ panelId: n.id
1232
+ });
1233
+ return o;
1234
+ }
1235
+ function Ze(t) {
1236
+ for (const e of t.headerContentCleanups.values())
1237
+ e();
1238
+ t.headerContentCleanups.clear(), t.activePanelCleanup && (t.activePanelCleanup(), t.activePanelCleanup = null);
1239
+ for (const e of t.toolbarButtonCleanups.values())
1240
+ e();
1241
+ t.toolbarButtonCleanups.clear(), t.activePanel && t.toolPanels.get(t.activePanel)?.onClose?.(), t.toolPanels.clear(), t.headerContents.clear(), t.toolbarButtons.clear(), t.lightDomButtons = [], t.lightDomHeaderContent = [], t.activePanel = null;
1242
+ }
1243
+ function Je(t, e) {
1244
+ let o = !1;
1245
+ const n = {
1246
+ get isInitialized() {
1247
+ return o;
1248
+ },
1249
+ setInitialized(i) {
1250
+ o = i;
1251
+ },
1252
+ get isPanelOpen() {
1253
+ return t.isPanelOpen;
1254
+ },
1255
+ get activePanel() {
1256
+ return t.isPanelOpen && t.expandedSections.size > 0 ? [...t.expandedSections][0] : null;
1257
+ },
1258
+ get expandedSections() {
1259
+ return [...t.expandedSections];
1260
+ },
1261
+ openToolPanel() {
1262
+ if (t.isPanelOpen) return;
1263
+ if (t.toolPanels.size === 0) {
1264
+ console.warn("[tbw-grid] No tool panels registered");
1265
+ return;
1266
+ }
1267
+ if (t.isPanelOpen = !0, t.expandedSections.size === 0 && t.toolPanels.size > 0) {
1268
+ const r = [...t.toolPanels.values()].sort((l, a) => (l.order ?? 100) - (a.order ?? 100))[0];
1269
+ r && t.expandedSections.add(r.id);
1270
+ }
1271
+ const i = e.getShadow();
1272
+ le(i, t), ae(i, t), je(i, t, e.getAccordionIcons()), e.emit("tool-panel-open", { sections: n.expandedSections });
1273
+ },
1274
+ closeToolPanel() {
1275
+ if (!t.isPanelOpen) return;
1276
+ for (const s of t.panelCleanups.values())
1277
+ s();
1278
+ t.panelCleanups.clear(), t.activePanelCleanup && (t.activePanelCleanup(), t.activePanelCleanup = null);
1279
+ for (const s of t.toolPanels.values())
1280
+ s.onClose?.();
1281
+ t.isPanelOpen = !1;
1282
+ const i = e.getShadow();
1283
+ le(i, t), ae(i, t), e.emit("tool-panel-close", {});
1284
+ },
1285
+ toggleToolPanel() {
1286
+ t.isPanelOpen ? n.closeToolPanel() : n.openToolPanel();
1287
+ },
1288
+ toggleToolPanelSection(i) {
1289
+ const s = t.toolPanels.get(i);
1290
+ if (!s) {
1291
+ console.warn(`[tbw-grid] Tool panel section "${i}" not found`);
1292
+ return;
1293
+ }
1294
+ if (t.toolPanels.size === 1)
1295
+ return;
1296
+ const r = e.getShadow(), l = t.expandedSections.has(i);
1297
+ if (l) {
1298
+ const a = t.panelCleanups.get(i);
1299
+ a && (a(), t.panelCleanups.delete(i)), s.onClose?.(), t.expandedSections.delete(i), X(r, i, !1);
1300
+ } else {
1301
+ for (const [a, d] of t.toolPanels)
1302
+ if (a !== i && t.expandedSections.has(a)) {
1303
+ const f = t.panelCleanups.get(a);
1304
+ f && (f(), t.panelCleanups.delete(a)), d.onClose?.(), t.expandedSections.delete(a), X(r, a, !1);
1305
+ const h = r.querySelector(`[data-section="${a}"] .tbw-accordion-content`);
1306
+ h && (h.innerHTML = "");
1307
+ }
1308
+ t.expandedSections.add(i), X(r, i, !0), Qe(r, t, i);
1309
+ }
1310
+ e.emit("tool-panel-section-toggle", { id: i, expanded: !l });
1311
+ },
1312
+ getToolPanels() {
1313
+ return [...t.toolPanels.values()];
1314
+ },
1315
+ registerToolPanel(i) {
1316
+ if (t.toolPanels.has(i.id)) {
1317
+ console.warn(`[tbw-grid] Tool panel "${i.id}" already registered`);
1318
+ return;
1319
+ }
1320
+ t.toolPanels.set(i.id, i), o && e.refreshShellHeader();
1321
+ },
1322
+ unregisterToolPanel(i) {
1323
+ if (t.expandedSections.has(i)) {
1324
+ const s = t.panelCleanups.get(i);
1325
+ s && (s(), t.panelCleanups.delete(i)), t.expandedSections.delete(i);
1326
+ }
1327
+ t.toolPanels.delete(i), o && e.refreshShellHeader();
1328
+ },
1329
+ getHeaderContents() {
1330
+ return [...t.headerContents.values()];
1331
+ },
1332
+ registerHeaderContent(i) {
1333
+ if (t.headerContents.has(i.id)) {
1334
+ console.warn(`[tbw-grid] Header content "${i.id}" already registered`);
1335
+ return;
1336
+ }
1337
+ t.headerContents.set(i.id, i), o && fe(e.getShadow(), t);
1338
+ },
1339
+ unregisterHeaderContent(i) {
1340
+ const s = t.headerContentCleanups.get(i);
1341
+ s && (s(), t.headerContentCleanups.delete(i)), t.headerContents.get(i)?.onDestroy?.(), t.headerContents.delete(i), e.getShadow().querySelector(`[data-header-content="${i}"]`)?.remove();
1342
+ },
1343
+ getToolbarButtons() {
1344
+ return Ke(e.getShellConfig(), t);
1345
+ },
1346
+ registerToolbarButton(i) {
1347
+ if (t.toolbarButtons.has(i.id)) {
1348
+ console.warn(`[tbw-grid] Toolbar button "${i.id}" already registered`);
1349
+ return;
1350
+ }
1351
+ t.toolbarButtons.set(i.id, i), o && e.refreshShellHeader();
1352
+ },
1353
+ unregisterToolbarButton(i) {
1354
+ const s = t.toolbarButtonCleanups.get(i);
1355
+ s && (s(), t.toolbarButtonCleanups.delete(i)), t.toolbarButtons.delete(i), o && e.refreshShellHeader();
1356
+ },
1357
+ setToolbarButtonDisabled(i, s) {
1358
+ const r = t.toolbarButtons.get(i);
1359
+ r && (r.disabled = s);
1360
+ const l = e.getShadow().querySelector(`[data-btn="${i}"]`);
1361
+ l && (l.disabled = s);
1362
+ }
1363
+ };
1364
+ return n;
1365
+ }
1366
+ function X(t, e, o) {
1367
+ const n = t.querySelector(`[data-section="${e}"]`);
1368
+ n && n.classList.toggle("expanded", o);
1369
+ }
1370
+ function Qe(t, e, o) {
1371
+ const n = e.toolPanels.get(o);
1372
+ if (!n?.render) return;
1373
+ const i = t.querySelector(`[data-section="${o}"] .tbw-accordion-content`);
1374
+ if (!i) return;
1375
+ const s = n.render(i);
1376
+ s && e.panelCleanups.set(o, s);
1377
+ }
1378
+ class et {
1379
+ constructor(e) {
1380
+ this.grid = e;
1381
+ }
1382
+ /** Plugin instances in order of attachment */
1383
+ plugins = [];
1384
+ /** Map from plugin class to instance for fast lookup */
1385
+ pluginMap = /* @__PURE__ */ new Map();
1386
+ /** Cell renderers registered by plugins */
1387
+ cellRenderers = /* @__PURE__ */ new Map();
1388
+ /** Header renderers registered by plugins */
1389
+ headerRenderers = /* @__PURE__ */ new Map();
1390
+ /** Cell editors registered by plugins */
1391
+ cellEditors = /* @__PURE__ */ new Map();
1392
+ /**
1393
+ * Attach all plugins from the config.
1394
+ */
1395
+ attachAll(e) {
1396
+ for (const o of e)
1397
+ this.attach(o);
1398
+ }
1399
+ /**
1400
+ * Attach a plugin to this grid.
1401
+ */
1402
+ attach(e) {
1403
+ if (this.pluginMap.set(e.constructor, e), this.plugins.push(e), e.cellRenderers)
1404
+ for (const [o, n] of Object.entries(e.cellRenderers))
1405
+ this.cellRenderers.set(o, n);
1406
+ if (e.headerRenderers)
1407
+ for (const [o, n] of Object.entries(e.headerRenderers))
1408
+ this.headerRenderers.set(o, n);
1409
+ if (e.cellEditors)
1410
+ for (const [o, n] of Object.entries(e.cellEditors))
1411
+ this.cellEditors.set(o, n);
1412
+ e.attach(this.grid);
1413
+ }
1414
+ /**
1415
+ * Detach all plugins and clean up.
1416
+ */
1417
+ detachAll() {
1418
+ for (let e = this.plugins.length - 1; e >= 0; e--)
1419
+ this.plugins[e].detach();
1420
+ this.plugins = [], this.pluginMap.clear(), this.cellRenderers.clear(), this.headerRenderers.clear(), this.cellEditors.clear();
1421
+ }
1422
+ /**
1423
+ * Get a plugin instance by its class.
1424
+ */
1425
+ getPlugin(e) {
1426
+ return this.pluginMap.get(e);
1427
+ }
1428
+ /**
1429
+ * Get a plugin instance by its name.
1430
+ */
1431
+ getPluginByName(e) {
1432
+ return this.plugins.find((o) => o.name === e);
1433
+ }
1434
+ /**
1435
+ * Check if a plugin is attached.
1436
+ */
1437
+ hasPlugin(e) {
1438
+ return this.pluginMap.has(e);
1439
+ }
1440
+ /**
1441
+ * Get all attached plugins.
1442
+ */
1443
+ getAll() {
1444
+ return this.plugins;
1445
+ }
1446
+ /**
1447
+ * Get a cell renderer by type name.
1448
+ */
1449
+ getCellRenderer(e) {
1450
+ return this.cellRenderers.get(e);
1451
+ }
1452
+ /**
1453
+ * Get a header renderer by type name.
1454
+ */
1455
+ getHeaderRenderer(e) {
1456
+ return this.headerRenderers.get(e);
1457
+ }
1458
+ /**
1459
+ * Get a cell editor by type name.
1460
+ */
1461
+ getCellEditor(e) {
1462
+ return this.cellEditors.get(e);
1463
+ }
1464
+ /**
1465
+ * Get all CSS styles from all plugins.
1466
+ */
1467
+ getAllStyles() {
1468
+ return this.plugins.filter((e) => e.styles).map((e) => e.styles).join(`
1469
+ `);
1470
+ }
1471
+ // #region Hook execution methods
1472
+ /**
1473
+ * Execute processRows hook on all plugins.
1474
+ */
1475
+ processRows(e) {
1476
+ let o = [...e];
1477
+ for (const n of this.plugins)
1478
+ n.processRows && (o = n.processRows(o));
1479
+ return o;
1480
+ }
1481
+ /**
1482
+ * Execute processColumns hook on all plugins.
1483
+ */
1484
+ processColumns(e) {
1485
+ let o = [...e];
1486
+ for (const n of this.plugins)
1487
+ n.processColumns && (o = n.processColumns(o));
1488
+ return o;
1489
+ }
1490
+ /**
1491
+ * Execute beforeRender hook on all plugins.
1492
+ */
1493
+ beforeRender() {
1494
+ for (const e of this.plugins)
1495
+ e.beforeRender?.();
1496
+ }
1497
+ /**
1498
+ * Execute afterRender hook on all plugins.
1499
+ */
1500
+ afterRender() {
1501
+ for (const e of this.plugins)
1502
+ e.afterRender?.();
1503
+ }
1504
+ /**
1505
+ * Execute onScrollRender hook on all plugins.
1506
+ * Called after scroll-triggered row rendering for lightweight visual state updates.
1507
+ */
1508
+ onScrollRender() {
1509
+ for (const e of this.plugins)
1510
+ e.onScrollRender?.();
1511
+ }
1512
+ /**
1513
+ * Get total extra height contributed by plugins (e.g., expanded detail rows).
1514
+ * Used to adjust scrollbar height calculations.
1515
+ */
1516
+ getExtraHeight() {
1517
+ let e = 0;
1518
+ for (const o of this.plugins)
1519
+ typeof o.getExtraHeight == "function" && (e += o.getExtraHeight());
1520
+ return e;
1521
+ }
1522
+ /**
1523
+ * Get extra height from plugins that appears before a given row index.
1524
+ * Used by virtualization to correctly position the scroll window.
1525
+ */
1526
+ getExtraHeightBefore(e) {
1527
+ let o = 0;
1528
+ for (const n of this.plugins)
1529
+ typeof n.getExtraHeightBefore == "function" && (o += n.getExtraHeightBefore(e));
1530
+ return o;
1531
+ }
1532
+ /**
1533
+ * Adjust the virtualization start index based on plugin needs.
1534
+ * Returns the minimum start index from all plugins.
1535
+ */
1536
+ adjustVirtualStart(e, o, n) {
1537
+ let i = e;
1538
+ for (const s of this.plugins)
1539
+ if (typeof s.adjustVirtualStart == "function") {
1540
+ const r = s.adjustVirtualStart(e, o, n);
1541
+ r < i && (i = r);
1542
+ }
1543
+ return i;
1544
+ }
1545
+ /**
1546
+ * Execute renderRow hook on all plugins.
1547
+ * Returns true if any plugin handled the row.
1548
+ */
1549
+ renderRow(e, o, n) {
1550
+ for (const i of this.plugins)
1551
+ if (i.renderRow?.(e, o, n))
1552
+ return !0;
1553
+ return !1;
1554
+ }
1555
+ /**
1556
+ * Query all plugins with a generic query and collect responses.
1557
+ * This enables inter-plugin communication without the core knowing plugin-specific concepts.
1558
+ *
1559
+ * Common query types are defined in PLUGIN_QUERIES, but plugins can define their own.
1560
+ *
1561
+ * @param query - The query object containing type and context
1562
+ * @returns Array of non-undefined responses from plugins
1563
+ */
1564
+ queryPlugins(e) {
1565
+ const o = [];
1566
+ for (const n of this.plugins) {
1567
+ const i = n.onPluginQuery?.(e);
1568
+ i !== void 0 && o.push(i);
1569
+ }
1570
+ return o;
1571
+ }
1572
+ /**
1573
+ * Execute onKeyDown hook on all plugins.
1574
+ * Returns true if any plugin handled the event.
1575
+ */
1576
+ onKeyDown(e) {
1577
+ for (const o of this.plugins)
1578
+ if (o.onKeyDown?.(e))
1579
+ return !0;
1580
+ return !1;
1581
+ }
1582
+ /**
1583
+ * Execute onCellClick hook on all plugins.
1584
+ * Returns true if any plugin handled the event.
1585
+ */
1586
+ onCellClick(e) {
1587
+ for (const o of this.plugins)
1588
+ if (o.onCellClick?.(e))
1589
+ return !0;
1590
+ return !1;
1591
+ }
1592
+ /**
1593
+ * Execute onRowClick hook on all plugins.
1594
+ * Returns true if any plugin handled the event.
1595
+ */
1596
+ onRowClick(e) {
1597
+ for (const o of this.plugins)
1598
+ if (o.onRowClick?.(e))
1599
+ return !0;
1600
+ return !1;
1601
+ }
1602
+ /**
1603
+ * Execute onHeaderClick hook on all plugins.
1604
+ * Returns true if any plugin handled the event.
1605
+ */
1606
+ onHeaderClick(e) {
1607
+ for (const o of this.plugins)
1608
+ if (o.onHeaderClick?.(e))
1609
+ return !0;
1610
+ return !1;
1611
+ }
1612
+ /**
1613
+ * Execute onScroll hook on all plugins.
1614
+ */
1615
+ onScroll(e) {
1616
+ for (const o of this.plugins)
1617
+ o.onScroll?.(e);
1618
+ }
1619
+ /**
1620
+ * Execute onCellMouseDown hook on all plugins.
1621
+ * Returns true if any plugin handled the event.
1622
+ */
1623
+ onCellMouseDown(e) {
1624
+ for (const o of this.plugins)
1625
+ if (o.onCellMouseDown?.(e))
1626
+ return !0;
1627
+ return !1;
1628
+ }
1629
+ /**
1630
+ * Execute onCellMouseMove hook on all plugins.
1631
+ * Returns true if any plugin handled the event.
1632
+ */
1633
+ onCellMouseMove(e) {
1634
+ for (const o of this.plugins)
1635
+ if (o.onCellMouseMove?.(e))
1636
+ return !0;
1637
+ return !1;
1638
+ }
1639
+ /**
1640
+ * Execute onCellMouseUp hook on all plugins.
1641
+ * Returns true if any plugin handled the event.
1642
+ */
1643
+ onCellMouseUp(e) {
1644
+ for (const o of this.plugins)
1645
+ if (o.onCellMouseUp?.(e))
1646
+ return !0;
1647
+ return !1;
1648
+ }
1649
+ // #endregion
1650
+ // #region Scroll Boundary Hooks
1651
+ /**
1652
+ * Collect horizontal scroll boundary offsets from all plugins.
1653
+ * Combines offsets from all plugins that report them.
1654
+ *
1655
+ * @param rowEl - The row element (optional, for calculating widths from rendered cells)
1656
+ * @param focusedCell - The currently focused cell element (optional, to determine if scrolling should be skipped)
1657
+ * @returns Combined left and right pixel offsets, plus skipScroll if any plugin requests it
1658
+ */
1659
+ getHorizontalScrollOffsets(e, o) {
1660
+ let n = 0, i = 0, s = !1;
1661
+ for (const r of this.plugins) {
1662
+ const l = r.getHorizontalScrollOffsets?.(e, o);
1663
+ l && (n += l.left, i += l.right, l.skipScroll && (s = !0));
1664
+ }
1665
+ return { left: n, right: i, skipScroll: s };
1666
+ }
1667
+ // #endregion
1668
+ // #region Shell Integration Hooks
1669
+ /**
1670
+ * Collect tool panels from all plugins.
1671
+ * Returns panels sorted by order (ascending).
1672
+ */
1673
+ getToolPanels() {
1674
+ const e = [];
1675
+ for (const o of this.plugins) {
1676
+ const n = o.getToolPanel?.();
1677
+ n && e.push({ plugin: o, panel: n });
1678
+ }
1679
+ return e.sort((o, n) => (o.panel.order ?? 0) - (n.panel.order ?? 0));
1680
+ }
1681
+ /**
1682
+ * Collect header contents from all plugins.
1683
+ * Returns contents sorted by order (ascending).
1684
+ */
1685
+ getHeaderContents() {
1686
+ const e = [];
1687
+ for (const o of this.plugins) {
1688
+ const n = o.getHeaderContent?.();
1689
+ n && e.push({ plugin: o, content: n });
1690
+ }
1691
+ return e.sort((o, n) => (o.content.order ?? 0) - (n.content.order ?? 0));
1692
+ }
1693
+ // #endregion
1694
+ }
1695
+ class W extends HTMLElement {
1696
+ // TODO: Rename to 'data-grid' when migration is complete
1697
+ static tagName = "tbw-grid";
1698
+ static version = "0.2.7";
1699
+ // ---------------- Observed Attributes ----------------
1700
+ static get observedAttributes() {
1701
+ return ["rows", "columns", "grid-config", "fit-mode", "edit-on"];
1702
+ }
1703
+ #o;
1704
+ #M = !1;
1705
+ // ---------------- Ready Promise ----------------
1706
+ #I;
1707
+ #$;
1708
+ // #region Input Properties
1709
+ // These backing fields store raw user input. They are merged into
1710
+ // #effectiveConfig by #mergeEffectiveConfig(). Never read directly
1711
+ // for rendering logic - always use effectiveConfig or derived state.
1712
+ #r = [];
1713
+ #l;
1714
+ #g;
1715
+ #C;
1716
+ #y;
1717
+ // #endregion
1718
+ // #region Private properties
1719
+ // All input sources converge here. This is the canonical config
1720
+ // that all rendering and logic should read from.
1721
+ #t = {};
1722
+ #p = !1;
1723
+ #b = 0;
1724
+ #S = null;
1725
+ #R = !1;
1726
+ // Cached flag for plugin scroll handlers
1727
+ #z;
1728
+ // Cached hook to avoid closures
1729
+ #x = !1;
1730
+ #A = null;
1731
+ #T = null;
1732
+ #L = null;
1733
+ #P = null;
1734
+ #m = null;
1735
+ #v = null;
1736
+ #_ = null;
1737
+ #d = 0;
1738
+ #u = 0;
1739
+ #w = 0;
1740
+ #a;
1741
+ #E;
1742
+ // ---------------- Plugin System ----------------
1743
+ #e;
1744
+ // ---------------- Column State ----------------
1745
+ #D;
1746
+ #h;
1747
+ // ---------------- Shell State ----------------
1748
+ #i = We();
1749
+ #n;
1750
+ #H;
1751
+ // #endregion
1752
+ // #region Derived State
1753
+ // _rows: result of applying plugin processRows hooks
1754
+ _rows = [];
1755
+ // _baseColumns: columns before plugin transformation (analogous to #rows for row processing)
1756
+ // This is the source of truth for processColumns - plugins transform these
1757
+ #N = [];
1758
+ // _columns is a getter/setter that operates on effectiveConfig.columns
1759
+ // This ensures effectiveConfig.columns is the single source of truth for columns
1760
+ // _columns always contains ALL columns (including hidden)
1761
+ get _columns() {
1762
+ return this.#t.columns ?? [];
1763
+ }
1764
+ set _columns(e) {
1765
+ this.#t.columns = e;
1766
+ }
1767
+ // visibleColumns returns only visible columns for rendering
1768
+ // This is what header/row rendering should use
1769
+ get _visibleColumns() {
1770
+ return this._columns.filter((e) => !e.hidden);
1771
+ }
1772
+ // #endregion
1773
+ // #region Runtime State (Plugin-accessible)
1774
+ // DOM references
1775
+ _headerRowEl;
1776
+ _bodyEl;
1777
+ _rowPool = [];
1778
+ _resizeController;
1779
+ // Virtualization & scroll state
1780
+ _virtualization = {
1781
+ enabled: !0,
1782
+ rowHeight: 28,
1783
+ bypassThreshold: 24,
1784
+ start: 0,
1785
+ end: 0,
1786
+ container: null,
1787
+ viewportEl: null,
1788
+ totalHeightEl: null
1789
+ };
1790
+ // Focus & navigation
1791
+ _focusRow = 0;
1792
+ _focusCol = 0;
1793
+ // Sort state
1794
+ _sortState = null;
1795
+ // Edit state
1796
+ _activeEditRows = -1;
1797
+ _rowEditSnapshots = /* @__PURE__ */ new Map();
1798
+ _changedRowIndices = /* @__PURE__ */ new Set();
1799
+ // Layout
1800
+ _gridTemplate = "";
1801
+ // #endregion
1802
+ // #region Implementation Details (Internal only)
1803
+ __rowRenderEpoch = 0;
1804
+ __didInitialAutoSize = !1;
1805
+ __lightDomColumnsCache;
1806
+ __originalColumnNodes;
1807
+ __originalOrder = [];
1808
+ // #endregion
1809
+ // #region Public API Props (getters/setters)
1810
+ // Getters return the EFFECTIVE value (after merging), not the raw input.
1811
+ // This is what consumers and plugins need - the current resolved state.
1812
+ // Setters update input properties which trigger re-merge into effectiveConfig.
1813
+ get rows() {
1814
+ return this._rows;
1815
+ }
1816
+ set rows(e) {
1817
+ const o = this.#r;
1818
+ this.#r = e, o !== e && this.#ee();
1819
+ }
1820
+ /**
1821
+ * Get the original unfiltered/unprocessed rows.
1822
+ * Use this when you need access to all source data regardless of active filters.
1823
+ */
1824
+ get sourceRows() {
1825
+ return this.#r;
1826
+ }
1827
+ get columns() {
1828
+ return [...this._columns];
1829
+ }
1830
+ set columns(e) {
1831
+ const o = this.#l;
1832
+ this.#l = e, o !== e && this.#te();
1833
+ }
1834
+ get gridConfig() {
1835
+ return this.#t;
1836
+ }
1837
+ set gridConfig(e) {
1838
+ const o = this.#g;
1839
+ this.#g = e, o !== e && this.#oe();
1840
+ }
1841
+ get fitMode() {
1842
+ return this.#t.fitMode ?? "stretch";
1843
+ }
1844
+ set fitMode(e) {
1845
+ const o = this.#C;
1846
+ this.#C = e, o !== e && this.#J();
1847
+ }
1848
+ get editOn() {
1849
+ return this.#t.editOn;
1850
+ }
1851
+ set editOn(e) {
1852
+ const o = this.#y;
1853
+ this.#y = e, o !== e && this.#Q();
1854
+ }
1855
+ /**
1856
+ * Effective config accessor for internal modules and plugins.
1857
+ * Returns the merged config (single source of truth) before plugin processing.
1858
+ * Use this when you need the raw merged config (e.g., for column definitions including hidden).
1859
+ * @internal Plugin API
1860
+ */
1861
+ get effectiveConfig() {
1862
+ return this.#t;
1863
+ }
1864
+ /**
1865
+ * Get the disconnect signal for event listener cleanup.
1866
+ * This signal is aborted when the grid disconnects from the DOM.
1867
+ * Plugins and internal code can use this for automatic listener cleanup.
1868
+ * @internal Plugin API
1869
+ * @example
1870
+ * element.addEventListener('click', handler, { signal: this.grid.disconnectSignal });
1871
+ */
1872
+ get disconnectSignal() {
1873
+ return this.#a || (this.#a = new AbortController()), this.#a.signal;
1874
+ }
1875
+ // #endregion
1876
+ constructor() {
1877
+ super(), this.#o = this.attachShadow({ mode: "open" }), this.#Y(), this.#I = new Promise((e) => this.#$ = e), this.#n = Je(this.#i, {
1878
+ getShadow: () => this.#o,
1879
+ getShellConfig: () => this.#t?.shell,
1880
+ getAccordionIcons: () => ({
1881
+ expand: this.#t?.icons?.expand ?? H.expand,
1882
+ collapse: this.#t?.icons?.collapse ?? H.collapse
1883
+ }),
1884
+ emit: (e, o) => this.#s(e, o),
1885
+ refreshShellHeader: () => this.refreshShellHeader()
1886
+ });
1887
+ }
1888
+ #Y() {
1889
+ const e = new CSSStyleSheet();
1890
+ e.replaceSync(pe), this.#o.adoptedStyleSheets = [e];
1891
+ }
1892
+ // ---------------- Plugin System ----------------
1893
+ /**
1894
+ * Get a plugin instance by its class.
1895
+ * Used by plugins for inter-plugin communication.
1896
+ * @internal Plugin API
1897
+ */
1898
+ getPlugin(e) {
1899
+ return this.#e?.getPlugin(e);
1900
+ }
1901
+ /**
1902
+ * Get a plugin instance by its name.
1903
+ * Used for loose coupling between plugins (avoids static imports).
1904
+ * @internal Plugin API
1905
+ */
1906
+ getPluginByName(e) {
1907
+ return this.#e?.getPluginByName(e);
1908
+ }
1909
+ /**
1910
+ * Request a full re-render of the grid.
1911
+ * Called by plugins when they need the grid to update.
1912
+ * Note: This does NOT reset plugin state - just re-processes rows/columns and renders.
1913
+ * @internal Plugin API
1914
+ */
1915
+ requestRender() {
1916
+ this.#O(), this.#k(), q(this), z(this), this.refreshVirtualWindow(!0);
1917
+ }
1918
+ /**
1919
+ * Update the grid's column template CSS.
1920
+ * Called by resize controller during column resize operations.
1921
+ * @internal
1922
+ */
1923
+ updateTemplate() {
1924
+ z(this);
1925
+ }
1926
+ /**
1927
+ * Request a lightweight style update without rebuilding DOM.
1928
+ * Called by plugins when they only need to update CSS classes/styles.
1929
+ * This runs all plugin afterRender hooks without rebuilding row/column DOM.
1930
+ * @internal Plugin API
1931
+ */
1932
+ requestAfterRender() {
1933
+ this.#e?.afterRender();
1934
+ }
1935
+ /**
1936
+ * Initialize plugin system with instances from config.
1937
+ * Plugins are class instances passed in gridConfig.plugins[].
1938
+ */
1939
+ #W() {
1940
+ this.#e = new et(this);
1941
+ const e = this.#t?.plugins, o = Array.isArray(e) ? e : [];
1942
+ this.#e.attachAll(o);
1943
+ }
1944
+ /**
1945
+ * Inject all plugin styles into the shadow DOM.
1946
+ * Must be called after #render() since innerHTML wipes existing content.
1947
+ */
1948
+ #V() {
1949
+ const e = this.#e?.getAllStyles() ?? "";
1950
+ if (e) {
1951
+ const o = document.createElement("style");
1952
+ o.setAttribute("data-plugin", "all"), o.textContent = e, this.#o.appendChild(o);
1953
+ }
1954
+ }
1955
+ /**
1956
+ * Update plugins when grid config changes.
1957
+ * With class-based plugins, we need to detach old and attach new.
1958
+ */
1959
+ #G() {
1960
+ this.#e && this.#e.detachAll(), this.#W(), this.#V(), this.#R = this.#e?.getAll().some((e) => e.onScroll) ?? !1;
1961
+ }
1962
+ /**
1963
+ * Clean up plugin states when grid disconnects.
1964
+ */
1965
+ #j() {
1966
+ this.#e?.detachAll();
1967
+ }
1968
+ /**
1969
+ * Collect tool panels and header content from all plugins.
1970
+ * Called after plugins are attached but before render.
1971
+ */
1972
+ #K() {
1973
+ if (!this.#e) return;
1974
+ const e = this.#e.getToolPanels();
1975
+ for (const { panel: n } of e)
1976
+ this.#i.toolPanels.has(n.id) || this.#i.toolPanels.set(n.id, n);
1977
+ const o = this.#e.getHeaderContents();
1978
+ for (const { content: n } of o)
1979
+ this.#i.headerContents.has(n.id) || this.#i.headerContents.set(n.id, n);
1980
+ }
1981
+ // ---------------- Lifecycle ----------------
1982
+ connectedCallback() {
1983
+ this.hasAttribute("tabindex") || (this.tabIndex = 0), this.hasAttribute("version") || this.setAttribute("version", W.version), this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#a?.abort(), this.#a = new AbortController(), this.#f(), this.#W(), this.#K(), this.#M || (this.#X(), this.#V(), this.#M = !0), this.#F();
1984
+ }
1985
+ disconnectedCallback() {
1986
+ this.#j(), Ze(this.#i), this.#n.setInitialized(!1), this.#H?.(), this.#H = void 0, this.#a && (this.#a.abort(), this.#a = void 0), this._resizeController && this._resizeController.dispose(), this.#E && (this.#E.disconnect(), this.#E = void 0), this.#p = !1;
1987
+ }
1988
+ /**
1989
+ * Handle HTML attribute changes.
1990
+ * Only processes attribute values when SET (non-null).
1991
+ * Removing an attribute does NOT clear JS-set properties.
1992
+ */
1993
+ attributeChangedCallback(e, o, n) {
1994
+ if (o === n || !n || n === "null" || n === "undefined") return;
1995
+ const s = {
1996
+ rows: "rows",
1997
+ columns: "columns",
1998
+ "grid-config": "gridConfig",
1999
+ "fit-mode": "fitMode",
2000
+ "edit-on": "editOn"
2001
+ }[e];
2002
+ if (s)
2003
+ if (e === "rows" || e === "columns" || e === "grid-config")
2004
+ try {
2005
+ this[s] = JSON.parse(n);
2006
+ } catch {
2007
+ console.warn(`[tbw-grid] Invalid JSON for '${e}' attribute:`, n);
2008
+ }
2009
+ else
2010
+ this[s] = n;
2011
+ }
2012
+ #F() {
2013
+ const o = this.#o.querySelector(".tbw-grid-content") ?? this.#o.querySelector(".tbw-grid-root");
2014
+ 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.#n.isInitialized) {
2015
+ fe(this.#o, this.#i), Ye(this.#o, this.#t?.shell, this.#i);
2016
+ const l = this.#t?.shell?.toolPanel?.defaultOpen;
2017
+ l && this.#i.toolPanels.has(l) && (this.openToolPanel(), this.#i.expandedSections.add(l));
2018
+ }
2019
+ this.setAttribute("data-upgraded", ""), this.#p = !0;
2020
+ const n = this.disconnectSignal;
2021
+ this._resizeController = $e(this), this.#c(), this.addEventListener("keydown", (l) => Me(this, l), { signal: n }), document.addEventListener(
2022
+ "keydown",
2023
+ (l) => {
2024
+ l.key === "Escape" && this._activeEditRows !== -1 && D(this, this._activeEditRows, !0);
2025
+ },
2026
+ { capture: !0, signal: n }
2027
+ ), document.addEventListener(
2028
+ "mousedown",
2029
+ (l) => {
2030
+ if (this._activeEditRows === -1) return;
2031
+ const a = this.findRenderedRowElement(this._activeEditRows);
2032
+ !a || (l.composedPath && l.composedPath() || []).includes(a) || D(this, this._activeEditRows, !1);
2033
+ },
2034
+ { signal: n }
2035
+ );
2036
+ const i = o?.querySelector(".faux-vscroll"), s = o?.querySelector(".rows");
2037
+ if (this._virtualization.container = i ?? this, this.#R = this.#e?.getAll().some((l) => l.onScroll) ?? !1, i && s) {
2038
+ i.addEventListener(
2039
+ "scroll",
2040
+ () => {
2041
+ if (!this._virtualization.enabled && !this.#R) return;
2042
+ const d = i.scrollTop, f = this._virtualization.rowHeight, h = Math.floor(d / f), p = h - h % 2, c = -(d - p * f);
2043
+ s.style.transform = `translateY(${c}px)`, this.#S = d, this.#b || (this.#b = requestAnimationFrame(() => {
2044
+ this.#b = 0, this.#S !== null && (this.#ie(this.#S), this.#S = null);
2045
+ }));
2046
+ },
2047
+ { passive: !0, signal: n }
2048
+ );
2049
+ const l = this.#o.querySelector(".tbw-grid-content"), a = this.#o.querySelector(".tbw-scroll-area");
2050
+ l && (l.addEventListener(
2051
+ "wheel",
2052
+ (d) => {
2053
+ const f = d.shiftKey || Math.abs(d.deltaX) > Math.abs(d.deltaY);
2054
+ if (f && a) {
2055
+ const h = d.shiftKey ? d.deltaY : d.deltaX, { scrollLeft: p, scrollWidth: c, clientWidth: u } = a;
2056
+ (h > 0 && p < c - u || h < 0 && p > 0) && (d.preventDefault(), a.scrollLeft += h);
2057
+ } else if (!f) {
2058
+ const { scrollTop: h, scrollHeight: p, clientHeight: c } = i;
2059
+ (d.deltaY > 0 && h < p - c || d.deltaY < 0 && h > 0) && (d.preventDefault(), i.scrollTop += d.deltaY);
2060
+ }
2061
+ },
2062
+ { passive: !1, signal: n }
2063
+ ), l.addEventListener(
2064
+ "touchstart",
2065
+ (d) => {
2066
+ d.touches.length === 1 && (this.#w && (cancelAnimationFrame(this.#w), this.#w = 0), this.#A = d.touches[0].clientY, this.#T = d.touches[0].clientX, this.#m = d.touches[0].clientY, this.#v = d.touches[0].clientX, this.#_ = performance.now(), this.#L = i.scrollTop, this.#P = a?.scrollLeft ?? 0, this.#d = 0, this.#u = 0);
2067
+ },
2068
+ { passive: !0, signal: n }
2069
+ ), l.addEventListener(
2070
+ "touchmove",
2071
+ (d) => {
2072
+ if (d.touches.length === 1 && this.#A !== null && this.#T !== null && this.#L !== null && this.#P !== null) {
2073
+ const f = d.touches[0].clientY, h = d.touches[0].clientX, p = performance.now(), c = this.#A - f, u = this.#T - h;
2074
+ if (this.#_ !== null && this.#m !== null && this.#v !== null) {
2075
+ const g = p - this.#_;
2076
+ g > 0 && (this.#d = (this.#m - f) / g, this.#u = (this.#v - h) / g);
2077
+ }
2078
+ this.#m = f, this.#v = h, this.#_ = p;
2079
+ const { scrollTop: b, scrollHeight: w, clientHeight: v } = i, S = w - v, R = c > 0 && b < S || c < 0 && b > 0;
2080
+ let E = !1;
2081
+ if (a) {
2082
+ const { scrollLeft: g, scrollWidth: m, clientWidth: C } = a, _ = m - C;
2083
+ E = u > 0 && g < _ || u < 0 && g > 0;
2084
+ }
2085
+ R && (i.scrollTop = this.#L + c), E && a && (a.scrollLeft = this.#P + u), (R || E) && d.preventDefault();
2086
+ }
2087
+ },
2088
+ { passive: !1, signal: n }
2089
+ ), l.addEventListener(
2090
+ "touchend",
2091
+ () => {
2092
+ (Math.abs(this.#d) > 0.1 || Math.abs(this.#u) > 0.1) && this.#se(i, a), this.#A = null, this.#T = null, this.#L = null, this.#P = null, this.#m = null, this.#v = null, this.#_ = null;
2093
+ },
2094
+ { passive: !0, signal: n }
2095
+ ));
2096
+ }
2097
+ this.#o.addEventListener("mousedown", (l) => this.#re(l), { signal: n }), document.addEventListener("mousemove", (l) => this.#le(l), { signal: n }), document.addEventListener("mouseup", (l) => this.#ae(l), { signal: n }), this._virtualization.enabled && requestAnimationFrame(() => this.refreshVirtualWindow(!0));
2098
+ const r = this.#t.rowHeight;
2099
+ r && r > 0 ? this._virtualization.rowHeight = r : requestAnimationFrame(() => {
2100
+ const l = this._bodyEl?.querySelector(".data-grid-row");
2101
+ if (l) {
2102
+ const a = l.getBoundingClientRect().height;
2103
+ a > 0 && (this._virtualization.rowHeight = a, this.refreshVirtualWindow(!0));
2104
+ }
2105
+ }), this._virtualization.viewportEl && (this.#E = new ResizeObserver(() => {
2106
+ this.#b || (this.#b = requestAnimationFrame(() => {
2107
+ this.#b = 0, this.refreshVirtualWindow(!0), M(this);
2108
+ }));
2109
+ }), this.#E.observe(this._virtualization.viewportEl)), queueMicrotask(() => this.#Z()), requestAnimationFrame(() => requestAnimationFrame(() => this.#$?.()));
2110
+ }
2111
+ // ---------------- Event Emitters ----------------
2112
+ #s(e, o) {
2113
+ this.dispatchEvent(new CustomEvent(e, { detail: o, bubbles: !0, composed: !0 }));
2114
+ }
2115
+ _emitCellCommit(e) {
2116
+ this.#s("cell-commit", e);
2117
+ }
2118
+ _emitRowCommit(e) {
2119
+ this.#s("row-commit", e);
2120
+ }
2121
+ _emitSortChange(e) {
2122
+ this.#s("sort-change", e);
2123
+ }
2124
+ _emitColumnResize(e) {
2125
+ this.#s("column-resize", e);
2126
+ }
2127
+ _emitActivateCell(e) {
2128
+ this.#s("activate-cell", e);
2129
+ }
2130
+ /** Update ARIA selection attributes on rendered rows/cells */
2131
+ #Z() {
2132
+ this._bodyEl?.querySelectorAll(".data-grid-row")?.forEach((o, n) => {
2133
+ const i = n === this._focusRow;
2134
+ o.setAttribute("aria-selected", String(i)), o.querySelectorAll(".cell").forEach((s, r) => {
2135
+ s.setAttribute("aria-selected", String(i && r === this._focusCol));
2136
+ });
2137
+ });
2138
+ }
2139
+ // ---------------- Watch Handlers ----------------
2140
+ #J() {
2141
+ if (!this.#p) return;
2142
+ this.#f(), this.#t.fitMode === "fixed" ? (this.__didInitialAutoSize = !1, te(this)) : (this._columns.forEach((o) => {
2143
+ !o.__userResized && o.__autoSized && delete o.width;
2144
+ }), z(this));
2145
+ }
2146
+ #Q() {
2147
+ this.#p && (this.#f(), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.refreshVirtualWindow(!0));
2148
+ }
2149
+ #ee() {
2150
+ this._rows = Array.isArray(this.#r) ? [...this.#r] : [], this.#O(), this._columns.length > 0 || Array.isArray(this.#t?.columns) && this.#t.columns.length > 0 || Array.isArray(this.#l) && this.#l.length > 0 ? (this.#k(), this.refreshVirtualWindow(!0)) : this.#c();
2151
+ }
2152
+ #te() {
2153
+ K(this), this.#p && (this.#f(), this.#c());
2154
+ }
2155
+ #oe() {
2156
+ this.#p && (this.#f(), this.#G(), this.#O(), this.#k(), q(this), z(this), this.refreshVirtualWindow(!0));
2157
+ }
2158
+ #k() {
2159
+ if (this.#e) {
2160
+ const e = this.#N.length > 0 ? this.#N : this._columns, o = e.filter((s) => !s.hidden), n = e.filter((s) => s.hidden), i = this.#e.processColumns([...o]);
2161
+ if (i !== o) {
2162
+ const s = new Map(i.map((l, a) => [l.field, { col: l, order: a }]));
2163
+ if (!o.some((l) => s.has(l.field)) && i.length > 0)
2164
+ this._columns = [...i, ...n];
2165
+ else {
2166
+ const l = e.map((a) => {
2167
+ if (a.hidden) return a;
2168
+ const d = s.get(a.field);
2169
+ return d ? d.col : a;
2170
+ });
2171
+ this._columns = l;
2172
+ }
2173
+ } else
2174
+ this._columns = [...e];
2175
+ }
2176
+ }
2177
+ /** Recompute row model via plugin hooks (grouping, tree, filtering, etc.). */
2178
+ #O() {
2179
+ K(this);
2180
+ const e = Array.isArray(this.#r) ? [...this.#r] : [], o = this.#e?.processRows(e) ?? e;
2181
+ this._rows = o;
2182
+ }
2183
+ /**
2184
+ * Build the canonical effective configuration by merging all input sources.
2185
+ *
2186
+ * This is the **single source of truth** for the grid's configuration.
2187
+ * All inputs (gridConfig, light DOM, individual props) converge here.
2188
+ *
2189
+ * **Precedence (lowest → highest):**
2190
+ * 1. `gridConfig` property - base config object
2191
+ * 2. Light DOM `<tbw-grid-column>` elements - declarative columns
2192
+ * 3. `columns` property - programmatic columns override
2193
+ * 4. Inferred columns - auto-detected from row data
2194
+ * 5. Individual props (`fitMode`, `editOn`) - convenience overrides
2195
+ *
2196
+ * After this method runs:
2197
+ * - `#effectiveConfig` contains the merged result
2198
+ * - `_columns` is NOT set here (done by #getColumnConfiguration + #processColumns)
2199
+ * - Plugins receive config via their attach() method
2200
+ */
2201
+ #f() {
2202
+ const e = this.#g ? { ...this.#g } : {};
2203
+ let o = Array.isArray(e.columns) ? [...e.columns] : [];
2204
+ const n = (this.__lightDomColumnsCache || []).map((i) => ({
2205
+ ...i
2206
+ }));
2207
+ if (n.length) {
2208
+ const i = {};
2209
+ o.forEach((s) => i[s.field] = s), n.forEach((s) => {
2210
+ const r = i[s.field];
2211
+ r ? (s.header && !r.header && (r.header = s.header), s.type && !r.type && (r.type = s.type), r.sortable = r.sortable || s.sortable, s.resizable && (r.resizable = !0), s.editable && (r.editable = !0)) : (o.push(s), i[s.field] = s);
2212
+ });
2213
+ }
2214
+ if (this.#l && this.#l.length && (o = [...this.#l]), (!o || o.length === 0) && this._rows.length && (o = ue(this._rows).columns), o.length) {
2215
+ o.forEach((r) => {
2216
+ r.sortable === void 0 && (r.sortable = !0), r.resizable === void 0 && (r.resizable = !0);
2217
+ const l = r;
2218
+ l.__originalWidth === void 0 && typeof r.width == "number" && (l.__originalWidth = r.width);
2219
+ });
2220
+ const i = this.#t.columns;
2221
+ i?.some((r) => r.__compiledView || r.__compiledEditor) ? e.columns = i : e.columns = o;
2222
+ } else {
2223
+ const i = this.#t.columns;
2224
+ i?.some((s) => s.__compiledView || s.__compiledEditor) && (e.columns = i);
2225
+ }
2226
+ this.#C && (e.fitMode = this.#C), e.fitMode || (e.fitMode = "stretch"), this.#y && (e.editOn = this.#y), e.rowHeight && e.rowHeight > 0 && (this._virtualization.rowHeight = e.rowHeight), e.columnState && !this.#h && (this.#h = e.columnState), this.#t = e, e.fitMode === "fixed" && this._columns.forEach((i) => {
2227
+ i.width == null && (i.width = 80);
2228
+ }), this.#ne();
2229
+ }
2230
+ /**
2231
+ * Apply animation configuration to CSS custom properties on the host element.
2232
+ * This makes the grid's animation settings available to plugins via CSS variables.
2233
+ */
2234
+ #ne() {
2235
+ const e = {
2236
+ ...me,
2237
+ ...this.#t.animation
2238
+ }, o = e.mode ?? "reduced-motion";
2239
+ let n = 1;
2240
+ o === !1 || o === "off" ? n = 0 : (o === !0 || o === "on") && (n = 1), this.style.setProperty("--tbw-animation-duration", `${e.duration}ms`), this.style.setProperty("--tbw-animation-easing", e.easing ?? "ease-out"), this.style.setProperty("--tbw-animation-enabled", String(n)), this.dataset.animationMode = typeof o == "boolean" ? o ? "on" : "off" : o;
2241
+ }
2242
+ // ---------------- Delegate Wrappers ----------------
2243
+ #q(e, o, n = this.__rowRenderEpoch) {
2244
+ this.#z || (this.#z = (i, s, r) => this.#e?.renderRow(i, s, r) ?? !1), Ne(this, e, o, n, this.#z);
2245
+ }
2246
+ // ---------------- Core Helpers ----------------
2247
+ #c() {
2248
+ if (!this.isConnected || !this._headerRowEl || !this._bodyEl)
2249
+ return;
2250
+ const e = this.#g?.columns || this.#l || [];
2251
+ if (e.length) {
2252
+ const n = new Map(this._columns.filter((s) => s.hidden).map((s) => [s.field, !0])), i = e.map((s) => ({
2253
+ ...s,
2254
+ hidden: n.get(s.field) ?? s.hidden
2255
+ }));
2256
+ this._columns = i;
2257
+ }
2258
+ if (ke(this), this.#f(), this.#G(), this.#N = [...this._columns], this.#O(), this.#k(), this.#h) {
2259
+ const n = this.#h;
2260
+ this.#h = void 0, this.#U(n);
2261
+ }
2262
+ q(this), z(this), this.refreshVirtualWindow(!0), this.#t.fitMode === "fixed" && !this.__didInitialAutoSize && requestAnimationFrame(() => te(this)), this._bodyEl && (this._bodyEl.style.display = "", this._bodyEl.style.gridTemplateColumns = ""), queueMicrotask(() => this.#e?.afterRender());
2263
+ }
2264
+ /** Internal method to apply column state without triggering setup loop */
2265
+ #U(e) {
2266
+ const o = this.#t.columns ?? [], n = this.#e?.getAll() ?? [];
2267
+ we(this, e, o, n);
2268
+ for (const i of e.columns) {
2269
+ const s = o.find((r) => r.field === i.field);
2270
+ s && (s.hidden = !i.visible);
2271
+ }
2272
+ }
2273
+ #ie(e) {
2274
+ if (this.refreshVirtualWindow(!1), this.#e?.onScrollRender(), this.#R) {
2275
+ const o = this._virtualization.container, n = {
2276
+ scrollTop: e,
2277
+ scrollLeft: o?.scrollLeft ?? 0,
2278
+ scrollHeight: o?.scrollHeight ?? 0,
2279
+ scrollWidth: o?.scrollWidth ?? 0,
2280
+ clientHeight: o?.clientHeight ?? 0,
2281
+ clientWidth: o?.clientWidth ?? 0,
2282
+ originalEvent: new Event("scroll")
2283
+ };
2284
+ this.#e?.onScroll(n);
2285
+ }
2286
+ }
2287
+ /**
2288
+ * Find the header row element in the shadow DOM.
2289
+ * Used by plugins that need to access header cells for styling or measurement.
2290
+ * @internal Plugin API
2291
+ */
2292
+ findHeaderRow() {
2293
+ return this.#o.querySelector(".header-row");
2294
+ }
2295
+ /**
2296
+ * Find a rendered row element by its data row index.
2297
+ * Returns null if the row is not currently rendered (virtualized out of view).
2298
+ * Used by plugins that need to access specific row elements for styling or measurement.
2299
+ * @internal Plugin API
2300
+ * @param rowIndex - The data row index (not the DOM position)
2301
+ */
2302
+ findRenderedRowElement(e) {
2303
+ return Array.from(this._bodyEl.querySelectorAll(".data-grid-row")).find((o) => {
2304
+ const n = o.querySelector(".cell[data-row]");
2305
+ return n && Number(n.getAttribute("data-row")) === e;
2306
+ }) || null;
2307
+ }
2308
+ /**
2309
+ * Dispatch a cell click event to the plugin system.
2310
+ * Returns true if any plugin handled the event.
2311
+ */
2312
+ _dispatchCellClick(e, o, n, i) {
2313
+ const s = this._rows[o], r = this._columns[n];
2314
+ if (!s || !r) return !1;
2315
+ const l = {
2316
+ row: s,
2317
+ rowIndex: o,
2318
+ colIndex: n,
2319
+ field: r.field,
2320
+ value: s[r.field],
2321
+ cellEl: i,
2322
+ originalEvent: e
2323
+ };
2324
+ return this.#e?.onCellClick(l) ?? !1;
2325
+ }
2326
+ /**
2327
+ * Dispatch a row click event to the plugin system.
2328
+ * Returns true if any plugin handled the event.
2329
+ */
2330
+ _dispatchRowClick(e, o, n, i) {
2331
+ if (!n) return !1;
2332
+ const s = {
2333
+ rowIndex: o,
2334
+ row: n,
2335
+ rowEl: i,
2336
+ originalEvent: e
2337
+ };
2338
+ return this.#e?.onRowClick(s) ?? !1;
2339
+ }
2340
+ /**
2341
+ * Dispatch a header click event to the plugin system.
2342
+ * Returns true if any plugin handled the event.
2343
+ */
2344
+ _dispatchHeaderClick(e, o, n) {
2345
+ const i = this._columns[o];
2346
+ if (!i) return !1;
2347
+ const s = {
2348
+ colIndex: o,
2349
+ field: i.field,
2350
+ column: i,
2351
+ headerEl: n,
2352
+ originalEvent: e
2353
+ };
2354
+ return this.#e?.onHeaderClick(s) ?? !1;
2355
+ }
2356
+ /**
2357
+ * Dispatch a keyboard event to the plugin system.
2358
+ * Returns true if any plugin handled the event.
2359
+ */
2360
+ _dispatchKeyDown(e) {
2361
+ return this.#e?.onKeyDown(e) ?? !1;
2362
+ }
2363
+ /**
2364
+ * Get horizontal scroll boundary offsets from plugins.
2365
+ * Used by keyboard navigation to ensure focused cells are fully visible
2366
+ * when plugins like pinned columns obscure part of the scroll area.
2367
+ */
2368
+ _getHorizontalScrollOffsets(e, o) {
2369
+ return this.#e?.getHorizontalScrollOffsets(e, o) ?? { left: 0, right: 0 };
2370
+ }
2371
+ /**
2372
+ * Query all plugins with a generic query and collect responses.
2373
+ * This enables inter-plugin communication without the core knowing plugin-specific concepts.
2374
+ * @internal Plugin API
2375
+ *
2376
+ * @example
2377
+ * // Check if any plugin vetoes moving a column
2378
+ * const responses = grid.queryPlugins<boolean>({ type: PLUGIN_QUERIES.CAN_MOVE_COLUMN, context: column });
2379
+ * const canMove = !responses.includes(false);
2380
+ */
2381
+ queryPlugins(e) {
2382
+ return this.#e?.queryPlugins(e) ?? [];
2383
+ }
2384
+ /**
2385
+ * Build a CellMouseEvent from a native MouseEvent.
2386
+ * Extracts cell/row information from the event target.
2387
+ */
2388
+ #B(e, o) {
2389
+ let n = null;
2390
+ const i = e.composedPath?.();
2391
+ if (i && i.length > 0 ? n = i[0] : n = e.target, n && !this.#o.contains(n)) {
2392
+ const u = this.#o.elementFromPoint(e.clientX, e.clientY);
2393
+ u && (n = u);
2394
+ }
2395
+ const s = n?.closest?.("[data-col]"), r = n?.closest?.(".data-grid-row"), l = n?.closest?.(".header-row");
2396
+ let a, d, f, h, p, c;
2397
+ return s && (a = parseInt(s.getAttribute("data-row") ?? "-1", 10), d = parseInt(s.getAttribute("data-col") ?? "-1", 10), a >= 0 && d >= 0 && (f = this._rows[a], c = this._columns[d], h = c?.field, p = f && h ? f[h] : void 0)), {
2398
+ type: o,
2399
+ row: f,
2400
+ rowIndex: a !== void 0 && a >= 0 ? a : void 0,
2401
+ colIndex: d !== void 0 && d >= 0 ? d : void 0,
2402
+ field: h,
2403
+ value: p,
2404
+ column: c,
2405
+ originalEvent: e,
2406
+ cellElement: s ?? void 0,
2407
+ rowElement: r ?? void 0,
2408
+ isHeader: !!l,
2409
+ cell: a !== void 0 && d !== void 0 && a >= 0 && d >= 0 ? { row: a, col: d } : void 0
2410
+ };
2411
+ }
2412
+ /**
2413
+ * Apply momentum scrolling animation after touch release.
2414
+ * Decelerates smoothly until velocity drops below threshold.
2415
+ */
2416
+ #se(e, o) {
2417
+ const s = () => {
2418
+ this.#d *= 0.95, this.#u *= 0.95;
2419
+ const r = this.#d * 16, l = this.#u * 16;
2420
+ Math.abs(this.#d) > 0.01 && (e.scrollTop += r), Math.abs(this.#u) > 0.01 && o && (o.scrollLeft += l), Math.abs(this.#d) > 0.01 || Math.abs(this.#u) > 0.01 ? this.#w = requestAnimationFrame(s) : this.#w = 0;
2421
+ };
2422
+ this.#w = requestAnimationFrame(s);
2423
+ }
2424
+ /**
2425
+ * Handle mousedown events and dispatch to plugin system.
2426
+ */
2427
+ #re(e) {
2428
+ const o = this.#B(e, "mousedown");
2429
+ (this.#e?.onCellMouseDown(o) ?? !1) && (this.#x = !0);
2430
+ }
2431
+ /**
2432
+ * Handle mousemove events (only when dragging).
2433
+ */
2434
+ #le(e) {
2435
+ if (!this.#x) return;
2436
+ const o = this.#B(e, "mousemove");
2437
+ this.#e?.onCellMouseMove(o);
2438
+ }
2439
+ /**
2440
+ * Handle mouseup events.
2441
+ */
2442
+ #ae(e) {
2443
+ if (!this.#x) return;
2444
+ const o = this.#B(e, "mouseup");
2445
+ this.#e?.onCellMouseUp(o), this.#x = !1;
2446
+ }
2447
+ // API consumed by internal utils (rows.ts)
2448
+ get changedRows() {
2449
+ return Array.from(this._changedRowIndices).map((e) => this._rows[e]);
2450
+ }
2451
+ get changedRowIndices() {
2452
+ return Array.from(this._changedRowIndices);
2453
+ }
2454
+ async resetChangedRows(e) {
2455
+ this._changedRowIndices.clear(), e || this.#s("changed-rows-reset", { rows: this.changedRows, indices: this.changedRowIndices }), this._rowPool.forEach((o) => o.classList.remove("changed"));
2456
+ }
2457
+ async beginBulkEdit(e) {
2458
+ if (!this._columns.some((s) => s.editable)) return;
2459
+ const n = this._rows[e];
2460
+ B(this, e, n);
2461
+ const i = this.findRenderedRowElement?.(e);
2462
+ i && (Array.from(i.children).forEach((s, r) => {
2463
+ const l = this._visibleColumns[r];
2464
+ if (l?.editable) {
2465
+ const a = s;
2466
+ a.classList.contains("editing") || k(this, n, e, l, a);
2467
+ }
2468
+ }), queueMicrotask(() => {
2469
+ const s = i.querySelector(`.cell[data-col="${this._focusCol}"]`);
2470
+ if (s?.classList.contains("editing")) {
2471
+ const r = s.querySelector(
2472
+ 'input,select,textarea,[contenteditable="true"],[contenteditable=""],[tabindex]:not([tabindex="-1"])'
2473
+ );
2474
+ try {
2475
+ r?.focus();
2476
+ } catch {
2477
+ }
2478
+ }
2479
+ }));
2480
+ }
2481
+ async commitActiveRowEdit() {
2482
+ this._activeEditRows !== -1 && D(this, this._activeEditRows, !1);
2483
+ }
2484
+ async ready() {
2485
+ return this.#I;
2486
+ }
2487
+ async forceLayout() {
2488
+ this.#c(), await new Promise((e) => requestAnimationFrame(() => requestAnimationFrame(e)));
2489
+ }
2490
+ /** Public method: returns a frozen snapshot of the merged effective configuration */
2491
+ async getConfig() {
2492
+ return Object.freeze({ ...this.#t || {} });
2493
+ }
2494
+ // ---------------- Column Visibility API ----------------
2495
+ /**
2496
+ * Set the visibility of a column.
2497
+ * @param field - The field name of the column
2498
+ * @param visible - Whether the column should be visible
2499
+ * @returns True if visibility was changed, false if column not found or locked
2500
+ */
2501
+ setColumnVisible(e, o) {
2502
+ const n = this.#t.columns, i = n?.find((l) => l.field === e);
2503
+ if (!i || !o && i.lockVisible || !o && (n ?? []).filter((a) => !a.hidden && a.field !== e).length === 0)
2504
+ return !1;
2505
+ const s = !!i.hidden, r = !o;
2506
+ return s !== r ? (i.hidden = r, this.#s("column-visibility", {
2507
+ field: e,
2508
+ visible: o,
2509
+ visibleColumns: (n ?? []).filter((l) => !l.hidden).map((l) => l.field)
2510
+ }), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.#c(), this.requestStateChange(), !0) : !1;
2511
+ }
2512
+ /**
2513
+ * Toggle the visibility of a column.
2514
+ * @param field - The field name of the column
2515
+ * @returns True if visibility was toggled, false if column not found or locked
2516
+ */
2517
+ toggleColumnVisibility(e) {
2518
+ const i = !!this.#t.columns?.find((s) => s.field === e)?.hidden;
2519
+ return this.setColumnVisible(e, i);
2520
+ }
2521
+ /**
2522
+ * Check if a column is currently visible.
2523
+ * @param field - The field name of the column
2524
+ * @returns True if visible, false if hidden or not found
2525
+ */
2526
+ isColumnVisible(e) {
2527
+ const n = this.#t.columns?.find((i) => i.field === e);
2528
+ return n ? !n.hidden : !1;
2529
+ }
2530
+ /**
2531
+ * Show all columns.
2532
+ */
2533
+ showAllColumns() {
2534
+ const e = this.#t.columns;
2535
+ e?.some((n) => n.hidden) && (e?.forEach((n) => {
2536
+ n.hidden = !1;
2537
+ }), this.#s("column-visibility", {
2538
+ visibleColumns: (e ?? []).map((n) => n.field)
2539
+ }), this._rowPool.length = 0, this._bodyEl && (this._bodyEl.innerHTML = ""), this.__rowRenderEpoch++, this.#c(), this.requestStateChange());
2540
+ }
2541
+ /**
2542
+ * Get list of all column fields (including hidden).
2543
+ * Returns columns reflecting current display order (after reordering).
2544
+ * Hidden columns are interleaved at their original relative positions.
2545
+ * @returns Array of all field names with their visibility status
2546
+ */
2547
+ getAllColumns() {
2548
+ return (this.#t.columns ?? []).map((o) => ({
2549
+ field: o.field,
2550
+ header: o.header || o.field,
2551
+ visible: !o.hidden,
2552
+ lockVisible: o.lockVisible
2553
+ }));
2554
+ }
2555
+ /**
2556
+ * Reorder columns according to the specified field order.
2557
+ * This directly updates _columns in place without going through processColumns.
2558
+ * @param order - Array of field names in the desired order
2559
+ */
2560
+ setColumnOrder(e) {
2561
+ if (!e.length) return;
2562
+ const o = new Map(this._columns.map((i) => [i.field, i])), n = [];
2563
+ for (const i of e) {
2564
+ const s = o.get(i);
2565
+ s && (n.push(s), o.delete(i));
2566
+ }
2567
+ for (const i of o.values())
2568
+ n.push(i);
2569
+ this._columns = n, q(this), z(this), this.refreshVirtualWindow(!0);
2570
+ }
2571
+ /**
2572
+ * Get the current column order as an array of field names.
2573
+ * @returns Array of field names in display order
2574
+ */
2575
+ getColumnOrder() {
2576
+ return this._columns.map((e) => e.field);
2577
+ }
2578
+ // ---------------- Column State API ----------------
2579
+ /**
2580
+ * Get the current column state, including order, width, visibility, sort, and plugin state.
2581
+ * Returns a serializable object suitable for localStorage or database storage.
2582
+ */
2583
+ getColumnState() {
2584
+ const e = this.#e?.getAll() ?? [];
2585
+ return de(this, e);
2586
+ }
2587
+ /**
2588
+ * Set the column state, restoring order, width, visibility, sort, and plugin state.
2589
+ * Use this to restore previously saved column state.
2590
+ */
2591
+ set columnState(e) {
2592
+ e && (this.#h = e, this.#M && this.#ce(e));
2593
+ }
2594
+ /**
2595
+ * Get the current column state.
2596
+ */
2597
+ get columnState() {
2598
+ return this.getColumnState();
2599
+ }
2600
+ /**
2601
+ * Apply column state internally.
2602
+ */
2603
+ #ce(e) {
2604
+ (this.#t.columns ?? []).forEach((n) => {
2605
+ n.hidden = !1;
2606
+ }), this.#U(e), this.#c();
2607
+ }
2608
+ /**
2609
+ * Request a state change event to be emitted.
2610
+ * Called internally after resize, reorder, visibility, or sort changes.
2611
+ * Plugins should call this after changing their state.
2612
+ * The event is debounced to avoid excessive events during drag operations.
2613
+ * @internal Plugin API
2614
+ */
2615
+ requestStateChange() {
2616
+ this.#D || (this.#D = ge(
2617
+ this,
2618
+ () => this.#e?.getAll() ?? [],
2619
+ (e) => this.#s("column-state-change", e)
2620
+ )), this.#D();
2621
+ }
2622
+ /**
2623
+ * Reset column state to initial configuration.
2624
+ * Clears all user modifications (order, width, visibility, sort).
2625
+ */
2626
+ resetColumnState() {
2627
+ this.#h = void 0, (this.#t.columns ?? []).forEach((n) => {
2628
+ n.hidden = !1;
2629
+ }), this._sortState = null, this.__originalOrder = [], this.#f(), this.#c();
2630
+ const o = this.#e?.getAll() ?? [];
2631
+ for (const n of o)
2632
+ if (n.applyColumnState)
2633
+ for (const i of this._columns)
2634
+ n.applyColumnState(i.field, {
2635
+ field: i.field,
2636
+ order: 0,
2637
+ visible: !0
2638
+ });
2639
+ this.requestStateChange();
2640
+ }
2641
+ // ---------------- Shell / Tool Panel API ----------------
2642
+ // These methods delegate to ShellController for implementation.
2643
+ // The controller encapsulates all tool panel logic while grid.ts
2644
+ // exposes the public API surface.
2645
+ /** Check if the tool panel is currently open. */
2646
+ get isToolPanelOpen() {
2647
+ return this.#n.isPanelOpen;
2648
+ }
2649
+ /**
2650
+ * Get the currently active tool panel ID, or null if none is open.
2651
+ * @deprecated Use isToolPanelOpen and expandedToolPanelSections instead.
2652
+ */
2653
+ get activeToolPanel() {
2654
+ return this.#n.activePanel;
2655
+ }
2656
+ /** Get the IDs of expanded accordion sections. */
2657
+ get expandedToolPanelSections() {
2658
+ return this.#n.expandedSections;
2659
+ }
2660
+ /** Open the tool panel (accordion view with all registered panels). */
2661
+ openToolPanel() {
2662
+ this.#n.openToolPanel();
2663
+ }
2664
+ /** Close the tool panel. */
2665
+ closeToolPanel() {
2666
+ this.#n.closeToolPanel();
2667
+ }
2668
+ /** Toggle the tool panel open/closed. */
2669
+ toggleToolPanel() {
2670
+ this.#n.toggleToolPanel();
2671
+ }
2672
+ /** Toggle an accordion section expanded/collapsed. */
2673
+ toggleToolPanelSection(e) {
2674
+ this.#n.toggleToolPanelSection(e);
2675
+ }
2676
+ /** Get registered tool panel definitions. */
2677
+ getToolPanels() {
2678
+ return this.#n.getToolPanels();
2679
+ }
2680
+ /** Register a custom tool panel (without creating a plugin). */
2681
+ registerToolPanel(e) {
2682
+ this.#n.registerToolPanel(e);
2683
+ }
2684
+ /** Unregister a custom tool panel. */
2685
+ unregisterToolPanel(e) {
2686
+ this.#n.unregisterToolPanel(e);
2687
+ }
2688
+ /** Get registered header content definitions. */
2689
+ getHeaderContents() {
2690
+ return this.#n.getHeaderContents();
2691
+ }
2692
+ /** Register custom header content (without creating a plugin). */
2693
+ registerHeaderContent(e) {
2694
+ this.#n.registerHeaderContent(e);
2695
+ }
2696
+ /** Unregister custom header content. */
2697
+ unregisterHeaderContent(e) {
2698
+ this.#n.unregisterHeaderContent(e);
2699
+ }
2700
+ /** Get all registered toolbar buttons. */
2701
+ getToolbarButtons() {
2702
+ return this.#n.getToolbarButtons();
2703
+ }
2704
+ /** Register a custom toolbar button programmatically. */
2705
+ registerToolbarButton(e) {
2706
+ this.#n.registerToolbarButton(e);
2707
+ }
2708
+ /** Unregister a custom toolbar button. */
2709
+ unregisterToolbarButton(e) {
2710
+ this.#n.unregisterToolbarButton(e);
2711
+ }
2712
+ /** Enable/disable a toolbar button by ID. */
2713
+ setToolbarButtonDisabled(e, o) {
2714
+ this.#n.setToolbarButtonDisabled(e, o);
2715
+ }
2716
+ /**
2717
+ * Re-parse light DOM shell elements and refresh shell header.
2718
+ * Call this after dynamically modifying <tbw-grid-header> children.
2719
+ */
2720
+ refreshShellHeader() {
2721
+ re(this, this.#i), this.#X(), this.#F();
2722
+ }
2723
+ // ---------------- Virtual Window ----------------
2724
+ /**
2725
+ * Core virtualization routine. Chooses between bypass (small datasets), grouped window rendering,
2726
+ * or standard row window rendering.
2727
+ * @internal Plugin API
2728
+ */
2729
+ refreshVirtualWindow(e = !1) {
2730
+ if (!this._bodyEl) return;
2731
+ const o = this._rows.length;
2732
+ if (!this._virtualization.enabled) {
2733
+ this.#q(0, o), this.#e?.afterRender();
2734
+ return;
2735
+ }
2736
+ if (this._rows.length <= this._virtualization.bypassThreshold) {
2737
+ if (this._virtualization.start = 0, this._virtualization.end = o, this._bodyEl.style.transform = "translateY(0px)", this.#q(0, o, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch), this._virtualization.totalHeightEl) {
2738
+ const C = this.#o.querySelector(".tbw-scroll-area"), _ = C ? C.offsetHeight - C.clientHeight : 0;
2739
+ this._virtualization.totalHeightEl.style.height = `${o * this._virtualization.rowHeight + _}px`;
2740
+ }
2741
+ const m = this.#o.querySelector(".rows-body");
2742
+ m?.setAttribute("aria-rowcount", String(o)), m?.setAttribute("aria-colcount", String(this._visibleColumns.length)), this.#e?.afterRender();
2743
+ return;
2744
+ }
2745
+ const n = this._virtualization.container ?? this, s = (this._virtualization.viewportEl ?? n).clientHeight, r = this._virtualization.rowHeight, l = n.scrollTop;
2746
+ let a = Math.floor(l / r), d = 0;
2747
+ const f = 10;
2748
+ for (; d < f; ) {
2749
+ const m = this.#e?.getExtraHeightBefore?.(a) ?? 0, C = Math.floor((l - m) / r);
2750
+ if (C >= a || C < 0) break;
2751
+ a = C, d++;
2752
+ }
2753
+ a = a - a % 2, a < 0 && (a = 0);
2754
+ const h = this.#e?.adjustVirtualStart(a, l, r);
2755
+ h !== void 0 && h < a && (a = h, a = a - a % 2, a < 0 && (a = 0));
2756
+ const p = Math.ceil(s / r) + 3;
2757
+ let c = a + p;
2758
+ c > o && (c = o), this._virtualization.start = a, this._virtualization.end = c;
2759
+ const b = this.#o.querySelector(".tbw-footer")?.offsetHeight ?? 0, w = this.#e?.getExtraHeight() ?? 0, v = this.#o.querySelector(".tbw-scroll-area"), S = v ? v.offsetHeight - v.clientHeight : 0;
2760
+ this._virtualization.totalHeightEl && (this._virtualization.totalHeightEl.style.height = `${o * r + r + b + w + S}px`);
2761
+ const R = this.#e?.getExtraHeightBefore?.(a) ?? 0, E = -(l - a * r - R);
2762
+ this._bodyEl.style.transform = `translateY(${E}px)`, this.#q(a, c, e ? ++this.__rowRenderEpoch : this.__rowRenderEpoch);
2763
+ const g = this.#o.querySelector(".rows-body");
2764
+ g?.setAttribute("aria-rowcount", String(o)), g?.setAttribute("aria-colcount", String(this._visibleColumns.length)), e && this.#e?.afterRender();
2765
+ }
2766
+ // ---------------- Render ----------------
2767
+ #X() {
2768
+ re(this, this.#i);
2769
+ const e = this.#t?.shell, o = Ve(e, this.#i), n = `
2770
+ <div class="tbw-scroll-area">
2771
+ <div class="rows-body-wrapper">
2772
+ <div class="rows-body" role="grid">
2773
+ <div class="header">
2774
+ <div class="header-row" part="header-row"></div>
2775
+ </div>
2776
+ <div class="rows-container">
2777
+ <div class="rows-viewport">
2778
+ <div class="rows"></div>
2779
+ </div>
2780
+ </div>
2781
+ </div>
2782
+ </div>
2783
+ </div>
2784
+ <div class="faux-vscroll">
2785
+ <div class="faux-vscroll-spacer"></div>
2786
+ </div>
2787
+ `;
2788
+ if (o) {
2789
+ const i = this.#t?.icons?.toolPanel ?? H.toolPanel, s = {
2790
+ expand: this.#t?.icons?.expand ?? H.expand,
2791
+ collapse: this.#t?.icons?.collapse ?? H.collapse
2792
+ }, r = Ge(e, this.#i, i), l = Fe(e, this.#i, n, s);
2793
+ this.#o.innerHTML = `
2794
+ <div class="tbw-grid-root has-shell">
2795
+ ${r}
2796
+ ${l}
2797
+ </div>
2798
+ `, this.#de(), this.#n.setInitialized(!0);
2799
+ } else
2800
+ this.#o.innerHTML = `
2801
+ <div class="tbw-grid-root">
2802
+ <div class="tbw-grid-content">
2803
+ ${n}
2804
+ </div>
2805
+ </div>
2806
+ `;
2807
+ }
2808
+ /**
2809
+ * Set up shell event listeners after render.
2810
+ */
2811
+ #de() {
2812
+ Ue(this.#o, this.#t?.shell, this.#i, {
2813
+ onPanelToggle: () => this.toggleToolPanel(),
2814
+ onSectionToggle: (e) => this.toggleToolPanelSection(e),
2815
+ onToolbarButtonClick: (e) => this.#ue(e)
2816
+ }), this.#H?.(), this.#H = Xe(this.#o, this.#t?.shell, (e) => {
2817
+ this.style.setProperty("--tbw-tool-panel-width", `${e}px`);
2818
+ });
2819
+ }
2820
+ /**
2821
+ * Handle toolbar button click (for config buttons with action).
2822
+ */
2823
+ #ue(e) {
2824
+ const n = (this.#t?.shell?.header?.toolbarButtons ?? []).find((s) => s.id === e);
2825
+ if (n?.action) {
2826
+ n.action();
2827
+ return;
2828
+ }
2829
+ const i = this.#i.toolbarButtons.get(e);
2830
+ i?.action && i.action();
2831
+ }
2832
+ }
2833
+ customElements.get(W.tagName) || customElements.define(W.tagName, W);
2834
+ const ot = {
2835
+ /** Ask if a column can be moved. Context: ColumnConfig. Response: boolean | undefined */
2836
+ CAN_MOVE_COLUMN: "canMoveColumn",
2837
+ /** Get context menu items. Context: ContextMenuParams. Response: ContextMenuItem[] */
2838
+ GET_CONTEXT_MENU_ITEMS: "getContextMenuItems"
2839
+ };
2840
+ class nt {
2841
+ /** Plugin version - override in subclass if needed */
2842
+ version = "1.0.0";
2843
+ /** CSS styles to inject into the grid's shadow DOM */
2844
+ styles;
2845
+ /** Custom cell renderers keyed by type name */
2846
+ cellRenderers;
2847
+ /** Custom header renderers keyed by type name */
2848
+ headerRenderers;
2849
+ /** Custom cell editors keyed by type name */
2850
+ cellEditors;
2851
+ /** The grid instance this plugin is attached to */
2852
+ grid;
2853
+ /** Plugin configuration - merged with defaults in attach() */
2854
+ config;
2855
+ /** User-provided configuration from constructor */
2856
+ userConfig;
2857
+ /**
2858
+ * Default configuration - subclasses should override this getter.
2859
+ * Note: This must be a getter (not property initializer) for proper inheritance
2860
+ * since property initializers run after parent constructor.
2861
+ */
2862
+ get defaultConfig() {
2863
+ return {};
2864
+ }
2865
+ constructor(e = {}) {
2866
+ this.userConfig = e;
2867
+ }
2868
+ /**
2869
+ * Called when the plugin is attached to a grid.
2870
+ * Override to set up event listeners, initialize state, etc.
2871
+ */
2872
+ attach(e) {
2873
+ this.grid = e, this.config = { ...this.defaultConfig, ...this.userConfig };
2874
+ }
2875
+ /**
2876
+ * Called when the plugin is detached from a grid.
2877
+ * Override to clean up event listeners, timers, etc.
2878
+ */
2879
+ detach() {
2880
+ }
2881
+ /**
2882
+ * Get another plugin instance from the same grid.
2883
+ * Use for inter-plugin communication.
2884
+ */
2885
+ getPlugin(e) {
2886
+ return this.grid?.getPlugin(e);
2887
+ }
2888
+ /**
2889
+ * Emit a custom event from the grid.
2890
+ */
2891
+ emit(e, o) {
2892
+ this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: o, bubbles: !0 }));
2893
+ }
2894
+ /**
2895
+ * Request a re-render of the grid.
2896
+ */
2897
+ requestRender() {
2898
+ this.grid?.requestRender?.();
2899
+ }
2900
+ /**
2901
+ * Request a lightweight style update without rebuilding DOM.
2902
+ * Use this instead of requestRender() when only CSS classes need updating.
2903
+ */
2904
+ requestAfterRender() {
2905
+ this.grid?.requestAfterRender?.();
2906
+ }
2907
+ /**
2908
+ * Get the current rows from the grid.
2909
+ */
2910
+ get rows() {
2911
+ return this.grid?.rows ?? [];
2912
+ }
2913
+ /**
2914
+ * Get the original unfiltered/unprocessed rows from the grid.
2915
+ * Use this when you need all source data regardless of active filters.
2916
+ */
2917
+ get sourceRows() {
2918
+ return this.grid?.sourceRows ?? [];
2919
+ }
2920
+ /**
2921
+ * Get the current columns from the grid.
2922
+ */
2923
+ get columns() {
2924
+ return this.grid?.columns ?? [];
2925
+ }
2926
+ /**
2927
+ * Get only visible columns from the grid (excludes hidden).
2928
+ * Use this for rendering that needs to match the grid template.
2929
+ */
2930
+ get visibleColumns() {
2931
+ return this.grid?._visibleColumns ?? [];
2932
+ }
2933
+ /**
2934
+ * Get the shadow root of the grid.
2935
+ */
2936
+ get shadowRoot() {
2937
+ return this.grid?.shadowRoot ?? null;
2938
+ }
2939
+ /**
2940
+ * Get the disconnect signal for event listener cleanup.
2941
+ * This signal is aborted when the grid disconnects from the DOM.
2942
+ * Use this when adding event listeners that should be cleaned up automatically.
2943
+ *
2944
+ * Best for:
2945
+ * - Document/window-level listeners added in attach()
2946
+ * - Listeners on the grid element itself
2947
+ * - Any listener that should persist across renders
2948
+ *
2949
+ * Not needed for:
2950
+ * - Listeners on elements created in afterRender() (removed with element)
2951
+ *
2952
+ * @example
2953
+ * element.addEventListener('click', handler, { signal: this.disconnectSignal });
2954
+ * document.addEventListener('keydown', handler, { signal: this.disconnectSignal });
2955
+ */
2956
+ get disconnectSignal() {
2957
+ return this.grid?.disconnectSignal;
2958
+ }
2959
+ /**
2960
+ * Get the grid-level icons configuration.
2961
+ * Returns merged icons (user config + defaults).
2962
+ */
2963
+ get gridIcons() {
2964
+ const e = this.grid?.gridConfig?.icons ?? {};
2965
+ return { ...H, ...e };
2966
+ }
2967
+ /**
2968
+ * Resolve an icon value to string or HTMLElement.
2969
+ * Checks plugin config first, then grid-level icons, then defaults.
2970
+ *
2971
+ * @param iconKey - The icon key in GridIcons (e.g., 'expand', 'collapse')
2972
+ * @param pluginOverride - Optional plugin-level override
2973
+ * @returns The resolved icon value
2974
+ */
2975
+ resolveIcon(e, o) {
2976
+ return o !== void 0 ? o : this.gridIcons[e];
2977
+ }
2978
+ /**
2979
+ * Set an icon value on an element.
2980
+ * Handles both string (text/HTML) and HTMLElement values.
2981
+ *
2982
+ * @param element - The element to set the icon on
2983
+ * @param icon - The icon value (string or HTMLElement)
2984
+ */
2985
+ setIcon(e, o) {
2986
+ typeof o == "string" ? e.innerHTML = o : o instanceof HTMLElement && (e.innerHTML = "", e.appendChild(o.cloneNode(!0)));
2987
+ }
2988
+ /**
2989
+ * Log a warning message.
2990
+ */
2991
+ warn(e) {
2992
+ console.warn(`[tbw-grid:${this.name}] ${e}`);
2993
+ }
2994
+ // #endregion
2995
+ }
2996
+ const T = {
2997
+ // ─── Core Structure ───────────────────────────────────────────────
2998
+ ROOT: "tbw-grid-root",
2999
+ HEADER: "header",
3000
+ HEADER_ROW: "header-row",
3001
+ HEADER_CELL: "header-cell",
3002
+ // Body structure
3003
+ ROWS_VIEWPORT: "rows-viewport",
3004
+ ROWS_SPACER: "rows-spacer",
3005
+ ROWS_CONTAINER: "rows",
3006
+ // Row elements
3007
+ DATA_ROW: "data-row",
3008
+ GROUP_ROW: "group-row",
3009
+ // Cell elements
3010
+ DATA_CELL: "data-cell",
3011
+ // ─── Core States ──────────────────────────────────────────────────
3012
+ SELECTED: "selected",
3013
+ FOCUSED: "focused",
3014
+ EDITING: "editing",
3015
+ EXPANDED: "expanded",
3016
+ COLLAPSED: "collapsed",
3017
+ DRAGGING: "dragging",
3018
+ RESIZING: "resizing",
3019
+ // Sorting (core feature)
3020
+ SORTABLE: "sortable",
3021
+ SORTED_ASC: "sorted-asc",
3022
+ SORTED_DESC: "sorted-desc",
3023
+ // Visibility
3024
+ HIDDEN: "hidden",
3025
+ // ─── Shared Classes (used by plugins, styled by core CSS) ────────
3026
+ // These are defined here because core CSS provides the base styling.
3027
+ // Plugins apply these classes; core CSS defines how they look.
3028
+ // Sticky positioning (PinnedColumnsPlugin applies, core CSS styles)
3029
+ STICKY_LEFT: "sticky-left",
3030
+ STICKY_RIGHT: "sticky-right",
3031
+ // Pinned rows (PinnedRowsPlugin applies, core CSS styles)
3032
+ PINNED_TOP: "pinned-top",
3033
+ PINNED_BOTTOM: "pinned-bottom",
3034
+ // Tree structure (TreePlugin applies, core CSS styles)
3035
+ TREE_TOGGLE: "tree-toggle",
3036
+ TREE_INDENT: "tree-indent",
3037
+ // Grouping (GroupingRowsPlugin applies, core CSS styles)
3038
+ GROUP_TOGGLE: "group-toggle",
3039
+ GROUP_LABEL: "group-label",
3040
+ GROUP_COUNT: "group-count",
3041
+ // Selection (SelectionPlugin applies, core CSS styles)
3042
+ RANGE_SELECTION: "range-selection",
3043
+ SELECTION_OVERLAY: "selection-overlay"
3044
+ }, G = {
3045
+ // ─── Core Attributes ──────────────────────────────────────────────
3046
+ ROW_INDEX: "data-row-index",
3047
+ COL_INDEX: "data-col-index",
3048
+ FIELD: "data-field",
3049
+ // ─── Shared Attributes (used by plugins) ──────────────────────────
3050
+ GROUP_KEY: "data-group-key",
3051
+ // GroupingRowsPlugin
3052
+ TREE_LEVEL: "data-tree-level",
3053
+ // TreePlugin
3054
+ STICKY: "data-sticky"
3055
+ // PinnedColumnsPlugin
3056
+ }, it = {
3057
+ ROOT: `.${T.ROOT}`,
3058
+ HEADER: `.${T.HEADER}`,
3059
+ HEADER_ROW: `.${T.HEADER_ROW}`,
3060
+ HEADER_CELL: `.${T.HEADER_CELL}`,
3061
+ ROWS_VIEWPORT: `.${T.ROWS_VIEWPORT}`,
3062
+ ROWS_CONTAINER: `.${T.ROWS_CONTAINER}`,
3063
+ DATA_ROW: `.${T.DATA_ROW}`,
3064
+ DATA_CELL: `.${T.DATA_CELL}`,
3065
+ GROUP_ROW: `.${T.GROUP_ROW}`,
3066
+ // By data attribute
3067
+ ROW_BY_INDEX: (t) => `.${T.DATA_ROW}[${G.ROW_INDEX}="${t}"]`,
3068
+ CELL_BY_FIELD: (t) => `.${T.DATA_CELL}[${G.FIELD}="${t}"]`,
3069
+ CELL_AT: (t, e) => `.${T.DATA_ROW}[${G.ROW_INDEX}="${t}"] .${T.DATA_CELL}[${G.COL_INDEX}="${e}"]`,
3070
+ // State selectors
3071
+ SELECTED_ROWS: `.${T.DATA_ROW}.${T.SELECTED}`,
3072
+ EDITING_CELL: `.${T.DATA_CELL}.${T.EDITING}`
3073
+ }, st = {
3074
+ // Colors
3075
+ COLOR_BG: "--tbw-color-bg",
3076
+ COLOR_FG: "--tbw-color-fg",
3077
+ COLOR_FG_MUTED: "--tbw-color-fg-muted",
3078
+ COLOR_BORDER: "--tbw-color-border",
3079
+ COLOR_ACCENT: "--tbw-color-accent",
3080
+ COLOR_HEADER_BG: "--tbw-color-header-bg",
3081
+ COLOR_HEADER_FG: "--tbw-color-header-fg",
3082
+ COLOR_SELECTION: "--tbw-color-selection",
3083
+ COLOR_ROW_HOVER: "--tbw-color-row-hover",
3084
+ COLOR_ROW_ALT: "--tbw-color-row-alt",
3085
+ // Sizing
3086
+ ROW_HEIGHT: "--tbw-row-height",
3087
+ HEADER_HEIGHT: "--tbw-header-height",
3088
+ CELL_PADDING: "--tbw-cell-padding",
3089
+ // Typography
3090
+ FONT_FAMILY: "--tbw-font-family",
3091
+ FONT_SIZE: "--tbw-font-size",
3092
+ // Borders
3093
+ BORDER_RADIUS: "--tbw-border-radius",
3094
+ FOCUS_OUTLINE: "--tbw-focus-outline"
3095
+ }, rt = {
3096
+ CELL_COMMIT: "cell-commit",
3097
+ ROW_COMMIT: "row-commit",
3098
+ CHANGED_ROWS_RESET: "changed-rows-reset",
3099
+ MOUNT_EXTERNAL_VIEW: "mount-external-view",
3100
+ MOUNT_EXTERNAL_EDITOR: "mount-external-editor",
3101
+ SORT_CHANGE: "sort-change",
3102
+ COLUMN_RESIZE: "column-resize",
3103
+ ACTIVATE_CELL: "activate-cell",
3104
+ GROUP_TOGGLE: "group-toggle",
3105
+ COLUMN_STATE_CHANGE: "column-state-change"
3106
+ }, lt = {
3107
+ // Selection plugin
3108
+ SELECTION_CHANGE: "selection-change",
3109
+ // Tree plugin
3110
+ TREE_EXPAND: "tree-expand",
3111
+ // Filtering plugin
3112
+ FILTER_CHANGE: "filter-change",
3113
+ // Sorting plugin
3114
+ SORT_MODEL_CHANGE: "sort-model-change",
3115
+ // Export plugin
3116
+ EXPORT_START: "export-start",
3117
+ EXPORT_COMPLETE: "export-complete",
3118
+ // Clipboard plugin
3119
+ CLIPBOARD_COPY: "clipboard-copy",
3120
+ CLIPBOARD_PASTE: "clipboard-paste",
3121
+ // Context menu plugin
3122
+ CONTEXT_MENU_OPEN: "context-menu-open",
3123
+ CONTEXT_MENU_CLOSE: "context-menu-close",
3124
+ // Undo/Redo plugin
3125
+ HISTORY_CHANGE: "history-change",
3126
+ // Server-side plugin
3127
+ SERVER_LOADING: "server-loading",
3128
+ SERVER_ERROR: "server-error",
3129
+ // Visibility plugin
3130
+ COLUMN_VISIBILITY_CHANGE: "column-visibility-change",
3131
+ // Reorder plugin
3132
+ COLUMN_REORDER: "column-reorder",
3133
+ // Master-detail plugin
3134
+ DETAIL_EXPAND: "detail-expand",
3135
+ // Grouping rows plugin
3136
+ GROUP_EXPAND: "group-expand"
3137
+ }, Y = {
3138
+ sum: (t, e) => t.reduce((o, n) => o + (Number(n[e]) || 0), 0),
3139
+ avg: (t, e) => {
3140
+ const o = t.reduce((n, i) => n + (Number(i[e]) || 0), 0);
3141
+ return t.length ? o / t.length : 0;
3142
+ },
3143
+ count: (t) => t.length,
3144
+ min: (t, e) => Math.min(...t.map((o) => Number(o[e]) || 1 / 0)),
3145
+ max: (t, e) => Math.max(...t.map((o) => Number(o[e]) || -1 / 0)),
3146
+ first: (t, e) => t[0]?.[e],
3147
+ last: (t, e) => t[t.length - 1]?.[e]
3148
+ }, I = /* @__PURE__ */ new Map(), O = {
3149
+ /**
3150
+ * Register a custom aggregator function.
3151
+ */
3152
+ register(t, e) {
3153
+ I.set(t, e);
3154
+ },
3155
+ /**
3156
+ * Unregister a custom aggregator function.
3157
+ */
3158
+ unregister(t) {
3159
+ I.delete(t);
3160
+ },
3161
+ /**
3162
+ * Get an aggregator function by reference.
3163
+ */
3164
+ get(t) {
3165
+ if (t !== void 0)
3166
+ return typeof t == "function" ? t : I.get(t) ?? Y[t];
3167
+ },
3168
+ /**
3169
+ * Run an aggregator on a set of rows.
3170
+ */
3171
+ run(t, e, o, n) {
3172
+ const i = this.get(t);
3173
+ return i ? i(e, o, n) : void 0;
3174
+ },
3175
+ /**
3176
+ * Check if an aggregator exists.
3177
+ */
3178
+ has(t) {
3179
+ return I.has(t) || t in Y;
3180
+ },
3181
+ /**
3182
+ * List all available aggregator names.
3183
+ */
3184
+ list() {
3185
+ return [...Object.keys(Y), ...I.keys()];
3186
+ }
3187
+ }, ce = {
3188
+ sum: (t) => t.reduce((e, o) => e + o, 0),
3189
+ avg: (t) => t.length ? t.reduce((e, o) => e + o, 0) / t.length : 0,
3190
+ count: (t) => t.length,
3191
+ min: (t) => t.length ? Math.min(...t) : 0,
3192
+ max: (t) => t.length ? Math.max(...t) : 0,
3193
+ first: (t) => t[0] ?? 0,
3194
+ last: (t) => t[t.length - 1] ?? 0
3195
+ };
3196
+ function tt(t) {
3197
+ return ce[t] ?? ce.sum;
3198
+ }
3199
+ function at(t, e) {
3200
+ return tt(t)(e);
3201
+ }
3202
+ const ct = O.register.bind(O), dt = O.unregister.bind(O), ut = O.get.bind(O), ht = O.run.bind(O), ft = O.list.bind(O);
3203
+ export {
3204
+ nt as B,
3205
+ H as D,
3206
+ $ as F,
3207
+ T as G,
3208
+ ot as P,
3209
+ tt as a,
3210
+ W as b,
3211
+ et as c,
3212
+ O as d,
3213
+ M as e,
3214
+ ct as f,
3215
+ ut as g,
3216
+ at as h,
3217
+ rt as i,
3218
+ lt as j,
3219
+ me as k,
3220
+ ft as l,
3221
+ Be as m,
3222
+ qe as n,
3223
+ st as o,
3224
+ G as p,
3225
+ it as q,
3226
+ ht as r,
3227
+ dt as u
3228
+ };
3229
+ //# sourceMappingURL=index-DG2CZ_Zo.js.map