@startsimpli/ui 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/chunk-27YUQBOE.mjs +3954 -0
  2. package/dist/chunk-27YUQBOE.mjs.map +1 -0
  3. package/dist/chunk-G2AM3DBU.mjs +1026 -0
  4. package/dist/chunk-G2AM3DBU.mjs.map +1 -0
  5. package/dist/chunk-G4XBXCFH.mjs +63 -0
  6. package/dist/chunk-G4XBXCFH.mjs.map +1 -0
  7. package/dist/chunk-LZOMFHX3.mjs +35 -0
  8. package/dist/chunk-LZOMFHX3.mjs.map +1 -0
  9. package/dist/chunk-QYXFLOO7.mjs +210 -0
  10. package/dist/chunk-QYXFLOO7.mjs.map +1 -0
  11. package/dist/components/index.d.mts +472 -0
  12. package/dist/components/index.d.ts +472 -0
  13. package/dist/components/index.js +5149 -0
  14. package/dist/components/index.js.map +1 -0
  15. package/dist/components/index.mjs +6 -0
  16. package/dist/components/index.mjs.map +1 -0
  17. package/dist/components/unified-table/index.d.mts +725 -0
  18. package/dist/components/unified-table/index.d.ts +725 -0
  19. package/dist/components/unified-table/index.js +4000 -0
  20. package/dist/components/unified-table/index.js.map +1 -0
  21. package/dist/components/unified-table/index.mjs +5 -0
  22. package/dist/components/unified-table/index.mjs.map +1 -0
  23. package/dist/index.d.mts +26 -0
  24. package/dist/index.d.ts +26 -0
  25. package/dist/index.js +5448 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/index.mjs +12 -0
  28. package/dist/index.mjs.map +1 -0
  29. package/dist/theme/index.d.mts +20 -0
  30. package/dist/theme/index.d.ts +20 -0
  31. package/dist/theme/index.js +245 -0
  32. package/dist/theme/index.js.map +1 -0
  33. package/dist/theme/index.mjs +9 -0
  34. package/dist/theme/index.mjs.map +1 -0
  35. package/dist/utils/index.d.mts +38 -0
  36. package/dist/utils/index.d.ts +38 -0
  37. package/dist/utils/index.js +72 -0
  38. package/dist/utils/index.js.map +1 -0
  39. package/dist/utils/index.mjs +4 -0
  40. package/dist/utils/index.mjs.map +1 -0
  41. package/package.json +62 -21
  42. package/src/__mocks__/next/navigation.js +18 -0
  43. package/src/components/__tests__/safe-html.test.tsx +45 -0
  44. package/src/components/__tests__/states.test.tsx +94 -0
  45. package/src/components/__tests__/status-badge.test.tsx +101 -0
  46. package/src/components/__tests__/toast.test.tsx +124 -0
  47. package/src/components/badge/StatusBadge.tsx +55 -0
  48. package/src/components/badge/index.ts +2 -0
  49. package/src/components/dialog/BaseDialog.tsx +184 -0
  50. package/src/components/dialog/index.ts +8 -0
  51. package/src/components/index.ts +25 -0
  52. package/src/components/loading/DashboardSkeleton.tsx +27 -0
  53. package/src/components/loading/TableSkeleton.tsx +63 -0
  54. package/src/components/loading/index.ts +4 -0
  55. package/src/components/safe-html.tsx +18 -0
  56. package/src/components/states/EmptyState.tsx +48 -0
  57. package/src/components/states/ErrorState.tsx +76 -0
  58. package/src/components/states/index.ts +4 -0
  59. package/src/components/toast/Toaster.tsx +72 -0
  60. package/src/components/toast/index.ts +5 -0
  61. package/src/components/toast/use-notify.ts +45 -0
  62. package/src/components/toast/use-toast.ts +150 -0
  63. package/src/components/ui/api-error-boundary.tsx +64 -0
  64. package/src/components/ui/feature-gate.tsx +87 -0
  65. package/src/components/ui/index.ts +4 -0
  66. package/src/components/ui/page-loader.tsx +31 -0
  67. package/src/components/ui/query-provider.tsx +30 -0
  68. package/src/components/unified-table/components/Toolbar/StandardTableToolbar.tsx +1 -1
  69. package/src/components/unified-table/hooks/useFilters.ts +1 -0
  70. package/src/components/unified-table/hooks/usePagination.ts +1 -0
  71. package/src/components/unified-table/hooks/useSelection.ts +2 -1
  72. package/src/components/unified-table/hooks/useTableKeyboard.ts +2 -1
  73. package/src/components/unified-table/hooks/useTablePreferences.ts +1 -0
  74. package/src/components/unified-table/hooks/useTableState.ts +1 -0
  75. package/src/components/unified-table/hooks/useTableURL.test.tsx +1 -1
  76. package/src/components/unified-table/index.ts +4 -0
  77. package/src/components/wizard/StepIndicator.tsx +60 -0
  78. package/src/components/wizard/index.ts +2 -0
  79. package/src/theme/tailwind.config.d.ts +3 -0
  80. package/tailwind.preset.js +87 -0
@@ -0,0 +1,1026 @@
1
+ import { buttonVariants, Button } from './chunk-27YUQBOE.mjs';
2
+ import { cn } from './chunk-G4XBXCFH.mjs';
3
+ import * as React12 from 'react';
4
+ import { useState } from 'react';
5
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
6
+ import { ChevronDown, ChevronLeft, ChevronRight, Check } from 'lucide-react';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
+ import { cva } from 'class-variance-authority';
9
+ import { DayPicker } from 'react-day-picker';
10
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
11
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
12
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
13
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
14
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
15
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
16
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
17
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
18
+ import Link from 'next/link';
19
+ import { usePathname } from 'next/navigation';
20
+ import DOMPurify from 'isomorphic-dompurify';
21
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
22
+
23
+ var Accordion = AccordionPrimitive.Root;
24
+ var AccordionItem = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
25
+ AccordionPrimitive.Item,
26
+ {
27
+ ref,
28
+ className: cn("border-b", className),
29
+ ...props
30
+ }
31
+ ));
32
+ AccordionItem.displayName = "AccordionItem";
33
+ var AccordionTrigger = React12.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
34
+ AccordionPrimitive.Trigger,
35
+ {
36
+ ref,
37
+ className: cn(
38
+ "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
39
+ className
40
+ ),
41
+ ...props,
42
+ children: [
43
+ children,
44
+ /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 shrink-0 transition-transform duration-200" })
45
+ ]
46
+ }
47
+ ) }));
48
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
49
+ var AccordionContent = React12.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
50
+ AccordionPrimitive.Content,
51
+ {
52
+ ref,
53
+ className: "overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
54
+ ...props,
55
+ children: /* @__PURE__ */ jsx("div", { className: cn("pb-4 pt-0", className), children })
56
+ }
57
+ ));
58
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
59
+ var alertVariants = cva(
60
+ "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
61
+ {
62
+ variants: {
63
+ variant: {
64
+ default: "bg-background text-foreground",
65
+ destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
66
+ }
67
+ },
68
+ defaultVariants: {
69
+ variant: "default"
70
+ }
71
+ }
72
+ );
73
+ var Alert = React12.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(
74
+ "div",
75
+ {
76
+ ref,
77
+ role: "alert",
78
+ className: cn(alertVariants({ variant }), className),
79
+ ...props
80
+ }
81
+ ));
82
+ Alert.displayName = "Alert";
83
+ var AlertTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
84
+ "h5",
85
+ {
86
+ ref,
87
+ className: cn("mb-1 font-medium leading-none tracking-tight", className),
88
+ ...props
89
+ }
90
+ ));
91
+ AlertTitle.displayName = "AlertTitle";
92
+ var AlertDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
93
+ "div",
94
+ {
95
+ ref,
96
+ className: cn("text-sm [&_p]:leading-relaxed", className),
97
+ ...props
98
+ }
99
+ ));
100
+ AlertDescription.displayName = "AlertDescription";
101
+ function Calendar({
102
+ className,
103
+ classNames,
104
+ showOutsideDays = true,
105
+ ...props
106
+ }) {
107
+ return /* @__PURE__ */ jsx(
108
+ DayPicker,
109
+ {
110
+ showOutsideDays,
111
+ className: cn("p-3", className),
112
+ classNames: {
113
+ months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
114
+ month: "space-y-4",
115
+ caption: "flex justify-center pt-1 relative items-center",
116
+ caption_label: "text-sm font-medium",
117
+ nav: "space-x-1 flex items-center",
118
+ nav_button: cn(
119
+ buttonVariants({ variant: "outline" }),
120
+ "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
121
+ ),
122
+ nav_button_previous: "absolute left-1",
123
+ nav_button_next: "absolute right-1",
124
+ table: "w-full border-collapse space-y-1",
125
+ head_row: "flex",
126
+ head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
127
+ row: "flex w-full mt-2",
128
+ cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
129
+ day: cn(
130
+ buttonVariants({ variant: "ghost" }),
131
+ "h-9 w-9 p-0 font-normal aria-selected:opacity-100"
132
+ ),
133
+ day_range_end: "day-range-end",
134
+ day_selected: "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
135
+ day_today: "bg-accent text-accent-foreground",
136
+ day_outside: "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
137
+ day_disabled: "text-muted-foreground opacity-50",
138
+ day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
139
+ day_hidden: "invisible",
140
+ ...classNames
141
+ },
142
+ components: {
143
+ Chevron: ({ orientation }) => orientation === "left" ? /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" })
144
+ },
145
+ ...props
146
+ }
147
+ );
148
+ }
149
+ Calendar.displayName = "Calendar";
150
+ var Collapsible = CollapsiblePrimitive.Root;
151
+ var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
152
+ var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
153
+ var Popover = PopoverPrimitive.Root;
154
+ var PopoverTrigger = PopoverPrimitive.Trigger;
155
+ var PopoverContent = React12.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
156
+ PopoverPrimitive.Content,
157
+ {
158
+ ref,
159
+ align,
160
+ sideOffset,
161
+ className: cn(
162
+ "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
163
+ className
164
+ ),
165
+ ...props
166
+ }
167
+ ) }));
168
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
169
+ var Progress = React12.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(
170
+ ProgressPrimitive.Root,
171
+ {
172
+ ref,
173
+ className: cn(
174
+ "relative h-4 w-full overflow-hidden rounded-full bg-secondary",
175
+ className
176
+ ),
177
+ ...props,
178
+ children: /* @__PURE__ */ jsx(
179
+ ProgressPrimitive.Indicator,
180
+ {
181
+ className: "h-full w-full flex-1 bg-primary transition-all",
182
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
183
+ }
184
+ )
185
+ }
186
+ ));
187
+ Progress.displayName = ProgressPrimitive.Root.displayName;
188
+ var ScrollArea = React12.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
189
+ ScrollAreaPrimitive.Root,
190
+ {
191
+ ref,
192
+ className: cn("relative overflow-hidden", className),
193
+ ...props,
194
+ children: [
195
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
196
+ /* @__PURE__ */ jsx(ScrollBar, {}),
197
+ /* @__PURE__ */ jsx(ScrollAreaPrimitive.Corner, {})
198
+ ]
199
+ }
200
+ ));
201
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
202
+ var ScrollBar = React12.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
203
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
204
+ {
205
+ ref,
206
+ orientation,
207
+ className: cn(
208
+ "flex touch-none select-none transition-colors",
209
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent p-[1px]",
210
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent p-[1px]",
211
+ className
212
+ ),
213
+ ...props,
214
+ children: /* @__PURE__ */ jsx(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border" })
215
+ }
216
+ ));
217
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
218
+ var Separator = React12.forwardRef(
219
+ ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
220
+ SeparatorPrimitive.Root,
221
+ {
222
+ ref,
223
+ decorative,
224
+ orientation,
225
+ className: cn(
226
+ "shrink-0 bg-border",
227
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
228
+ className
229
+ ),
230
+ ...props
231
+ }
232
+ )
233
+ );
234
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
235
+ function Skeleton({
236
+ className,
237
+ ...props
238
+ }) {
239
+ return /* @__PURE__ */ jsx(
240
+ "div",
241
+ {
242
+ className: cn("animate-pulse rounded-md bg-gray-200", className),
243
+ ...props
244
+ }
245
+ );
246
+ }
247
+ var Tabs = TabsPrimitive.Root;
248
+ var TabsList = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
249
+ TabsPrimitive.List,
250
+ {
251
+ ref,
252
+ className: cn(
253
+ "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
254
+ className
255
+ ),
256
+ ...props
257
+ }
258
+ ));
259
+ TabsList.displayName = TabsPrimitive.List.displayName;
260
+ var TabsTrigger = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
261
+ TabsPrimitive.Trigger,
262
+ {
263
+ ref,
264
+ className: cn(
265
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
266
+ className
267
+ ),
268
+ ...props
269
+ }
270
+ ));
271
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
272
+ var TabsContent = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
273
+ TabsPrimitive.Content,
274
+ {
275
+ ref,
276
+ className: cn(
277
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
278
+ className
279
+ ),
280
+ ...props
281
+ }
282
+ ));
283
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
284
+ var Textarea = React12.forwardRef(
285
+ ({ className, ...props }, ref) => {
286
+ return /* @__PURE__ */ jsx(
287
+ "textarea",
288
+ {
289
+ className: cn(
290
+ "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
291
+ className
292
+ ),
293
+ ref,
294
+ ...props
295
+ }
296
+ );
297
+ }
298
+ );
299
+ Textarea.displayName = "Textarea";
300
+ var TooltipProvider = TooltipPrimitive.Provider;
301
+ var Tooltip = TooltipPrimitive.Root;
302
+ var TooltipTrigger = TooltipPrimitive.Trigger;
303
+ var TooltipContent = React12.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(
304
+ TooltipPrimitive.Content,
305
+ {
306
+ ref,
307
+ sideOffset,
308
+ className: cn(
309
+ "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md 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",
310
+ className
311
+ ),
312
+ ...props
313
+ }
314
+ ));
315
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
316
+ function FeatureGate({
317
+ enabled,
318
+ mode = "disable",
319
+ tooltip = "Coming soon",
320
+ children,
321
+ className
322
+ }) {
323
+ if (enabled) {
324
+ return /* @__PURE__ */ jsx(Fragment, { children });
325
+ }
326
+ if (mode === "hide") {
327
+ return null;
328
+ }
329
+ if (mode === "badge") {
330
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex", className), children: [
331
+ /* @__PURE__ */ jsx("div", { className: "opacity-60 pointer-events-none select-none", children }),
332
+ /* @__PURE__ */ jsx("span", { className: "absolute -top-1.5 -right-1.5 rounded-full bg-muted text-muted-foreground text-[10px] font-medium px-1.5 py-0.5 leading-none border", children: "Soon" })
333
+ ] });
334
+ }
335
+ return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
336
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
337
+ "span",
338
+ {
339
+ className: cn("inline-flex cursor-not-allowed", className),
340
+ "aria-disabled": "true",
341
+ children: /* @__PURE__ */ jsx("span", { className: "pointer-events-none opacity-50 select-none", children })
342
+ }
343
+ ) }),
344
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: tooltip }) })
345
+ ] }) });
346
+ }
347
+ function ErrorState({
348
+ title = "Something went wrong",
349
+ message,
350
+ onRetry,
351
+ className
352
+ }) {
353
+ return /* @__PURE__ */ jsxs(
354
+ "div",
355
+ {
356
+ className: cn(
357
+ "flex flex-col items-center justify-center py-12 px-4 text-center",
358
+ className
359
+ ),
360
+ role: "alert",
361
+ "aria-live": "assertive",
362
+ children: [
363
+ /* @__PURE__ */ jsx(
364
+ "div",
365
+ {
366
+ className: "w-16 h-16 mb-4 rounded-full bg-red-50 flex items-center justify-center",
367
+ "aria-hidden": "true",
368
+ children: /* @__PURE__ */ jsxs(
369
+ "svg",
370
+ {
371
+ xmlns: "http://www.w3.org/2000/svg",
372
+ width: "32",
373
+ height: "32",
374
+ viewBox: "0 0 24 24",
375
+ fill: "none",
376
+ stroke: "currentColor",
377
+ strokeWidth: "2",
378
+ strokeLinecap: "round",
379
+ strokeLinejoin: "round",
380
+ className: "text-red-500",
381
+ children: [
382
+ /* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" }),
383
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
384
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
385
+ ]
386
+ }
387
+ )
388
+ }
389
+ ),
390
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-foreground mb-2", children: title }),
391
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-6 max-w-sm", children: message }),
392
+ onRetry && /* @__PURE__ */ jsxs(
393
+ "button",
394
+ {
395
+ onClick: onRetry,
396
+ className: "inline-flex items-center justify-center rounded-md text-sm font-medium border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-9 px-4 py-2 transition-colors",
397
+ "aria-label": "Retry loading content",
398
+ children: [
399
+ /* @__PURE__ */ jsxs(
400
+ "svg",
401
+ {
402
+ xmlns: "http://www.w3.org/2000/svg",
403
+ width: "16",
404
+ height: "16",
405
+ viewBox: "0 0 24 24",
406
+ fill: "none",
407
+ stroke: "currentColor",
408
+ strokeWidth: "2",
409
+ strokeLinecap: "round",
410
+ strokeLinejoin: "round",
411
+ className: "mr-2",
412
+ "aria-hidden": "true",
413
+ children: [
414
+ /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8" }),
415
+ /* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" })
416
+ ]
417
+ }
418
+ ),
419
+ "Try Again"
420
+ ]
421
+ }
422
+ )
423
+ ]
424
+ }
425
+ );
426
+ }
427
+ var ApiErrorBoundary = class extends React12.Component {
428
+ constructor(props) {
429
+ super(props);
430
+ this.reset = () => {
431
+ this.setState({ hasError: false, error: null });
432
+ };
433
+ this.state = { hasError: false, error: null };
434
+ }
435
+ static getDerivedStateFromError(error2) {
436
+ return { hasError: true, error: error2 };
437
+ }
438
+ componentDidCatch(error2, info2) {
439
+ this.props.onError?.(error2, info2);
440
+ }
441
+ render() {
442
+ if (this.state.hasError && this.state.error) {
443
+ if (this.props.fallback) {
444
+ return this.props.fallback({ error: this.state.error, reset: this.reset });
445
+ }
446
+ return /* @__PURE__ */ jsx(
447
+ ErrorState,
448
+ {
449
+ message: this.state.error.message || "An unexpected error occurred",
450
+ onRetry: this.reset
451
+ }
452
+ );
453
+ }
454
+ return this.props.children;
455
+ }
456
+ };
457
+ function PageLoader({ rows = 5, className }) {
458
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full space-y-3 p-4", className), "aria-busy": "true", "aria-label": "Loading", children: [
459
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-1/3 rounded-md bg-muted animate-pulse" }),
460
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsx(
461
+ "div",
462
+ {
463
+ className: "h-12 w-full rounded-md bg-muted animate-pulse",
464
+ style: { opacity: 1 - i * 0.1 }
465
+ },
466
+ i
467
+ )) })
468
+ ] });
469
+ }
470
+ function QueryProvider({ children }) {
471
+ const [queryClient] = useState(
472
+ () => new QueryClient({
473
+ defaultOptions: {
474
+ queries: {
475
+ staleTime: 5 * 60 * 1e3,
476
+ refetchOnWindowFocus: false
477
+ }
478
+ }
479
+ })
480
+ );
481
+ return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children });
482
+ }
483
+ function Sidebar({
484
+ appName,
485
+ sections,
486
+ userDropdown,
487
+ className,
488
+ collapsible = true,
489
+ defaultCollapsed = false
490
+ }) {
491
+ const pathname = usePathname();
492
+ const [collapsed, setCollapsed] = useState(defaultCollapsed);
493
+ const isActivePath = (href) => {
494
+ if (href === "/") {
495
+ return pathname === "/";
496
+ }
497
+ return pathname.startsWith(href);
498
+ };
499
+ return /* @__PURE__ */ jsxs(
500
+ "div",
501
+ {
502
+ className: cn(
503
+ "fixed left-0 inset-y-0 z-30 flex flex-col bg-gray-900 text-white transition-all duration-200",
504
+ collapsed ? "w-20" : "w-64",
505
+ className
506
+ ),
507
+ children: [
508
+ /* @__PURE__ */ jsx("div", { className: "p-4 border-b border-gray-800", children: /* @__PURE__ */ jsx(
509
+ Link,
510
+ {
511
+ href: "/",
512
+ className: cn(
513
+ "font-bold hover:text-primary-400 transition-colors",
514
+ collapsed ? "text-lg" : "text-xl"
515
+ ),
516
+ children: collapsed ? appName.substring(0, 2).toUpperCase() : appName
517
+ }
518
+ ) }),
519
+ /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-y-auto p-4 space-y-6", children: sections.map((section, idx) => /* @__PURE__ */ jsxs("div", { children: [
520
+ section.title && !collapsed && /* @__PURE__ */ jsx("h3", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2 px-3", children: section.title }),
521
+ /* @__PURE__ */ jsx("div", { className: "space-y-1", children: section.links.map((link) => {
522
+ const isActive = isActivePath(link.href);
523
+ return /* @__PURE__ */ jsxs(
524
+ Link,
525
+ {
526
+ href: link.href,
527
+ className: cn(
528
+ "flex items-center gap-3 px-3 py-2 rounded-md text-sm font-medium transition-colors",
529
+ isActive ? "bg-primary-600 text-white" : "text-gray-300 hover:bg-gray-800 hover:text-white",
530
+ collapsed && "justify-center"
531
+ ),
532
+ children: [
533
+ link.icon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 w-5 h-5", children: link.icon }),
534
+ !collapsed && /* @__PURE__ */ jsx("span", { children: link.label })
535
+ ]
536
+ },
537
+ link.href
538
+ );
539
+ }) })
540
+ ] }, idx)) }),
541
+ userDropdown && /* @__PURE__ */ jsx("div", { className: "p-4 border-t border-gray-800", children: userDropdown }),
542
+ collapsible && /* @__PURE__ */ jsx("div", { className: cn("p-4 border-t border-gray-800", userDropdown && "border-t-0"), children: /* @__PURE__ */ jsx(
543
+ Button,
544
+ {
545
+ variant: "ghost",
546
+ size: "sm",
547
+ onClick: () => setCollapsed(!collapsed),
548
+ className: "w-full text-gray-400 hover:text-white hover:bg-gray-800",
549
+ children: collapsed ? /* @__PURE__ */ jsx(ChevronRight, { className: "w-5 h-5" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
550
+ /* @__PURE__ */ jsx(ChevronLeft, { className: "w-5 h-5 mr-2" }),
551
+ /* @__PURE__ */ jsx("span", { children: "Collapse" })
552
+ ] })
553
+ }
554
+ ) })
555
+ ]
556
+ }
557
+ );
558
+ }
559
+ function SidebarLayout({ children, collapsed = false }) {
560
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-screen bg-gray-50", children: [
561
+ /* @__PURE__ */ jsx("div", { className: cn("flex-shrink-0 transition-all duration-200", collapsed ? "w-20" : "w-64") }),
562
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsx("main", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6 sm:py-8", children }) })
563
+ ] });
564
+ }
565
+ function SafeHtml({ html, as: Tag = "div", ...props }) {
566
+ const sanitized = DOMPurify.sanitize(html, { ALLOW_DATA_ATTR: false });
567
+ return /* @__PURE__ */ jsx(Tag, { ...props, dangerouslySetInnerHTML: { __html: sanitized } });
568
+ }
569
+ var TOAST_LIMIT = 5;
570
+ var TOAST_AUTO_DISMISS = 5e3;
571
+ var toastTimeouts = /* @__PURE__ */ new Map();
572
+ function addToRemoveQueue(toastId, delay) {
573
+ if (toastTimeouts.has(toastId)) {
574
+ return;
575
+ }
576
+ const timeout = setTimeout(() => {
577
+ toastTimeouts.delete(toastId);
578
+ dispatch({ type: "REMOVE_TOAST", toastId });
579
+ }, delay);
580
+ toastTimeouts.set(toastId, timeout);
581
+ }
582
+ function reducer(state, action) {
583
+ switch (action.type) {
584
+ case "ADD_TOAST":
585
+ return {
586
+ ...state,
587
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
588
+ };
589
+ case "UPDATE_TOAST":
590
+ return {
591
+ ...state,
592
+ toasts: state.toasts.map(
593
+ (t) => t.id === action.toast.id ? { ...t, ...action.toast } : t
594
+ )
595
+ };
596
+ case "DISMISS_TOAST": {
597
+ const { toastId } = action;
598
+ if (toastId) {
599
+ addToRemoveQueue(toastId, 300);
600
+ } else {
601
+ state.toasts.forEach((t) => addToRemoveQueue(t.id, 300));
602
+ }
603
+ return state;
604
+ }
605
+ case "REMOVE_TOAST":
606
+ if (action.toastId === void 0) {
607
+ return { ...state, toasts: [] };
608
+ }
609
+ return {
610
+ ...state,
611
+ toasts: state.toasts.filter((t) => t.id !== action.toastId)
612
+ };
613
+ }
614
+ }
615
+ var listeners = [];
616
+ var memoryState = { toasts: [] };
617
+ function dispatch(action) {
618
+ memoryState = reducer(memoryState, action);
619
+ listeners.forEach((listener) => listener(memoryState));
620
+ }
621
+ var count = 0;
622
+ function genId() {
623
+ count = (count + 1) % Number.MAX_VALUE;
624
+ return count.toString();
625
+ }
626
+ function toast(props) {
627
+ const id = genId();
628
+ const duration = props.duration ?? TOAST_AUTO_DISMISS;
629
+ dispatch({
630
+ type: "ADD_TOAST",
631
+ toast: { ...props, id }
632
+ });
633
+ if (duration > 0) {
634
+ addToRemoveQueue(id, duration);
635
+ }
636
+ const update = (updateProps) => dispatch({ type: "UPDATE_TOAST", toast: { ...updateProps, id } });
637
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
638
+ return { id, dismiss, update };
639
+ }
640
+ function clearAllToasts() {
641
+ toastTimeouts.forEach((timeout) => clearTimeout(timeout));
642
+ toastTimeouts.clear();
643
+ dispatch({ type: "REMOVE_TOAST", toastId: void 0 });
644
+ }
645
+ function useToast() {
646
+ const [state, setState] = React12.useState(memoryState);
647
+ React12.useEffect(() => {
648
+ listeners.push(setState);
649
+ return () => {
650
+ const index = listeners.indexOf(setState);
651
+ if (index > -1) {
652
+ listeners.splice(index, 1);
653
+ }
654
+ };
655
+ }, [state]);
656
+ return {
657
+ ...state,
658
+ toast,
659
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId }),
660
+ clear: clearAllToasts
661
+ };
662
+ }
663
+ var variantClasses = {
664
+ default: "bg-background border-border text-foreground",
665
+ destructive: "bg-destructive border-destructive text-destructive-foreground",
666
+ success: "bg-green-50 border-green-200 text-green-900",
667
+ warning: "bg-yellow-50 border-yellow-200 text-yellow-900",
668
+ info: "bg-blue-50 border-blue-200 text-blue-900"
669
+ };
670
+ function Toaster() {
671
+ const { toasts, dismiss } = useToast();
672
+ if (toasts.length === 0) return null;
673
+ return /* @__PURE__ */ jsx(
674
+ "div",
675
+ {
676
+ className: "fixed bottom-4 right-4 z-[100] flex flex-col gap-2 w-full max-w-sm",
677
+ role: "region",
678
+ "aria-label": "Notifications",
679
+ children: toasts.map((t) => /* @__PURE__ */ jsxs(
680
+ "div",
681
+ {
682
+ className: cn(
683
+ "rounded-lg border p-4 shadow-lg transition-all animate-in slide-in-from-bottom-2 fade-in-0",
684
+ variantClasses[t.variant ?? "default"]
685
+ ),
686
+ role: "status",
687
+ "aria-live": "polite",
688
+ children: [
689
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
690
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
691
+ t.title && /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold", children: t.title }),
692
+ t.description && /* @__PURE__ */ jsx("div", { className: "text-sm opacity-90 mt-1", children: t.description })
693
+ ] }),
694
+ /* @__PURE__ */ jsx(
695
+ "button",
696
+ {
697
+ onClick: () => dismiss(t.id),
698
+ className: "shrink-0 rounded-sm opacity-70 hover:opacity-100 transition-opacity",
699
+ "aria-label": "Dismiss notification",
700
+ children: /* @__PURE__ */ jsxs(
701
+ "svg",
702
+ {
703
+ xmlns: "http://www.w3.org/2000/svg",
704
+ width: "16",
705
+ height: "16",
706
+ viewBox: "0 0 24 24",
707
+ fill: "none",
708
+ stroke: "currentColor",
709
+ strokeWidth: "2",
710
+ strokeLinecap: "round",
711
+ strokeLinejoin: "round",
712
+ "aria-hidden": "true",
713
+ children: [
714
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
715
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
716
+ ]
717
+ }
718
+ )
719
+ }
720
+ )
721
+ ] }),
722
+ t.action && /* @__PURE__ */ jsx("div", { className: "mt-2", children: t.action })
723
+ ]
724
+ },
725
+ t.id
726
+ ))
727
+ }
728
+ );
729
+ }
730
+
731
+ // src/components/toast/use-notify.ts
732
+ function success(messageOrOptions) {
733
+ const opts = typeof messageOrOptions === "string" ? { title: messageOrOptions } : messageOrOptions;
734
+ return toast({ variant: "success", ...opts });
735
+ }
736
+ function error(messageOrOptions) {
737
+ const opts = typeof messageOrOptions === "string" ? { title: messageOrOptions } : messageOrOptions;
738
+ return toast({ variant: "destructive", ...opts });
739
+ }
740
+ function warning(messageOrOptions) {
741
+ const opts = typeof messageOrOptions === "string" ? { title: messageOrOptions } : messageOrOptions;
742
+ return toast({ variant: "warning", ...opts });
743
+ }
744
+ function info(messageOrOptions) {
745
+ const opts = typeof messageOrOptions === "string" ? { title: messageOrOptions } : messageOrOptions;
746
+ return toast({ variant: "info", ...opts });
747
+ }
748
+ var notify = { success, error, warning, info };
749
+ function useNotify() {
750
+ return notify;
751
+ }
752
+ function EmptyState({
753
+ title,
754
+ description,
755
+ action,
756
+ className
757
+ }) {
758
+ return /* @__PURE__ */ jsxs(
759
+ "div",
760
+ {
761
+ className: cn(
762
+ "flex flex-col items-center justify-center py-12 px-4 text-center",
763
+ className
764
+ ),
765
+ role: "status",
766
+ "aria-live": "polite",
767
+ children: [
768
+ /* @__PURE__ */ jsx("h3", { className: "text-xl font-semibold text-foreground mb-3", children: title }),
769
+ description && /* @__PURE__ */ jsx("p", { className: "text-base text-muted-foreground mb-8 max-w-md leading-relaxed", children: description }),
770
+ action && /* @__PURE__ */ jsx(
771
+ "button",
772
+ {
773
+ onClick: action.onClick,
774
+ className: "inline-flex items-center justify-center rounded-md text-sm font-medium bg-primary text-primary-foreground shadow hover:bg-primary/90 h-9 px-4 py-2 transition-colors",
775
+ "aria-label": action.label,
776
+ children: action.label
777
+ }
778
+ )
779
+ ]
780
+ }
781
+ );
782
+ }
783
+ var DialogContext = React12.createContext(null);
784
+ function useDialogContext() {
785
+ const context = React12.useContext(DialogContext);
786
+ if (!context) {
787
+ throw new Error("Dialog components must be used within BaseDialog");
788
+ }
789
+ return context;
790
+ }
791
+ var sizeClasses = {
792
+ sm: "max-w-sm",
793
+ md: "max-w-md",
794
+ lg: "max-w-lg"
795
+ };
796
+ function BaseDialog({
797
+ open,
798
+ onOpenChange,
799
+ children,
800
+ size = "md",
801
+ loading = false
802
+ }) {
803
+ const [isLoading, setIsLoading] = React12.useState(loading);
804
+ const [canClose, setCanClose] = React12.useState(!loading);
805
+ React12.useEffect(() => {
806
+ setIsLoading(loading);
807
+ setCanClose(!loading);
808
+ }, [loading]);
809
+ const handleOpenChange = React12.useCallback(
810
+ (newOpen) => {
811
+ if (!newOpen && !canClose) {
812
+ return;
813
+ }
814
+ onOpenChange(newOpen);
815
+ },
816
+ [canClose, onOpenChange]
817
+ );
818
+ const contextValue = React12.useMemo(
819
+ () => ({ isLoading, setIsLoading, canClose, setCanClose }),
820
+ [isLoading, canClose]
821
+ );
822
+ return /* @__PURE__ */ jsx(DialogContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(DialogPrimitive.Root, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
823
+ /* @__PURE__ */ jsx(DialogPrimitive.Overlay, { className: "fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0" }),
824
+ /* @__PURE__ */ jsx(
825
+ DialogPrimitive.Content,
826
+ {
827
+ className: cn(
828
+ "fixed left-[50%] top-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
829
+ sizeClasses[size]
830
+ ),
831
+ onInteractOutside: (e) => {
832
+ if (!canClose) e.preventDefault();
833
+ },
834
+ onEscapeKeyDown: (e) => {
835
+ if (!canClose) e.preventDefault();
836
+ },
837
+ children
838
+ }
839
+ )
840
+ ] }) }) });
841
+ }
842
+ function DialogHeader({ children, className }) {
843
+ const { canClose } = useDialogContext();
844
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-start justify-between", className), children: [
845
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-1.5", children }),
846
+ /* @__PURE__ */ jsxs(
847
+ DialogPrimitive.Close,
848
+ {
849
+ className: cn(
850
+ "rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none",
851
+ !canClose && "pointer-events-none opacity-30"
852
+ ),
853
+ disabled: !canClose,
854
+ children: [
855
+ /* @__PURE__ */ jsxs(
856
+ "svg",
857
+ {
858
+ xmlns: "http://www.w3.org/2000/svg",
859
+ width: "16",
860
+ height: "16",
861
+ viewBox: "0 0 24 24",
862
+ fill: "none",
863
+ stroke: "currentColor",
864
+ strokeWidth: "2",
865
+ strokeLinecap: "round",
866
+ strokeLinejoin: "round",
867
+ children: [
868
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
869
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
870
+ ]
871
+ }
872
+ ),
873
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
874
+ ]
875
+ }
876
+ )
877
+ ] });
878
+ }
879
+ function DialogTitle({ children, className }) {
880
+ return /* @__PURE__ */ jsx(
881
+ DialogPrimitive.Title,
882
+ {
883
+ className: cn(
884
+ "text-lg font-semibold leading-none tracking-tight",
885
+ className
886
+ ),
887
+ children
888
+ }
889
+ );
890
+ }
891
+ function DialogBody({ children, className }) {
892
+ return /* @__PURE__ */ jsx("div", { className: cn("py-4 overflow-y-auto", className), children });
893
+ }
894
+ function DialogFooter({ children, className }) {
895
+ return /* @__PURE__ */ jsx(
896
+ "div",
897
+ {
898
+ className: cn(
899
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
900
+ className
901
+ ),
902
+ children
903
+ }
904
+ );
905
+ }
906
+ BaseDialog.Header = DialogHeader;
907
+ BaseDialog.Title = DialogTitle;
908
+ BaseDialog.Body = DialogBody;
909
+ BaseDialog.Footer = DialogFooter;
910
+ var sizeClasses2 = {
911
+ sm: "px-2 py-0.5 text-xs",
912
+ md: "px-2.5 py-0.5 text-xs"
913
+ };
914
+ function StatusBadge({
915
+ status,
916
+ config,
917
+ size = "md",
918
+ className
919
+ }) {
920
+ const entry = config[status];
921
+ if (!entry) {
922
+ return /* @__PURE__ */ jsx(
923
+ "span",
924
+ {
925
+ className: cn(
926
+ "inline-flex items-center rounded-full font-medium bg-gray-100 text-gray-700 border border-gray-200",
927
+ sizeClasses2[size],
928
+ className
929
+ ),
930
+ children: status
931
+ }
932
+ );
933
+ }
934
+ return /* @__PURE__ */ jsx(
935
+ "span",
936
+ {
937
+ className: cn(
938
+ "inline-flex items-center rounded-full font-medium",
939
+ sizeClasses2[size],
940
+ entry.className,
941
+ className
942
+ ),
943
+ children: entry.label
944
+ }
945
+ );
946
+ }
947
+ function TableSkeleton({
948
+ rows = 5,
949
+ columns = 4,
950
+ className
951
+ }) {
952
+ return /* @__PURE__ */ jsxs("div", { className: cn("bg-background rounded-lg border", className), children: [
953
+ /* @__PURE__ */ jsx("div", { className: "p-4 border-b", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-4", children: [
954
+ /* @__PURE__ */ jsx("div", { className: "h-10 w-full max-w-sm animate-pulse rounded-md bg-gray-200" }),
955
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsx("div", { className: "h-10 w-24 animate-pulse rounded-md bg-gray-200" }) })
956
+ ] }) }),
957
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
958
+ /* @__PURE__ */ jsx("thead", { className: "border-b bg-muted/50", children: /* @__PURE__ */ jsx("tr", { children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx("th", { className: "p-4 text-left", children: /* @__PURE__ */ jsx("div", { className: "h-4 w-24 animate-pulse rounded-md bg-gray-200" }) }, i)) }) }),
959
+ /* @__PURE__ */ jsx("tbody", { children: Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ jsx("tr", { className: "border-b last:border-b-0", children: Array.from({ length: columns }).map((_2, colIndex) => /* @__PURE__ */ jsx("td", { className: "p-4", children: /* @__PURE__ */ jsx("div", { className: "h-4 w-full max-w-[200px] animate-pulse rounded-md bg-gray-200" }) }, colIndex)) }, rowIndex)) })
960
+ ] }) }),
961
+ /* @__PURE__ */ jsxs("div", { className: "p-4 border-t flex justify-between items-center", children: [
962
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-40 animate-pulse rounded-md bg-gray-200" }),
963
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
964
+ /* @__PURE__ */ jsx("div", { className: "h-9 w-20 animate-pulse rounded-md bg-gray-200" }),
965
+ /* @__PURE__ */ jsx("div", { className: "h-9 w-20 animate-pulse rounded-md bg-gray-200" })
966
+ ] })
967
+ ] })
968
+ ] });
969
+ }
970
+ function DashboardSkeleton({
971
+ cards = 4,
972
+ className
973
+ }) {
974
+ return /* @__PURE__ */ jsx("div", { className: cn("grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4", className), children: Array.from({ length: cards }).map((_, i) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-background p-6", children: [
975
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
976
+ /* @__PURE__ */ jsx("div", { className: "h-4 w-24 animate-pulse rounded-md bg-gray-200" }),
977
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-pulse rounded-md bg-gray-200" })
978
+ ] }),
979
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-20 animate-pulse rounded-md bg-gray-200 mb-2" }),
980
+ /* @__PURE__ */ jsx("div", { className: "h-3 w-32 animate-pulse rounded-md bg-gray-200" })
981
+ ] }, i)) });
982
+ }
983
+ function StepIndicator({ steps, currentIndex, className = "" }) {
984
+ return /* @__PURE__ */ jsx("ol", { className: `flex items-center gap-0 ${className}`, children: steps.map((step, index) => {
985
+ const isCompleted = index < currentIndex;
986
+ const isActive = index === currentIndex;
987
+ const isLast = index === steps.length - 1;
988
+ return /* @__PURE__ */ jsxs("li", { className: `flex items-center ${!isLast ? "flex-1" : ""}`, children: [
989
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
990
+ /* @__PURE__ */ jsx(
991
+ "div",
992
+ {
993
+ className: [
994
+ "flex h-8 w-8 items-center justify-center rounded-full border-2 text-sm font-medium transition-colors",
995
+ isCompleted ? "border-primary-600 bg-primary-600 text-white" : isActive ? "border-primary-600 bg-white text-primary-600" : "border-gray-300 bg-white text-gray-400"
996
+ ].join(" "),
997
+ children: isCompleted ? /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) : index + 1
998
+ }
999
+ ),
1000
+ /* @__PURE__ */ jsx(
1001
+ "span",
1002
+ {
1003
+ className: [
1004
+ "mt-1 text-xs font-medium",
1005
+ isActive ? "text-primary-600" : isCompleted ? "text-gray-600" : "text-gray-400"
1006
+ ].join(" "),
1007
+ children: step.label
1008
+ }
1009
+ )
1010
+ ] }),
1011
+ !isLast && /* @__PURE__ */ jsx(
1012
+ "div",
1013
+ {
1014
+ className: [
1015
+ "h-0.5 flex-1 mx-2 mb-4 transition-colors",
1016
+ isCompleted ? "bg-primary-600" : "bg-gray-200"
1017
+ ].join(" ")
1018
+ }
1019
+ )
1020
+ ] }, index);
1021
+ }) });
1022
+ }
1023
+
1024
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertTitle, ApiErrorBoundary, BaseDialog, Calendar, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, DashboardSkeleton, EmptyState, ErrorState, FeatureGate, PageLoader, Popover, PopoverContent, PopoverTrigger, Progress, QueryProvider, SafeHtml, ScrollArea, ScrollBar, Separator, Sidebar, SidebarLayout, Skeleton, StatusBadge, StepIndicator, TableSkeleton, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, clearAllToasts, notify, toast, useDialogContext, useNotify, useToast };
1025
+ //# sourceMappingURL=chunk-G2AM3DBU.mjs.map
1026
+ //# sourceMappingURL=chunk-G2AM3DBU.mjs.map