@toolbox-web/grid 1.23.4 → 1.24.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 +35 -6
- package/all.d.ts +2 -2
- package/all.d.ts.map +1 -1
- package/all.js +2 -2
- package/all.js.map +1 -1
- package/index.js +1 -1
- 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/feature-hook.d.ts +8 -0
- package/lib/core/internal/feature-hook.d.ts.map +1 -0
- package/lib/core/plugin/base-plugin.d.ts +8 -2
- package/lib/core/plugin/base-plugin.d.ts.map +1 -1
- package/lib/core/plugin/types.d.ts +1 -1
- package/lib/core/types.d.ts +59 -0
- package/lib/core/types.d.ts.map +1 -1
- package/lib/features/clipboard.d.ts +8 -0
- package/lib/features/clipboard.d.ts.map +1 -0
- package/lib/features/clipboard.js +2 -0
- package/lib/features/clipboard.js.map +1 -0
- package/lib/features/column-virtualization.d.ts +8 -0
- package/lib/features/column-virtualization.d.ts.map +1 -0
- package/lib/features/column-virtualization.js +2 -0
- package/lib/features/column-virtualization.js.map +1 -0
- package/lib/features/context-menu.d.ts +8 -0
- package/lib/features/context-menu.d.ts.map +1 -0
- package/lib/features/context-menu.js +2 -0
- package/lib/features/context-menu.js.map +1 -0
- package/lib/features/editing.d.ts +8 -0
- package/lib/features/editing.d.ts.map +1 -0
- package/lib/features/editing.js +2 -0
- package/lib/features/editing.js.map +1 -0
- package/lib/features/export.d.ts +8 -0
- package/lib/features/export.d.ts.map +1 -0
- package/lib/features/export.js +2 -0
- package/lib/features/export.js.map +1 -0
- package/lib/features/filtering.d.ts +8 -0
- package/lib/features/filtering.d.ts.map +1 -0
- package/lib/features/filtering.js +2 -0
- package/lib/features/filtering.js.map +1 -0
- package/lib/features/grouping-columns.d.ts +8 -0
- package/lib/features/grouping-columns.d.ts.map +1 -0
- package/lib/features/grouping-columns.js +2 -0
- package/lib/features/grouping-columns.js.map +1 -0
- package/lib/features/grouping-rows.d.ts +8 -0
- package/lib/features/grouping-rows.d.ts.map +1 -0
- package/lib/features/grouping-rows.js +2 -0
- package/lib/features/grouping-rows.js.map +1 -0
- package/lib/features/magic-string.es-CkyDP9Ir.mjs.map +1 -0
- package/lib/features/master-detail.d.ts +8 -0
- package/lib/features/master-detail.d.ts.map +1 -0
- package/lib/features/master-detail.js +2 -0
- package/lib/features/master-detail.js.map +1 -0
- package/lib/features/multi-sort.d.ts +10 -0
- package/lib/features/multi-sort.d.ts.map +1 -0
- package/lib/features/multi-sort.js +2 -0
- package/lib/features/multi-sort.js.map +1 -0
- package/lib/features/pinned-columns.d.ts +18 -0
- package/lib/features/pinned-columns.d.ts.map +1 -0
- package/lib/features/pinned-columns.js +2 -0
- package/lib/features/pinned-columns.js.map +1 -0
- package/lib/features/pinned-rows.d.ts +8 -0
- package/lib/features/pinned-rows.d.ts.map +1 -0
- package/lib/features/pinned-rows.js +2 -0
- package/lib/features/pinned-rows.js.map +1 -0
- package/lib/features/pivot.d.ts +8 -0
- package/lib/features/pivot.d.ts.map +1 -0
- package/lib/features/pivot.js +2 -0
- package/lib/features/pivot.js.map +1 -0
- package/lib/features/print.d.ts +8 -0
- package/lib/features/print.d.ts.map +1 -0
- package/lib/features/print.js +2 -0
- package/lib/features/print.js.map +1 -0
- package/lib/features/registry.d.ts +50 -0
- package/lib/features/registry.d.ts.map +1 -0
- package/lib/features/registry.js +2 -0
- package/lib/features/registry.js.map +1 -0
- package/lib/features/registry.spec.js +5 -0
- package/lib/features/registry.spec.js.map +1 -0
- package/lib/features/reorder-columns.d.ts +10 -0
- package/lib/features/reorder-columns.d.ts.map +1 -0
- package/lib/features/reorder-columns.js +2 -0
- package/lib/features/reorder-columns.js.map +1 -0
- package/lib/features/reorder-rows.d.ts +10 -0
- package/lib/features/reorder-rows.d.ts.map +1 -0
- package/lib/features/reorder-rows.js +2 -0
- package/lib/features/reorder-rows.js.map +1 -0
- package/lib/features/responsive.d.ts +8 -0
- package/lib/features/responsive.d.ts.map +1 -0
- package/lib/features/responsive.js +2 -0
- package/lib/features/responsive.js.map +1 -0
- package/lib/features/selection.d.ts +8 -0
- package/lib/features/selection.d.ts.map +1 -0
- package/lib/features/selection.js +2 -0
- package/lib/features/selection.js.map +1 -0
- package/lib/features/server-side.d.ts +8 -0
- package/lib/features/server-side.d.ts.map +1 -0
- package/lib/features/server-side.js +2 -0
- package/lib/features/server-side.js.map +1 -0
- package/lib/features/tree.d.ts +8 -0
- package/lib/features/tree.d.ts.map +1 -0
- package/lib/features/tree.js +2 -0
- package/lib/features/tree.js.map +1 -0
- package/lib/features/undo-redo.d.ts +8 -0
- package/lib/features/undo-redo.d.ts.map +1 -0
- package/lib/features/undo-redo.js +2 -0
- package/lib/features/undo-redo.js.map +1 -0
- package/lib/features/visibility.d.ts +8 -0
- package/lib/features/visibility.d.ts.map +1 -0
- package/lib/features/visibility.js +2 -0
- package/lib/features/visibility.js.map +1 -0
- package/lib/plugins/clipboard/index.js +1 -1
- package/lib/plugins/clipboard/index.js.map +1 -1
- package/lib/plugins/column-virtualization/index.js +1 -1
- package/lib/plugins/column-virtualization/index.js.map +1 -1
- package/lib/plugins/context-menu/index.js +1 -1
- package/lib/plugins/context-menu/index.js.map +1 -1
- package/lib/plugins/editing/index.js +1 -1
- package/lib/plugins/editing/index.js.map +1 -1
- package/lib/plugins/export/index.js +1 -1
- package/lib/plugins/export/index.js.map +1 -1
- package/lib/plugins/filtering/index.js +1 -1
- package/lib/plugins/filtering/index.js.map +1 -1
- package/lib/plugins/filtering/types.d.ts +428 -27
- package/lib/plugins/filtering/types.d.ts.map +1 -1
- package/lib/plugins/grouping-columns/index.d.ts +1 -1
- package/lib/plugins/grouping-columns/index.js +1 -1
- package/lib/plugins/grouping-columns/index.js.map +1 -1
- package/lib/plugins/grouping-rows/index.d.ts +2 -2
- package/lib/plugins/grouping-rows/index.d.ts.map +1 -1
- package/lib/plugins/grouping-rows/index.js +1 -1
- package/lib/plugins/grouping-rows/index.js.map +1 -1
- package/lib/plugins/master-detail/MasterDetailPlugin.d.ts +2 -2
- package/lib/plugins/master-detail/index.js +1 -1
- package/lib/plugins/master-detail/index.js.map +1 -1
- package/lib/plugins/multi-sort/index.js +1 -1
- package/lib/plugins/multi-sort/index.js.map +1 -1
- package/lib/plugins/pinned-columns/index.js +1 -1
- package/lib/plugins/pinned-columns/index.js.map +1 -1
- package/lib/plugins/pinned-columns/types.d.ts +3 -3
- package/lib/plugins/pinned-rows/index.js +1 -1
- package/lib/plugins/pinned-rows/index.js.map +1 -1
- package/lib/plugins/pivot/index.js +1 -1
- package/lib/plugins/pivot/index.js.map +1 -1
- package/lib/plugins/print/index.js +1 -1
- package/lib/plugins/print/index.js.map +1 -1
- package/lib/plugins/{reorder → reorder-columns}/ReorderPlugin.d.ts +5 -3
- package/lib/plugins/reorder-columns/ReorderPlugin.d.ts.map +1 -0
- package/lib/plugins/reorder-columns/column-drag.d.ts.map +1 -0
- package/lib/plugins/{reorder → reorder-columns}/index.d.ts +2 -2
- package/lib/plugins/reorder-columns/index.d.ts.map +1 -0
- package/lib/plugins/reorder-columns/index.js +2 -0
- package/lib/plugins/reorder-columns/index.js.map +1 -0
- package/lib/plugins/{reorder → reorder-columns}/types.d.ts +5 -0
- package/lib/plugins/reorder-columns/types.d.ts.map +1 -0
- package/lib/plugins/{row-reorder → reorder-rows}/RowReorderPlugin.d.ts +5 -3
- package/lib/plugins/reorder-rows/RowReorderPlugin.d.ts.map +1 -0
- package/lib/plugins/{row-reorder → reorder-rows}/index.d.ts +2 -2
- package/lib/plugins/reorder-rows/index.d.ts.map +1 -0
- package/lib/plugins/reorder-rows/index.js +2 -0
- package/lib/plugins/reorder-rows/index.js.map +1 -0
- package/lib/plugins/{row-reorder → reorder-rows}/types.d.ts +5 -0
- package/lib/plugins/reorder-rows/types.d.ts.map +1 -0
- package/lib/plugins/responsive/ResponsivePlugin.d.ts +2 -2
- package/lib/plugins/responsive/index.js +1 -1
- package/lib/plugins/responsive/index.js.map +1 -1
- package/lib/plugins/selection/index.js +1 -1
- package/lib/plugins/selection/index.js.map +1 -1
- package/lib/plugins/server-side/index.js +1 -1
- package/lib/plugins/server-side/index.js.map +1 -1
- package/lib/plugins/tree/index.js +1 -1
- package/lib/plugins/tree/index.js.map +1 -1
- package/lib/plugins/undo-redo/index.js +1 -1
- package/lib/plugins/undo-redo/index.js.map +1 -1
- package/lib/plugins/visibility/VisibilityPlugin.d.ts +1 -1
- package/lib/plugins/visibility/index.js +1 -1
- package/lib/plugins/visibility/index.js.map +1 -1
- package/package.json +17 -2
- package/public.d.ts +9 -2
- package/public.d.ts.map +1 -1
- package/umd/grid.all.umd.js +1 -1
- package/umd/grid.all.umd.js.map +1 -1
- package/umd/grid.umd.js +1 -1
- package/umd/grid.umd.js.map +1 -1
- package/umd/plugins/master-detail.umd.js.map +1 -1
- package/umd/plugins/reorder-columns.umd.js +2 -0
- package/umd/plugins/reorder-columns.umd.js.map +1 -0
- package/umd/plugins/reorder-rows.umd.js +2 -0
- package/umd/plugins/reorder-rows.umd.js.map +1 -0
- package/umd/plugins/responsive.umd.js.map +1 -1
- package/umd/plugins/visibility.umd.js.map +1 -1
- package/lib/plugins/reorder/ReorderPlugin.d.ts.map +0 -1
- package/lib/plugins/reorder/column-drag.d.ts.map +0 -1
- package/lib/plugins/reorder/index.d.ts.map +0 -1
- package/lib/plugins/reorder/index.js +0 -2
- package/lib/plugins/reorder/index.js.map +0 -1
- package/lib/plugins/reorder/types.d.ts.map +0 -1
- package/lib/plugins/row-reorder/RowReorderPlugin.d.ts.map +0 -1
- package/lib/plugins/row-reorder/index.d.ts.map +0 -1
- package/lib/plugins/row-reorder/index.js +0 -2
- package/lib/plugins/row-reorder/index.js.map +0 -1
- package/lib/plugins/row-reorder/types.d.ts.map +0 -1
- package/umd/plugins/reorder.umd.js +0 -2
- package/umd/plugins/reorder.umd.js.map +0 -1
- package/umd/plugins/row-reorder.umd.js +0 -2
- package/umd/plugins/row-reorder.umd.js.map +0 -1
- /package/lib/plugins/{reorder → reorder-columns}/column-drag.d.ts +0 -0
|
@@ -300,27 +300,191 @@ export interface FilterModel {
|
|
|
300
300
|
/** Secondary value for 'between' operator */
|
|
301
301
|
valueTo?: unknown;
|
|
302
302
|
}
|
|
303
|
-
/**
|
|
303
|
+
/**
|
|
304
|
+
* Parameters passed to a custom {@link FilterPanelRenderer} when the filter panel
|
|
305
|
+
* opens for a column. Provides all the state and action callbacks needed to build
|
|
306
|
+
* a fully custom filter UI.
|
|
307
|
+
*
|
|
308
|
+
* The object is created fresh each time the panel opens and captures the current
|
|
309
|
+
* filter state for the column. Use the action methods (`applySetFilter`,
|
|
310
|
+
* `applyTextFilter`, `clearFilter`, `closePanel`) to drive filtering — they
|
|
311
|
+
* handle state updates, re-rendering, and panel lifecycle automatically.
|
|
312
|
+
*
|
|
313
|
+
* **Resolution priority** for filter panel renderers:
|
|
314
|
+
* 1. Plugin-level `filterPanelRenderer` (in `FilterConfig`)
|
|
315
|
+
* 2. Type-level `filterPanelRenderer` (in `typeDefaults`)
|
|
316
|
+
* 3. Built-in default panel (checkbox set filter, number range, or date range)
|
|
317
|
+
*
|
|
318
|
+
* Returning `undefined` from a plugin-level renderer falls through to the next
|
|
319
|
+
* level, so you can override only specific columns/fields while keeping defaults
|
|
320
|
+
* for the rest.
|
|
321
|
+
*
|
|
322
|
+
* **Framework adapters** wrap this for idiomatic usage:
|
|
323
|
+
* - **Angular**: Extend `BaseFilterPanel` — params are available as a signal input.
|
|
324
|
+
* - **React**: Use a single-argument `(params) => ReactNode` signature.
|
|
325
|
+
* - **Vue**: Use a single-argument `(params) => VNode` signature.
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```typescript
|
|
329
|
+
* // Vanilla: radio-button filter for a "status" column, default for everything else
|
|
330
|
+
* new FilteringPlugin({
|
|
331
|
+
* filterPanelRenderer: (container, params) => {
|
|
332
|
+
* if (params.field !== 'status') return undefined; // fall through to default
|
|
333
|
+
*
|
|
334
|
+
* const options = ['All', ...params.uniqueValues.map(String)];
|
|
335
|
+
* options.forEach(opt => {
|
|
336
|
+
* const label = document.createElement('label');
|
|
337
|
+
* label.style.display = 'block';
|
|
338
|
+
* const radio = document.createElement('input');
|
|
339
|
+
* radio.type = 'radio';
|
|
340
|
+
* radio.name = 'status';
|
|
341
|
+
* radio.checked = opt === 'All' && params.excludedValues.size === 0;
|
|
342
|
+
* radio.addEventListener('change', () => {
|
|
343
|
+
* if (opt === 'All') params.clearFilter();
|
|
344
|
+
* else params.applySetFilter(
|
|
345
|
+
* params.uniqueValues.filter(v => String(v) !== opt) as unknown[]
|
|
346
|
+
* );
|
|
347
|
+
* });
|
|
348
|
+
* label.append(radio, ` ${opt}`);
|
|
349
|
+
* container.appendChild(label);
|
|
350
|
+
* });
|
|
351
|
+
* },
|
|
352
|
+
* });
|
|
353
|
+
* ```
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```typescript
|
|
357
|
+
* // React: custom slider filter via single-argument signature
|
|
358
|
+
* <DataGrid
|
|
359
|
+
* filtering={{
|
|
360
|
+
* filterPanelRenderer: (params) => (
|
|
361
|
+
* <MySliderFilter
|
|
362
|
+
* min={0} max={100}
|
|
363
|
+
* currentFilter={params.currentFilter}
|
|
364
|
+
* onApply={(min, max) => params.applyTextFilter('between', min, max)}
|
|
365
|
+
* onClear={() => params.clearFilter()}
|
|
366
|
+
* />
|
|
367
|
+
* ),
|
|
368
|
+
* }}
|
|
369
|
+
* />
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
304
372
|
export interface FilterPanelParams {
|
|
305
|
-
/**
|
|
373
|
+
/**
|
|
374
|
+
* The field name (column key) being filtered.
|
|
375
|
+
* Matches {@link ColumnConfig.field} — use it to conditionally render
|
|
376
|
+
* different UIs for different columns in a shared renderer.
|
|
377
|
+
*/
|
|
306
378
|
field: string;
|
|
307
|
-
/**
|
|
379
|
+
/**
|
|
380
|
+
* The full column configuration for the filtered column.
|
|
381
|
+
* Useful for reading `column.type`, `column.filterParams`, `column.header`,
|
|
382
|
+
* or any other column metadata to tailor the filter panel UI.
|
|
383
|
+
*/
|
|
308
384
|
column: ColumnConfig;
|
|
309
|
-
/**
|
|
385
|
+
/**
|
|
386
|
+
* All unique values present in the current dataset for this field,
|
|
387
|
+
* sorted and de-duplicated. For columns with a `filterValue` extractor,
|
|
388
|
+
* these are the extracted/flattened values (not the raw cell values).
|
|
389
|
+
*
|
|
390
|
+
* When a `valuesHandler` is provided in the plugin config, this array
|
|
391
|
+
* contains the values returned by the handler instead of locally-extracted ones.
|
|
392
|
+
*
|
|
393
|
+
* Typical use: render checkboxes, radio buttons, or a searchable list.
|
|
394
|
+
*/
|
|
310
395
|
uniqueValues: unknown[];
|
|
311
|
-
/**
|
|
396
|
+
/**
|
|
397
|
+
* Currently excluded values for set-type (`notIn`) filters.
|
|
398
|
+
* An empty `Set` means no values are excluded (i.e., all values are shown).
|
|
399
|
+
*
|
|
400
|
+
* Use this to restore checkbox/toggle states when the panel re-opens.
|
|
401
|
+
* A value present in this set should appear **unchecked** in a set filter UI.
|
|
402
|
+
*/
|
|
312
403
|
excludedValues: Set<unknown>;
|
|
313
|
-
/**
|
|
404
|
+
/**
|
|
405
|
+
* The current search text the user has typed into the filter panel's
|
|
406
|
+
* search input (if any). Persisted across panel open/close cycles for
|
|
407
|
+
* the same field. Defaults to `''` when no search has been performed.
|
|
408
|
+
*
|
|
409
|
+
* Use this to pre-populate a search box if your custom panel includes one.
|
|
410
|
+
*/
|
|
314
411
|
searchText: string;
|
|
315
|
-
/**
|
|
412
|
+
/**
|
|
413
|
+
* The currently active {@link FilterModel} for this field, or `undefined`
|
|
414
|
+
* if no filter is applied. Inspect this to reflect the active filter state
|
|
415
|
+
* in your UI (e.g., highlight the active operator, show the current value).
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```typescript
|
|
419
|
+
* if (params.currentFilter?.operator === 'between') {
|
|
420
|
+
* minInput.value = String(params.currentFilter.value);
|
|
421
|
+
* maxInput.value = String(params.currentFilter.valueTo);
|
|
422
|
+
* }
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
316
425
|
currentFilter?: FilterModel;
|
|
317
|
-
/**
|
|
426
|
+
/**
|
|
427
|
+
* Apply a **set filter** (`notIn` operator) that excludes the given values.
|
|
428
|
+
* Rows whose field value is in `excludedValues` will be hidden.
|
|
429
|
+
*
|
|
430
|
+
* Calling this automatically closes the panel and triggers a filter-change event.
|
|
431
|
+
*
|
|
432
|
+
* Pass an empty array to clear the set filter (show all values).
|
|
433
|
+
*
|
|
434
|
+
* @param excludedValues - Array of values to exclude.
|
|
435
|
+
* @param valueTo - Optional metadata stored alongside the filter
|
|
436
|
+
* (e.g., a label, date range, or selected category). Accessible later
|
|
437
|
+
* via `FilterModel.valueTo` in the `filter-change` event or `currentFilter`.
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* ```typescript
|
|
441
|
+
* // Exclude "Inactive" and "Archived" statuses
|
|
442
|
+
* params.applySetFilter(['Inactive', 'Archived']);
|
|
443
|
+
*
|
|
444
|
+
* // Exclude everything except the selected value
|
|
445
|
+
* const excluded = params.uniqueValues.filter(v => v !== selectedValue);
|
|
446
|
+
* params.applySetFilter(excluded as unknown[]);
|
|
447
|
+
* ```
|
|
448
|
+
*/
|
|
318
449
|
applySetFilter: (excludedValues: unknown[], valueTo?: unknown) => void;
|
|
319
|
-
/**
|
|
450
|
+
/**
|
|
451
|
+
* Apply a **text, number, or date filter** with the given operator and value(s).
|
|
452
|
+
*
|
|
453
|
+
* Calling this automatically closes the panel and triggers a filter-change event.
|
|
454
|
+
*
|
|
455
|
+
* @param operator - The filter operator to apply (e.g., `'contains'`,
|
|
456
|
+
* `'greaterThan'`, `'between'`). See {@link FilterOperator} for all options.
|
|
457
|
+
* @param value - The primary filter value.
|
|
458
|
+
* @param valueTo - Secondary value required by the `'between'` operator
|
|
459
|
+
* (defines the upper bound of the range).
|
|
460
|
+
*
|
|
461
|
+
* @example
|
|
462
|
+
* ```typescript
|
|
463
|
+
* // Text: contains search
|
|
464
|
+
* params.applyTextFilter('contains', searchInput.value);
|
|
465
|
+
*
|
|
466
|
+
* // Number: range between 10 and 100
|
|
467
|
+
* params.applyTextFilter('between', 10, 100);
|
|
468
|
+
*
|
|
469
|
+
* // Date: after a specific date
|
|
470
|
+
* params.applyTextFilter('greaterThan', '2025-01-01');
|
|
471
|
+
* ```
|
|
472
|
+
*/
|
|
320
473
|
applyTextFilter: (operator: FilterOperator, value: string | number, valueTo?: string | number) => void;
|
|
321
|
-
/**
|
|
474
|
+
/**
|
|
475
|
+
* Clear the active filter for this field entirely and close the panel.
|
|
476
|
+
* After calling, the column will show all rows (as if no filter was ever applied).
|
|
477
|
+
*
|
|
478
|
+
* Equivalent to removing the field's entry from the filter model.
|
|
479
|
+
*/
|
|
322
480
|
clearFilter: () => void;
|
|
323
|
-
/**
|
|
481
|
+
/**
|
|
482
|
+
* Close the filter panel **without** applying or clearing any filter.
|
|
483
|
+
* Use this for a "Cancel" / dismiss action where the user abandons changes.
|
|
484
|
+
*
|
|
485
|
+
* Note: `applySetFilter`, `applyTextFilter`, and `clearFilter` already close
|
|
486
|
+
* the panel automatically — you only need `closePanel` for explicit dismiss.
|
|
487
|
+
*/
|
|
324
488
|
closePanel: () => void;
|
|
325
489
|
}
|
|
326
490
|
/** Custom filter panel renderer function. Return undefined to use default panel for this column. */
|
|
@@ -367,17 +531,163 @@ export type FilterValuesHandler = (field: string, column: ColumnConfig) => Promi
|
|
|
367
531
|
* ```
|
|
368
532
|
*/
|
|
369
533
|
export type FilterHandler<TRow = unknown> = (filters: FilterModel[], currentRows: TRow[]) => TRow[] | Promise<TRow[]>;
|
|
370
|
-
/**
|
|
534
|
+
/**
|
|
535
|
+
* Configuration options for the {@link FilteringPlugin}.
|
|
536
|
+
*
|
|
537
|
+
* Pass this object to the `FilteringPlugin` constructor to customize filtering
|
|
538
|
+
* behavior, panel rendering, server-side integration, and state persistence.
|
|
539
|
+
*
|
|
540
|
+
* @typeParam TRow - The row data type. Inferred when using a typed `filterHandler`.
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* ```typescript
|
|
544
|
+
* // Basic usage with defaults
|
|
545
|
+
* new FilteringPlugin()
|
|
546
|
+
*
|
|
547
|
+
* // Customized local filtering
|
|
548
|
+
* new FilteringPlugin({
|
|
549
|
+
* debounceMs: 200,
|
|
550
|
+
* caseSensitive: true,
|
|
551
|
+
* trackColumnState: true,
|
|
552
|
+
* })
|
|
553
|
+
*
|
|
554
|
+
* // Server-side filtering with custom values
|
|
555
|
+
* new FilteringPlugin<Employee>({
|
|
556
|
+
* valuesHandler: async (field) => {
|
|
557
|
+
* const res = await fetch(`/api/employees/distinct/${field}`);
|
|
558
|
+
* return res.json();
|
|
559
|
+
* },
|
|
560
|
+
* filterHandler: async (filters) => {
|
|
561
|
+
* const params = new URLSearchParams();
|
|
562
|
+
* filters.forEach(f => params.append(f.field, `${f.operator}:${f.value}`));
|
|
563
|
+
* const res = await fetch(`/api/employees?${params}`);
|
|
564
|
+
* return res.json();
|
|
565
|
+
* },
|
|
566
|
+
* })
|
|
567
|
+
* ```
|
|
568
|
+
*/
|
|
371
569
|
export interface FilterConfig<TRow = unknown> {
|
|
372
|
-
/**
|
|
570
|
+
/**
|
|
571
|
+
* Debounce delay in milliseconds for the search input inside the default
|
|
572
|
+
* filter panel. Controls how long the panel waits after the user stops
|
|
573
|
+
* typing before re-filtering the unique values list.
|
|
574
|
+
*
|
|
575
|
+
* Lower values feel more responsive but cause more DOM updates.
|
|
576
|
+
* Higher values reduce work for columns with many unique values.
|
|
577
|
+
*
|
|
578
|
+
* @default 300
|
|
579
|
+
*
|
|
580
|
+
* @example
|
|
581
|
+
* ```typescript
|
|
582
|
+
* // Faster response for small datasets
|
|
583
|
+
* new FilteringPlugin({ debounceMs: 100 })
|
|
584
|
+
*
|
|
585
|
+
* // Slower debounce for columns with thousands of unique values
|
|
586
|
+
* new FilteringPlugin({ debounceMs: 500 })
|
|
587
|
+
* ```
|
|
588
|
+
*/
|
|
373
589
|
debounceMs?: number;
|
|
374
|
-
/**
|
|
590
|
+
/**
|
|
591
|
+
* Whether text-based filtering comparisons are case-sensitive.
|
|
592
|
+
*
|
|
593
|
+
* When `false` (default), `"alice"` matches `"Alice"`, `"ALICE"`, etc.
|
|
594
|
+
* When `true`, only exact case matches pass the filter.
|
|
595
|
+
*
|
|
596
|
+
* Affects both:
|
|
597
|
+
* - The core `filterRows()` logic (text operators like `contains`, `equals`, etc.)
|
|
598
|
+
* - The search input inside the default filter panel (value list filtering)
|
|
599
|
+
*
|
|
600
|
+
* @default false
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```typescript
|
|
604
|
+
* // Enable case-sensitive filtering
|
|
605
|
+
* new FilteringPlugin({ caseSensitive: true })
|
|
606
|
+
* ```
|
|
607
|
+
*/
|
|
375
608
|
caseSensitive?: boolean;
|
|
376
|
-
/**
|
|
609
|
+
/**
|
|
610
|
+
* Whether to trim leading/trailing whitespace from filter input values
|
|
611
|
+
* before applying them.
|
|
612
|
+
*
|
|
613
|
+
* @default true
|
|
614
|
+
*
|
|
615
|
+
* @remarks
|
|
616
|
+
* **Reserved for future use.** This option is accepted in configuration
|
|
617
|
+
* but not yet applied in the current filtering implementation.
|
|
618
|
+
*/
|
|
377
619
|
trimInput?: boolean;
|
|
378
|
-
/**
|
|
620
|
+
/**
|
|
621
|
+
* Whether to offload filtering to a Web Worker for large datasets.
|
|
622
|
+
*
|
|
623
|
+
* @default true
|
|
624
|
+
*
|
|
625
|
+
* @remarks
|
|
626
|
+
* **Reserved for future use.** This option is accepted in configuration
|
|
627
|
+
* but not yet implemented. Filtering currently runs synchronously on
|
|
628
|
+
* the main thread for all dataset sizes. Performance is excellent for
|
|
629
|
+
* most use cases — the grid handles 10,000+ rows without noticeable delay
|
|
630
|
+
* thanks to result caching and debounced input.
|
|
631
|
+
*
|
|
632
|
+
* When implemented, this will automatically offload `filterRows()` to a
|
|
633
|
+
* Web Worker when the row count exceeds an internal threshold, keeping
|
|
634
|
+
* the main thread responsive during heavy filtering operations.
|
|
635
|
+
*/
|
|
379
636
|
useWorker?: boolean;
|
|
380
|
-
/**
|
|
637
|
+
/**
|
|
638
|
+
* Custom filter panel renderer that replaces the built-in panel content
|
|
639
|
+
* for **all** columns (unless you return `undefined` for specific columns
|
|
640
|
+
* to fall through to the next level).
|
|
641
|
+
*
|
|
642
|
+
* **Resolution priority** (first non-empty result wins):
|
|
643
|
+
* 1. This plugin-level `filterPanelRenderer`
|
|
644
|
+
* 2. Type-level `filterPanelRenderer` (in `gridConfig.typeDefaults[type]`)
|
|
645
|
+
* 3. Built-in panel (checkbox set filter, number range slider, or date picker)
|
|
646
|
+
*
|
|
647
|
+
* The renderer receives the panel container element and a {@link FilterPanelParams}
|
|
648
|
+
* object with state and action callbacks. Append your UI to the container.
|
|
649
|
+
*
|
|
650
|
+
* **Return `undefined`** (or leave the container empty) to fall through to
|
|
651
|
+
* the next resolution level. This lets you override only specific fields.
|
|
652
|
+
*
|
|
653
|
+
* @example
|
|
654
|
+
* ```typescript
|
|
655
|
+
* // Override only the "status" column, use defaults for everything else
|
|
656
|
+
* new FilteringPlugin({
|
|
657
|
+
* filterPanelRenderer: (container, params) => {
|
|
658
|
+
* if (params.field !== 'status') return undefined; // fall through
|
|
659
|
+
*
|
|
660
|
+
* params.uniqueValues.forEach(val => {
|
|
661
|
+
* const btn = document.createElement('button');
|
|
662
|
+
* btn.textContent = String(val);
|
|
663
|
+
* btn.onclick = () => {
|
|
664
|
+
* const excluded = params.uniqueValues.filter(v => v !== val);
|
|
665
|
+
* params.applySetFilter(excluded as unknown[]);
|
|
666
|
+
* };
|
|
667
|
+
* container.appendChild(btn);
|
|
668
|
+
* });
|
|
669
|
+
* },
|
|
670
|
+
* })
|
|
671
|
+
* ```
|
|
672
|
+
*
|
|
673
|
+
* @example
|
|
674
|
+
* ```typescript
|
|
675
|
+
* // Replace ALL filter panels with a custom component
|
|
676
|
+
* new FilteringPlugin({
|
|
677
|
+
* filterPanelRenderer: (container, params) => {
|
|
678
|
+
* const myFilter = new MyCustomFilterElement();
|
|
679
|
+
* myFilter.field = params.field;
|
|
680
|
+
* myFilter.values = params.uniqueValues;
|
|
681
|
+
* myFilter.onApply = (excluded) => params.applySetFilter(excluded);
|
|
682
|
+
* myFilter.onClear = () => params.clearFilter();
|
|
683
|
+
* container.appendChild(myFilter);
|
|
684
|
+
* },
|
|
685
|
+
* })
|
|
686
|
+
* ```
|
|
687
|
+
*
|
|
688
|
+
* @see {@link FilterPanelParams} for all available state and action callbacks.
|
|
689
|
+
* @see {@link FilterPanelRenderer} for the function signature.
|
|
690
|
+
*/
|
|
381
691
|
filterPanelRenderer?: FilterPanelRenderer;
|
|
382
692
|
/**
|
|
383
693
|
* Whether filter state should be included in column state persistence.
|
|
@@ -385,28 +695,119 @@ export interface FilterConfig<TRow = unknown> {
|
|
|
385
695
|
* When `true`:
|
|
386
696
|
* - `getColumnState()` includes filter data for each column
|
|
387
697
|
* - Filter changes fire the `column-state-change` event (debounced)
|
|
388
|
-
* - `applyColumnState()` restores filter state
|
|
698
|
+
* - `applyColumnState()` restores filter state from a saved snapshot
|
|
389
699
|
*
|
|
390
700
|
* When `false` (default):
|
|
391
701
|
* - Filters are excluded from column state entirely
|
|
392
|
-
* - Filter changes do not fire `column-state-change`
|
|
702
|
+
* - Filter changes do **not** fire `column-state-change`
|
|
703
|
+
*
|
|
704
|
+
* Enable this when you persist column state (e.g., to localStorage or a server)
|
|
705
|
+
* and want filter selections to survive page reloads.
|
|
393
706
|
*
|
|
394
707
|
* @default false
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```typescript
|
|
711
|
+
* // Persist filters alongside column order, widths, and sort state
|
|
712
|
+
* new FilteringPlugin({ trackColumnState: true })
|
|
713
|
+
*
|
|
714
|
+
* // Save/restore cycle:
|
|
715
|
+
* const state = grid.getColumnState(); // includes filter data
|
|
716
|
+
* localStorage.setItem('grid-state', JSON.stringify(state));
|
|
717
|
+
* // ... later ...
|
|
718
|
+
* grid.applyColumnState(JSON.parse(localStorage.getItem('grid-state')!));
|
|
719
|
+
* ```
|
|
395
720
|
*/
|
|
396
721
|
trackColumnState?: boolean;
|
|
397
722
|
/**
|
|
398
|
-
* Async handler for fetching unique values from a server.
|
|
399
|
-
*
|
|
400
|
-
*
|
|
723
|
+
* Async handler for fetching unique filter values from a server.
|
|
724
|
+
*
|
|
725
|
+
* When provided, this handler is called **each time a filter panel opens**
|
|
726
|
+
* instead of extracting unique values from the locally-loaded rows. The panel
|
|
727
|
+
* shows a loading indicator while the handler resolves.
|
|
728
|
+
*
|
|
729
|
+
* Use this for server-side or paginated datasets where the client only holds
|
|
730
|
+
* a subset of the data and the local unique values would be incomplete.
|
|
731
|
+
*
|
|
732
|
+
* The returned values populate `FilterPanelParams.uniqueValues` and appear
|
|
733
|
+
* in the checkbox list (or are passed to your custom `filterPanelRenderer`).
|
|
734
|
+
*
|
|
735
|
+
* @example
|
|
736
|
+
* ```typescript
|
|
737
|
+
* new FilteringPlugin({
|
|
738
|
+
* valuesHandler: async (field, column) => {
|
|
739
|
+
* const res = await fetch(`/api/data/distinct/${field}`);
|
|
740
|
+
* return res.json(); // ['Engineering', 'Marketing', 'Sales', ...]
|
|
741
|
+
* },
|
|
742
|
+
* })
|
|
743
|
+
* ```
|
|
744
|
+
*
|
|
745
|
+
* @example
|
|
746
|
+
* ```typescript
|
|
747
|
+
* // Combine with filterHandler for full server-side filtering
|
|
748
|
+
* new FilteringPlugin<Employee>({
|
|
749
|
+
* valuesHandler: async (field) => {
|
|
750
|
+
* const res = await fetch(`/api/employees/distinct/${field}`);
|
|
751
|
+
* return res.json();
|
|
752
|
+
* },
|
|
753
|
+
* filterHandler: async (filters) => {
|
|
754
|
+
* const body = JSON.stringify(filters);
|
|
755
|
+
* const res = await fetch('/api/employees/filter', { method: 'POST', body });
|
|
756
|
+
* return res.json();
|
|
757
|
+
* },
|
|
758
|
+
* })
|
|
759
|
+
* ```
|
|
760
|
+
*
|
|
761
|
+
* @see {@link FilterValuesHandler} for the full type signature.
|
|
401
762
|
*/
|
|
402
763
|
valuesHandler?: FilterValuesHandler;
|
|
403
764
|
/**
|
|
404
|
-
* Async handler for
|
|
405
|
-
*
|
|
406
|
-
*
|
|
765
|
+
* Async handler for delegating filtering to a server.
|
|
766
|
+
*
|
|
767
|
+
* When provided, the plugin's `processRows()` hook becomes a **passthrough**
|
|
768
|
+
* (returns rows unfiltered) and instead calls this handler whenever the
|
|
769
|
+
* active filters change. The handler should return the filtered rows, which
|
|
770
|
+
* replace the grid's current data.
|
|
771
|
+
*
|
|
772
|
+
* This enables full server-side filtering for large datasets that can't be
|
|
773
|
+
* loaded into the browser. The handler receives the complete list of active
|
|
774
|
+
* {@link FilterModel} objects and the current row array (useful for optimistic
|
|
775
|
+
* updates or reference).
|
|
776
|
+
*
|
|
777
|
+
* The handler may return rows synchronously (plain array) or asynchronously
|
|
778
|
+
* (Promise). While an async handler is pending, the grid retains its current
|
|
779
|
+
* rows until the new data arrives.
|
|
780
|
+
*
|
|
781
|
+
* @example
|
|
782
|
+
* ```typescript
|
|
783
|
+
* // Server-side filtering with query params
|
|
784
|
+
* new FilteringPlugin<Employee>({
|
|
785
|
+
* filterHandler: async (filters, currentRows) => {
|
|
786
|
+
* const params = new URLSearchParams();
|
|
787
|
+
* filters.forEach(f => params.append(f.field, `${f.operator}:${f.value}`));
|
|
788
|
+
* const res = await fetch(`/api/employees?${params}`);
|
|
789
|
+
* return res.json();
|
|
790
|
+
* },
|
|
791
|
+
* })
|
|
792
|
+
* ```
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* ```typescript
|
|
796
|
+
* // POST-based filtering with full filter models
|
|
797
|
+
* new FilteringPlugin<Product>({
|
|
798
|
+
* filterHandler: async (filters) => {
|
|
799
|
+
* const res = await fetch('/api/products/filter', {
|
|
800
|
+
* method: 'POST',
|
|
801
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
802
|
+
* body: JSON.stringify({ filters }),
|
|
803
|
+
* });
|
|
804
|
+
* return res.json();
|
|
805
|
+
* },
|
|
806
|
+
* })
|
|
807
|
+
* ```
|
|
407
808
|
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
809
|
+
* @see {@link FilterHandler} for the full type signature.
|
|
810
|
+
* @see {@link FilterChangeDetail} for the event emitted after filter changes.
|
|
410
811
|
*/
|
|
411
812
|
filterHandler?: FilterHandler<TRow>;
|
|
412
813
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/filtering/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIrD,OAAO,QAAQ,kBAAkB,CAAC;IAChC,UAAU,gBAAgB;QACxB;;;WAGG;QACH,UAAU,CAAC,EAAE,OAAO,CAAC;QAErB;;;;;WAKG;QACH,YAAY,CAAC,EAAE,YAAY,CAAC;QAE5B;;;;;;;;;;;;;;;;;;;;;;;WAuBG;QACH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC;KACjE;IAED,UAAU,WAAW;QACnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA6BG;QACH,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;KAC3C;IAGD,UAAU,WAAW;QACnB;;;WAGG;QACH,MAAM,CAAC,EAAE;YACP,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;YACrD,QAAQ,EAAE,MAAM,CAAC;YACjB,KAAK,EAAE,OAAO,CAAC;YACf,OAAO,CAAC,EAAE,OAAO,CAAC;SACnB,CAAC;KACH;IAED,UAAU,UAAU;QAClB;;;;;;;;;;;;;;;;;;;;;WAqBG;QACH,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB;IAED,UAAU,aAAa;QACrB,SAAS,EAAE,OAAO,mBAAmB,EAAE,eAAe,CAAC;KACxD;CACF;AAGD;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,yCAAyC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAGD;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8IG;AACH,MAAM,MAAM,cAAc,GAEtB,UAAU,GACV,aAAa,GACb,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,UAAU,GAEV,OAAO,GACP,UAAU,GAEV,UAAU,GACV,iBAAiB,GACjB,aAAa,GACb,oBAAoB,GACpB,SAAS,GAET,IAAI,GACJ,OAAO,CAAC;AAEZ,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,0BAA0B;IAC1B,QAAQ,EAAE,cAAc,CAAC;IACzB,kDAAkD;IAClD,KAAK,EAAE,OAAO,CAAC;IACf,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../libs/grid/src/lib/plugins/filtering/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Grouping Columns Plugin Entry Point
|
|
3
3
|
* Re-exports plugin class and types for tree-shakeable imports.
|
|
4
4
|
*
|
|
5
|
-
* @module Plugins/
|
|
5
|
+
* @module Plugins/Grouping Columns
|
|
6
6
|
*/
|
|
7
7
|
export { GroupingColumnsPlugin } from './GroupingColumnsPlugin';
|
|
8
8
|
export type { ColumnGroup, ColumnGroupDefinition, GroupingColumnsConfig } from './types';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e='<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>',t={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:e,filterActive:e,print:"🖨️"};class r{static dependencies;static manifest;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const r=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(r),r.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...t,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),r=parseInt(t,10);if(!isNaN(r))return r}return 200}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}setIcon(e,t){"string"==typeof t?e.innerHTML=t:t instanceof HTMLElement&&(e.innerHTML="",e.appendChild(t.cloneNode(!0)))}warn(e){console.warn(`[tbw-grid:${this.name}] ${e}`)}}function o(e){if(!e.length)return[];const t=/* @__PURE__ */new Map,r=[],o=(e,t)=>{if(!t.length)return;const o=r[r.length-1];o&&o.implicit&&o.firstIndex+o.columns.length===e?o.columns.push(...t):r.push({id:"__implicit__"+e,label:void 0,columns:t,firstIndex:e,implicit:!0})};let i=[],n=0;return e.forEach((e,s)=>{const l=e.group;if(!l)return 0===i.length&&(n=s),void i.push(e);i.length&&(o(n,i.slice()),i=[]);const d="string"==typeof l?l:l.id;let u=t.get(d);u||(u={id:d,label:"string"==typeof l?void 0:l.label,columns:[],firstIndex:s},t.set(d,u),r.push(u)),u.columns.push(e)}),i.length&&o(n,i),1===r.length&&r[0].implicit&&r[0].columns.length===e.length?[]:r}function i(e,t){const r=e.columns[0],o=e.columns[e.columns.length-1],i=r?t.findIndex(e=>e.field===r.field):-1,n=o?t.findIndex(e=>e.field===o.field):-1;return-1!==i&&-1!==n?[i,n]:null}function n(e,t){const r=/* @__PURE__ */new Set,o=[];for(const n of e){if(String(n.id).startsWith("__implicit__"))continue;const e=i(n,t);e&&o.push(e)}for(const n of e){if(!String(n.id).startsWith("__implicit__"))continue;const e=i(n,t);if(!e)continue;const[s,l]=e;o.some(([e,t])=>s>=e&&l<=t)&&r.add(String(n.id))}return r}class s extends r{static manifest={ownedProperties:[{property:"group",level:"column",description:'the "group" column property'},{property:"columnGroups",level:"config",description:'the "columnGroups" config property',isUsed:e=>Array.isArray(e)&&e.length>0}],queries:[{type:"getColumnGrouping",description:"Returns column group metadata for the visibility panel"}]};name="groupingColumns";styles="@layer tbw-plugins{.header-group-row{display:grid;grid-auto-flow:column;background:var(--tbw-grouping-columns-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell{display:flex;align-items:center;justify-content:center;padding:var(--tbw-button-padding-sm, .25rem .5rem);font-weight:600;font-size:var(--tbw-font-size-sm, .9em);text-transform:uppercase;letter-spacing:.5px;border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.header-group-cell:last-child{border-right:none}.header-row .cell.grouped{border-top:none}.header-row .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.header-row .cell.group-end:last-child{border-right:none}.rows .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.rows .cell.group-end:last-child{border-right:none}.header-group-row.no-borders{border-bottom:none}.header-group-row.no-borders .header-group-cell{border-right:none}.header-row.no-group-borders .cell.group-end{border-right:1px solid var(--tbw-color-border)}}";get defaultConfig(){return{showGroupBorders:!0,lockGroupOrder:!1}}groups=[];isActive=!1;#t=/* @__PURE__ */new Set;attach(e){super.attach(e),e.addEventListener("column-move",this.#r,{signal:this.disconnectSignal})}detach(){this.groups=[],this.isActive=!1,this.#t.clear()}#r=e=>{if(!this.isActive)return;const t=e,{field:r,columnOrder:o}=t.detail;if(this.config.lockGroupOrder)for(const i of this.groups)if(!i.id.startsWith("__implicit__")&&!this.#o(i,o))return t.preventDefault(),void this.#i(r);this.#n(o)};#n(e){this.#t.clear();const t=this.#s(e);for(const r of this.groups){const o=new Set(r.columns.map(e=>e.field));for(let r=e.length-1;r>=0;r--)if(o.has(e[r])){const o=e[r];o!==t&&this.#t.add(o);break}}}#s(e){if(0===this.groups.length)return null;for(let t=e.length-1;t>=0;t--){const r=e[t];for(const t of this.groups)if(t.columns.some(e=>e.field===r)){const r=new Set(t.columns.map(e=>e.field));for(let t=e.length-1;t>=0;t--)if(r.has(e[t]))return e[t]}}return null}#o(e,t){const r=e.columns.map(e=>t.indexOf(e.field)).filter(e=>-1!==e).sort((e,t)=>e-t);return r.length<=1||r.length===r[r.length-1]-r[0]+1}#i(e){const t=this.gridElement?.querySelector(`.header-row [part~="header-cell"][data-field="${e}"]`);t&&(t.style.setProperty("--_flash-color","var(--tbw-color-error)"),t.animate([{backgroundColor:"rgba(from var(--_flash-color) r g b / 30%)"},{backgroundColor:"transparent"}],{duration:400,easing:"ease-out"}))}handleQuery(e){if("getColumnGrouping"===e.type)return this.#l()}#l(){let e;const t=this.grid?.gridConfig?.columnGroups;if(t&&Array.isArray(t)&&t.length>0)e=t.filter(e=>e.children.length>0).map(e=>({id:e.id,label:e.header,fields:[...e.children]}));else if(this.isActive&&this.groups.length>0){e=this.groups.filter(e=>!e.id.startsWith("__implicit__")).map(e=>({id:e.id,label:e.label??e.id,fields:e.columns.map(e=>e.field)}));const t=this.columns;for(const r of t)if(r.hidden&&r.group){const t="string"==typeof r.group?r.group:r.group.id,o="string"==typeof r.group?r.group:r.group.label??r.group.id,i=e.find(e=>e.id===t);i?i.fields.includes(r.field)||i.fields.push(r.field):e.push({id:t,label:o,fields:[r.field]})}}else{const t=this.columns,r=/* @__PURE__ */new Map;for(const e of t){if(!e.group)continue;const t="string"==typeof e.group?e.group:e.group.id,o="string"==typeof e.group?e.group:e.group.label??e.group.id,i=r.get(t);i?i.fields.includes(e.field)||i.fields.push(e.field):r.set(t,{id:t,label:o,fields:[e.field]})}e=Array.from(r.values())}const r=this.grid?.getColumnOrder();if(r&&r.length>0){const t=new Map(r.map((e,t)=>[e,t]));for(const r of e)r.fields.sort((e,r)=>(t.get(e)??1/0)-(t.get(r)??1/0))}return e}static detect(e,t){if(t?.columnGroups&&Array.isArray(t.columnGroups)&&t.columnGroups.length>0)return!0;const r=t?.columns;return!!Array.isArray(r)&&function(e){return e.some(e=>null!=e.group)}(r)}processColumns(e){const t=this.grid?.gridConfig?.columnGroups;let r;if(t&&Array.isArray(t)&&t.length>0){const o=/* @__PURE__ */new Map;for(const e of t)for(const t of e.children)o.set(t,{id:e.id,label:e.header});r=e.map(e=>{const t=o.get(e.field);return t&&!e.group?{...e,group:t}:e})}else r=[...e];const i=o(r);if(0===i.length)return this.isActive=!1,this.groups=[],r;this.isActive=!0,this.groups=i,this.#t.clear();for(const o of i){const e=o.columns[o.columns.length-1];e?.field&&this.#t.add(e.field)}return r}afterRender(){if(!this.isActive){const e=this.gridElement?.querySelector(".header"),t=e?.querySelector(".header-group-row");return void(t&&t.remove())}const e=this.gridElement?.querySelector(".header");if(!e)return;const t=e.querySelector(".header-group-row");t&&t.remove();const r=this.visibleColumns,s=o(r);if(0===s.length)return;this.#t.clear();const l=n(s,r);for(let o=0;o<s.length;o++){const e=s[o];if(String(e.id).startsWith("__implicit__")&&l.has(String(e.id)))continue;const t=e.columns[e.columns.length-1];t?.field&&o<s.length-1&&this.#t.add(t.field)}const d=function(e,t){if(0===e.length)return null;const r=document.createElement("div");r.className="header-group-row",r.setAttribute("role","row");const o=n(e,t);for(const n of e){const e=String(n.id),s=e.startsWith("__implicit__");if(s&&o.has(e))continue;const l=i(n,t);if(!l)continue;const[d,u]=l,c=u-d+1,g=s?"":n.label||n.id,a=document.createElement("div");a.className="cell header-group-cell",s&&a.classList.add("implicit-group"),a.setAttribute("data-group",e),a.style.gridColumn=`${d+1} / span ${c}`,a.textContent=g,r.appendChild(a)}return r}(s,r);if(d){d.classList.toggle("no-borders",!this.config.showGroupBorders);const t=e.querySelector(".header-row");t?e.insertBefore(d,t):e.appendChild(d)}const u=e.querySelector(".header-row");u&&(u.classList.toggle("no-group-borders",!this.config.showGroupBorders),function(e,t,r){if(!t.length||!e)return;const o=n(t,r),i=/* @__PURE__ */new Map;for(const n of t)if(!String(n.id).startsWith("__implicit__")||!o.has(String(n.id)))for(const e of n.columns)e.field&&i.set(e.field,n.id);const s=Array.from(e.querySelectorAll(".cell[data-field]"));s.forEach(e=>{const t=e.getAttribute("data-field")||"",r=i.get(t);r&&(e.classList.add("grouped"),e.getAttribute("data-group")||e.setAttribute("data-group",r))});for(const n of t){if(String(n.id).startsWith("__implicit__")&&o.has(String(n.id)))continue;const e=n.columns[n.columns.length-1],t=s.find(t=>t.getAttribute("data-field")===e.field);t&&t.classList.add("group-end")}}(u,s,r))}afterCellRender(e){this.isActive&&this.config.showGroupBorders&&e.cellElement.classList.toggle("group-end",this.#t.has(e.column.field))}isGroupingActive(){return this.isActive}getGroups(){return this.groups}getGroupColumns(e){const t=this.groups.find(t=>t.id===e);return t?t.columns:[]}refresh(){this.requestRender()}}export{s as GroupingColumnsPlugin};
|
|
1
|
+
const e='<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>',t={expand:"▶",collapse:"▼",sortAsc:"▲",sortDesc:"▼",sortNone:"⇅",submenuArrow:"▶",dragHandle:"⋮⋮",toolPanel:"☰",filter:e,filterActive:e,print:"🖨️"};class r{static dependencies;static manifest;aliases;version="undefined"!=typeof __GRID_VERSION__?__GRID_VERSION__:"dev";styles;cellRenderers;headerRenderers;cellEditors;grid;config;userConfig;#e;get defaultConfig(){return{}}constructor(e={}){this.userConfig=e}attach(e){this.#e?.abort(),this.#e=new AbortController,this.grid=e,this.config={...this.defaultConfig,...this.userConfig}}detach(){this.#e?.abort(),this.#e=void 0}getPlugin(e){return this.grid?.getPlugin(e)}emit(e,t){this.grid?.dispatchEvent?.(new CustomEvent(e,{detail:t,bubbles:!0}))}emitCancelable(e,t){const r=new CustomEvent(e,{detail:t,bubbles:!0,cancelable:!0});return this.grid?.dispatchEvent?.(r),r.defaultPrevented}on(e,t){this.grid?._pluginManager?.subscribe(this,e,t)}off(e){this.grid?._pluginManager?.unsubscribe(this,e)}emitPluginEvent(e,t){this.grid?._pluginManager?.emitPluginEvent(e,t)}requestRender(){this.grid?.requestRender?.()}requestColumnsRender(){this.grid?.requestColumnsRender?.()}requestRenderWithFocus(){this.grid?.requestRenderWithFocus?.()}requestAfterRender(){this.grid?.requestAfterRender?.()}get rows(){return this.grid?.rows??[]}get sourceRows(){return this.grid?.sourceRows??[]}get columns(){return this.grid?.columns??[]}get visibleColumns(){return this.grid?._visibleColumns??[]}get gridElement(){return this.grid}get disconnectSignal(){return this.#e?.signal??this.grid?.disconnectSignal}get gridIcons(){const e=this.grid?.gridConfig?.icons??{};return{...t,...e}}get isAnimationEnabled(){const e=this.grid?.effectiveConfig?.animation?.mode??"reduced-motion";if(!1===e||"off"===e)return!1;if(!0===e||"on"===e)return!0;const t=this.gridElement;if(t){return"0"!==getComputedStyle(t).getPropertyValue("--tbw-animation-enabled").trim()}return!0}get animationDuration(){const e=this.gridElement;if(e){const t=getComputedStyle(e).getPropertyValue("--tbw-animation-duration").trim(),r=parseInt(t,10);if(!isNaN(r))return r}return 200}resolveIcon(e,t){return void 0!==t?t:this.gridIcons[e]}setIcon(e,t){"string"==typeof t?e.innerHTML=t:t instanceof HTMLElement&&(e.innerHTML="",e.appendChild(t.cloneNode(!0)))}warn(e){console.warn(`[tbw-grid:${this.name}] ${e}`)}}function o(e){if(!e.length)return[];const t=/* @__PURE__ */new Map,r=[],o=(e,t)=>{if(!t.length)return;const o=r[r.length-1];o&&o.implicit&&o.firstIndex+o.columns.length===e?o.columns.push(...t):r.push({id:"__implicit__"+e,label:void 0,columns:t,firstIndex:e,implicit:!0})};let i=[],n=0;return e.forEach((e,s)=>{const l=e.group;if(!l)return 0===i.length&&(n=s),void i.push(e);i.length&&(o(n,i.slice()),i=[]);const d="string"==typeof l?l:l.id;let u=t.get(d);u||(u={id:d,label:"string"==typeof l?void 0:l.label,columns:[],firstIndex:s},t.set(d,u),r.push(u)),u.columns.push(e)}),i.length&&o(n,i),1===r.length&&r[0].implicit&&r[0].columns.length===e.length?[]:r}function i(e,t){const r=e.columns[0],o=e.columns[e.columns.length-1],i=r?t.findIndex(e=>e.field===r.field):-1,n=o?t.findIndex(e=>e.field===o.field):-1;return-1!==i&&-1!==n?[i,n]:null}function n(e,t){const r=/* @__PURE__ */new Set,o=[];for(const n of e){if(String(n.id).startsWith("__implicit__"))continue;const e=i(n,t);e&&o.push(e)}for(const n of e){if(!String(n.id).startsWith("__implicit__"))continue;const e=i(n,t);if(!e)continue;const[s,l]=e;o.some(([e,t])=>s>=e&&l<=t)&&r.add(String(n.id))}return r}class s extends r{static manifest={ownedProperties:[{property:"group",level:"column",description:'the "group" column property'},{property:"columnGroups",level:"config",description:'the "columnGroups" config property',isUsed:e=>Array.isArray(e)&&e.length>0}],queries:[{type:"getColumnGrouping",description:"Returns column group metadata for the visibility panel"}]};name="groupingColumns";styles="@layer tbw-plugins{.header-group-row{display:grid;grid-auto-flow:column;background:var(--tbw-grouping-columns-header-bg, var(--tbw-color-header-bg));border-bottom:1px solid var(--tbw-grouping-columns-border, var(--tbw-color-border))}.header-group-cell{display:flex;align-items:center;justify-content:center;padding:var(--tbw-button-padding-sm, .25rem .5rem);font-weight:600;font-size:var(--tbw-font-size-sm, .9em);text-transform:uppercase;letter-spacing:.5px;border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.header-group-cell:last-child{border-right:none}.header-row .cell.grouped{border-top:none}.header-row .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.header-row .cell.group-end:last-child{border-right:none}.rows .cell.group-end{border-right:2px solid var(--tbw-grouping-columns-separator, var(--tbw-color-border-strong, var(--tbw-color-border)))}.rows .cell.group-end:last-child{border-right:none}.header-group-row.no-borders{border-bottom:none}.header-group-row.no-borders .header-group-cell{border-right:none}.header-row.no-group-borders .cell.group-end{border-right:1px solid var(--tbw-color-border)}}";get defaultConfig(){return{showGroupBorders:!0,lockGroupOrder:!1}}groups=[];isActive=!1;#t=/* @__PURE__ */new Set;attach(e){super.attach(e),e.addEventListener("column-move",this.#r,{signal:this.disconnectSignal})}detach(){this.groups=[],this.isActive=!1,this.#t.clear()}#r=e=>{if(!this.isActive)return;const t=e,{field:r,columnOrder:o}=t.detail;if(this.config.lockGroupOrder)for(const i of this.groups)if(!i.id.startsWith("__implicit__")&&!this.#o(i,o))return t.preventDefault(),void this.#i(r);this.#n(o)};#n(e){this.#t.clear();const t=this.#s(e);for(const r of this.groups){const o=new Set(r.columns.map(e=>e.field));for(let r=e.length-1;r>=0;r--)if(o.has(e[r])){const o=e[r];o!==t&&this.#t.add(o);break}}}#s(e){if(0===this.groups.length)return null;for(let t=e.length-1;t>=0;t--){const r=e[t];for(const t of this.groups)if(t.columns.some(e=>e.field===r)){const r=new Set(t.columns.map(e=>e.field));for(let t=e.length-1;t>=0;t--)if(r.has(e[t]))return e[t]}}return null}#o(e,t){const r=e.columns.map(e=>t.indexOf(e.field)).filter(e=>-1!==e).sort((e,t)=>e-t);return r.length<=1||r.length===r[r.length-1]-r[0]+1}#i(e){const t=this.gridElement?.querySelector(`.header-row [part~="header-cell"][data-field="${e}"]`);t&&(t.style.setProperty("--_flash-color","var(--tbw-color-error)"),t.animate([{backgroundColor:"rgba(from var(--_flash-color) r g b / 30%)"},{backgroundColor:"transparent"}],{duration:400,easing:"ease-out"}))}handleQuery(e){if("getColumnGrouping"===e.type)return this.#l()}#l(){let e;const t=this.grid?.gridConfig?.columnGroups;if(t&&Array.isArray(t)&&t.length>0)e=t.filter(e=>e.children.length>0).map(e=>({id:e.id,label:e.header,fields:[...e.children]}));else if(this.isActive&&this.groups.length>0){e=this.groups.filter(e=>!e.id.startsWith("__implicit__")).map(e=>({id:e.id,label:e.label??e.id,fields:e.columns.map(e=>e.field)}));const t=this.columns;for(const r of t)if(r.hidden&&r.group){const t="string"==typeof r.group?r.group:r.group.id,o="string"==typeof r.group?r.group:r.group.label??r.group.id,i=e.find(e=>e.id===t);i?i.fields.includes(r.field)||i.fields.push(r.field):e.push({id:t,label:o,fields:[r.field]})}}else{const t=this.columns,r=/* @__PURE__ */new Map;for(const e of t){if(!e.group)continue;const t="string"==typeof e.group?e.group:e.group.id,o="string"==typeof e.group?e.group:e.group.label??e.group.id,i=r.get(t);i?i.fields.includes(e.field)||i.fields.push(e.field):r.set(t,{id:t,label:o,fields:[e.field]})}e=Array.from(r.values())}const r=this.grid?.getColumnOrder();if(r&&r.length>0){const t=new Map(r.map((e,t)=>[e,t]));for(const r of e)r.fields.sort((e,r)=>(t.get(e)??1/0)-(t.get(r)??1/0))}return e}static detect(e,t){if(t?.columnGroups&&Array.isArray(t.columnGroups)&&t.columnGroups.length>0)return!0;const r=t?.columns;return!!Array.isArray(r)&&function(e){return e.some(e=>null!=e.group)}(r)}processColumns(e){const t=this.grid?.gridConfig?.columnGroups;let r;if(t&&Array.isArray(t)&&t.length>0){const o=/* @__PURE__ */new Map;for(const e of t)for(const t of e.children)o.set(t,{id:e.id,label:e.header});r=e.map(e=>{const t=o.get(e.field);return t&&!e.group?{...e,group:t}:e})}else r=[...e];const i=o(r);if(0===i.length)return this.isActive=!1,this.groups=[],r;this.isActive=!0,this.groups=i,this.#t.clear();for(const o of i){const e=o.columns[o.columns.length-1];e?.field&&this.#t.add(e.field)}return r}afterRender(){if(!this.isActive){const e=this.gridElement?.querySelector(".header"),t=e?.querySelector(".header-group-row");return void(t&&t.remove())}const e=this.gridElement?.querySelector(".header");if(!e)return;const t=e.querySelector(".header-group-row");t&&t.remove();const r=this.visibleColumns,s=o(r);if(0===s.length)return;this.#t.clear();const l=n(s,r);for(let o=0;o<s.length;o++){const e=s[o];if(String(e.id).startsWith("__implicit__")&&l.has(String(e.id)))continue;const t=e.columns[e.columns.length-1];t?.field&&o<s.length-1&&this.#t.add(t.field)}const d=function(e,t){if(0===e.length)return null;const r=document.createElement("div");r.className="header-group-row",r.setAttribute("role","row");const o=n(e,t);for(const n of e){const e=String(n.id),s=e.startsWith("__implicit__");if(s&&o.has(e))continue;const l=i(n,t);if(!l)continue;const[d,u]=l,c=u-d+1,g=s?"":n.label||n.id,a=document.createElement("div");a.className="cell header-group-cell",s&&a.classList.add("implicit-group"),a.setAttribute("data-group",e),a.style.gridColumn=`${d+1} / span ${c}`,a.textContent=g,r.appendChild(a)}return r}(s,r);if(d){d.classList.toggle("no-borders",!this.config.showGroupBorders);const t=e.querySelector(".header-row");t?e.insertBefore(d,t):e.appendChild(d)}const u=e.querySelector(".header-row");u&&(u.classList.toggle("no-group-borders",!this.config.showGroupBorders),function(e,t,r){if(!t.length||!e)return;const o=n(t,r),i=/* @__PURE__ */new Map;for(const n of t)if(!String(n.id).startsWith("__implicit__")||!o.has(String(n.id)))for(const e of n.columns)e.field&&i.set(e.field,n.id);const s=Array.from(e.querySelectorAll(".cell[data-field]"));s.forEach(e=>{const t=e.getAttribute("data-field")||"",r=i.get(t);r&&(e.classList.add("grouped"),e.getAttribute("data-group")||e.setAttribute("data-group",r))});for(const n of t){if(String(n.id).startsWith("__implicit__")&&o.has(String(n.id)))continue;const e=n.columns[n.columns.length-1],t=s.find(t=>t.getAttribute("data-field")===e.field);t&&t.classList.add("group-end")}}(u,s,r))}afterCellRender(e){this.isActive&&this.config.showGroupBorders&&e.cellElement.classList.toggle("group-end",this.#t.has(e.column.field))}isGroupingActive(){return this.isActive}getGroups(){return this.groups}getGroupColumns(e){const t=this.groups.find(t=>t.id===e);return t?t.columns:[]}refresh(){this.requestRender()}}export{s as GroupingColumnsPlugin};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|