@toolbox-web/grid 0.3.3 → 0.4.1

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 (148) hide show
  1. package/all.d.ts +19 -19
  2. package/all.d.ts.map +1 -1
  3. package/all.js +1798 -1201
  4. package/all.js.map +1 -1
  5. package/index.js +2215 -2026
  6. package/index.js.map +1 -1
  7. package/lib/core/grid.d.ts +22 -12
  8. package/lib/core/grid.d.ts.map +1 -1
  9. package/lib/core/internal/columns.d.ts +0 -9
  10. package/lib/core/internal/columns.d.ts.map +1 -1
  11. package/lib/core/internal/config-manager.d.ts +236 -0
  12. package/lib/core/internal/config-manager.d.ts.map +1 -0
  13. package/lib/core/internal/editing.d.ts +3 -3
  14. package/lib/core/internal/editing.d.ts.map +1 -1
  15. package/lib/core/internal/event-delegation.d.ts.map +1 -1
  16. package/lib/core/internal/header.d.ts.map +1 -1
  17. package/lib/core/internal/keyboard.d.ts.map +1 -1
  18. package/lib/core/internal/render-scheduler.d.ts +123 -0
  19. package/lib/core/internal/render-scheduler.d.ts.map +1 -0
  20. package/lib/core/internal/rows.d.ts +8 -3
  21. package/lib/core/internal/rows.d.ts.map +1 -1
  22. package/lib/core/internal/sanitize.d.ts +2 -2
  23. package/lib/core/internal/sanitize.d.ts.map +1 -1
  24. package/lib/core/internal/shell.d.ts +40 -2
  25. package/lib/core/internal/shell.d.ts.map +1 -1
  26. package/lib/core/internal/validate-config.d.ts +25 -0
  27. package/lib/core/internal/validate-config.d.ts.map +1 -0
  28. package/lib/core/plugin/base-plugin.d.ts +118 -0
  29. package/lib/core/plugin/base-plugin.d.ts.map +1 -1
  30. package/lib/core/plugin/index.d.ts +1 -0
  31. package/lib/core/plugin/index.d.ts.map +1 -1
  32. package/lib/core/plugin/plugin-manager.d.ts +13 -2
  33. package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
  34. package/lib/core/plugin/types.d.ts +17 -3
  35. package/lib/core/plugin/types.d.ts.map +1 -1
  36. package/lib/core/types.d.ts +112 -12
  37. package/lib/core/types.d.ts.map +1 -1
  38. package/lib/plugins/clipboard/ClipboardPlugin.d.ts +7 -1
  39. package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
  40. package/lib/plugins/clipboard/index.js +78 -22
  41. package/lib/plugins/clipboard/index.js.map +1 -1
  42. package/lib/plugins/column-virtualization/index.js +72 -21
  43. package/lib/plugins/column-virtualization/index.js.map +1 -1
  44. package/lib/plugins/context-menu/index.js +53 -2
  45. package/lib/plugins/context-menu/index.js.map +1 -1
  46. package/lib/plugins/editing/EditingPlugin.d.ts +117 -0
  47. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -0
  48. package/lib/{core/internal → plugins/editing}/editors.d.ts +1 -1
  49. package/lib/plugins/editing/editors.d.ts.map +1 -0
  50. package/lib/plugins/editing/index.d.ts +8 -0
  51. package/lib/plugins/editing/index.d.ts.map +1 -0
  52. package/lib/plugins/editing/index.js +721 -0
  53. package/lib/plugins/editing/index.js.map +1 -0
  54. package/lib/plugins/editing/types.d.ts +45 -0
  55. package/lib/plugins/editing/types.d.ts.map +1 -0
  56. package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
  57. package/lib/plugins/export/index.js +68 -17
  58. package/lib/plugins/export/index.js.map +1 -1
  59. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  60. package/lib/plugins/filtering/index.js +103 -50
  61. package/lib/plugins/filtering/index.js.map +1 -1
  62. package/lib/plugins/grouping-columns/grouping-columns.d.ts +4 -4
  63. package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
  64. package/lib/plugins/grouping-columns/index.js +80 -29
  65. package/lib/plugins/grouping-columns/index.js.map +1 -1
  66. package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
  67. package/lib/plugins/grouping-rows/grouping-rows.d.ts.map +1 -1
  68. package/lib/plugins/grouping-rows/index.js +62 -11
  69. package/lib/plugins/grouping-rows/index.js.map +1 -1
  70. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +2 -2
  71. package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
  72. package/lib/plugins/master-detail/index.js +156 -102
  73. package/lib/plugins/master-detail/index.js.map +1 -1
  74. package/lib/plugins/master-detail/types.d.ts +12 -2
  75. package/lib/plugins/master-detail/types.d.ts.map +1 -1
  76. package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
  77. package/lib/plugins/multi-sort/index.js +75 -22
  78. package/lib/plugins/multi-sort/index.js.map +1 -1
  79. package/lib/plugins/pinned-columns/index.js +57 -6
  80. package/lib/plugins/pinned-columns/index.js.map +1 -1
  81. package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
  82. package/lib/plugins/pinned-rows/index.js +61 -9
  83. package/lib/plugins/pinned-rows/index.js.map +1 -1
  84. package/lib/plugins/pivot/index.js +58 -7
  85. package/lib/plugins/pivot/index.js.map +1 -1
  86. package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
  87. package/lib/plugins/reorder/index.js +75 -19
  88. package/lib/plugins/reorder/index.js.map +1 -1
  89. package/lib/plugins/selection/index.js +57 -6
  90. package/lib/plugins/selection/index.js.map +1 -1
  91. package/lib/plugins/server-side/index.js +60 -9
  92. package/lib/plugins/server-side/index.js.map +1 -1
  93. package/lib/plugins/tree/TreePlugin.d.ts +3 -3
  94. package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
  95. package/lib/plugins/tree/index.js +181 -126
  96. package/lib/plugins/tree/index.js.map +1 -1
  97. package/lib/plugins/tree/tree-data.d.ts +6 -6
  98. package/lib/plugins/tree/tree-data.d.ts.map +1 -1
  99. package/lib/plugins/tree/tree-detect.d.ts +5 -9
  100. package/lib/plugins/tree/tree-detect.d.ts.map +1 -1
  101. package/lib/plugins/tree/types.d.ts +16 -4
  102. package/lib/plugins/tree/types.d.ts.map +1 -1
  103. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +7 -1
  104. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
  105. package/lib/plugins/undo-redo/index.js +65 -6
  106. package/lib/plugins/undo-redo/index.js.map +1 -1
  107. package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -1
  108. package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
  109. package/lib/plugins/visibility/index.js +61 -2
  110. package/lib/plugins/visibility/index.js.map +1 -1
  111. package/package.json +1 -1
  112. package/public.d.ts +104 -13
  113. package/public.d.ts.map +1 -1
  114. package/umd/grid.all.umd.js +37 -19
  115. package/umd/grid.all.umd.js.map +1 -1
  116. package/umd/grid.umd.js +25 -7
  117. package/umd/grid.umd.js.map +1 -1
  118. package/umd/plugins/clipboard.umd.js +2 -2
  119. package/umd/plugins/clipboard.umd.js.map +1 -1
  120. package/umd/plugins/editing.umd.js +2 -0
  121. package/umd/plugins/editing.umd.js.map +1 -0
  122. package/umd/plugins/export.umd.js +2 -2
  123. package/umd/plugins/export.umd.js.map +1 -1
  124. package/umd/plugins/filtering.umd.js +1 -1
  125. package/umd/plugins/filtering.umd.js.map +1 -1
  126. package/umd/plugins/grouping-columns.umd.js +1 -1
  127. package/umd/plugins/grouping-columns.umd.js.map +1 -1
  128. package/umd/plugins/grouping-rows.umd.js +1 -1
  129. package/umd/plugins/grouping-rows.umd.js.map +1 -1
  130. package/umd/plugins/master-detail.umd.js +1 -1
  131. package/umd/plugins/master-detail.umd.js.map +1 -1
  132. package/umd/plugins/multi-sort.umd.js +1 -1
  133. package/umd/plugins/multi-sort.umd.js.map +1 -1
  134. package/umd/plugins/pinned-rows.umd.js +1 -1
  135. package/umd/plugins/pinned-rows.umd.js.map +1 -1
  136. package/umd/plugins/reorder.umd.js +1 -1
  137. package/umd/plugins/reorder.umd.js.map +1 -1
  138. package/umd/plugins/tree.umd.js +1 -1
  139. package/umd/plugins/tree.umd.js.map +1 -1
  140. package/umd/plugins/undo-redo.umd.js +1 -1
  141. package/umd/plugins/undo-redo.umd.js.map +1 -1
  142. package/umd/plugins/visibility.umd.js +1 -1
  143. package/umd/plugins/visibility.umd.js.map +1 -1
  144. package/lib/core/internal/column-state.d.ts +0 -124
  145. package/lib/core/internal/column-state.d.ts.map +0 -1
  146. package/lib/core/internal/editors.d.ts.map +0 -1
  147. package/lib/core/internal/grid-internals.d.ts +0 -83
  148. package/lib/core/internal/grid-internals.d.ts.map +0 -1
@@ -2,10 +2,10 @@ function P(p) {
2
2
  const { totalRows: e, viewportHeight: t, scrollTop: r, rowHeight: l, overscan: n } = p, o = Math.ceil(t / l);
3
3
  let i = Math.floor(r / l) - n;
4
4
  i < 0 && (i = 0);
5
- let a = i + o + n * 2;
6
- return a > e && (a = e), a === e && i > 0 && (i = Math.max(0, a - o - n * 2)), {
5
+ let s = i + o + n * 2;
6
+ return s > e && (s = e), s === e && i > 0 && (i = Math.max(0, s - o - n * 2)), {
7
7
  start: i,
8
- end: a,
8
+ end: s,
9
9
  offsetY: i * l,
10
10
  totalHeight: e * l
11
11
  };
@@ -24,6 +24,22 @@ const V = {
24
24
  toolPanel: "☰"
25
25
  };
26
26
  class _ {
27
+ /**
28
+ * Plugin dependencies - declare other plugins this one requires.
29
+ *
30
+ * Dependencies are validated when the plugin is attached.
31
+ * Required dependencies throw an error if missing.
32
+ * Optional dependencies log an info message if missing.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * static readonly dependencies: PluginDependency[] = [
37
+ * { name: 'editing', required: true, reason: 'Tracks cell edits for undo/redo' },
38
+ * { name: 'selection', required: false, reason: 'Enables selection-based undo' },
39
+ * ];
40
+ * ```
41
+ */
42
+ static dependencies;
27
43
  /** Plugin version - override in subclass if needed */
28
44
  version = "1.0.0";
29
45
  /** CSS styles to inject into the grid's shadow DOM */
@@ -40,6 +56,12 @@ class _ {
40
56
  config;
41
57
  /** User-provided configuration from constructor */
42
58
  userConfig;
59
+ /**
60
+ * Plugin-level AbortController for event listener cleanup.
61
+ * Created fresh in attach(), aborted in detach().
62
+ * This ensures event listeners are properly cleaned up when plugins are re-attached.
63
+ */
64
+ #e;
43
65
  /**
44
66
  * Default configuration - subclasses should override this getter.
45
67
  * Note: This must be a getter (not property initializer) for proper inheritance
@@ -54,19 +76,48 @@ class _ {
54
76
  /**
55
77
  * Called when the plugin is attached to a grid.
56
78
  * Override to set up event listeners, initialize state, etc.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * attach(grid: GridElement): void {
83
+ * super.attach(grid);
84
+ * // Set up document-level listeners with auto-cleanup
85
+ * document.addEventListener('keydown', this.handleEscape, {
86
+ * signal: this.disconnectSignal
87
+ * });
88
+ * }
89
+ * ```
57
90
  */
58
91
  attach(e) {
59
- this.grid = e, this.config = { ...this.defaultConfig, ...this.userConfig };
92
+ this.#e?.abort(), this.#e = new AbortController(), this.grid = e, this.config = { ...this.defaultConfig, ...this.userConfig };
60
93
  }
61
94
  /**
62
95
  * Called when the plugin is detached from a grid.
63
96
  * Override to clean up event listeners, timers, etc.
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * detach(): void {
101
+ * // Clean up any state not handled by disconnectSignal
102
+ * this.selectedRows.clear();
103
+ * this.cache = null;
104
+ * }
105
+ * ```
64
106
  */
65
107
  detach() {
108
+ this.#e?.abort(), this.#e = void 0;
66
109
  }
67
110
  /**
68
111
  * Get another plugin instance from the same grid.
69
112
  * Use for inter-plugin communication.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * const selection = this.getPlugin(SelectionPlugin);
117
+ * if (selection) {
118
+ * const selectedRows = selection.getSelectedRows();
119
+ * }
120
+ * ```
70
121
  */
71
122
  getPlugin(e) {
72
123
  return this.grid?.getPlugin(e);
@@ -140,7 +191,7 @@ class _ {
140
191
  * document.addEventListener('keydown', handler, { signal: this.disconnectSignal });
141
192
  */
142
193
  get disconnectSignal() {
143
- return this.grid?.disconnectSignal;
194
+ return this.#e?.signal ?? this.grid?.disconnectSignal;
144
195
  }
145
196
  /**
146
197
  * Get the grid-level icons configuration.
@@ -242,7 +293,7 @@ function N(p, e) {
242
293
  }
243
294
  return [...t].sort((r, l) => typeof r == "number" && typeof l == "number" ? r - l : String(r).localeCompare(String(l)));
244
295
  }
245
- const $ = ':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)}.header-cell.filtered:before{content:"";position:absolute;top:4px;right:4px;width:6px;height:6px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}.tbw-filter-btn{display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:4px;opacity:.4;transition:opacity .15s;color:inherit;vertical-align:middle}.tbw-filter-btn:hover,.tbw-filter-btn.active{opacity:1}.tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}', K = ".tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, 4px));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:12px;z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, 13px)}.tbw-filter-search{margin-bottom:8px}.tbw-filter-search-input{width:100%;padding:6px 10px;background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, 4px);font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:4px 2px;margin-bottom:8px;border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-action-btn{background:transparent;border:none;color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));cursor:pointer;font-size:12px;padding:2px 0}.tbw-filter-action-btn:hover{text-decoration:underline}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:8px;max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:8px;padding:4px 2px;cursor:pointer;border-radius:3px}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:8px 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:8px;padding-top:8px;border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:6px 12px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:6px 12px;background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}";
296
+ const $ = ':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 .header-cell.filtered:before{content:"";position:absolute;top:4px;right:4px;width:6px;height:6px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}:host .tbw-filter-btn{display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:4px;opacity:.4;transition:opacity .15s;color:inherit;vertical-align:middle}:host .tbw-filter-btn:hover,:host .tbw-filter-btn.active{opacity:1}:host .tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}', K = ".tbw-filter-panel{position:fixed;background:var(--tbw-filter-panel-bg, var(--tbw-color-panel-bg, light-dark(#eeeeee, #222222)));color:var(--tbw-filter-panel-fg, var(--tbw-color-fg, light-dark(#222222, #eeeeee)));border:1px solid var(--tbw-filter-panel-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-panel-radius, var(--tbw-border-radius, 4px));box-shadow:0 4px 16px var(--tbw-filter-panel-shadow, var(--tbw-color-shadow, light-dark(rgba(0, 0, 0, .1), rgba(0, 0, 0, .3))));padding:12px;z-index:10000;min-width:200px;max-width:280px;max-height:350px;display:flex;flex-direction:column;font-family:var(--tbw-font-family, system-ui, sans-serif);font-size:var(--tbw-font-size, 13px)}.tbw-filter-search{margin-bottom:8px}.tbw-filter-search-input{width:100%;padding:6px 10px;background:var(--tbw-filter-input-bg, var(--tbw-color-bg, transparent));color:inherit;border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:var(--tbw-filter-input-radius, 4px);font-size:inherit;box-sizing:border-box}.tbw-filter-search-input:focus{outline:none;border-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));box-shadow:0 0 0 2px rgba(from var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6)) r g b / 15%)}.tbw-filter-actions{display:flex;padding:4px 2px;margin-bottom:8px;border-bottom:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-action-btn{background:transparent;border:none;color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));cursor:pointer;font-size:12px;padding:2px 0}.tbw-filter-action-btn:hover{text-decoration:underline}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:8px;max-height:180px;position:relative}.tbw-filter-values-spacer{width:1px}.tbw-filter-values-content{position:absolute;top:0;left:0;right:0}.tbw-filter-value-item{display:flex;align-items:center;gap:8px;padding:4px 2px;cursor:pointer;border-radius:3px}.tbw-filter-value-item:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}.tbw-filter-checkbox{margin:0;cursor:pointer;accent-color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}.tbw-filter-no-match{color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));padding:8px 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:8px;padding-top:8px;border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:6px 12px;background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));color:var(--tbw-filter-accent-fg, var(--tbw-color-accent-fg, light-dark(#ffffff, #000000)));border:none;border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:6px 12px;background:transparent;color:var(--tbw-filter-muted, var(--tbw-color-fg-muted, light-dark(#555555, #aaaaaa)));border:1px solid var(--tbw-filter-input-border, var(--tbw-color-border, light-dark(#d0d0d4, #454545)));border-radius:4px;cursor:pointer;font-size:13px}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}";
246
297
  class x extends _ {
247
298
  name = "filtering";
248
299
  version = "1.0.0";
@@ -302,14 +353,16 @@ class x extends _ {
302
353
  const o = n.field;
303
354
  if (!o) return;
304
355
  const i = this.filters.has(o);
305
- let a = r.querySelector(".tbw-filter-btn");
306
- if (a) {
307
- a.classList.toggle("active", i), r.classList.toggle("filtered", i);
356
+ let s = r.querySelector(".tbw-filter-btn");
357
+ if (s) {
358
+ s.classList.toggle("active", i), r.classList.toggle("filtered", i);
308
359
  return;
309
360
  }
310
- a = document.createElement("button"), a.className = "tbw-filter-btn", a.setAttribute("aria-label", `Filter ${n.header ?? o}`), a.innerHTML = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', i && (a.classList.add("active"), r.classList.add("filtered")), a.addEventListener("click", (f) => {
311
- f.stopPropagation(), this.toggleFilterPanel(o, n, a);
312
- }), r.appendChild(a);
361
+ s = document.createElement("button"), s.className = "tbw-filter-btn", s.setAttribute("aria-label", `Filter ${n.header ?? o}`), s.innerHTML = '<svg viewBox="0 0 16 16" width="12" height="12"><path fill="currentColor" d="M6 10.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm-2-3a.5.5 0 0 1 .5-.5h11a.5.5 0 0 1 0 1h-11a.5.5 0 0 1-.5-.5z"/></svg>', i && (s.classList.add("active"), r.classList.add("filtered")), s.addEventListener("click", (b) => {
362
+ b.stopPropagation(), this.toggleFilterPanel(o, n, s);
363
+ });
364
+ const f = r.querySelector(".resize-handle");
365
+ f ? r.insertBefore(s, f) : r.appendChild(s);
313
366
  });
314
367
  }
315
368
  // #endregion
@@ -440,16 +493,16 @@ class x extends _ {
440
493
  applySetFilter: (f) => {
441
494
  this.applySetFilter(e, f), this.closeFilterPanel();
442
495
  },
443
- applyTextFilter: (f, g, C) => {
444
- this.applyTextFilter(e, f, g, C), this.closeFilterPanel();
496
+ applyTextFilter: (f, b, C) => {
497
+ this.applyTextFilter(e, f, b, C), this.closeFilterPanel();
445
498
  },
446
499
  clearFilter: () => {
447
500
  this.clearFieldFilter(e), this.closeFilterPanel();
448
501
  },
449
502
  closePanel: () => this.closeFilterPanel()
450
503
  };
451
- let a = !1;
452
- this.config.filterPanelRenderer && (this.config.filterPanelRenderer(r, i), a = r.children.length > 0), a || this.renderDefaultFilterPanel(r, i, l, n);
504
+ let s = !1;
505
+ this.config.filterPanelRenderer && (this.config.filterPanelRenderer(r, i), s = r.children.length > 0), s || this.renderDefaultFilterPanel(r, i, l, n);
453
506
  }
454
507
  /**
455
508
  * Setup click-outside handler to close the panel
@@ -489,38 +542,38 @@ class x extends _ {
489
542
  o.className = "tbw-filter-search";
490
543
  const i = document.createElement("input");
491
544
  i.type = "text", i.placeholder = "Search...", i.className = "tbw-filter-search-input", i.value = this.searchText.get(n) ?? "", o.appendChild(i), e.appendChild(o);
492
- const a = document.createElement("div");
493
- a.className = "tbw-filter-actions";
545
+ const s = document.createElement("div");
546
+ s.className = "tbw-filter-actions";
494
547
  const f = document.createElement("label");
495
548
  f.className = "tbw-filter-value-item", f.style.padding = "0", f.style.margin = "0";
496
- const g = document.createElement("input");
497
- g.type = "checkbox", g.className = "tbw-filter-checkbox";
549
+ const b = document.createElement("input");
550
+ b.type = "checkbox", b.className = "tbw-filter-checkbox";
498
551
  const C = document.createElement("span");
499
- C.textContent = "Select All", f.appendChild(g), f.appendChild(C), a.appendChild(f);
552
+ C.textContent = "Select All", f.appendChild(b), f.appendChild(C), s.appendChild(f);
500
553
  const k = () => {
501
- const s = [...m.values()], u = s.every((d) => d), h = s.every((d) => !d);
502
- g.checked = u, g.indeterminate = !u && !h;
554
+ const a = [...m.values()], u = a.every((d) => d), h = a.every((d) => !d);
555
+ b.checked = u, b.indeterminate = !u && !h;
503
556
  };
504
- g.addEventListener("change", () => {
505
- const s = g.checked;
557
+ b.addEventListener("change", () => {
558
+ const a = b.checked;
506
559
  for (const u of m.keys())
507
- m.set(u, s);
560
+ m.set(u, a);
508
561
  k(), F();
509
- }), e.appendChild(a);
562
+ }), e.appendChild(s);
510
563
  const v = document.createElement("div");
511
564
  v.className = "tbw-filter-values";
512
565
  const S = document.createElement("div");
513
566
  S.className = "tbw-filter-values-spacer", v.appendChild(S);
514
- const b = document.createElement("div");
515
- b.className = "tbw-filter-values-content", v.appendChild(b);
567
+ const g = document.createElement("div");
568
+ g.className = "tbw-filter-values-content", v.appendChild(g);
516
569
  const m = /* @__PURE__ */ new Map();
517
- r.forEach((s) => {
518
- const u = s == null ? "__null__" : String(s);
519
- m.set(u, !l.has(s));
570
+ r.forEach((a) => {
571
+ const u = a == null ? "__null__" : String(a);
572
+ m.set(u, !l.has(a));
520
573
  }), k();
521
574
  let y = [];
522
- const I = (s, u) => {
523
- const h = s == null ? "(Blank)" : String(s), d = s == null ? "__null__" : String(s), c = document.createElement("label");
575
+ const I = (a, u) => {
576
+ const h = a == null ? "(Blank)" : String(a), d = a == null ? "__null__" : String(a), c = document.createElement("label");
524
577
  c.className = "tbw-filter-value-item", c.style.position = "absolute", c.style.top = `${u * x.LIST_ITEM_HEIGHT}px`, c.style.left = "0", c.style.right = "0", c.style.height = `${x.LIST_ITEM_HEIGHT}px`, c.style.boxSizing = "border-box";
525
578
  const w = document.createElement("input");
526
579
  w.type = "checkbox", w.className = "tbw-filter-checkbox", w.checked = m.get(d) ?? !0, w.dataset.value = d, w.addEventListener("change", () => {
@@ -529,32 +582,32 @@ class x extends _ {
529
582
  const H = document.createElement("span");
530
583
  return H.textContent = h, c.appendChild(w), c.appendChild(H), c;
531
584
  }, F = () => {
532
- const s = y.length, u = v.clientHeight, h = v.scrollTop;
533
- if (S.style.height = `${s * x.LIST_ITEM_HEIGHT}px`, M(s, x.LIST_BYPASS_THRESHOLD / 3)) {
534
- b.innerHTML = "", b.style.transform = "translateY(0px)", y.forEach((c, w) => {
535
- b.appendChild(I(c, w));
585
+ const a = y.length, u = v.clientHeight, h = v.scrollTop;
586
+ if (S.style.height = `${a * x.LIST_ITEM_HEIGHT}px`, M(a, x.LIST_BYPASS_THRESHOLD / 3)) {
587
+ g.innerHTML = "", g.style.transform = "translateY(0px)", y.forEach((c, w) => {
588
+ g.appendChild(I(c, w));
536
589
  });
537
590
  return;
538
591
  }
539
592
  const d = P({
540
- totalRows: s,
593
+ totalRows: a,
541
594
  viewportHeight: u,
542
595
  scrollTop: h,
543
596
  rowHeight: x.LIST_ITEM_HEIGHT,
544
597
  overscan: x.LIST_OVERSCAN
545
598
  });
546
- b.style.transform = `translateY(${d.offsetY}px)`, b.innerHTML = "";
599
+ g.style.transform = `translateY(${d.offsetY}px)`, g.innerHTML = "";
547
600
  for (let c = d.start; c < d.end; c++)
548
- b.appendChild(I(y[c], c - d.start));
549
- }, L = (s) => {
550
- const u = s.toLowerCase();
601
+ g.appendChild(I(y[c], c - d.start));
602
+ }, L = (a) => {
603
+ const u = a.toLowerCase();
551
604
  if (y = r.filter((h) => {
552
605
  const d = h == null ? "(Blank)" : String(h);
553
- return !s || d.toLowerCase().includes(u);
606
+ return !a || d.toLowerCase().includes(u);
554
607
  }), y.length === 0) {
555
- S.style.height = "0px", b.innerHTML = "";
608
+ S.style.height = "0px", g.innerHTML = "";
556
609
  const h = document.createElement("div");
557
- h.className = "tbw-filter-no-match", h.textContent = "No matching values", b.appendChild(h);
610
+ h.className = "tbw-filter-no-match", h.textContent = "No matching values", g.appendChild(h);
558
611
  return;
559
612
  }
560
613
  F();
@@ -576,16 +629,16 @@ class x extends _ {
576
629
  T.className = "tbw-filter-buttons";
577
630
  const E = document.createElement("button");
578
631
  E.className = "tbw-filter-apply-btn", E.textContent = "Apply", E.addEventListener("click", () => {
579
- const s = [];
632
+ const a = [];
580
633
  for (const [u, h] of m)
581
634
  if (!h)
582
635
  if (u === "__null__")
583
- s.push(null);
636
+ a.push(null);
584
637
  else {
585
638
  const d = r.find((c) => String(c) === u);
586
- s.push(d !== void 0 ? d : u);
639
+ a.push(d !== void 0 ? d : u);
587
640
  }
588
- t.applySetFilter(s);
641
+ t.applySetFilter(a);
589
642
  }), T.appendChild(E);
590
643
  const R = document.createElement("button");
591
644
  R.className = "tbw-filter-clear-btn", R.textContent = "Clear Filter", R.addEventListener("click", () => {