@docyrus/shadcn 1.2.1 → 1.3.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.
Files changed (52) hide show
  1. package/dist/data-table-DWI8FPWh.d.ts +209 -0
  2. package/dist/hooks/index.d.ts +5 -0
  3. package/dist/hooks/index.js +300 -16
  4. package/dist/hooks/index.js.map +1 -1
  5. package/dist/hooks/use-data-table.d.ts +29 -0
  6. package/dist/hooks/use-data-table.js +322 -0
  7. package/dist/hooks/use-data-table.js.map +1 -0
  8. package/dist/index.d.ts +87 -25
  9. package/dist/index.js +2504 -1151
  10. package/dist/index.js.map +1 -1
  11. package/dist/lib/data-table.d.ts +4 -0
  12. package/dist/lib/data-table.js +100 -0
  13. package/dist/lib/data-table.js.map +1 -0
  14. package/dist/lib/index.d.ts +4 -0
  15. package/dist/lib/index.js +155 -1
  16. package/dist/lib/index.js.map +1 -1
  17. package/dist/lib/parsers.d.ts +4 -0
  18. package/dist/lib/parsers.js +94 -0
  19. package/dist/lib/parsers.js.map +1 -0
  20. package/dist/radix-vega/data-table-column-header.d.ts +13 -0
  21. package/dist/radix-vega/data-table-column-header.js +178 -0
  22. package/dist/radix-vega/data-table-column-header.js.map +1 -0
  23. package/dist/radix-vega/data-table-date-filter.d.ts +11 -0
  24. package/dist/radix-vega/data-table-date-filter.js +470 -0
  25. package/dist/radix-vega/data-table-date-filter.js.map +1 -0
  26. package/dist/radix-vega/data-table-faceted-filter.d.ts +166 -0
  27. package/dist/radix-vega/data-table-faceted-filter.js +468 -0
  28. package/dist/radix-vega/data-table-faceted-filter.js.map +1 -0
  29. package/dist/radix-vega/data-table-pagination.d.ts +10 -0
  30. package/dist/radix-vega/data-table-pagination.js +286 -0
  31. package/dist/radix-vega/data-table-pagination.js.map +1 -0
  32. package/dist/radix-vega/data-table-skeleton.d.ts +14 -0
  33. package/dist/radix-vega/data-table-skeleton.js +151 -0
  34. package/dist/radix-vega/data-table-skeleton.js.map +1 -0
  35. package/dist/radix-vega/data-table-slider-filter.d.ts +10 -0
  36. package/dist/radix-vega/data-table-slider-filter.js +387 -0
  37. package/dist/radix-vega/data-table-slider-filter.js.map +1 -0
  38. package/dist/radix-vega/data-table-toolbar.d.ts +10 -0
  39. package/dist/radix-vega/data-table-toolbar.js +1272 -0
  40. package/dist/radix-vega/data-table-toolbar.js.map +1 -0
  41. package/dist/radix-vega/data-table-view-options.d.ts +13 -0
  42. package/dist/radix-vega/data-table-view-options.js +314 -0
  43. package/dist/radix-vega/data-table-view-options.js.map +1 -0
  44. package/dist/radix-vega/data-table.d.ts +11 -0
  45. package/dist/radix-vega/data-table.js +429 -0
  46. package/dist/radix-vega/data-table.js.map +1 -0
  47. package/dist/radix-vega/index.d.ts +10 -0
  48. package/dist/radix-vega/index.js +2170 -1156
  49. package/dist/radix-vega/index.js.map +1 -1
  50. package/dist/radix-vega/relative-time-card.d.ts +2 -7
  51. package/dist/radix-vega/relative-time-card.js.map +1 -1
  52. package/package.json +4 -3
@@ -0,0 +1,166 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { RowData, Column } from '@tanstack/react-table';
3
+
4
+ type DataTableConfig = typeof dataTableConfig;
5
+ declare const dataTableConfig: {
6
+ textOperators: ({
7
+ label: string;
8
+ value: "iLike";
9
+ } | {
10
+ label: string;
11
+ value: "notILike";
12
+ } | {
13
+ label: string;
14
+ value: "eq";
15
+ } | {
16
+ label: string;
17
+ value: "ne";
18
+ } | {
19
+ label: string;
20
+ value: "isEmpty";
21
+ } | {
22
+ label: string;
23
+ value: "isNotEmpty";
24
+ })[];
25
+ numericOperators: ({
26
+ label: string;
27
+ value: "eq";
28
+ } | {
29
+ label: string;
30
+ value: "ne";
31
+ } | {
32
+ label: string;
33
+ value: "lt";
34
+ } | {
35
+ label: string;
36
+ value: "lte";
37
+ } | {
38
+ label: string;
39
+ value: "gt";
40
+ } | {
41
+ label: string;
42
+ value: "gte";
43
+ } | {
44
+ label: string;
45
+ value: "isBetween";
46
+ } | {
47
+ label: string;
48
+ value: "isEmpty";
49
+ } | {
50
+ label: string;
51
+ value: "isNotEmpty";
52
+ })[];
53
+ dateOperators: ({
54
+ label: string;
55
+ value: "eq";
56
+ } | {
57
+ label: string;
58
+ value: "ne";
59
+ } | {
60
+ label: string;
61
+ value: "lt";
62
+ } | {
63
+ label: string;
64
+ value: "gt";
65
+ } | {
66
+ label: string;
67
+ value: "lte";
68
+ } | {
69
+ label: string;
70
+ value: "gte";
71
+ } | {
72
+ label: string;
73
+ value: "isBetween";
74
+ } | {
75
+ label: string;
76
+ value: "isRelativeToToday";
77
+ } | {
78
+ label: string;
79
+ value: "isEmpty";
80
+ } | {
81
+ label: string;
82
+ value: "isNotEmpty";
83
+ })[];
84
+ selectOperators: ({
85
+ label: string;
86
+ value: "eq";
87
+ } | {
88
+ label: string;
89
+ value: "ne";
90
+ } | {
91
+ label: string;
92
+ value: "isEmpty";
93
+ } | {
94
+ label: string;
95
+ value: "isNotEmpty";
96
+ })[];
97
+ multiSelectOperators: ({
98
+ label: string;
99
+ value: "inArray";
100
+ } | {
101
+ label: string;
102
+ value: "notInArray";
103
+ } | {
104
+ label: string;
105
+ value: "isEmpty";
106
+ } | {
107
+ label: string;
108
+ value: "isNotEmpty";
109
+ })[];
110
+ booleanOperators: ({
111
+ label: string;
112
+ value: "eq";
113
+ } | {
114
+ label: string;
115
+ value: "ne";
116
+ })[];
117
+ sortOrders: ({
118
+ label: string;
119
+ value: "asc";
120
+ } | {
121
+ label: string;
122
+ value: "desc";
123
+ })[];
124
+ filterVariants: readonly ["text", "number", "range", "date", "dateRange", "boolean", "select", "multiSelect"];
125
+ operators: readonly ["iLike", "notILike", "eq", "ne", "inArray", "notInArray", "isEmpty", "isNotEmpty", "lt", "lte", "gt", "gte", "isBetween", "isRelativeToToday"];
126
+ joinOperators: readonly ["and", "or"];
127
+ };
128
+
129
+ declare module "@tanstack/react-table" {
130
+ interface TableMeta<TData extends RowData> {
131
+ queryKeys?: QueryKeys;
132
+ }
133
+ interface ColumnMeta<TData extends RowData, TValue> {
134
+ label?: string;
135
+ placeholder?: string;
136
+ variant?: FilterVariant;
137
+ options?: Option[];
138
+ range?: [number, number];
139
+ unit?: string;
140
+ icon?: React.FC<React.SVGProps<SVGSVGElement>>;
141
+ }
142
+ }
143
+ interface QueryKeys {
144
+ page: string;
145
+ perPage: string;
146
+ sort: string;
147
+ filters: string;
148
+ joinOperator: string;
149
+ }
150
+ interface Option {
151
+ label: string;
152
+ value: string;
153
+ count?: number;
154
+ icon?: React.FC<React.SVGProps<SVGSVGElement>>;
155
+ }
156
+ type FilterVariant = DataTableConfig["filterVariants"][number];
157
+
158
+ interface DataTableFacetedFilterProps<TData, TValue> {
159
+ column?: Column<TData, TValue>;
160
+ title?: string;
161
+ options: Option[];
162
+ multiple?: boolean;
163
+ }
164
+ declare function DataTableFacetedFilter<TData, TValue>({ column, title, options, multiple, }: DataTableFacetedFilterProps<TData, TValue>): react_jsx_runtime.JSX.Element;
165
+
166
+ export { DataTableFacetedFilter };
@@ -0,0 +1,468 @@
1
+ import { XCircle, PlusCircle, Check, SearchIcon, CheckIcon } from 'lucide-react';
2
+ import * as React from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { Popover as Popover$1, Slot, Separator as Separator$1 } from 'radix-ui';
5
+ import { clsx } from 'clsx';
6
+ import { twMerge } from 'tailwind-merge';
7
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
+ import { Command as Command$1 } from 'cmdk';
9
+
10
+ function cn(...inputs) {
11
+ return twMerge(clsx(inputs));
12
+ }
13
+ var badgeVariants = cva(
14
+ "h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive overflow-hidden group/badge",
15
+ {
16
+ variants: {
17
+ variant: {
18
+ default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
19
+ secondary: "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
20
+ destructive: "bg-destructive/10 [a]:hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 text-destructive dark:bg-destructive/20",
21
+ outline: "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
22
+ ghost: "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
23
+ link: "text-primary underline-offset-4 hover:underline"
24
+ }
25
+ },
26
+ defaultVariants: {
27
+ variant: "default"
28
+ }
29
+ }
30
+ );
31
+ function Badge({
32
+ className,
33
+ variant = "default",
34
+ asChild = false,
35
+ ...props
36
+ }) {
37
+ const Comp = asChild ? Slot.Root : "span";
38
+ return /* @__PURE__ */ jsx(
39
+ Comp,
40
+ {
41
+ "data-slot": "badge",
42
+ "data-variant": variant,
43
+ className: cn(badgeVariants({ variant }), className),
44
+ ...props
45
+ }
46
+ );
47
+ }
48
+ var buttonVariants = cva(
49
+ "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-md border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
50
+ {
51
+ variants: {
52
+ variant: {
53
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
54
+ outline: "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground shadow-xs",
55
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
56
+ ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
57
+ destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
58
+ link: "text-primary underline-offset-4 hover:underline"
59
+ },
60
+ size: {
61
+ default: "h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
62
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
63
+ sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
64
+ lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
65
+ icon: "size-9",
66
+ "icon-xs": "size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
67
+ "icon-sm": "size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
68
+ "icon-lg": "size-10"
69
+ }
70
+ },
71
+ defaultVariants: {
72
+ variant: "default",
73
+ size: "default"
74
+ }
75
+ }
76
+ );
77
+ function Button({
78
+ className,
79
+ variant = "default",
80
+ size = "default",
81
+ asChild = false,
82
+ ...props
83
+ }) {
84
+ const Comp = asChild ? Slot.Root : "button";
85
+ return /* @__PURE__ */ jsx(
86
+ Comp,
87
+ {
88
+ "data-slot": "button",
89
+ "data-variant": variant,
90
+ "data-size": size,
91
+ className: cn(buttonVariants({ variant, size, className })),
92
+ ...props
93
+ }
94
+ );
95
+ }
96
+ function InputGroup({ className, ...props }) {
97
+ return /* @__PURE__ */ jsx(
98
+ "div",
99
+ {
100
+ "data-slot": "input-group",
101
+ role: "group",
102
+ className: cn(
103
+ "border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 h-9 rounded-md border shadow-xs transition-[color,box-shadow] in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5 group/input-group relative flex w-full min-w-0 items-center outline-none has-[>textarea]:h-auto",
104
+ className
105
+ ),
106
+ ...props
107
+ }
108
+ );
109
+ }
110
+ var inputGroupAddonVariants = cva(
111
+ "text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 flex cursor-text items-center justify-center select-none",
112
+ {
113
+ variants: {
114
+ align: {
115
+ "inline-start": "pl-2 has-[>button]:-ml-1 has-[>kbd]:ml-[-0.15rem] order-first",
116
+ "inline-end": "pr-2 has-[>button]:-mr-1 has-[>kbd]:mr-[-0.15rem] order-last",
117
+ "block-start": "px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start",
118
+ "block-end": "px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start"
119
+ }
120
+ },
121
+ defaultVariants: {
122
+ align: "inline-start"
123
+ }
124
+ }
125
+ );
126
+ function InputGroupAddon({
127
+ className,
128
+ align = "inline-start",
129
+ ...props
130
+ }) {
131
+ return /* @__PURE__ */ jsx(
132
+ "div",
133
+ {
134
+ role: "group",
135
+ "data-slot": "input-group-addon",
136
+ "data-align": align,
137
+ className: cn(inputGroupAddonVariants({ align }), className),
138
+ onClick: (e) => {
139
+ if (e.target.closest("button")) {
140
+ return;
141
+ }
142
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
143
+ },
144
+ ...props
145
+ }
146
+ );
147
+ }
148
+ cva(
149
+ "gap-2 text-sm shadow-none flex items-center",
150
+ {
151
+ variants: {
152
+ size: {
153
+ xs: "h-6 gap-1 rounded-[calc(var(--radius)-5px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
154
+ sm: "",
155
+ "icon-xs": "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
156
+ "icon-sm": "size-8 p-0 has-[>svg]:p-0"
157
+ }
158
+ },
159
+ defaultVariants: {
160
+ size: "xs"
161
+ }
162
+ }
163
+ );
164
+ function Command({
165
+ className,
166
+ ...props
167
+ }) {
168
+ return /* @__PURE__ */ jsx(
169
+ Command$1,
170
+ {
171
+ "data-slot": "command",
172
+ className: cn(
173
+ "bg-popover text-popover-foreground rounded-xl! p-1 flex size-full flex-col overflow-hidden",
174
+ className
175
+ ),
176
+ ...props
177
+ }
178
+ );
179
+ }
180
+ function CommandInput({
181
+ className,
182
+ ...props
183
+ }) {
184
+ return /* @__PURE__ */ jsx("div", { "data-slot": "command-input-wrapper", className: "p-1 pb-0", children: /* @__PURE__ */ jsxs(InputGroup, { className: "bg-input/30 border-input/30 h-8! rounded-lg! shadow-none! *:data-[slot=input-group-addon]:pl-2!", children: [
185
+ /* @__PURE__ */ jsx(
186
+ Command$1.Input,
187
+ {
188
+ "data-slot": "command-input",
189
+ className: cn(
190
+ "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
191
+ className
192
+ ),
193
+ ...props
194
+ }
195
+ ),
196
+ /* @__PURE__ */ jsx(InputGroupAddon, { children: /* @__PURE__ */ jsx(SearchIcon, { className: "size-4 shrink-0 opacity-50" }) })
197
+ ] }) });
198
+ }
199
+ function CommandList({
200
+ className,
201
+ ...props
202
+ }) {
203
+ return /* @__PURE__ */ jsx(
204
+ Command$1.List,
205
+ {
206
+ "data-slot": "command-list",
207
+ className: cn(
208
+ "no-scrollbar max-h-72 scroll-py-1 outline-none overflow-x-hidden overflow-y-auto",
209
+ className
210
+ ),
211
+ ...props
212
+ }
213
+ );
214
+ }
215
+ function CommandEmpty({
216
+ className,
217
+ ...props
218
+ }) {
219
+ return /* @__PURE__ */ jsx(
220
+ Command$1.Empty,
221
+ {
222
+ "data-slot": "command-empty",
223
+ className: cn("py-6 text-center text-sm", className),
224
+ ...props
225
+ }
226
+ );
227
+ }
228
+ function CommandGroup({
229
+ className,
230
+ ...props
231
+ }) {
232
+ return /* @__PURE__ */ jsx(
233
+ Command$1.Group,
234
+ {
235
+ "data-slot": "command-group",
236
+ className: cn("text-foreground **:[[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium", className),
237
+ ...props
238
+ }
239
+ );
240
+ }
241
+ function CommandSeparator({
242
+ className,
243
+ ...props
244
+ }) {
245
+ return /* @__PURE__ */ jsx(
246
+ Command$1.Separator,
247
+ {
248
+ "data-slot": "command-separator",
249
+ className: cn("bg-border -mx-1 h-px w-auto", className),
250
+ ...props
251
+ }
252
+ );
253
+ }
254
+ function CommandItem({
255
+ className,
256
+ children,
257
+ ...props
258
+ }) {
259
+ return /* @__PURE__ */ jsxs(
260
+ Command$1.Item,
261
+ {
262
+ "data-slot": "command-item",
263
+ className: cn(
264
+ "data-selected:bg-muted data-selected:text-foreground data-selected:**:[svg]:text-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! [&_svg:not([class*='size-'])]:size-4 group/command-item data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
265
+ className
266
+ ),
267
+ ...props,
268
+ children: [
269
+ children,
270
+ /* @__PURE__ */ jsx(CheckIcon, { className: "ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" })
271
+ ]
272
+ }
273
+ );
274
+ }
275
+ function Popover({
276
+ ...props
277
+ }) {
278
+ return /* @__PURE__ */ jsx(Popover$1.Root, { "data-slot": "popover", ...props });
279
+ }
280
+ function PopoverTrigger({
281
+ ...props
282
+ }) {
283
+ return /* @__PURE__ */ jsx(Popover$1.Trigger, { "data-slot": "popover-trigger", ...props });
284
+ }
285
+ function PopoverContent({
286
+ className,
287
+ align = "center",
288
+ sideOffset = 4,
289
+ ...props
290
+ }) {
291
+ return /* @__PURE__ */ jsx(Popover$1.Portal, { children: /* @__PURE__ */ jsx(
292
+ Popover$1.Content,
293
+ {
294
+ "data-slot": "popover-content",
295
+ align,
296
+ sideOffset,
297
+ className: cn(
298
+ "bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-4 rounded-md p-4 text-sm shadow-md ring-1 duration-100 z-50 w-72 origin-(--radix-popover-content-transform-origin) outline-hidden",
299
+ className
300
+ ),
301
+ ...props
302
+ }
303
+ ) });
304
+ }
305
+ function Separator({
306
+ className,
307
+ orientation = "horizontal",
308
+ decorative = true,
309
+ ...props
310
+ }) {
311
+ return /* @__PURE__ */ jsx(
312
+ Separator$1.Root,
313
+ {
314
+ "data-slot": "separator",
315
+ decorative,
316
+ orientation,
317
+ className: cn(
318
+ "bg-border shrink-0 data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
319
+ className
320
+ ),
321
+ ...props
322
+ }
323
+ );
324
+ }
325
+ function DataTableFacetedFilter({
326
+ column,
327
+ title,
328
+ options,
329
+ multiple
330
+ }) {
331
+ const [open, setOpen] = React.useState(false);
332
+ const columnFilterValue = column?.getFilterValue();
333
+ const selectedValues = new Set(
334
+ Array.isArray(columnFilterValue) ? columnFilterValue : []
335
+ );
336
+ const onItemSelect = React.useCallback(
337
+ (option, isSelected) => {
338
+ if (!column) return;
339
+ if (multiple) {
340
+ const newSelectedValues = new Set(selectedValues);
341
+ if (isSelected) {
342
+ newSelectedValues.delete(option.value);
343
+ } else {
344
+ newSelectedValues.add(option.value);
345
+ }
346
+ const filterValues = Array.from(newSelectedValues);
347
+ column.setFilterValue(filterValues.length ? filterValues : void 0);
348
+ } else {
349
+ column.setFilterValue(isSelected ? void 0 : [option.value]);
350
+ setOpen(false);
351
+ }
352
+ },
353
+ [column, multiple, selectedValues]
354
+ );
355
+ const onReset = React.useCallback(
356
+ (event) => {
357
+ event?.stopPropagation();
358
+ column?.setFilterValue(void 0);
359
+ },
360
+ [column]
361
+ );
362
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
363
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
364
+ Button,
365
+ {
366
+ variant: "outline",
367
+ size: "sm",
368
+ className: "border-dashed font-normal",
369
+ children: [
370
+ selectedValues?.size > 0 ? /* @__PURE__ */ jsx(
371
+ "div",
372
+ {
373
+ role: "button",
374
+ "aria-label": `Clear ${title} filter`,
375
+ tabIndex: 0,
376
+ className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
377
+ onClick: onReset,
378
+ children: /* @__PURE__ */ jsx(XCircle, {})
379
+ }
380
+ ) : /* @__PURE__ */ jsx(PlusCircle, {}),
381
+ title,
382
+ selectedValues?.size > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
383
+ /* @__PURE__ */ jsx(
384
+ Separator,
385
+ {
386
+ orientation: "vertical",
387
+ className: "mx-0.5 data-[orientation=vertical]:h-4"
388
+ }
389
+ ),
390
+ /* @__PURE__ */ jsx(
391
+ Badge,
392
+ {
393
+ variant: "secondary",
394
+ className: "rounded-sm px-1 font-normal lg:hidden",
395
+ children: selectedValues.size
396
+ }
397
+ ),
398
+ /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-1 lg:flex", children: selectedValues.size > 2 ? /* @__PURE__ */ jsxs(
399
+ Badge,
400
+ {
401
+ variant: "secondary",
402
+ className: "rounded-sm px-1 font-normal",
403
+ children: [
404
+ selectedValues.size,
405
+ " selected"
406
+ ]
407
+ }
408
+ ) : options.filter((option) => selectedValues.has(option.value)).map((option) => /* @__PURE__ */ jsx(
409
+ Badge,
410
+ {
411
+ variant: "secondary",
412
+ className: "rounded-sm px-1 font-normal",
413
+ children: option.label
414
+ },
415
+ option.value
416
+ )) })
417
+ ] })
418
+ ]
419
+ }
420
+ ) }),
421
+ /* @__PURE__ */ jsx(PopoverContent, { className: "w-50 p-0", align: "start", children: /* @__PURE__ */ jsxs(Command, { children: [
422
+ /* @__PURE__ */ jsx(CommandInput, { placeholder: title }),
423
+ /* @__PURE__ */ jsxs(CommandList, { className: "max-h-full", children: [
424
+ /* @__PURE__ */ jsx(CommandEmpty, { children: "No results found." }),
425
+ /* @__PURE__ */ jsx(CommandGroup, { className: "max-h-[300px] scroll-py-1 overflow-y-auto overflow-x-hidden", children: options.map((option) => {
426
+ const isSelected = selectedValues.has(option.value);
427
+ return /* @__PURE__ */ jsxs(
428
+ CommandItem,
429
+ {
430
+ onSelect: () => onItemSelect(option, isSelected),
431
+ children: [
432
+ /* @__PURE__ */ jsx(
433
+ "div",
434
+ {
435
+ className: cn(
436
+ "flex size-4 items-center justify-center rounded-sm border border-primary",
437
+ isSelected ? "bg-primary" : "opacity-50 [&_svg]:invisible"
438
+ ),
439
+ children: /* @__PURE__ */ jsx(Check, {})
440
+ }
441
+ ),
442
+ option.icon && /* @__PURE__ */ jsx(option.icon, {}),
443
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: option.label }),
444
+ option.count && /* @__PURE__ */ jsx("span", { className: "ml-auto font-mono text-xs", children: option.count })
445
+ ]
446
+ },
447
+ option.value
448
+ );
449
+ }) }),
450
+ selectedValues.size > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
451
+ /* @__PURE__ */ jsx(CommandSeparator, {}),
452
+ /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsx(
453
+ CommandItem,
454
+ {
455
+ onSelect: () => onReset(),
456
+ className: "justify-center text-center",
457
+ children: "Clear filters"
458
+ }
459
+ ) })
460
+ ] })
461
+ ] })
462
+ ] }) })
463
+ ] });
464
+ }
465
+
466
+ export { DataTableFacetedFilter };
467
+ //# sourceMappingURL=data-table-faceted-filter.js.map
468
+ //# sourceMappingURL=data-table-faceted-filter.js.map