@alexgorbatchev/shadcn 0.0.35 → 0.0.36

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.
@@ -22,14 +22,21 @@ import {
22
22
  // src/components/data-grid/DataGrid.tsx
23
23
  import {
24
24
  FlexRender,
25
+ columnFacetingFeature,
25
26
  columnFilteringFeature,
26
27
  columnOrderingFeature,
27
28
  columnResizingFeature,
28
29
  columnSizingFeature,
29
30
  columnVisibilityFeature,
31
+ createFacetedMinMaxValues,
32
+ createFacetedRowModel,
33
+ createFacetedUniqueValues,
30
34
  createFilteredRowModel,
31
35
  createPaginatedRowModel,
32
36
  createSortedRowModel,
37
+ filterFn_arrHas,
38
+ filterFn_arrIncludesSome,
39
+ filterFn_inNumberRange,
33
40
  filterFn_includesString,
34
41
  globalFilteringFeature,
35
42
  rowPaginationFeature,
@@ -97,6 +104,7 @@ function getDataGridColumnSizeVariables(table) {
97
104
  import { jsx as jsx2, jsxs, Fragment } from "react/jsx-runtime";
98
105
  var columnMeta = {};
99
106
  var dataGridFeatures2 = tableFeatures({
107
+ columnFacetingFeature,
100
108
  columnFilteringFeature,
101
109
  columnOrderingFeature,
102
110
  columnSizingFeature,
@@ -106,10 +114,18 @@ var dataGridFeatures2 = tableFeatures({
106
114
  rowPaginationFeature,
107
115
  rowSelectionFeature,
108
116
  rowSortingFeature,
117
+ facetedRowModel: createFacetedRowModel(),
118
+ facetedMinMaxValues: createFacetedMinMaxValues(),
119
+ facetedUniqueValues: createFacetedUniqueValues(),
109
120
  filteredRowModel: createFilteredRowModel(),
110
121
  sortedRowModel: createSortedRowModel(),
111
122
  paginatedRowModel: createPaginatedRowModel(),
112
- filterFns: { includesString: filterFn_includesString },
123
+ filterFns: {
124
+ arrHas: filterFn_arrHas,
125
+ arrIncludesSome: filterFn_arrIncludesSome,
126
+ includesString: filterFn_includesString,
127
+ inNumberRange: filterFn_inNumberRange
128
+ },
113
129
  sortFns: { alphanumeric: sortFn_alphanumeric, basic: sortFn_basic },
114
130
  columnMeta
115
131
  });
@@ -1,7 +1,36 @@
1
1
  import { type CellData, type Column, type ReactTable, type Row, type RowData, type Table as CoreTable, type TableState } from "@tanstack/react-table";
2
2
  import { type ReactElement, type ReactNode } from "react";
3
3
  import type { IDensityProps } from "../../density/types.js";
4
+ import type { ILabelValue } from "../../options/types.js";
4
5
  import { type TableTextAlign, type TableVisibility } from "../Table.js";
6
+ /**
7
+ * A numeric range. The filter value is `[min, max]`, with `null` for an open end; pair it with
8
+ * `filterFn: "inNumberRange"`. The inputs suggest the range of the rows other filters leave.
9
+ */
10
+ interface IDataGridRangeFilter {
11
+ variant: "range";
12
+ /** Names the filter; defaults to the column label. */
13
+ label?: string;
14
+ step?: number;
15
+ /** Formats the bounds in the inputs and the active-filter summary, such as `{ useGrouping: false }` for years. */
16
+ format?: Intl.NumberFormatOptions;
17
+ }
18
+ /**
19
+ * A choice among known values. The filter value is the chosen option values; pair it with `filterFn: "arrHas"` for a
20
+ * single value per row, `"arrIncludesSome"` for an array of values, or a column `filterFn` that reads them. Each option
21
+ * shows how many rows the other filters leave with that value, so the column's unique values must be option values;
22
+ * a column whose rows hold several values, or values in another form, supplies them through `getUniqueValues`.
23
+ */
24
+ interface IDataGridOptionsFilter {
25
+ variant: "options";
26
+ /** Names the filter; defaults to the column label. */
27
+ label?: string;
28
+ options: readonly ILabelValue[];
29
+ /** Allows choosing several options; a single choice still writes a one-value array. Defaults to true. */
30
+ multiple?: boolean;
31
+ }
32
+ /** How `DataGridFilters` edits a column's filter and `DataGridFilterSummary` describes it. */
33
+ type DataGridColumnFilter = IDataGridRangeFilter | IDataGridOptionsFilter;
5
34
  /** Presentation settings a column definition carries in its `meta`. */
6
35
  interface IDataGridColumnMeta {
7
36
  /** Name in the column picker and resize handle; defaults to a string header, then the column ID. */
@@ -17,8 +46,11 @@ interface IDataGridColumnMeta {
17
46
  * header's `aria-sort` reports whichever of them, or the column itself, is sorted.
18
47
  */
19
48
  sortColumnIds?: readonly string[];
49
+ /** Offers the column in `DataGridFilters`, whether or not it is visible. */
50
+ filter?: DataGridColumnFilter;
20
51
  }
21
52
  declare const dataGridFeatures: {
53
+ columnFacetingFeature: import("@tanstack/react-table").TableFeature;
22
54
  columnFilteringFeature: import("@tanstack/react-table").TableFeature;
23
55
  columnOrderingFeature: import("@tanstack/react-table").TableFeature;
24
56
  columnSizingFeature: import("@tanstack/react-table").TableFeature;
@@ -28,11 +60,17 @@ declare const dataGridFeatures: {
28
60
  rowPaginationFeature: import("@tanstack/react-table").TableFeature;
29
61
  rowSelectionFeature: import("@tanstack/react-table").TableFeature;
30
62
  rowSortingFeature: import("@tanstack/react-table").TableFeature;
63
+ facetedRowModel: (table: CoreTable<any, any>, columnId: string) => () => import("@tanstack/react-table").RowModel<any, any>;
64
+ facetedMinMaxValues: (table: CoreTable<import("@tanstack/react-table").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
65
+ facetedUniqueValues: (table: CoreTable<import("@tanstack/react-table").TableFeatures, any>, columnId: string) => () => Map<any, number>;
31
66
  filteredRowModel: (table: CoreTable<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
32
67
  sortedRowModel: (table: CoreTable<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
33
68
  paginatedRowModel: (table: CoreTable<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
34
69
  filterFns: {
70
+ arrHas: import("@tanstack/react-table").CreatedFilterFn<any, any>;
71
+ arrIncludesSome: import("@tanstack/react-table").CreatedFilterFn<any, any>;
35
72
  includesString: import("@tanstack/react-table").CreatedFilterFn<any, any>;
73
+ inNumberRange: import("@tanstack/react-table").CreatedFilterFn<any, any>;
36
74
  };
37
75
  sortFns: {
38
76
  alphanumeric: import("@tanstack/react-table").CreatedSortFn<any, any>;
@@ -43,6 +81,12 @@ declare const dataGridFeatures: {
43
81
  type DataGridFeatures = typeof dataGridFeatures;
44
82
  /** A table built with `dataGridFeatures`; `TSelected` is the state its `useTable` selector returns. */
45
83
  type DataGridTable<T extends RowData, TSelected = TableState<DataGridFeatures>> = ReactTable<DataGridFeatures, T, TSelected>;
84
+ /** Props of a control that works on a whole grid, such as its column options or filters. */
85
+ interface IDataGridControlProps<T extends RowData> {
86
+ table: CoreTable<DataGridFeatures, T>;
87
+ /** Names the control; each control documents its default. */
88
+ label?: string;
89
+ }
46
90
  type DataGridRow<T extends RowData> = Row<DataGridFeatures, T>;
47
91
  type DataGridColumn<T extends RowData> = Column<DataGridFeatures, T, CellData>;
48
92
  declare function getDataGridColumnLabel<T extends RowData>(column: DataGridColumn<T>): string;
@@ -85,4 +129,4 @@ declare function DataGridPagination<T extends RowData>({ table }: {
85
129
  table: DataGridTable<T>;
86
130
  }): ReactElement;
87
131
  export { DataGrid, DataGridCells, DataGridColumnHeader, DataGridColumns, DataGridFilter, DataGridHeaderRows, DataGridPagination, dataGridFeatures, getDataGridColumnLabel, };
88
- export type { DataGridColumn, DataGridFeatures, DataGridProps, DataGridRow, DataGridTable, IDataGridColumnMeta };
132
+ export type { DataGridColumn, DataGridColumnFilter, DataGridFeatures, DataGridProps, DataGridRow, DataGridTable, IDataGridColumnMeta, IDataGridControlProps, IDataGridOptionsFilter, IDataGridRangeFilter, };
@@ -1,14 +1,8 @@
1
- import { type RowData, type Table } from "@tanstack/react-table";
1
+ import { type RowData } from "@tanstack/react-table";
2
2
  import type { ReactElement } from "react";
3
- import { type DataGridFeatures } from "./DataGrid.js";
4
- interface IDataGridColumnOptionsProps<T extends RowData> {
5
- table: Table<DataGridFeatures, T>;
6
- /** Trigger and popover title. */
7
- label?: string;
8
- }
3
+ import { type IDataGridControlProps } from "./DataGrid.js";
9
4
  /**
10
5
  * Shows, hides, and reorders the columns that allow hiding. Columns with `enableHiding: false` keep their positions.
11
- * Reset restores the table's initial visibility, order, and sizes.
6
+ * Reset restores the table's initial visibility, order, and sizes. `label` titles the trigger and popover.
12
7
  */
13
- export declare function DataGridColumnOptions<T extends RowData>({ table, label, }: IDataGridColumnOptionsProps<T>): ReactElement;
14
- export {};
8
+ export declare function DataGridColumnOptions<T extends RowData>({ table, label, }: IDataGridControlProps<T>): ReactElement;
@@ -0,0 +1,8 @@
1
+ import { type RowData } from "@tanstack/react-table";
2
+ import type { ReactElement } from "react";
3
+ import type { IDataGridControlProps } from "./DataGrid.js";
4
+ /**
5
+ * Lists the active filters of columns whose `meta.filter` describes one, each with a button that removes it, followed by
6
+ * Clear filters. Renders nothing while no such filter is active. `label` names the list.
7
+ */
8
+ export declare function DataGridFilterSummary<T extends RowData>({ table, label, }: IDataGridControlProps<T>): ReactElement;
@@ -0,0 +1,9 @@
1
+ import { type RowData } from "@tanstack/react-table";
2
+ import { type ReactElement } from "react";
3
+ import type { IDataGridControlProps } from "./DataGrid.js";
4
+ /**
5
+ * Edits the filters of every column whose `meta.filter` describes one, hidden columns included. Filters combine with
6
+ * each other and with the global filter; each control suggests only values the other filters leave. The trigger counts
7
+ * the active column filters, and Clear filters removes them all. `label` titles the trigger and popover.
8
+ */
9
+ export declare function DataGridFilters<T extends RowData>({ table, label, }: IDataGridControlProps<T>): ReactElement;
@@ -0,0 +1,8 @@
1
+ import type { DataGridColumnFilter } from "./DataGrid.js";
2
+ /**
3
+ * Describes a filter value in a few words: `120–128`, `≥ 120`, or `≤ 128` for a range, and the chosen option labels for
4
+ * options. Values without a matching option read as themselves. Returns an empty string for a value that filters
5
+ * nothing.
6
+ */
7
+ declare function describeDataGridFilter(filter: DataGridColumnFilter, value: unknown, locale?: string): string;
8
+ export { describeDataGridFilter };
@@ -0,0 +1,5 @@
1
+ import type { RowData } from "@tanstack/react-table";
2
+ import { type DataGridColumn } from "./DataGrid.js";
3
+ /** Names a column's filter: its own label, else the column's. */
4
+ declare function getDataGridFilterLabel<T extends RowData>(column: DataGridColumn<T>): string;
5
+ export { getDataGridFilterLabel };
@@ -1,3 +1,5 @@
1
1
  export { DataGrid, DataGridCells, DataGridColumnHeader, DataGridFilter, DataGridPagination, dataGridFeatures, } from "./DataGrid.js";
2
- export type { DataGridColumn, DataGridFeatures, DataGridProps, DataGridRow, DataGridTable, IDataGridColumnMeta, } from "./DataGrid.js";
2
+ export type { DataGridColumn, DataGridColumnFilter, DataGridFeatures, DataGridProps, DataGridRow, DataGridTable, IDataGridColumnMeta, IDataGridControlProps, IDataGridOptionsFilter, IDataGridRangeFilter, } from "./DataGrid.js";
3
3
  export { DataGridColumnOptions } from "./DataGridColumnOptions.js";
4
+ export { DataGridFilters } from "./DataGridFilters.js";
5
+ export { DataGridFilterSummary } from "./DataGridFilterSummary.js";
@@ -13,7 +13,7 @@ import {
13
13
  DataGridColumnHeader2,
14
14
  DataGridFilter2,
15
15
  DataGridPagination2
16
- } from "../../chunk-h5kjmt32.js";
16
+ } from "../../chunk-kmvvw1vr.js";
17
17
  import {
18
18
  Checkbox2
19
19
  } from "../../chunk-tnnf8ydf.js";
@@ -30,6 +30,28 @@ import {
30
30
  PopoverHeader2,
31
31
  PopoverTitle2
32
32
  } from "../../chunk-4djw71cv.js";
33
+ import {
34
+ Combobox2,
35
+ ComboboxValue2,
36
+ ComboboxInput2,
37
+ ComboboxContent2,
38
+ ComboboxList2,
39
+ ComboboxItem2,
40
+ ComboboxEmpty2,
41
+ ComboboxChips2,
42
+ ComboboxChip2,
43
+ ComboboxChipsInput2,
44
+ useComboboxAnchor2,
45
+ ScrollArea2,
46
+ NumberField2,
47
+ NumberFieldGroup2,
48
+ NumberFieldInput2
49
+ } from "../../chunk-c7tnf6h7.js";
50
+ import {
51
+ Badge2
52
+ } from "../../chunk-wjx6zf94.js";
53
+ import"../../chunk-hz9azhzx.js";
54
+ import"../../chunk-57jj9v64.js";
33
55
  // src/components/data-grid/DataGridColumnOptions.tsx
34
56
  import { Subscribe } from "@tanstack/react-table";
35
57
  import { ArrowDownIcon, ArrowUpIcon, Columns3Icon } from "lucide-react";
@@ -142,12 +164,349 @@ function DataGridColumnOptions({
142
164
  ]
143
165
  });
144
166
  }
167
+ // src/components/data-grid/DataGridFilters.tsx
168
+ import { Subscribe as Subscribe2 } from "@tanstack/react-table";
169
+ import { ListFilterIcon } from "lucide-react";
170
+ import { useId } from "react";
171
+
172
+ // src/components/data-grid/getDataGridFilterLabel.ts
173
+ function getDataGridFilterLabel(column) {
174
+ return column.columnDef.meta?.filter?.label ?? getDataGridColumnLabel(column);
175
+ }
176
+
177
+ // src/components/data-grid/readDataGridOptionValues.ts
178
+ var NO_VALUES = [];
179
+ function readDataGridOptionValues(value) {
180
+ if (!Array.isArray(value))
181
+ return NO_VALUES;
182
+ return value.filter((item) => typeof item === "string");
183
+ }
184
+
185
+ // src/components/data-grid/readDataGridRange.ts
186
+ var OPEN_RANGE = [null, null];
187
+ function readBound(value) {
188
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
189
+ }
190
+ function readDataGridRange(value) {
191
+ if (!Array.isArray(value) || value.length !== 2)
192
+ return OPEN_RANGE;
193
+ return [readBound(value[0]), readBound(value[1])];
194
+ }
195
+
196
+ // src/components/data-grid/DataGridFilters.tsx
197
+ import { jsx as jsx2, jsxs as jsxs2, Fragment } from "react/jsx-runtime";
198
+ function DataGridRangeFilterControl({
199
+ column,
200
+ filter,
201
+ label
202
+ }) {
203
+ const labelId = useId();
204
+ const [min, max] = readDataGridRange(column.getFilterValue());
205
+ const available = column.getFacetedMinMaxValues();
206
+ const formatter = new Intl.NumberFormat(undefined, filter.format);
207
+ const update = (next) => column.setFilterValue(next[0] === null && next[1] === null ? undefined : next);
208
+ return /* @__PURE__ */ jsxs2("div", {
209
+ role: "group",
210
+ "aria-labelledby": labelId,
211
+ className: "grid gap-1.5",
212
+ children: [
213
+ /* @__PURE__ */ jsx2("span", {
214
+ id: labelId,
215
+ className: "text-xs font-medium text-muted-foreground",
216
+ children: label
217
+ }),
218
+ /* @__PURE__ */ jsxs2("div", {
219
+ className: "grid grid-cols-2 gap-2",
220
+ children: [
221
+ /* @__PURE__ */ jsx2(NumberField2, {
222
+ value: min,
223
+ step: filter.step,
224
+ format: filter.format,
225
+ onValueChange: (value) => update([value, max]),
226
+ children: /* @__PURE__ */ jsx2(NumberFieldGroup2, {
227
+ children: /* @__PURE__ */ jsx2(NumberFieldInput2, {
228
+ "aria-label": `Minimum ${label}`,
229
+ placeholder: available ? formatter.format(available[0]) : "Min"
230
+ })
231
+ })
232
+ }),
233
+ /* @__PURE__ */ jsx2(NumberField2, {
234
+ value: max,
235
+ step: filter.step,
236
+ format: filter.format,
237
+ onValueChange: (value) => update([min, value]),
238
+ children: /* @__PURE__ */ jsx2(NumberFieldGroup2, {
239
+ children: /* @__PURE__ */ jsx2(NumberFieldInput2, {
240
+ "aria-label": `Maximum ${label}`,
241
+ placeholder: available ? formatter.format(available[1]) : "Max"
242
+ })
243
+ })
244
+ })
245
+ ]
246
+ })
247
+ ]
248
+ });
249
+ }
250
+ function DataGridOptionsFilterControl({
251
+ column,
252
+ filter,
253
+ label
254
+ }) {
255
+ const labelId = useId();
256
+ const anchor = useComboboxAnchor2();
257
+ const counts = column.getFacetedUniqueValues();
258
+ const selected = readDataGridOptionValues(column.getFilterValue()).map((value) => filter.options.find((option) => option.value === value) ?? { label: value, value });
259
+ const update = (next) => column.setFilterValue(next.length ? next.map((option) => option.value) : undefined);
260
+ const content = /* @__PURE__ */ jsxs2(Fragment, {
261
+ children: [
262
+ /* @__PURE__ */ jsx2(ComboboxEmpty2, {
263
+ children: "No matches."
264
+ }),
265
+ /* @__PURE__ */ jsx2(ComboboxList2, {
266
+ children: (option) => /* @__PURE__ */ jsxs2(ComboboxItem2, {
267
+ value: option,
268
+ children: [
269
+ /* @__PURE__ */ jsx2("span", {
270
+ className: "min-w-0 flex-1 truncate",
271
+ children: option.label
272
+ }),
273
+ " ",
274
+ /* @__PURE__ */ jsx2("span", {
275
+ className: "text-xs text-muted-foreground tabular-nums",
276
+ children: counts.get(option.value) ?? 0
277
+ })
278
+ ]
279
+ }, option.value)
280
+ })
281
+ ]
282
+ });
283
+ return /* @__PURE__ */ jsxs2("div", {
284
+ className: "grid gap-1.5",
285
+ children: [
286
+ /* @__PURE__ */ jsx2("span", {
287
+ id: labelId,
288
+ className: "text-xs font-medium text-muted-foreground",
289
+ children: label
290
+ }),
291
+ filter.multiple === false ? /* @__PURE__ */ jsxs2(Combobox2, {
292
+ items: filter.options,
293
+ value: selected[0] ?? null,
294
+ onValueChange: (option) => update(option ? [option] : []),
295
+ itemToStringLabel: (option) => option.label,
296
+ isItemEqualToValue: (option, value) => option.value === value.value,
297
+ children: [
298
+ /* @__PURE__ */ jsx2(ComboboxInput2, {
299
+ "aria-labelledby": labelId,
300
+ placeholder: "Any",
301
+ showClear: true,
302
+ clearLabel: `Clear ${label}`
303
+ }),
304
+ /* @__PURE__ */ jsx2(ComboboxContent2, {
305
+ children: content
306
+ })
307
+ ]
308
+ }) : /* @__PURE__ */ jsxs2(Combobox2, {
309
+ items: filter.options,
310
+ multiple: true,
311
+ value: selected,
312
+ onValueChange: (options) => update(options),
313
+ itemToStringLabel: (option) => option.label,
314
+ isItemEqualToValue: (option, value) => option.value === value.value,
315
+ children: [
316
+ /* @__PURE__ */ jsx2(ComboboxChips2, {
317
+ ref: anchor,
318
+ children: /* @__PURE__ */ jsx2(ComboboxValue2, {
319
+ children: (options) => /* @__PURE__ */ jsxs2(Fragment, {
320
+ children: [
321
+ options.map((option) => /* @__PURE__ */ jsx2(ComboboxChip2, {
322
+ removeLabel: `Remove ${option.label}`,
323
+ children: option.label
324
+ }, option.value)),
325
+ /* @__PURE__ */ jsx2(ComboboxChipsInput2, {
326
+ "aria-labelledby": labelId,
327
+ placeholder: options.length ? undefined : "Any"
328
+ })
329
+ ]
330
+ })
331
+ })
332
+ }),
333
+ /* @__PURE__ */ jsx2(ComboboxContent2, {
334
+ anchor,
335
+ children: content
336
+ })
337
+ ]
338
+ })
339
+ ]
340
+ });
341
+ }
342
+ function DataGridFilters({
343
+ table,
344
+ label = "Filters"
345
+ }) {
346
+ return /* @__PURE__ */ jsxs2(Popover2, {
347
+ children: [
348
+ /* @__PURE__ */ jsx2(Subscribe2, {
349
+ source: table.atoms.columnFilters,
350
+ children: (filters) => /* @__PURE__ */ jsxs2(PopoverTrigger2, {
351
+ render: /* @__PURE__ */ jsx2(Button2, {
352
+ variant: "outline"
353
+ }),
354
+ children: [
355
+ /* @__PURE__ */ jsx2(ListFilterIcon, {
356
+ "data-icon": "inline-start",
357
+ "aria-hidden": "true"
358
+ }),
359
+ label,
360
+ filters.length > 0 && /* @__PURE__ */ jsxs2(Badge2, {
361
+ variant: "secondary",
362
+ children: [
363
+ filters.length,
364
+ /* @__PURE__ */ jsx2("span", {
365
+ className: "sr-only",
366
+ children: " active"
367
+ })
368
+ ]
369
+ })
370
+ ]
371
+ })
372
+ }),
373
+ /* @__PURE__ */ jsxs2(PopoverContent2, {
374
+ align: "end",
375
+ className: "max-h-(--available-height) w-80",
376
+ children: [
377
+ /* @__PURE__ */ jsx2(PopoverHeader2, {
378
+ children: /* @__PURE__ */ jsx2(PopoverTitle2, {
379
+ children: label
380
+ })
381
+ }),
382
+ /* @__PURE__ */ jsx2(Subscribe2, {
383
+ source: table.atoms.columnFilters,
384
+ children: (filters) => /* @__PURE__ */ jsxs2(Fragment, {
385
+ children: [
386
+ /* @__PURE__ */ jsx2(ScrollArea2, {
387
+ className: "flex-1",
388
+ children: /* @__PURE__ */ jsx2("div", {
389
+ className: "grid gap-3 pe-2.5",
390
+ children: table.getAllLeafColumns().map((column) => {
391
+ const filter = column.columnDef.meta?.filter;
392
+ if (!filter)
393
+ return null;
394
+ const name = getDataGridFilterLabel(column);
395
+ return filter.variant === "range" ? /* @__PURE__ */ jsx2(DataGridRangeFilterControl, {
396
+ column,
397
+ filter,
398
+ label: name
399
+ }, column.id) : /* @__PURE__ */ jsx2(DataGridOptionsFilterControl, {
400
+ column,
401
+ filter,
402
+ label: name
403
+ }, column.id);
404
+ })
405
+ })
406
+ }),
407
+ /* @__PURE__ */ jsx2(Button2, {
408
+ variant: "outline",
409
+ size: "sm",
410
+ disabled: filters.length === 0,
411
+ onClick: () => table.setColumnFilters([]),
412
+ children: "Clear filters"
413
+ })
414
+ ]
415
+ })
416
+ })
417
+ ]
418
+ })
419
+ ]
420
+ });
421
+ }
422
+ // src/components/data-grid/DataGridFilterSummary.tsx
423
+ import { Subscribe as Subscribe3 } from "@tanstack/react-table";
424
+ import { XIcon } from "lucide-react";
425
+
426
+ // src/components/data-grid/describeDataGridFilter.ts
427
+ function describeDataGridFilter(filter, value, locale) {
428
+ if (filter.variant === "options") {
429
+ return readDataGridOptionValues(value).map((item) => filter.options.find((option) => option.value === item)?.label ?? item).join(", ");
430
+ }
431
+ const formatter = new Intl.NumberFormat(locale, filter.format);
432
+ const [min, max] = readDataGridRange(value);
433
+ if (min !== null && max !== null)
434
+ return `${formatter.format(Math.min(min, max))}–${formatter.format(Math.max(min, max))}`;
435
+ if (min !== null)
436
+ return `≥ ${formatter.format(min)}`;
437
+ if (max !== null)
438
+ return `≤ ${formatter.format(max)}`;
439
+ return "";
440
+ }
441
+
442
+ // src/components/data-grid/DataGridFilterSummary.tsx
443
+ import { jsx as jsx3, jsxs as jsxs3, Fragment as Fragment2 } from "react/jsx-runtime";
444
+ function DataGridFilterSummary({
445
+ table,
446
+ label = "Active filters"
447
+ }) {
448
+ return /* @__PURE__ */ jsx3(Subscribe3, {
449
+ source: table.atoms.columnFilters,
450
+ children: () => {
451
+ const active = table.getAllLeafColumns().flatMap((column) => {
452
+ const filter = column.columnDef.meta?.filter;
453
+ const description = filter ? describeDataGridFilter(filter, column.getFilterValue()) : "";
454
+ return description ? [{ column, description, name: getDataGridFilterLabel(column) }] : [];
455
+ });
456
+ return /* @__PURE__ */ jsx3(Fragment2, {
457
+ children: active.length > 0 && /* @__PURE__ */ jsxs3("div", {
458
+ className: "flex min-w-0 flex-wrap items-center gap-2",
459
+ children: [
460
+ /* @__PURE__ */ jsx3("ul", {
461
+ "aria-label": label,
462
+ className: "flex min-w-0 flex-wrap gap-1.5",
463
+ children: active.map(({ column, description, name }) => /* @__PURE__ */ jsx3("li", {
464
+ className: "min-w-0",
465
+ children: /* @__PURE__ */ jsxs3(Badge2, {
466
+ variant: "outline",
467
+ className: "max-w-full pe-0",
468
+ children: [
469
+ /* @__PURE__ */ jsxs3("span", {
470
+ className: "truncate",
471
+ children: [
472
+ name,
473
+ ": ",
474
+ description
475
+ ]
476
+ }),
477
+ /* @__PURE__ */ jsx3(Button2, {
478
+ variant: "ghost",
479
+ size: "icon-xs",
480
+ "aria-label": `Remove ${name} filter`,
481
+ onClick: () => column.setFilterValue(undefined),
482
+ children: /* @__PURE__ */ jsx3(XIcon, {
483
+ "aria-hidden": "true"
484
+ })
485
+ })
486
+ ]
487
+ })
488
+ }, column.id))
489
+ }),
490
+ /* @__PURE__ */ jsx3(Button2, {
491
+ variant: "ghost",
492
+ size: "sm",
493
+ onClick: () => table.setColumnFilters([]),
494
+ children: "Clear filters"
495
+ })
496
+ ]
497
+ })
498
+ });
499
+ }
500
+ });
501
+ }
145
502
  export {
146
503
  DataGrid2 as DataGrid,
147
504
  DataGridCells2 as DataGridCells,
148
505
  DataGridColumnHeader2 as DataGridColumnHeader,
149
506
  DataGridColumnOptions,
150
507
  DataGridFilter2 as DataGridFilter,
508
+ DataGridFilterSummary,
509
+ DataGridFilters,
151
510
  DataGridPagination2 as DataGridPagination,
152
511
  dataGridFeatures2 as dataGridFeatures
153
512
  };
@@ -0,0 +1,3 @@
1
+ /** Reads an options filter value: its string items, or none when it is not an array. */
2
+ declare function readDataGridOptionValues(value: unknown): readonly string[];
3
+ export { readDataGridOptionValues };
@@ -0,0 +1,6 @@
1
+ /** A range filter's bounds; `null` leaves that end open. */
2
+ type DataGridRange = readonly [min: number | null, max: number | null];
3
+ /** Reads a range filter value, treating anything other than a two-item array of finite numbers or nulls as open. */
4
+ declare function readDataGridRange(value: unknown): DataGridRange;
5
+ export { readDataGridRange };
6
+ export type { DataGridRange };
@@ -27,7 +27,7 @@ import {
27
27
  DrawerHeader2,
28
28
  DrawerTitle2,
29
29
  DrawerDescription2
30
- } from "../../chunk-c6g2rbhv.js";
30
+ } from "../../chunk-f71469fs.js";
31
31
  import"../../chunk-e6hk39ev.js";
32
32
  import"../../chunk-j89xg1ak.js";
33
33
  import"../../chunk-aa7m22zj.js";
@@ -93,6 +93,7 @@ import {
93
93
  CardContent2
94
94
  } from "../../chunk-bygq5yqf.js";
95
95
  import"../../chunk-57jj9v64.js";
96
+ import"../../chunk-c7tnf6h7.js";
96
97
  import {
97
98
  Tabs2,
98
99
  TabsList2,
@@ -10,7 +10,7 @@ import {
10
10
  DataGridHeaderRows,
11
11
  DataGridCells2,
12
12
  DataGridColumns
13
- } from "../../chunk-h5kjmt32.js";
13
+ } from "../../chunk-kmvvw1vr.js";
14
14
  import {
15
15
  VirtualTable2
16
16
  } from "../../chunk-efs4bk5b.js";