@tirth_jasoliya/ui 1.0.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.
package/dist/index.js ADDED
@@ -0,0 +1,3091 @@
1
+ // src/components/data/data-table/data-table.tsx
2
+ import {
3
+ flexRender,
4
+ getCoreRowModel,
5
+ getFilteredRowModel,
6
+ getPaginationRowModel,
7
+ getSortedRowModel,
8
+ useReactTable
9
+ } from "@tanstack/react-table";
10
+ import { Loader2, ChevronUp, ChevronDown as ChevronDown2, ChevronsUpDown, MoreHorizontal, MoveRightIcon, PinOffIcon } from "lucide-react";
11
+
12
+ // src/components/ui/button.tsx
13
+ import { Slot as SlotPrimitive } from "radix-ui";
14
+ import { cva } from "class-variance-authority";
15
+
16
+ // src/lib/utils.ts
17
+ import { clsx } from "clsx";
18
+ import { twMerge } from "tailwind-merge";
19
+ function cn(...inputs) {
20
+ return twMerge(clsx(inputs));
21
+ }
22
+
23
+ // src/components/ui/button.tsx
24
+ import { jsx } from "react/jsx-runtime";
25
+ var buttonVariants = cva(
26
+ "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",
27
+ {
28
+ variants: {
29
+ variant: {
30
+ default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
31
+ destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
32
+ 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",
33
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
34
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
35
+ link: "text-primary underline-offset-4 hover:underline"
36
+ },
37
+ size: {
38
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
39
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
40
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
41
+ icon: "size-9"
42
+ }
43
+ },
44
+ defaultVariants: {
45
+ variant: "default",
46
+ size: "default"
47
+ }
48
+ }
49
+ );
50
+ function Button({
51
+ className,
52
+ variant,
53
+ size,
54
+ asChild = false,
55
+ ...props
56
+ }) {
57
+ const Comp = asChild ? SlotPrimitive.Slot : "button";
58
+ return /* @__PURE__ */ jsx(
59
+ Comp,
60
+ {
61
+ "data-slot": "button",
62
+ className: cn(buttonVariants({ variant, size, className }), "transition-none"),
63
+ ...props
64
+ }
65
+ );
66
+ }
67
+
68
+ // src/components/ui/table.tsx
69
+ import { jsx as jsx2 } from "react/jsx-runtime";
70
+ function Table({ className, ...props }) {
71
+ return /* @__PURE__ */ jsx2(
72
+ "div",
73
+ {
74
+ "data-slot": "table-container",
75
+ className: "relative w-full overflow-auto max-h-full",
76
+ children: /* @__PURE__ */ jsx2(
77
+ "table",
78
+ {
79
+ "data-slot": "table",
80
+ className: cn("w-full caption-bottom text-sm", className),
81
+ ...props
82
+ }
83
+ )
84
+ }
85
+ );
86
+ }
87
+ function TableHeader({ className, ...props }) {
88
+ return /* @__PURE__ */ jsx2(
89
+ "thead",
90
+ {
91
+ "data-slot": "table-header",
92
+ className: cn("[&_tr]:border-b", className),
93
+ ...props
94
+ }
95
+ );
96
+ }
97
+ function TableBody({ className, ...props }) {
98
+ return /* @__PURE__ */ jsx2(
99
+ "tbody",
100
+ {
101
+ "data-slot": "table-body",
102
+ className: cn("[&_tr:last-child]:border-0", className),
103
+ ...props
104
+ }
105
+ );
106
+ }
107
+ function TableFooter({ className, ...props }) {
108
+ return /* @__PURE__ */ jsx2(
109
+ "tfoot",
110
+ {
111
+ "data-slot": "table-footer",
112
+ className: cn(
113
+ "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
114
+ className
115
+ ),
116
+ ...props
117
+ }
118
+ );
119
+ }
120
+ function TableRow({ className, ...props }) {
121
+ return /* @__PURE__ */ jsx2(
122
+ "tr",
123
+ {
124
+ "data-slot": "table-row",
125
+ className: cn(
126
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
127
+ className
128
+ ),
129
+ ...props
130
+ }
131
+ );
132
+ }
133
+ function TableHead({ className, ...props }) {
134
+ return /* @__PURE__ */ jsx2(
135
+ "th",
136
+ {
137
+ "data-slot": "table-head",
138
+ className: cn(
139
+ "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap",
140
+ className
141
+ ),
142
+ ...props
143
+ }
144
+ );
145
+ }
146
+ function TableCell({ className, ...props }) {
147
+ return /* @__PURE__ */ jsx2(
148
+ "td",
149
+ {
150
+ "data-slot": "table-cell",
151
+ className: cn(
152
+ "p-2 align-middle whitespace-nowrap",
153
+ className
154
+ ),
155
+ ...props
156
+ }
157
+ );
158
+ }
159
+
160
+ // src/components/ui/card.tsx
161
+ import { jsx as jsx3 } from "react/jsx-runtime";
162
+ function Card({ className, ...props }) {
163
+ return /* @__PURE__ */ jsx3(
164
+ "div",
165
+ {
166
+ "data-slot": "card",
167
+ className: cn(
168
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
169
+ className
170
+ ),
171
+ ...props
172
+ }
173
+ );
174
+ }
175
+ function CardContent({ className, ...props }) {
176
+ return /* @__PURE__ */ jsx3(
177
+ "div",
178
+ {
179
+ "data-slot": "card-content",
180
+ className: cn("px-6", className),
181
+ ...props
182
+ }
183
+ );
184
+ }
185
+
186
+ // src/components/ui/tooltip.tsx
187
+ import { Tooltip as TooltipPrimitive } from "radix-ui";
188
+ import { jsx as jsx4, jsxs } from "react/jsx-runtime";
189
+ function TooltipProvider({
190
+ delayDuration = 0,
191
+ ...props
192
+ }) {
193
+ return /* @__PURE__ */ jsx4(
194
+ TooltipPrimitive.Provider,
195
+ {
196
+ "data-slot": "tooltip-provider",
197
+ delayDuration,
198
+ ...props
199
+ }
200
+ );
201
+ }
202
+ function Tooltip({
203
+ ...props
204
+ }) {
205
+ return /* @__PURE__ */ jsx4(TooltipProvider, { children: /* @__PURE__ */ jsx4(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
206
+ }
207
+ function TooltipTrigger({
208
+ ...props
209
+ }) {
210
+ return /* @__PURE__ */ jsx4(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
211
+ }
212
+ function TooltipContent({
213
+ className,
214
+ sideOffset = 0,
215
+ children,
216
+ ...props
217
+ }) {
218
+ return /* @__PURE__ */ jsx4(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
219
+ TooltipPrimitive.Content,
220
+ {
221
+ "data-slot": "tooltip-content",
222
+ sideOffset,
223
+ className: cn(
224
+ "bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
225
+ className
226
+ ),
227
+ ...props,
228
+ children: [
229
+ children,
230
+ /* @__PURE__ */ jsx4(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
231
+ ]
232
+ }
233
+ ) });
234
+ }
235
+
236
+ // src/components/data/data-table/data-table-toolbar.tsx
237
+ import { Search, RefreshCw, Download, Settings2, Filter, ArrowUpDown, PinOff, Pin, ChevronDown } from "lucide-react";
238
+
239
+ // src/components/ui/input.tsx
240
+ import { jsx as jsx5 } from "react/jsx-runtime";
241
+ function Input({ className, type, ...props }) {
242
+ return /* @__PURE__ */ jsx5(
243
+ "input",
244
+ {
245
+ type,
246
+ "data-slot": "input",
247
+ className: cn(
248
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
249
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
250
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
251
+ className
252
+ ),
253
+ ...props
254
+ }
255
+ );
256
+ }
257
+
258
+ // src/components/ui/select.tsx
259
+ import { Select as SelectPrimitive } from "radix-ui";
260
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react";
261
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
262
+ function Select({
263
+ ...props
264
+ }) {
265
+ return /* @__PURE__ */ jsx6(SelectPrimitive.Root, { "data-slot": "select", ...props });
266
+ }
267
+ function SelectValue({
268
+ ...props
269
+ }) {
270
+ return /* @__PURE__ */ jsx6(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
271
+ }
272
+ function SelectTrigger({
273
+ className,
274
+ size = "default",
275
+ children,
276
+ ...props
277
+ }) {
278
+ return /* @__PURE__ */ jsxs2(
279
+ SelectPrimitive.Trigger,
280
+ {
281
+ "data-slot": "select-trigger",
282
+ "data-size": size,
283
+ className: cn(
284
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
285
+ className
286
+ ),
287
+ ...props,
288
+ children: [
289
+ children,
290
+ /* @__PURE__ */ jsx6(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "size-4 opacity-50" }) })
291
+ ]
292
+ }
293
+ );
294
+ }
295
+ function SelectContent({
296
+ className,
297
+ children,
298
+ position = "popper",
299
+ ...props
300
+ }) {
301
+ return /* @__PURE__ */ jsx6(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs2(
302
+ SelectPrimitive.Content,
303
+ {
304
+ "data-slot": "select-content",
305
+ className: cn(
306
+ "bg-popover text-popover-foreground 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 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
307
+ 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",
308
+ className
309
+ ),
310
+ position,
311
+ ...props,
312
+ children: [
313
+ /* @__PURE__ */ jsx6(SelectScrollUpButton, {}),
314
+ /* @__PURE__ */ jsx6(
315
+ SelectPrimitive.Viewport,
316
+ {
317
+ className: cn(
318
+ "p-1",
319
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
320
+ ),
321
+ children
322
+ }
323
+ ),
324
+ /* @__PURE__ */ jsx6(SelectScrollDownButton, {})
325
+ ]
326
+ }
327
+ ) });
328
+ }
329
+ function SelectItem({
330
+ className,
331
+ children,
332
+ ...props
333
+ }) {
334
+ return /* @__PURE__ */ jsxs2(
335
+ SelectPrimitive.Item,
336
+ {
337
+ "data-slot": "select-item",
338
+ className: cn(
339
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
340
+ className
341
+ ),
342
+ ...props,
343
+ children: [
344
+ /* @__PURE__ */ jsx6("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx6(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx6(CheckIcon, { className: "size-4" }) }) }),
345
+ /* @__PURE__ */ jsx6(SelectPrimitive.ItemText, { children })
346
+ ]
347
+ }
348
+ );
349
+ }
350
+ function SelectScrollUpButton({
351
+ className,
352
+ ...props
353
+ }) {
354
+ return /* @__PURE__ */ jsx6(
355
+ SelectPrimitive.ScrollUpButton,
356
+ {
357
+ "data-slot": "select-scroll-up-button",
358
+ className: cn(
359
+ "flex cursor-default items-center justify-center py-1",
360
+ className
361
+ ),
362
+ ...props,
363
+ children: /* @__PURE__ */ jsx6(ChevronUpIcon, { className: "size-4" })
364
+ }
365
+ );
366
+ }
367
+ function SelectScrollDownButton({
368
+ className,
369
+ ...props
370
+ }) {
371
+ return /* @__PURE__ */ jsx6(
372
+ SelectPrimitive.ScrollDownButton,
373
+ {
374
+ "data-slot": "select-scroll-down-button",
375
+ className: cn(
376
+ "flex cursor-default items-center justify-center py-1",
377
+ className
378
+ ),
379
+ ...props,
380
+ children: /* @__PURE__ */ jsx6(ChevronDownIcon, { className: "size-4" })
381
+ }
382
+ );
383
+ }
384
+
385
+ // src/components/ui/dropdown-menu.tsx
386
+ import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
387
+ import { CheckIcon as CheckIcon2, ChevronRightIcon, CircleIcon } from "lucide-react";
388
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
389
+ function DropdownMenu({
390
+ ...props
391
+ }) {
392
+ return /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
393
+ }
394
+ function DropdownMenuTrigger({
395
+ ...props
396
+ }) {
397
+ return /* @__PURE__ */ jsx7(
398
+ DropdownMenuPrimitive.Trigger,
399
+ {
400
+ "data-slot": "dropdown-menu-trigger",
401
+ ...props
402
+ }
403
+ );
404
+ }
405
+ function DropdownMenuContent({
406
+ className,
407
+ sideOffset = 4,
408
+ ...props
409
+ }) {
410
+ return /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
411
+ DropdownMenuPrimitive.Content,
412
+ {
413
+ "data-slot": "dropdown-menu-content",
414
+ sideOffset,
415
+ className: cn(
416
+ "bg-popover text-popover-foreground 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) rounded-md border p-1 shadow-md",
417
+ className
418
+ ),
419
+ ...props
420
+ }
421
+ ) });
422
+ }
423
+ function DropdownMenuGroup({
424
+ ...props
425
+ }) {
426
+ return /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
427
+ }
428
+ function DropdownMenuItem({
429
+ className,
430
+ inset,
431
+ variant = "default",
432
+ ...props
433
+ }) {
434
+ return /* @__PURE__ */ jsx7(
435
+ DropdownMenuPrimitive.Item,
436
+ {
437
+ "data-slot": "dropdown-menu-item",
438
+ "data-inset": inset,
439
+ "data-variant": variant,
440
+ className: cn(
441
+ "cursor-pointer focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
442
+ className
443
+ ),
444
+ ...props
445
+ }
446
+ );
447
+ }
448
+ function DropdownMenuCheckboxItem({
449
+ className,
450
+ children,
451
+ checked,
452
+ ...props
453
+ }) {
454
+ return /* @__PURE__ */ jsxs3(
455
+ DropdownMenuPrimitive.CheckboxItem,
456
+ {
457
+ "data-slot": "dropdown-menu-checkbox-item",
458
+ className: cn(
459
+ "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
460
+ className
461
+ ),
462
+ checked,
463
+ ...props,
464
+ children: [
465
+ /* @__PURE__ */ jsx7("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx7(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx7(CheckIcon2, { className: "size-4" }) }) }),
466
+ children
467
+ ]
468
+ }
469
+ );
470
+ }
471
+ function DropdownMenuLabel({
472
+ className,
473
+ inset,
474
+ ...props
475
+ }) {
476
+ return /* @__PURE__ */ jsx7(
477
+ DropdownMenuPrimitive.Label,
478
+ {
479
+ "data-slot": "dropdown-menu-label",
480
+ "data-inset": inset,
481
+ className: cn(
482
+ "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
483
+ className
484
+ ),
485
+ ...props
486
+ }
487
+ );
488
+ }
489
+ function DropdownMenuSeparator({
490
+ className,
491
+ ...props
492
+ }) {
493
+ return /* @__PURE__ */ jsx7(
494
+ DropdownMenuPrimitive.Separator,
495
+ {
496
+ "data-slot": "dropdown-menu-separator",
497
+ className: cn("bg-border -mx-1 my-1 h-px", className),
498
+ ...props
499
+ }
500
+ );
501
+ }
502
+
503
+ // src/components/data/data-table/data-table-toolbar.tsx
504
+ import { Fragment, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
505
+ function DataTableToolbar({
506
+ table,
507
+ filters = [],
508
+ globalFilter,
509
+ onGlobalFilterChange,
510
+ enableGlobalFilter = true,
511
+ onExport,
512
+ onRefresh,
513
+ loading = false,
514
+ enableColumnVisibility = true,
515
+ data,
516
+ onClearSorting,
517
+ onClearFilters,
518
+ enableColumnPinning = false
519
+ }) {
520
+ const getAllLeafColumns = () => {
521
+ return table.getAllLeafColumns().filter((column) => column.getCanHide?.() !== false);
522
+ };
523
+ const getGroupColumns = () => {
524
+ return table.getAllColumns().filter(
525
+ (column) => !table.getAllLeafColumns().includes(column) && column.columns?.length && column.columns.some((col) => col.getCanHide?.() !== false)
526
+ );
527
+ };
528
+ const getUngroupedLeafColumns = () => {
529
+ const groupedColumnIds = new Set(
530
+ getGroupColumns().flatMap(
531
+ (group) => group.columns?.filter((col) => col.getCanHide?.() !== false).map((c) => c.id) || []
532
+ )
533
+ );
534
+ return getAllLeafColumns().filter((column) => !groupedColumnIds.has(column.id));
535
+ };
536
+ const getColumnDisplayName = (columnId, groupName) => {
537
+ if (groupName && columnId.startsWith(`${groupName}.`)) {
538
+ const cleanId = columnId.replace(`${groupName}.`, "");
539
+ return cleanId.split("_").map((word) => word.slice(1)).join(" ");
540
+ }
541
+ return columnId.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
542
+ };
543
+ return /* @__PURE__ */ jsx8("div", { className: "rounded-xl", children: /* @__PURE__ */ jsx8("div", { className: "px-2", children: /* @__PURE__ */ jsx8("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between", children: [
544
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-3", children: filters.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3 flex-wrap", children: [
545
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: /* @__PURE__ */ jsx8(Filter, { className: "h-4 w-4" }) }),
546
+ filters.map((filter) => /* @__PURE__ */ jsx8("div", { className: cn("relative min-w-[150px]", filter.width), children: filter.type === "select" ? /* @__PURE__ */ jsxs4(
547
+ Select,
548
+ {
549
+ value: table.getColumn(filter.key)?.getFilterValue() ?? "",
550
+ onValueChange: (value) => table.getColumn(filter.key)?.setFilterValue(value === "all" ? "" : value),
551
+ children: [
552
+ filter.icon && /* @__PURE__ */ jsx8("span", { children: /* @__PURE__ */ jsx8(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }) }),
553
+ /* @__PURE__ */ jsx8(SelectTrigger, { className: cn("h-9 rounded-lg w-full", filter.icon && "pl-9"), children: /* @__PURE__ */ jsx8(SelectValue, { placeholder: filter.placeholder }) }),
554
+ /* @__PURE__ */ jsxs4(SelectContent, { className: "rounded-lg", children: [
555
+ /* @__PURE__ */ jsx8(SelectItem, { value: "all", children: "All" }),
556
+ filter.options?.map((option) => /* @__PURE__ */ jsx8(SelectItem, { value: option.value, children: option.label }, option.label))
557
+ ] })
558
+ ]
559
+ }
560
+ ) : /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
561
+ filter.icon && /* @__PURE__ */ jsx8("span", { children: /* @__PURE__ */ jsx8(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }) }),
562
+ /* @__PURE__ */ jsx8(
563
+ Input,
564
+ {
565
+ placeholder: filter.placeholder,
566
+ value: table.getColumn(filter.key)?.getFilterValue() ?? "",
567
+ onChange: (event) => table.getColumn(filter.key)?.setFilterValue(event.target.value),
568
+ className: cn("h-9 rounded-lg", filter.icon && "pl-9"),
569
+ type: filter.type === "number" ? "number" : filter.type === "date" ? "date" : "text"
570
+ }
571
+ )
572
+ ] }) }, filter.key))
573
+ ] }) }),
574
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
575
+ enableGlobalFilter && /* @__PURE__ */ jsxs4("div", { className: "relative", children: [
576
+ /* @__PURE__ */ jsx8(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
577
+ /* @__PURE__ */ jsx8(
578
+ Input,
579
+ {
580
+ placeholder: "Global search...",
581
+ value: globalFilter ?? "",
582
+ onChange: (event) => onGlobalFilterChange(event.target.value),
583
+ className: "pl-9 max-w-max"
584
+ }
585
+ )
586
+ ] }),
587
+ onExport && /* @__PURE__ */ jsxs4(Button, { variant: "outline", size: "sm", onClick: () => onExport(data), className: "rounded-lg", children: [
588
+ /* @__PURE__ */ jsx8(Download, { className: "mr-2 h-4 w-4" }),
589
+ "Export"
590
+ ] }),
591
+ enableColumnVisibility && /* @__PURE__ */ jsxs4(DropdownMenu, { children: [
592
+ /* @__PURE__ */ jsx8(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(Button, { variant: "outline", size: "sm", className: "rounded-lg gap-1", children: [
593
+ /* @__PURE__ */ jsx8("span", { children: "Columns" }),
594
+ /* @__PURE__ */ jsx8(ChevronDown, { className: "h-4 w-4 opacity-50" })
595
+ ] }) }),
596
+ /* @__PURE__ */ jsxs4(DropdownMenuContent, { align: "end", className: "w-[220px] rounded-lg max-h-[400px] overflow-y-auto", children: [
597
+ /* @__PURE__ */ jsx8(DropdownMenuLabel, { className: "px-4 py-2 text-sm font-medium", children: "Toggle Columns" }),
598
+ /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}),
599
+ getUngroupedLeafColumns().length > 0 && /* @__PURE__ */ jsxs4(DropdownMenuGroup, { children: [
600
+ /* @__PURE__ */ jsx8(DropdownMenuLabel, { className: "px-4 py-1.5 text-sm font-medium text-muted-foreground", children: "General" }),
601
+ getUngroupedLeafColumns().map((column) => /* @__PURE__ */ jsx8(
602
+ DropdownMenuCheckboxItem,
603
+ {
604
+ className: "text-sm",
605
+ checked: column.getIsVisible(),
606
+ onCheckedChange: (value) => column.toggleVisibility(!!value),
607
+ children: getColumnDisplayName(column.id)
608
+ },
609
+ column.id
610
+ ))
611
+ ] }),
612
+ getGroupColumns().map((group) => /* @__PURE__ */ jsxs4(DropdownMenuGroup, { children: [
613
+ /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}),
614
+ /* @__PURE__ */ jsx8(DropdownMenuLabel, { className: "px-4 py-1.5 text-sm font-medium text-muted-foreground", children: group.id }),
615
+ group.columns?.filter((column) => column.getCanHide?.() !== false).map((column) => /* @__PURE__ */ jsx8(
616
+ DropdownMenuCheckboxItem,
617
+ {
618
+ className: "text-sm",
619
+ checked: column.getIsVisible(),
620
+ onCheckedChange: (value) => column.toggleVisibility(!!value),
621
+ children: getColumnDisplayName(column.id, group.id)
622
+ },
623
+ column.id
624
+ ))
625
+ ] }, group.id))
626
+ ] })
627
+ ] }),
628
+ /* @__PURE__ */ jsxs4(DropdownMenu, { children: [
629
+ /* @__PURE__ */ jsx8(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx8(Button, { variant: "outline", size: "sm", className: "rounded-lg", children: /* @__PURE__ */ jsx8(Settings2, { className: "h-4 w-4" }) }) }),
630
+ /* @__PURE__ */ jsxs4(DropdownMenuContent, { align: "end", className: "w-[200px] rounded-lg", children: [
631
+ /* @__PURE__ */ jsx8(DropdownMenuLabel, { children: "Table Settings" }),
632
+ /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}),
633
+ /* @__PURE__ */ jsxs4(DropdownMenuItem, { onClick: onClearSorting, children: [
634
+ /* @__PURE__ */ jsx8(ArrowUpDown, { className: "mr-2 h-4 w-4" }),
635
+ "Clear All Sorting"
636
+ ] }),
637
+ /* @__PURE__ */ jsxs4(DropdownMenuItem, { onClick: onClearFilters, children: [
638
+ /* @__PURE__ */ jsx8(Filter, { className: "mr-2 h-4 w-4" }),
639
+ "Clear All Filters"
640
+ ] }),
641
+ enableColumnPinning && /* @__PURE__ */ jsxs4(Fragment, { children: [
642
+ /* @__PURE__ */ jsx8(DropdownMenuSeparator, {}),
643
+ /* @__PURE__ */ jsx8(DropdownMenuLabel, { children: "Column Pinning" }),
644
+ /* @__PURE__ */ jsxs4(
645
+ DropdownMenuItem,
646
+ {
647
+ onClick: () => table.setColumnPinning({ left: [], right: [] }),
648
+ children: [
649
+ /* @__PURE__ */ jsx8(PinOff, { className: "mr-2 h-4 w-4" }),
650
+ "Reset All Pinning"
651
+ ]
652
+ }
653
+ ),
654
+ /* @__PURE__ */ jsxs4(
655
+ DropdownMenuItem,
656
+ {
657
+ onClick: () => {
658
+ const leftColumns = getAllLeafColumns().filter((column) => column.getCanPin?.() !== false).map((column) => column.id);
659
+ table.setColumnPinning({ left: leftColumns, right: [] });
660
+ },
661
+ children: [
662
+ /* @__PURE__ */ jsx8(Pin, { className: "mr-2 h-4 w-4 rotate-90" }),
663
+ "Pin All Left"
664
+ ]
665
+ }
666
+ ),
667
+ /* @__PURE__ */ jsxs4(
668
+ DropdownMenuItem,
669
+ {
670
+ onClick: () => {
671
+ const rightColumns = getAllLeafColumns().filter((column) => column.getCanPin?.() !== false).map((column) => column.id);
672
+ table.setColumnPinning({ left: [], right: rightColumns });
673
+ },
674
+ children: [
675
+ /* @__PURE__ */ jsx8(Pin, { className: "mr-2 h-4 w-4 -rotate-90" }),
676
+ "Pin All Right"
677
+ ]
678
+ }
679
+ )
680
+ ] })
681
+ ] })
682
+ ] }),
683
+ onRefresh && /* @__PURE__ */ jsx8(Button, { variant: "outline", size: "sm", onClick: onRefresh, disabled: loading, className: "rounded-lg", children: /* @__PURE__ */ jsx8(RefreshCw, { className: cn("h-4 w-4", loading && "animate-spin") }) })
684
+ ] })
685
+ ] }) }) }) });
686
+ }
687
+
688
+ // src/components/data/data-table/data-table-pagination.tsx
689
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
690
+ function DataTablePagination({ table, config }) {
691
+ if (!config.enabled) return null;
692
+ return /* @__PURE__ */ jsx9("div", { className: "rounded-xl", children: /* @__PURE__ */ jsx9("div", { children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
693
+ /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-6 text-sm text-muted-foreground", children: config.showInfo !== false && /* @__PURE__ */ jsxs5("span", { children: [
694
+ "Showing ",
695
+ table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1,
696
+ " to",
697
+ " ",
698
+ Math.min(
699
+ (table.getState().pagination.pageIndex + 1) * table.getState().pagination.pageSize,
700
+ table.getFilteredRowModel().rows.length
701
+ ),
702
+ " ",
703
+ "of ",
704
+ table.getFilteredRowModel().rows.length,
705
+ " entries"
706
+ ] }) }),
707
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4", children: [
708
+ config.pageSizeOptions && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
709
+ /* @__PURE__ */ jsx9("span", { className: "text-sm font-medium", children: "Rows per page:" }),
710
+ /* @__PURE__ */ jsxs5(
711
+ Select,
712
+ {
713
+ value: `${table.getState().pagination.pageSize}`,
714
+ onValueChange: (value) => table.setPageSize(Number(value)),
715
+ children: [
716
+ /* @__PURE__ */ jsx9(SelectTrigger, { className: "h-9 w-[70px] rounded-lg", children: /* @__PURE__ */ jsx9(SelectValue, {}) }),
717
+ /* @__PURE__ */ jsx9(SelectContent, { side: "top", className: "rounded-lg", children: config.pageSizeOptions.map((pageSize) => /* @__PURE__ */ jsx9(SelectItem, { value: `${pageSize}`, children: pageSize }, pageSize)) })
718
+ ]
719
+ }
720
+ )
721
+ ] }),
722
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
723
+ /* @__PURE__ */ jsx9(
724
+ Button,
725
+ {
726
+ variant: "outline",
727
+ size: "sm",
728
+ onClick: () => table.setPageIndex(0),
729
+ disabled: !table.getCanPreviousPage(),
730
+ className: "rounded-lg",
731
+ children: "First"
732
+ }
733
+ ),
734
+ /* @__PURE__ */ jsx9(
735
+ Button,
736
+ {
737
+ variant: "outline",
738
+ size: "sm",
739
+ onClick: () => table.previousPage(),
740
+ disabled: !table.getCanPreviousPage(),
741
+ className: "rounded-lg",
742
+ children: "Previous"
743
+ }
744
+ ),
745
+ config.showPageNumbers && /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-1", children: Array.from({ length: Math.min(5, table.getPageCount()) }, (_, i) => {
746
+ const pageIndex = table.getState().pagination.pageIndex;
747
+ const pageNumber = pageIndex - 2 + i + 1;
748
+ if (pageNumber < 1 || pageNumber > table.getPageCount()) return null;
749
+ return /* @__PURE__ */ jsx9(
750
+ Button,
751
+ {
752
+ variant: pageNumber === pageIndex + 1 ? "default" : "outline",
753
+ size: "sm",
754
+ className: "size-8 p-0 rounded-lg",
755
+ onClick: () => table.setPageIndex(pageNumber - 1),
756
+ children: pageNumber
757
+ },
758
+ pageNumber
759
+ );
760
+ }) }),
761
+ /* @__PURE__ */ jsx9(
762
+ Button,
763
+ {
764
+ variant: "outline",
765
+ size: "sm",
766
+ onClick: () => table.nextPage(),
767
+ disabled: !table.getCanNextPage(),
768
+ className: "rounded-lg",
769
+ children: "Next"
770
+ }
771
+ ),
772
+ /* @__PURE__ */ jsx9(
773
+ Button,
774
+ {
775
+ variant: "outline",
776
+ size: "sm",
777
+ onClick: () => table.setPageIndex(table.getPageCount() - 1),
778
+ disabled: !table.getCanNextPage(),
779
+ className: "rounded-lg",
780
+ children: "Last"
781
+ }
782
+ )
783
+ ] })
784
+ ] })
785
+ ] }) }) });
786
+ }
787
+
788
+ // src/components/ui/toggle.tsx
789
+ import { Toggle as TogglePrimitive } from "radix-ui";
790
+ import { cva as cva2 } from "class-variance-authority";
791
+ import { jsx as jsx10 } from "react/jsx-runtime";
792
+ var toggleVariants = cva2(
793
+ "inline-flex cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
794
+ {
795
+ variants: {
796
+ variant: {
797
+ default: "bg-transparent",
798
+ outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
799
+ },
800
+ size: {
801
+ sm: "h-7 px-0 min-w-7",
802
+ default: "h-8 px-1 min-w-8",
803
+ lg: "h-9 px-2 min-w-10"
804
+ },
805
+ bg: {
806
+ enabled: "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
807
+ disabled: ""
808
+ }
809
+ },
810
+ defaultVariants: {
811
+ variant: "default",
812
+ size: "default",
813
+ bg: "enabled"
814
+ }
815
+ }
816
+ );
817
+ function Toggle({
818
+ className,
819
+ variant,
820
+ size,
821
+ noBg,
822
+ ...props
823
+ }) {
824
+ return /* @__PURE__ */ jsx10(
825
+ TogglePrimitive.Root,
826
+ {
827
+ "data-slot": "toggle",
828
+ className: cn(toggleVariants({ className, variant, size, bg: noBg ? "disabled" : "enabled" })),
829
+ ...props
830
+ }
831
+ );
832
+ }
833
+
834
+ // src/components/ui/checkbox.tsx
835
+ import { Checkbox as CheckboxPrimitive } from "radix-ui";
836
+ import { CheckIcon as CheckIcon3 } from "lucide-react";
837
+ import { jsx as jsx11 } from "react/jsx-runtime";
838
+ function Checkbox({
839
+ className,
840
+ ...props
841
+ }) {
842
+ return /* @__PURE__ */ jsx11(
843
+ CheckboxPrimitive.Root,
844
+ {
845
+ "data-slot": "checkbox",
846
+ className: cn(
847
+ "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",
848
+ className
849
+ ),
850
+ ...props,
851
+ children: /* @__PURE__ */ jsx11(
852
+ CheckboxPrimitive.Indicator,
853
+ {
854
+ "data-slot": "checkbox-indicator",
855
+ className: "flex items-center justify-center text-current transition-none",
856
+ children: /* @__PURE__ */ jsx11(CheckIcon3, { className: "size-3.5" })
857
+ }
858
+ )
859
+ }
860
+ );
861
+ }
862
+
863
+ // src/components/data/data-table/data-table.tsx
864
+ import { useCallback, useEffect, useMemo, useState } from "react";
865
+ import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
866
+ function DataTable({
867
+ data,
868
+ columns: initialColumns,
869
+ filters = [],
870
+ pagination = { enabled: false },
871
+ settings = {},
872
+ header,
873
+ footer,
874
+ className = "",
875
+ maxHeight = "600px",
876
+ loading = false,
877
+ error,
878
+ emptyMessage = "No data available",
879
+ onRowSelectionChange,
880
+ onExport,
881
+ onRefresh,
882
+ onTableReady,
883
+ children
884
+ }) {
885
+ const [sorting, setSorting] = useState([]);
886
+ const [columnFilters, setColumnFilters] = useState([]);
887
+ const [columnVisibility, setColumnVisibility] = useState({});
888
+ const [rowSelection, setRowSelection] = useState({});
889
+ const [globalFilter, setGlobalFilter] = useState("");
890
+ const [columnOrder, setColumnOrder] = useState([]);
891
+ const [columnPinning, setColumnPinning] = useState(
892
+ settings.enableColumnPinning ? { left: [], right: [] } : {}
893
+ );
894
+ const {
895
+ enableSorting = true,
896
+ enableFiltering = true,
897
+ enableGlobalFilter = true,
898
+ enableColumnVisibility = true,
899
+ enableRowSelection = true,
900
+ stickyHeader = true,
901
+ toolbar = false,
902
+ showSerialNumbers = true,
903
+ fixedCheckboxColumn = true,
904
+ striped = true,
905
+ hoverable = true,
906
+ compact = true,
907
+ bordered = true,
908
+ fullHeight = false,
909
+ enableColumnResizing = false,
910
+ enableColumnPinning = true,
911
+ hideHeader = false
912
+ } = settings;
913
+ const columns = useMemo(() => {
914
+ const cols = [...initialColumns];
915
+ const processColumns = (columns2) => {
916
+ return columns2.map((col) => {
917
+ if (col.id === "select" || col.id === "serialNumber") {
918
+ return col;
919
+ }
920
+ const newCol = {
921
+ ...col,
922
+ enablePinning: true
923
+ };
924
+ if (col.columns) {
925
+ newCol.columns = processColumns(col.columns);
926
+ }
927
+ return newCol;
928
+ });
929
+ };
930
+ const processedCols = processColumns(cols);
931
+ if (enableRowSelection) {
932
+ const selectColumn = {
933
+ id: "select",
934
+ header: ({ table: table2 }) => /* @__PURE__ */ jsx12(
935
+ Checkbox,
936
+ {
937
+ checked: table2.getIsAllPageRowsSelected() || table2.getIsSomePageRowsSelected() && "indeterminate",
938
+ onCheckedChange: (value) => table2.toggleAllPageRowsSelected(!!value),
939
+ "aria-label": "Select all"
940
+ }
941
+ ),
942
+ cell: ({ row }) => /* @__PURE__ */ jsx12("div", { className: cn("flex items-center justify-center"), children: /* @__PURE__ */ jsx12(
943
+ Checkbox,
944
+ {
945
+ checked: row.getIsSelected(),
946
+ onCheckedChange: (value) => row.toggleSelected(!!value),
947
+ "aria-label": "Select row"
948
+ }
949
+ ) }),
950
+ enableSorting: false,
951
+ enableHiding: false,
952
+ enablePinning: true,
953
+ headerAlign: "center",
954
+ size: 10
955
+ };
956
+ processedCols.unshift(selectColumn);
957
+ }
958
+ if (showSerialNumbers) {
959
+ const serialColumn = {
960
+ id: "serialNumber",
961
+ header: "No.",
962
+ cell: ({ row }) => /* @__PURE__ */ jsx12("div", { className: "text-center font-medium text-muted-foreground", children: row.index + 1 }),
963
+ enableSorting: true,
964
+ enableHiding: false,
965
+ enablePinning: true,
966
+ size: 60,
967
+ headerAlign: "center"
968
+ };
969
+ processedCols.unshift(serialColumn);
970
+ }
971
+ return processedCols;
972
+ }, [initialColumns, showSerialNumbers, enableRowSelection, fixedCheckboxColumn]);
973
+ const table = useReactTable({
974
+ data,
975
+ columns,
976
+ onSortingChange: enableSorting ? setSorting : void 0,
977
+ onColumnFiltersChange: enableFiltering ? setColumnFilters : void 0,
978
+ onGlobalFilterChange: enableGlobalFilter ? setGlobalFilter : void 0,
979
+ getCoreRowModel: getCoreRowModel(),
980
+ getPaginationRowModel: pagination.enabled ? getPaginationRowModel() : void 0,
981
+ getSortedRowModel: enableSorting ? getSortedRowModel() : void 0,
982
+ getFilteredRowModel: enableFiltering ? getFilteredRowModel() : void 0,
983
+ onColumnVisibilityChange: enableColumnVisibility ? setColumnVisibility : void 0,
984
+ onRowSelectionChange: enableRowSelection ? setRowSelection : void 0,
985
+ onColumnOrderChange: setColumnOrder,
986
+ onColumnPinningChange: enableColumnPinning ? setColumnPinning : void 0,
987
+ state: {
988
+ sorting: enableSorting ? sorting : void 0,
989
+ columnFilters: enableFiltering ? columnFilters : void 0,
990
+ columnVisibility: enableColumnVisibility ? columnVisibility : void 0,
991
+ rowSelection: enableRowSelection ? rowSelection : {},
992
+ globalFilter,
993
+ columnOrder,
994
+ columnPinning: enableColumnPinning ? columnPinning : {}
995
+ },
996
+ initialState: {
997
+ pagination: pagination.enabled ? { pageSize: pagination.pageSize || 10 } : void 0,
998
+ columnPinning: enableColumnPinning ? {
999
+ left: [
1000
+ ...showSerialNumbers ? ["serialNumber"] : [],
1001
+ ...enableRowSelection ? ["select"] : []
1002
+ ],
1003
+ right: []
1004
+ } : void 0
1005
+ },
1006
+ enableRowSelection,
1007
+ enableColumnResizing,
1008
+ enableColumnPinning,
1009
+ columnResizeMode: "onChange"
1010
+ });
1011
+ useEffect(() => {
1012
+ if (onTableReady) {
1013
+ onTableReady(table);
1014
+ }
1015
+ }, [table, onTableReady]);
1016
+ useEffect(() => {
1017
+ if (enableRowSelection && onRowSelectionChange) {
1018
+ const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
1019
+ onRowSelectionChange(selectedRows);
1020
+ }
1021
+ }, [rowSelection, enableRowSelection, onRowSelectionChange, table]);
1022
+ const handleClearSorting = useCallback(() => {
1023
+ setSorting([]);
1024
+ }, []);
1025
+ const handleClearFilters = useCallback(() => {
1026
+ setColumnFilters([]);
1027
+ setGlobalFilter("");
1028
+ }, []);
1029
+ const handlePinColumn = (columnId, side) => {
1030
+ if (!enableColumnPinning) return;
1031
+ const alwaysPinnedLeft = [
1032
+ ...showSerialNumbers ? ["serialNumber"] : [],
1033
+ ...enableRowSelection && fixedCheckboxColumn ? ["select"] : []
1034
+ ];
1035
+ const newPinning = {
1036
+ left: [...(columnPinning.left ?? []).filter((id) => alwaysPinnedLeft.includes(id))],
1037
+ right: [...columnPinning.right ?? []]
1038
+ };
1039
+ if (side === false) {
1040
+ newPinning.left = newPinning.left.filter((id) => id !== columnId);
1041
+ newPinning.right = newPinning.right.filter((id) => id !== columnId);
1042
+ } else if (side === "right") {
1043
+ newPinning.left = newPinning.left.filter((id) => id !== columnId);
1044
+ if (!newPinning.right.includes(columnId)) {
1045
+ newPinning.right.push(columnId);
1046
+ }
1047
+ } else if (side === "left") {
1048
+ newPinning.right = newPinning.right.filter((id) => id !== columnId);
1049
+ if (!newPinning.left.includes(columnId) && !alwaysPinnedLeft.includes(columnId)) {
1050
+ newPinning.left.push(columnId);
1051
+ }
1052
+ }
1053
+ table.setColumnPinning(newPinning);
1054
+ };
1055
+ const renderTableHeader = () => /* @__PURE__ */ jsx12(TableHeader, { className: cn(
1056
+ stickyHeader && "sticky top-0 bg-sidebar z-20"
1057
+ ), children: table.getHeaderGroups().map((headerGroup, groupIndex) => /* @__PURE__ */ jsx12(TableRow, { className: "hover:bg-transparent", children: headerGroup.headers.map((header2, index) => {
1058
+ const isGroupHeader = header2.depth === 0 && header2.colSpan > 1;
1059
+ const isPinnedLeft = enableColumnPinning && (header2.column.getIsPinned() === "left" || header2.column.id === "serialNumber" || header2.column.id === "select" && enableRowSelection);
1060
+ const isPinnedRight = enableColumnPinning && header2.column.getIsPinned() === "right";
1061
+ const canSort = header2.column.getCanSort();
1062
+ const canPin = enableColumnPinning && header2.column.columnDef.enablePinning !== false;
1063
+ const isSerialNumber = header2.column.id === "serialNumber";
1064
+ const isCheckbox = header2.column.id === "select";
1065
+ const alwaysPinned = isSerialNumber || isCheckbox && fixedCheckboxColumn;
1066
+ const headerAlign = header2.column.columnDef.headerAlign || "left";
1067
+ const flexJustify = {
1068
+ left: "justify-start",
1069
+ center: "justify-center",
1070
+ right: "justify-end"
1071
+ }[headerAlign];
1072
+ return /* @__PURE__ */ jsxs6(
1073
+ TableHead,
1074
+ {
1075
+ colSpan: header2.colSpan,
1076
+ className: cn(
1077
+ "font-semibold text-foreground bg-sidebar group px-0",
1078
+ !compact && "py-2",
1079
+ bordered && index < headerGroup.headers.length - 1 && "border-r",
1080
+ "relative",
1081
+ isPinnedLeft && "sticky left-0 z-15 bg-sidebar",
1082
+ isPinnedRight && "sticky right-0 z-15 bg-sidebar",
1083
+ (isSerialNumber || isCheckbox) && "sticky left-0 z-15 bg-sidebar",
1084
+ isGroupHeader ? "text-center" : "text-left"
1085
+ ),
1086
+ style: {
1087
+ width: header2.getSize() !== 150 ? header2.getSize() : "auto",
1088
+ minWidth: header2.getSize() !== 150 ? header2.getSize() : "auto",
1089
+ ...isPinnedLeft && {
1090
+ left: isSerialNumber ? 0 : isCheckbox ? showSerialNumbers ? table.getColumn("serialNumber")?.getSize() || 0 : 0 : getLeftOffset(header2.column)
1091
+ },
1092
+ ...isPinnedRight && { right: getRightOffset(header2.column) },
1093
+ ...isSerialNumber && { left: 0 }
1094
+ },
1095
+ children: [
1096
+ isGroupHeader ? /* @__PURE__ */ jsx12("div", { className: "flex items-center justify-center", children: flexRender(header2.column.columnDef.header, header2.getContext()) }) : /* @__PURE__ */ jsxs6("div", { className: cn("relative flex items-center w-full px-2", flexJustify), children: [
1097
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
1098
+ canSort && headerAlign === "right" && /* @__PURE__ */ jsx12("span", { className: "ml-1 order-2", children: header2.column.getIsSorted() && {
1099
+ asc: /* @__PURE__ */ jsx12(ChevronUp, { className: "h-4 w-4" }),
1100
+ desc: /* @__PURE__ */ jsx12(ChevronDown2, { className: "h-4 w-4" })
1101
+ }[header2.column.getIsSorted()] }),
1102
+ header2.isPlaceholder ? null : flexRender(header2.column.columnDef.header, header2.getContext()),
1103
+ canSort && headerAlign !== "right" && header2.column.getIsSorted() && /* @__PURE__ */ jsx12("span", { className: "ml-1 order-2", children: header2.column.getIsSorted() && {
1104
+ asc: /* @__PURE__ */ jsx12(ChevronUp, { className: "h-4 w-4" }),
1105
+ desc: /* @__PURE__ */ jsx12(ChevronDown2, { className: "h-4 w-4" })
1106
+ }[header2.column.getIsSorted()] })
1107
+ ] }),
1108
+ (canSort || canPin && !alwaysPinned) && /* @__PURE__ */ jsxs6(DropdownMenu, { children: [
1109
+ /* @__PURE__ */ jsx12(DropdownMenuTrigger, { asChild: true, className: cn(
1110
+ "absolute",
1111
+ headerAlign === "left" && "right-1",
1112
+ headerAlign === "center" && "right-1",
1113
+ headerAlign === "right" && "left-1"
1114
+ ), children: /* @__PURE__ */ jsx12(
1115
+ Toggle,
1116
+ {
1117
+ variant: "default",
1118
+ size: "sm",
1119
+ noBg: true,
1120
+ tabIndex: -1,
1121
+ className: "opacity-0 group-hover:opacity-70 hover:opacity-100 data-[state=open]:opacity-100",
1122
+ children: /* @__PURE__ */ jsx12(MoreHorizontal, { className: "h-4 w-4" })
1123
+ }
1124
+ ) }),
1125
+ /* @__PURE__ */ jsxs6(DropdownMenuContent, { align: "end", className: "w-48", children: [
1126
+ canSort && /* @__PURE__ */ jsxs6(Fragment2, { children: [
1127
+ /* @__PURE__ */ jsx12(DropdownMenuLabel, { children: "Sorting" }),
1128
+ /* @__PURE__ */ jsxs6(
1129
+ DropdownMenuItem,
1130
+ {
1131
+ onClick: () => header2.column.toggleSorting(false),
1132
+ children: [
1133
+ /* @__PURE__ */ jsx12(ChevronUp, { className: "mr-2 h-4 w-4" }),
1134
+ "Sort Ascending"
1135
+ ]
1136
+ }
1137
+ ),
1138
+ /* @__PURE__ */ jsxs6(
1139
+ DropdownMenuItem,
1140
+ {
1141
+ onClick: () => header2.column.toggleSorting(true),
1142
+ children: [
1143
+ /* @__PURE__ */ jsx12(ChevronDown2, { className: "mr-2 h-4 w-4" }),
1144
+ "Sort Descending"
1145
+ ]
1146
+ }
1147
+ ),
1148
+ /* @__PURE__ */ jsxs6(
1149
+ DropdownMenuItem,
1150
+ {
1151
+ onClick: () => header2.column.clearSorting(),
1152
+ disabled: !header2.column.getIsSorted(),
1153
+ children: [
1154
+ /* @__PURE__ */ jsx12(ChevronsUpDown, { className: "mr-2 h-4 w-4" }),
1155
+ "Clear Sort"
1156
+ ]
1157
+ }
1158
+ ),
1159
+ /* @__PURE__ */ jsx12(DropdownMenuSeparator, {})
1160
+ ] }),
1161
+ canPin && !alwaysPinned && /* @__PURE__ */ jsxs6(Fragment2, { children: [
1162
+ /* @__PURE__ */ jsx12(DropdownMenuLabel, { children: "Pin Column" }),
1163
+ /* @__PURE__ */ jsxs6(
1164
+ DropdownMenuItem,
1165
+ {
1166
+ onClick: () => handlePinColumn(header2.column.id, "right"),
1167
+ disabled: header2.column.getIsPinned() === "right",
1168
+ children: [
1169
+ /* @__PURE__ */ jsx12(MoveRightIcon, {}),
1170
+ "Pin Right"
1171
+ ]
1172
+ }
1173
+ ),
1174
+ /* @__PURE__ */ jsxs6(
1175
+ DropdownMenuItem,
1176
+ {
1177
+ onClick: () => handlePinColumn(header2.column.id, false),
1178
+ disabled: !header2.column.getIsPinned(),
1179
+ children: [
1180
+ /* @__PURE__ */ jsx12(PinOffIcon, {}),
1181
+ "Unpin"
1182
+ ]
1183
+ }
1184
+ )
1185
+ ] })
1186
+ ] })
1187
+ ] })
1188
+ ] }),
1189
+ enableColumnResizing && header2.column.getCanResize() && !isGroupHeader && header2.colSpan === 1 && /* @__PURE__ */ jsx12(
1190
+ "div",
1191
+ {
1192
+ className: "absolute right-0 top-0 h-full w-1 bg-border hover:bg-primary cursor-col-resize opacity-0 hover:opacity-100 transition-opacity",
1193
+ onMouseDown: header2.getResizeHandler()
1194
+ }
1195
+ )
1196
+ ]
1197
+ },
1198
+ header2.id
1199
+ );
1200
+ }) }, headerGroup.id)) });
1201
+ const getLeftOffset = (column) => {
1202
+ if (!enableColumnPinning) return void 0;
1203
+ let offset = 0;
1204
+ const pinnedLeftColumns = table.getLeftHeaderGroups()[0]?.headers || [];
1205
+ const alwaysPinnedColumns = [
1206
+ ...showSerialNumbers ? ["serialNumber"] : [],
1207
+ ...enableRowSelection ? ["select"] : []
1208
+ ];
1209
+ for (const col of pinnedLeftColumns) {
1210
+ if (col.id === column.id) break;
1211
+ if (alwaysPinnedColumns.includes(col.id)) {
1212
+ const column2 = table.getColumn(col.id);
1213
+ if (column2) {
1214
+ offset += column2.getSize();
1215
+ }
1216
+ }
1217
+ }
1218
+ return offset;
1219
+ };
1220
+ const getRightOffset = (column) => {
1221
+ if (!enableColumnPinning) return void 0;
1222
+ const pinnedRightIds = table.getState().columnPinning.right || [];
1223
+ const columnIndex = pinnedRightIds.indexOf(column.id);
1224
+ if (columnIndex === -1) return void 0;
1225
+ let offset = 0;
1226
+ for (let i = columnIndex + 1; i < pinnedRightIds.length; i++) {
1227
+ const col = table.getColumn(pinnedRightIds[i]);
1228
+ if (col) {
1229
+ offset += col.getSize();
1230
+ }
1231
+ }
1232
+ return offset;
1233
+ };
1234
+ if (error) {
1235
+ return /* @__PURE__ */ jsx12(Card, { className: "w-full rounded-xl shadow-sm", children: /* @__PURE__ */ jsx12(CardContent, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
1236
+ /* @__PURE__ */ jsx12("div", { className: "text-red-500 mb-3 text-2xl", children: "\u26A0\uFE0F" }),
1237
+ /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground mb-4", children: error }),
1238
+ onRefresh && /* @__PURE__ */ jsxs6(Button, { variant: "outline", size: "sm", onClick: onRefresh, className: "rounded-lg", children: [
1239
+ /* @__PURE__ */ jsx12(Loader2, { className: "mr-2 h-4 w-4" }),
1240
+ "Try Again"
1241
+ ] })
1242
+ ] }) }) });
1243
+ }
1244
+ return /* @__PURE__ */ jsx12(TooltipProvider, { children: /* @__PURE__ */ jsxs6("div", { className: cn("w-full space-y-2 flex flex-col h-full", className), children: [
1245
+ header && /* @__PURE__ */ jsx12(Card, { className: "rounded-2xl py-2 sticky top-0 z-20", children: /* @__PURE__ */ jsx12(CardContent, { className: "px-2", children: header }) }),
1246
+ toolbar && /* @__PURE__ */ jsx12(
1247
+ DataTableToolbar,
1248
+ {
1249
+ table,
1250
+ filters,
1251
+ globalFilter,
1252
+ onGlobalFilterChange: setGlobalFilter,
1253
+ enableGlobalFilter,
1254
+ onExport,
1255
+ onRefresh,
1256
+ loading,
1257
+ enableColumnVisibility,
1258
+ enableColumnPinning,
1259
+ data,
1260
+ onClearSorting: handleClearSorting,
1261
+ onClearFilters: handleClearFilters
1262
+ }
1263
+ ),
1264
+ /* @__PURE__ */ jsx12(Card, { className: cn("shadow-sm overflow-auto py-0", fullHeight && "flex-1"), children: /* @__PURE__ */ jsx12(CardContent, { className: "p-0 h-full", children: /* @__PURE__ */ jsxs6("div", { className: "relative flex flex-col h-full justify-between", children: [
1265
+ loading && /* @__PURE__ */ jsx12("div", { className: "absolute inset-0 bg-background/80 backdrop-blur-sm z-50 flex items-center justify-center rounded-xl", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3 bg-background/90 px-4 py-3 rounded-lg shadow-sm", children: [
1266
+ /* @__PURE__ */ jsx12(Loader2, { className: "size-5 animate-spin text-primary" }),
1267
+ /* @__PURE__ */ jsx12("span", { className: "text-sm font-medium text-muted-foreground", children: "Loading..." })
1268
+ ] }) }),
1269
+ /* @__PURE__ */ jsx12("div", { className: "relative rounded-t-xl overflow-auto border-b", children: /* @__PURE__ */ jsxs6(Table, { className: "border-collapse w-full", children: [
1270
+ !hideHeader && renderTableHeader(),
1271
+ /* @__PURE__ */ jsx12(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row, rowIndex) => /* @__PURE__ */ jsx12(
1272
+ TableRow,
1273
+ {
1274
+ "data-state": row.getIsSelected() && "selected",
1275
+ className: cn(
1276
+ hoverable && "hover:bg-muted/50",
1277
+ striped && rowIndex % 2 === 0 && "bg-muted/20",
1278
+ row.getIsSelected() && "bg-muted",
1279
+ "border-b last:border-b-0"
1280
+ ),
1281
+ children: row.getVisibleCells().map((cell, cellIndex) => {
1282
+ const isPinnedLeft = enableColumnPinning && (cell.column.getIsPinned() === "left" || cell.column.id === "serialNumber" || cell.column.id === "select" && enableRowSelection);
1283
+ const isPinnedRight = enableColumnPinning && cell.column.getIsPinned() === "right";
1284
+ const isSerialNumber = cell.column.id === "serialNumber";
1285
+ const isCheckbox = cell.column.id === "select";
1286
+ const alwaysPinned = isSerialNumber || isCheckbox && fixedCheckboxColumn;
1287
+ return /* @__PURE__ */ jsx12(
1288
+ TableCell,
1289
+ {
1290
+ className: cn(
1291
+ compact ? "py-2" : "py-4",
1292
+ bordered && cellIndex < row.getVisibleCells().length && "border-r",
1293
+ isPinnedLeft && "sticky left-0 z-10 bg-sidebar/97",
1294
+ isPinnedRight && "sticky right-0 z-10 bg-sidebar/97",
1295
+ isSerialNumber && "sticky left-0 z-10 bg-sidebar/97",
1296
+ "p-1"
1297
+ ),
1298
+ style: {
1299
+ width: cell.column.getSize() !== 150 ? cell.column.getSize() : "auto",
1300
+ minWidth: cell.column.getSize() !== 150 ? cell.column.getSize() : "auto",
1301
+ ...isPinnedLeft && {
1302
+ left: isSerialNumber ? 0 : isCheckbox ? showSerialNumbers ? table.getColumn("serialNumber")?.getSize() || 0 : 0 : getLeftOffset(cell.column)
1303
+ },
1304
+ ...isPinnedRight && { right: getRightOffset(cell.column) },
1305
+ ...isSerialNumber && { left: 0 }
1306
+ },
1307
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
1308
+ },
1309
+ cell.id
1310
+ );
1311
+ })
1312
+ },
1313
+ row.id
1314
+ )) : /* @__PURE__ */ jsx12(TableRow, { children: /* @__PURE__ */ jsx12(TableCell, { colSpan: columns.length, className: "h-32 text-center border-0", children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center gap-3", children: [
1315
+ /* @__PURE__ */ jsx12("div", { className: "text-muted-foreground text-5xl", children: "\u{1F4CB}" }),
1316
+ /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground font-medium", children: emptyMessage })
1317
+ ] }) }) }) })
1318
+ ] }) }),
1319
+ footer && /* @__PURE__ */ jsx12("div", { className: "sticky bottom-0 bg-sidebar w-full z-20", style: {
1320
+ width: "100%",
1321
+ minWidth: "fit-content"
1322
+ }, children: /* @__PURE__ */ jsx12(Table, { children: /* @__PURE__ */ jsx12(TableFooter, { children: /* @__PURE__ */ jsx12(TableRow, { className: "bg-sidebar", children: /* @__PURE__ */ jsx12(TableCell, { colSpan: columns.length, className: "p-2", children: footer }) }) }) }) })
1323
+ ] }) }) }),
1324
+ /* @__PURE__ */ jsx12(DataTablePagination, { table, config: pagination }),
1325
+ children && children(table)
1326
+ ] }) });
1327
+ }
1328
+
1329
+ // src/components/ui/separator.tsx
1330
+ import { Separator as SeparatorPrimitive } from "radix-ui";
1331
+ import { jsx as jsx13 } from "react/jsx-runtime";
1332
+ function Separator({
1333
+ className,
1334
+ orientation = "horizontal",
1335
+ decorative = true,
1336
+ ...props
1337
+ }) {
1338
+ return /* @__PURE__ */ jsx13(
1339
+ SeparatorPrimitive.Root,
1340
+ {
1341
+ "data-slot": "separator-root",
1342
+ decorative,
1343
+ orientation,
1344
+ className: cn(
1345
+ "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
1346
+ className
1347
+ ),
1348
+ ...props
1349
+ }
1350
+ );
1351
+ }
1352
+
1353
+ // src/components/data/data-table/data-table-action-bar.tsx
1354
+ import { Loader, X } from "lucide-react";
1355
+ import { AnimatePresence, motion } from "framer-motion";
1356
+ import * as React from "react";
1357
+ import * as ReactDOM from "react-dom";
1358
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1359
+ function DataTableActionBar({
1360
+ table,
1361
+ visible: visibleProp,
1362
+ container: containerProp,
1363
+ children,
1364
+ className,
1365
+ ...props
1366
+ }) {
1367
+ const [mounted, setMounted] = React.useState(false);
1368
+ React.useLayoutEffect(() => {
1369
+ setMounted(true);
1370
+ }, []);
1371
+ React.useEffect(() => {
1372
+ function onKeyDown(event) {
1373
+ if (event.key === "Escape" && table) {
1374
+ table.toggleAllRowsSelected(false);
1375
+ }
1376
+ }
1377
+ window.addEventListener("keydown", onKeyDown);
1378
+ return () => window.removeEventListener("keydown", onKeyDown);
1379
+ }, [table]);
1380
+ const container = containerProp ?? (mounted ? globalThis.document?.body : null);
1381
+ if (!container || !table) return null;
1382
+ const visible = visibleProp ?? table.getFilteredSelectedRowModel().rows.length > 0;
1383
+ return ReactDOM.createPortal(
1384
+ /* @__PURE__ */ jsx14(AnimatePresence, { children: visible && /* @__PURE__ */ jsx14(
1385
+ motion.div,
1386
+ {
1387
+ role: "toolbar",
1388
+ "aria-orientation": "horizontal",
1389
+ initial: { opacity: 0, y: 20 },
1390
+ animate: { opacity: 1, y: 0 },
1391
+ exit: { opacity: 0, y: 20 },
1392
+ transition: { duration: 0.3, ease: "easeInOut" },
1393
+ className: cn(
1394
+ "fixed inset-x-0 bottom-6 z-50 mx-auto flex w-fit flex-wrap items-center justify-center gap-2 rounded-xl border bg-primary/10 backdrop-blur-sm p-3 text-foreground ring-5 ring-primary/5",
1395
+ className
1396
+ ),
1397
+ ...props,
1398
+ children: /* @__PURE__ */ jsxs7(TooltipProvider, { children: [
1399
+ "1",
1400
+ children
1401
+ ] })
1402
+ }
1403
+ ) }),
1404
+ container
1405
+ );
1406
+ }
1407
+ function DataTableActionBarAction({
1408
+ size = "sm",
1409
+ tooltip,
1410
+ isPending,
1411
+ disabled,
1412
+ className,
1413
+ children,
1414
+ ...props
1415
+ }) {
1416
+ const trigger = /* @__PURE__ */ jsx14(
1417
+ Button,
1418
+ {
1419
+ variant: "secondary",
1420
+ size,
1421
+ className: cn(
1422
+ "gap-1.5 rounded-lg border border-secondary bg-secondary/50 hover:bg-secondary/70 transition-all duration-200",
1423
+ size === "icon" ? "size-8" : "h-8 px-3",
1424
+ className
1425
+ ),
1426
+ disabled: disabled || isPending,
1427
+ ...props,
1428
+ children: isPending ? /* @__PURE__ */ jsx14(Loader, { className: "animate-spin" }) : children
1429
+ }
1430
+ );
1431
+ if (!tooltip) return trigger;
1432
+ return /* @__PURE__ */ jsxs7(Tooltip, { children: [
1433
+ /* @__PURE__ */ jsx14(TooltipTrigger, { asChild: true, children: trigger }),
1434
+ /* @__PURE__ */ jsx14(
1435
+ TooltipContent,
1436
+ {
1437
+ sideOffset: 8,
1438
+ className: "rounded-lg border font-semibold text-foreground bg-secondary [&>span]:hidden",
1439
+ children: /* @__PURE__ */ jsx14("p", { children: tooltip })
1440
+ }
1441
+ )
1442
+ ] });
1443
+ }
1444
+ function DataTableActionBarSelection({ table }) {
1445
+ const onClearSelection = React.useCallback(() => {
1446
+ if (table) {
1447
+ table.toggleAllRowsSelected(false);
1448
+ }
1449
+ }, [table]);
1450
+ if (!table) return null;
1451
+ return /* @__PURE__ */ jsxs7("div", { className: "flex h-8 items-center rounded-lg border bg-muted/50 pr-1 pl-3", children: [
1452
+ /* @__PURE__ */ jsxs7("span", { className: "whitespace-nowrap text-sm font-medium", children: [
1453
+ table.getFilteredSelectedRowModel().rows.length,
1454
+ " selected"
1455
+ ] }),
1456
+ /* @__PURE__ */ jsx14(Separator, { orientation: "vertical", className: "mr-2 ml-3 data-[orientation=vertical]:h-4" }),
1457
+ /* @__PURE__ */ jsxs7(Tooltip, { children: [
1458
+ /* @__PURE__ */ jsx14(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx14(Button, { variant: "ghost", size: "icon", className: "size-6 rounded-md", onClick: onClearSelection, children: /* @__PURE__ */ jsx14(X, { className: "size-3.5" }) }) }),
1459
+ /* @__PURE__ */ jsxs7(
1460
+ TooltipContent,
1461
+ {
1462
+ sideOffset: 10,
1463
+ className: "flex items-center gap-2 rounded-lg border px-3 py-2 font-semibold text-foregroun bg-secondary [&>span]:hidden",
1464
+ children: [
1465
+ /* @__PURE__ */ jsx14("p", { children: "Clear selection" }),
1466
+ /* @__PURE__ */ jsx14("kbd", { className: "select-none rounded border bg-primary/50 px-2 py-1 font-mono font-normal text-[0.7rem] text-foreground shadow-sm", children: /* @__PURE__ */ jsx14("abbr", { title: "Escape", className: "no-underline", children: "Esc" }) })
1467
+ ]
1468
+ }
1469
+ )
1470
+ ] })
1471
+ ] });
1472
+ }
1473
+
1474
+ // src/components/data/data-table/data-table-column-header.tsx
1475
+ import { ArrowUpDown as ArrowUpDown2, EyeOff } from "lucide-react";
1476
+ import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1477
+
1478
+ // src/components/data/data-table/data-table-view-options.tsx
1479
+ import { ChevronDown as ChevronDown3, Eye } from "lucide-react";
1480
+ import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
1481
+
1482
+ // src/components/ui/badge.tsx
1483
+ import { Slot as SlotPrimitive2 } from "radix-ui";
1484
+ import { cva as cva3 } from "class-variance-authority";
1485
+ import { jsx as jsx17 } from "react/jsx-runtime";
1486
+ var badgeVariants = cva3(
1487
+ "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
1488
+ {
1489
+ variants: {
1490
+ variant: {
1491
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
1492
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
1493
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
1494
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
1495
+ }
1496
+ },
1497
+ defaultVariants: {
1498
+ variant: "default"
1499
+ }
1500
+ }
1501
+ );
1502
+
1503
+ // src/components/ui/command.tsx
1504
+ import { Command as CommandPrimitive } from "cmdk";
1505
+ import { SearchIcon } from "lucide-react";
1506
+
1507
+ // src/components/ui/dialog.tsx
1508
+ import { Dialog as DialogPrimitive } from "radix-ui";
1509
+ import { XIcon } from "lucide-react";
1510
+ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
1511
+
1512
+ // src/components/ui/command.tsx
1513
+ import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
1514
+
1515
+ // src/components/ui/popover.tsx
1516
+ import { Popover as PopoverPrimitive } from "radix-ui";
1517
+ import { jsx as jsx20 } from "react/jsx-runtime";
1518
+
1519
+ // src/components/data/data-table/data-table-faceted-filter.tsx
1520
+ import { CheckIcon as CheckIcon4, PlusCircleIcon } from "lucide-react";
1521
+ import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
1522
+
1523
+ // src/components/data/data-template/data-template.tsx
1524
+ import { useState as useState3, useEffect as useEffect3, useMemo as useMemo2, useCallback as useCallback3, useRef } from "react";
1525
+ import { Loader2 as Loader22 } from "lucide-react";
1526
+
1527
+ // src/components/data/data-template/data-template-toolbar.tsx
1528
+ import { Search as Search2, Download as Download2, RefreshCw as RefreshCw2, Filter as Filter2, ChevronDown as ChevronDown4, Settings2 as Settings22 } from "lucide-react";
1529
+ import { Fragment as Fragment4, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
1530
+ function DataTemplateToolbar({
1531
+ fields,
1532
+ filters,
1533
+ globalFilter,
1534
+ onGlobalFilterChange,
1535
+ fieldFilters,
1536
+ onFieldFilterChange,
1537
+ sortField,
1538
+ sortDirection,
1539
+ onSortChange,
1540
+ selectedCount,
1541
+ totalCount,
1542
+ visibleCount,
1543
+ onExport,
1544
+ onRefresh,
1545
+ loading,
1546
+ onClearFilters,
1547
+ onClearSorting
1548
+ }) {
1549
+ const sortableFields = fields.filter((field) => field.sortable);
1550
+ const hasActiveFilters = Object.values(fieldFilters).some((value) => value !== void 0 && value !== null && value !== "") || globalFilter !== "";
1551
+ const hasActiveSorting = sortField !== "";
1552
+ return /* @__PURE__ */ jsx22("div", { className: "rounded-xl p-0.5", children: /* @__PURE__ */ jsx22("div", { className: "px-2", children: /* @__PURE__ */ jsx22("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
1553
+ /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-3", children: filters.length > 0 && /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-3 flex-wrap", children: [
1554
+ /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: /* @__PURE__ */ jsx22(Filter2, { className: "h-4 w-4" }) }),
1555
+ filters.map((filter) => /* @__PURE__ */ jsx22("div", { className: "relative min-w-[150px]", children: filter.type === "select" ? /* @__PURE__ */ jsxs13(
1556
+ Select,
1557
+ {
1558
+ value: fieldFilters[filter.key] || "all",
1559
+ onValueChange: (value) => onFieldFilterChange(filter.key, value),
1560
+ children: [
1561
+ filter.icon && /* @__PURE__ */ jsx22(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }),
1562
+ /* @__PURE__ */ jsx22(SelectTrigger, { className: cn("h-9 rounded-lg w-full", filter.icon && "pl-9"), children: /* @__PURE__ */ jsx22(SelectValue, { placeholder: filter.placeholder || "Select..." }) }),
1563
+ /* @__PURE__ */ jsxs13(SelectContent, { className: "rounded-lg", children: [
1564
+ /* @__PURE__ */ jsx22(SelectItem, { value: "all", children: "All" }),
1565
+ filter.options?.map((option) => /* @__PURE__ */ jsx22(SelectItem, { value: option.value, children: option.label }, option.value))
1566
+ ] })
1567
+ ]
1568
+ }
1569
+ ) : /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
1570
+ filter.icon && /* @__PURE__ */ jsx22(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }),
1571
+ /* @__PURE__ */ jsx22(
1572
+ Input,
1573
+ {
1574
+ type: filter.type,
1575
+ placeholder: filter.placeholder,
1576
+ value: fieldFilters[filter.key] || "",
1577
+ onChange: (e) => onFieldFilterChange(filter.key, e.target.value),
1578
+ className: cn("h-9 rounded-lg", filter.icon && "pl-9")
1579
+ }
1580
+ )
1581
+ ] }) }, String(filter.key)))
1582
+ ] }) }),
1583
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1584
+ /* @__PURE__ */ jsxs13("div", { className: "relative", children: [
1585
+ /* @__PURE__ */ jsx22(Search2, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
1586
+ /* @__PURE__ */ jsx22(
1587
+ Input,
1588
+ {
1589
+ placeholder: "Global search...",
1590
+ value: globalFilter,
1591
+ onChange: (e) => onGlobalFilterChange(e.target.value),
1592
+ className: "pl-9 h-9 rounded-lg max-w-max"
1593
+ }
1594
+ )
1595
+ ] }),
1596
+ sortableFields.length > 0 && /* @__PURE__ */ jsxs13(DropdownMenu, { children: [
1597
+ /* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs13(Button, { variant: "outline", size: "sm", className: "rounded-lg gap-1", children: [
1598
+ /* @__PURE__ */ jsx22("span", { children: "Sort" }),
1599
+ /* @__PURE__ */ jsx22(ChevronDown4, { className: "h-4 w-4 opacity-50" })
1600
+ ] }) }),
1601
+ /* @__PURE__ */ jsxs13(DropdownMenuContent, { align: "end", className: "w-[200px] rounded-lg", children: [
1602
+ /* @__PURE__ */ jsx22(DropdownMenuLabel, { children: "Sort By" }),
1603
+ /* @__PURE__ */ jsx22(DropdownMenuSeparator, {}),
1604
+ sortableFields.map((field) => /* @__PURE__ */ jsxs13("div", { children: [
1605
+ /* @__PURE__ */ jsxs13(DropdownMenuItem, { onClick: () => onSortChange(field.key, "asc"), children: [
1606
+ field.label,
1607
+ " (A-Z)"
1608
+ ] }),
1609
+ /* @__PURE__ */ jsxs13(DropdownMenuItem, { onClick: () => onSortChange(field.key, "desc"), children: [
1610
+ field.label,
1611
+ " (Z-A)"
1612
+ ] })
1613
+ ] }, String(field.key))),
1614
+ hasActiveSorting && /* @__PURE__ */ jsxs13(Fragment4, { children: [
1615
+ /* @__PURE__ */ jsx22(DropdownMenuSeparator, {}),
1616
+ /* @__PURE__ */ jsx22(DropdownMenuItem, { onClick: onClearSorting, children: "Clear All Sorting" })
1617
+ ] })
1618
+ ] })
1619
+ ] }),
1620
+ /* @__PURE__ */ jsxs13(DropdownMenu, { children: [
1621
+ /* @__PURE__ */ jsx22(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx22(Button, { variant: "outline", size: "sm", className: "rounded-lg", children: /* @__PURE__ */ jsx22(Settings22, { className: "h-4 w-4" }) }) }),
1622
+ /* @__PURE__ */ jsxs13(DropdownMenuContent, { align: "end", className: "w-[200px] rounded-lg", children: [
1623
+ /* @__PURE__ */ jsx22(DropdownMenuLabel, { children: "Table Settings" }),
1624
+ /* @__PURE__ */ jsx22(DropdownMenuSeparator, {}),
1625
+ /* @__PURE__ */ jsx22(DropdownMenuItem, { onClick: onClearSorting, children: "Clear All Sorting" }),
1626
+ /* @__PURE__ */ jsx22(DropdownMenuItem, { onClick: onClearFilters, children: "Clear All Filters" })
1627
+ ] })
1628
+ ] }),
1629
+ onExport && /* @__PURE__ */ jsxs13(Button, { variant: "outline", size: "sm", onClick: onExport, className: "rounded-lg", children: [
1630
+ /* @__PURE__ */ jsx22(Download2, { className: "mr-2 h-4 w-4" }),
1631
+ "Export"
1632
+ ] }),
1633
+ onRefresh && /* @__PURE__ */ jsx22(
1634
+ Button,
1635
+ {
1636
+ variant: "outline",
1637
+ size: "sm",
1638
+ onClick: onRefresh,
1639
+ disabled: loading,
1640
+ className: "rounded-lg",
1641
+ children: /* @__PURE__ */ jsx22(RefreshCw2, { className: cn("h-4 w-4", loading && "animate-spin") })
1642
+ }
1643
+ )
1644
+ ] })
1645
+ ] }) }) }) });
1646
+ }
1647
+
1648
+ // src/components/data/data-template/data-template-pagination.tsx
1649
+ import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react";
1650
+ import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
1651
+ function DataTemplatePagination({
1652
+ currentPage,
1653
+ totalPages,
1654
+ pageSize,
1655
+ totalItems,
1656
+ onPageChange,
1657
+ onPageSizeChange,
1658
+ config
1659
+ }) {
1660
+ if (!config.enabled) {
1661
+ return null;
1662
+ }
1663
+ const pageSizeOptions = config.pageSizeOptions || [10, 20, 50, 100];
1664
+ const startItem = (currentPage - 1) * pageSize + 1;
1665
+ const endItem = Math.min(currentPage * pageSize, totalItems);
1666
+ const canPreviousPage = currentPage > 1;
1667
+ const canNextPage = currentPage < totalPages;
1668
+ const getPageNumbers = () => {
1669
+ const delta = 2;
1670
+ const range = [];
1671
+ const rangeWithDots = [];
1672
+ for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) {
1673
+ range.push(i);
1674
+ }
1675
+ if (currentPage - delta > 2) {
1676
+ rangeWithDots.push(1, "...");
1677
+ } else {
1678
+ rangeWithDots.push(1);
1679
+ }
1680
+ rangeWithDots.push(...range);
1681
+ if (currentPage + delta < totalPages - 1) {
1682
+ rangeWithDots.push("...", totalPages);
1683
+ } else if (totalPages > 1) {
1684
+ rangeWithDots.push(totalPages);
1685
+ }
1686
+ return rangeWithDots;
1687
+ };
1688
+ return /* @__PURE__ */ jsx23("div", { className: "rounded-xl", children: /* @__PURE__ */ jsxs14("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-4", children: [
1689
+ /* @__PURE__ */ jsx23("div", { className: "flex items-center gap-6 text-sm text-muted-foreground", children: config.showInfo !== false && /* @__PURE__ */ jsxs14("span", { children: [
1690
+ "Showing ",
1691
+ startItem,
1692
+ " to ",
1693
+ endItem,
1694
+ " of ",
1695
+ totalItems,
1696
+ " entries"
1697
+ ] }) }),
1698
+ /* @__PURE__ */ jsxs14("div", { className: "flex flex-col sm:flex-row items-center gap-4", children: [
1699
+ pageSizeOptions && /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
1700
+ /* @__PURE__ */ jsx23("span", { className: "text-sm font-medium whitespace-nowrap", children: "Page size:" }),
1701
+ /* @__PURE__ */ jsxs14(Select, { value: `${pageSize}`, onValueChange: (value) => onPageSizeChange(Number(value)), children: [
1702
+ /* @__PURE__ */ jsx23(SelectTrigger, { className: "h-9 w-[70px] rounded-lg", children: /* @__PURE__ */ jsx23(SelectValue, {}) }),
1703
+ /* @__PURE__ */ jsx23(SelectContent, { side: "top", className: "rounded-lg", children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx23(SelectItem, { value: `${size}`, children: size }, size)) })
1704
+ ] })
1705
+ ] }),
1706
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
1707
+ /* @__PURE__ */ jsxs14(
1708
+ Button,
1709
+ {
1710
+ variant: "outline",
1711
+ size: "sm",
1712
+ onClick: () => onPageChange(1),
1713
+ disabled: !canPreviousPage,
1714
+ className: "hidden sm:flex rounded-lg",
1715
+ children: [
1716
+ /* @__PURE__ */ jsx23(ChevronsLeft, { className: "h-4 w-4" }),
1717
+ /* @__PURE__ */ jsx23("span", { className: "sr-only", children: "Go to first page" })
1718
+ ]
1719
+ }
1720
+ ),
1721
+ /* @__PURE__ */ jsxs14(
1722
+ Button,
1723
+ {
1724
+ variant: "outline",
1725
+ size: "sm",
1726
+ onClick: () => onPageChange(currentPage - 1),
1727
+ disabled: !canPreviousPage,
1728
+ className: "rounded-lg",
1729
+ children: [
1730
+ /* @__PURE__ */ jsx23(ChevronLeft, { className: "h-4 w-4 sm:mr-2" }),
1731
+ /* @__PURE__ */ jsx23("span", { className: "hidden sm:inline", children: "Previous" }),
1732
+ /* @__PURE__ */ jsx23("span", { className: "sr-only sm:hidden", children: "Go to previous page" })
1733
+ ]
1734
+ }
1735
+ ),
1736
+ config.showPageNumbers && totalPages > 1 && /* @__PURE__ */ jsx23("div", { className: "hidden sm:flex items-center gap-1", children: getPageNumbers().map((pageNumber, index) => {
1737
+ if (pageNumber === "...") {
1738
+ return /* @__PURE__ */ jsx23("span", { className: "px-2 py-1 text-sm text-muted-foreground", children: "..." }, `dots-${index}`);
1739
+ }
1740
+ const page = pageNumber;
1741
+ return /* @__PURE__ */ jsx23(
1742
+ Button,
1743
+ {
1744
+ variant: page === currentPage ? "default" : "outline",
1745
+ size: "sm",
1746
+ className: "w-9 h-9 p-0 rounded-lg",
1747
+ onClick: () => onPageChange(page),
1748
+ children: page
1749
+ },
1750
+ page
1751
+ );
1752
+ }) }),
1753
+ /* @__PURE__ */ jsxs14("div", { className: "sm:hidden flex items-center gap-2 px-3 py-1 text-sm font-medium bg-muted rounded-lg", children: [
1754
+ currentPage,
1755
+ " of ",
1756
+ totalPages
1757
+ ] }),
1758
+ /* @__PURE__ */ jsxs14(
1759
+ Button,
1760
+ {
1761
+ variant: "outline",
1762
+ size: "sm",
1763
+ onClick: () => onPageChange(currentPage + 1),
1764
+ disabled: !canNextPage,
1765
+ className: "rounded-lg",
1766
+ children: [
1767
+ /* @__PURE__ */ jsx23("span", { className: "hidden sm:inline", children: "Next" }),
1768
+ /* @__PURE__ */ jsx23(ChevronRight, { className: "h-4 w-4 sm:ml-2" }),
1769
+ /* @__PURE__ */ jsx23("span", { className: "sr-only sm:hidden", children: "Go to next page" })
1770
+ ]
1771
+ }
1772
+ ),
1773
+ /* @__PURE__ */ jsxs14(
1774
+ Button,
1775
+ {
1776
+ variant: "outline",
1777
+ size: "sm",
1778
+ onClick: () => onPageChange(totalPages),
1779
+ disabled: !canNextPage,
1780
+ className: "hidden sm:flex rounded-lg",
1781
+ children: [
1782
+ /* @__PURE__ */ jsx23(ChevronsRight, { className: "h-4 w-4" }),
1783
+ /* @__PURE__ */ jsx23("span", { className: "sr-only", children: "Go to last page" })
1784
+ ]
1785
+ }
1786
+ )
1787
+ ] })
1788
+ ] })
1789
+ ] }) });
1790
+ }
1791
+
1792
+ // src/components/data/data-template/data-template.tsx
1793
+ import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
1794
+ function DataTemplate({
1795
+ data,
1796
+ template,
1797
+ fields = [],
1798
+ filters = [],
1799
+ pagination = { enabled: false },
1800
+ settings = {},
1801
+ header,
1802
+ footer,
1803
+ className = "",
1804
+ loading = false,
1805
+ error,
1806
+ emptyMessage = "No items found",
1807
+ emptyIcon,
1808
+ onSelectionChange,
1809
+ onExport,
1810
+ onRefresh,
1811
+ onTemplateReady,
1812
+ children
1813
+ }) {
1814
+ const {
1815
+ enableSorting = true,
1816
+ enableFiltering = true,
1817
+ enableGlobalSearch = true,
1818
+ enableSelection = false,
1819
+ enableExport = false,
1820
+ toolbar = true,
1821
+ selectionMode = "multiple",
1822
+ gridCols = { default: 3, sm: 1, md: 2, lg: 3, xl: 4, "2xl": 6 },
1823
+ gap = 4,
1824
+ aspectRatio = "auto",
1825
+ minCardWidth = 350,
1826
+ maxCardWidth = 350
1827
+ } = settings;
1828
+ const [globalFilter, setGlobalFilter] = useState3("");
1829
+ const [fieldFilters, setFieldFilters] = useState3({});
1830
+ const [sortField, setSortField] = useState3("");
1831
+ const [sortDirection, setSortDirection] = useState3("asc");
1832
+ const [selectedItems, setSelectedItems] = useState3(/* @__PURE__ */ new Set());
1833
+ const [currentPage, setCurrentPage] = useState3(1);
1834
+ const [pageSize, setPageSize] = useState3(pagination.pageSize || 12);
1835
+ const [currentGridCols, setCurrentGridCols] = useState3(gridCols.default);
1836
+ const filteredAndSortedData = useMemo2(() => {
1837
+ let result = [...data];
1838
+ if (enableGlobalSearch && globalFilter) {
1839
+ const searchableFields = fields.filter((field) => field.searchable !== false);
1840
+ result = result.filter(
1841
+ (item) => searchableFields.some((field) => {
1842
+ const value = item[field.key];
1843
+ return value?.toString().toLowerCase().includes(globalFilter.toLowerCase());
1844
+ })
1845
+ );
1846
+ }
1847
+ if (enableFiltering) {
1848
+ Object.keys(fieldFilters).forEach((key) => {
1849
+ const value = fieldFilters[key];
1850
+ if (value !== void 0 && value !== null && value !== "") {
1851
+ const field = fields.find((f) => f.key === key);
1852
+ if (field) {
1853
+ result = result.filter((item) => {
1854
+ const itemValue = item[key];
1855
+ if (field.type === "boolean") {
1856
+ return itemValue === (value === "true");
1857
+ } else if (field.type === "number") {
1858
+ return itemValue === Number(value);
1859
+ } else {
1860
+ return itemValue?.toString().toLowerCase().includes(String(value).toLowerCase());
1861
+ }
1862
+ });
1863
+ }
1864
+ }
1865
+ });
1866
+ }
1867
+ if (enableSorting && sortField) {
1868
+ const field = fields.find((f) => f.key === sortField);
1869
+ if (field) {
1870
+ result.sort((a, b) => {
1871
+ const aValue = a[sortField];
1872
+ const bValue = b[sortField];
1873
+ if (field.type === "number") {
1874
+ return sortDirection === "asc" ? Number(aValue) - Number(bValue) : Number(bValue) - Number(aValue);
1875
+ } else if (field.type === "date") {
1876
+ const aDate = new Date(aValue);
1877
+ const bDate = new Date(bValue);
1878
+ return sortDirection === "asc" ? aDate.getTime() - bDate.getTime() : bDate.getTime() - aDate.getTime();
1879
+ } else {
1880
+ const aStr = String(aValue).toLowerCase();
1881
+ const bStr = String(bValue).toLowerCase();
1882
+ return sortDirection === "asc" ? aStr.localeCompare(bStr) : bStr.localeCompare(aStr);
1883
+ }
1884
+ });
1885
+ }
1886
+ }
1887
+ return result;
1888
+ }, [
1889
+ data,
1890
+ globalFilter,
1891
+ fieldFilters,
1892
+ sortField,
1893
+ sortDirection,
1894
+ fields,
1895
+ enableGlobalSearch,
1896
+ enableFiltering,
1897
+ enableSorting
1898
+ ]);
1899
+ const paginatedData = useMemo2(() => {
1900
+ if (!pagination.enabled) return filteredAndSortedData;
1901
+ const startIndex = (currentPage - 1) * pageSize;
1902
+ const endIndex = startIndex + pageSize;
1903
+ return filteredAndSortedData.slice(startIndex, endIndex);
1904
+ }, [filteredAndSortedData, currentPage, pageSize, pagination.enabled]);
1905
+ const totalPages = Math.ceil(filteredAndSortedData.length / pageSize);
1906
+ const handleToggleSelect = useCallback3(
1907
+ (index) => {
1908
+ if (!enableSelection) return;
1909
+ setSelectedItems((prev) => {
1910
+ const newSelection = new Set(prev);
1911
+ if (selectionMode === "single") {
1912
+ newSelection.clear();
1913
+ newSelection.add(index);
1914
+ } else {
1915
+ if (newSelection.has(index)) {
1916
+ newSelection.delete(index);
1917
+ } else {
1918
+ newSelection.add(index);
1919
+ }
1920
+ }
1921
+ return newSelection;
1922
+ });
1923
+ },
1924
+ [enableSelection, selectionMode]
1925
+ );
1926
+ const handleSelectAll = useCallback3(() => {
1927
+ if (!enableSelection || selectionMode === "single") return;
1928
+ if (selectedItems.size === filteredAndSortedData.length) {
1929
+ setSelectedItems(/* @__PURE__ */ new Set());
1930
+ } else {
1931
+ setSelectedItems(new Set(filteredAndSortedData.map((_, index) => index)));
1932
+ }
1933
+ }, [enableSelection, selectionMode, selectedItems.size, filteredAndSortedData.length]);
1934
+ const handleFieldFilterChange = useCallback3((key, value) => {
1935
+ setFieldFilters((prev) => ({ ...prev, [key]: value }));
1936
+ setCurrentPage(1);
1937
+ }, []);
1938
+ const handleSortChange = useCallback3((field, direction) => {
1939
+ setSortField(field);
1940
+ setSortDirection(direction);
1941
+ }, []);
1942
+ const handleClearFilters = useCallback3(() => {
1943
+ setGlobalFilter("");
1944
+ setFieldFilters({});
1945
+ setCurrentPage(1);
1946
+ }, []);
1947
+ const handleClearSorting = useCallback3(() => {
1948
+ setSortField("");
1949
+ setSortDirection("asc");
1950
+ }, []);
1951
+ const controller = useMemo2(
1952
+ () => ({
1953
+ getSelectedItems: () => Array.from(selectedItems).map((index) => filteredAndSortedData[index]),
1954
+ clearSelection: () => setSelectedItems(/* @__PURE__ */ new Set()),
1955
+ selectAll: handleSelectAll,
1956
+ getFilteredData: () => filteredAndSortedData,
1957
+ getTotalCount: () => data.length,
1958
+ getVisibleCount: () => filteredAndSortedData.length,
1959
+ refresh: () => onRefresh?.(),
1960
+ exportData: () => onExport?.(filteredAndSortedData)
1961
+ }),
1962
+ [selectedItems, filteredAndSortedData, data.length, handleSelectAll, onRefresh, onExport]
1963
+ );
1964
+ const controllerRef = useRef(null);
1965
+ controllerRef.current = controller;
1966
+ useEffect3(() => {
1967
+ if (onTemplateReady && controllerRef.current) {
1968
+ onTemplateReady(controllerRef.current);
1969
+ }
1970
+ }, []);
1971
+ useEffect3(() => {
1972
+ if (enableSelection && onSelectionChange) {
1973
+ const selected = Array.from(selectedItems).map((index) => filteredAndSortedData[index]);
1974
+ onSelectionChange(selected);
1975
+ }
1976
+ }, [selectedItems]);
1977
+ const gridContainerClasses = cn(
1978
+ "w-full",
1979
+ "overflow-hidden",
1980
+ // Prevent any potential overflow issues
1981
+ className
1982
+ );
1983
+ const gridClasses = cn(
1984
+ "grid",
1985
+ `gap-${gap}`,
1986
+ "w-full",
1987
+ // Ensure grid takes full width
1988
+ "mx-auto",
1989
+ // Center the grid if it doesn't take full width
1990
+ "items-start"
1991
+ // Align items to the top
1992
+ );
1993
+ const gridStyle = {
1994
+ // Primary grid definition - choose one of these options:
1995
+ gridTemplateColumns: currentGridCols === 0 ? `repeat(auto-fill, minmax(clamp(${minCardWidth}px, 30%, ${maxCardWidth}px), 1fr))` : `repeat(auto-fill, minmax(clamp(${minCardWidth}px, calc(100%/${currentGridCols} - ${gap * 4}px), ${maxCardWidth}px), 1fr))`,
1996
+ // gridTemplateColumns: `repeat(auto-fill, minmax(clamp(${minCardWidth}px, calc(100%/${Math.min(
1997
+ // currentGridCols,
1998
+ // gridCols["2xl"] || 6
1999
+ // )} - ${gap * 4}px), ${maxCardWidth}px))`,
2000
+ // Option 1: Fully fluid grid (recommended)
2001
+ // gridTemplateColumns: `repeat(auto-fill, minmax(clamp(${minCardWidth}px, 30%, ${maxCardWidth}px), 1fr))`,
2002
+ // Option 2: More controlled fluid grid
2003
+ // gridTemplateColumns: `repeat(auto-fit, minmax(clamp(${minCardWidth}px, 25vw, ${maxCardWidth}px), 1fr))`,
2004
+ // Option 3: Fixed maximum columns with fluid width
2005
+ // gridTemplateColumns: `repeat(min(6, auto-fill), minmax(${minCardWidth}px, ${maxCardWidth}px))`,
2006
+ // Additional grid enhancements
2007
+ justifyItems: "center",
2008
+ // Center items horizontally in their grid cells
2009
+ alignItems: "stretch",
2010
+ // Stretch items vertically to fill the grid cell
2011
+ gridAutoRows: "1fr",
2012
+ // Make all rows the same height
2013
+ gridAutoFlow: "dense"
2014
+ // Try to fill holes in the grid
2015
+ };
2016
+ if (error) {
2017
+ return /* @__PURE__ */ jsx24(Card, { className: "w-full", children: /* @__PURE__ */ jsx24(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxs15("div", { className: "text-center", children: [
2018
+ /* @__PURE__ */ jsx24("div", { className: "text-red-500 mb-3 text-2xl", children: "\u26A0\uFE0F" }),
2019
+ /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground mb-4", children: error }),
2020
+ onRefresh && /* @__PURE__ */ jsxs15(Button, { variant: "outline", size: "sm", onClick: onRefresh, children: [
2021
+ /* @__PURE__ */ jsx24(Loader22, { className: "mr-2 h-4 w-4" }),
2022
+ "Try Again"
2023
+ ] })
2024
+ ] }) }) });
2025
+ }
2026
+ return /* @__PURE__ */ jsxs15("div", { className: cn("w-full flex gap-2 flex-col h-full", gridContainerClasses), children: [
2027
+ header && /* @__PURE__ */ jsx24(Card, { className: "shadow-sm border-0 bg-gradient-to-r from-background to-muted/20", children: /* @__PURE__ */ jsx24(CardContent, { className: "p-6", children: header }) }),
2028
+ toolbar && /* @__PURE__ */ jsx24(
2029
+ DataTemplateToolbar,
2030
+ {
2031
+ fields,
2032
+ filters,
2033
+ globalFilter,
2034
+ onGlobalFilterChange: setGlobalFilter,
2035
+ fieldFilters,
2036
+ onFieldFilterChange: handleFieldFilterChange,
2037
+ sortField,
2038
+ sortDirection,
2039
+ onSortChange: handleSortChange,
2040
+ selectedCount: selectedItems.size,
2041
+ totalCount: data.length,
2042
+ visibleCount: filteredAndSortedData.length,
2043
+ onExport: enableExport ? () => onExport?.(filteredAndSortedData) : void 0,
2044
+ onRefresh,
2045
+ loading,
2046
+ onClearFilters: handleClearFilters,
2047
+ onClearSorting: handleClearSorting
2048
+ }
2049
+ ),
2050
+ /* @__PURE__ */ jsx24(Card, { className: "border-0 overflow-auto shadow-none py-0 p-2 flex-1", children: /* @__PURE__ */ jsx24(CardContent, { className: "px-0", children: /* @__PURE__ */ jsxs15("div", { className: "relative", children: [
2051
+ loading && /* @__PURE__ */ jsx24("div", { className: "absolute inset-0 bg-background/80 backdrop-blur-sm z-50 flex items-center justify-center rounded-lg", children: /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-3 bg-background/90 px-4 py-3 rounded-lg shadow-sm", children: [
2052
+ /* @__PURE__ */ jsx24(Loader22, { className: "size-5 animate-spin text-primary" }),
2053
+ /* @__PURE__ */ jsx24("span", { className: "text-sm font-medium text-muted-foreground", children: "Loading..." })
2054
+ ] }) }),
2055
+ paginatedData.length > 0 ? /* @__PURE__ */ jsx24(
2056
+ "div",
2057
+ {
2058
+ className: cn(gridClasses),
2059
+ style: gridStyle,
2060
+ children: paginatedData.map((item, index) => {
2061
+ const globalIndex = pagination.enabled ? (currentPage - 1) * pageSize + index : index;
2062
+ const isSelected = selectedItems.has(globalIndex);
2063
+ return /* @__PURE__ */ jsxs15(
2064
+ "div",
2065
+ {
2066
+ className: cn(
2067
+ "relative h-full w-full flex flex-col",
2068
+ "transition-all duration-200 overflow-hidden",
2069
+ "rounded-2xl",
2070
+ "border border-border/20 hover:border-border/50",
2071
+ aspectRatio === "square" ? "aspect-square" : "",
2072
+ aspectRatio === "video" ? "aspect-video" : "",
2073
+ enableSelection ? "cursor-pointer" : "",
2074
+ isSelected ? "ring-2 ring-primary" : ""
2075
+ ),
2076
+ onClick: () => enableSelection && handleToggleSelect(globalIndex),
2077
+ children: [
2078
+ enableSelection && selectionMode === "multiple" && /* @__PURE__ */ jsx24("div", { className: "absolute top-2 right-2 z-10", children: /* @__PURE__ */ jsx24(
2079
+ Checkbox,
2080
+ {
2081
+ checked: isSelected,
2082
+ onCheckedChange: () => handleToggleSelect(globalIndex),
2083
+ className: "bg-background/80 backdrop-blur-sm",
2084
+ onClick: (e) => e.stopPropagation()
2085
+ }
2086
+ ) }),
2087
+ template(item, index, isSelected, () => handleToggleSelect(globalIndex))
2088
+ ]
2089
+ },
2090
+ globalIndex
2091
+ );
2092
+ })
2093
+ }
2094
+ ) : /* @__PURE__ */ jsxs15("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
2095
+ /* @__PURE__ */ jsx24("div", { className: "text-6xl mb-4", children: emptyIcon || "\u{1F4CB}" }),
2096
+ /* @__PURE__ */ jsx24("p", { className: "text-lg font-medium text-muted-foreground mb-2", children: emptyMessage }),
2097
+ (globalFilter || Object.values(fieldFilters).some((v) => v)) && /* @__PURE__ */ jsx24(Button, { variant: "outline", onClick: handleClearFilters, children: "Clear Filters" })
2098
+ ] })
2099
+ ] }) }) }),
2100
+ pagination.enabled && /* @__PURE__ */ jsx24("div", { className: "pb-1", children: /* @__PURE__ */ jsx24(
2101
+ DataTemplatePagination,
2102
+ {
2103
+ currentPage,
2104
+ totalPages,
2105
+ pageSize,
2106
+ totalItems: filteredAndSortedData.length,
2107
+ onPageChange: setCurrentPage,
2108
+ onPageSizeChange: (size) => {
2109
+ setPageSize(size);
2110
+ setCurrentPage(1);
2111
+ },
2112
+ config: pagination
2113
+ }
2114
+ ) }),
2115
+ footer && /* @__PURE__ */ jsx24("div", { className: "p-2 m-0.5", children: footer }),
2116
+ children && children(controller)
2117
+ ] });
2118
+ }
2119
+
2120
+ // src/components/data/data-template/data-template-action-bar.tsx
2121
+ import { Loader as Loader3, X as X3 } from "lucide-react";
2122
+ import { AnimatePresence as AnimatePresence2, motion as motion2 } from "framer-motion";
2123
+ import * as React2 from "react";
2124
+ import * as ReactDOM2 from "react-dom";
2125
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
2126
+ function DataTemplateActionBar({
2127
+ controller,
2128
+ visible: visibleProp,
2129
+ container: containerProp,
2130
+ children,
2131
+ className,
2132
+ ...props
2133
+ }) {
2134
+ const [mounted, setMounted] = React2.useState(false);
2135
+ React2.useLayoutEffect(() => {
2136
+ setMounted(true);
2137
+ }, []);
2138
+ React2.useEffect(() => {
2139
+ function onKeyDown(event) {
2140
+ if (event.key === "Escape" && controller) {
2141
+ controller.clearSelection();
2142
+ }
2143
+ }
2144
+ window.addEventListener("keydown", onKeyDown);
2145
+ return () => window.removeEventListener("keydown", onKeyDown);
2146
+ }, [controller]);
2147
+ const container = containerProp ?? (mounted ? globalThis.document?.body : null);
2148
+ if (!container || !controller) return null;
2149
+ const selectedItems = controller.getSelectedItems();
2150
+ const visible = visibleProp ?? selectedItems.length > 0;
2151
+ return ReactDOM2.createPortal(
2152
+ /* @__PURE__ */ jsx25(AnimatePresence2, { children: visible && /* @__PURE__ */ jsx25(
2153
+ motion2.div,
2154
+ {
2155
+ role: "toolbar",
2156
+ "aria-orientation": "horizontal",
2157
+ initial: { opacity: 0, y: 20 },
2158
+ animate: { opacity: 1, y: 0 },
2159
+ exit: { opacity: 0, y: 20 },
2160
+ transition: { duration: 0.3, ease: "easeInOut" },
2161
+ className: cn(
2162
+ "fixed inset-x-0 bottom-6 z-50 mx-auto flex w-fit flex-wrap items-center justify-center gap-2 rounded-xl border bg-primary/10 backdrop-blur-sm p-3 text-foreground ring-8 ring-primary/5",
2163
+ className
2164
+ ),
2165
+ ...props,
2166
+ children: /* @__PURE__ */ jsx25(TooltipProvider, { children })
2167
+ }
2168
+ ) }),
2169
+ container
2170
+ );
2171
+ }
2172
+ function DataTemplateActionBarAction({
2173
+ size = "sm",
2174
+ variant = "secondary",
2175
+ tooltip,
2176
+ isPending,
2177
+ disabled,
2178
+ className,
2179
+ children,
2180
+ onClick,
2181
+ ...props
2182
+ }) {
2183
+ const trigger = /* @__PURE__ */ jsx25(
2184
+ Button,
2185
+ {
2186
+ variant,
2187
+ size,
2188
+ className: cn(
2189
+ "gap-1.5 rounded-lg border border-secondary bg-secondary/50 hover:bg-secondary/70 transition-all duration-200",
2190
+ size === "icon" ? "size-8" : "h-8 px-3",
2191
+ className
2192
+ ),
2193
+ disabled: disabled || isPending,
2194
+ onClick,
2195
+ ...props,
2196
+ children: isPending ? /* @__PURE__ */ jsx25(Loader3, { className: "animate-spin" }) : children
2197
+ }
2198
+ );
2199
+ if (!tooltip) return trigger;
2200
+ return /* @__PURE__ */ jsxs16(Tooltip, { children: [
2201
+ /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: trigger }),
2202
+ /* @__PURE__ */ jsx25(
2203
+ TooltipContent,
2204
+ {
2205
+ sideOffset: 8,
2206
+ className: "rounded-lg border font-semibold text-foreground bg-secondary [&>span]:hidden",
2207
+ children: /* @__PURE__ */ jsx25("p", { children: tooltip })
2208
+ }
2209
+ )
2210
+ ] });
2211
+ }
2212
+ function DataTemplateActionBarSelection({ controller }) {
2213
+ const onClearSelection = React2.useCallback(() => {
2214
+ if (controller) {
2215
+ controller.clearSelection();
2216
+ }
2217
+ }, [controller]);
2218
+ if (!controller) return null;
2219
+ const selectedItems = controller.getSelectedItems();
2220
+ return /* @__PURE__ */ jsxs16("div", { className: "flex h-8 items-center rounded-lg border bg-muted/50 pr-1 pl-3", children: [
2221
+ /* @__PURE__ */ jsxs16("span", { className: "whitespace-nowrap text-sm font-medium", children: [
2222
+ selectedItems.length,
2223
+ " selected"
2224
+ ] }),
2225
+ /* @__PURE__ */ jsx25(Separator, { orientation: "vertical", className: "mr-2 ml-3 data-[orientation=vertical]:h-4" }),
2226
+ /* @__PURE__ */ jsxs16(Tooltip, { children: [
2227
+ /* @__PURE__ */ jsx25(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx25(Button, { variant: "ghost", size: "icon", className: "size-6 rounded-md", onClick: onClearSelection, children: /* @__PURE__ */ jsx25(X3, { className: "size-3.5" }) }) }),
2228
+ /* @__PURE__ */ jsxs16(
2229
+ TooltipContent,
2230
+ {
2231
+ sideOffset: 10,
2232
+ className: "flex items-center gap-2 rounded-lg border px-3 py-2 font-semibold text-foreground bg-secondary [&>span]:hidden",
2233
+ children: [
2234
+ /* @__PURE__ */ jsx25("p", { children: "Clear selection" }),
2235
+ /* @__PURE__ */ jsx25("kbd", { className: "select-none rounded border bg-primary/50 px-2 py-1 font-mono font-normal text-[0.7rem] text-foreground shadow-sm", children: /* @__PURE__ */ jsx25("abbr", { title: "Escape", className: "no-underline", children: "Esc" }) })
2236
+ ]
2237
+ }
2238
+ )
2239
+ ] })
2240
+ ] });
2241
+ }
2242
+
2243
+ // src/components/layouts/app-container.tsx
2244
+ import { jsx as jsx26 } from "react/jsx-runtime";
2245
+ var spacingClasses = {
2246
+ "none": "gap-0",
2247
+ "tight": "gap-2",
2248
+ "default": "gap-4",
2249
+ "loose": "gap-6",
2250
+ "extra-loose": "gap-8"
2251
+ };
2252
+ var paddingClasses = {
2253
+ "none": "p-0",
2254
+ "tight": "p-2",
2255
+ "default": "p-4",
2256
+ "loose": "p-6"
2257
+ };
2258
+ var AppContainer = ({
2259
+ children,
2260
+ className,
2261
+ spacing = "tight",
2262
+ padding = "none"
2263
+ }) => {
2264
+ return /* @__PURE__ */ jsx26("div", { className: cn(
2265
+ "flex flex-col h-full",
2266
+ spacingClasses[spacing],
2267
+ paddingClasses[padding],
2268
+ className
2269
+ ), children });
2270
+ };
2271
+
2272
+ // src/components/layouts/app-header.tsx
2273
+ import { ArrowLeftIcon, ChevronRight as ChevronRight2 } from "lucide-react";
2274
+ import { jsx as jsx27, jsxs as jsxs17 } from "react/jsx-runtime";
2275
+ var AppHeader = ({
2276
+ className,
2277
+ columns = [],
2278
+ showBackButton = true,
2279
+ meta = { title: "" }
2280
+ }) => {
2281
+ const renderBackAction = () => {
2282
+ if (!meta.backAction || !showBackButton) return null;
2283
+ const buttonProps = {
2284
+ variant: "secondary",
2285
+ size: "icon",
2286
+ className: "hover:bg-primary/20 inline-flex"
2287
+ };
2288
+ if (meta.backAction.href) {
2289
+ return /* @__PURE__ */ jsxs17(Button, { ...buttonProps, children: [
2290
+ /* @__PURE__ */ jsx27(ArrowLeftIcon, { className: "size-6" }),
2291
+ meta.backAction.content
2292
+ ] });
2293
+ }
2294
+ return /* @__PURE__ */ jsxs17(Button, { ...buttonProps, onClick: meta.backAction.onClick, children: [
2295
+ /* @__PURE__ */ jsx27(ArrowLeftIcon, { className: "size-6" }),
2296
+ meta.backAction.content
2297
+ ] });
2298
+ };
2299
+ const renderMetadata = () => {
2300
+ if (!meta.metadata || meta.metadata.length === 0) return null;
2301
+ return /* @__PURE__ */ jsx27("div", { className: "flex gap-4", children: meta.metadata.map((item, index) => item.value && /* @__PURE__ */ jsxs17("div", { className: "text-sm", children: [
2302
+ /* @__PURE__ */ jsxs17("span", { className: "text-muted-foreground", children: [
2303
+ item.label,
2304
+ " "
2305
+ ] }),
2306
+ /* @__PURE__ */ jsx27("span", { children: item.value })
2307
+ ] }, index)) });
2308
+ };
2309
+ const renderStatus = () => {
2310
+ if (!meta.status) return null;
2311
+ const colorClasses = {
2312
+ success: "bg-green-100 text-green-800",
2313
+ warning: "bg-yellow-100 text-yellow-800",
2314
+ critical: "bg-red-100 text-red-800",
2315
+ info: "bg-blue-100 text-blue-800",
2316
+ default: "bg-gray-100 text-gray-800"
2317
+ };
2318
+ return /* @__PURE__ */ jsx27("span", { className: cn(
2319
+ "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium",
2320
+ colorClasses[meta.status.color]
2321
+ ), children: meta.status.content });
2322
+ };
2323
+ const reservedColumn = {
2324
+ content: /* @__PURE__ */ jsxs17("div", { className: "flex gap-2 items-center", children: [
2325
+ renderBackAction(),
2326
+ /* @__PURE__ */ jsxs17("div", { className: "flex flex-col gap-2 w-max", children: [
2327
+ /* @__PURE__ */ jsx27("h1", { className: "text-2xl font-bold tracking-tight", children: meta.title }),
2328
+ renderStatus(),
2329
+ meta.description && /* @__PURE__ */ jsx27("p", { className: "text-muted-foreground", children: meta.description }),
2330
+ renderMetadata(),
2331
+ meta.breadcrumbs && meta.breadcrumbs.length > 0 && /* @__PURE__ */ jsx27("div", { className: "flex items-center text-sm text-muted-foreground", children: meta.breadcrumbs.map((crumb, index) => /* @__PURE__ */ jsxs17("div", { className: "flex items-center", children: [
2332
+ crumb.href ? /* @__PURE__ */ jsx27("span", { className: "hover:text-primary hover:underline", children: crumb.label }) : /* @__PURE__ */ jsx27("span", { children: crumb.label }),
2333
+ index < meta.breadcrumbs.length - 1 && /* @__PURE__ */ jsx27(ChevronRight2, { className: "mx-2 h-4 w-4" })
2334
+ ] }, index)) })
2335
+ ] })
2336
+ ] }),
2337
+ align: "left",
2338
+ width: "fill"
2339
+ };
2340
+ const actionsColumn = {
2341
+ content: meta.primaryActions,
2342
+ align: "right",
2343
+ width: "auto"
2344
+ };
2345
+ const allColumns = [
2346
+ reservedColumn,
2347
+ ...columns.filter((col) => col !== void 0),
2348
+ actionsColumn
2349
+ ];
2350
+ return /* @__PURE__ */ jsx27("div", { className: cn("flex items-center w-full gap-4 p-2", className), children: allColumns.map((column, index) => /* @__PURE__ */ jsx27(
2351
+ "div",
2352
+ {
2353
+ className: cn(
2354
+ "flex items-center h-full",
2355
+ column.className,
2356
+ {
2357
+ "justify-start": column.align === "left",
2358
+ "justify-center": column.align === "center",
2359
+ "justify-end": column.align === "right",
2360
+ "flex-1": column.width === "fill"
2361
+ }
2362
+ ),
2363
+ children: column.content
2364
+ },
2365
+ index
2366
+ )) });
2367
+ };
2368
+
2369
+ // src/components/layouts/app-content.tsx
2370
+ import React3, { useState as useState5, createContext, useContext } from "react";
2371
+
2372
+ // src/components/ui/sheet.tsx
2373
+ import { Dialog as SheetPrimitive } from "radix-ui";
2374
+ import { XIcon as XIcon2 } from "lucide-react";
2375
+ import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
2376
+ function Sheet({ ...props }) {
2377
+ return /* @__PURE__ */ jsx28(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
2378
+ }
2379
+ function SheetTrigger({
2380
+ ...props
2381
+ }) {
2382
+ return /* @__PURE__ */ jsx28(SheetPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
2383
+ }
2384
+ function SheetPortal({
2385
+ ...props
2386
+ }) {
2387
+ return /* @__PURE__ */ jsx28(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
2388
+ }
2389
+ function SheetOverlay({
2390
+ className,
2391
+ ...props
2392
+ }) {
2393
+ return /* @__PURE__ */ jsx28(
2394
+ SheetPrimitive.Overlay,
2395
+ {
2396
+ "data-slot": "sheet-overlay",
2397
+ className: cn(
2398
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
2399
+ className
2400
+ ),
2401
+ ...props
2402
+ }
2403
+ );
2404
+ }
2405
+ function SheetContent({
2406
+ className,
2407
+ children,
2408
+ side = "right",
2409
+ ...props
2410
+ }) {
2411
+ return /* @__PURE__ */ jsxs18(SheetPortal, { children: [
2412
+ /* @__PURE__ */ jsx28(SheetOverlay, {}),
2413
+ /* @__PURE__ */ jsxs18(
2414
+ SheetPrimitive.Content,
2415
+ {
2416
+ "data-slot": "sheet-content",
2417
+ className: cn(
2418
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
2419
+ side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
2420
+ side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
2421
+ side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
2422
+ side === "bottom" && "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
2423
+ className
2424
+ ),
2425
+ ...props,
2426
+ children: [
2427
+ children,
2428
+ /* @__PURE__ */ jsxs18(SheetPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none", children: [
2429
+ /* @__PURE__ */ jsx28(XIcon2, { className: "size-4" }),
2430
+ /* @__PURE__ */ jsx28("span", { className: "sr-only", children: "Close" })
2431
+ ] })
2432
+ ]
2433
+ }
2434
+ )
2435
+ ] });
2436
+ }
2437
+
2438
+ // src/components/layouts/app-content.tsx
2439
+ import { jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
2440
+ var AppContentContext = createContext(false);
2441
+ var splitRatioClasses = {
2442
+ "one-half": ["w-1/2", "w-1/2"],
2443
+ "one-third": ["w-1/3", "w-2/3"],
2444
+ "two-third": ["w-2/3", "w-1/3"],
2445
+ "one-fourth": ["w-1/4", "w-3/4"],
2446
+ "three-fourth": ["w-3/4", "w-1/4"],
2447
+ "one-fifth": ["w-1/5", "w-4/5"],
2448
+ "four-fifth": ["w-4/5", "w-1/5"]
2449
+ };
2450
+ var paddingClasses2 = {
2451
+ none: "p-0",
2452
+ tight: "p-2",
2453
+ default: "p-4",
2454
+ loose: "p-6"
2455
+ };
2456
+ var getContainerSheetClasses = (side, width) => {
2457
+ const [contentWidth, sheetWidth] = splitRatioClasses[width];
2458
+ return {
2459
+ container: "inset-y-0 z-50 transition-all duration-500 ease-in-out",
2460
+ content: cn(
2461
+ "h-full bg-background transition-all duration-500 ease-in-out",
2462
+ side === "right" ? "border-l" : "border-r"
2463
+ ),
2464
+ transform: side === "right" ? "translate-x-full" : "-translate-x-full",
2465
+ transformOpen: "translate-x-0",
2466
+ contentPushClass: side === "right" ? contentWidth : sheetWidth,
2467
+ sheetPushClass: side === "right" ? sheetWidth : contentWidth
2468
+ };
2469
+ };
2470
+ var baseClasses = "flex flex-col overflow-hidden rounded-2xl relative";
2471
+ var variantClasses = {
2472
+ default: "bg-background",
2473
+ card: "bg-background shadow-sm border",
2474
+ border: "bg-background border-2",
2475
+ transparent: "bg-transparent"
2476
+ };
2477
+ var AppContent = (props) => {
2478
+ const {
2479
+ children,
2480
+ className,
2481
+ variant = "default",
2482
+ layout = "full",
2483
+ header,
2484
+ footer,
2485
+ headerClassName,
2486
+ footerClassName,
2487
+ parentContainer = false,
2488
+ padding = parentContainer ? "none" : "tight"
2489
+ } = props;
2490
+ const isNested = useContext(AppContentContext);
2491
+ const [internalSheetOpen, setInternalSheetOpen] = useState5(false);
2492
+ const contentWrapper = React3.useCallback(
2493
+ (content) => /* @__PURE__ */ jsx29("div", { className: cn(
2494
+ "flex-1 overflow-auto h-full no-scrollbar",
2495
+ parentContainer && "flex",
2496
+ !parentContainer && paddingClasses2[padding]
2497
+ ), children: content }),
2498
+ [padding, parentContainer]
2499
+ );
2500
+ const renderContent = () => {
2501
+ switch (layout) {
2502
+ case "split": {
2503
+ const { splitRatio = "three-fourth", reverse = false } = props;
2504
+ if (!Array.isArray(children) || children.length !== 2) {
2505
+ return /* @__PURE__ */ jsx29("div", { className: "flex items-center justify-center h-full text-red-500", children: 'Error: AppContent with layout="split" requires exactly 2 children' });
2506
+ }
2507
+ const [leftClass, rightClass] = splitRatioClasses[splitRatio];
2508
+ const [firstChild, secondChild] = reverse ? [children[1], children[0]] : [children[0], children[1]];
2509
+ const [firstClass, secondClass] = reverse ? [rightClass, leftClass] : [leftClass, rightClass];
2510
+ return /* @__PURE__ */ jsxs19("div", { className: "flex h-full gap-2", children: [
2511
+ /* @__PURE__ */ jsx29("div", { className: cn(firstClass, "overflow-auto"), children: contentWrapper(firstChild) }),
2512
+ /* @__PURE__ */ jsx29("div", { className: cn(secondClass, "overflow-auto"), children: contentWrapper(secondChild) })
2513
+ ] });
2514
+ }
2515
+ case "with-sheet": {
2516
+ const {
2517
+ sheetContent,
2518
+ sheetWidth = "four-fifth",
2519
+ sheetSide = "right",
2520
+ sheetMode = "container",
2521
+ sheetTrigger,
2522
+ sheetClassName,
2523
+ isSheetOpen,
2524
+ onSheetOpenChange,
2525
+ showSheetOverlay = true,
2526
+ disableOverlay = true
2527
+ } = props;
2528
+ const isControlled = isSheetOpen !== void 0;
2529
+ const sheetOpen = isControlled ? isSheetOpen : internalSheetOpen;
2530
+ const setSheetOpen = isControlled ? onSheetOpenChange : setInternalSheetOpen;
2531
+ if (sheetMode === "container") {
2532
+ const sheetClasses = getContainerSheetClasses(sheetSide, sheetWidth);
2533
+ return /* @__PURE__ */ jsxs19("div", { className: cn(
2534
+ "flex relative flex-1 overflow-hidden",
2535
+ sheetOpen && disableOverlay && ["left", "right"].includes(sheetSide)
2536
+ ), children: [
2537
+ /* @__PURE__ */ jsxs19("div", { className: cn(
2538
+ "h-full overflow-auto transition-all duration-500",
2539
+ sheetOpen && disableOverlay && ["left", "right"].includes(sheetSide) ? sheetClasses.contentPushClass : "w-full",
2540
+ sheetOpen && disableOverlay && "overflow-y-auto overflow-x-hidden"
2541
+ ), children: [
2542
+ sheetTrigger && /* @__PURE__ */ jsx29("div", { onClick: () => setSheetOpen?.(!sheetOpen), children: sheetTrigger }),
2543
+ /* @__PURE__ */ jsx29("div", { className: cn("h-full", !parentContainer && paddingClasses2[padding]), children })
2544
+ ] }),
2545
+ /* @__PURE__ */ jsx29(
2546
+ "div",
2547
+ {
2548
+ className: cn(
2549
+ sheetClasses.container,
2550
+ "transition-all duration-500 ease-in-out",
2551
+ sheetOpen && disableOverlay && ["left", "right"].includes(sheetSide) ? cn(sheetClasses.sheetPushClass, "overflow-y-auto") : sheetOpen ? sheetClasses.transformOpen : cn(sheetClasses.transform, "hidden"),
2552
+ "overflow-y-auto"
2553
+ ),
2554
+ children: /* @__PURE__ */ jsx29("div", { className: cn(sheetClasses.content, sheetClassName, "h-full"), children: sheetContent })
2555
+ }
2556
+ ),
2557
+ sheetOpen && showSheetOverlay && !disableOverlay && /* @__PURE__ */ jsx29(
2558
+ "div",
2559
+ {
2560
+ className: cn(
2561
+ "absolute inset-0 bg-secondary/20 z-40",
2562
+ "transition-opacity duration-500 ease-in-out",
2563
+ "opacity-0",
2564
+ sheetOpen ? "opacity-100" : "opacity-0"
2565
+ ),
2566
+ onClick: () => setSheetOpen?.(false)
2567
+ }
2568
+ )
2569
+ ] });
2570
+ }
2571
+ return /* @__PURE__ */ jsxs19(Sheet, { open: sheetOpen, onOpenChange: setSheetOpen, children: [
2572
+ sheetTrigger && /* @__PURE__ */ jsx29(SheetTrigger, { asChild: true, children: sheetTrigger }),
2573
+ /* @__PURE__ */ jsxs19(SheetPortal, { children: [
2574
+ showSheetOverlay && /* @__PURE__ */ jsx29(SheetOverlay, { className: "fixed inset-0 bg-secondary/50 z-50" }),
2575
+ /* @__PURE__ */ jsx29(
2576
+ SheetContent,
2577
+ {
2578
+ side: sheetSide,
2579
+ className: cn(
2580
+ "fixed bg-background border",
2581
+ "transition-all duration-500 ease-in-out",
2582
+ splitRatioClasses[sheetWidth][1],
2583
+ sheetClassName
2584
+ ),
2585
+ children: sheetContent
2586
+ }
2587
+ )
2588
+ ] })
2589
+ ] });
2590
+ }
2591
+ default:
2592
+ return contentWrapper(children);
2593
+ }
2594
+ };
2595
+ return /* @__PURE__ */ jsx29(AppContentContext.Provider, { value: true, children: /* @__PURE__ */ jsxs19("div", { className: cn(
2596
+ baseClasses,
2597
+ variantClasses[variant],
2598
+ paddingClasses2[padding],
2599
+ isNested && "flex-1",
2600
+ parentContainer && "h-full",
2601
+ !parentContainer && "rounded-2xl",
2602
+ className
2603
+ ), children: [
2604
+ header && /* @__PURE__ */ jsx29(
2605
+ "div",
2606
+ {
2607
+ className: cn(
2608
+ "border-b",
2609
+ headerClassName,
2610
+ variant === "card" && !parentContainer && "rounded-t-2xl",
2611
+ variant === "border" && "border-b-2",
2612
+ paddingClasses2[padding]
2613
+ ),
2614
+ children: header
2615
+ }
2616
+ ),
2617
+ renderContent(),
2618
+ footer && /* @__PURE__ */ jsx29(
2619
+ "div",
2620
+ {
2621
+ className: cn(
2622
+ "border-t",
2623
+ footerClassName,
2624
+ variant === "card" && !parentContainer && "rounded-b-2xl",
2625
+ variant === "border" && "border-t-2",
2626
+ paddingClasses2[padding]
2627
+ ),
2628
+ children: footer
2629
+ }
2630
+ )
2631
+ ] }) });
2632
+ };
2633
+
2634
+ // src/components/layouts/app-footer.tsx
2635
+ import { jsx as jsx30 } from "react/jsx-runtime";
2636
+ var AppFooter = ({
2637
+ className,
2638
+ columns = [],
2639
+ meta = { title: "" }
2640
+ }) => {
2641
+ const actionsColumn = {
2642
+ content: /* @__PURE__ */ jsx30("div", { className: "flex items-center gap-4 p-2", children: meta.secondaryActions }),
2643
+ align: "right",
2644
+ width: "fill"
2645
+ };
2646
+ const allColumns = [
2647
+ ...columns.filter((col) => col !== void 0),
2648
+ actionsColumn
2649
+ ];
2650
+ return /* @__PURE__ */ jsx30("div", { className: cn("flex items-center w-full gap-4", className), children: allColumns.map((column, index) => /* @__PURE__ */ jsx30(
2651
+ "div",
2652
+ {
2653
+ className: cn(
2654
+ "flex items-center h-full",
2655
+ column.className,
2656
+ {
2657
+ "justify-start": column.align === "left",
2658
+ "justify-center": column.align === "center",
2659
+ "justify-end": column.align === "right",
2660
+ "flex-1": column.width === "fill"
2661
+ }
2662
+ ),
2663
+ children: column.content
2664
+ },
2665
+ index
2666
+ )) });
2667
+ };
2668
+
2669
+ // src/components/layouts/factories.tsx
2670
+ import { jsx as jsx31 } from "react/jsx-runtime";
2671
+ function createLayoutComponents({
2672
+ useTypedAppMeta
2673
+ }) {
2674
+ const AppHeader2 = (props) => {
2675
+ const { meta } = useTypedAppMeta();
2676
+ return /* @__PURE__ */ jsx31(AppHeader, { ...props, meta });
2677
+ };
2678
+ const AppFooter2 = (props) => {
2679
+ const { meta } = useTypedAppMeta();
2680
+ return /* @__PURE__ */ jsx31(AppFooter, { ...props, meta });
2681
+ };
2682
+ const AppContent2 = (props) => /* @__PURE__ */ jsx31(AppContent, { ...props });
2683
+ const AppContainer2 = (props) => /* @__PURE__ */ jsx31(AppContainer, { ...props });
2684
+ return {
2685
+ AppHeader: AppHeader2,
2686
+ AppFooter: AppFooter2,
2687
+ AppContent: AppContent2,
2688
+ AppContainer: AppContainer2
2689
+ };
2690
+ }
2691
+
2692
+ // src/context/app-meta/context.tsx
2693
+ import { createContext as createContext2, useContext as useContext2, useState as useState6, useCallback as useCallback5 } from "react";
2694
+ import { jsx as jsx32 } from "react/jsx-runtime";
2695
+ var AppMetaContext = createContext2(void 0);
2696
+ var AppMetaProvider = ({ children }) => {
2697
+ const [meta, setMetaState] = useState6({
2698
+ title: "",
2699
+ description: "",
2700
+ breadcrumbs: []
2701
+ });
2702
+ const setMeta = useCallback5((partialMeta) => {
2703
+ setMetaState((prev) => ({ ...prev, ...partialMeta }));
2704
+ }, []);
2705
+ const resetMeta = useCallback5(() => {
2706
+ setMetaState({
2707
+ title: "",
2708
+ description: "",
2709
+ breadcrumbs: []
2710
+ });
2711
+ }, []);
2712
+ return /* @__PURE__ */ jsx32(AppMetaContext.Provider, { value: { meta, setMeta, resetMeta }, children });
2713
+ };
2714
+ function createTypedAppMetaContext() {
2715
+ const TypedAppMetaContext = createContext2(void 0);
2716
+ const TypedAppMetaProvider = ({ children }) => {
2717
+ const [meta, setMetaState] = useState6({
2718
+ title: "",
2719
+ description: "",
2720
+ breadcrumbs: []
2721
+ });
2722
+ const setMeta = useCallback5((partialMeta) => {
2723
+ setMetaState((prev) => ({ ...prev, ...partialMeta }));
2724
+ }, []);
2725
+ const resetMeta = useCallback5(() => {
2726
+ setMetaState({
2727
+ title: "",
2728
+ description: "",
2729
+ breadcrumbs: []
2730
+ });
2731
+ }, []);
2732
+ return /* @__PURE__ */ jsx32(TypedAppMetaContext.Provider, { value: { meta, setMeta, resetMeta }, children });
2733
+ };
2734
+ const useTypedAppMeta = () => {
2735
+ const context = useContext2(TypedAppMetaContext);
2736
+ if (!context) {
2737
+ throw new Error("useTypedAppMeta must be used within a TypedAppMetaProvider");
2738
+ }
2739
+ return context;
2740
+ };
2741
+ return { TypedAppMetaProvider, useTypedAppMeta, TypedAppMetaContext };
2742
+ }
2743
+
2744
+ // src/context/app-meta/hooks.ts
2745
+ import { useEffect as useEffect5, useMemo as useMemo3 } from "react";
2746
+ function createPageTemplateHook({
2747
+ useTypedAppMeta
2748
+ }) {
2749
+ function usePageTemplate(options) {
2750
+ const { setMeta, resetMeta } = useTypedAppMeta();
2751
+ const memoizedOptions = useMemo3(() => options, [
2752
+ options.title,
2753
+ options.description,
2754
+ options.breadcrumbs,
2755
+ options.primaryActions,
2756
+ options.secondaryActions,
2757
+ options.backAction,
2758
+ options.pagination,
2759
+ options.metadata,
2760
+ options.status
2761
+ ]);
2762
+ useEffect5(() => {
2763
+ setMeta(memoizedOptions);
2764
+ return () => resetMeta();
2765
+ }, [memoizedOptions, setMeta, resetMeta]);
2766
+ }
2767
+ return { usePageTemplate };
2768
+ }
2769
+
2770
+ // src/components/general.tsx
2771
+ import { useState as useState7 } from "react";
2772
+ import { Copy, Check, Loader2Icon } from "lucide-react";
2773
+ import { jsx as jsx33, jsxs as jsxs20 } from "react/jsx-runtime";
2774
+ var GeneralHelper = class {
2775
+ static currencyFormatter = new Intl.NumberFormat("en-IN", {
2776
+ style: "currency",
2777
+ currency: "INR",
2778
+ maximumFractionDigits: 2
2779
+ });
2780
+ static compactFormatter = new Intl.NumberFormat("en-IN", {
2781
+ style: "currency",
2782
+ currency: "INR",
2783
+ notation: "compact",
2784
+ maximumFractionDigits: 1
2785
+ });
2786
+ static MONTH_NAMES_SHORT = [
2787
+ "Jan",
2788
+ "Feb",
2789
+ "Mar",
2790
+ "Apr",
2791
+ "May",
2792
+ "Jun",
2793
+ "Jul",
2794
+ "Aug",
2795
+ "Sep",
2796
+ "Oct",
2797
+ "Nov",
2798
+ "Dec"
2799
+ ];
2800
+ /**
2801
+ * Copies text to clipboard
2802
+ * @param text Text to copy
2803
+ * @returns Promise that resolves when copy is complete
2804
+ */
2805
+ static async copyToClipboard(text) {
2806
+ if (!text) return;
2807
+ try {
2808
+ await navigator.clipboard.writeText(text);
2809
+ } catch (error) {
2810
+ console.error("Failed to copy text:", error);
2811
+ throw error;
2812
+ }
2813
+ }
2814
+ /**
2815
+ * React component for copy to clipboard functionality
2816
+ */
2817
+ static CopyToClipboard = ({
2818
+ text,
2819
+ children,
2820
+ className,
2821
+ size = "icon",
2822
+ variant = "ghost"
2823
+ }) => {
2824
+ const [isCopied, setIsCopied] = useState7(false);
2825
+ const [isLoading, setIsLoading] = useState7(false);
2826
+ const handleCopy = async () => {
2827
+ if (!text || isLoading) return;
2828
+ setIsLoading(true);
2829
+ try {
2830
+ await this.copyToClipboard(text);
2831
+ setIsCopied(true);
2832
+ setTimeout(() => setIsCopied(false), 2e3);
2833
+ } catch (error) {
2834
+ console.error("Failed to copy text:", error);
2835
+ } finally {
2836
+ setIsLoading(false);
2837
+ }
2838
+ };
2839
+ return /* @__PURE__ */ jsxs20(Tooltip, { children: [
2840
+ /* @__PURE__ */ jsx33(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx33(
2841
+ Button,
2842
+ {
2843
+ variant,
2844
+ size,
2845
+ className: cn(
2846
+ size === "icon" && "size-6",
2847
+ className
2848
+ ),
2849
+ onClick: handleCopy,
2850
+ disabled: isLoading || !text,
2851
+ children: isLoading ? /* @__PURE__ */ jsx33(Loader2Icon, { className: "animate-spin" }) : isCopied ? /* @__PURE__ */ jsx33(Check, { className: "h-3 w-3" }) : children ? children : /* @__PURE__ */ jsx33(Copy, { className: "h-3 w-3" })
2852
+ }
2853
+ ) }),
2854
+ /* @__PURE__ */ jsx33(TooltipContent, { children: isCopied ? "Copied!" : isLoading ? "Copying..." : "Copy to clipboard" })
2855
+ ] });
2856
+ };
2857
+ /**
2858
+ * Formats a number as Indian Rupees (INR)
2859
+ * @param amount Amount to format
2860
+ * @param options Formatting options
2861
+ * @returns Formatted currency string
2862
+ */
2863
+ static formatINR(amount, options = {}) {
2864
+ const { prefix = "", suffix = "", withSymbol = true, compact = false } = options;
2865
+ if (typeof amount !== "number" || isNaN(amount)) {
2866
+ return `${prefix}${withSymbol ? "\u20B9 " : ""}0.00${suffix}`;
2867
+ }
2868
+ const isNegative = amount < 0;
2869
+ const absoluteAmount = Math.abs(amount);
2870
+ const formatter = compact && absoluteAmount >= 1e5 ? this.compactFormatter : this.currencyFormatter;
2871
+ const formatted = formatter.format(absoluteAmount).replace("\u20B9", "");
2872
+ return `${prefix}${isNegative ? "- " : ""}${withSymbol ? "\u20B9 " : ""}${formatted}${suffix}`;
2873
+ }
2874
+ /**
2875
+ * Formats a date according to specified options
2876
+ * @param input Date input (string, number, or Date object)
2877
+ * @param options Formatting options
2878
+ * @returns Formatted date string
2879
+ */
2880
+ static formatDate(input, options = {}) {
2881
+ const { format = "dd-mm-yyyy", separator = "-" } = options;
2882
+ const dateObj = new Date(input);
2883
+ if (isNaN(dateObj.getTime())) return "";
2884
+ const dd = String(dateObj.getDate()).padStart(2, "0");
2885
+ const mm = String(dateObj.getMonth() + 1).padStart(2, "0");
2886
+ const mmm = this.MONTH_NAMES_SHORT[dateObj.getMonth()];
2887
+ const yyyy = dateObj.getFullYear();
2888
+ switch (format) {
2889
+ case "dd-mmm-yyyy":
2890
+ return `${dd}${separator}${mmm}${separator}${yyyy}`;
2891
+ case "iso":
2892
+ return dateObj.toISOString().split("T")[0];
2893
+ case "long":
2894
+ return dateObj.toLocaleDateString("en-IN", {
2895
+ year: "numeric",
2896
+ month: "long",
2897
+ day: "numeric"
2898
+ });
2899
+ case "short":
2900
+ return dateObj.toLocaleDateString("en-IN");
2901
+ default:
2902
+ return `${dd}${separator}${mm}${separator}${yyyy}`;
2903
+ }
2904
+ }
2905
+ static toProperCase(text) {
2906
+ if (!text) return "";
2907
+ return text.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
2908
+ }
2909
+ /**
2910
+ * Advanced proper case conversion that handles hyphenated words and apostrophes
2911
+ * @param text Text to convert
2912
+ * @returns Text in proper case with special handling
2913
+ */
2914
+ static toProperCaseAdvanced(text) {
2915
+ if (!text) return "";
2916
+ return text.toLowerCase().split(/(\s+|['-])/).map((part, index, array) => {
2917
+ if (["-", "'", " "].includes(part) || index > 0 && ["-", "'"].includes(array[index - 1])) {
2918
+ return part;
2919
+ }
2920
+ return part.charAt(0).toUpperCase() + part.slice(1);
2921
+ }).join("");
2922
+ }
2923
+ static StatusBadge = ({
2924
+ status,
2925
+ className,
2926
+ showDot = true,
2927
+ capitalize = true,
2928
+ size = "md",
2929
+ variant = "outline",
2930
+ customColors,
2931
+ icon,
2932
+ trueMessage = "active",
2933
+ falseMessage = "inactive"
2934
+ }) => {
2935
+ const normalizedStatus = typeof status === "boolean" ? status ? trueMessage : falseMessage : typeof status === "number" ? status > 0 ? trueMessage : falseMessage : status.toLowerCase();
2936
+ const statusConfig = {
2937
+ active: {
2938
+ label: "active",
2939
+ solid: {
2940
+ bg: "bg-emerald-500",
2941
+ text: "text-white",
2942
+ border: "border-emerald-600",
2943
+ dot: "bg-white"
2944
+ },
2945
+ outline: {
2946
+ bg: "bg-emerald-50",
2947
+ text: "text-emerald-700",
2948
+ border: "border-emerald-100",
2949
+ dot: "bg-emerald-500"
2950
+ },
2951
+ subtle: {
2952
+ bg: "bg-emerald-50",
2953
+ text: "text-emerald-700",
2954
+ border: "border-transparent",
2955
+ dot: "bg-emerald-500"
2956
+ }
2957
+ },
2958
+ pending: {
2959
+ label: "pending",
2960
+ solid: {
2961
+ bg: "bg-amber-500",
2962
+ text: "text-white",
2963
+ border: "border-amber-600",
2964
+ dot: "bg-white"
2965
+ },
2966
+ outline: {
2967
+ bg: "bg-amber-50",
2968
+ text: "text-amber-700",
2969
+ border: "border-amber-100",
2970
+ dot: "bg-amber-500"
2971
+ },
2972
+ subtle: {
2973
+ bg: "bg-amber-50",
2974
+ text: "text-amber-700",
2975
+ border: "border-transparent",
2976
+ dot: "bg-amber-500"
2977
+ }
2978
+ },
2979
+ inactive: {
2980
+ label: "inactive",
2981
+ solid: {
2982
+ bg: "bg-rose-500",
2983
+ text: "text-white",
2984
+ border: "border-rose-600",
2985
+ dot: "bg-white"
2986
+ },
2987
+ outline: {
2988
+ bg: "bg-rose-50",
2989
+ text: "text-rose-700",
2990
+ border: "border-rose-100",
2991
+ dot: "bg-rose-500"
2992
+ },
2993
+ subtle: {
2994
+ bg: "bg-rose-50",
2995
+ text: "text-rose-700",
2996
+ border: "border-transparent",
2997
+ dot: "bg-rose-500"
2998
+ }
2999
+ },
3000
+ draft: {
3001
+ label: "draft",
3002
+ solid: {
3003
+ bg: "bg-gray-500",
3004
+ text: "text-white",
3005
+ border: "border-gray-600",
3006
+ dot: "bg-white"
3007
+ },
3008
+ outline: {
3009
+ bg: "bg-gray-50",
3010
+ text: "text-gray-700",
3011
+ border: "border-gray-100",
3012
+ dot: "bg-gray-500"
3013
+ },
3014
+ subtle: {
3015
+ bg: "bg-gray-50",
3016
+ text: "text-gray-700",
3017
+ border: "border-transparent",
3018
+ dot: "bg-gray-500"
3019
+ }
3020
+ },
3021
+ completed: {
3022
+ label: "completed",
3023
+ solid: {
3024
+ bg: "bg-indigo-500",
3025
+ text: "text-white",
3026
+ border: "border-indigo-600",
3027
+ dot: "bg-white"
3028
+ },
3029
+ outline: {
3030
+ bg: "bg-indigo-50",
3031
+ text: "text-indigo-700",
3032
+ border: "border-indigo-100",
3033
+ dot: "bg-indigo-500"
3034
+ },
3035
+ subtle: {
3036
+ bg: "bg-indigo-50",
3037
+ text: "text-indigo-700",
3038
+ border: "border-transparent",
3039
+ dot: "bg-indigo-500"
3040
+ }
3041
+ }
3042
+ };
3043
+ const config = statusConfig[normalizedStatus.toLowerCase()] || statusConfig.inactive;
3044
+ const colors = customColors || config[variant];
3045
+ const sizeClasses = {
3046
+ sm: "text-xs px-2 py-0.5",
3047
+ md: "text-xs px-2.5 py-0.5",
3048
+ lg: "text-sm px-3 py-1"
3049
+ };
3050
+ const displayText = capitalize ? normalizedStatus.charAt(0).toUpperCase() + normalizedStatus.slice(1) : normalizedStatus;
3051
+ return /* @__PURE__ */ jsx33("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxs20(
3052
+ "span",
3053
+ {
3054
+ className: cn(
3055
+ "inline-flex items-center gap-1.5 rounded-full border font-medium",
3056
+ colors.bg,
3057
+ colors.text,
3058
+ colors.border,
3059
+ sizeClasses[size],
3060
+ className
3061
+ ),
3062
+ children: [
3063
+ showDot && (icon ? /* @__PURE__ */ jsx33("span", { className: "flex items-center", children: icon }) : /* @__PURE__ */ jsx33(
3064
+ "span",
3065
+ {
3066
+ className: cn("size-2 rounded-full", colors.dot),
3067
+ "aria-hidden": "true"
3068
+ }
3069
+ )),
3070
+ displayText
3071
+ ]
3072
+ }
3073
+ ) });
3074
+ };
3075
+ };
3076
+ export {
3077
+ AppMetaProvider,
3078
+ DataTable,
3079
+ DataTableActionBar,
3080
+ DataTableActionBarAction,
3081
+ DataTableActionBarSelection,
3082
+ DataTemplate,
3083
+ DataTemplateActionBar,
3084
+ DataTemplateActionBarAction,
3085
+ DataTemplateActionBarSelection,
3086
+ GeneralHelper,
3087
+ createLayoutComponents,
3088
+ createPageTemplateHook,
3089
+ createTypedAppMetaContext
3090
+ };
3091
+ //# sourceMappingURL=index.js.map