luxtable 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,12 +1,15 @@
1
- // src/components/LuxTable.tsx
1
+ // src/components/lux-table/lux-table.tsx
2
+ import * as React7 from "react";
2
3
  import {
3
4
  flexRender,
4
5
  getCoreRowModel,
5
6
  useReactTable,
6
7
  getPaginationRowModel,
7
8
  getSortedRowModel,
8
- getFilteredRowModel
9
+ getFilteredRowModel,
10
+ getFacetedUniqueValues
9
11
  } from "@tanstack/react-table";
12
+ import { CheckCircle2 } from "lucide-react";
10
13
 
11
14
  // src/lib/utils.ts
12
15
  import { clsx } from "clsx";
@@ -15,73 +18,1561 @@ function cn(...inputs) {
15
18
  return twMerge(clsx(inputs));
16
19
  }
17
20
 
18
- // src/components/LuxTable.tsx
19
- import { jsx, jsxs } from "react/jsx-runtime";
21
+ // src/components/table/table.tsx
22
+ import * as React from "react";
23
+ import { jsx } from "react/jsx-runtime";
24
+ var Table = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx(
25
+ "table",
26
+ {
27
+ ref,
28
+ className: cn("w-full caption-bottom text-sm", className),
29
+ ...props
30
+ }
31
+ ) }));
32
+ Table.displayName = "Table";
33
+ var TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
34
+ "thead",
35
+ {
36
+ ref,
37
+ className: cn("[&_tr]:border-b [&_tr]:border-slate-200 dark:[&_tr]:border-slate-800", className),
38
+ ...props
39
+ }
40
+ ));
41
+ TableHeader.displayName = "TableHeader";
42
+ var TableBody = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
43
+ "tbody",
44
+ {
45
+ ref,
46
+ className: cn("[&_tr:last-child]:border-0", className),
47
+ ...props
48
+ }
49
+ ));
50
+ TableBody.displayName = "TableBody";
51
+ var TableFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
52
+ "tfoot",
53
+ {
54
+ ref,
55
+ className: cn(
56
+ "border-t border-slate-200 dark:border-slate-800 bg-slate-100/50 dark:bg-slate-800/50 font-medium [&>tr]:last:border-b-0",
57
+ className
58
+ ),
59
+ ...props
60
+ }
61
+ ));
62
+ TableFooter.displayName = "TableFooter";
63
+ var TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
64
+ "tr",
65
+ {
66
+ ref,
67
+ className: cn(
68
+ "border-b border-slate-200 dark:border-slate-800 transition-colors",
69
+ "hover:bg-slate-100/50 dark:hover:bg-slate-800/50",
70
+ "data-[state=selected]:bg-slate-100 dark:data-[state=selected]:bg-slate-800",
71
+ className
72
+ ),
73
+ ...props
74
+ }
75
+ ));
76
+ TableRow.displayName = "TableRow";
77
+ var TableHead = React.forwardRef(({ className, children, ...props }, ref) => {
78
+ return /* @__PURE__ */ jsx(
79
+ "th",
80
+ {
81
+ ref,
82
+ className: cn(
83
+ "h-10 px-4 text-left align-middle font-medium text-slate-500 dark:text-slate-400",
84
+ "[&:has([role=checkbox])]:pr-0",
85
+ "group",
86
+ // Enable group-hover for action buttons
87
+ className
88
+ ),
89
+ ...props,
90
+ children
91
+ }
92
+ );
93
+ });
94
+ TableHead.displayName = "TableHead";
95
+ var TableCell = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
96
+ "td",
97
+ {
98
+ ref,
99
+ className: cn(
100
+ "p-4 align-middle [&:has([role=checkbox])]:pr-0",
101
+ className
102
+ ),
103
+ ...props
104
+ }
105
+ ));
106
+ TableCell.displayName = "TableCell";
107
+ var TableCaption = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
108
+ "caption",
109
+ {
110
+ ref,
111
+ className: cn("mt-4 text-sm text-slate-500 dark:text-slate-400", className),
112
+ ...props
113
+ }
114
+ ));
115
+ TableCaption.displayName = "TableCaption";
116
+
117
+ // src/components/table/sort-icon.tsx
118
+ import { ChevronsUpDown, ChevronUp, ChevronDown } from "lucide-react";
119
+ import { jsx as jsx2 } from "react/jsx-runtime";
120
+ function SortIcon({ direction }) {
121
+ if (!direction) {
122
+ return /* @__PURE__ */ jsx2(ChevronsUpDown, { className: "h-4 w-4 text-slate-400 dark:text-slate-500" });
123
+ }
124
+ if (direction === "asc") {
125
+ return /* @__PURE__ */ jsx2("div", { className: "flex items-center justify-center rounded bg-blue-100 dark:bg-blue-900/50 p-0.5", children: /* @__PURE__ */ jsx2(ChevronUp, { className: "h-3.5 w-3.5 text-blue-600 dark:text-blue-400", strokeWidth: 2.5 }) });
126
+ }
127
+ return /* @__PURE__ */ jsx2("div", { className: "flex items-center justify-center rounded bg-blue-100 dark:bg-blue-900/50 p-0.5", children: /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-blue-600 dark:text-blue-400", strokeWidth: 2.5 }) });
128
+ }
129
+
130
+ // src/components/lux-table/column-filter.tsx
131
+ import * as React4 from "react";
132
+
133
+ // src/components/ui/input.tsx
134
+ import * as React2 from "react";
135
+ import { jsx as jsx3 } from "react/jsx-runtime";
136
+ var Input = React2.forwardRef(({ className, type, ...props }, ref) => {
137
+ return /* @__PURE__ */ jsx3(
138
+ "input",
139
+ {
140
+ type,
141
+ className: cn(
142
+ "flex h-9 w-full rounded-md border border-slate-200 bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-slate-950 placeholder:text-slate-500 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-700 dark:file:text-slate-50 dark:placeholder:text-slate-400 dark:focus-visible:ring-slate-300",
143
+ className
144
+ ),
145
+ ref,
146
+ ...props
147
+ }
148
+ );
149
+ });
150
+ Input.displayName = "Input";
151
+
152
+ // src/components/ui/select.tsx
153
+ import * as React3 from "react";
154
+ import * as SelectPrimitive from "@radix-ui/react-select";
155
+ import { Check, ChevronDown as ChevronDown2, ChevronUp as ChevronUp2 } from "lucide-react";
156
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
157
+ var Select = SelectPrimitive.Root;
158
+ var SelectGroup = SelectPrimitive.Group;
159
+ var SelectValue = SelectPrimitive.Value;
160
+ var SelectTrigger = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
161
+ SelectPrimitive.Trigger,
162
+ {
163
+ ref,
164
+ className: cn(
165
+ "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-slate-200 bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-white placeholder:text-slate-500 focus:outline-none focus:ring-1 focus:ring-slate-950 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 dark:border-slate-700 dark:ring-offset-slate-950 dark:placeholder:text-slate-400 dark:focus:ring-slate-300",
166
+ className
167
+ ),
168
+ ...props,
169
+ children: [
170
+ children,
171
+ /* @__PURE__ */ jsx4(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx4(ChevronDown2, { className: "h-4 w-4 opacity-50" }) })
172
+ ]
173
+ }
174
+ ));
175
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
176
+ var SelectScrollUpButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
177
+ SelectPrimitive.ScrollUpButton,
178
+ {
179
+ ref,
180
+ className: cn(
181
+ "flex cursor-default items-center justify-center py-1",
182
+ className
183
+ ),
184
+ ...props,
185
+ children: /* @__PURE__ */ jsx4(ChevronUp2, { className: "h-4 w-4" })
186
+ }
187
+ ));
188
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
189
+ var SelectScrollDownButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
190
+ SelectPrimitive.ScrollDownButton,
191
+ {
192
+ ref,
193
+ className: cn(
194
+ "flex cursor-default items-center justify-center py-1",
195
+ className
196
+ ),
197
+ ...props,
198
+ children: /* @__PURE__ */ jsx4(ChevronDown2, { className: "h-4 w-4" })
199
+ }
200
+ ));
201
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
202
+ var SelectContent = React3.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx4(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
203
+ SelectPrimitive.Content,
204
+ {
205
+ ref,
206
+ className: cn(
207
+ "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-white text-slate-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-50",
208
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
209
+ className
210
+ ),
211
+ position,
212
+ ...props,
213
+ children: [
214
+ /* @__PURE__ */ jsx4(SelectScrollUpButton, {}),
215
+ /* @__PURE__ */ jsx4(
216
+ SelectPrimitive.Viewport,
217
+ {
218
+ className: cn(
219
+ "p-1",
220
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
221
+ ),
222
+ children
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsx4(SelectScrollDownButton, {})
226
+ ]
227
+ }
228
+ ) }));
229
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
230
+ var SelectLabel = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
231
+ SelectPrimitive.Label,
232
+ {
233
+ ref,
234
+ className: cn("px-2 py-1.5 text-sm font-semibold", className),
235
+ ...props
236
+ }
237
+ ));
238
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
239
+ var SelectItem = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
240
+ SelectPrimitive.Item,
241
+ {
242
+ ref,
243
+ className: cn(
244
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-slate-100 focus:text-slate-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-800 dark:focus:text-slate-50",
245
+ className
246
+ ),
247
+ ...props,
248
+ children: [
249
+ /* @__PURE__ */ jsx4("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx4(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx4(Check, { className: "h-4 w-4" }) }) }),
250
+ /* @__PURE__ */ jsx4(SelectPrimitive.ItemText, { children })
251
+ ]
252
+ }
253
+ ));
254
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
255
+ var SelectSeparator = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
256
+ SelectPrimitive.Separator,
257
+ {
258
+ ref,
259
+ className: cn("-mx-1 my-1 h-px bg-slate-100 dark:bg-slate-800", className),
260
+ ...props
261
+ }
262
+ ));
263
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
264
+
265
+ // src/components/lux-table/column-filter.tsx
266
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
267
+ function ColumnFilter({ column }) {
268
+ const columnFilterValue = column.getFilterValue();
269
+ const filterVariant = column.columnDef.meta?.filterVariant ?? "text";
270
+ const sortedUniqueValues = React4.useMemo(() => {
271
+ if (filterVariant !== "select") return [];
272
+ const values = /* @__PURE__ */ new Set();
273
+ column.getFacetedUniqueValues().forEach((_, key) => {
274
+ if (key !== null && key !== void 0) {
275
+ values.add(String(key));
276
+ }
277
+ });
278
+ return Array.from(values).sort();
279
+ }, [column, filterVariant]);
280
+ if (filterVariant === "select") {
281
+ return /* @__PURE__ */ jsxs2(
282
+ Select,
283
+ {
284
+ value: columnFilterValue ?? "",
285
+ onValueChange: (value) => column.setFilterValue(value === "__all__" ? void 0 : value),
286
+ children: [
287
+ /* @__PURE__ */ jsx5(
288
+ SelectTrigger,
289
+ {
290
+ className: cn(
291
+ "h-8 text-xs",
292
+ "border-slate-200 dark:border-slate-700",
293
+ "bg-white dark:bg-slate-900",
294
+ "text-slate-900 dark:text-slate-100"
295
+ ),
296
+ onClick: (e) => e.stopPropagation(),
297
+ children: /* @__PURE__ */ jsx5(SelectValue, { placeholder: "All" })
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsxs2(SelectContent, { children: [
301
+ /* @__PURE__ */ jsx5(SelectItem, { value: "__all__", children: "All" }),
302
+ sortedUniqueValues.map((value) => /* @__PURE__ */ jsx5(SelectItem, { value, children: value }, value))
303
+ ] })
304
+ ]
305
+ }
306
+ );
307
+ }
308
+ return /* @__PURE__ */ jsx5(
309
+ Input,
310
+ {
311
+ type: "text",
312
+ value: columnFilterValue ?? "",
313
+ onChange: (e) => column.setFilterValue(e.target.value || void 0),
314
+ placeholder: "Filter...",
315
+ className: cn(
316
+ "h-8 text-xs",
317
+ "border-slate-200 dark:border-slate-700",
318
+ "bg-white dark:bg-slate-900",
319
+ "text-slate-900 dark:text-slate-100",
320
+ "placeholder:text-slate-400 dark:placeholder:text-slate-500"
321
+ ),
322
+ onClick: (e) => e.stopPropagation()
323
+ }
324
+ );
325
+ }
326
+
327
+ // src/components/lux-table/pagination.tsx
328
+ import {
329
+ ChevronsLeft,
330
+ ChevronLeft,
331
+ ChevronRight,
332
+ ChevronsRight
333
+ } from "lucide-react";
334
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
335
+ function PaginationButton({ onClick, disabled, title, children }) {
336
+ return /* @__PURE__ */ jsx6(
337
+ "button",
338
+ {
339
+ className: cn(
340
+ "inline-flex items-center justify-center rounded-md text-sm font-medium",
341
+ "h-9 w-9",
342
+ "border border-slate-200 dark:border-slate-800",
343
+ "bg-white dark:bg-slate-950",
344
+ "hover:bg-slate-100 dark:hover:bg-slate-800",
345
+ "disabled:pointer-events-none disabled:opacity-50",
346
+ "transition-colors"
347
+ ),
348
+ onClick,
349
+ disabled,
350
+ title,
351
+ children
352
+ }
353
+ );
354
+ }
355
+ function PageNumberButton({ pageNum, isActive, onClick }) {
356
+ return /* @__PURE__ */ jsx6(
357
+ "button",
358
+ {
359
+ onClick,
360
+ className: cn(
361
+ "inline-flex items-center justify-center rounded-md text-sm font-medium",
362
+ "h-9 w-9",
363
+ "transition-colors",
364
+ isActive ? "bg-blue-600 text-white border border-blue-600" : "border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-950 hover:bg-slate-100 dark:hover:bg-slate-800"
365
+ ),
366
+ children: pageNum + 1
367
+ }
368
+ );
369
+ }
370
+ function TablePagination({ table }) {
371
+ const currentPage = table.getState().pagination.pageIndex;
372
+ const totalPages = table.getPageCount();
373
+ const pageSize = table.getState().pagination.pageSize;
374
+ const totalRows = table.getFilteredRowModel().rows.length;
375
+ const startRow = currentPage * pageSize + 1;
376
+ const endRow = Math.min((currentPage + 1) * pageSize, totalRows);
377
+ const getPageNumbers = () => {
378
+ const pages = [];
379
+ if (totalPages <= 7) {
380
+ for (let i = 0; i < totalPages; i++) {
381
+ pages.push(i);
382
+ }
383
+ } else {
384
+ pages.push(0);
385
+ if (currentPage > 3) {
386
+ pages.push("...");
387
+ }
388
+ for (let i = Math.max(1, currentPage - 1); i <= Math.min(totalPages - 2, currentPage + 1); i++) {
389
+ pages.push(i);
390
+ }
391
+ if (currentPage < totalPages - 4) {
392
+ pages.push("...");
393
+ }
394
+ pages.push(totalPages - 1);
395
+ }
396
+ return pages;
397
+ };
398
+ return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-4 px-2 py-3", children: [
399
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-4", children: [
400
+ /* @__PURE__ */ jsxs3("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: [
401
+ /* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-700 dark:text-slate-300", children: startRow }),
402
+ "-",
403
+ /* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-700 dark:text-slate-300", children: endRow }),
404
+ " ",
405
+ "of",
406
+ " ",
407
+ /* @__PURE__ */ jsx6("span", { className: "font-medium text-slate-700 dark:text-slate-300", children: totalRows }),
408
+ " ",
409
+ "records shown"
410
+ ] }),
411
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
412
+ /* @__PURE__ */ jsx6("span", { className: "text-sm text-slate-500 dark:text-slate-400", children: "Rows per page:" }),
413
+ /* @__PURE__ */ jsx6(
414
+ "select",
415
+ {
416
+ value: pageSize,
417
+ onChange: (e) => {
418
+ table.setPageSize(Number(e.target.value));
419
+ },
420
+ className: cn(
421
+ "h-9 rounded-md border border-slate-200 dark:border-slate-800",
422
+ "bg-white dark:bg-slate-950",
423
+ "px-3 py-1 text-sm",
424
+ "focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1",
425
+ "cursor-pointer"
426
+ ),
427
+ children: [10, 20, 30, 50, 100].map((size) => /* @__PURE__ */ jsx6("option", { value: size, children: size }, size))
428
+ }
429
+ )
430
+ ] })
431
+ ] }),
432
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
433
+ /* @__PURE__ */ jsx6(
434
+ PaginationButton,
435
+ {
436
+ onClick: () => table.setPageIndex(0),
437
+ disabled: !table.getCanPreviousPage(),
438
+ title: "First page",
439
+ children: /* @__PURE__ */ jsx6(ChevronsLeft, { className: "h-4 w-4" })
440
+ }
441
+ ),
442
+ /* @__PURE__ */ jsx6(
443
+ PaginationButton,
444
+ {
445
+ onClick: () => table.previousPage(),
446
+ disabled: !table.getCanPreviousPage(),
447
+ title: "Previous page",
448
+ children: /* @__PURE__ */ jsx6(ChevronLeft, { className: "h-4 w-4" })
449
+ }
450
+ ),
451
+ /* @__PURE__ */ jsx6("div", { className: "flex items-center gap-1", children: getPageNumbers().map((page, idx) => {
452
+ if (page === "...") {
453
+ return /* @__PURE__ */ jsx6("span", { className: "px-2 text-slate-400", children: "..." }, `ellipsis-${idx}`);
454
+ }
455
+ const pageNum = page;
456
+ return /* @__PURE__ */ jsx6(
457
+ PageNumberButton,
458
+ {
459
+ pageNum,
460
+ isActive: pageNum === currentPage,
461
+ onClick: () => table.setPageIndex(pageNum)
462
+ },
463
+ pageNum
464
+ );
465
+ }) }),
466
+ /* @__PURE__ */ jsx6(
467
+ PaginationButton,
468
+ {
469
+ onClick: () => table.nextPage(),
470
+ disabled: !table.getCanNextPage(),
471
+ title: "Next page",
472
+ children: /* @__PURE__ */ jsx6(ChevronRight, { className: "h-4 w-4" })
473
+ }
474
+ ),
475
+ /* @__PURE__ */ jsx6(
476
+ PaginationButton,
477
+ {
478
+ onClick: () => table.setPageIndex(table.getPageCount() - 1),
479
+ disabled: !table.getCanNextPage(),
480
+ title: "Last page",
481
+ children: /* @__PURE__ */ jsx6(ChevronsRight, { className: "h-4 w-4" })
482
+ }
483
+ )
484
+ ] })
485
+ ] });
486
+ }
487
+
488
+ // src/components/lux-table/table-toolbar.tsx
489
+ import * as React6 from "react";
490
+ import {
491
+ Search,
492
+ Filter,
493
+ FilterX,
494
+ Columns3,
495
+ Eye,
496
+ EyeOff,
497
+ RotateCcw,
498
+ ChevronDown as ChevronDown3
499
+ } from "lucide-react";
500
+
501
+ // src/components/ui/button.tsx
502
+ import { Slot } from "@radix-ui/react-slot";
503
+ import { cva } from "class-variance-authority";
504
+ import { jsx as jsx7 } from "react/jsx-runtime";
505
+ var buttonVariants = cva(
506
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
507
+ {
508
+ variants: {
509
+ variant: {
510
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
511
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
512
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
513
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
514
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
515
+ link: "text-primary underline-offset-4 hover:underline"
516
+ },
517
+ size: {
518
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
519
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
520
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
521
+ icon: "size-9",
522
+ "icon-sm": "size-8",
523
+ "icon-lg": "size-10"
524
+ }
525
+ },
526
+ defaultVariants: {
527
+ variant: "default",
528
+ size: "default"
529
+ }
530
+ }
531
+ );
532
+ function Button({
533
+ className,
534
+ variant = "default",
535
+ size = "default",
536
+ asChild = false,
537
+ ...props
538
+ }) {
539
+ const Comp = asChild ? Slot : "button";
540
+ return /* @__PURE__ */ jsx7(
541
+ Comp,
542
+ {
543
+ "data-slot": "button",
544
+ "data-variant": variant,
545
+ "data-size": size,
546
+ className: cn(buttonVariants({ variant, size, className })),
547
+ ...props
548
+ }
549
+ );
550
+ }
551
+
552
+ // src/components/ui/dropdown-menu.tsx
553
+ import * as React5 from "react";
554
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
555
+ import { Check as Check2, ChevronRight as ChevronRight2, Circle } from "lucide-react";
556
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
557
+ var DropdownMenu = DropdownMenuPrimitive.Root;
558
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
559
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
560
+ var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
561
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
562
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
563
+ var DropdownMenuSubTrigger = React5.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs4(
564
+ DropdownMenuPrimitive.SubTrigger,
565
+ {
566
+ ref,
567
+ className: cn(
568
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-slate-100 data-[state=open]:bg-slate-100 dark:focus:bg-slate-800 dark:data-[state=open]:bg-slate-800",
569
+ inset && "pl-8",
570
+ className
571
+ ),
572
+ ...props,
573
+ children: [
574
+ children,
575
+ /* @__PURE__ */ jsx8(ChevronRight2, { className: "ml-auto h-4 w-4" })
576
+ ]
577
+ }
578
+ ));
579
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
580
+ var DropdownMenuSubContent = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
581
+ DropdownMenuPrimitive.SubContent,
582
+ {
583
+ ref,
584
+ className: cn(
585
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-white p-1 text-slate-950 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50",
586
+ className
587
+ ),
588
+ ...props
589
+ }
590
+ ));
591
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
592
+ var DropdownMenuContent = React5.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx8(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx8(
593
+ DropdownMenuPrimitive.Content,
594
+ {
595
+ ref,
596
+ sideOffset,
597
+ className: cn(
598
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-white p-1 text-slate-950 shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50",
599
+ className
600
+ ),
601
+ ...props
602
+ }
603
+ ) }));
604
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
605
+ var DropdownMenuItem = React5.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx8(
606
+ DropdownMenuPrimitive.Item,
607
+ {
608
+ ref,
609
+ className: cn(
610
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-slate-100 focus:text-slate-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-800 dark:focus:text-slate-50",
611
+ inset && "pl-8",
612
+ className
613
+ ),
614
+ ...props
615
+ }
616
+ ));
617
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
618
+ var DropdownMenuCheckboxItem = React5.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs4(
619
+ DropdownMenuPrimitive.CheckboxItem,
620
+ {
621
+ ref,
622
+ className: cn(
623
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-slate-100 focus:text-slate-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-800 dark:focus:text-slate-50",
624
+ className
625
+ ),
626
+ checked,
627
+ ...props,
628
+ children: [
629
+ /* @__PURE__ */ jsx8("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx8(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx8(Check2, { className: "h-4 w-4" }) }) }),
630
+ children
631
+ ]
632
+ }
633
+ ));
634
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
635
+ var DropdownMenuRadioItem = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs4(
636
+ DropdownMenuPrimitive.RadioItem,
637
+ {
638
+ ref,
639
+ className: cn(
640
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-slate-100 focus:text-slate-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 dark:focus:bg-slate-800 dark:focus:text-slate-50",
641
+ className
642
+ ),
643
+ ...props,
644
+ children: [
645
+ /* @__PURE__ */ jsx8("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx8(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx8(Circle, { className: "h-2 w-2 fill-current" }) }) }),
646
+ children
647
+ ]
648
+ }
649
+ ));
650
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
651
+ var DropdownMenuLabel = React5.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx8(
652
+ DropdownMenuPrimitive.Label,
653
+ {
654
+ ref,
655
+ className: cn(
656
+ "px-2 py-1.5 text-sm font-semibold",
657
+ inset && "pl-8",
658
+ className
659
+ ),
660
+ ...props
661
+ }
662
+ ));
663
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
664
+ var DropdownMenuSeparator = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
665
+ DropdownMenuPrimitive.Separator,
666
+ {
667
+ ref,
668
+ className: cn("-mx-1 my-1 h-px bg-slate-100 dark:bg-slate-800", className),
669
+ ...props
670
+ }
671
+ ));
672
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
673
+ var DropdownMenuShortcut = ({
674
+ className,
675
+ ...props
676
+ }) => {
677
+ return /* @__PURE__ */ jsx8(
678
+ "span",
679
+ {
680
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
681
+ ...props
682
+ }
683
+ );
684
+ };
685
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
686
+
687
+ // src/components/lux-table/table-toolbar.tsx
688
+ import { Fragment, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
689
+ function TableToolbar({
690
+ table,
691
+ showFiltering = true,
692
+ onFilteringToggle,
693
+ filteringEnabled = false,
694
+ showGlobalSearch = true,
695
+ showColumnVisibility = true,
696
+ className
697
+ }) {
698
+ const [globalFilter, setGlobalFilter] = React6.useState("");
699
+ const hidableColumns = table.getAllColumns().filter((column) => column.getCanHide() && column.id !== "__selection__");
700
+ const hiddenColumns = hidableColumns.filter((column) => !column.getIsVisible());
701
+ const handleGlobalSearch = React6.useCallback(
702
+ (value) => {
703
+ setGlobalFilter(value);
704
+ table.setGlobalFilter(value);
705
+ },
706
+ [table]
707
+ );
708
+ const handleResetVisibility = React6.useCallback(() => {
709
+ table.resetColumnVisibility();
710
+ }, [table]);
711
+ const handleShowAllColumns = React6.useCallback(() => {
712
+ hidableColumns.forEach((column) => {
713
+ column.toggleVisibility(true);
714
+ });
715
+ }, [hidableColumns]);
716
+ return /* @__PURE__ */ jsxs5(
717
+ "div",
718
+ {
719
+ className: cn(
720
+ "flex flex-wrap items-center gap-2 p-3 rounded-lg border border-slate-200 dark:border-slate-800 bg-slate-50/50 dark:bg-slate-900/50",
721
+ className
722
+ ),
723
+ children: [
724
+ showGlobalSearch && /* @__PURE__ */ jsxs5("div", { className: "relative flex-1 min-w-[200px] max-w-sm", children: [
725
+ /* @__PURE__ */ jsx9(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-slate-400" }),
726
+ /* @__PURE__ */ jsx9(
727
+ "input",
728
+ {
729
+ type: "text",
730
+ placeholder: "Search in all columns...",
731
+ value: globalFilter,
732
+ onChange: (e) => handleGlobalSearch(e.target.value),
733
+ className: cn(
734
+ "w-full h-9 pl-9 pr-3 rounded-md border border-slate-200 dark:border-slate-700",
735
+ "bg-white dark:bg-slate-950 text-sm text-slate-900 dark:text-slate-100",
736
+ "placeholder:text-slate-400 dark:placeholder:text-slate-500",
737
+ "focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500",
738
+ "transition-colors"
739
+ )
740
+ }
741
+ ),
742
+ globalFilter && /* @__PURE__ */ jsx9(
743
+ "button",
744
+ {
745
+ onClick: () => handleGlobalSearch(""),
746
+ className: "absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded-full hover:bg-slate-200 dark:hover:bg-slate-700 transition-colors",
747
+ children: /* @__PURE__ */ jsx9(FilterX, { className: "h-3 w-3 text-slate-400" })
748
+ }
749
+ )
750
+ ] }),
751
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 ml-auto", children: [
752
+ showFiltering && onFilteringToggle && /* @__PURE__ */ jsx9(
753
+ Button,
754
+ {
755
+ variant: filteringEnabled ? "default" : "outline",
756
+ size: "sm",
757
+ onClick: () => onFilteringToggle(!filteringEnabled),
758
+ className: "gap-2",
759
+ children: filteringEnabled ? /* @__PURE__ */ jsxs5(Fragment, { children: [
760
+ /* @__PURE__ */ jsx9(FilterX, { className: "h-4 w-4" }),
761
+ /* @__PURE__ */ jsx9("span", { className: "hidden sm:inline", children: "Hide Filters" })
762
+ ] }) : /* @__PURE__ */ jsxs5(Fragment, { children: [
763
+ /* @__PURE__ */ jsx9(Filter, { className: "h-4 w-4" }),
764
+ /* @__PURE__ */ jsx9("span", { className: "hidden sm:inline", children: "Show Filters" })
765
+ ] })
766
+ }
767
+ ),
768
+ showColumnVisibility && /* @__PURE__ */ jsxs5(DropdownMenu, { children: [
769
+ /* @__PURE__ */ jsx9(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(Button, { variant: "outline", size: "sm", className: "gap-2", children: [
770
+ /* @__PURE__ */ jsx9(Columns3, { className: "h-4 w-4" }),
771
+ /* @__PURE__ */ jsx9("span", { className: "hidden sm:inline", children: "Columns" }),
772
+ hiddenColumns.length > 0 && /* @__PURE__ */ jsx9("span", { className: "ml-1 flex h-5 w-5 items-center justify-center rounded-full bg-blue-500 text-[10px] font-medium text-white", children: hiddenColumns.length }),
773
+ /* @__PURE__ */ jsx9(ChevronDown3, { className: "h-3 w-3 opacity-50" })
774
+ ] }) }),
775
+ /* @__PURE__ */ jsxs5(DropdownMenuContent, { align: "end", className: "w-56", children: [
776
+ /* @__PURE__ */ jsxs5(DropdownMenuLabel, { className: "flex items-center gap-2", children: [
777
+ /* @__PURE__ */ jsx9(Columns3, { className: "h-4 w-4" }),
778
+ "Toggle Columns"
779
+ ] }),
780
+ /* @__PURE__ */ jsx9(DropdownMenuSeparator, {}),
781
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
782
+ /* @__PURE__ */ jsxs5(
783
+ Button,
784
+ {
785
+ variant: "ghost",
786
+ size: "sm",
787
+ onClick: handleShowAllColumns,
788
+ disabled: hiddenColumns.length === 0,
789
+ className: "h-7 flex-1 text-xs",
790
+ children: [
791
+ /* @__PURE__ */ jsx9(Eye, { className: "mr-1 h-3 w-3" }),
792
+ "Show All"
793
+ ]
794
+ }
795
+ ),
796
+ /* @__PURE__ */ jsxs5(
797
+ Button,
798
+ {
799
+ variant: "ghost",
800
+ size: "sm",
801
+ onClick: handleResetVisibility,
802
+ className: "h-7 flex-1 text-xs",
803
+ children: [
804
+ /* @__PURE__ */ jsx9(RotateCcw, { className: "mr-1 h-3 w-3" }),
805
+ "Reset"
806
+ ]
807
+ }
808
+ )
809
+ ] }),
810
+ /* @__PURE__ */ jsx9(DropdownMenuSeparator, {}),
811
+ /* @__PURE__ */ jsx9("div", { className: "max-h-[300px] overflow-y-auto", children: hidableColumns.map((column) => {
812
+ const columnDef = column.columnDef;
813
+ const headerText = typeof columnDef.header === "string" ? columnDef.header : column.id;
814
+ return /* @__PURE__ */ jsx9(
815
+ DropdownMenuCheckboxItem,
816
+ {
817
+ checked: column.getIsVisible(),
818
+ onCheckedChange: (value) => column.toggleVisibility(!!value),
819
+ className: "capitalize",
820
+ children: /* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-2", children: [
821
+ column.getIsVisible() ? /* @__PURE__ */ jsx9(Eye, { className: "h-3.5 w-3.5 text-green-500" }) : /* @__PURE__ */ jsx9(EyeOff, { className: "h-3.5 w-3.5 text-slate-400" }),
822
+ headerText
823
+ ] })
824
+ },
825
+ column.id
826
+ );
827
+ }) }),
828
+ hiddenColumns.length > 0 && /* @__PURE__ */ jsxs5(Fragment, { children: [
829
+ /* @__PURE__ */ jsx9(DropdownMenuSeparator, {}),
830
+ /* @__PURE__ */ jsxs5("div", { className: "px-2 py-1.5 text-xs text-slate-500 dark:text-slate-400", children: [
831
+ hiddenColumns.length,
832
+ " column(s) hidden"
833
+ ] })
834
+ ] })
835
+ ] })
836
+ ] })
837
+ ] })
838
+ ]
839
+ }
840
+ );
841
+ }
842
+
843
+ // src/components/ui/checkbox.tsx
844
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
845
+ import { CheckIcon } from "lucide-react";
846
+ import { jsx as jsx10 } from "react/jsx-runtime";
847
+ function Checkbox({
848
+ className,
849
+ ...props
850
+ }) {
851
+ return /* @__PURE__ */ jsx10(
852
+ CheckboxPrimitive.Root,
853
+ {
854
+ "data-slot": "checkbox",
855
+ className: cn(
856
+ "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
857
+ className
858
+ ),
859
+ ...props,
860
+ children: /* @__PURE__ */ jsx10(
861
+ CheckboxPrimitive.Indicator,
862
+ {
863
+ "data-slot": "checkbox-indicator",
864
+ className: "grid place-content-center text-current transition-none",
865
+ children: /* @__PURE__ */ jsx10(CheckIcon, { className: "size-3.5" })
866
+ }
867
+ )
868
+ }
869
+ );
870
+ }
871
+
872
+ // src/components/lux-table/lux-table.tsx
873
+ import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
874
+ function createSelectionColumn() {
875
+ return {
876
+ id: "__selection__",
877
+ header: ({ table }) => /* @__PURE__ */ jsx11(
878
+ Checkbox,
879
+ {
880
+ checked: table.getIsAllPageRowsSelected() || table.getIsSomePageRowsSelected() && "indeterminate",
881
+ onCheckedChange: (value) => table.toggleAllPageRowsSelected(!!value),
882
+ "aria-label": "Select all rows"
883
+ }
884
+ ),
885
+ cell: ({ row }) => /* @__PURE__ */ jsx11(
886
+ Checkbox,
887
+ {
888
+ checked: row.getIsSelected(),
889
+ disabled: !row.getCanSelect(),
890
+ onCheckedChange: (value) => row.toggleSelected(!!value),
891
+ "aria-label": "Select row"
892
+ }
893
+ ),
894
+ size: 40,
895
+ enableSorting: false,
896
+ enableHiding: false
897
+ };
898
+ }
20
899
  function LuxTable({
21
900
  columns,
22
901
  data,
23
902
  className,
24
- options
903
+ options,
904
+ sorting: controlledSorting,
905
+ onSortingChange,
906
+ rowSelection: controlledRowSelection,
907
+ onRowSelectionChange,
908
+ onSelectedRowsChange,
909
+ getRowId
25
910
  }) {
911
+ const [internalSorting, setInternalSorting] = React7.useState([]);
912
+ const [columnFilters, setColumnFilters] = React7.useState([]);
913
+ const [globalFilter, setGlobalFilter] = React7.useState("");
914
+ const [filteringVisible, setFilteringVisible] = React7.useState(options?.filtering ?? false);
915
+ const [internalRowSelection, setInternalRowSelection] = React7.useState({});
916
+ const isControlledSorting = controlledSorting !== void 0;
917
+ const sorting = isControlledSorting ? controlledSorting : internalSorting;
918
+ const isControlledRowSelection = controlledRowSelection !== void 0;
919
+ const rowSelection = isControlledRowSelection ? controlledRowSelection : internalRowSelection;
920
+ const selectionMode = options?.selection ?? "none";
921
+ const showCheckbox = options?.showSelectionCheckbox ?? selectionMode !== "none";
922
+ const enableRowSelection = selectionMode !== "none";
923
+ const enableMultiRowSelection = selectionMode === "multiple";
924
+ const tableColumns = React7.useMemo(() => {
925
+ if (showCheckbox && enableRowSelection) {
926
+ return [createSelectionColumn(), ...columns];
927
+ }
928
+ return columns;
929
+ }, [columns, showCheckbox, enableRowSelection]);
930
+ const handleRowSelectionChange = React7.useCallback(
931
+ (updater) => {
932
+ const newSelection = typeof updater === "function" ? updater(rowSelection) : updater;
933
+ if (isControlledRowSelection && onRowSelectionChange) {
934
+ onRowSelectionChange(newSelection);
935
+ } else {
936
+ setInternalRowSelection(newSelection);
937
+ }
938
+ },
939
+ [isControlledRowSelection, onRowSelectionChange, rowSelection]
940
+ );
26
941
  const table = useReactTable({
27
942
  data,
28
- columns,
943
+ columns: tableColumns,
944
+ state: {
945
+ sorting,
946
+ columnFilters,
947
+ rowSelection,
948
+ globalFilter
949
+ },
950
+ onGlobalFilterChange: setGlobalFilter,
951
+ onSortingChange: (updater) => {
952
+ const newSorting = typeof updater === "function" ? updater(sorting) : updater;
953
+ if (isControlledSorting && onSortingChange) {
954
+ onSortingChange(newSorting);
955
+ } else {
956
+ setInternalSorting(newSorting);
957
+ }
958
+ },
959
+ onColumnFiltersChange: setColumnFilters,
960
+ onRowSelectionChange: handleRowSelectionChange,
961
+ enableRowSelection,
962
+ enableMultiRowSelection,
963
+ getRowId: getRowId ?? ((row, index) => {
964
+ if (typeof row === "object" && row !== null && "id" in row) {
965
+ return String(row.id);
966
+ }
967
+ return String(index);
968
+ }),
29
969
  getCoreRowModel: getCoreRowModel(),
30
970
  getPaginationRowModel: options?.pagination ? getPaginationRowModel() : void 0,
31
971
  getSortedRowModel: getSortedRowModel(),
32
- getFilteredRowModel: getFilteredRowModel()
972
+ getFilteredRowModel: getFilteredRowModel(),
973
+ getFacetedUniqueValues: getFacetedUniqueValues(),
974
+ initialState: {
975
+ pagination: {
976
+ pageSize: options?.pageSize ?? 10
977
+ }
978
+ }
33
979
  });
34
- return /* @__PURE__ */ jsxs("div", { className: cn("w-full space-y-4", className), children: [
35
- /* @__PURE__ */ jsx("div", { className: "rounded-md border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-950 overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full caption-bottom text-sm text-left", children: [
36
- /* @__PURE__ */ jsx("thead", { className: "[&_tr]:border-b [&_tr]:border-slate-200 dark:[&_tr]:border-slate-800", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx("tr", { className: "border-b transition-colors hover:bg-slate-100/50 dark:hover:bg-slate-800/50 data-[state=selected]:bg-slate-100 dark:data-[state=selected]:bg-slate-800", children: headerGroup.headers.map((header) => {
37
- return /* @__PURE__ */ jsx(
38
- "th",
39
- {
40
- className: "h-10 px-4 text-left align-middle font-medium text-slate-500 [&:has([role=checkbox])]:pr-0 dark:text-slate-400",
41
- children: header.isPlaceholder ? null : flexRender(
42
- header.column.columnDef.header,
43
- header.getContext()
44
- )
45
- },
46
- header.id
47
- );
48
- }) }, headerGroup.id)) }),
49
- /* @__PURE__ */ jsx("tbody", { className: "[&_tr:last-child]:border-0", children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx(
50
- "tr",
980
+ React7.useEffect(() => {
981
+ if (onSelectedRowsChange) {
982
+ const selectedRows = table.getSelectedRowModel().rows.map((row) => row.original);
983
+ onSelectedRowsChange(selectedRows);
984
+ }
985
+ }, [rowSelection, onSelectedRowsChange, table]);
986
+ const visibleColumnCount = tableColumns.length;
987
+ const showToolbar = options?.showToolbar ?? false;
988
+ const showGlobalSearch = options?.showGlobalSearch ?? true;
989
+ const showColumnVisibility = options?.showColumnVisibility ?? true;
990
+ return /* @__PURE__ */ jsxs6("div", { className: cn("w-full space-y-4", className), children: [
991
+ showToolbar && /* @__PURE__ */ jsx11(
992
+ TableToolbar,
993
+ {
994
+ table,
995
+ showFiltering: options?.filtering !== void 0,
996
+ filteringEnabled: filteringVisible,
997
+ onFilteringToggle: setFilteringVisible,
998
+ showGlobalSearch,
999
+ showColumnVisibility
1000
+ }
1001
+ ),
1002
+ enableRowSelection && Object.keys(rowSelection).length > 0 && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 px-4 py-2 text-sm bg-blue-50 dark:bg-blue-950/50 text-blue-700 dark:text-blue-300 rounded-lg border border-blue-200 dark:border-blue-800", children: [
1003
+ /* @__PURE__ */ jsx11(CheckCircle2, { className: "w-4 h-4" }),
1004
+ /* @__PURE__ */ jsxs6("span", { children: [
1005
+ /* @__PURE__ */ jsx11("strong", { children: Object.keys(rowSelection).length }),
1006
+ " rows selected",
1007
+ table.getFilteredRowModel().rows.length > 0 && /* @__PURE__ */ jsxs6("span", { className: "text-blue-500 dark:text-blue-400", children: [
1008
+ " / ",
1009
+ table.getFilteredRowModel().rows.length,
1010
+ " total"
1011
+ ] })
1012
+ ] }),
1013
+ /* @__PURE__ */ jsx11(
1014
+ "button",
1015
+ {
1016
+ type: "button",
1017
+ onClick: () => handleRowSelectionChange({}),
1018
+ className: "ml-auto text-xs hover:text-blue-900 dark:hover:text-blue-100 underline underline-offset-2",
1019
+ children: "Clear selection"
1020
+ }
1021
+ )
1022
+ ] }),
1023
+ /* @__PURE__ */ jsx11("div", { className: "rounded-md border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-950 overflow-hidden", children: /* @__PURE__ */ jsxs6(Table, { children: [
1024
+ /* @__PURE__ */ jsxs6(TableHeader, { children: [
1025
+ table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx11(TableRow, { children: headerGroup.headers.map((header) => {
1026
+ const isSelectionColumn = header.id === "__selection__";
1027
+ return /* @__PURE__ */ jsx11(
1028
+ TableHead,
1029
+ {
1030
+ style: isSelectionColumn ? { width: 40, padding: "0 12px" } : void 0,
1031
+ children: header.isPlaceholder ? null : flexRender(
1032
+ header.column.columnDef.header,
1033
+ header.getContext()
1034
+ )
1035
+ },
1036
+ header.id
1037
+ );
1038
+ }) }, headerGroup.id)),
1039
+ filteringVisible && /* @__PURE__ */ jsx11(TableRow, { className: "bg-slate-50/50 dark:bg-slate-900/50", children: table.getHeaderGroups()[0]?.headers.map((header) => {
1040
+ const isSelectionColumn = header.id === "__selection__";
1041
+ return /* @__PURE__ */ jsx11(TableHead, { className: "py-2", children: !isSelectionColumn && header.column.getCanFilter() ? /* @__PURE__ */ jsx11(ColumnFilter, { column: header.column }) : null }, `filter-${header.id}`);
1042
+ }) })
1043
+ ] }),
1044
+ /* @__PURE__ */ jsx11(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx11(
1045
+ TableRow,
51
1046
  {
52
1047
  "data-state": row.getIsSelected() && "selected",
53
- className: "border-b border-slate-200 dark:border-slate-800 transition-colors hover:bg-slate-100/50 dark:hover:bg-slate-800/50",
54
- children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx("td", { className: "p-4 align-middle [&:has([role=checkbox])]:pr-0", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
1048
+ className: cn(
1049
+ enableRowSelection && "cursor-pointer",
1050
+ row.getIsSelected() && "bg-blue-50/50 dark:bg-blue-950/30"
1051
+ ),
1052
+ onClick: enableRowSelection && !showCheckbox ? () => {
1053
+ if (selectionMode === "single") {
1054
+ handleRowSelectionChange({ [row.id]: true });
1055
+ } else {
1056
+ row.toggleSelected();
1057
+ }
1058
+ } : void 0,
1059
+ children: row.getVisibleCells().map((cell) => {
1060
+ const isSelectionColumn = cell.column.id === "__selection__";
1061
+ return /* @__PURE__ */ jsx11(
1062
+ TableCell,
1063
+ {
1064
+ style: isSelectionColumn ? { width: 40, padding: "0 12px" } : void 0,
1065
+ onClick: isSelectionColumn ? (e) => e.stopPropagation() : void 0,
1066
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
1067
+ },
1068
+ cell.id
1069
+ );
1070
+ })
55
1071
  },
56
1072
  row.id
57
- )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "h-24 text-center", children: "No results." }) }) })
58
- ] }) }) }),
59
- options?.pagination && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end space-x-2 py-4", children: [
60
- /* @__PURE__ */ jsx(
61
- "button",
62
- {
63
- className: "px-3 py-1 border rounded text-sm disabled:opacity-50",
64
- onClick: () => table.previousPage(),
65
- disabled: !table.getCanPreviousPage(),
66
- children: "Previous"
67
- }
68
- ),
69
- /* @__PURE__ */ jsx(
70
- "button",
1073
+ )) : /* @__PURE__ */ jsx11(TableRow, { children: /* @__PURE__ */ jsx11(TableCell, { colSpan: visibleColumnCount, className: "h-24 text-center", children: "No results." }) }) })
1074
+ ] }) }),
1075
+ options?.pagination && /* @__PURE__ */ jsx11(TablePagination, { table })
1076
+ ] });
1077
+ }
1078
+
1079
+ // src/components/lux-table/column-header.tsx
1080
+ import {
1081
+ ArrowDown,
1082
+ ArrowUp,
1083
+ ChevronsUpDown as ChevronsUpDown2,
1084
+ EyeOff as EyeOff2,
1085
+ MoreVertical,
1086
+ X
1087
+ } from "lucide-react";
1088
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1089
+ function LuxDataTableColumnHeader({
1090
+ column,
1091
+ title,
1092
+ className
1093
+ }) {
1094
+ const isSorted = column.getIsSorted();
1095
+ if (!column.getCanSort()) {
1096
+ return /* @__PURE__ */ jsx12("div", { className: cn("flex items-center justify-between", className), children: /* @__PURE__ */ jsx12("span", { className: "text-sm font-medium text-muted-foreground", children: title }) });
1097
+ }
1098
+ return /* @__PURE__ */ jsxs7("div", { className: cn("flex items-center justify-between gap-1", className), children: [
1099
+ /* @__PURE__ */ jsxs7(
1100
+ Button,
1101
+ {
1102
+ variant: "ghost",
1103
+ size: "sm",
1104
+ className: "-ml-3 h-8 hover:bg-accent",
1105
+ onClick: () => column.toggleSorting(isSorted === "asc"),
1106
+ children: [
1107
+ /* @__PURE__ */ jsx12("span", { children: title }),
1108
+ isSorted === "desc" ? /* @__PURE__ */ jsx12(ArrowDown, { className: "ml-1.5 h-4 w-4 text-primary" }) : isSorted === "asc" ? /* @__PURE__ */ jsx12(ArrowUp, { className: "ml-1.5 h-4 w-4 text-primary" }) : /* @__PURE__ */ jsx12(ChevronsUpDown2, { className: "ml-1.5 h-4 w-4 text-muted-foreground/50" })
1109
+ ]
1110
+ }
1111
+ ),
1112
+ /* @__PURE__ */ jsxs7(DropdownMenu, { children: [
1113
+ /* @__PURE__ */ jsx12(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs7(
1114
+ Button,
71
1115
  {
72
- className: "px-3 py-1 border rounded text-sm disabled:opacity-50",
73
- onClick: () => table.nextPage(),
74
- disabled: !table.getCanNextPage(),
75
- children: "Next"
1116
+ variant: "ghost",
1117
+ size: "icon",
1118
+ className: "h-6 w-6 opacity-0 group-hover:opacity-100 hover:opacity-100 focus:opacity-100 data-[state=open]:opacity-100 transition-opacity",
1119
+ children: [
1120
+ /* @__PURE__ */ jsx12(MoreVertical, { className: "h-3.5 w-3.5" }),
1121
+ /* @__PURE__ */ jsx12("span", { className: "sr-only", children: "Column actions" })
1122
+ ]
76
1123
  }
77
- )
1124
+ ) }),
1125
+ /* @__PURE__ */ jsxs7(DropdownMenuContent, { align: "end", children: [
1126
+ /* @__PURE__ */ jsxs7(DropdownMenuItem, { onClick: () => column.toggleSorting(false), children: [
1127
+ /* @__PURE__ */ jsx12(ArrowUp, { className: "mr-2 h-3.5 w-3.5 text-muted-foreground/70" }),
1128
+ "Sort Ascending"
1129
+ ] }),
1130
+ /* @__PURE__ */ jsxs7(DropdownMenuItem, { onClick: () => column.toggleSorting(true), children: [
1131
+ /* @__PURE__ */ jsx12(ArrowDown, { className: "mr-2 h-3.5 w-3.5 text-muted-foreground/70" }),
1132
+ "Sort Descending"
1133
+ ] }),
1134
+ isSorted && /* @__PURE__ */ jsxs7(Fragment2, { children: [
1135
+ /* @__PURE__ */ jsx12(DropdownMenuSeparator, {}),
1136
+ /* @__PURE__ */ jsxs7(DropdownMenuItem, { onClick: () => column.clearSorting(), children: [
1137
+ /* @__PURE__ */ jsx12(X, { className: "mr-2 h-3.5 w-3.5 text-muted-foreground/70" }),
1138
+ "Clear sorting"
1139
+ ] })
1140
+ ] }),
1141
+ /* @__PURE__ */ jsx12(DropdownMenuSeparator, {}),
1142
+ /* @__PURE__ */ jsxs7(DropdownMenuItem, { onClick: () => column.toggleVisibility(false), children: [
1143
+ /* @__PURE__ */ jsx12(EyeOff2, { className: "mr-2 h-3.5 w-3.5 text-muted-foreground/70" }),
1144
+ "Hide column"
1145
+ ] })
1146
+ ] })
78
1147
  ] })
79
1148
  ] });
80
1149
  }
81
1150
 
1151
+ // src/components/cell-renderers/status-cell.tsx
1152
+ import { jsx as jsx13 } from "react/jsx-runtime";
1153
+ var defaultStatusColors = {
1154
+ Active: {
1155
+ bg: "bg-green-100",
1156
+ text: "text-green-800",
1157
+ darkBg: "dark:bg-green-900",
1158
+ darkText: "dark:text-green-300"
1159
+ },
1160
+ Inactive: {
1161
+ bg: "bg-red-100",
1162
+ text: "text-red-800",
1163
+ darkBg: "dark:bg-red-900",
1164
+ darkText: "dark:text-red-300"
1165
+ },
1166
+ Pending: {
1167
+ bg: "bg-yellow-100",
1168
+ text: "text-yellow-800",
1169
+ darkBg: "dark:bg-yellow-900",
1170
+ darkText: "dark:text-yellow-300"
1171
+ },
1172
+ Completed: {
1173
+ bg: "bg-blue-100",
1174
+ text: "text-blue-800",
1175
+ darkBg: "dark:bg-blue-900",
1176
+ darkText: "dark:text-blue-300"
1177
+ },
1178
+ Cancelled: {
1179
+ bg: "bg-gray-100",
1180
+ text: "text-gray-800",
1181
+ darkBg: "dark:bg-gray-900",
1182
+ darkText: "dark:text-gray-300"
1183
+ }
1184
+ };
1185
+ function StatusCell({ value, colors, className }) {
1186
+ const mergedColors = { ...defaultStatusColors, ...colors };
1187
+ const colorConfig = mergedColors[value];
1188
+ if (!colorConfig) {
1189
+ return /* @__PURE__ */ jsx13("span", { className: `px-2 py-1 rounded-full text-xs font-medium bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300 ${className || ""}`, children: value });
1190
+ }
1191
+ const { bg, text, darkBg, darkText } = colorConfig;
1192
+ return /* @__PURE__ */ jsx13("span", { className: `px-2 py-1 rounded-full text-xs font-medium ${bg} ${text} ${darkBg || ""} ${darkText || ""} ${className || ""}`, children: value });
1193
+ }
1194
+
1195
+ // src/components/cell-renderers/progress-cell.tsx
1196
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1197
+ function ProgressCell({
1198
+ value,
1199
+ barColor = "bg-blue-600",
1200
+ bgColor = "bg-gray-200 dark:bg-gray-700",
1201
+ showLabel = false,
1202
+ className
1203
+ }) {
1204
+ const clampedValue = Math.min(100, Math.max(0, value));
1205
+ return /* @__PURE__ */ jsxs8("div", { className: `flex items-center gap-2 ${className || ""}`, children: [
1206
+ /* @__PURE__ */ jsx14("div", { className: `w-full rounded-full h-2.5 ${bgColor}`, children: /* @__PURE__ */ jsx14(
1207
+ "div",
1208
+ {
1209
+ className: `${barColor} h-2.5 rounded-full transition-all`,
1210
+ style: { width: `${clampedValue}%` }
1211
+ }
1212
+ ) }),
1213
+ showLabel && /* @__PURE__ */ jsxs8("span", { className: "text-xs text-gray-500 dark:text-gray-400 w-8", children: [
1214
+ value,
1215
+ "%"
1216
+ ] })
1217
+ ] });
1218
+ }
1219
+
1220
+ // src/components/cell-renderers/boolean-cell.tsx
1221
+ import { jsx as jsx15 } from "react/jsx-runtime";
1222
+ function BooleanCell({
1223
+ value,
1224
+ trueLabel = "Yes",
1225
+ falseLabel = "No",
1226
+ trueColor = "text-green-600 dark:text-green-400",
1227
+ falseColor = "text-red-600 dark:text-red-400"
1228
+ }) {
1229
+ return /* @__PURE__ */ jsx15("span", { className: `font-medium ${value ? trueColor : falseColor}`, children: value ? trueLabel : falseLabel });
1230
+ }
1231
+
1232
+ // src/components/cell-renderers/date-cell.tsx
1233
+ import { jsx as jsx16 } from "react/jsx-runtime";
1234
+ function DateCell({ value, format = "short", locale = "en-US" }) {
1235
+ const date = typeof value === "string" ? new Date(value) : value;
1236
+ if (isNaN(date.getTime())) {
1237
+ return /* @__PURE__ */ jsx16("span", { className: "text-gray-400", children: "-" });
1238
+ }
1239
+ let formatted;
1240
+ switch (format) {
1241
+ case "long":
1242
+ formatted = date.toLocaleDateString(locale, {
1243
+ year: "numeric",
1244
+ month: "long",
1245
+ day: "numeric"
1246
+ });
1247
+ break;
1248
+ case "relative": {
1249
+ const now = /* @__PURE__ */ new Date();
1250
+ const diffMs = now.getTime() - date.getTime();
1251
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
1252
+ if (diffDays === 0) formatted = "Today";
1253
+ else if (diffDays === 1) formatted = "Yesterday";
1254
+ else if (diffDays < 7) formatted = `${diffDays} days ago`;
1255
+ else formatted = date.toLocaleDateString(locale);
1256
+ break;
1257
+ }
1258
+ default:
1259
+ formatted = date.toLocaleDateString(locale);
1260
+ }
1261
+ return /* @__PURE__ */ jsx16("span", { children: formatted });
1262
+ }
1263
+
1264
+ // src/components/cell-renderers/currency-cell.tsx
1265
+ import { jsx as jsx17 } from "react/jsx-runtime";
1266
+ function CurrencyCell({ value, currency = "TRY", locale = "tr-TR" }) {
1267
+ const formatted = new Intl.NumberFormat(locale, {
1268
+ style: "currency",
1269
+ currency
1270
+ }).format(value);
1271
+ return /* @__PURE__ */ jsx17("span", { className: "font-medium", children: formatted });
1272
+ }
1273
+
1274
+ // src/components/cell-renderers/copyable-cell.tsx
1275
+ import * as React8 from "react";
1276
+ import { Copy, Check as Check3 } from "lucide-react";
1277
+ import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
1278
+ function CopyableCell({
1279
+ value,
1280
+ feedbackDuration = 2e3,
1281
+ onCopy,
1282
+ className,
1283
+ tooltip = "Click to copy",
1284
+ alwaysShowIcon = false
1285
+ }) {
1286
+ const [copied, setCopied] = React8.useState(false);
1287
+ const [isHovered, setIsHovered] = React8.useState(false);
1288
+ const handleCopy = async (e) => {
1289
+ e.stopPropagation();
1290
+ const textToCopy = String(value);
1291
+ try {
1292
+ await navigator.clipboard.writeText(textToCopy);
1293
+ setCopied(true);
1294
+ onCopy?.(textToCopy);
1295
+ setTimeout(() => {
1296
+ setCopied(false);
1297
+ }, feedbackDuration);
1298
+ } catch (err) {
1299
+ console.error("Copy error:", err);
1300
+ }
1301
+ };
1302
+ return /* @__PURE__ */ jsxs9(
1303
+ "button",
1304
+ {
1305
+ type: "button",
1306
+ onClick: handleCopy,
1307
+ onMouseEnter: () => setIsHovered(true),
1308
+ onMouseLeave: () => setIsHovered(false),
1309
+ title: tooltip,
1310
+ className: `
1311
+ group inline-flex items-center gap-2
1312
+ px-2 py-1 -mx-2 -my-1
1313
+ rounded-md
1314
+ transition-all duration-200
1315
+ hover:bg-slate-100 dark:hover:bg-slate-800
1316
+ focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1
1317
+ cursor-pointer
1318
+ ${className || ""}
1319
+ `,
1320
+ children: [
1321
+ /* @__PURE__ */ jsx18("span", { className: "select-none", children: value }),
1322
+ /* @__PURE__ */ jsx18(
1323
+ "span",
1324
+ {
1325
+ className: `
1326
+ inline-flex items-center justify-center
1327
+ transition-all duration-200
1328
+ ${alwaysShowIcon || isHovered || copied ? "opacity-100" : "opacity-0"}
1329
+ `,
1330
+ children: copied ? /* @__PURE__ */ jsx18(Check3, { className: "h-3.5 w-3.5 text-green-600 dark:text-green-400" }) : /* @__PURE__ */ jsx18(Copy, { className: "h-3.5 w-3.5 text-slate-400 dark:text-slate-500 group-hover:text-slate-600 dark:group-hover:text-slate-300" })
1331
+ }
1332
+ )
1333
+ ]
1334
+ }
1335
+ );
1336
+ }
1337
+ function createCopyableCell(value, options) {
1338
+ return /* @__PURE__ */ jsx18(CopyableCell, { value, ...options });
1339
+ }
1340
+
1341
+ // src/components/ui/label.tsx
1342
+ import * as React9 from "react";
1343
+ import * as LabelPrimitive from "@radix-ui/react-label";
1344
+ import { cva as cva2 } from "class-variance-authority";
1345
+ import { jsx as jsx19 } from "react/jsx-runtime";
1346
+ var labelVariants = cva2(
1347
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
1348
+ );
1349
+ var Label3 = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(
1350
+ LabelPrimitive.Root,
1351
+ {
1352
+ ref,
1353
+ className: cn(labelVariants(), className),
1354
+ ...props
1355
+ }
1356
+ ));
1357
+ Label3.displayName = LabelPrimitive.Root.displayName;
1358
+
1359
+ // src/components/ui/popover.tsx
1360
+ import * as React10 from "react";
1361
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
1362
+ import { jsx as jsx20 } from "react/jsx-runtime";
1363
+ var Popover = PopoverPrimitive.Root;
1364
+ var PopoverTrigger = PopoverPrimitive.Trigger;
1365
+ var PopoverAnchor = PopoverPrimitive.Anchor;
1366
+ var PopoverContent = React10.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx20(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx20(
1367
+ PopoverPrimitive.Content,
1368
+ {
1369
+ ref,
1370
+ align,
1371
+ sideOffset,
1372
+ className: cn(
1373
+ "z-50 w-72 rounded-md border border-slate-200 bg-white p-4 text-slate-950 shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-50",
1374
+ className
1375
+ ),
1376
+ ...props
1377
+ }
1378
+ ) }));
1379
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
1380
+
1381
+ // src/components/ui/separator.tsx
1382
+ import * as React11 from "react";
1383
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
1384
+ import { jsx as jsx21 } from "react/jsx-runtime";
1385
+ var Separator3 = React11.forwardRef(
1386
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx21(
1387
+ SeparatorPrimitive.Root,
1388
+ {
1389
+ ref,
1390
+ decorative,
1391
+ orientation,
1392
+ className: cn(
1393
+ "shrink-0 bg-slate-200 dark:bg-slate-800",
1394
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
1395
+ className
1396
+ ),
1397
+ ...props
1398
+ }
1399
+ )
1400
+ );
1401
+ Separator3.displayName = SeparatorPrimitive.Root.displayName;
1402
+
1403
+ // src/lib/column-helper.tsx
1404
+ import { createColumnHelper as tanstackCreateColumnHelper } from "@tanstack/react-table";
1405
+ import { jsx as jsx22 } from "react/jsx-runtime";
1406
+ var toTitleCase = (str) => {
1407
+ return str.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()).trim();
1408
+ };
1409
+ function createColumnHelper() {
1410
+ const helper = tanstackCreateColumnHelper();
1411
+ return {
1412
+ /**
1413
+ * Simple accessor - if cell is not provided, value is rendered automatically
1414
+ */
1415
+ accessor: (accessor, column) => {
1416
+ const headerContent = column?.header;
1417
+ const finalColumn = {
1418
+ ...column,
1419
+ // enableSorting is true by default
1420
+ enableSorting: column?.enableSorting !== false,
1421
+ // Pass meta information (filterVariant etc.)
1422
+ meta: column?.meta,
1423
+ // Use LuxDataTableColumnHeader if header is string or undefined
1424
+ header: typeof headerContent === "function" ? headerContent : ({ column: colParam }) => /* @__PURE__ */ jsx22(
1425
+ LuxDataTableColumnHeader,
1426
+ {
1427
+ column: colParam,
1428
+ title: typeof headerContent === "string" ? headerContent : toTitleCase(accessor)
1429
+ }
1430
+ ),
1431
+ // If cell is not defined, show value directly
1432
+ cell: column?.cell || ((info) => {
1433
+ const value = info.getValue();
1434
+ if (value === null || value === void 0) {
1435
+ return "-";
1436
+ }
1437
+ return String(value);
1438
+ })
1439
+ };
1440
+ return helper.accessor(accessor, finalColumn);
1441
+ },
1442
+ /**
1443
+ * Display column (for actions etc.)
1444
+ */
1445
+ display: (column) => {
1446
+ return helper.display(column);
1447
+ },
1448
+ /**
1449
+ * Action column - specialized display column for row actions
1450
+ * Disables sorting by default
1451
+ */
1452
+ action: (column) => {
1453
+ return helper.display({
1454
+ id: "actions",
1455
+ header: "",
1456
+ enableSorting: false,
1457
+ enableHiding: false,
1458
+ ...column
1459
+ });
1460
+ },
1461
+ /**
1462
+ * Create all columns automatically - Table directly from JSON
1463
+ * Just specifying headers is enough, cell is rendered automatically
1464
+ */
1465
+ auto: (columns) => {
1466
+ return columns.map((col) => {
1467
+ return helper.accessor(col.accessor, {
1468
+ header: ({ column }) => /* @__PURE__ */ jsx22(LuxDataTableColumnHeader, { column, title: col.header }),
1469
+ cell: col.cell || ((info) => {
1470
+ const value = info.getValue();
1471
+ if (value === null || value === void 0) return "-";
1472
+ return String(value);
1473
+ })
1474
+ });
1475
+ });
1476
+ }
1477
+ };
1478
+ }
1479
+ function createColumnsFromData(data, options) {
1480
+ if (!data || data.length === 0) return [];
1481
+ const helper = tanstackCreateColumnHelper();
1482
+ const firstRow = data[0];
1483
+ let keys = Object.keys(firstRow);
1484
+ if (options?.include) {
1485
+ keys = keys.filter((k) => options.include?.includes(k));
1486
+ }
1487
+ if (options?.exclude) {
1488
+ keys = keys.filter((k) => !options.exclude?.includes(k));
1489
+ }
1490
+ return keys.map((key) => {
1491
+ const headerText = options?.headers?.[key] || toTitleCase(key);
1492
+ const cellRenderer = options?.cells?.[key];
1493
+ return helper.accessor(key, {
1494
+ header: ({ column }) => /* @__PURE__ */ jsx22(LuxDataTableColumnHeader, { column, title: headerText }),
1495
+ cell: cellRenderer || ((info) => {
1496
+ const value = info.getValue();
1497
+ if (value === null || value === void 0) return "-";
1498
+ return String(value);
1499
+ })
1500
+ });
1501
+ });
1502
+ }
1503
+
82
1504
  // src/index.ts
83
- export * from "@tanstack/react-table";
1505
+ import {
1506
+ flexRender as flexRender2,
1507
+ getCoreRowModel as getCoreRowModel2,
1508
+ getPaginationRowModel as getPaginationRowModel2,
1509
+ getSortedRowModel as getSortedRowModel2,
1510
+ getFilteredRowModel as getFilteredRowModel2
1511
+ } from "@tanstack/react-table";
84
1512
  export {
1513
+ BooleanCell,
1514
+ Button,
1515
+ Checkbox,
1516
+ ColumnFilter,
1517
+ CopyableCell,
1518
+ CurrencyCell,
1519
+ DateCell,
1520
+ DropdownMenu,
1521
+ DropdownMenuCheckboxItem,
1522
+ DropdownMenuContent,
1523
+ DropdownMenuGroup,
1524
+ DropdownMenuItem,
1525
+ DropdownMenuLabel,
1526
+ DropdownMenuPortal,
1527
+ DropdownMenuRadioGroup,
1528
+ DropdownMenuRadioItem,
1529
+ DropdownMenuSeparator,
1530
+ DropdownMenuShortcut,
1531
+ DropdownMenuSub,
1532
+ DropdownMenuSubContent,
1533
+ DropdownMenuSubTrigger,
1534
+ DropdownMenuTrigger,
1535
+ Input,
1536
+ Label3 as Label,
1537
+ LuxDataTableColumnHeader,
85
1538
  LuxTable,
86
- cn
1539
+ Popover,
1540
+ PopoverAnchor,
1541
+ PopoverContent,
1542
+ PopoverTrigger,
1543
+ ProgressCell,
1544
+ Select,
1545
+ SelectContent,
1546
+ SelectGroup,
1547
+ SelectItem,
1548
+ SelectLabel,
1549
+ SelectScrollDownButton,
1550
+ SelectScrollUpButton,
1551
+ SelectSeparator,
1552
+ SelectTrigger,
1553
+ SelectValue,
1554
+ Separator3 as Separator,
1555
+ SortIcon,
1556
+ StatusCell,
1557
+ Table,
1558
+ TableBody,
1559
+ TableCaption,
1560
+ TableCell,
1561
+ TableFooter,
1562
+ TableHead,
1563
+ TableHeader,
1564
+ TablePagination,
1565
+ TableRow,
1566
+ TableToolbar,
1567
+ buttonVariants,
1568
+ cn,
1569
+ createColumnHelper,
1570
+ createColumnsFromData,
1571
+ createCopyableCell,
1572
+ defaultStatusColors,
1573
+ flexRender2 as flexRender,
1574
+ getCoreRowModel2 as getCoreRowModel,
1575
+ getFilteredRowModel2 as getFilteredRowModel,
1576
+ getPaginationRowModel2 as getPaginationRowModel,
1577
+ getSortedRowModel2 as getSortedRowModel
87
1578
  };