@toolbox-web/grid 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -13
- package/all.js +1678 -1588
- package/all.js.map +1 -1
- package/index.js +762 -568
- package/index.js.map +1 -1
- package/lib/core/grid.d.ts +21 -0
- package/lib/core/grid.d.ts.map +1 -1
- package/lib/core/internal/config-manager.d.ts +1 -0
- package/lib/core/internal/config-manager.d.ts.map +1 -1
- package/lib/core/internal/dom-builder.d.ts +2 -0
- package/lib/core/internal/dom-builder.d.ts.map +1 -1
- package/lib/core/internal/header.d.ts.map +1 -1
- package/lib/core/internal/keyboard.d.ts.map +1 -1
- package/lib/core/internal/resize.d.ts.map +1 -1
- package/lib/core/internal/rows.d.ts.map +1 -1
- package/lib/core/internal/shell.d.ts +19 -13
- package/lib/core/internal/shell.d.ts.map +1 -1
- package/lib/core/internal/utils.d.ts +1 -0
- package/lib/core/internal/utils.d.ts.map +1 -1
- package/lib/core/plugin/base-plugin.d.ts +70 -3
- package/lib/core/plugin/base-plugin.d.ts.map +1 -1
- package/lib/core/plugin/expander-column.d.ts +51 -0
- package/lib/core/plugin/expander-column.d.ts.map +1 -0
- package/lib/core/plugin/plugin-manager.d.ts +6 -2
- package/lib/core/plugin/plugin-manager.d.ts.map +1 -1
- package/lib/core/plugin/types.d.ts +117 -1
- package/lib/core/plugin/types.d.ts.map +1 -1
- package/lib/core/types.d.ts +10 -5
- package/lib/core/types.d.ts.map +1 -1
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts +5 -4
- package/lib/plugins/clipboard/ClipboardPlugin.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.d.ts +1 -1
- package/lib/plugins/clipboard/index.d.ts.map +1 -1
- package/lib/plugins/clipboard/index.js +295 -190
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/clipboard/types.d.ts +72 -2
- package/lib/plugins/clipboard/types.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts +0 -1
- package/lib/plugins/column-virtualization/ColumnVirtualizationPlugin.d.ts.map +1 -1
- package/lib/plugins/column-virtualization/index.js +143 -56
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts +0 -1
- package/lib/plugins/context-menu/ContextMenuPlugin.d.ts.map +1 -1
- package/lib/plugins/context-menu/index.js +189 -102
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/editing/EditingPlugin.d.ts +2 -7
- package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
- package/lib/plugins/editing/index.js +227 -150
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/export/ExportPlugin.d.ts +0 -1
- package/lib/plugins/export/ExportPlugin.d.ts.map +1 -1
- package/lib/plugins/export/index.js +184 -97
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/FilteringPlugin.d.ts +14 -3
- package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
- package/lib/plugins/filtering/index.js +296 -176
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts +2 -2
- package/lib/plugins/grouping-columns/GroupingColumnsPlugin.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/grouping-columns.d.ts +1 -1
- package/lib/plugins/grouping-columns/grouping-columns.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/index.js +169 -61
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts +14 -2
- package/lib/plugins/grouping-rows/GroupingRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/grouping-rows/index.js +243 -140
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +13 -11
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts.map +1 -1
- package/lib/plugins/master-detail/index.js +278 -196
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/master-detail/types.d.ts +0 -10
- package/lib/plugins/master-detail/types.d.ts.map +1 -1
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts +1 -2
- package/lib/plugins/multi-sort/MultiSortPlugin.d.ts.map +1 -1
- package/lib/plugins/multi-sort/index.js +125 -40
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts +0 -1
- package/lib/plugins/pinned-columns/PinnedColumnsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-columns/index.js +156 -75
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-columns/pinned-columns.d.ts +2 -2
- package/lib/plugins/pinned-columns/pinned-columns.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts +1 -2
- package/lib/plugins/pinned-rows/PinnedRowsPlugin.d.ts.map +1 -1
- package/lib/plugins/pinned-rows/index.js +202 -117
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/PivotPlugin.d.ts +26 -4
- package/lib/plugins/pivot/PivotPlugin.d.ts.map +1 -1
- package/lib/plugins/pivot/index.js +413 -314
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/pivot/pivot-rows.d.ts +2 -1
- package/lib/plugins/pivot/pivot-rows.d.ts.map +1 -1
- package/lib/plugins/reorder/ReorderPlugin.d.ts +13 -10
- package/lib/plugins/reorder/ReorderPlugin.d.ts.map +1 -1
- package/lib/plugins/reorder/index.d.ts +1 -1
- package/lib/plugins/reorder/index.d.ts.map +1 -1
- package/lib/plugins/reorder/index.js +296 -223
- package/lib/plugins/reorder/index.js.map +1 -1
- package/lib/plugins/selection/SelectionPlugin.d.ts +21 -3
- package/lib/plugins/selection/SelectionPlugin.d.ts.map +1 -1
- package/lib/plugins/selection/index.d.ts +2 -2
- package/lib/plugins/selection/index.d.ts.map +1 -1
- package/lib/plugins/selection/index.js +282 -141
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/selection/types.d.ts +24 -0
- package/lib/plugins/selection/types.d.ts.map +1 -1
- package/lib/plugins/server-side/ServerSidePlugin.d.ts +0 -1
- package/lib/plugins/server-side/ServerSidePlugin.d.ts.map +1 -1
- package/lib/plugins/server-side/index.js +96 -9
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tree/TreePlugin.d.ts +5 -1
- package/lib/plugins/tree/TreePlugin.d.ts.map +1 -1
- package/lib/plugins/tree/index.js +209 -113
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/tree/types.d.ts +0 -10
- package/lib/plugins/tree/types.d.ts.map +1 -1
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +0 -1
- package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
- package/lib/plugins/undo-redo/index.js +98 -11
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/VisibilityPlugin.d.ts +7 -4
- package/lib/plugins/visibility/VisibilityPlugin.d.ts.map +1 -1
- package/lib/plugins/visibility/index.js +155 -64
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +1 -1
- package/themes/dg-theme-bootstrap.css +55 -53
- package/themes/dg-theme-contrast.css +42 -40
- package/themes/dg-theme-large.css +38 -37
- package/themes/dg-theme-material.css +54 -52
- package/themes/dg-theme-standard.css +19 -17
- package/themes/dg-theme-vibrant.css +16 -14
- package/umd/grid.all.umd.js +23 -24
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +12 -11
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/clipboard.umd.js +5 -7
- package/umd/plugins/clipboard.umd.js.map +1 -1
- package/umd/plugins/column-virtualization.umd.js +1 -1
- package/umd/plugins/column-virtualization.umd.js.map +1 -1
- package/umd/plugins/context-menu.umd.js +1 -1
- package/umd/plugins/context-menu.umd.js.map +1 -1
- package/umd/plugins/editing.umd.js +1 -1
- package/umd/plugins/editing.umd.js.map +1 -1
- package/umd/plugins/export.umd.js +1 -1
- package/umd/plugins/export.umd.js.map +1 -1
- package/umd/plugins/filtering.umd.js +1 -1
- package/umd/plugins/filtering.umd.js.map +1 -1
- package/umd/plugins/grouping-columns.umd.js +1 -1
- package/umd/plugins/grouping-columns.umd.js.map +1 -1
- package/umd/plugins/grouping-rows.umd.js +1 -1
- package/umd/plugins/grouping-rows.umd.js.map +1 -1
- package/umd/plugins/master-detail.umd.js +1 -1
- package/umd/plugins/master-detail.umd.js.map +1 -1
- package/umd/plugins/multi-sort.umd.js +1 -1
- package/umd/plugins/multi-sort.umd.js.map +1 -1
- package/umd/plugins/pinned-columns.umd.js +1 -1
- package/umd/plugins/pinned-columns.umd.js.map +1 -1
- package/umd/plugins/pinned-rows.umd.js +1 -1
- package/umd/plugins/pinned-rows.umd.js.map +1 -1
- package/umd/plugins/pivot.umd.js +1 -1
- package/umd/plugins/pivot.umd.js.map +1 -1
- package/umd/plugins/reorder.umd.js +1 -1
- package/umd/plugins/reorder.umd.js.map +1 -1
- package/umd/plugins/selection.umd.js +1 -1
- package/umd/plugins/selection.umd.js.map +1 -1
- package/umd/plugins/server-side.umd.js +1 -1
- package/umd/plugins/server-side.umd.js.map +1 -1
- package/umd/plugins/tree.umd.js +1 -1
- package/umd/plugins/tree.umd.js.map +1 -1
- package/umd/plugins/undo-redo.umd.js +1 -1
- package/umd/plugins/undo-redo.umd.js.map +1 -1
- package/umd/plugins/visibility.umd.js +1 -1
- package/umd/plugins/visibility.umd.js.map +1 -1
- package/lib/core/internal/editing.d.ts +0 -76
- package/lib/core/internal/editing.d.ts.map +0 -1
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
function P(
|
|
2
|
-
const { totalRows: e, viewportHeight: t, scrollTop: r, rowHeight:
|
|
3
|
-
let
|
|
4
|
-
|
|
5
|
-
let
|
|
6
|
-
return
|
|
7
|
-
start:
|
|
8
|
-
end:
|
|
9
|
-
offsetY:
|
|
10
|
-
totalHeight: e *
|
|
1
|
+
function P(h) {
|
|
2
|
+
const { totalRows: e, viewportHeight: t, scrollTop: r, rowHeight: n, overscan: i } = h, l = Math.ceil(t / n);
|
|
3
|
+
let a = Math.floor(r / n) - i;
|
|
4
|
+
a < 0 && (a = 0);
|
|
5
|
+
let o = a + l + i * 2;
|
|
6
|
+
return o > e && (o = e), o === e && a > 0 && (a = Math.max(0, o - l - i * 2)), {
|
|
7
|
+
start: a,
|
|
8
|
+
end: o,
|
|
9
|
+
offsetY: a * n,
|
|
10
|
+
totalHeight: e * n
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
function
|
|
14
|
-
return
|
|
13
|
+
function V(h, e) {
|
|
14
|
+
return h <= e;
|
|
15
15
|
}
|
|
16
|
-
const
|
|
16
|
+
const _ = {
|
|
17
17
|
expand: "▶",
|
|
18
18
|
collapse: "▼",
|
|
19
19
|
sortAsc: "▲",
|
|
@@ -23,7 +23,7 @@ const V = {
|
|
|
23
23
|
dragHandle: "⋮⋮",
|
|
24
24
|
toolPanel: "☰"
|
|
25
25
|
};
|
|
26
|
-
class
|
|
26
|
+
class M {
|
|
27
27
|
/**
|
|
28
28
|
* Plugin dependencies - declare other plugins this one requires.
|
|
29
29
|
*
|
|
@@ -40,8 +40,11 @@ class _ {
|
|
|
40
40
|
* ```
|
|
41
41
|
*/
|
|
42
42
|
static dependencies;
|
|
43
|
-
/**
|
|
44
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Plugin version - defaults to grid version for built-in plugins.
|
|
45
|
+
* Third-party plugins can override with their own semver.
|
|
46
|
+
*/
|
|
47
|
+
version = typeof __GRID_VERSION__ < "u" ? __GRID_VERSION__ : "dev";
|
|
45
48
|
/** CSS styles to inject into the grid's shadow DOM */
|
|
46
49
|
styles;
|
|
47
50
|
/** Custom cell renderers keyed by type name */
|
|
@@ -128,12 +131,28 @@ class _ {
|
|
|
128
131
|
emit(e, t) {
|
|
129
132
|
this.grid?.dispatchEvent?.(new CustomEvent(e, { detail: t, bubbles: !0 }));
|
|
130
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Emit a cancelable custom event from the grid.
|
|
136
|
+
* @returns `true` if the event was cancelled (preventDefault called), `false` otherwise
|
|
137
|
+
*/
|
|
138
|
+
emitCancelable(e, t) {
|
|
139
|
+
const r = new CustomEvent(e, { detail: t, bubbles: !0, cancelable: !0 });
|
|
140
|
+
return this.grid?.dispatchEvent?.(r), r.defaultPrevented;
|
|
141
|
+
}
|
|
131
142
|
/**
|
|
132
143
|
* Request a re-render of the grid.
|
|
133
144
|
*/
|
|
134
145
|
requestRender() {
|
|
135
146
|
this.grid?.requestRender?.();
|
|
136
147
|
}
|
|
148
|
+
/**
|
|
149
|
+
* Request a re-render and restore focus styling afterward.
|
|
150
|
+
* Use this when a plugin action (like expand/collapse) triggers a render
|
|
151
|
+
* but needs to maintain keyboard navigation focus.
|
|
152
|
+
*/
|
|
153
|
+
requestRenderWithFocus() {
|
|
154
|
+
this.grid?.requestRenderWithFocus?.();
|
|
155
|
+
}
|
|
137
156
|
/**
|
|
138
157
|
* Request a lightweight style update without rebuilding DOM.
|
|
139
158
|
* Use this instead of requestRender() when only CSS classes need updating.
|
|
@@ -168,10 +187,34 @@ class _ {
|
|
|
168
187
|
return this.grid?._visibleColumns ?? [];
|
|
169
188
|
}
|
|
170
189
|
/**
|
|
171
|
-
* Get the
|
|
190
|
+
* Get the grid as an HTMLElement for direct DOM operations.
|
|
191
|
+
* Use sparingly - prefer the typed GridElementRef API when possible.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```ts
|
|
195
|
+
* const width = this.gridElement.clientWidth;
|
|
196
|
+
* this.gridElement.classList.add('my-plugin-active');
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
get gridElement() {
|
|
200
|
+
return this.grid;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get the render root of the grid for DOM queries.
|
|
204
|
+
* @deprecated Use `gridElement` instead. This getter exists only for backward compatibility.
|
|
205
|
+
*
|
|
206
|
+
* With Shadow DOM removed, the grid element itself is the render root.
|
|
207
|
+
* All new code should use `this.gridElement` for DOM queries.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* // OLD (deprecated)
|
|
211
|
+
* const rows = this.shadowRoot?.querySelector('.rows');
|
|
212
|
+
*
|
|
213
|
+
* // NEW (preferred)
|
|
214
|
+
* const rows = this.gridElement.querySelector('.rows');
|
|
172
215
|
*/
|
|
173
216
|
get shadowRoot() {
|
|
174
|
-
return this.
|
|
217
|
+
return this.gridElement;
|
|
175
218
|
}
|
|
176
219
|
/**
|
|
177
220
|
* Get the disconnect signal for event listener cleanup.
|
|
@@ -199,8 +242,53 @@ class _ {
|
|
|
199
242
|
*/
|
|
200
243
|
get gridIcons() {
|
|
201
244
|
const e = this.grid?.gridConfig?.icons ?? {};
|
|
202
|
-
return { ...
|
|
245
|
+
return { ..._, ...e };
|
|
246
|
+
}
|
|
247
|
+
// #region Animation Helpers
|
|
248
|
+
/**
|
|
249
|
+
* Check if animations are enabled at the grid level.
|
|
250
|
+
* Respects gridConfig.animation.mode and the CSS variable set by the grid.
|
|
251
|
+
*
|
|
252
|
+
* Plugins should use this to skip animations when:
|
|
253
|
+
* - Animation mode is 'off' or `false`
|
|
254
|
+
* - User prefers reduced motion and mode is 'reduced-motion' (default)
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* ```ts
|
|
258
|
+
* private get animationStyle(): 'slide' | 'fade' | false {
|
|
259
|
+
* if (!this.isAnimationEnabled) return false;
|
|
260
|
+
* return this.config.animation ?? 'slide';
|
|
261
|
+
* }
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
get isAnimationEnabled() {
|
|
265
|
+
const e = this.grid?.effectiveConfig?.animation?.mode ?? "reduced-motion";
|
|
266
|
+
if (e === !1 || e === "off") return !1;
|
|
267
|
+
if (e === !0 || e === "on") return !0;
|
|
268
|
+
const t = this.gridElement;
|
|
269
|
+
return t ? getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim() !== "0" : !0;
|
|
203
270
|
}
|
|
271
|
+
/**
|
|
272
|
+
* Get the animation duration in milliseconds from CSS variable.
|
|
273
|
+
* Falls back to 200ms if not set.
|
|
274
|
+
*
|
|
275
|
+
* Plugins can use this for their animation timing to stay consistent
|
|
276
|
+
* with the grid-level animation.duration setting.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```ts
|
|
280
|
+
* element.animate(keyframes, { duration: this.animationDuration });
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
get animationDuration() {
|
|
284
|
+
const e = this.gridElement;
|
|
285
|
+
if (e) {
|
|
286
|
+
const t = getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(), r = parseInt(t, 10);
|
|
287
|
+
if (!isNaN(r)) return r;
|
|
288
|
+
}
|
|
289
|
+
return 200;
|
|
290
|
+
}
|
|
291
|
+
// #endregion
|
|
204
292
|
/**
|
|
205
293
|
* Resolve an icon value to string or HTMLElement.
|
|
206
294
|
* Checks plugin config first, then grid-level icons, then defaults.
|
|
@@ -230,28 +318,31 @@ class _ {
|
|
|
230
318
|
}
|
|
231
319
|
// #endregion
|
|
232
320
|
}
|
|
233
|
-
function
|
|
234
|
-
|
|
321
|
+
function z(h) {
|
|
322
|
+
return h.meta?.utility === !0;
|
|
323
|
+
}
|
|
324
|
+
function q(h, e, t = !1) {
|
|
325
|
+
const r = h[e.field];
|
|
235
326
|
if (e.operator === "blank")
|
|
236
327
|
return r == null || r === "";
|
|
237
328
|
if (e.operator === "notBlank")
|
|
238
329
|
return r != null && r !== "";
|
|
239
330
|
if (r == null) return !1;
|
|
240
|
-
const
|
|
331
|
+
const n = String(r), i = t ? n : n.toLowerCase(), l = t ? String(e.value) : String(e.value).toLowerCase();
|
|
241
332
|
switch (e.operator) {
|
|
242
333
|
// Text operators
|
|
243
334
|
case "contains":
|
|
244
|
-
return
|
|
335
|
+
return i.includes(l);
|
|
245
336
|
case "notContains":
|
|
246
|
-
return !
|
|
337
|
+
return !i.includes(l);
|
|
247
338
|
case "equals":
|
|
248
|
-
return
|
|
339
|
+
return i === l;
|
|
249
340
|
case "notEquals":
|
|
250
|
-
return
|
|
341
|
+
return i !== l;
|
|
251
342
|
case "startsWith":
|
|
252
|
-
return
|
|
343
|
+
return i.startsWith(l);
|
|
253
344
|
case "endsWith":
|
|
254
|
-
return
|
|
345
|
+
return i.endsWith(l);
|
|
255
346
|
// Number/Date operators (use raw numeric values)
|
|
256
347
|
case "lessThan":
|
|
257
348
|
return Number(r) < Number(e.value);
|
|
@@ -272,12 +363,12 @@ function q(p, e, t = !1) {
|
|
|
272
363
|
return !0;
|
|
273
364
|
}
|
|
274
365
|
}
|
|
275
|
-
function
|
|
276
|
-
return e.length ?
|
|
366
|
+
function B(h, e, t = !1) {
|
|
367
|
+
return e.length ? h.filter((r) => e.every((n) => q(r, n, t))) : h;
|
|
277
368
|
}
|
|
278
|
-
function
|
|
369
|
+
function Y(h) {
|
|
279
370
|
return JSON.stringify(
|
|
280
|
-
|
|
371
|
+
h.map((e) => ({
|
|
281
372
|
field: e.field,
|
|
282
373
|
operator: e.operator,
|
|
283
374
|
value: e.value,
|
|
@@ -285,18 +376,18 @@ function B(p) {
|
|
|
285
376
|
}))
|
|
286
377
|
);
|
|
287
378
|
}
|
|
288
|
-
function
|
|
379
|
+
function H(h, e) {
|
|
289
380
|
const t = /* @__PURE__ */ new Set();
|
|
290
|
-
for (const r of
|
|
291
|
-
const
|
|
292
|
-
|
|
381
|
+
for (const r of h) {
|
|
382
|
+
const n = r[e];
|
|
383
|
+
n != null && t.add(n);
|
|
293
384
|
}
|
|
294
|
-
return [...t].sort((r,
|
|
385
|
+
return [...t].sort((r, n) => typeof r == "number" && typeof n == "number" ? r - n : String(r).localeCompare(String(n)));
|
|
295
386
|
}
|
|
296
|
-
const
|
|
297
|
-
class
|
|
387
|
+
const G = '@layer tbw-plugins{tbw-grid .tbw-quick-filter-input{flex:1;max-width:300px;height:var(--tbw-input-height, 1.75rem);padding:var(--tbw-input-padding, 0 .5rem);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:var(--tbw-font-size-sm, .8125rem)}tbw-grid .tbw-quick-filter-input:focus{outline:none;border-color:var(--tbw-color-accent)}tbw-grid .header-cell.filtered:before{content:"";position:absolute;top:var(--tbw-spacing-xs, .25rem);right:var(--tbw-spacing-xs, .25rem);width:var(--tbw-indicator-size, .375rem);height:var(--tbw-indicator-size, .375rem);background:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6));border-radius:50%}tbw-grid .tbw-filter-btn{display:inline-flex;align-items:center;justify-content:center;background:transparent;border:none;cursor:pointer;padding:2px;margin-left:var(--tbw-spacing-xs, .25rem);opacity:.4;transition:opacity .15s;color:inherit;vertical-align:middle}tbw-grid .tbw-filter-btn:hover,tbw-grid .tbw-filter-btn.active{opacity:1}tbw-grid .tbw-filter-btn.active{color:var(--tbw-filter-accent, var(--tbw-color-accent, #3b82f6))}}', $ = "@layer tbw-plugins{.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, .25rem));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:var(--tbw-panel-padding, var(--tbw-spacing-lg, .75rem));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, .8125rem);transform-origin:top center}.tbw-filter-panel.tbw-filter-panel-above{transform-origin:bottom center}.tbw-filter-panel.tbw-filter-panel-animated{animation:tbw-filter-panel-enter var(--tbw-animation-duration, .15s) var(--tbw-animation-easing, ease-out)}.tbw-filter-panel.tbw-filter-panel-above.tbw-filter-panel-animated{animation:tbw-filter-panel-enter-above var(--tbw-animation-duration, .15s) var(--tbw-animation-easing, ease-out)}@keyframes tbw-filter-panel-enter{0%{opacity:0;transform:scaleY(.3) translateY(-10px)}to{opacity:1;transform:scaleY(1) translateY(0)}}@keyframes tbw-filter-panel-enter-above{0%{opacity:0;transform:scaleY(.3) translateY(10px)}to{opacity:1;transform:scaleY(1) translateY(0)}}@supports (anchor-name: --test){.tbw-filter-panel{position-anchor:--tbw-filter-anchor;top:anchor(bottom);left:anchor(left);margin-top:4px;position-try-fallbacks:flip-inline,flip-block,flip-block flip-inline}}.tbw-filter-search{margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem))}.tbw-filter-search-input{width:100%;padding:var(--tbw-button-padding, .375rem .625rem);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, var(--tbw-border-radius, .25rem));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:var(--tbw-button-padding-sm, .25rem .125rem);margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));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:var(--tbw-font-size-xs, .75rem);padding:2px 0}.tbw-filter-action-btn:hover{text-decoration:underline}.tbw-filter-values{flex:1;overflow-y:auto;margin-bottom:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));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:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));padding:var(--tbw-button-padding-sm, .25rem .125rem);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:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem)) 0;text-align:center;font-style:italic}.tbw-filter-buttons{display:flex;gap:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));padding-top:var(--tbw-panel-gap, var(--tbw-spacing-md, .5rem));border-top:1px solid var(--tbw-filter-divider, var(--tbw-color-border, light-dark(#d0d0d4, #454545)))}.tbw-filter-apply-btn{flex:1;padding:var(--tbw-button-padding, .375rem .75rem);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:var(--tbw-border-radius, .25rem);cursor:pointer;font-size:var(--tbw-font-size-sm, .8125rem)}.tbw-filter-apply-btn:hover{filter:brightness(.9)}.tbw-filter-clear-btn{flex:1;padding:var(--tbw-button-padding, .375rem .75rem);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:var(--tbw-border-radius, .25rem);cursor:pointer;font-size:var(--tbw-font-size-sm, .8125rem)}.tbw-filter-clear-btn:hover{background:var(--tbw-filter-hover, var(--tbw-color-row-hover, light-dark(#f0f6ff, #1c1c1c)))}}";
|
|
388
|
+
class g extends M {
|
|
298
389
|
name = "filtering";
|
|
299
|
-
|
|
390
|
+
styles = G;
|
|
300
391
|
get defaultConfig() {
|
|
301
392
|
return {
|
|
302
393
|
debounceMs: 300,
|
|
@@ -311,6 +402,8 @@ class x extends _ {
|
|
|
311
402
|
cacheKey = null;
|
|
312
403
|
openPanelField = null;
|
|
313
404
|
panelElement = null;
|
|
405
|
+
panelAnchorElement = null;
|
|
406
|
+
// For CSS anchor positioning cleanup
|
|
314
407
|
searchText = /* @__PURE__ */ new Map();
|
|
315
408
|
excludedValues = /* @__PURE__ */ new Map();
|
|
316
409
|
panelAbortController = null;
|
|
@@ -321,6 +414,12 @@ class x extends _ {
|
|
|
321
414
|
static LIST_OVERSCAN = 3;
|
|
322
415
|
static LIST_BYPASS_THRESHOLD = 50;
|
|
323
416
|
// Don't virtualize if < 50 items
|
|
417
|
+
/**
|
|
418
|
+
* Sync excludedValues map from a filter model (for set filters).
|
|
419
|
+
*/
|
|
420
|
+
syncExcludedValues(e, t) {
|
|
421
|
+
t ? t.type === "set" && t.operator === "notIn" && Array.isArray(t.value) ? this.excludedValues.set(e, new Set(t.value)) : t.type === "set" && this.excludedValues.delete(e) : this.excludedValues.delete(e);
|
|
422
|
+
}
|
|
324
423
|
// #endregion
|
|
325
424
|
// #region Lifecycle
|
|
326
425
|
attach(e) {
|
|
@@ -336,33 +435,33 @@ class x extends _ {
|
|
|
336
435
|
if (!t.length) return [...e];
|
|
337
436
|
if (this.config.filterHandler)
|
|
338
437
|
return this.cachedResult ? this.cachedResult : [...e];
|
|
339
|
-
const r =
|
|
438
|
+
const r = Y(t);
|
|
340
439
|
if (this.cacheKey === r && this.cachedResult)
|
|
341
440
|
return this.cachedResult;
|
|
342
|
-
const
|
|
343
|
-
return this.cachedResult =
|
|
441
|
+
const n = B([...e], t, this.config.caseSensitive);
|
|
442
|
+
return this.cachedResult = n, this.cacheKey = r, n;
|
|
344
443
|
}
|
|
345
444
|
afterRender() {
|
|
346
|
-
const e = this.
|
|
445
|
+
const e = this.gridElement;
|
|
347
446
|
if (!e) return;
|
|
348
447
|
e.querySelectorAll('[part~="header-cell"]').forEach((r) => {
|
|
349
|
-
const
|
|
350
|
-
if (
|
|
351
|
-
const
|
|
352
|
-
if (!
|
|
353
|
-
const
|
|
354
|
-
if (!
|
|
355
|
-
const
|
|
356
|
-
let
|
|
357
|
-
if (
|
|
358
|
-
|
|
448
|
+
const n = r.getAttribute("data-col");
|
|
449
|
+
if (n === null) return;
|
|
450
|
+
const i = this.visibleColumns[parseInt(n, 10)];
|
|
451
|
+
if (!i || i.filterable === !1 || z(i)) return;
|
|
452
|
+
const l = i.field;
|
|
453
|
+
if (!l) return;
|
|
454
|
+
const a = this.filters.has(l);
|
|
455
|
+
let o = r.querySelector(".tbw-filter-btn");
|
|
456
|
+
if (o) {
|
|
457
|
+
o.classList.toggle("active", a), r.classList.toggle("filtered", a);
|
|
359
458
|
return;
|
|
360
459
|
}
|
|
361
|
-
|
|
362
|
-
b.stopPropagation(), this.toggleFilterPanel(
|
|
460
|
+
o = document.createElement("button"), o.className = "tbw-filter-btn", o.setAttribute("aria-label", `Filter ${i.header ?? l}`), o.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>', a && (o.classList.add("active"), r.classList.add("filtered")), o.addEventListener("click", (b) => {
|
|
461
|
+
b.stopPropagation(), this.toggleFilterPanel(l, i, o);
|
|
363
462
|
});
|
|
364
|
-
const
|
|
365
|
-
|
|
463
|
+
const p = r.querySelector(".resize-handle");
|
|
464
|
+
p ? r.insertBefore(o, p) : r.appendChild(o);
|
|
366
465
|
});
|
|
367
466
|
}
|
|
368
467
|
// #endregion
|
|
@@ -372,7 +471,13 @@ class x extends _ {
|
|
|
372
471
|
* Pass null to remove the filter.
|
|
373
472
|
*/
|
|
374
473
|
setFilter(e, t) {
|
|
375
|
-
|
|
474
|
+
if (t === null)
|
|
475
|
+
this.filters.delete(e), this.syncExcludedValues(e, null);
|
|
476
|
+
else {
|
|
477
|
+
const r = { ...t, field: e };
|
|
478
|
+
this.filters.set(e, r), this.syncExcludedValues(e, r);
|
|
479
|
+
}
|
|
480
|
+
this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
|
|
376
481
|
filters: [...this.filters.values()],
|
|
377
482
|
filteredRowCount: 0
|
|
378
483
|
// Will be accurate after processRows
|
|
@@ -402,7 +507,7 @@ class x extends _ {
|
|
|
402
507
|
setFilterModel(e) {
|
|
403
508
|
this.filters.clear(), this.excludedValues.clear();
|
|
404
509
|
for (const t of e)
|
|
405
|
-
this.filters.set(t.field, t),
|
|
510
|
+
this.filters.set(t.field, t), this.syncExcludedValues(t.field, t);
|
|
406
511
|
this.cachedResult = null, this.cacheKey = null, this.emit("filter-change", {
|
|
407
512
|
filters: [...this.filters.values()],
|
|
408
513
|
filteredRowCount: 0
|
|
@@ -443,7 +548,7 @@ class x extends _ {
|
|
|
443
548
|
* Uses sourceRows to include all values regardless of current filter.
|
|
444
549
|
*/
|
|
445
550
|
getUniqueValues(e) {
|
|
446
|
-
return
|
|
551
|
+
return H(this.sourceRows, e);
|
|
447
552
|
}
|
|
448
553
|
// #endregion
|
|
449
554
|
// #region Private Methods
|
|
@@ -457,7 +562,7 @@ class x extends _ {
|
|
|
457
562
|
return;
|
|
458
563
|
}
|
|
459
564
|
const e = document.createElement("style");
|
|
460
|
-
e.id = "tbw-filter-panel-styles", e.textContent =
|
|
565
|
+
e.id = "tbw-filter-panel-styles", e.textContent = $, document.head.appendChild(e), this.globalStylesInjected = !0;
|
|
461
566
|
}
|
|
462
567
|
/**
|
|
463
568
|
* Toggle the filter panel for a field
|
|
@@ -468,41 +573,41 @@ class x extends _ {
|
|
|
468
573
|
return;
|
|
469
574
|
}
|
|
470
575
|
this.closeFilterPanel();
|
|
471
|
-
const
|
|
472
|
-
if (
|
|
473
|
-
|
|
474
|
-
this.openPanelField !== e || !this.panelElement || (
|
|
576
|
+
const n = document.createElement("div");
|
|
577
|
+
if (n.className = "tbw-filter-panel", this.isAnimationEnabled && n.classList.add("tbw-filter-panel-animated"), this.panelElement = n, this.openPanelField = e, this.config.valuesHandler) {
|
|
578
|
+
n.innerHTML = '<div class="tbw-filter-loading">Loading...</div>', document.body.appendChild(n), this.positionPanel(n, r), this.setupPanelCloseHandler(n, r), this.config.valuesHandler(e, t).then((l) => {
|
|
579
|
+
this.openPanelField !== e || !this.panelElement || (n.innerHTML = "", this.renderPanelContent(e, t, n, l));
|
|
475
580
|
});
|
|
476
581
|
return;
|
|
477
582
|
}
|
|
478
|
-
const
|
|
479
|
-
this.renderPanelContent(e, t,
|
|
583
|
+
const i = H(this.sourceRows, e);
|
|
584
|
+
this.renderPanelContent(e, t, n, i), document.body.appendChild(n), this.positionPanel(n, r), this.setupPanelCloseHandler(n, r);
|
|
480
585
|
}
|
|
481
586
|
/**
|
|
482
587
|
* Render filter panel content with given values
|
|
483
588
|
*/
|
|
484
|
-
renderPanelContent(e, t, r,
|
|
485
|
-
let
|
|
486
|
-
|
|
487
|
-
const
|
|
589
|
+
renderPanelContent(e, t, r, n) {
|
|
590
|
+
let i = this.excludedValues.get(e);
|
|
591
|
+
i || (i = /* @__PURE__ */ new Set(), this.excludedValues.set(e, i));
|
|
592
|
+
const l = this.searchText.get(e) ?? "", a = {
|
|
488
593
|
field: e,
|
|
489
594
|
column: t,
|
|
490
|
-
uniqueValues:
|
|
491
|
-
excludedValues:
|
|
492
|
-
searchText:
|
|
493
|
-
applySetFilter: (
|
|
494
|
-
this.applySetFilter(e,
|
|
595
|
+
uniqueValues: n,
|
|
596
|
+
excludedValues: i,
|
|
597
|
+
searchText: l,
|
|
598
|
+
applySetFilter: (p) => {
|
|
599
|
+
this.applySetFilter(e, p), this.closeFilterPanel();
|
|
495
600
|
},
|
|
496
|
-
applyTextFilter: (
|
|
497
|
-
this.applyTextFilter(e,
|
|
601
|
+
applyTextFilter: (p, b, C) => {
|
|
602
|
+
this.applyTextFilter(e, p, b, C), this.closeFilterPanel();
|
|
498
603
|
},
|
|
499
604
|
clearFilter: () => {
|
|
500
605
|
this.clearFieldFilter(e), this.closeFilterPanel();
|
|
501
606
|
},
|
|
502
607
|
closePanel: () => this.closeFilterPanel()
|
|
503
608
|
};
|
|
504
|
-
let
|
|
505
|
-
this.config.filterPanelRenderer && (this.config.filterPanelRenderer(r,
|
|
609
|
+
let o = !1;
|
|
610
|
+
this.config.filterPanelRenderer && (this.config.filterPanelRenderer(r, a), o = r.children.length > 0), o || this.renderDefaultFilterPanel(r, a, n, i);
|
|
506
611
|
}
|
|
507
612
|
/**
|
|
508
613
|
* Setup click-outside handler to close the panel
|
|
@@ -522,128 +627,146 @@ class x extends _ {
|
|
|
522
627
|
* Close the filter panel
|
|
523
628
|
*/
|
|
524
629
|
closeFilterPanel() {
|
|
525
|
-
|
|
630
|
+
const e = this.panelElement;
|
|
631
|
+
e && (e.remove(), this.panelElement = null), this.panelAnchorElement && (this.panelAnchorElement.style.anchorName = "", this.panelAnchorElement = null), this.openPanelField = null, this.panelAbortController?.abort(), this.panelAbortController = null;
|
|
526
632
|
}
|
|
633
|
+
/** Cache for CSS anchor positioning support check */
|
|
634
|
+
static supportsAnchorPositioning = null;
|
|
527
635
|
/**
|
|
528
|
-
*
|
|
636
|
+
* Check if browser supports CSS Anchor Positioning
|
|
637
|
+
*/
|
|
638
|
+
static checkAnchorPositioningSupport() {
|
|
639
|
+
return g.supportsAnchorPositioning === null && (g.supportsAnchorPositioning = CSS.supports("anchor-name", "--test")), g.supportsAnchorPositioning;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Position the panel below the header cell
|
|
643
|
+
* Uses CSS Anchor Positioning if supported, falls back to JS positioning
|
|
529
644
|
*/
|
|
530
645
|
positionPanel(e, t) {
|
|
531
|
-
const
|
|
532
|
-
|
|
646
|
+
const n = t.closest(".cell") ?? t;
|
|
647
|
+
if (n.style.anchorName = "--tbw-filter-anchor", this.panelAnchorElement = n, g.checkAnchorPositioningSupport()) {
|
|
648
|
+
requestAnimationFrame(() => {
|
|
649
|
+
const l = e.getBoundingClientRect(), a = n.getBoundingClientRect();
|
|
650
|
+
l.top < a.top && e.classList.add("tbw-filter-panel-above");
|
|
651
|
+
});
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
const i = n.getBoundingClientRect();
|
|
655
|
+
e.style.position = "fixed", e.style.top = `${i.bottom + 4}px`, e.style.left = `${i.left}px`, requestAnimationFrame(() => {
|
|
533
656
|
const l = e.getBoundingClientRect();
|
|
534
|
-
l.right > window.innerWidth - 8 && (e.style.left = `${
|
|
657
|
+
l.right > window.innerWidth - 8 && (e.style.left = `${i.right - l.width}px`), l.bottom > window.innerHeight - 8 && (e.style.top = `${i.top - l.height - 4}px`, e.classList.add("tbw-filter-panel-above"));
|
|
535
658
|
});
|
|
536
659
|
}
|
|
537
660
|
/**
|
|
538
661
|
* Render the default filter panel content
|
|
539
662
|
*/
|
|
540
|
-
renderDefaultFilterPanel(e, t, r,
|
|
541
|
-
const { field:
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
const
|
|
548
|
-
|
|
663
|
+
renderDefaultFilterPanel(e, t, r, n) {
|
|
664
|
+
const { field: i } = t, l = document.createElement("div");
|
|
665
|
+
l.className = "tbw-filter-search";
|
|
666
|
+
const a = document.createElement("input");
|
|
667
|
+
a.type = "text", a.placeholder = "Search...", a.className = "tbw-filter-search-input", a.value = this.searchText.get(i) ?? "", l.appendChild(a), e.appendChild(l);
|
|
668
|
+
const o = document.createElement("div");
|
|
669
|
+
o.className = "tbw-filter-actions";
|
|
670
|
+
const p = document.createElement("label");
|
|
671
|
+
p.className = "tbw-filter-value-item", p.style.padding = "0", p.style.margin = "0";
|
|
549
672
|
const b = document.createElement("input");
|
|
550
673
|
b.type = "checkbox", b.className = "tbw-filter-checkbox";
|
|
551
674
|
const C = document.createElement("span");
|
|
552
|
-
C.textContent = "Select All",
|
|
553
|
-
const
|
|
554
|
-
const
|
|
555
|
-
b.checked = u, b.indeterminate = !u && !
|
|
675
|
+
C.textContent = "Select All", p.appendChild(b), p.appendChild(C), o.appendChild(p);
|
|
676
|
+
const T = () => {
|
|
677
|
+
const s = [...y.values()], u = s.every((c) => c), w = s.every((c) => !c);
|
|
678
|
+
b.checked = u, b.indeterminate = !u && !w;
|
|
556
679
|
};
|
|
557
680
|
b.addEventListener("change", () => {
|
|
558
|
-
const
|
|
559
|
-
for (const u of
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
}), e.appendChild(
|
|
681
|
+
const s = b.checked;
|
|
682
|
+
for (const u of y.keys())
|
|
683
|
+
y.set(u, s);
|
|
684
|
+
T(), A();
|
|
685
|
+
}), e.appendChild(o);
|
|
563
686
|
const v = document.createElement("div");
|
|
564
687
|
v.className = "tbw-filter-values";
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
const
|
|
570
|
-
r.forEach((
|
|
571
|
-
const u =
|
|
572
|
-
|
|
573
|
-
}),
|
|
574
|
-
let
|
|
575
|
-
const
|
|
576
|
-
const
|
|
577
|
-
|
|
578
|
-
const
|
|
579
|
-
|
|
580
|
-
|
|
688
|
+
const E = document.createElement("div");
|
|
689
|
+
E.className = "tbw-filter-values-spacer", v.appendChild(E);
|
|
690
|
+
const m = document.createElement("div");
|
|
691
|
+
m.className = "tbw-filter-values-content", v.appendChild(m);
|
|
692
|
+
const y = /* @__PURE__ */ new Map();
|
|
693
|
+
r.forEach((s) => {
|
|
694
|
+
const u = s == null ? "__null__" : String(s);
|
|
695
|
+
y.set(u, !n.has(s));
|
|
696
|
+
}), T();
|
|
697
|
+
let x = [];
|
|
698
|
+
const F = (s, u) => {
|
|
699
|
+
const w = s == null ? "(Blank)" : String(s), c = s == null ? "__null__" : String(s), d = document.createElement("label");
|
|
700
|
+
d.className = "tbw-filter-value-item", d.style.position = "absolute", d.style.top = `${u * g.LIST_ITEM_HEIGHT}px`, d.style.left = "0", d.style.right = "0", d.style.height = `${g.LIST_ITEM_HEIGHT}px`, d.style.boxSizing = "border-box";
|
|
701
|
+
const f = document.createElement("input");
|
|
702
|
+
f.type = "checkbox", f.className = "tbw-filter-checkbox", f.checked = y.get(c) ?? !0, f.dataset.value = c, f.addEventListener("change", () => {
|
|
703
|
+
y.set(c, f.checked), T();
|
|
581
704
|
});
|
|
582
|
-
const
|
|
583
|
-
return
|
|
584
|
-
},
|
|
585
|
-
const
|
|
586
|
-
if (
|
|
587
|
-
|
|
588
|
-
|
|
705
|
+
const N = document.createElement("span");
|
|
706
|
+
return N.textContent = w, d.appendChild(f), d.appendChild(N), d;
|
|
707
|
+
}, A = () => {
|
|
708
|
+
const s = x.length, u = v.clientHeight, w = v.scrollTop;
|
|
709
|
+
if (E.style.height = `${s * g.LIST_ITEM_HEIGHT}px`, V(s, g.LIST_BYPASS_THRESHOLD / 3)) {
|
|
710
|
+
m.innerHTML = "", m.style.transform = "translateY(0px)", x.forEach((d, f) => {
|
|
711
|
+
m.appendChild(F(d, f));
|
|
589
712
|
});
|
|
590
713
|
return;
|
|
591
714
|
}
|
|
592
|
-
const
|
|
593
|
-
totalRows:
|
|
715
|
+
const c = P({
|
|
716
|
+
totalRows: s,
|
|
594
717
|
viewportHeight: u,
|
|
595
|
-
scrollTop:
|
|
596
|
-
rowHeight:
|
|
597
|
-
overscan:
|
|
718
|
+
scrollTop: w,
|
|
719
|
+
rowHeight: g.LIST_ITEM_HEIGHT,
|
|
720
|
+
overscan: g.LIST_OVERSCAN
|
|
598
721
|
});
|
|
599
|
-
|
|
600
|
-
for (let
|
|
601
|
-
|
|
602
|
-
},
|
|
603
|
-
const u =
|
|
604
|
-
if (
|
|
605
|
-
const d =
|
|
606
|
-
return !
|
|
607
|
-
}),
|
|
608
|
-
|
|
609
|
-
const
|
|
610
|
-
|
|
722
|
+
m.style.transform = `translateY(${c.offsetY}px)`, m.innerHTML = "";
|
|
723
|
+
for (let d = c.start; d < c.end; d++)
|
|
724
|
+
m.appendChild(F(x[d], d - c.start));
|
|
725
|
+
}, I = (s) => {
|
|
726
|
+
const u = this.config.caseSensitive ?? !1, w = u ? s : s.toLowerCase();
|
|
727
|
+
if (x = r.filter((c) => {
|
|
728
|
+
const d = c == null ? "(Blank)" : String(c), f = u ? d : d.toLowerCase();
|
|
729
|
+
return !s || f.includes(w);
|
|
730
|
+
}), x.length === 0) {
|
|
731
|
+
E.style.height = "0px", m.innerHTML = "";
|
|
732
|
+
const c = document.createElement("div");
|
|
733
|
+
c.className = "tbw-filter-no-match", c.textContent = "No matching values", m.appendChild(c);
|
|
611
734
|
return;
|
|
612
735
|
}
|
|
613
|
-
|
|
736
|
+
A();
|
|
614
737
|
};
|
|
615
738
|
v.addEventListener(
|
|
616
739
|
"scroll",
|
|
617
740
|
() => {
|
|
618
|
-
|
|
741
|
+
x.length > 0 && A();
|
|
619
742
|
},
|
|
620
743
|
{ passive: !0 }
|
|
621
|
-
),
|
|
622
|
-
let
|
|
623
|
-
|
|
624
|
-
clearTimeout(
|
|
625
|
-
this.searchText.set(
|
|
744
|
+
), I(a.value), e.appendChild(v);
|
|
745
|
+
let L;
|
|
746
|
+
a.addEventListener("input", () => {
|
|
747
|
+
clearTimeout(L), L = setTimeout(() => {
|
|
748
|
+
this.searchText.set(i, a.value), I(a.value);
|
|
626
749
|
}, this.config.debounceMs ?? 150);
|
|
627
750
|
});
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
const
|
|
633
|
-
for (const [u,
|
|
634
|
-
if (!
|
|
751
|
+
const S = document.createElement("div");
|
|
752
|
+
S.className = "tbw-filter-buttons";
|
|
753
|
+
const R = document.createElement("button");
|
|
754
|
+
R.className = "tbw-filter-apply-btn", R.textContent = "Apply", R.addEventListener("click", () => {
|
|
755
|
+
const s = [];
|
|
756
|
+
for (const [u, w] of y)
|
|
757
|
+
if (!w)
|
|
635
758
|
if (u === "__null__")
|
|
636
|
-
|
|
759
|
+
s.push(null);
|
|
637
760
|
else {
|
|
638
|
-
const
|
|
639
|
-
|
|
761
|
+
const c = r.find((d) => String(d) === u);
|
|
762
|
+
s.push(c !== void 0 ? c : u);
|
|
640
763
|
}
|
|
641
|
-
t.applySetFilter(
|
|
642
|
-
}),
|
|
643
|
-
const
|
|
644
|
-
|
|
764
|
+
t.applySetFilter(s);
|
|
765
|
+
}), S.appendChild(R);
|
|
766
|
+
const k = document.createElement("button");
|
|
767
|
+
k.className = "tbw-filter-clear-btn", k.textContent = "Clear Filter", k.addEventListener("click", () => {
|
|
645
768
|
t.clearFilter();
|
|
646
|
-
}),
|
|
769
|
+
}), S.appendChild(k), e.appendChild(S);
|
|
647
770
|
}
|
|
648
771
|
/**
|
|
649
772
|
* Apply a set filter (exclude values)
|
|
@@ -659,13 +782,13 @@ class x extends _ {
|
|
|
659
782
|
/**
|
|
660
783
|
* Apply a text filter
|
|
661
784
|
*/
|
|
662
|
-
applyTextFilter(e, t, r,
|
|
785
|
+
applyTextFilter(e, t, r, n) {
|
|
663
786
|
this.filters.set(e, {
|
|
664
787
|
field: e,
|
|
665
788
|
type: "text",
|
|
666
789
|
operator: t,
|
|
667
790
|
value: r,
|
|
668
|
-
valueTo:
|
|
791
|
+
valueTo: n
|
|
669
792
|
}), this.applyFiltersInternal();
|
|
670
793
|
}
|
|
671
794
|
/**
|
|
@@ -677,13 +800,13 @@ class x extends _ {
|
|
|
677
800
|
if (this.config.filterHandler) {
|
|
678
801
|
const t = this.grid;
|
|
679
802
|
t.setAttribute("aria-busy", "true");
|
|
680
|
-
const r = this.config.filterHandler(e, this.sourceRows),
|
|
681
|
-
t.removeAttribute("aria-busy"), this.cachedResult =
|
|
803
|
+
const r = this.config.filterHandler(e, this.sourceRows), n = (i) => {
|
|
804
|
+
t.removeAttribute("aria-busy"), this.cachedResult = i, this.grid.rows = i, this.emit("filter-change", {
|
|
682
805
|
filters: e,
|
|
683
|
-
filteredRowCount:
|
|
806
|
+
filteredRowCount: i.length
|
|
684
807
|
}), this.requestRender();
|
|
685
808
|
};
|
|
686
|
-
r && typeof r.then == "function" ? r.then(
|
|
809
|
+
r && typeof r.then == "function" ? r.then(n) : n(r);
|
|
687
810
|
return;
|
|
688
811
|
}
|
|
689
812
|
this.emit("filter-change", {
|
|
@@ -726,11 +849,8 @@ class x extends _ {
|
|
|
726
849
|
this.filters.set(e, r), this.cachedResult = null, this.cacheKey = null;
|
|
727
850
|
}
|
|
728
851
|
// #endregion
|
|
729
|
-
// #region Styles
|
|
730
|
-
styles = $;
|
|
731
|
-
// #endregion
|
|
732
852
|
}
|
|
733
853
|
export {
|
|
734
|
-
|
|
854
|
+
g as FilteringPlugin
|
|
735
855
|
};
|
|
736
856
|
//# sourceMappingURL=index.js.map
|