@alexgorbatchev/shadcn 0.0.35 → 0.0.37

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,37 @@
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
+ /** Choices known where the column is defined; the filter controls' `options` prop supplies choices known later. */
29
+ options?: readonly ILabelValue[];
30
+ /** Allows choosing several options; a single choice still writes a one-value array. Defaults to true. */
31
+ multiple?: boolean;
32
+ }
33
+ /** How `DataGridFilters` edits a column's filter and `DataGridFilterSummary` describes it. */
34
+ type DataGridColumnFilter = IDataGridRangeFilter | IDataGridOptionsFilter;
5
35
  /** Presentation settings a column definition carries in its `meta`. */
6
36
  interface IDataGridColumnMeta {
7
37
  /** Name in the column picker and resize handle; defaults to a string header, then the column ID. */
@@ -17,8 +47,11 @@ interface IDataGridColumnMeta {
17
47
  * header's `aria-sort` reports whichever of them, or the column itself, is sorted.
18
48
  */
19
49
  sortColumnIds?: readonly string[];
50
+ /** Offers the column in `DataGridFilters`, whether or not it is visible. */
51
+ filter?: DataGridColumnFilter;
20
52
  }
21
53
  declare const dataGridFeatures: {
54
+ columnFacetingFeature: import("@tanstack/react-table").TableFeature;
22
55
  columnFilteringFeature: import("@tanstack/react-table").TableFeature;
23
56
  columnOrderingFeature: import("@tanstack/react-table").TableFeature;
24
57
  columnSizingFeature: import("@tanstack/react-table").TableFeature;
@@ -28,11 +61,17 @@ declare const dataGridFeatures: {
28
61
  rowPaginationFeature: import("@tanstack/react-table").TableFeature;
29
62
  rowSelectionFeature: import("@tanstack/react-table").TableFeature;
30
63
  rowSortingFeature: import("@tanstack/react-table").TableFeature;
64
+ facetedRowModel: (table: CoreTable<any, any>, columnId: string) => () => import("@tanstack/react-table").RowModel<any, any>;
65
+ facetedMinMaxValues: (table: CoreTable<import("@tanstack/react-table").TableFeatures, any>, columnId: string) => () => undefined | [number, number];
66
+ facetedUniqueValues: (table: CoreTable<import("@tanstack/react-table").TableFeatures, any>, columnId: string) => () => Map<any, number>;
31
67
  filteredRowModel: (table: CoreTable<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
32
68
  sortedRowModel: (table: CoreTable<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
33
69
  paginatedRowModel: (table: CoreTable<any, any>) => () => import("@tanstack/react-table").RowModel<any, any>;
34
70
  filterFns: {
71
+ arrHas: import("@tanstack/react-table").CreatedFilterFn<any, any>;
72
+ arrIncludesSome: import("@tanstack/react-table").CreatedFilterFn<any, any>;
35
73
  includesString: import("@tanstack/react-table").CreatedFilterFn<any, any>;
74
+ inNumberRange: import("@tanstack/react-table").CreatedFilterFn<any, any>;
36
75
  };
37
76
  sortFns: {
38
77
  alphanumeric: import("@tanstack/react-table").CreatedSortFn<any, any>;
@@ -43,6 +82,19 @@ declare const dataGridFeatures: {
43
82
  type DataGridFeatures = typeof dataGridFeatures;
44
83
  /** A table built with `dataGridFeatures`; `TSelected` is the state its `useTable` selector returns. */
45
84
  type DataGridTable<T extends RowData, TSelected = TableState<DataGridFeatures>> = ReactTable<DataGridFeatures, T, TSelected>;
85
+ /** Props of a control that works on a whole grid, such as its column options or filters. */
86
+ interface IDataGridControlProps<T extends RowData> {
87
+ table: CoreTable<DataGridFeatures, T>;
88
+ /** Names the control; each control documents its default. */
89
+ label?: string;
90
+ }
91
+ /** Options-filter choices by column ID, for choices that depend on data the column definitions cannot hold. */
92
+ type DataGridFilterOptions = Readonly<Record<string, readonly ILabelValue[]>>;
93
+ /** Props of a control that edits or describes column filters. */
94
+ interface IDataGridFilterControlProps<T extends RowData> extends IDataGridControlProps<T> {
95
+ /** Replaces the choices of the options filters it names; other filters keep their column's `meta.filter.options`. */
96
+ options?: DataGridFilterOptions;
97
+ }
46
98
  type DataGridRow<T extends RowData> = Row<DataGridFeatures, T>;
47
99
  type DataGridColumn<T extends RowData> = Column<DataGridFeatures, T, CellData>;
48
100
  declare function getDataGridColumnLabel<T extends RowData>(column: DataGridColumn<T>): string;
@@ -85,4 +137,4 @@ declare function DataGridPagination<T extends RowData>({ table }: {
85
137
  table: DataGridTable<T>;
86
138
  }): ReactElement;
87
139
  export { DataGrid, DataGridCells, DataGridColumnHeader, DataGridColumns, DataGridFilter, DataGridHeaderRows, DataGridPagination, dataGridFeatures, getDataGridColumnLabel, };
88
- export type { DataGridColumn, DataGridFeatures, DataGridProps, DataGridRow, DataGridTable, IDataGridColumnMeta };
140
+ export type { DataGridColumn, DataGridColumnFilter, DataGridFeatures, DataGridProps, DataGridRow, DataGridTable, IDataGridColumnMeta, IDataGridControlProps, DataGridFilterOptions, IDataGridFilterControlProps, 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,9 @@
1
+ import { type RowData } from "@tanstack/react-table";
2
+ import type { ReactElement } from "react";
3
+ import type { IDataGridFilterControlProps } 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; `options` supplies the
7
+ * options-filter choices given to `DataGridFilters`, so the summary names them the same way.
8
+ */
9
+ export declare function DataGridFilterSummary<T extends RowData>({ table, label, options, }: IDataGridFilterControlProps<T>): ReactElement;
@@ -0,0 +1,10 @@
1
+ import { type RowData } from "@tanstack/react-table";
2
+ import { type ReactElement } from "react";
3
+ import type { IDataGridFilterControlProps } 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; `options`
8
+ * supplies options-filter choices that depend on runtime data.
9
+ */
10
+ export declare function DataGridFilters<T extends RowData>({ table, label, options, }: IDataGridFilterControlProps<T>): ReactElement;
@@ -0,0 +1,9 @@
1
+ import type { ILabelValue } from "../../options/types.js";
2
+ import type { DataGridColumnFilter } from "./DataGrid.js";
3
+ /**
4
+ * Describes a filter value in a few words: `120–128`, `≥ 120`, or `≤ 128` for a range, and the labels of the chosen
5
+ * `options` for an options filter. Values without a matching option read as themselves. Returns an empty string for a
6
+ * value that filters nothing.
7
+ */
8
+ declare function describeDataGridFilter(filter: DataGridColumnFilter, value: unknown, options: readonly ILabelValue[]): string;
9
+ 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 };
@@ -0,0 +1,6 @@
1
+ import type { RowData } from "@tanstack/react-table";
2
+ import type { ILabelValue } from "../../options/types.js";
3
+ import type { DataGridColumn, DataGridFilterOptions } from "./DataGrid.js";
4
+ /** A column's options-filter choices: those the controls were given for it, else its own. */
5
+ declare function getDataGridFilterOptions<T extends RowData>(column: DataGridColumn<T>, options: DataGridFilterOptions | undefined): readonly ILabelValue[];
6
+ export { getDataGridFilterOptions };
@@ -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, DataGridFilterOptions, IDataGridFilterControlProps, 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,360 @@ 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/getDataGridFilterOptions.ts
178
+ var NO_OPTIONS = [];
179
+ function getDataGridFilterOptions(column, options) {
180
+ const filter = column.columnDef.meta?.filter;
181
+ return options?.[column.id] ?? (filter?.variant === "options" ? filter.options : undefined) ?? NO_OPTIONS;
182
+ }
183
+
184
+ // src/components/data-grid/readDataGridOptionValues.ts
185
+ var NO_VALUES = [];
186
+ function readDataGridOptionValues(value) {
187
+ if (!Array.isArray(value))
188
+ return NO_VALUES;
189
+ return value.filter((item) => typeof item === "string");
190
+ }
191
+
192
+ // src/components/data-grid/readDataGridRange.ts
193
+ var OPEN_RANGE = [null, null];
194
+ function readBound(value) {
195
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
196
+ }
197
+ function readDataGridRange(value) {
198
+ if (!Array.isArray(value) || value.length !== 2)
199
+ return OPEN_RANGE;
200
+ return [readBound(value[0]), readBound(value[1])];
201
+ }
202
+
203
+ // src/components/data-grid/DataGridFilters.tsx
204
+ import { jsx as jsx2, jsxs as jsxs2, Fragment } from "react/jsx-runtime";
205
+ function DataGridRangeFilterControl({
206
+ column,
207
+ filter,
208
+ label
209
+ }) {
210
+ const labelId = useId();
211
+ const [min, max] = readDataGridRange(column.getFilterValue());
212
+ const available = column.getFacetedMinMaxValues();
213
+ const formatter = new Intl.NumberFormat(undefined, filter.format);
214
+ const update = (next) => column.setFilterValue(next[0] === null && next[1] === null ? undefined : next);
215
+ return /* @__PURE__ */ jsxs2("div", {
216
+ role: "group",
217
+ "aria-labelledby": labelId,
218
+ className: "grid gap-1.5",
219
+ children: [
220
+ /* @__PURE__ */ jsx2("span", {
221
+ id: labelId,
222
+ className: "text-xs font-medium text-muted-foreground",
223
+ children: label
224
+ }),
225
+ /* @__PURE__ */ jsxs2("div", {
226
+ className: "grid grid-cols-2 gap-2",
227
+ children: [
228
+ /* @__PURE__ */ jsx2(NumberField2, {
229
+ value: min,
230
+ step: filter.step,
231
+ format: filter.format,
232
+ onValueChange: (value) => update([value, max]),
233
+ children: /* @__PURE__ */ jsx2(NumberFieldGroup2, {
234
+ children: /* @__PURE__ */ jsx2(NumberFieldInput2, {
235
+ "aria-label": `Minimum ${label}`,
236
+ placeholder: available ? formatter.format(available[0]) : "Min"
237
+ })
238
+ })
239
+ }),
240
+ /* @__PURE__ */ jsx2(NumberField2, {
241
+ value: max,
242
+ step: filter.step,
243
+ format: filter.format,
244
+ onValueChange: (value) => update([min, value]),
245
+ children: /* @__PURE__ */ jsx2(NumberFieldGroup2, {
246
+ children: /* @__PURE__ */ jsx2(NumberFieldInput2, {
247
+ "aria-label": `Maximum ${label}`,
248
+ placeholder: available ? formatter.format(available[1]) : "Max"
249
+ })
250
+ })
251
+ })
252
+ ]
253
+ })
254
+ ]
255
+ });
256
+ }
257
+ function DataGridOptionsFilterControl({
258
+ column,
259
+ filter,
260
+ options,
261
+ label
262
+ }) {
263
+ const labelId = useId();
264
+ const anchor = useComboboxAnchor2();
265
+ const counts = column.getFacetedUniqueValues();
266
+ const selected = readDataGridOptionValues(column.getFilterValue()).map((value) => options.find((option) => option.value === value) ?? { label: value, value });
267
+ const update = (next) => column.setFilterValue(next.length ? next.map((option) => option.value) : undefined);
268
+ const content = /* @__PURE__ */ jsxs2(Fragment, {
269
+ children: [
270
+ /* @__PURE__ */ jsx2(ComboboxEmpty2, {
271
+ children: "No matches."
272
+ }),
273
+ /* @__PURE__ */ jsx2(ComboboxList2, {
274
+ children: (option) => /* @__PURE__ */ jsxs2(ComboboxItem2, {
275
+ value: option,
276
+ children: [
277
+ /* @__PURE__ */ jsx2("span", {
278
+ className: "min-w-0 flex-1 truncate",
279
+ children: option.label
280
+ }),
281
+ " ",
282
+ /* @__PURE__ */ jsx2("span", {
283
+ className: "text-xs text-muted-foreground tabular-nums",
284
+ children: counts.get(option.value) ?? 0
285
+ })
286
+ ]
287
+ }, option.value)
288
+ })
289
+ ]
290
+ });
291
+ return /* @__PURE__ */ jsxs2("div", {
292
+ className: "grid gap-1.5",
293
+ children: [
294
+ /* @__PURE__ */ jsx2("span", {
295
+ id: labelId,
296
+ className: "text-xs font-medium text-muted-foreground",
297
+ children: label
298
+ }),
299
+ filter.multiple === false ? /* @__PURE__ */ jsxs2(Combobox2, {
300
+ items: options,
301
+ value: selected[0] ?? null,
302
+ onValueChange: (option) => update(option ? [option] : []),
303
+ itemToStringLabel: (option) => option.label,
304
+ isItemEqualToValue: (option, value) => option.value === value.value,
305
+ children: [
306
+ /* @__PURE__ */ jsx2(ComboboxInput2, {
307
+ "aria-labelledby": labelId,
308
+ placeholder: "Any",
309
+ showClear: true,
310
+ clearLabel: `Clear ${label}`
311
+ }),
312
+ /* @__PURE__ */ jsx2(ComboboxContent2, {
313
+ children: content
314
+ })
315
+ ]
316
+ }) : /* @__PURE__ */ jsxs2(Combobox2, {
317
+ items: options,
318
+ multiple: true,
319
+ value: selected,
320
+ onValueChange: (chosen) => update(chosen),
321
+ itemToStringLabel: (option) => option.label,
322
+ isItemEqualToValue: (option, value) => option.value === value.value,
323
+ children: [
324
+ /* @__PURE__ */ jsx2(ComboboxChips2, {
325
+ ref: anchor,
326
+ children: /* @__PURE__ */ jsx2(ComboboxValue2, {
327
+ children: (chosen) => /* @__PURE__ */ jsxs2(Fragment, {
328
+ children: [
329
+ chosen.map((option) => /* @__PURE__ */ jsx2(ComboboxChip2, {
330
+ removeLabel: `Remove ${option.label}`,
331
+ children: option.label
332
+ }, option.value)),
333
+ /* @__PURE__ */ jsx2(ComboboxChipsInput2, {
334
+ "aria-labelledby": labelId,
335
+ placeholder: chosen.length ? undefined : "Any"
336
+ })
337
+ ]
338
+ })
339
+ })
340
+ }),
341
+ /* @__PURE__ */ jsx2(ComboboxContent2, {
342
+ anchor,
343
+ children: content
344
+ })
345
+ ]
346
+ })
347
+ ]
348
+ });
349
+ }
350
+ function DataGridFilters({
351
+ table,
352
+ label = "Filters",
353
+ options
354
+ }) {
355
+ return /* @__PURE__ */ jsxs2(Popover2, {
356
+ children: [
357
+ /* @__PURE__ */ jsx2(Subscribe2, {
358
+ source: table.atoms.columnFilters,
359
+ children: (filters) => /* @__PURE__ */ jsxs2(PopoverTrigger2, {
360
+ render: /* @__PURE__ */ jsx2(Button2, {
361
+ variant: "outline"
362
+ }),
363
+ children: [
364
+ /* @__PURE__ */ jsx2(ListFilterIcon, {
365
+ "data-icon": "inline-start",
366
+ "aria-hidden": "true"
367
+ }),
368
+ label,
369
+ filters.length > 0 && /* @__PURE__ */ jsxs2(Badge2, {
370
+ variant: "secondary",
371
+ children: [
372
+ filters.length,
373
+ /* @__PURE__ */ jsx2("span", {
374
+ className: "sr-only",
375
+ children: " active"
376
+ })
377
+ ]
378
+ })
379
+ ]
380
+ })
381
+ }),
382
+ /* @__PURE__ */ jsxs2(PopoverContent2, {
383
+ align: "end",
384
+ className: "max-h-(--available-height) w-80",
385
+ children: [
386
+ /* @__PURE__ */ jsx2(PopoverHeader2, {
387
+ children: /* @__PURE__ */ jsx2(PopoverTitle2, {
388
+ children: label
389
+ })
390
+ }),
391
+ /* @__PURE__ */ jsx2(Subscribe2, {
392
+ source: table.atoms.columnFilters,
393
+ children: (filters) => /* @__PURE__ */ jsxs2(Fragment, {
394
+ children: [
395
+ /* @__PURE__ */ jsx2(ScrollArea2, {
396
+ className: "flex-1",
397
+ children: /* @__PURE__ */ jsx2("div", {
398
+ className: "grid gap-3 pe-2.5",
399
+ children: table.getAllLeafColumns().map((column) => {
400
+ const filter = column.columnDef.meta?.filter;
401
+ if (!filter)
402
+ return null;
403
+ const name = getDataGridFilterLabel(column);
404
+ return filter.variant === "range" ? /* @__PURE__ */ jsx2(DataGridRangeFilterControl, {
405
+ column,
406
+ filter,
407
+ label: name
408
+ }, column.id) : /* @__PURE__ */ jsx2(DataGridOptionsFilterControl, {
409
+ column,
410
+ filter,
411
+ options: getDataGridFilterOptions(column, options),
412
+ label: name
413
+ }, column.id);
414
+ })
415
+ })
416
+ }),
417
+ /* @__PURE__ */ jsx2(Button2, {
418
+ variant: "outline",
419
+ size: "sm",
420
+ disabled: filters.length === 0,
421
+ onClick: () => table.setColumnFilters([]),
422
+ children: "Clear filters"
423
+ })
424
+ ]
425
+ })
426
+ })
427
+ ]
428
+ })
429
+ ]
430
+ });
431
+ }
432
+ // src/components/data-grid/DataGridFilterSummary.tsx
433
+ import { Subscribe as Subscribe3 } from "@tanstack/react-table";
434
+ import { XIcon } from "lucide-react";
435
+
436
+ // src/components/data-grid/describeDataGridFilter.ts
437
+ function describeDataGridFilter(filter, value, options) {
438
+ if (filter.variant === "options") {
439
+ return readDataGridOptionValues(value).map((item) => options.find((option) => option.value === item)?.label ?? item).join(", ");
440
+ }
441
+ const formatter = new Intl.NumberFormat(undefined, filter.format);
442
+ const [min, max] = readDataGridRange(value);
443
+ if (min !== null && max !== null)
444
+ return `${formatter.format(Math.min(min, max))}–${formatter.format(Math.max(min, max))}`;
445
+ if (min !== null)
446
+ return `≥ ${formatter.format(min)}`;
447
+ if (max !== null)
448
+ return `≤ ${formatter.format(max)}`;
449
+ return "";
450
+ }
451
+
452
+ // src/components/data-grid/DataGridFilterSummary.tsx
453
+ import { jsx as jsx3, jsxs as jsxs3, Fragment as Fragment2 } from "react/jsx-runtime";
454
+ function DataGridFilterSummary({
455
+ table,
456
+ label = "Active filters",
457
+ options
458
+ }) {
459
+ return /* @__PURE__ */ jsx3(Subscribe3, {
460
+ source: table.atoms.columnFilters,
461
+ children: () => {
462
+ const active = table.getAllLeafColumns().flatMap((column) => {
463
+ const filter = column.columnDef.meta?.filter;
464
+ const description = filter ? describeDataGridFilter(filter, column.getFilterValue(), getDataGridFilterOptions(column, options)) : "";
465
+ return description ? [{ column, description, name: getDataGridFilterLabel(column) }] : [];
466
+ });
467
+ return /* @__PURE__ */ jsx3(Fragment2, {
468
+ children: active.length > 0 && /* @__PURE__ */ jsxs3("div", {
469
+ className: "flex min-w-0 flex-wrap items-center gap-2",
470
+ children: [
471
+ /* @__PURE__ */ jsx3("ul", {
472
+ "aria-label": label,
473
+ className: "flex min-w-0 flex-wrap gap-1.5",
474
+ children: active.map(({ column, description, name }) => /* @__PURE__ */ jsx3("li", {
475
+ className: "min-w-0",
476
+ children: /* @__PURE__ */ jsxs3(Badge2, {
477
+ variant: "outline",
478
+ className: "max-w-full pe-0",
479
+ children: [
480
+ /* @__PURE__ */ jsxs3("span", {
481
+ className: "truncate",
482
+ children: [
483
+ name,
484
+ ": ",
485
+ description
486
+ ]
487
+ }),
488
+ /* @__PURE__ */ jsx3(Button2, {
489
+ variant: "ghost",
490
+ size: "icon-xs",
491
+ "aria-label": `Remove ${name} filter`,
492
+ onClick: () => column.setFilterValue(undefined),
493
+ children: /* @__PURE__ */ jsx3(XIcon, {
494
+ "aria-hidden": "true"
495
+ })
496
+ })
497
+ ]
498
+ })
499
+ }, column.id))
500
+ }),
501
+ /* @__PURE__ */ jsx3(Button2, {
502
+ variant: "ghost",
503
+ size: "sm",
504
+ onClick: () => table.setColumnFilters([]),
505
+ children: "Clear filters"
506
+ })
507
+ ]
508
+ })
509
+ });
510
+ }
511
+ });
512
+ }
145
513
  export {
146
514
  DataGrid2 as DataGrid,
147
515
  DataGridCells2 as DataGridCells,
148
516
  DataGridColumnHeader2 as DataGridColumnHeader,
149
517
  DataGridColumnOptions,
150
518
  DataGridFilter2 as DataGridFilter,
519
+ DataGridFilterSummary,
520
+ DataGridFilters,
151
521
  DataGridPagination2 as DataGridPagination,
152
522
  dataGridFeatures2 as dataGridFeatures
153
523
  };
@@ -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";