@caffeinebounce/ui 0.62.3 → 0.63.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 (96) hide show
  1. package/README.md +1 -1
  2. package/dist/blog.js +7 -6
  3. package/dist/blog.mjs +2 -1
  4. package/dist/charts.d.cts +1 -1
  5. package/dist/charts.d.ts +1 -1
  6. package/dist/{chunk-6DVWMJ3H.mjs → chunk-2EFVMX6V.mjs} +3 -3
  7. package/dist/{chunk-6ZJCK6KH.js → chunk-375DECW4.js} +31 -31
  8. package/dist/{chunk-PZRI43EZ.js → chunk-46JYKBRX.js} +0 -43
  9. package/dist/chunk-5D55OVD5.js +75 -0
  10. package/dist/{chunk-JORVSG52.js → chunk-663CFAHS.js} +211 -269
  11. package/dist/chunk-6HKJDV43.mjs +48 -0
  12. package/dist/chunk-6NCRGHV3.mjs +64 -0
  13. package/dist/{chunk-OLAAXLXY.mjs → chunk-6QAKQG57.mjs} +4 -4
  14. package/dist/{chunk-N6AFNFZR.mjs → chunk-7ERVZXIN.mjs} +214 -270
  15. package/dist/chunk-APFEP5B7.mjs +100 -0
  16. package/dist/chunk-C3OADNSG.js +348 -0
  17. package/dist/{chunk-GIJQE3JR.js → chunk-DH5Z3ETN.js} +66 -45
  18. package/dist/chunk-DYWZ23QT.mjs +90 -0
  19. package/dist/{chunk-DTVWRRFN.mjs → chunk-E67IR6HU.mjs} +30 -9
  20. package/dist/{chunk-OVNLC5RD.mjs → chunk-EXQSWHLD.mjs} +6 -6
  21. package/dist/{chunk-ZOA7B32D.js → chunk-F35KL6TX.js} +9 -9
  22. package/dist/{chunk-YSLD2HLP.mjs → chunk-FFJC66KO.mjs} +1 -1
  23. package/dist/{chunk-MPZFPU4X.js → chunk-GMBLPQ3I.js} +3 -3
  24. package/dist/chunk-IJFPPLQW.js +50 -0
  25. package/dist/{chunk-BMFQG6RA.mjs → chunk-KJIX6V32.mjs} +107 -1885
  26. package/dist/chunk-LABHD4PU.js +109 -0
  27. package/dist/{chunk-GAIQJCAZ.js → chunk-LT5VD4KR.js} +149 -1953
  28. package/dist/{chunk-7DHKQODW.mjs → chunk-LTLCIRZY.mjs} +256 -474
  29. package/dist/chunk-N5BHXWR3.mjs +34 -0
  30. package/dist/chunk-OCO3Z5YA.js +37 -0
  31. package/dist/chunk-OIJ7XMDV.mjs +71 -0
  32. package/dist/chunk-ORBH4IBC.mjs +316 -0
  33. package/dist/chunk-OWWOAYIY.js +2652 -0
  34. package/dist/chunk-PFHOXDSW.mjs +10 -0
  35. package/dist/chunk-QRS7DJGS.js +103 -0
  36. package/dist/{chunk-NXPEJ2UR.mjs → chunk-R3X4B4JJ.mjs} +53 -6
  37. package/dist/chunk-RM7ACPTM.mjs +2601 -0
  38. package/dist/chunk-RODSGPBB.mjs +75 -0
  39. package/dist/{chunk-T6ZBA6VJ.js → chunk-UHAV34YX.js} +8 -8
  40. package/dist/{chunk-GUSTCU2W.mjs → chunk-ULANYJ7Y.mjs} +1 -59
  41. package/dist/chunk-ULDE7QSN.js +70 -0
  42. package/dist/chunk-UT36VNVZ.mjs +47 -0
  43. package/dist/chunk-UY3H4PKB.js +71 -0
  44. package/dist/{chunk-KB7UXIQZ.mjs → chunk-VIVWFQG5.mjs} +2 -1
  45. package/dist/{chunk-ESZ7CBA2.js → chunk-VKBJ3SGT.js} +6 -5
  46. package/dist/{chunk-UM7WMXIU.js → chunk-W3YOQ5ZD.js} +264 -505
  47. package/dist/{chunk-GHOFYK2E.js → chunk-XGJL6DLV.js} +55 -5
  48. package/dist/chunk-YRIBFIQ5.js +116 -0
  49. package/dist/chunk-ZWWJ3RRA.js +15 -0
  50. package/dist/data-grid.d.cts +241 -0
  51. package/dist/data-grid.d.ts +241 -0
  52. package/dist/data-grid.js +6486 -0
  53. package/dist/data-grid.mjs +6459 -0
  54. package/dist/data-table-CDQBo-Ve.d.ts +818 -0
  55. package/dist/data-table-jLzt6plY.d.cts +818 -0
  56. package/dist/data-table.d.cts +8 -42
  57. package/dist/data-table.d.ts +8 -42
  58. package/dist/data-table.js +61 -187
  59. package/dist/data-table.mjs +11 -5
  60. package/dist/finance.d.cts +534 -0
  61. package/dist/finance.d.ts +534 -0
  62. package/dist/finance.js +188 -0
  63. package/dist/finance.mjs +15 -0
  64. package/dist/forms.js +9 -6
  65. package/dist/forms.mjs +7 -4
  66. package/dist/{hooks-B2jU1GVT.d.ts → hooks-A55E0fgf.d.ts} +3 -2
  67. package/dist/{hooks-8ORd7T1A.d.cts → hooks-Bys_AZPI.d.cts} +3 -2
  68. package/dist/hooks.d.cts +1 -1
  69. package/dist/hooks.d.ts +1 -1
  70. package/dist/hooks.js +26 -23
  71. package/dist/hooks.mjs +6 -3
  72. package/dist/index.d.cts +536 -665
  73. package/dist/index.d.ts +536 -665
  74. package/dist/index.js +3829 -3408
  75. package/dist/index.mjs +2067 -1767
  76. package/dist/layouts.js +25 -25
  77. package/dist/layouts.mjs +4 -4
  78. package/dist/marketing.js +74 -74
  79. package/dist/marketing.mjs +4 -4
  80. package/dist/navigation.js +28 -28
  81. package/dist/navigation.mjs +6 -6
  82. package/dist/primitives.d.cts +72 -109
  83. package/dist/primitives.d.ts +72 -109
  84. package/dist/primitives.js +78 -72
  85. package/dist/primitives.mjs +8 -6
  86. package/dist/settings.js +9 -9
  87. package/dist/settings.mjs +4 -4
  88. package/package.json +17 -1
  89. package/dist/UnifiedTableControls-CG299y9h.d.ts +0 -1233
  90. package/dist/UnifiedTableControls-CIjRpNhy.d.cts +0 -1233
  91. package/dist/chunk-GMBGWOCR.mjs +0 -49
  92. package/dist/chunk-HBLKVQIQ.mjs +0 -23
  93. package/dist/chunk-HMAMMC72.js +0 -26
  94. package/dist/chunk-MVYRNJA6.js +0 -75
  95. /package/dist/{chunk-RVEFPVZF.mjs → chunk-C57MX3BG.mjs} +0 -0
  96. /package/dist/{chunk-C4UT5V3P.js → chunk-OWHI5VGJ.js} +0 -0
@@ -0,0 +1,2652 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var chunk5D55OVD5_js = require('./chunk-5D55OVD5.js');
5
+ var chunk33JR5SYE_js = require('./chunk-33JR5SYE.js');
6
+ var chunkZWWJ3RRA_js = require('./chunk-ZWWJ3RRA.js');
7
+ var chunkLABHD4PU_js = require('./chunk-LABHD4PU.js');
8
+ var chunkULDE7QSN_js = require('./chunk-ULDE7QSN.js');
9
+ var chunkIJFPPLQW_js = require('./chunk-IJFPPLQW.js');
10
+ var chunkC3OADNSG_js = require('./chunk-C3OADNSG.js');
11
+ var chunkQRS7DJGS_js = require('./chunk-QRS7DJGS.js');
12
+ var chunkKGGQ5NZV_js = require('./chunk-KGGQ5NZV.js');
13
+ var chunkWOITB4JL_js = require('./chunk-WOITB4JL.js');
14
+ var chunk6TGV2DNP_js = require('./chunk-6TGV2DNP.js');
15
+ var chunkLQCVRWVF_js = require('./chunk-LQCVRWVF.js');
16
+ var chunkOCO3Z5YA_js = require('./chunk-OCO3Z5YA.js');
17
+ var chunkJ6OLBSZR_js = require('./chunk-J6OLBSZR.js');
18
+ var chunkSORWLKOK_js = require('./chunk-SORWLKOK.js');
19
+ var chunkDQWHYBV2_js = require('./chunk-DQWHYBV2.js');
20
+ var chunkADIDI7AJ_js = require('./chunk-ADIDI7AJ.js');
21
+ var lucideReact = require('lucide-react');
22
+ var jsxRuntime = require('react/jsx-runtime');
23
+ var React12 = require('react');
24
+ var classVarianceAuthority = require('class-variance-authority');
25
+ var sharedUtils = require('@caffeinebounce/shared-utils');
26
+ var reactTable = require('@tanstack/react-table');
27
+ var SliderPrimitive = require('@radix-ui/react-slider');
28
+ var server = require('nuqs/server');
29
+ var zod = require('zod');
30
+ var nuqs = require('nuqs');
31
+
32
+ function _interopNamespace(e) {
33
+ if (e && e.__esModule) return e;
34
+ var n = Object.create(null);
35
+ if (e) {
36
+ Object.keys(e).forEach(function (k) {
37
+ if (k !== 'default') {
38
+ var d = Object.getOwnPropertyDescriptor(e, k);
39
+ Object.defineProperty(n, k, d.get ? d : {
40
+ enumerable: true,
41
+ get: function () { return e[k]; }
42
+ });
43
+ }
44
+ });
45
+ }
46
+ n.default = e;
47
+ return Object.freeze(n);
48
+ }
49
+
50
+ var React12__namespace = /*#__PURE__*/_interopNamespace(React12);
51
+ var SliderPrimitive__namespace = /*#__PURE__*/_interopNamespace(SliderPrimitive);
52
+
53
+ function DataTableAddButton({
54
+ label = "Add",
55
+ icon,
56
+ responsiveLabel = true,
57
+ className,
58
+ children,
59
+ ...props
60
+ }) {
61
+ const fontSizeClass = "text-xs";
62
+ const iconElement = icon ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "size-4" });
63
+ return /* @__PURE__ */ jsxRuntime.jsxs(
64
+ chunk6TGV2DNP_js.Button,
65
+ {
66
+ ...chunkZWWJ3RRA_js.dataTableTopperButtonProps,
67
+ className: chunkADIDI7AJ_js.cn(
68
+ fontSizeClass,
69
+ responsiveLabel ? chunkZWWJ3RRA_js.dataTableTopperResponsiveClasses : "px-2 w-auto",
70
+ className
71
+ ),
72
+ ...props,
73
+ children: [
74
+ iconElement,
75
+ responsiveLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden @min-[450px]:inline", children: children ?? label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: children ?? label })
76
+ ]
77
+ }
78
+ );
79
+ }
80
+ function escapeCsvField(value) {
81
+ if (value.includes(",") || value.includes('"') || value.includes("\n") || value.includes("\r")) {
82
+ return `"${value.replace(/"/g, '""')}"`;
83
+ }
84
+ return value;
85
+ }
86
+ function formatCsvValue(value) {
87
+ if (value === null || value === void 0) {
88
+ return "";
89
+ }
90
+ if (typeof value === "boolean") {
91
+ return value ? "Yes" : "No";
92
+ }
93
+ if (value instanceof Date) {
94
+ return value.toISOString();
95
+ }
96
+ if (typeof value === "object") {
97
+ try {
98
+ return JSON.stringify(value);
99
+ } catch {
100
+ return String(value);
101
+ }
102
+ }
103
+ return String(value);
104
+ }
105
+ function serializeTableExport({
106
+ table,
107
+ visibleColumnsOnly = true,
108
+ selectedRowsOnly = false,
109
+ customHeaders = {},
110
+ excludeColumns = [],
111
+ formatters = {}
112
+ }) {
113
+ const allColumns = visibleColumnsOnly ? table.getVisibleLeafColumns() : table.getAllLeafColumns();
114
+ const columns = allColumns.filter((col) => {
115
+ const colId = col.id;
116
+ if (["select", "selection", "actions", "_actions"].includes(colId)) {
117
+ return false;
118
+ }
119
+ return !excludeColumns.includes(colId);
120
+ });
121
+ const tableRows = selectedRowsOnly ? table.getFilteredSelectedRowModel().rows : table.getFilteredRowModel().rows;
122
+ return {
123
+ headers: columns.map((col) => customHeaders[col.id] ?? col.id),
124
+ rows: tableRows.map(
125
+ (row) => columns.map((col) => {
126
+ const cellValue = row.getValue(col.id);
127
+ const formatter = formatters[col.id];
128
+ return formatter ? formatter(cellValue) : formatCsvValue(cellValue);
129
+ })
130
+ )
131
+ };
132
+ }
133
+ function exportToCsv({
134
+ table,
135
+ filename = "export",
136
+ visibleColumnsOnly = true,
137
+ selectedRowsOnly = false,
138
+ customHeaders = {},
139
+ excludeColumns = [],
140
+ formatters = {}
141
+ }) {
142
+ const { headers, rows } = serializeTableExport({
143
+ table,
144
+ visibleColumnsOnly,
145
+ selectedRowsOnly,
146
+ customHeaders,
147
+ excludeColumns,
148
+ formatters
149
+ });
150
+ const csvContent = [
151
+ headers.map(escapeCsvField).join(","),
152
+ ...rows.map((row) => row.map(escapeCsvField).join(","))
153
+ ].join("\n");
154
+ const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
155
+ const url = URL.createObjectURL(blob);
156
+ const link = document.createElement("a");
157
+ link.setAttribute("href", url);
158
+ link.setAttribute("download", `${filename}.csv`);
159
+ link.style.visibility = "hidden";
160
+ document.body.appendChild(link);
161
+ link.click();
162
+ document.body.removeChild(link);
163
+ URL.revokeObjectURL(url);
164
+ }
165
+ function exportToExcel({
166
+ table,
167
+ filename = "export",
168
+ visibleColumnsOnly = true,
169
+ selectedRowsOnly = false,
170
+ customHeaders = {},
171
+ excludeColumns = [],
172
+ formatters = {}
173
+ }) {
174
+ const { headers, rows } = serializeTableExport({
175
+ table,
176
+ visibleColumnsOnly,
177
+ selectedRowsOnly,
178
+ customHeaders,
179
+ excludeColumns,
180
+ formatters
181
+ });
182
+ const sheetRows = [
183
+ headers.map((header) => ({ value: header, style: "header" })),
184
+ ...rows.map(
185
+ (row) => row.map((cell) => {
186
+ const trimmed = cell.trim();
187
+ const isNumericPattern = trimmed !== "" && /^-?\d+(\.\d+)?$/.test(trimmed);
188
+ const hasLeadingZero = /^0\d+$/.test(trimmed) || /^-0\d+$/.test(trimmed);
189
+ const numValue = Number(trimmed);
190
+ const isNumber = isNumericPattern && !hasLeadingZero && !Number.isNaN(numValue);
191
+ if (isNumber) {
192
+ return {
193
+ value: numValue,
194
+ type: "Number",
195
+ style: "number"
196
+ };
197
+ }
198
+ return { value: cell, style: "text" };
199
+ })
200
+ )
201
+ ];
202
+ const xmlContent = chunk5D55OVD5_js.buildSpreadsheetWorkbookXml({
203
+ worksheetName: "Data",
204
+ rows: sheetRows
205
+ });
206
+ chunk5D55OVD5_js.downloadExcelXml(xmlContent, filename);
207
+ }
208
+ function DataTableExportButton({
209
+ table,
210
+ onExportCsv,
211
+ onExportExcel,
212
+ onExport,
213
+ // deprecated, maps to CSV
214
+ filename = "export",
215
+ label = "Export",
216
+ disabled = false,
217
+ selectedRowsOnly = false,
218
+ excludeColumns = [],
219
+ customHeaders = {},
220
+ formatters = {}
221
+ }) {
222
+ const fontSizeClass = "text-xs";
223
+ const [isExporting, setIsExporting] = React12__namespace.useState(false);
224
+ const [exportingFormat, setExportingFormat] = React12__namespace.useState(null);
225
+ const handleExport = React12__namespace.useCallback(
226
+ async (format) => {
227
+ if (disabled) return;
228
+ setIsExporting(true);
229
+ setExportingFormat(format);
230
+ try {
231
+ if (table) {
232
+ if (format === "csv") {
233
+ exportToCsv({
234
+ table,
235
+ filename,
236
+ selectedRowsOnly,
237
+ excludeColumns,
238
+ customHeaders,
239
+ formatters
240
+ });
241
+ } else {
242
+ exportToExcel({
243
+ table,
244
+ filename,
245
+ selectedRowsOnly,
246
+ excludeColumns,
247
+ customHeaders,
248
+ formatters
249
+ });
250
+ }
251
+ } else {
252
+ if (format === "csv") {
253
+ await (onExportCsv ?? onExport)?.();
254
+ } else {
255
+ await onExportExcel?.();
256
+ }
257
+ }
258
+ } finally {
259
+ setIsExporting(false);
260
+ setExportingFormat(null);
261
+ }
262
+ },
263
+ [
264
+ table,
265
+ onExportCsv,
266
+ onExportExcel,
267
+ onExport,
268
+ filename,
269
+ selectedRowsOnly,
270
+ excludeColumns,
271
+ customHeaders,
272
+ formatters,
273
+ disabled
274
+ ]
275
+ );
276
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenu, { children: [
277
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkSORWLKOK_js.Tooltip, { children: [
278
+ /* @__PURE__ */ jsxRuntime.jsx(chunkSORWLKOK_js.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
279
+ chunk6TGV2DNP_js.Button,
280
+ {
281
+ ...chunkZWWJ3RRA_js.dataTableTopperButtonProps,
282
+ disabled: isExporting || disabled,
283
+ "aria-label": label,
284
+ className: chunkZWWJ3RRA_js.dataTableTopperOpenStateClasses,
285
+ children: isExporting ? /* @__PURE__ */ jsxRuntime.jsx(chunkOCO3Z5YA_js.SizedSpinner, { className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "size-4" })
286
+ }
287
+ ) }) }),
288
+ /* @__PURE__ */ jsxRuntime.jsx(chunkSORWLKOK_js.TooltipContent, { className: fontSizeClass, children: label })
289
+ ] }),
290
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenuContent, { align: "end", className: "w-44", children: [
291
+ /* @__PURE__ */ jsxRuntime.jsx(
292
+ chunkJ6OLBSZR_js.DropdownMenuLabel,
293
+ {
294
+ className: chunkADIDI7AJ_js.cn("font-normal text-muted-foreground", fontSizeClass),
295
+ children: "Export Data"
296
+ }
297
+ ),
298
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuSeparator, {}),
299
+ /* @__PURE__ */ jsxRuntime.jsxs(
300
+ chunkJ6OLBSZR_js.DropdownMenuItem,
301
+ {
302
+ onClick: () => handleExport("csv"),
303
+ disabled: isExporting,
304
+ className: chunkADIDI7AJ_js.cn("gap-2", fontSizeClass),
305
+ children: [
306
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: chunkZWWJ3RRA_js.dataTableTopperIconClasses }),
307
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "CSV" }),
308
+ exportingFormat === "csv" && /* @__PURE__ */ jsxRuntime.jsx(chunkOCO3Z5YA_js.SizedSpinner, { className: "size-3 ml-auto" })
309
+ ]
310
+ }
311
+ ),
312
+ /* @__PURE__ */ jsxRuntime.jsxs(
313
+ chunkJ6OLBSZR_js.DropdownMenuItem,
314
+ {
315
+ onClick: () => handleExport("excel"),
316
+ disabled: isExporting,
317
+ className: chunkADIDI7AJ_js.cn("gap-2", fontSizeClass),
318
+ children: [
319
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileSpreadsheet, { className: chunkZWWJ3RRA_js.dataTableTopperIconClasses }),
320
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Excel" }),
321
+ exportingFormat === "excel" && /* @__PURE__ */ jsxRuntime.jsx(chunkOCO3Z5YA_js.SizedSpinner, { className: "size-3 ml-auto" })
322
+ ]
323
+ }
324
+ )
325
+ ] })
326
+ ] });
327
+ }
328
+ var iconButtonVariants = classVarianceAuthority.cva(
329
+ "inline-flex items-center justify-center rounded-box transition-colors duration-200 cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
330
+ {
331
+ variants: {
332
+ variant: {
333
+ default: "text-muted-foreground hover:text-foreground hover:bg-accent",
334
+ ghost: "text-muted-foreground/50 hover:text-foreground hover:bg-transparent",
335
+ delete: "text-muted-foreground/50 hover:text-destructive hover:bg-transparent",
336
+ edit: "text-muted-foreground/50 hover:text-foreground hover:bg-transparent",
337
+ destructive: "text-muted-foreground/50 hover:text-destructive hover:bg-transparent",
338
+ success: "text-muted-foreground/50 hover:text-green-600 hover:bg-transparent",
339
+ successActive: "text-green-600 hover:text-muted-foreground/60 hover:bg-transparent"
340
+ },
341
+ size: {
342
+ default: "h-8 w-8 [&_svg]:size-4",
343
+ sm: "h-6 w-6 [&_svg]:size-3.5",
344
+ xs: "h-5 w-5 [&_svg]:size-3",
345
+ lg: "h-10 w-10 [&_svg]:size-5"
346
+ }
347
+ },
348
+ defaultVariants: {
349
+ variant: "default",
350
+ size: "default"
351
+ }
352
+ }
353
+ );
354
+ function IconButton({ className, variant, size, ...props }) {
355
+ return /* @__PURE__ */ jsxRuntime.jsx(
356
+ "button",
357
+ {
358
+ type: "button",
359
+ "data-slot": "icon-button",
360
+ className: chunkADIDI7AJ_js.cn(iconButtonVariants({ variant, size, className })),
361
+ ...props
362
+ }
363
+ );
364
+ }
365
+ function useIsDesktop() {
366
+ const [isDesktop, setIsDesktop] = React12__namespace.useState(false);
367
+ React12__namespace.useEffect(() => {
368
+ const mediaQuery = window.matchMedia("(min-width: 768px)");
369
+ setIsDesktop(mediaQuery.matches);
370
+ const handler = (e) => setIsDesktop(e.matches);
371
+ mediaQuery.addEventListener("change", handler);
372
+ return () => mediaQuery.removeEventListener("change", handler);
373
+ }, []);
374
+ return isDesktop;
375
+ }
376
+ function ActionsDropdown({
377
+ actions,
378
+ fontSizeClass,
379
+ density
380
+ }) {
381
+ const isCompact = density === "compact";
382
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenu, { children: [
383
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
384
+ IconButton,
385
+ {
386
+ variant: "ghost",
387
+ size: isCompact ? "xs" : "sm",
388
+ className: "data-[state=open]:bg-muted",
389
+ children: [
390
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: isCompact ? "size-3.5" : "size-4" }),
391
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Open menu" })
392
+ ]
393
+ }
394
+ ) }),
395
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuContent, { align: "end", className: "w-40", children: actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
396
+ action.separatorBefore && index > 0 && /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuSeparator, {}),
397
+ /* @__PURE__ */ jsxRuntime.jsxs(
398
+ chunkJ6OLBSZR_js.DropdownMenuItem,
399
+ {
400
+ onClick: action.onClick,
401
+ disabled: action.disabled,
402
+ className: chunkADIDI7AJ_js.cn(
403
+ fontSizeClass,
404
+ action.destructive && "hover:text-destructive hover:bg-destructive/10",
405
+ action.success && "hover:text-success hover:bg-success/10",
406
+ action.successActive && "text-green-600 hover:text-muted-foreground hover:bg-accent"
407
+ ),
408
+ children: [
409
+ action.icon && /* @__PURE__ */ jsxRuntime.jsx(
410
+ "span",
411
+ {
412
+ className: chunkADIDI7AJ_js.cn(
413
+ "mr-2",
414
+ action.destructive && "group-hover:text-destructive",
415
+ action.success && "group-hover:text-success",
416
+ action.successActive && "text-green-600 group-hover:text-muted-foreground"
417
+ ),
418
+ children: action.icon
419
+ }
420
+ ),
421
+ action.label
422
+ ]
423
+ }
424
+ )
425
+ ] }, action.label)) })
426
+ ] });
427
+ }
428
+ function ActionsInline({
429
+ actions,
430
+ fontSizeClass,
431
+ density
432
+ }) {
433
+ const isCompact = density === "compact";
434
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkADIDI7AJ_js.cn("flex items-center", isCompact ? "gap-0.5" : "gap-1"), children: actions.map((action) => {
435
+ const variant = action.destructive ? "delete" : action.successActive ? "successActive" : action.success ? "success" : "ghost";
436
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkSORWLKOK_js.Tooltip, { children: [
437
+ /* @__PURE__ */ jsxRuntime.jsx(chunkSORWLKOK_js.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
438
+ IconButton,
439
+ {
440
+ variant,
441
+ size: isCompact ? "xs" : "default",
442
+ onClick: action.onClick,
443
+ disabled: action.disabled,
444
+ children: [
445
+ action.icon,
446
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: action.label })
447
+ ]
448
+ }
449
+ ) }),
450
+ /* @__PURE__ */ jsxRuntime.jsx(chunkSORWLKOK_js.TooltipContent, { className: fontSizeClass, children: action.label })
451
+ ] }, action.label);
452
+ }) });
453
+ }
454
+ function DataTableRowActions({
455
+ actions,
456
+ mode = "dropdown"
457
+ }) {
458
+ const fontSizeClass = "text-xs";
459
+ const density = "comfy";
460
+ const isDesktop = useIsDesktop();
461
+ if (actions.length === 0) return null;
462
+ if (mode === "dropdown") {
463
+ return /* @__PURE__ */ jsxRuntime.jsx(
464
+ ActionsDropdown,
465
+ {
466
+ actions,
467
+ fontSizeClass,
468
+ density
469
+ }
470
+ );
471
+ }
472
+ if (mode === "inline") {
473
+ return /* @__PURE__ */ jsxRuntime.jsx(
474
+ ActionsInline,
475
+ {
476
+ actions,
477
+ fontSizeClass,
478
+ density
479
+ }
480
+ );
481
+ }
482
+ if (isDesktop) {
483
+ return /* @__PURE__ */ jsxRuntime.jsx(
484
+ ActionsInline,
485
+ {
486
+ actions,
487
+ fontSizeClass,
488
+ density
489
+ }
490
+ );
491
+ }
492
+ return /* @__PURE__ */ jsxRuntime.jsx(
493
+ ActionsDropdown,
494
+ {
495
+ actions,
496
+ fontSizeClass,
497
+ density
498
+ }
499
+ );
500
+ }
501
+ function DataTableSearch({
502
+ searchValue = "",
503
+ searchPlaceholder = "Search...",
504
+ onSearchChange,
505
+ className
506
+ }) {
507
+ const fontSizeClass = "text-xs";
508
+ const [isExpanded, setIsExpanded] = React12__namespace.useState(false);
509
+ const inputRef = React12__namespace.useRef(null);
510
+ React12__namespace.useEffect(() => {
511
+ if (searchValue && !isExpanded) {
512
+ setIsExpanded(true);
513
+ }
514
+ }, [searchValue, isExpanded]);
515
+ React12__namespace.useEffect(() => {
516
+ if (isExpanded && inputRef.current) {
517
+ inputRef.current.focus();
518
+ }
519
+ }, [isExpanded]);
520
+ const handleBlur = () => {
521
+ if (!searchValue) {
522
+ setIsExpanded(false);
523
+ }
524
+ };
525
+ const handleClear = () => {
526
+ onSearchChange?.("");
527
+ setIsExpanded(false);
528
+ };
529
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkADIDI7AJ_js.cn("relative flex items-center", className), children: /* @__PURE__ */ jsxRuntime.jsxs(
530
+ "div",
531
+ {
532
+ className: chunkADIDI7AJ_js.cn(
533
+ "flex items-center rounded-md border border-transparent transition-all duration-200 ease-out",
534
+ isExpanded ? "w-48 border-input bg-background" : "w-8 cursor-pointer"
535
+ ),
536
+ children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx(
538
+ "button",
539
+ {
540
+ type: "button",
541
+ onClick: () => !isExpanded && setIsExpanded(true),
542
+ className: chunkADIDI7AJ_js.cn(
543
+ "flex items-center justify-center shrink-0 transition-colors rounded-md",
544
+ chunkZWWJ3RRA_js.dataTableTopperIconClasses,
545
+ isExpanded ? "size-8 cursor-default" : "size-8"
546
+ ),
547
+ "aria-label": isExpanded ? void 0 : "Search",
548
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "size-4" })
549
+ }
550
+ ),
551
+ /* @__PURE__ */ jsxRuntime.jsx(
552
+ "input",
553
+ {
554
+ ref: inputRef,
555
+ type: "text",
556
+ placeholder: searchPlaceholder,
557
+ value: searchValue,
558
+ onChange: (e) => onSearchChange?.(e.target.value),
559
+ onBlur: handleBlur,
560
+ className: chunkADIDI7AJ_js.cn(
561
+ "h-8 bg-transparent outline-none placeholder:text-muted-foreground transition-all duration-200",
562
+ fontSizeClass,
563
+ isExpanded ? "w-full pr-7 opacity-100" : "w-0 opacity-0"
564
+ )
565
+ }
566
+ ),
567
+ isExpanded && searchValue && /* @__PURE__ */ jsxRuntime.jsx(
568
+ "button",
569
+ {
570
+ type: "button",
571
+ onClick: handleClear,
572
+ className: "absolute right-1.5 flex items-center justify-center size-5 rounded-sm hover:bg-accent/50",
573
+ "aria-label": "Clear search",
574
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-3.5 text-muted-foreground" })
575
+ }
576
+ )
577
+ ]
578
+ }
579
+ ) });
580
+ }
581
+ var summaryOptions = {
582
+ text: [
583
+ { value: "none", label: "None" },
584
+ { value: "count", label: "Count" },
585
+ { value: "count_unique", label: "Count unique" },
586
+ { value: "percent_empty", label: "% Empty" },
587
+ { value: "percent_filled", label: "% Filled" }
588
+ ],
589
+ number: [
590
+ { value: "none", label: "None" },
591
+ { value: "count", label: "Count" },
592
+ { value: "sum", label: "Sum" },
593
+ { value: "average", label: "Average" },
594
+ { value: "median", label: "Median" },
595
+ { value: "min", label: "Min" },
596
+ { value: "max", label: "Max" },
597
+ { value: "range", label: "Range" },
598
+ { value: "percent_empty", label: "% Empty" },
599
+ { value: "percent_filled", label: "% Filled" }
600
+ ],
601
+ boolean: [
602
+ { value: "none", label: "None" },
603
+ { value: "count", label: "Count" },
604
+ { value: "percent_empty", label: "% Empty" },
605
+ { value: "percent_filled", label: "% Filled" }
606
+ ],
607
+ date: [
608
+ { value: "none", label: "None" },
609
+ { value: "count", label: "Count" },
610
+ { value: "min", label: "Earliest" },
611
+ { value: "max", label: "Latest" },
612
+ { value: "range", label: "Date range" },
613
+ { value: "percent_empty", label: "% Empty" },
614
+ { value: "percent_filled", label: "% Filled" }
615
+ ]
616
+ };
617
+ function calculateSummary(column, allData, type, dataType) {
618
+ if (type === "none") return "";
619
+ const accessor = column.accessorFn;
620
+ if (!accessor) return "";
621
+ const allValues = allData.map((row) => accessor(row, 0)).filter((v) => v !== null && v !== void 0 && v !== "");
622
+ const totalCount = allData.length;
623
+ const filledCount = allValues.length;
624
+ const emptyCount = totalCount - filledCount;
625
+ switch (type) {
626
+ case "count":
627
+ return `Count: ${filledCount.toLocaleString()}`;
628
+ case "count_unique": {
629
+ const uniqueValues = new Set(allValues.map((v) => String(v)));
630
+ return `Unique: ${uniqueValues.size.toLocaleString()}`;
631
+ }
632
+ case "percent_empty":
633
+ return totalCount > 0 ? `Empty: ${(emptyCount / totalCount * 100).toFixed(1)}%` : "Empty: 0%";
634
+ case "percent_filled":
635
+ return totalCount > 0 ? `Filled: ${(filledCount / totalCount * 100).toFixed(1)}%` : "Filled: 0%";
636
+ case "sum":
637
+ case "average":
638
+ case "median":
639
+ case "min":
640
+ case "max":
641
+ case "range": {
642
+ if (dataType === "number") {
643
+ const numericValues = allValues.map((v) => Number(v)).filter((n) => !Number.isNaN(n));
644
+ if (numericValues.length === 0) return "\u2014";
645
+ switch (type) {
646
+ case "sum": {
647
+ const sum = numericValues.reduce((a, b) => a + b, 0);
648
+ return `Sum: ${formatNumber(sum)}`;
649
+ }
650
+ case "average": {
651
+ const avg = numericValues.reduce((a, b) => a + b, 0) / numericValues.length;
652
+ return `Avg: ${formatNumber(avg)}`;
653
+ }
654
+ case "median": {
655
+ const sorted = [...numericValues].sort((a, b) => a - b);
656
+ const mid = Math.floor(sorted.length / 2);
657
+ const median = sorted.length % 2 !== 0 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
658
+ return `Median: ${formatNumber(median)}`;
659
+ }
660
+ case "min":
661
+ return `Min: ${formatNumber(Math.min(...numericValues))}`;
662
+ case "max":
663
+ return `Max: ${formatNumber(Math.max(...numericValues))}`;
664
+ case "range": {
665
+ const min = Math.min(...numericValues);
666
+ const max = Math.max(...numericValues);
667
+ return `${formatNumber(min)} \u2013 ${formatNumber(max)}`;
668
+ }
669
+ }
670
+ }
671
+ if (dataType === "date") {
672
+ const dateValues = allValues.map((v) => {
673
+ const d = v instanceof Date ? v : new Date(String(v));
674
+ return d.getTime();
675
+ }).filter((t) => !Number.isNaN(t));
676
+ if (dateValues.length === 0) return "\u2014";
677
+ switch (type) {
678
+ case "min":
679
+ return sharedUtils.formatDate(new Date(Math.min(...dateValues)));
680
+ case "max":
681
+ return sharedUtils.formatDate(new Date(Math.max(...dateValues)));
682
+ case "range": {
683
+ const min = new Date(Math.min(...dateValues));
684
+ const max = new Date(Math.max(...dateValues));
685
+ return `${sharedUtils.formatDate(min)} \u2013 ${sharedUtils.formatDate(max)}`;
686
+ }
687
+ default:
688
+ return "\u2014";
689
+ }
690
+ }
691
+ return "\u2014";
692
+ }
693
+ default:
694
+ return "";
695
+ }
696
+ }
697
+ function formatNumber(n) {
698
+ if (Number.isInteger(n)) {
699
+ return n.toLocaleString();
700
+ }
701
+ return n.toLocaleString(void 0, {
702
+ minimumFractionDigits: 2,
703
+ maximumFractionDigits: 2
704
+ });
705
+ }
706
+ function DataTableSummary({
707
+ table,
708
+ allData,
709
+ summaryConfig,
710
+ onSummaryChange,
711
+ getColumnDataType,
712
+ gutterWidth = 0,
713
+ className
714
+ }) {
715
+ const visibleColumns = table.getVisibleLeafColumns().filter((col) => col.id !== "select" && col.id !== "actions");
716
+ const [hoveredColumnId, setHoveredColumnId] = React12__namespace.useState(
717
+ null
718
+ );
719
+ const detectDataType = React12__namespace.useCallback(
720
+ (columnId) => {
721
+ if (getColumnDataType) return getColumnDataType(columnId);
722
+ const column = table.getColumn(columnId);
723
+ if (!column) return "text";
724
+ const meta = column.columnDef.meta;
725
+ if (meta?.filterType === "number") return "number";
726
+ if (meta?.filterType === "boolean") return "boolean";
727
+ const accessor = column.accessorFn;
728
+ if (!accessor) return "text";
729
+ for (const row of allData) {
730
+ const value = accessor(row, 0);
731
+ if (value === null || value === void 0) continue;
732
+ if (typeof value === "number") return "number";
733
+ if (typeof value === "boolean") return "boolean";
734
+ if (value instanceof Date) return "date";
735
+ if (typeof value === "string" && !Number.isNaN(Date.parse(value))) {
736
+ const parsed = new Date(value);
737
+ if (parsed.getFullYear() > 1900 && parsed.getFullYear() < 2100) {
738
+ return "date";
739
+ }
740
+ }
741
+ break;
742
+ }
743
+ return "text";
744
+ },
745
+ [getColumnDataType, table, allData]
746
+ );
747
+ return /* @__PURE__ */ jsxRuntime.jsxs(
748
+ chunkLABHD4PU_js.TableRow,
749
+ {
750
+ className: chunkADIDI7AJ_js.cn("hover:bg-transparent border-0 bg-transparent", className),
751
+ children: [
752
+ gutterWidth > 0 && /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableCell, { className: "p-0 border-0", style: { width: gutterWidth } }),
753
+ visibleColumns.map((column, index) => {
754
+ const columnId = column.id;
755
+ const dataType = detectDataType(columnId);
756
+ const currentType = summaryConfig[columnId] ?? "none";
757
+ const options = summaryOptions[dataType] ?? summaryOptions.text;
758
+ const summaryValue = calculateSummary(
759
+ column,
760
+ allData,
761
+ currentType,
762
+ dataType
763
+ );
764
+ const isHovered = hoveredColumnId === columnId;
765
+ const isLastColumn = index === visibleColumns.length - 1;
766
+ const isFirstColumn = index === 0;
767
+ return /* @__PURE__ */ jsxRuntime.jsx(
768
+ chunkLABHD4PU_js.TableCell,
769
+ {
770
+ className: chunkADIDI7AJ_js.cn(
771
+ "p-0 border-0",
772
+ isLastColumn && "rounded-br-md",
773
+ isFirstColumn && "rounded-bl-md"
774
+ ),
775
+ style: { width: column.getSize(), minWidth: column.getSize() },
776
+ children: /* @__PURE__ */ jsxRuntime.jsx(
777
+ SummaryCell,
778
+ {
779
+ columnId,
780
+ column,
781
+ currentType,
782
+ summaryValue,
783
+ options,
784
+ isHovered,
785
+ onSummaryChange,
786
+ onMouseEnter: () => setHoveredColumnId(columnId),
787
+ onMouseLeave: () => setHoveredColumnId(null)
788
+ }
789
+ )
790
+ },
791
+ columnId
792
+ );
793
+ })
794
+ ]
795
+ }
796
+ );
797
+ }
798
+ function SummaryCell({
799
+ columnId,
800
+ currentType,
801
+ summaryValue,
802
+ options,
803
+ isHovered,
804
+ onSummaryChange,
805
+ onMouseEnter,
806
+ onMouseLeave
807
+ }) {
808
+ const [isOpen, setIsOpen] = React12__namespace.useState(false);
809
+ const showCalculate = currentType === "none" && (isHovered || isOpen);
810
+ return (
811
+ // biome-ignore lint/a11y/noStaticElementInteractions: Hover state for visual feedback only
812
+ /* @__PURE__ */ jsxRuntime.jsx(
813
+ "div",
814
+ {
815
+ className: chunkADIDI7AJ_js.cn(
816
+ "flex items-center min-w-0",
817
+ "px-2 py-1"
818
+ ),
819
+ onMouseEnter,
820
+ onMouseLeave,
821
+ role: "presentation",
822
+ children: /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenu, { open: isOpen, onOpenChange: setIsOpen, children: [
823
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
824
+ "button",
825
+ {
826
+ type: "button",
827
+ className: chunkADIDI7AJ_js.cn(
828
+ "group flex items-center gap-1 text-xs transition-colors rounded px-1 py-0.5 -mx-1 focus:outline-none focus-visible:outline-none",
829
+ currentType === "none" ? "text-muted-foreground/50 hover:text-muted-foreground" : "text-muted-foreground hover:text-foreground"
830
+ ),
831
+ children: [
832
+ currentType === "none" ? /* @__PURE__ */ jsxRuntime.jsx(
833
+ "span",
834
+ {
835
+ className: chunkADIDI7AJ_js.cn(
836
+ "italic transition-opacity",
837
+ showCalculate ? "opacity-100" : "opacity-0"
838
+ ),
839
+ children: "Calculate"
840
+ }
841
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate italic pr-1", children: summaryValue }),
842
+ /* @__PURE__ */ jsxRuntime.jsx(
843
+ lucideReact.ChevronDown,
844
+ {
845
+ className: chunkADIDI7AJ_js.cn(
846
+ "size-3 shrink-0 transition-opacity",
847
+ currentType !== "none" ? "opacity-0 group-hover:opacity-50" : "opacity-0"
848
+ )
849
+ }
850
+ )
851
+ ]
852
+ }
853
+ ) }),
854
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuContent, { align: "start", className: "w-40", children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
855
+ chunkJ6OLBSZR_js.DropdownMenuItem,
856
+ {
857
+ onClick: () => onSummaryChange(columnId, option.value),
858
+ className: chunkADIDI7AJ_js.cn(
859
+ "text-xs",
860
+ currentType === option.value && "bg-accent"
861
+ ),
862
+ children: option.label
863
+ },
864
+ option.value
865
+ )) })
866
+ ] })
867
+ }
868
+ )
869
+ );
870
+ }
871
+ function DataTableTopper({
872
+ tabs,
873
+ activeTab,
874
+ onTabChange,
875
+ gutterWidth = 0,
876
+ className,
877
+ children,
878
+ ...props
879
+ }) {
880
+ return /* @__PURE__ */ jsxRuntime.jsx(
881
+ "div",
882
+ {
883
+ className: chunkADIDI7AJ_js.cn(
884
+ // Container context for responsive layout based on available width
885
+ "@container w-full min-w-0 shrink-0",
886
+ // Visual styling
887
+ "border-b border-border/40 pb-1",
888
+ className
889
+ ),
890
+ ...props,
891
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-row items-center justify-between gap-3", children: [
892
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink-0 items-center gap-0.5", children: [
893
+ gutterWidth > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", style: { width: gutterWidth } }),
894
+ tabs && tabs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "block @min-[450px]:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(chunkWOITB4JL_js.Select, { value: activeTab, onValueChange: onTabChange, children: [
895
+ /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectTrigger, { className: "h-7 w-[100px] text-xs", children: /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectValue, { placeholder: "Select tab" }) }),
896
+ /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectContent, { children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectItem, { value: tab.id, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
897
+ tab.label,
898
+ tab.count !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: tab.count })
899
+ ] }) }, tab.id)) })
900
+ ] }) }),
901
+ /* @__PURE__ */ jsxRuntime.jsx(
902
+ "div",
903
+ {
904
+ className: chunkADIDI7AJ_js.cn(
905
+ "items-center gap-0.5 overflow-x-auto no-scrollbar",
906
+ tabs && tabs.length > 0 ? "hidden @min-[450px]:flex" : "flex"
907
+ ),
908
+ children: tabs?.map((tab) => /* @__PURE__ */ jsxRuntime.jsxs(
909
+ "button",
910
+ {
911
+ type: "button",
912
+ onClick: () => onTabChange?.(tab.id),
913
+ className: chunkADIDI7AJ_js.cn(
914
+ "relative flex items-center gap-1.5 px-2 py-1 text-sm transition-colors rounded-md whitespace-nowrap",
915
+ activeTab === tab.id ? "text-foreground font-medium" : "text-muted-foreground hover:text-foreground hover:bg-accent/50"
916
+ ),
917
+ children: [
918
+ tab.label,
919
+ tab.count !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
920
+ "span",
921
+ {
922
+ className: chunkADIDI7AJ_js.cn(
923
+ "text-xs tabular-nums",
924
+ activeTab === tab.id ? "text-muted-foreground" : "text-muted-foreground/60"
925
+ ),
926
+ children: tab.count
927
+ }
928
+ ),
929
+ activeTab === tab.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0 left-2 right-2 h-0.5 bg-foreground rounded-full" })
930
+ ]
931
+ },
932
+ tab.id
933
+ ))
934
+ }
935
+ )
936
+ ] }),
937
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children })
938
+ ] })
939
+ }
940
+ );
941
+ }
942
+ function hasUnsavedChanges(currentState, activeView) {
943
+ if (!activeView) return false;
944
+ const visA = JSON.stringify(currentState.columnVisibility ?? {});
945
+ const visB = JSON.stringify(activeView.columnVisibility ?? {});
946
+ if (visA !== visB) return true;
947
+ const filtA = JSON.stringify(currentState.filters ?? []);
948
+ const filtB = JSON.stringify(activeView.filters ?? []);
949
+ if (filtA !== filtB) return true;
950
+ const sortA = JSON.stringify(currentState.sorting ?? []);
951
+ const sortB = JSON.stringify(activeView.sorting ?? []);
952
+ if (sortA !== sortB) return true;
953
+ const orderA = JSON.stringify(currentState.columnOrder ?? []);
954
+ const orderB = JSON.stringify(activeView.columnOrder ?? []);
955
+ if (orderA !== orderB) return true;
956
+ const wrapA = JSON.stringify(currentState.columnWrapping ?? {});
957
+ const wrapB = JSON.stringify(activeView.columnWrapping ?? {});
958
+ if (wrapA !== wrapB) return true;
959
+ const rowA = JSON.stringify(currentState.rowOrder ?? []);
960
+ const rowB = JSON.stringify(activeView.rowOrder ?? []);
961
+ if (rowA !== rowB) return true;
962
+ return false;
963
+ }
964
+ function DataTableViews({
965
+ views,
966
+ activeViewId,
967
+ currentState,
968
+ onSelectView,
969
+ onSaveView,
970
+ onUpdateView,
971
+ onDeleteView,
972
+ onSetDefaultView,
973
+ className
974
+ }) {
975
+ const fontSizeClass = "text-xs";
976
+ const [saveDialogOpen, setSaveDialogOpen] = React12__namespace.useState(false);
977
+ const [newViewName, setNewViewName] = React12__namespace.useState("");
978
+ const [setAsDefault, setSetAsDefault] = React12__namespace.useState(false);
979
+ const [nameError, setNameError] = React12__namespace.useState(null);
980
+ const activeView = views.find((v) => v.id === activeViewId);
981
+ views.find((v) => v.isDefault);
982
+ const hasChanges = hasUnsavedChanges(currentState, activeView);
983
+ const checkDuplicateName = (name) => {
984
+ const trimmedName = name.trim();
985
+ if (!trimmedName) {
986
+ setNameError(null);
987
+ return;
988
+ }
989
+ const isDuplicate = views.some(
990
+ (v) => v.name.toLowerCase() === trimmedName.toLowerCase()
991
+ );
992
+ setNameError(isDuplicate ? "A view with this name already exists" : null);
993
+ };
994
+ const handleSaveNewView = () => {
995
+ if (!newViewName.trim()) return;
996
+ const trimmedName = newViewName.trim();
997
+ const isDuplicate = views.some(
998
+ (v) => v.name.toLowerCase() === trimmedName.toLowerCase()
999
+ );
1000
+ if (isDuplicate) {
1001
+ setNameError("A view with this name already exists");
1002
+ return;
1003
+ }
1004
+ if (onSaveView) {
1005
+ onSaveView({
1006
+ name: trimmedName,
1007
+ columnVisibility: currentState.columnVisibility,
1008
+ columnOrder: currentState.columnOrder,
1009
+ filters: currentState.filters,
1010
+ sorting: currentState.sorting,
1011
+ isDefault: setAsDefault
1012
+ });
1013
+ }
1014
+ setNewViewName("");
1015
+ setSetAsDefault(false);
1016
+ setNameError(null);
1017
+ setSaveDialogOpen(false);
1018
+ };
1019
+ const handleUpdateCurrentView = () => {
1020
+ if (!activeViewId || !onUpdateView) return;
1021
+ onUpdateView(activeViewId, {
1022
+ columnVisibility: currentState.columnVisibility,
1023
+ columnOrder: currentState.columnOrder,
1024
+ filters: currentState.filters,
1025
+ sorting: currentState.sorting,
1026
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1027
+ });
1028
+ };
1029
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1030
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkADIDI7AJ_js.cn("flex items-center gap-1", className), children: /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenu, { children: [
1031
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
1032
+ chunk6TGV2DNP_js.Button,
1033
+ {
1034
+ ...chunkZWWJ3RRA_js.dataTableTopperButtonProps,
1035
+ className: chunkADIDI7AJ_js.cn(
1036
+ fontSizeClass,
1037
+ chunkZWWJ3RRA_js.dataTableTopperOpenStateClasses,
1038
+ chunkZWWJ3RRA_js.dataTableTopperResponsiveClasses
1039
+ ),
1040
+ children: [
1041
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutGrid, { className: "size-4" }),
1042
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden @min-[450px]:inline", children: activeView?.name ?? "Default View" })
1043
+ ]
1044
+ }
1045
+ ) }),
1046
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenuContent, { align: "start", className: "w-56", children: [
1047
+ views.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1048
+ views.map((view) => /* @__PURE__ */ jsxRuntime.jsxs(
1049
+ "div",
1050
+ {
1051
+ className: "group relative flex items-center",
1052
+ children: [
1053
+ /* @__PURE__ */ jsxRuntime.jsxs(
1054
+ chunkJ6OLBSZR_js.DropdownMenuItem,
1055
+ {
1056
+ onClick: () => onSelectView(view),
1057
+ className: chunkADIDI7AJ_js.cn(
1058
+ "flex-1 flex items-center justify-between pr-16",
1059
+ fontSizeClass
1060
+ ),
1061
+ children: [
1062
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
1063
+ view.isDefault && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Star, { className: "size-3 fill-yellow-400 text-yellow-400" }),
1064
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: view.name })
1065
+ ] }),
1066
+ activeViewId === view.id && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5 text-primary" })
1067
+ ]
1068
+ }
1069
+ ),
1070
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-2 flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity", children: [
1071
+ !view.isDefault && onSetDefaultView && /* @__PURE__ */ jsxRuntime.jsx(
1072
+ "button",
1073
+ {
1074
+ type: "button",
1075
+ onClick: (e) => {
1076
+ e.stopPropagation();
1077
+ onSetDefaultView(view.id);
1078
+ },
1079
+ className: "p-1 rounded hover:bg-accent text-muted-foreground hover:text-foreground",
1080
+ title: "Set as default",
1081
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Star, { className: "size-3" })
1082
+ }
1083
+ ),
1084
+ views.length > 1 && onDeleteView && /* @__PURE__ */ jsxRuntime.jsx(
1085
+ "button",
1086
+ {
1087
+ type: "button",
1088
+ onClick: (e) => {
1089
+ e.stopPropagation();
1090
+ onDeleteView(view.id);
1091
+ },
1092
+ className: "p-1 rounded hover:bg-accent text-muted-foreground hover:text-destructive",
1093
+ title: "Delete view",
1094
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "size-3" })
1095
+ }
1096
+ )
1097
+ ] })
1098
+ ]
1099
+ },
1100
+ view.id
1101
+ )),
1102
+ /* @__PURE__ */ jsxRuntime.jsx(chunkJ6OLBSZR_js.DropdownMenuSeparator, {})
1103
+ ] }) : null,
1104
+ onUpdateView && hasChanges && activeView && /* @__PURE__ */ jsxRuntime.jsxs(
1105
+ chunkJ6OLBSZR_js.DropdownMenuItem,
1106
+ {
1107
+ onClick: handleUpdateCurrentView,
1108
+ className: fontSizeClass,
1109
+ children: [
1110
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Save, { className: "mr-2 size-3.5" }),
1111
+ "Save changes"
1112
+ ]
1113
+ }
1114
+ ),
1115
+ onSaveView && /* @__PURE__ */ jsxRuntime.jsxs(
1116
+ chunkJ6OLBSZR_js.DropdownMenuItem,
1117
+ {
1118
+ onClick: () => setSaveDialogOpen(true),
1119
+ className: fontSizeClass,
1120
+ children: [
1121
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "mr-2 size-3.5" }),
1122
+ "Save as new view"
1123
+ ]
1124
+ }
1125
+ )
1126
+ ] })
1127
+ ] }) }),
1128
+ /* @__PURE__ */ jsxRuntime.jsx(
1129
+ chunkKGGQ5NZV_js.Dialog,
1130
+ {
1131
+ open: saveDialogOpen,
1132
+ onOpenChange: (open) => {
1133
+ setSaveDialogOpen(open);
1134
+ if (!open) {
1135
+ setNewViewName("");
1136
+ setSetAsDefault(false);
1137
+ setNameError(null);
1138
+ }
1139
+ },
1140
+ children: /* @__PURE__ */ jsxRuntime.jsxs(chunkKGGQ5NZV_js.DialogContent, { className: "sm:max-w-md", children: [
1141
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKGGQ5NZV_js.DialogHeader, { children: [
1142
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKGGQ5NZV_js.DialogTitle, { children: "Save View" }),
1143
+ /* @__PURE__ */ jsxRuntime.jsx(chunkKGGQ5NZV_js.DialogDescription, { children: "Save your current table configuration as a reusable view." })
1144
+ ] }),
1145
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 py-4", children: [
1146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1147
+ /* @__PURE__ */ jsxRuntime.jsx(chunk33JR5SYE_js.Label, { htmlFor: "view-name", children: "View name" }),
1148
+ /* @__PURE__ */ jsxRuntime.jsx(
1149
+ chunkDQWHYBV2_js.Input,
1150
+ {
1151
+ id: "view-name",
1152
+ placeholder: "e.g., Active Users, Recent Signups",
1153
+ value: newViewName,
1154
+ onChange: (e) => {
1155
+ setNewViewName(e.target.value);
1156
+ checkDuplicateName(e.target.value);
1157
+ },
1158
+ onKeyDown: (e) => {
1159
+ if (e.key === "Enter") handleSaveNewView();
1160
+ },
1161
+ className: nameError ? "border-destructive" : "",
1162
+ autoFocus: true
1163
+ }
1164
+ ),
1165
+ nameError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: nameError })
1166
+ ] }),
1167
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1168
+ /* @__PURE__ */ jsxRuntime.jsx(
1169
+ "input",
1170
+ {
1171
+ type: "checkbox",
1172
+ id: "set-default",
1173
+ checked: setAsDefault,
1174
+ onChange: (e) => setSetAsDefault(e.target.checked),
1175
+ className: "size-4 rounded border-muted-foreground/30"
1176
+ }
1177
+ ),
1178
+ /* @__PURE__ */ jsxRuntime.jsx(
1179
+ chunk33JR5SYE_js.Label,
1180
+ {
1181
+ htmlFor: "set-default",
1182
+ className: "text-sm font-normal cursor-pointer",
1183
+ children: "Set as default view"
1184
+ }
1185
+ )
1186
+ ] })
1187
+ ] }),
1188
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkKGGQ5NZV_js.DialogFooter, { children: [
1189
+ /* @__PURE__ */ jsxRuntime.jsx(chunk6TGV2DNP_js.Button, { variant: "outline", onClick: () => setSaveDialogOpen(false), children: "Cancel" }),
1190
+ /* @__PURE__ */ jsxRuntime.jsx(
1191
+ chunk6TGV2DNP_js.Button,
1192
+ {
1193
+ onClick: handleSaveNewView,
1194
+ disabled: !newViewName.trim() || !!nameError,
1195
+ children: "Save View"
1196
+ }
1197
+ )
1198
+ ] })
1199
+ ] })
1200
+ }
1201
+ )
1202
+ ] });
1203
+ }
1204
+
1205
+ // src/blocks/table/config.ts
1206
+ var dataTableConfig = {
1207
+ textOperators: [
1208
+ { label: "Contains", value: "iLike" },
1209
+ { label: "Does not contain", value: "notILike" },
1210
+ { label: "Is", value: "eq" },
1211
+ { label: "Is not", value: "ne" },
1212
+ { label: "Is empty", value: "isEmpty" },
1213
+ { label: "Is not empty", value: "isNotEmpty" }
1214
+ ],
1215
+ numericOperators: [
1216
+ { label: "Is", value: "eq" },
1217
+ { label: "Is not", value: "ne" },
1218
+ { label: "Is less than", value: "lt" },
1219
+ { label: "Is less than or equal to", value: "lte" },
1220
+ { label: "Is greater than", value: "gt" },
1221
+ { label: "Is greater than or equal to", value: "gte" },
1222
+ { label: "Is between", value: "isBetween" },
1223
+ { label: "Is empty", value: "isEmpty" },
1224
+ { label: "Is not empty", value: "isNotEmpty" }
1225
+ ],
1226
+ dateOperators: [
1227
+ { label: "Is", value: "eq" },
1228
+ { label: "Is not", value: "ne" },
1229
+ { label: "Is before", value: "lt" },
1230
+ { label: "Is after", value: "gt" },
1231
+ { label: "Is on or before", value: "lte" },
1232
+ { label: "Is on or after", value: "gte" },
1233
+ { label: "Is between", value: "isBetween" },
1234
+ { label: "Is relative to today", value: "isRelativeToToday" },
1235
+ { label: "Is empty", value: "isEmpty" },
1236
+ { label: "Is not empty", value: "isNotEmpty" }
1237
+ ],
1238
+ selectOperators: [
1239
+ { label: "Is", value: "eq" },
1240
+ { label: "Is not", value: "ne" },
1241
+ { label: "Is empty", value: "isEmpty" },
1242
+ { label: "Is not empty", value: "isNotEmpty" }
1243
+ ],
1244
+ multiSelectOperators: [
1245
+ { label: "Has any of", value: "inArray" },
1246
+ { label: "Has none of", value: "notInArray" },
1247
+ { label: "Is empty", value: "isEmpty" },
1248
+ { label: "Is not empty", value: "isNotEmpty" }
1249
+ ],
1250
+ booleanOperators: [
1251
+ { label: "Is", value: "eq" },
1252
+ { label: "Is not", value: "ne" }
1253
+ ],
1254
+ sortOrders: [
1255
+ { label: "Asc", value: "asc" },
1256
+ { label: "Desc", value: "desc" }
1257
+ ],
1258
+ filterVariants: [
1259
+ "text",
1260
+ "number",
1261
+ "range",
1262
+ "date",
1263
+ "dateRange",
1264
+ "boolean",
1265
+ "select",
1266
+ "multiSelect"
1267
+ ],
1268
+ operators: [
1269
+ "iLike",
1270
+ "notILike",
1271
+ "eq",
1272
+ "ne",
1273
+ "inArray",
1274
+ "notInArray",
1275
+ "isEmpty",
1276
+ "isNotEmpty",
1277
+ "lt",
1278
+ "lte",
1279
+ "gt",
1280
+ "gte",
1281
+ "isBetween",
1282
+ "isRelativeToToday"
1283
+ ],
1284
+ joinOperators: ["and", "or"]
1285
+ };
1286
+ function DataTablePagination({
1287
+ table,
1288
+ pageSizeOptions = [10, 20, 30, 40, 50],
1289
+ className,
1290
+ ...props
1291
+ }) {
1292
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1293
+ "div",
1294
+ {
1295
+ className: chunkADIDI7AJ_js.cn(
1296
+ "flex w-full flex-col-reverse items-center justify-between gap-4 overflow-auto p-1 sm:flex-row sm:gap-8",
1297
+ className
1298
+ ),
1299
+ ...props,
1300
+ children: [
1301
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 whitespace-nowrap text-muted-foreground text-sm", children: [
1302
+ table.getFilteredSelectedRowModel().rows.length,
1303
+ " of",
1304
+ " ",
1305
+ table.getFilteredRowModel().rows.length,
1306
+ " row(s) selected."
1307
+ ] }),
1308
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col-reverse items-center gap-4 sm:flex-row sm:gap-6 lg:gap-8", children: [
1309
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
1310
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-nowrap font-medium text-sm", children: "Rows per page" }),
1311
+ /* @__PURE__ */ jsxRuntime.jsxs(
1312
+ chunkWOITB4JL_js.Select,
1313
+ {
1314
+ value: `${table.getState().pagination.pageSize}`,
1315
+ onValueChange: (value) => {
1316
+ table.setPageSize(Number(value));
1317
+ },
1318
+ children: [
1319
+ /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectTrigger, { className: "h-8 w-18 data-size:h-8", children: /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectValue, { placeholder: table.getState().pagination.pageSize }) }),
1320
+ /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectContent, { side: "top", children: /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectGroup, { children: pageSizeOptions.map((pageSize) => /* @__PURE__ */ jsxRuntime.jsx(chunkWOITB4JL_js.SelectItem, { value: `${pageSize}`, children: pageSize }, pageSize)) }) })
1321
+ ]
1322
+ }
1323
+ )
1324
+ ] }),
1325
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center font-medium text-sm", children: [
1326
+ "Page ",
1327
+ table.getState().pagination.pageIndex + 1,
1328
+ " of",
1329
+ " ",
1330
+ table.getPageCount()
1331
+ ] }),
1332
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
1333
+ /* @__PURE__ */ jsxRuntime.jsx(
1334
+ chunk6TGV2DNP_js.Button,
1335
+ {
1336
+ "aria-label": "Go to first page",
1337
+ variant: "outline",
1338
+ size: "icon",
1339
+ className: "hidden size-8 lg:flex",
1340
+ onClick: () => table.setPageIndex(0),
1341
+ disabled: !table.getCanPreviousPage(),
1342
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeft, {})
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ jsxRuntime.jsx(
1346
+ chunk6TGV2DNP_js.Button,
1347
+ {
1348
+ "aria-label": "Go to previous page",
1349
+ variant: "outline",
1350
+ size: "icon",
1351
+ className: "size-8",
1352
+ onClick: () => table.previousPage(),
1353
+ disabled: !table.getCanPreviousPage(),
1354
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, {})
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ jsxRuntime.jsx(
1358
+ chunk6TGV2DNP_js.Button,
1359
+ {
1360
+ "aria-label": "Go to next page",
1361
+ variant: "outline",
1362
+ size: "icon",
1363
+ className: "size-8",
1364
+ onClick: () => table.nextPage(),
1365
+ disabled: !table.getCanNextPage(),
1366
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, {})
1367
+ }
1368
+ ),
1369
+ /* @__PURE__ */ jsxRuntime.jsx(
1370
+ chunk6TGV2DNP_js.Button,
1371
+ {
1372
+ "aria-label": "Go to last page",
1373
+ variant: "outline",
1374
+ size: "icon",
1375
+ className: "hidden size-8 lg:flex",
1376
+ onClick: () => table.setPageIndex(table.getPageCount() - 1),
1377
+ disabled: !table.getCanNextPage(),
1378
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsRight, {})
1379
+ }
1380
+ )
1381
+ ] })
1382
+ ] })
1383
+ ]
1384
+ }
1385
+ );
1386
+ }
1387
+
1388
+ // src/blocks/table/lib/data-table.ts
1389
+ function getColumnPinningStyle({
1390
+ column,
1391
+ withBorder = false
1392
+ }) {
1393
+ const isPinned = column.getIsPinned();
1394
+ const isLastLeftPinnedColumn = isPinned === "left" && column.getIsLastColumn("left");
1395
+ const isFirstRightPinnedColumn = isPinned === "right" && column.getIsFirstColumn("right");
1396
+ return {
1397
+ boxShadow: withBorder ? isLastLeftPinnedColumn ? "-4px 0 4px -4px var(--border) inset" : isFirstRightPinnedColumn ? "4px 0 4px -4px var(--border) inset" : void 0 : void 0,
1398
+ left: isPinned === "left" ? `${column.getStart("left")}px` : void 0,
1399
+ right: isPinned === "right" ? `${column.getAfter("right")}px` : void 0,
1400
+ opacity: isPinned ? 0.97 : 1,
1401
+ position: isPinned ? "sticky" : "relative",
1402
+ background: isPinned ? "var(--background)" : "var(--background)",
1403
+ width: column.getSize(),
1404
+ zIndex: isPinned ? 1 : void 0
1405
+ };
1406
+ }
1407
+ function getFilterOperators(filterVariant) {
1408
+ const operatorMap = {
1409
+ text: dataTableConfig.textOperators,
1410
+ number: dataTableConfig.numericOperators,
1411
+ range: dataTableConfig.numericOperators,
1412
+ date: dataTableConfig.dateOperators,
1413
+ dateRange: dataTableConfig.dateOperators,
1414
+ boolean: dataTableConfig.booleanOperators,
1415
+ select: dataTableConfig.selectOperators,
1416
+ multiSelect: dataTableConfig.multiSelectOperators
1417
+ };
1418
+ return operatorMap[filterVariant] ?? dataTableConfig.textOperators;
1419
+ }
1420
+ function getDefaultFilterOperator(filterVariant) {
1421
+ const operators = getFilterOperators(filterVariant);
1422
+ return operators[0]?.value ?? (filterVariant === "text" ? "iLike" : "eq");
1423
+ }
1424
+ function getValidFilters(filters) {
1425
+ return filters.filter(
1426
+ (filter) => filter.operator === "isEmpty" || filter.operator === "isNotEmpty" || (Array.isArray(filter.value) ? filter.value.length > 0 : filter.value !== "" && filter.value !== null && filter.value !== void 0)
1427
+ );
1428
+ }
1429
+ function DataTable({
1430
+ table,
1431
+ actionBar,
1432
+ footer,
1433
+ onRowClick,
1434
+ getRowClassName,
1435
+ children,
1436
+ className,
1437
+ ...props
1438
+ }) {
1439
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1440
+ "div",
1441
+ {
1442
+ className: chunkADIDI7AJ_js.cn("flex w-full flex-col gap-2.5 overflow-auto", className),
1443
+ ...props,
1444
+ children: [
1445
+ children,
1446
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(chunkLABHD4PU_js.Table, { children: [
1447
+ /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(
1448
+ chunkLABHD4PU_js.TableHead,
1449
+ {
1450
+ colSpan: header.colSpan,
1451
+ style: {
1452
+ ...getColumnPinningStyle({ column: header.column })
1453
+ },
1454
+ children: header.isPlaceholder ? null : reactTable.flexRender(
1455
+ header.column.columnDef.header,
1456
+ header.getContext()
1457
+ )
1458
+ },
1459
+ header.id
1460
+ )) }, headerGroup.id)) }),
1461
+ /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(
1462
+ chunkLABHD4PU_js.TableRow,
1463
+ {
1464
+ "data-state": row.getIsSelected() && "selected",
1465
+ className: chunkADIDI7AJ_js.cn(
1466
+ onRowClick && "cursor-pointer",
1467
+ getRowClassName?.(row)
1468
+ ),
1469
+ onClick: onRowClick ? () => onRowClick(row) : void 0,
1470
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsxRuntime.jsx(
1471
+ chunkLABHD4PU_js.TableCell,
1472
+ {
1473
+ style: {
1474
+ ...getColumnPinningStyle({ column: cell.column })
1475
+ },
1476
+ children: reactTable.flexRender(
1477
+ cell.column.columnDef.cell,
1478
+ cell.getContext()
1479
+ )
1480
+ },
1481
+ cell.id
1482
+ ))
1483
+ },
1484
+ row.id
1485
+ )) : /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableRow, { children: /* @__PURE__ */ jsxRuntime.jsx(
1486
+ chunkLABHD4PU_js.TableCell,
1487
+ {
1488
+ colSpan: table.getAllColumns().length,
1489
+ className: "h-24 text-center",
1490
+ children: "No results."
1491
+ }
1492
+ ) }) }),
1493
+ footer ? /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableFooter, { children: footer }) : null
1494
+ ] }) }),
1495
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2.5", children: [
1496
+ /* @__PURE__ */ jsxRuntime.jsx(DataTablePagination, { table }),
1497
+ actionBar && table.getFilteredSelectedRowModel().rows.length > 0 && actionBar
1498
+ ] })
1499
+ ]
1500
+ }
1501
+ );
1502
+ }
1503
+ function DataTableColumnHeader({
1504
+ column,
1505
+ label,
1506
+ className,
1507
+ ...props
1508
+ }) {
1509
+ if (!column.getCanSort() && !column.getCanHide()) {
1510
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkADIDI7AJ_js.cn(className), children: label });
1511
+ }
1512
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenu, { children: [
1513
+ /* @__PURE__ */ jsxRuntime.jsxs(
1514
+ chunkJ6OLBSZR_js.DropdownMenuTrigger,
1515
+ {
1516
+ className: chunkADIDI7AJ_js.cn(
1517
+ "-ml-1.5 flex h-8 items-center gap-1.5 rounded-md px-2 py-1.5 hover:bg-accent focus:outline-none focus:ring-1 focus:ring-ring data-[state=open]:bg-accent [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground",
1518
+ className
1519
+ ),
1520
+ ...props,
1521
+ children: [
1522
+ label,
1523
+ column.getCanSort() && (column.getIsSorted() === "desc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) : column.getIsSorted() === "asc" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, {}))
1524
+ ]
1525
+ }
1526
+ ),
1527
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkJ6OLBSZR_js.DropdownMenuContent, { align: "start", className: "w-28", children: [
1528
+ column.getCanSort() && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1529
+ /* @__PURE__ */ jsxRuntime.jsxs(
1530
+ chunkJ6OLBSZR_js.DropdownMenuCheckboxItem,
1531
+ {
1532
+ className: "relative pr-8 pl-2 [&>span:first-child]:right-2 [&>span:first-child]:left-auto [&_svg]:text-muted-foreground",
1533
+ checked: column.getIsSorted() === "asc",
1534
+ onClick: () => column.toggleSorting(false),
1535
+ children: [
1536
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, {}),
1537
+ "Asc"
1538
+ ]
1539
+ }
1540
+ ),
1541
+ /* @__PURE__ */ jsxRuntime.jsxs(
1542
+ chunkJ6OLBSZR_js.DropdownMenuCheckboxItem,
1543
+ {
1544
+ className: "relative pr-8 pl-2 [&>span:first-child]:right-2 [&>span:first-child]:left-auto [&_svg]:text-muted-foreground",
1545
+ checked: column.getIsSorted() === "desc",
1546
+ onClick: () => column.toggleSorting(true),
1547
+ children: [
1548
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}),
1549
+ "Desc"
1550
+ ]
1551
+ }
1552
+ ),
1553
+ column.getIsSorted() && /* @__PURE__ */ jsxRuntime.jsxs(
1554
+ chunkJ6OLBSZR_js.DropdownMenuItem,
1555
+ {
1556
+ className: "pl-2 [&_svg]:text-muted-foreground",
1557
+ onClick: () => column.clearSorting(),
1558
+ children: [
1559
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}),
1560
+ "Reset"
1561
+ ]
1562
+ }
1563
+ )
1564
+ ] }),
1565
+ column.getCanHide() && /* @__PURE__ */ jsxRuntime.jsxs(
1566
+ chunkJ6OLBSZR_js.DropdownMenuCheckboxItem,
1567
+ {
1568
+ className: "relative pr-8 pl-2 [&>span:first-child]:right-2 [&>span:first-child]:left-auto [&_svg]:text-muted-foreground",
1569
+ checked: !column.getIsVisible(),
1570
+ onClick: () => column.toggleVisibility(false),
1571
+ children: [
1572
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, {}),
1573
+ "Hide"
1574
+ ]
1575
+ }
1576
+ )
1577
+ ] })
1578
+ ] });
1579
+ }
1580
+
1581
+ // src/blocks/table/lib/format.ts
1582
+ function formatDate2(date, opts = {}) {
1583
+ if (!date) return "";
1584
+ try {
1585
+ return new Intl.DateTimeFormat("en-US", {
1586
+ month: opts.month ?? "long",
1587
+ day: opts.day ?? "numeric",
1588
+ year: opts.year ?? "numeric",
1589
+ ...opts
1590
+ }).format(new Date(date));
1591
+ } catch (_err) {
1592
+ return "";
1593
+ }
1594
+ }
1595
+ function getIsDateRange(value) {
1596
+ return value && typeof value === "object" && !Array.isArray(value);
1597
+ }
1598
+ function parseAsDate(timestamp) {
1599
+ if (!timestamp) return void 0;
1600
+ const numericTimestamp = typeof timestamp === "string" ? Number(timestamp) : timestamp;
1601
+ const date = new Date(numericTimestamp);
1602
+ return !Number.isNaN(date.getTime()) ? date : void 0;
1603
+ }
1604
+ function parseColumnFilterValue(value) {
1605
+ if (value === null || value === void 0) {
1606
+ return [];
1607
+ }
1608
+ if (Array.isArray(value)) {
1609
+ return value.map((item) => {
1610
+ if (typeof item === "number" || typeof item === "string") {
1611
+ return item;
1612
+ }
1613
+ return void 0;
1614
+ });
1615
+ }
1616
+ if (typeof value === "string" || typeof value === "number") {
1617
+ return [value];
1618
+ }
1619
+ return [];
1620
+ }
1621
+ function DataTableDateFilter({
1622
+ column,
1623
+ title,
1624
+ multiple
1625
+ }) {
1626
+ const columnFilterValue = column.getFilterValue();
1627
+ const selectedDates = React12__namespace.useMemo(() => {
1628
+ if (!columnFilterValue) {
1629
+ return multiple ? { from: void 0, to: void 0 } : [];
1630
+ }
1631
+ if (multiple) {
1632
+ const timestamps2 = parseColumnFilterValue(columnFilterValue);
1633
+ return {
1634
+ from: parseAsDate(timestamps2[0]),
1635
+ to: parseAsDate(timestamps2[1])
1636
+ };
1637
+ }
1638
+ const timestamps = parseColumnFilterValue(columnFilterValue);
1639
+ const date = parseAsDate(timestamps[0]);
1640
+ return date ? [date] : [];
1641
+ }, [columnFilterValue, multiple]);
1642
+ const onSelect = React12__namespace.useCallback(
1643
+ (date) => {
1644
+ if (!date) {
1645
+ column.setFilterValue(void 0);
1646
+ return;
1647
+ }
1648
+ if (multiple && !("getTime" in date)) {
1649
+ const from = date.from?.getTime();
1650
+ const to = date.to?.getTime();
1651
+ column.setFilterValue(from || to ? [from, to] : void 0);
1652
+ } else if (!multiple && "getTime" in date) {
1653
+ column.setFilterValue(date.getTime());
1654
+ }
1655
+ },
1656
+ [column, multiple]
1657
+ );
1658
+ const onReset = React12__namespace.useCallback(
1659
+ (event) => {
1660
+ event.stopPropagation();
1661
+ column.setFilterValue(void 0);
1662
+ },
1663
+ [column]
1664
+ );
1665
+ const hasValue = React12__namespace.useMemo(() => {
1666
+ if (multiple) {
1667
+ if (!getIsDateRange(selectedDates)) return false;
1668
+ return selectedDates.from || selectedDates.to;
1669
+ }
1670
+ if (!Array.isArray(selectedDates)) return false;
1671
+ return selectedDates.length > 0;
1672
+ }, [multiple, selectedDates]);
1673
+ const formatDateRange = React12__namespace.useCallback((range) => {
1674
+ if (!range.from && !range.to) return "";
1675
+ if (range.from && range.to) {
1676
+ return `${formatDate2(range.from)} - ${formatDate2(range.to)}`;
1677
+ }
1678
+ return formatDate2(range.from ?? range.to);
1679
+ }, []);
1680
+ const label = React12__namespace.useMemo(() => {
1681
+ if (multiple) {
1682
+ if (!getIsDateRange(selectedDates)) return null;
1683
+ const hasSelectedDates = selectedDates.from || selectedDates.to;
1684
+ const dateText2 = hasSelectedDates ? formatDateRange(selectedDates) : "Select date range";
1685
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
1686
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
1687
+ hasSelectedDates && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1688
+ /* @__PURE__ */ jsxRuntime.jsx(
1689
+ chunkLQCVRWVF_js.Separator,
1690
+ {
1691
+ orientation: "vertical",
1692
+ className: "mx-0.5 data-[orientation=vertical]:h-4"
1693
+ }
1694
+ ),
1695
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: dateText2 })
1696
+ ] })
1697
+ ] });
1698
+ }
1699
+ if (getIsDateRange(selectedDates)) return null;
1700
+ const hasSelectedDate = selectedDates.length > 0;
1701
+ const dateText = hasSelectedDate ? formatDate2(selectedDates[0]) : "Select date";
1702
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-2", children: [
1703
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
1704
+ hasSelectedDate && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1705
+ /* @__PURE__ */ jsxRuntime.jsx(
1706
+ chunkLQCVRWVF_js.Separator,
1707
+ {
1708
+ orientation: "vertical",
1709
+ className: "mx-0.5 data-[orientation=vertical]:h-4"
1710
+ }
1711
+ ),
1712
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: dateText })
1713
+ ] })
1714
+ ] });
1715
+ }, [selectedDates, multiple, formatDateRange, title]);
1716
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkQRS7DJGS_js.Popover, { children: [
1717
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(chunk6TGV2DNP_js.Button, { variant: "outline", className: "border-dashed font-normal", children: [
1718
+ hasValue ? /* @__PURE__ */ jsxRuntime.jsx(
1719
+ "div",
1720
+ {
1721
+ role: "button",
1722
+ "aria-label": `Clear ${title} filter`,
1723
+ tabIndex: 0,
1724
+ onClick: onReset,
1725
+ className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1726
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, {})
1727
+ }
1728
+ ) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CalendarIcon, {}),
1729
+ label
1730
+ ] }) }),
1731
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverContent, { className: "w-auto p-0", align: "start", children: multiple ? /* @__PURE__ */ jsxRuntime.jsx(
1732
+ chunkC3OADNSG_js.Calendar,
1733
+ {
1734
+ autoFocus: true,
1735
+ captionLayout: "dropdown",
1736
+ mode: "range",
1737
+ selected: getIsDateRange(selectedDates) ? selectedDates : { from: void 0, to: void 0 },
1738
+ onSelect
1739
+ }
1740
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1741
+ chunkC3OADNSG_js.Calendar,
1742
+ {
1743
+ captionLayout: "dropdown",
1744
+ mode: "single",
1745
+ selected: !getIsDateRange(selectedDates) ? selectedDates[0] : void 0,
1746
+ onSelect
1747
+ }
1748
+ ) })
1749
+ ] });
1750
+ }
1751
+ function DataTableFacetedFilter({
1752
+ column,
1753
+ title,
1754
+ options,
1755
+ multiple
1756
+ }) {
1757
+ const [open, setOpen] = React12__namespace.useState(false);
1758
+ const columnFilterValue = column?.getFilterValue();
1759
+ const selectedValues = new Set(
1760
+ Array.isArray(columnFilterValue) ? columnFilterValue : []
1761
+ );
1762
+ const onItemSelect = React12__namespace.useCallback(
1763
+ (option, isSelected) => {
1764
+ if (!column) return;
1765
+ if (multiple) {
1766
+ const newSelectedValues = new Set(selectedValues);
1767
+ if (isSelected) {
1768
+ newSelectedValues.delete(option.value);
1769
+ } else {
1770
+ newSelectedValues.add(option.value);
1771
+ }
1772
+ const filterValues = Array.from(newSelectedValues);
1773
+ column.setFilterValue(filterValues.length ? filterValues : void 0);
1774
+ } else {
1775
+ column.setFilterValue(isSelected ? void 0 : [option.value]);
1776
+ setOpen(false);
1777
+ }
1778
+ },
1779
+ [column, multiple, selectedValues]
1780
+ );
1781
+ const onReset = React12__namespace.useCallback(
1782
+ (event) => {
1783
+ event?.stopPropagation();
1784
+ column?.setFilterValue(void 0);
1785
+ },
1786
+ [column]
1787
+ );
1788
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkQRS7DJGS_js.Popover, { open, onOpenChange: setOpen, children: [
1789
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(chunk6TGV2DNP_js.Button, { variant: "outline", className: "border-dashed font-normal", children: [
1790
+ selectedValues?.size > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1791
+ "div",
1792
+ {
1793
+ role: "button",
1794
+ "aria-label": `Clear ${title} filter`,
1795
+ tabIndex: 0,
1796
+ className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
1797
+ onClick: onReset,
1798
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, {})
1799
+ }
1800
+ ) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusCircle, {}),
1801
+ title,
1802
+ selectedValues?.size > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1803
+ /* @__PURE__ */ jsxRuntime.jsx(
1804
+ chunkLQCVRWVF_js.Separator,
1805
+ {
1806
+ orientation: "vertical",
1807
+ className: "mx-0.5 data-[orientation=vertical]:h-4"
1808
+ }
1809
+ ),
1810
+ /* @__PURE__ */ jsxRuntime.jsx(
1811
+ chunkIJFPPLQW_js.Badge,
1812
+ {
1813
+ variant: "secondary",
1814
+ className: "rounded-sm px-1 font-normal lg:hidden",
1815
+ children: selectedValues.size
1816
+ }
1817
+ ),
1818
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden items-center gap-1 lg:flex", children: selectedValues.size > 2 ? /* @__PURE__ */ jsxRuntime.jsxs(
1819
+ chunkIJFPPLQW_js.Badge,
1820
+ {
1821
+ variant: "secondary",
1822
+ className: "rounded-sm px-1 font-normal",
1823
+ children: [
1824
+ selectedValues.size,
1825
+ " selected"
1826
+ ]
1827
+ }
1828
+ ) : options.filter((option) => selectedValues.has(option.value)).map((option) => /* @__PURE__ */ jsxRuntime.jsx(
1829
+ chunkIJFPPLQW_js.Badge,
1830
+ {
1831
+ variant: "secondary",
1832
+ className: "rounded-sm px-1 font-normal",
1833
+ children: option.label
1834
+ },
1835
+ option.value
1836
+ )) })
1837
+ ] })
1838
+ ] }) }),
1839
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverContent, { className: "w-50 p-0", align: "start", children: /* @__PURE__ */ jsxRuntime.jsxs(chunkC3OADNSG_js.Command, { children: [
1840
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandInput, { placeholder: title }),
1841
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkC3OADNSG_js.CommandList, { className: "max-h-full", children: [
1842
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandEmpty, { children: "No results found." }),
1843
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandGroup, { className: "max-h-[300px] scroll-py-1 overflow-y-auto overflow-x-hidden", children: options.map((option) => {
1844
+ const isSelected = selectedValues.has(option.value);
1845
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1846
+ chunkC3OADNSG_js.CommandItem,
1847
+ {
1848
+ className: "[&>svg:last-child]:hidden",
1849
+ onSelect: () => onItemSelect(option, isSelected),
1850
+ children: [
1851
+ /* @__PURE__ */ jsxRuntime.jsx(
1852
+ "div",
1853
+ {
1854
+ className: chunkADIDI7AJ_js.cn(
1855
+ "flex size-4 items-center justify-center rounded-sm border border-primary",
1856
+ isSelected ? "bg-primary text-primary-foreground" : "opacity-50 [&_svg]:invisible"
1857
+ ),
1858
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {})
1859
+ }
1860
+ ),
1861
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx(option.icon, {}),
1862
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: option.label }),
1863
+ option.count && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto font-mono text-xs", children: option.count })
1864
+ ]
1865
+ },
1866
+ option.value
1867
+ );
1868
+ }) }),
1869
+ selectedValues.size > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1870
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandSeparator, {}),
1871
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(
1872
+ chunkC3OADNSG_js.CommandItem,
1873
+ {
1874
+ onSelect: () => onReset(),
1875
+ className: "justify-center text-center",
1876
+ children: "Clear filters"
1877
+ }
1878
+ ) })
1879
+ ] })
1880
+ ] })
1881
+ ] }) })
1882
+ ] });
1883
+ }
1884
+ function DataTableSkeleton({
1885
+ columnCount,
1886
+ rowCount = 10,
1887
+ filterCount = 0,
1888
+ cellWidths = ["auto"],
1889
+ withViewOptions = true,
1890
+ withPagination = true,
1891
+ shrinkZero = false,
1892
+ className,
1893
+ ...props
1894
+ }) {
1895
+ const cozyCellWidths = Array.from(
1896
+ { length: columnCount },
1897
+ (_, index) => cellWidths[index % cellWidths.length] ?? "auto"
1898
+ );
1899
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1900
+ "div",
1901
+ {
1902
+ className: chunkADIDI7AJ_js.cn("flex w-full flex-col gap-2.5 overflow-auto", className),
1903
+ ...props,
1904
+ children: [
1905
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between gap-2 overflow-auto p-1", children: [
1906
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-center gap-2", children: filterCount > 0 ? Array.from({ length: filterCount }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-7 w-18 border-dashed" }, i)) : null }),
1907
+ withViewOptions ? /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "ml-auto hidden h-7 w-18 lg:flex" }) : null
1908
+ ] }),
1909
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsxs(chunkLABHD4PU_js.Table, { children: [
1910
+ /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableHeader, { children: Array.from({ length: 1 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableRow, { className: "hover:bg-transparent", children: Array.from({ length: columnCount }).map((_2, j) => /* @__PURE__ */ jsxRuntime.jsx(
1911
+ chunkLABHD4PU_js.TableHead,
1912
+ {
1913
+ style: {
1914
+ width: cozyCellWidths[j],
1915
+ minWidth: shrinkZero ? cozyCellWidths[j] : "auto"
1916
+ },
1917
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-6 w-full" })
1918
+ },
1919
+ j
1920
+ )) }, i)) }),
1921
+ /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableBody, { children: Array.from({ length: rowCount }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(chunkLABHD4PU_js.TableRow, { className: "hover:bg-transparent", children: Array.from({ length: columnCount }).map((_2, j) => /* @__PURE__ */ jsxRuntime.jsx(
1922
+ chunkLABHD4PU_js.TableCell,
1923
+ {
1924
+ style: {
1925
+ width: cozyCellWidths[j],
1926
+ minWidth: shrinkZero ? cozyCellWidths[j] : "auto"
1927
+ },
1928
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-6 w-full" })
1929
+ },
1930
+ j
1931
+ )) }, i)) })
1932
+ ] }) }),
1933
+ withPagination ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center justify-between gap-4 overflow-auto p-1 sm:gap-8", children: [
1934
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-7 w-40 shrink-0" }),
1935
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 sm:gap-6 lg:gap-8", children: [
1936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1937
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-7 w-24" }),
1938
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-7 w-18" })
1939
+ ] }),
1940
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center font-medium text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "h-7 w-20" }) }),
1941
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1942
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "hidden size-7 lg:block" }),
1943
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "size-7" }),
1944
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "size-7" }),
1945
+ /* @__PURE__ */ jsxRuntime.jsx(chunkULDE7QSN_js.Skeleton, { className: "hidden size-7 lg:block" })
1946
+ ] })
1947
+ ] })
1948
+ ] }) : null
1949
+ ]
1950
+ }
1951
+ );
1952
+ }
1953
+ function Slider({
1954
+ className,
1955
+ defaultValue,
1956
+ value,
1957
+ min = 0,
1958
+ max = 100,
1959
+ ...props
1960
+ }) {
1961
+ const _values = React12__namespace.useMemo(
1962
+ () => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [min, max],
1963
+ [value, defaultValue, min, max]
1964
+ );
1965
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1966
+ SliderPrimitive__namespace.Root,
1967
+ {
1968
+ "data-slot": "slider",
1969
+ defaultValue,
1970
+ value,
1971
+ min,
1972
+ max,
1973
+ className: chunkADIDI7AJ_js.cn(
1974
+ "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
1975
+ className
1976
+ ),
1977
+ ...props,
1978
+ children: [
1979
+ /* @__PURE__ */ jsxRuntime.jsx(
1980
+ SliderPrimitive__namespace.Track,
1981
+ {
1982
+ "data-slot": "slider-track",
1983
+ className: chunkADIDI7AJ_js.cn(
1984
+ "relative grow overflow-hidden rounded-full bg-muted data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
1985
+ ),
1986
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1987
+ SliderPrimitive__namespace.Range,
1988
+ {
1989
+ "data-slot": "slider-range",
1990
+ className: chunkADIDI7AJ_js.cn(
1991
+ "absolute bg-primary data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
1992
+ )
1993
+ }
1994
+ )
1995
+ }
1996
+ ),
1997
+ Array.from({ length: _values.length }, (_, index) => /* @__PURE__ */ jsxRuntime.jsx(
1998
+ SliderPrimitive__namespace.Thumb,
1999
+ {
2000
+ "data-slot": "slider-thumb",
2001
+ className: "block size-4 shrink-0 rounded-full border border-primary bg-white shadow-sm ring-ring/50 transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
2002
+ },
2003
+ index
2004
+ ))
2005
+ ]
2006
+ }
2007
+ );
2008
+ }
2009
+ function getIsValidRange(value) {
2010
+ return Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && typeof value[1] === "number";
2011
+ }
2012
+ function parseValuesAsNumbers(value) {
2013
+ if (Array.isArray(value) && value.length === 2 && value.every(
2014
+ (v) => (typeof v === "string" || typeof v === "number") && !Number.isNaN(v)
2015
+ )) {
2016
+ return [Number(value[0]), Number(value[1])];
2017
+ }
2018
+ return void 0;
2019
+ }
2020
+ function DataTableSliderFilter({
2021
+ column,
2022
+ title
2023
+ }) {
2024
+ const id = React12__namespace.useId();
2025
+ const columnFilterValue = parseValuesAsNumbers(column.getFilterValue());
2026
+ const defaultRange = column.columnDef.meta?.range;
2027
+ const unit = column.columnDef.meta?.unit;
2028
+ const { min, max, step } = React12__namespace.useMemo(() => {
2029
+ let minValue = 0;
2030
+ let maxValue = 100;
2031
+ if (defaultRange && getIsValidRange(defaultRange)) {
2032
+ [minValue, maxValue] = defaultRange;
2033
+ } else {
2034
+ const values = column.getFacetedMinMaxValues();
2035
+ if (values && Array.isArray(values) && values.length === 2) {
2036
+ const [facetMinValue, facetMaxValue] = values;
2037
+ if (typeof facetMinValue === "number" && typeof facetMaxValue === "number") {
2038
+ minValue = facetMinValue;
2039
+ maxValue = facetMaxValue;
2040
+ }
2041
+ }
2042
+ }
2043
+ const rangeSize = maxValue - minValue;
2044
+ const step2 = rangeSize <= 20 ? 1 : rangeSize <= 100 ? Math.ceil(rangeSize / 20) : Math.ceil(rangeSize / 50);
2045
+ return { min: minValue, max: maxValue, step: step2 };
2046
+ }, [column, defaultRange]);
2047
+ const range = React12__namespace.useMemo(() => {
2048
+ return columnFilterValue ?? [min, max];
2049
+ }, [columnFilterValue, min, max]);
2050
+ const formatValue = React12__namespace.useCallback((value) => {
2051
+ return value.toLocaleString(void 0, { maximumFractionDigits: 0 });
2052
+ }, []);
2053
+ const onFromInputChange = React12__namespace.useCallback(
2054
+ (event) => {
2055
+ const numValue = Number(event.target.value);
2056
+ if (!Number.isNaN(numValue) && numValue >= min && numValue <= range[1]) {
2057
+ column.setFilterValue([numValue, range[1]]);
2058
+ }
2059
+ },
2060
+ [column, min, range]
2061
+ );
2062
+ const onToInputChange = React12__namespace.useCallback(
2063
+ (event) => {
2064
+ const numValue = Number(event.target.value);
2065
+ if (!Number.isNaN(numValue) && numValue <= max && numValue >= range[0]) {
2066
+ column.setFilterValue([range[0], numValue]);
2067
+ }
2068
+ },
2069
+ [column, max, range]
2070
+ );
2071
+ const onSliderValueChange = React12__namespace.useCallback(
2072
+ (value) => {
2073
+ if (Array.isArray(value) && value.length === 2) {
2074
+ column.setFilterValue(value);
2075
+ }
2076
+ },
2077
+ [column]
2078
+ );
2079
+ const onReset = React12__namespace.useCallback(
2080
+ (event) => {
2081
+ if (event.target instanceof HTMLDivElement) {
2082
+ event.stopPropagation();
2083
+ }
2084
+ column.setFilterValue(void 0);
2085
+ },
2086
+ [column]
2087
+ );
2088
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkQRS7DJGS_js.Popover, { children: [
2089
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(chunk6TGV2DNP_js.Button, { variant: "outline", className: "border-dashed font-normal", children: [
2090
+ columnFilterValue ? /* @__PURE__ */ jsxRuntime.jsx(
2091
+ "div",
2092
+ {
2093
+ role: "button",
2094
+ "aria-label": `Clear ${title} filter`,
2095
+ tabIndex: 0,
2096
+ className: "rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
2097
+ onClick: onReset,
2098
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, {})
2099
+ }
2100
+ ) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusCircle, {}),
2101
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: title }),
2102
+ columnFilterValue ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2103
+ /* @__PURE__ */ jsxRuntime.jsx(
2104
+ chunkLQCVRWVF_js.Separator,
2105
+ {
2106
+ orientation: "vertical",
2107
+ className: "mx-0.5 data-[orientation=vertical]:h-4"
2108
+ }
2109
+ ),
2110
+ formatValue(columnFilterValue[0]),
2111
+ " -",
2112
+ " ",
2113
+ formatValue(columnFilterValue[1]),
2114
+ unit ? ` ${unit}` : ""
2115
+ ] }) : null
2116
+ ] }) }),
2117
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkQRS7DJGS_js.PopoverContent, { align: "start", className: "flex w-auto flex-col gap-4", children: [
2118
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
2119
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", children: title }),
2120
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
2121
+ /* @__PURE__ */ jsxRuntime.jsx(chunk33JR5SYE_js.Label, { htmlFor: `${id}-from`, className: "sr-only", children: "From" }),
2122
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2123
+ /* @__PURE__ */ jsxRuntime.jsx(
2124
+ chunkDQWHYBV2_js.Input,
2125
+ {
2126
+ id: `${id}-from`,
2127
+ type: "number",
2128
+ "aria-valuemin": min,
2129
+ "aria-valuemax": max,
2130
+ inputMode: "numeric",
2131
+ pattern: "[0-9]*",
2132
+ placeholder: min.toString(),
2133
+ min,
2134
+ max,
2135
+ value: range[0]?.toString(),
2136
+ onChange: onFromInputChange,
2137
+ className: chunkADIDI7AJ_js.cn("h-8 w-24", unit && "pr-8")
2138
+ }
2139
+ ),
2140
+ unit && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-0 right-0 bottom-0 flex items-center rounded-r-md bg-accent px-2 text-muted-foreground text-sm", children: unit })
2141
+ ] }),
2142
+ /* @__PURE__ */ jsxRuntime.jsx(chunk33JR5SYE_js.Label, { htmlFor: `${id}-to`, className: "sr-only", children: "to" }),
2143
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2144
+ /* @__PURE__ */ jsxRuntime.jsx(
2145
+ chunkDQWHYBV2_js.Input,
2146
+ {
2147
+ id: `${id}-to`,
2148
+ type: "number",
2149
+ "aria-valuemin": min,
2150
+ "aria-valuemax": max,
2151
+ inputMode: "numeric",
2152
+ pattern: "[0-9]*",
2153
+ placeholder: max.toString(),
2154
+ min,
2155
+ max,
2156
+ value: range[1]?.toString(),
2157
+ onChange: onToInputChange,
2158
+ className: chunkADIDI7AJ_js.cn("h-8 w-24", unit && "pr-8")
2159
+ }
2160
+ ),
2161
+ unit && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-0 right-0 bottom-0 flex items-center rounded-r-md bg-accent px-2 text-muted-foreground text-sm", children: unit })
2162
+ ] })
2163
+ ] }),
2164
+ /* @__PURE__ */ jsxRuntime.jsxs(chunk33JR5SYE_js.Label, { htmlFor: `${id}-slider`, className: "sr-only", children: [
2165
+ title,
2166
+ " slider"
2167
+ ] }),
2168
+ /* @__PURE__ */ jsxRuntime.jsx(
2169
+ Slider,
2170
+ {
2171
+ id: `${id}-slider`,
2172
+ min,
2173
+ max,
2174
+ step,
2175
+ value: range,
2176
+ onValueChange: onSliderValueChange
2177
+ }
2178
+ )
2179
+ ] }),
2180
+ /* @__PURE__ */ jsxRuntime.jsx(
2181
+ chunk6TGV2DNP_js.Button,
2182
+ {
2183
+ "aria-label": `Clear ${title} filter`,
2184
+ variant: "outline",
2185
+ onClick: onReset,
2186
+ children: "Clear"
2187
+ }
2188
+ )
2189
+ ] })
2190
+ ] });
2191
+ }
2192
+ function DataTableViewOptions({
2193
+ table,
2194
+ disabled,
2195
+ className,
2196
+ ...props
2197
+ }) {
2198
+ const columns = React12__namespace.useMemo(
2199
+ () => table.getAllColumns().filter(
2200
+ (column) => typeof column.accessorFn !== "undefined" && column.getCanHide()
2201
+ ),
2202
+ [table]
2203
+ );
2204
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkQRS7DJGS_js.Popover, { children: [
2205
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
2206
+ chunk6TGV2DNP_js.Button,
2207
+ {
2208
+ "aria-label": "Toggle columns",
2209
+ role: "combobox",
2210
+ variant: "outline",
2211
+ className: "ml-auto hidden h-8 font-normal lg:flex",
2212
+ disabled,
2213
+ children: [
2214
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings2, { className: "text-muted-foreground" }),
2215
+ "View"
2216
+ ]
2217
+ }
2218
+ ) }),
2219
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQRS7DJGS_js.PopoverContent, { className: chunkADIDI7AJ_js.cn("w-44 p-0", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(chunkC3OADNSG_js.Command, { children: [
2220
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandInput, { placeholder: "Search columns..." }),
2221
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkC3OADNSG_js.CommandList, { children: [
2222
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandEmpty, { children: "No columns found." }),
2223
+ /* @__PURE__ */ jsxRuntime.jsx(chunkC3OADNSG_js.CommandGroup, { children: columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
2224
+ chunkC3OADNSG_js.CommandItem,
2225
+ {
2226
+ "data-checked": column.getIsVisible(),
2227
+ onSelect: () => column.toggleVisibility(!column.getIsVisible()),
2228
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: column.columnDef.meta?.label ?? column.id })
2229
+ },
2230
+ column.id
2231
+ )) })
2232
+ ] })
2233
+ ] }) })
2234
+ ] });
2235
+ }
2236
+ function DataTableToolbar({
2237
+ table,
2238
+ children,
2239
+ className,
2240
+ ...props
2241
+ }) {
2242
+ const isFiltered = table.getState().columnFilters.length > 0;
2243
+ const columns = React12__namespace.useMemo(
2244
+ () => table.getAllColumns().filter((column) => column.getCanFilter()),
2245
+ [table]
2246
+ );
2247
+ const onReset = React12__namespace.useCallback(() => {
2248
+ table.resetColumnFilters();
2249
+ }, [table]);
2250
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2251
+ "div",
2252
+ {
2253
+ role: "toolbar",
2254
+ "aria-orientation": "horizontal",
2255
+ className: chunkADIDI7AJ_js.cn(
2256
+ "flex w-full items-start justify-between gap-2 p-1",
2257
+ className
2258
+ ),
2259
+ ...props,
2260
+ children: [
2261
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-wrap items-center gap-2", children: [
2262
+ columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(DataTableToolbarFilter, { column }, column.id)),
2263
+ isFiltered && /* @__PURE__ */ jsxRuntime.jsxs(
2264
+ chunk6TGV2DNP_js.Button,
2265
+ {
2266
+ "aria-label": "Reset filters",
2267
+ variant: "outline",
2268
+ className: "border-dashed",
2269
+ onClick: onReset,
2270
+ children: [
2271
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}),
2272
+ "Reset"
2273
+ ]
2274
+ }
2275
+ )
2276
+ ] }),
2277
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2278
+ children,
2279
+ /* @__PURE__ */ jsxRuntime.jsx(DataTableViewOptions, { table, align: "end" })
2280
+ ] })
2281
+ ]
2282
+ }
2283
+ );
2284
+ }
2285
+ function DataTableToolbarFilter({
2286
+ column
2287
+ }) {
2288
+ {
2289
+ const columnMeta = column.columnDef.meta;
2290
+ const onFilterRender = React12__namespace.useCallback(() => {
2291
+ if (!columnMeta?.variant) return null;
2292
+ switch (columnMeta.variant) {
2293
+ case "text":
2294
+ return /* @__PURE__ */ jsxRuntime.jsx(
2295
+ chunkDQWHYBV2_js.Input,
2296
+ {
2297
+ placeholder: columnMeta.placeholder ?? columnMeta.label,
2298
+ value: column.getFilterValue() ?? "",
2299
+ onChange: (event) => column.setFilterValue(event.target.value),
2300
+ className: "h-8 w-40 lg:w-56"
2301
+ }
2302
+ );
2303
+ case "number":
2304
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
2305
+ /* @__PURE__ */ jsxRuntime.jsx(
2306
+ chunkDQWHYBV2_js.Input,
2307
+ {
2308
+ type: "number",
2309
+ inputMode: "numeric",
2310
+ placeholder: columnMeta.placeholder ?? columnMeta.label,
2311
+ value: column.getFilterValue() ?? "",
2312
+ onChange: (event) => column.setFilterValue(event.target.value),
2313
+ className: chunkADIDI7AJ_js.cn("h-8 w-[120px]", columnMeta.unit && "pr-8")
2314
+ }
2315
+ ),
2316
+ columnMeta.unit && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-0 right-0 bottom-0 flex items-center rounded-r-md bg-accent px-2 text-muted-foreground text-sm", children: columnMeta.unit })
2317
+ ] });
2318
+ case "range":
2319
+ return /* @__PURE__ */ jsxRuntime.jsx(
2320
+ DataTableSliderFilter,
2321
+ {
2322
+ column,
2323
+ title: columnMeta.label ?? column.id
2324
+ }
2325
+ );
2326
+ case "date":
2327
+ case "dateRange":
2328
+ return /* @__PURE__ */ jsxRuntime.jsx(
2329
+ DataTableDateFilter,
2330
+ {
2331
+ column,
2332
+ title: columnMeta.label ?? column.id,
2333
+ multiple: columnMeta.variant === "dateRange"
2334
+ }
2335
+ );
2336
+ case "select":
2337
+ case "multiSelect":
2338
+ return /* @__PURE__ */ jsxRuntime.jsx(
2339
+ DataTableFacetedFilter,
2340
+ {
2341
+ column,
2342
+ title: columnMeta.label ?? column.id,
2343
+ options: columnMeta.options ?? [],
2344
+ multiple: columnMeta.variant === "multiSelect"
2345
+ }
2346
+ );
2347
+ default:
2348
+ return null;
2349
+ }
2350
+ }, [column, columnMeta]);
2351
+ return onFilterRender();
2352
+ }
2353
+ }
2354
+ var sortingItemSchema = zod.z.object({
2355
+ id: zod.z.string(),
2356
+ desc: zod.z.boolean()
2357
+ });
2358
+ var getSortingStateParser = (columnIds) => {
2359
+ const validKeys = columnIds ? columnIds instanceof Set ? columnIds : new Set(columnIds) : null;
2360
+ return server.createParser({
2361
+ parse: (value) => {
2362
+ try {
2363
+ const parsed = JSON.parse(value);
2364
+ const result = zod.z.array(sortingItemSchema).safeParse(parsed);
2365
+ if (!result.success) return null;
2366
+ if (validKeys && result.data.some((item) => !validKeys.has(item.id))) {
2367
+ return null;
2368
+ }
2369
+ return result.data;
2370
+ } catch {
2371
+ return null;
2372
+ }
2373
+ },
2374
+ serialize: (value) => JSON.stringify(value),
2375
+ eq: (a, b) => a.length === b.length && a.every(
2376
+ (item, index) => item.id === b[index]?.id && item.desc === b[index]?.desc
2377
+ )
2378
+ });
2379
+ };
2380
+ var filterItemSchema = zod.z.object({
2381
+ id: zod.z.string(),
2382
+ value: zod.z.union([zod.z.string(), zod.z.array(zod.z.string())]),
2383
+ variant: zod.z.enum(dataTableConfig.filterVariants),
2384
+ operator: zod.z.enum(dataTableConfig.operators),
2385
+ filterId: zod.z.string()
2386
+ });
2387
+ var getFiltersStateParser = (columnIds) => {
2388
+ const validKeys = columnIds ? columnIds instanceof Set ? columnIds : new Set(columnIds) : null;
2389
+ return server.createParser({
2390
+ parse: (value) => {
2391
+ try {
2392
+ const parsed = JSON.parse(value);
2393
+ const result = zod.z.array(filterItemSchema).safeParse(parsed);
2394
+ if (!result.success) return null;
2395
+ if (validKeys && result.data.some((item) => !validKeys.has(item.id))) {
2396
+ return null;
2397
+ }
2398
+ return result.data;
2399
+ } catch {
2400
+ return null;
2401
+ }
2402
+ },
2403
+ serialize: (value) => JSON.stringify(value),
2404
+ eq: (a, b) => a.length === b.length && a.every(
2405
+ (filter, index) => filter.id === b[index]?.id && filter.value === b[index]?.value && filter.variant === b[index]?.variant && filter.operator === b[index]?.operator
2406
+ )
2407
+ });
2408
+ };
2409
+ var PAGE_KEY = "page";
2410
+ var PER_PAGE_KEY = "perPage";
2411
+ var SORT_KEY = "sort";
2412
+ var FILTERS_KEY = "filters";
2413
+ var JOIN_OPERATOR_KEY = "joinOperator";
2414
+ var ARRAY_SEPARATOR = ",";
2415
+ var DEBOUNCE_MS = 300;
2416
+ var THROTTLE_MS = 50;
2417
+ function useDataTable(props) {
2418
+ const {
2419
+ columns,
2420
+ pageCount = -1,
2421
+ initialState,
2422
+ queryKeys,
2423
+ history = "replace",
2424
+ debounceMs = DEBOUNCE_MS,
2425
+ throttleMs = THROTTLE_MS,
2426
+ clearOnDefault = false,
2427
+ enableAdvancedFilter = false,
2428
+ scroll = false,
2429
+ shallow = true,
2430
+ startTransition,
2431
+ ...tableProps
2432
+ } = props;
2433
+ const pageKey = queryKeys?.page ?? PAGE_KEY;
2434
+ const perPageKey = queryKeys?.perPage ?? PER_PAGE_KEY;
2435
+ const sortKey = queryKeys?.sort ?? SORT_KEY;
2436
+ const filtersKey = queryKeys?.filters ?? FILTERS_KEY;
2437
+ const joinOperatorKey = queryKeys?.joinOperator ?? JOIN_OPERATOR_KEY;
2438
+ const queryStateOptions = React12__namespace.useMemo(
2439
+ () => ({
2440
+ history,
2441
+ scroll,
2442
+ shallow,
2443
+ throttleMs,
2444
+ debounceMs,
2445
+ clearOnDefault,
2446
+ startTransition
2447
+ }),
2448
+ [
2449
+ history,
2450
+ scroll,
2451
+ shallow,
2452
+ throttleMs,
2453
+ debounceMs,
2454
+ clearOnDefault,
2455
+ startTransition
2456
+ ]
2457
+ );
2458
+ const [rowSelection, setRowSelection] = React12__namespace.useState(
2459
+ initialState?.rowSelection ?? {}
2460
+ );
2461
+ const [columnVisibility, setColumnVisibility] = React12__namespace.useState(initialState?.columnVisibility ?? {});
2462
+ const [page, setPage] = nuqs.useQueryState(
2463
+ pageKey,
2464
+ nuqs.parseAsInteger.withOptions(queryStateOptions).withDefault(1)
2465
+ );
2466
+ const [perPage, setPerPage] = nuqs.useQueryState(
2467
+ perPageKey,
2468
+ nuqs.parseAsInteger.withOptions(queryStateOptions).withDefault(initialState?.pagination?.pageSize ?? 10)
2469
+ );
2470
+ const pagination = React12__namespace.useMemo(() => {
2471
+ return {
2472
+ pageIndex: page - 1,
2473
+ // zero-based index -> one-based index
2474
+ pageSize: perPage
2475
+ };
2476
+ }, [page, perPage]);
2477
+ const onPaginationChange = React12__namespace.useCallback(
2478
+ (updaterOrValue) => {
2479
+ if (typeof updaterOrValue === "function") {
2480
+ const newPagination = updaterOrValue(pagination);
2481
+ void setPage(newPagination.pageIndex + 1);
2482
+ void setPerPage(newPagination.pageSize);
2483
+ } else {
2484
+ void setPage(updaterOrValue.pageIndex + 1);
2485
+ void setPerPage(updaterOrValue.pageSize);
2486
+ }
2487
+ },
2488
+ [pagination, setPage, setPerPage]
2489
+ );
2490
+ const columnIds = React12__namespace.useMemo(() => {
2491
+ return new Set(
2492
+ columns.map((column) => column.id).filter(Boolean)
2493
+ );
2494
+ }, [columns]);
2495
+ const [sorting, setSorting] = nuqs.useQueryState(
2496
+ sortKey,
2497
+ getSortingStateParser(columnIds).withOptions(queryStateOptions).withDefault(initialState?.sorting ?? [])
2498
+ );
2499
+ const onSortingChange = React12__namespace.useCallback(
2500
+ (updaterOrValue) => {
2501
+ if (typeof updaterOrValue === "function") {
2502
+ const newSorting = updaterOrValue(sorting);
2503
+ setSorting(newSorting);
2504
+ } else {
2505
+ setSorting(updaterOrValue);
2506
+ }
2507
+ },
2508
+ [sorting, setSorting]
2509
+ );
2510
+ const filterableColumns = React12__namespace.useMemo(() => {
2511
+ if (enableAdvancedFilter) return [];
2512
+ return columns.filter((column) => column.enableColumnFilter);
2513
+ }, [columns, enableAdvancedFilter]);
2514
+ const filterParsers = React12__namespace.useMemo(() => {
2515
+ if (enableAdvancedFilter) return {};
2516
+ return filterableColumns.reduce((acc, column) => {
2517
+ if (column.meta?.options) {
2518
+ acc[column.id ?? ""] = nuqs.parseAsArrayOf(
2519
+ nuqs.parseAsString,
2520
+ ARRAY_SEPARATOR
2521
+ ).withOptions(queryStateOptions);
2522
+ } else {
2523
+ acc[column.id ?? ""] = nuqs.parseAsString.withOptions(queryStateOptions);
2524
+ }
2525
+ return acc;
2526
+ }, {});
2527
+ }, [filterableColumns, queryStateOptions, enableAdvancedFilter]);
2528
+ const [filterValues, setFilterValues] = nuqs.useQueryStates(filterParsers);
2529
+ const debouncedSetFilterValues = chunkULDE7QSN_js.useDebouncedCallback(
2530
+ (values) => {
2531
+ void setPage(1);
2532
+ void setFilterValues(values);
2533
+ },
2534
+ debounceMs
2535
+ );
2536
+ const initialColumnFilters = React12__namespace.useMemo(() => {
2537
+ if (enableAdvancedFilter) return [];
2538
+ return Object.entries(filterValues).reduce(
2539
+ (filters, [key, value]) => {
2540
+ if (value !== null) {
2541
+ const processedValue = Array.isArray(value) ? value : typeof value === "string" && /[^a-zA-Z0-9]/.test(value) ? value.split(/[^a-zA-Z0-9]+/).filter(Boolean) : [value];
2542
+ filters.push({
2543
+ id: key,
2544
+ value: processedValue
2545
+ });
2546
+ }
2547
+ return filters;
2548
+ },
2549
+ []
2550
+ );
2551
+ }, [filterValues, enableAdvancedFilter]);
2552
+ const [columnFilters, setColumnFilters] = React12__namespace.useState(initialColumnFilters);
2553
+ const onColumnFiltersChange = React12__namespace.useCallback(
2554
+ (updaterOrValue) => {
2555
+ if (enableAdvancedFilter) return;
2556
+ setColumnFilters((prev) => {
2557
+ const next = typeof updaterOrValue === "function" ? updaterOrValue(prev) : updaterOrValue;
2558
+ const filterUpdates = next.reduce((acc, filter) => {
2559
+ if (filterableColumns.find((column) => column.id === filter.id)) {
2560
+ acc[filter.id] = filter.value;
2561
+ }
2562
+ return acc;
2563
+ }, {});
2564
+ for (const prevFilter of prev) {
2565
+ if (!next.some((filter) => filter.id === prevFilter.id)) {
2566
+ filterUpdates[prevFilter.id] = null;
2567
+ }
2568
+ }
2569
+ debouncedSetFilterValues(filterUpdates);
2570
+ return next;
2571
+ });
2572
+ },
2573
+ [debouncedSetFilterValues, filterableColumns, enableAdvancedFilter]
2574
+ );
2575
+ const table = reactTable.useReactTable({
2576
+ ...tableProps,
2577
+ columns,
2578
+ initialState,
2579
+ pageCount,
2580
+ state: {
2581
+ pagination,
2582
+ sorting,
2583
+ columnVisibility,
2584
+ rowSelection,
2585
+ columnFilters
2586
+ },
2587
+ defaultColumn: {
2588
+ ...tableProps.defaultColumn,
2589
+ enableColumnFilter: false
2590
+ },
2591
+ enableRowSelection: true,
2592
+ onRowSelectionChange: setRowSelection,
2593
+ onPaginationChange,
2594
+ onSortingChange,
2595
+ onColumnFiltersChange,
2596
+ onColumnVisibilityChange: setColumnVisibility,
2597
+ getCoreRowModel: reactTable.getCoreRowModel(),
2598
+ getFilteredRowModel: reactTable.getFilteredRowModel(),
2599
+ getPaginationRowModel: reactTable.getPaginationRowModel(),
2600
+ getSortedRowModel: reactTable.getSortedRowModel(),
2601
+ getFacetedRowModel: reactTable.getFacetedRowModel(),
2602
+ getFacetedUniqueValues: reactTable.getFacetedUniqueValues(),
2603
+ getFacetedMinMaxValues: reactTable.getFacetedMinMaxValues(),
2604
+ manualPagination: true,
2605
+ manualSorting: true,
2606
+ manualFiltering: true,
2607
+ meta: {
2608
+ ...tableProps.meta,
2609
+ queryKeys: {
2610
+ page: pageKey,
2611
+ perPage: perPageKey,
2612
+ sort: sortKey,
2613
+ filters: filtersKey,
2614
+ joinOperator: joinOperatorKey
2615
+ }
2616
+ }
2617
+ });
2618
+ return React12__namespace.useMemo(
2619
+ () => ({ table, shallow, debounceMs, throttleMs }),
2620
+ [table, shallow, debounceMs, throttleMs]
2621
+ );
2622
+ }
2623
+
2624
+ exports.DataTable = DataTable;
2625
+ exports.DataTableAddButton = DataTableAddButton;
2626
+ exports.DataTableColumnHeader = DataTableColumnHeader;
2627
+ exports.DataTableDateFilter = DataTableDateFilter;
2628
+ exports.DataTableExportButton = DataTableExportButton;
2629
+ exports.DataTableFacetedFilter = DataTableFacetedFilter;
2630
+ exports.DataTablePagination = DataTablePagination;
2631
+ exports.DataTableRowActions = DataTableRowActions;
2632
+ exports.DataTableSearch = DataTableSearch;
2633
+ exports.DataTableSkeleton = DataTableSkeleton;
2634
+ exports.DataTableSliderFilter = DataTableSliderFilter;
2635
+ exports.DataTableSummary = DataTableSummary;
2636
+ exports.DataTableToolbar = DataTableToolbar;
2637
+ exports.DataTableTopper = DataTableTopper;
2638
+ exports.DataTableViewOptions = DataTableViewOptions;
2639
+ exports.DataTableViews = DataTableViews;
2640
+ exports.IconButton = IconButton;
2641
+ exports.Slider = Slider;
2642
+ exports.dataTableConfig = dataTableConfig;
2643
+ exports.exportToCsv = exportToCsv;
2644
+ exports.exportToExcel = exportToExcel;
2645
+ exports.getColumnPinningStyle = getColumnPinningStyle;
2646
+ exports.getDefaultFilterOperator = getDefaultFilterOperator;
2647
+ exports.getFilterOperators = getFilterOperators;
2648
+ exports.getFiltersStateParser = getFiltersStateParser;
2649
+ exports.getSortingStateParser = getSortingStateParser;
2650
+ exports.getValidFilters = getValidFilters;
2651
+ exports.iconButtonVariants = iconButtonVariants;
2652
+ exports.useDataTable = useDataTable;