@cortexasystem/ui 0.1.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,1977 @@
1
+ // src/providers/theme-provider.tsx
2
+ import {
3
+ createContext,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useState
8
+ } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ var ThemeProviderContext = createContext(void 0);
11
+ function resolveTheme(theme) {
12
+ if (theme === "system") {
13
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
14
+ }
15
+ return theme;
16
+ }
17
+ function ThemeProvider({
18
+ children,
19
+ defaultTheme = "system",
20
+ forcedTheme,
21
+ storageKey = "cortexa-theme"
22
+ }) {
23
+ const [theme, setThemeState] = useState(() => {
24
+ if (typeof window === "undefined") {
25
+ return forcedTheme ?? defaultTheme;
26
+ }
27
+ return window.localStorage.getItem(storageKey) ?? forcedTheme ?? defaultTheme;
28
+ });
29
+ const activeTheme = forcedTheme ?? theme;
30
+ const resolvedTheme = typeof window === "undefined" ? "light" : resolveTheme(activeTheme);
31
+ useEffect(() => {
32
+ const root = document.documentElement;
33
+ root.classList.remove("light", "dark");
34
+ root.classList.add(resolvedTheme);
35
+ }, [resolvedTheme]);
36
+ useEffect(() => {
37
+ if (forcedTheme || typeof window === "undefined") {
38
+ return;
39
+ }
40
+ window.localStorage.setItem(storageKey, theme);
41
+ }, [forcedTheme, storageKey, theme]);
42
+ const value = useMemo(
43
+ () => ({
44
+ theme: activeTheme,
45
+ resolvedTheme,
46
+ setTheme: (nextTheme) => {
47
+ if (!forcedTheme) {
48
+ setThemeState(nextTheme);
49
+ }
50
+ }
51
+ }),
52
+ [activeTheme, forcedTheme, resolvedTheme]
53
+ );
54
+ return /* @__PURE__ */ jsx(ThemeProviderContext.Provider, { value, children });
55
+ }
56
+ function useTheme() {
57
+ const context = useContext(ThemeProviderContext);
58
+ if (!context) {
59
+ throw new Error("useTheme must be used within ThemeProvider");
60
+ }
61
+ return context;
62
+ }
63
+
64
+ // src/lib/cn.ts
65
+ import { clsx } from "clsx";
66
+ import { twMerge } from "tailwind-merge";
67
+ function cn(...inputs) {
68
+ return twMerge(clsx(inputs));
69
+ }
70
+
71
+ // src/assets/isotipo-cortexa-dark.png
72
+ var isotipo_cortexa_dark_default = "./isotipo-cortexa-dark-F2MDSEEV.png";
73
+
74
+ // src/assets/isotipo-cortexa-light.png
75
+ var isotipo_cortexa_light_default = "./isotipo-cortexa-light-LV3O6ASR.png";
76
+
77
+ // src/components/branding/brand-logo.tsx
78
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
79
+ var sizeMap = {
80
+ sm: { icon: "h-6 w-6", text: "text-sm", gap: "gap-2" },
81
+ md: { icon: "h-7 w-7", text: "text-lg", gap: "gap-3" },
82
+ lg: { icon: "h-9 w-9", text: "text-xl", gap: "gap-3" }
83
+ };
84
+ function BrandLogo({ className, size = "md", href }) {
85
+ const { resolvedTheme } = useTheme();
86
+ const isDark = resolvedTheme === "dark";
87
+ const s = sizeMap[size];
88
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
89
+ /* @__PURE__ */ jsx2(
90
+ "div",
91
+ {
92
+ className: cn(
93
+ "flex shrink-0 items-center justify-center rounded-md",
94
+ s.icon,
95
+ isDark ? "bg-[var(--color-brand)] p-1" : "bg-transparent"
96
+ ),
97
+ children: /* @__PURE__ */ jsx2(
98
+ "img",
99
+ {
100
+ src: isDark ? isotipo_cortexa_dark_default : isotipo_cortexa_light_default,
101
+ alt: "Cortexa",
102
+ className: "max-h-full max-w-full object-contain"
103
+ }
104
+ )
105
+ }
106
+ ),
107
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline", children: [
108
+ /* @__PURE__ */ jsx2(
109
+ "span",
110
+ {
111
+ className: cn(
112
+ "font-bold leading-none",
113
+ s.text,
114
+ isDark ? "text-white" : "text-[var(--color-brand)]"
115
+ ),
116
+ children: "Cortexa"
117
+ }
118
+ ),
119
+ /* @__PURE__ */ jsx2(
120
+ "span",
121
+ {
122
+ className: cn(
123
+ "ml-1 font-normal leading-none",
124
+ s.text,
125
+ isDark ? "text-white" : "text-[var(--color-accent-blue)]"
126
+ ),
127
+ children: "Fiscal"
128
+ }
129
+ )
130
+ ] })
131
+ ] });
132
+ const wrapperClass = cn("flex items-center", s.gap, className);
133
+ if (href) {
134
+ return /* @__PURE__ */ jsx2("a", { href, className: wrapperClass, "aria-label": "Cortexa Fiscal \u2014 Inicio", children: content });
135
+ }
136
+ return /* @__PURE__ */ jsx2("div", { className: wrapperClass, "aria-label": "Cortexa Fiscal", children: content });
137
+ }
138
+
139
+ // src/components/data-display/icons.tsx
140
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
141
+ var toneStyles = {
142
+ brand: "bg-[var(--color-brand)]/10 text-[var(--color-brand)]",
143
+ info: "bg-[var(--color-info-bg)] text-[var(--color-accent-blue)]",
144
+ success: "bg-[var(--color-success-bg)] text-[var(--color-success)]",
145
+ warning: "bg-[var(--color-warning-bg)] text-[var(--color-warning)]",
146
+ danger: "bg-destructive/10 text-destructive",
147
+ neutral: "bg-muted text-muted-foreground"
148
+ };
149
+ var sizeStyles = {
150
+ sm: { wrapper: "h-8 w-8 rounded-lg", icon: "h-4 w-4" },
151
+ md: { wrapper: "h-10 w-10 rounded-lg", icon: "h-5 w-5" },
152
+ lg: { wrapper: "h-12 w-12 rounded-xl", icon: "h-6 w-6" }
153
+ };
154
+ function FeatureIcon({ className, icon: Icon2, tone = "brand", size = "md", iconClassName }) {
155
+ const classes = sizeStyles[size];
156
+ return /* @__PURE__ */ jsx3("span", { className: cn("inline-flex items-center justify-center", classes.wrapper, toneStyles[tone], className), children: /* @__PURE__ */ jsx3(Icon2, { className: cn(classes.icon, iconClassName) }) });
157
+ }
158
+ function ModuleIconButton({
159
+ className,
160
+ type = "button",
161
+ icon,
162
+ label,
163
+ description,
164
+ tone = "brand",
165
+ ...props
166
+ }) {
167
+ return /* @__PURE__ */ jsxs2(
168
+ "button",
169
+ {
170
+ type,
171
+ className: cn(
172
+ "group flex flex-col items-center gap-3 rounded-lg border border-border bg-card p-5 text-center transition-all hover:bg-accent/30 hover:border-[var(--color-accent-blue)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
173
+ className
174
+ ),
175
+ ...props,
176
+ children: [
177
+ /* @__PURE__ */ jsx3(
178
+ FeatureIcon,
179
+ {
180
+ icon,
181
+ tone,
182
+ size: "md",
183
+ className: "transition-colors group-hover:bg-[var(--color-brand)]/20"
184
+ }
185
+ ),
186
+ /* @__PURE__ */ jsxs2("span", { className: "grid gap-1", children: [
187
+ /* @__PURE__ */ jsx3("span", { className: "text-sm font-medium text-foreground", children: label }),
188
+ description ? /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: description }) : null
189
+ ] })
190
+ ]
191
+ }
192
+ );
193
+ }
194
+
195
+ // src/components/primitives/avatar.tsx
196
+ import * as React from "react";
197
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
198
+ import { jsx as jsx4 } from "react/jsx-runtime";
199
+ var Avatar = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
200
+ AvatarPrimitive.Root,
201
+ {
202
+ ref,
203
+ className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
204
+ ...props
205
+ }
206
+ ));
207
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
208
+ var AvatarImage = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(AvatarPrimitive.Image, { ref, className: cn("aspect-square h-full w-full", className), ...props }));
209
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
210
+ var AvatarFallback = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx4(
211
+ AvatarPrimitive.Fallback,
212
+ {
213
+ ref,
214
+ className: cn("flex h-full w-full items-center justify-center rounded-full bg-muted", className),
215
+ ...props
216
+ }
217
+ ));
218
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
219
+
220
+ // src/components/data-display/profile-avatar.tsx
221
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
222
+ var sizeMap2 = {
223
+ xs: { avatar: "h-8 w-8", text: "text-xs", dot: "h-2.5 w-2.5" },
224
+ sm: { avatar: "h-10 w-10", text: "text-sm", dot: "h-3 w-3" },
225
+ md: { avatar: "h-12 w-12", text: "text-base", dot: "h-3.5 w-3.5" },
226
+ lg: { avatar: "h-16 w-16", text: "text-lg", dot: "h-4 w-4" }
227
+ };
228
+ var statusMap = {
229
+ online: "bg-[var(--color-success)]",
230
+ away: "bg-[var(--color-warning)]",
231
+ offline: "bg-muted-foreground",
232
+ inactive: "bg-border"
233
+ };
234
+ function getInitials(name) {
235
+ return name.trim().split(/\s+/).slice(0, 2).map((part) => part[0]?.toUpperCase() ?? "").join("");
236
+ }
237
+ function ProfileAvatar({
238
+ className,
239
+ avatarClassName,
240
+ fallbackClassName,
241
+ name,
242
+ src,
243
+ alt,
244
+ initials,
245
+ size = "sm",
246
+ status
247
+ }) {
248
+ const classes = sizeMap2[size];
249
+ return /* @__PURE__ */ jsxs3("div", { className: cn("relative inline-flex", className), children: [
250
+ /* @__PURE__ */ jsxs3(Avatar, { className: cn(classes.avatar, avatarClassName), children: [
251
+ src ? /* @__PURE__ */ jsx5(AvatarImage, { src, alt: alt ?? name }) : null,
252
+ /* @__PURE__ */ jsx5(AvatarFallback, { className: cn("bg-[var(--color-brand)] text-white font-medium", classes.text, fallbackClassName), children: initials ?? getInitials(name) })
253
+ ] }),
254
+ status ? /* @__PURE__ */ jsx5(
255
+ "span",
256
+ {
257
+ "aria-hidden": "true",
258
+ className: cn("absolute bottom-0 right-0 rounded-full border-2 border-card", classes.dot, statusMap[status])
259
+ }
260
+ ) : null
261
+ ] });
262
+ }
263
+ function AvatarGroup({ className, users, size = "xs", limit = 4, extraLabel }) {
264
+ const visibleUsers = users.slice(0, limit);
265
+ const hiddenCount = Math.max(0, users.length - limit);
266
+ const classes = sizeMap2[size];
267
+ return /* @__PURE__ */ jsxs3("div", { className: cn("flex items-center gap-3", className), children: [
268
+ /* @__PURE__ */ jsxs3("div", { className: "flex -space-x-2", children: [
269
+ visibleUsers.map((user) => /* @__PURE__ */ jsx5(
270
+ ProfileAvatar,
271
+ {
272
+ name: user.name,
273
+ src: user.src,
274
+ initials: user.initials,
275
+ size,
276
+ status: user.status,
277
+ avatarClassName: "border-2 border-card"
278
+ },
279
+ user.id ?? user.name
280
+ )),
281
+ hiddenCount > 0 ? /* @__PURE__ */ jsxs3(
282
+ "div",
283
+ {
284
+ className: cn(
285
+ "flex items-center justify-center rounded-full border-2 border-card bg-muted text-muted-foreground font-medium",
286
+ classes.avatar,
287
+ classes.text
288
+ ),
289
+ children: [
290
+ "+",
291
+ hiddenCount
292
+ ]
293
+ }
294
+ ) : null
295
+ ] }),
296
+ extraLabel ? /* @__PURE__ */ jsx5("div", { className: "text-sm text-muted-foreground", children: extraLabel }) : null
297
+ ] });
298
+ }
299
+ function ProfileAvatarRow({ className, name, role, src, initials, status, size = "sm", aside }) {
300
+ return /* @__PURE__ */ jsxs3("div", { className: cn("flex items-center justify-between gap-3", className), children: [
301
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
302
+ /* @__PURE__ */ jsx5(ProfileAvatar, { name, src, initials, status, size }),
303
+ /* @__PURE__ */ jsxs3("div", { className: "grid gap-0.5", children: [
304
+ /* @__PURE__ */ jsx5("p", { className: "text-sm font-medium text-foreground", children: name }),
305
+ role ? /* @__PURE__ */ jsx5("p", { className: "text-xs text-muted-foreground", children: role }) : null
306
+ ] })
307
+ ] }),
308
+ aside
309
+ ] });
310
+ }
311
+
312
+ // src/components/data-display/typography.tsx
313
+ import { cva } from "class-variance-authority";
314
+ import { jsx as jsx6 } from "react/jsx-runtime";
315
+ var typographyVariants = cva("text-foreground", {
316
+ variants: {
317
+ variant: {
318
+ h1: "font-display text-4xl font-bold tracking-tight",
319
+ h2: "font-display text-3xl font-bold tracking-tight",
320
+ h3: "font-display text-2xl font-semibold tracking-tight",
321
+ h4: "text-xl font-semibold",
322
+ lead: "text-lg text-muted-foreground",
323
+ body: "text-base",
324
+ small: "text-sm text-muted-foreground",
325
+ muted: "text-sm text-muted-foreground",
326
+ code: "font-mono text-sm"
327
+ }
328
+ },
329
+ defaultVariants: {
330
+ variant: "body"
331
+ }
332
+ });
333
+ function Typography({
334
+ as,
335
+ className,
336
+ variant,
337
+ children,
338
+ ...props
339
+ }) {
340
+ const Component = as ?? "p";
341
+ return /* @__PURE__ */ jsx6(Component, { className: cn(typographyVariants({ variant }), className), ...props, children });
342
+ }
343
+
344
+ // src/components/primitives/card.tsx
345
+ import * as React2 from "react";
346
+ import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
347
+ var cardBaseClassName = "rounded-lg border bg-card text-card-foreground shadow-sm";
348
+ var Card = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx7("div", { ref, className: cn(cardBaseClassName, className), ...props }));
349
+ Card.displayName = "Card";
350
+ var ClickableCard = React2.forwardRef(
351
+ ({ className, type = "button", ...props }, ref) => /* @__PURE__ */ jsx7(
352
+ "button",
353
+ {
354
+ ref,
355
+ type,
356
+ className: cn(
357
+ cardBaseClassName,
358
+ "w-full cursor-pointer text-left transition-all hover:bg-accent/30 hover:border-[var(--color-accent-blue)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
359
+ className
360
+ ),
361
+ ...props
362
+ }
363
+ )
364
+ );
365
+ ClickableCard.displayName = "ClickableCard";
366
+ var CenteredIconCard = React2.forwardRef(
367
+ ({ className, type = "button", icon: Icon2, title, iconClassName, ...props }, ref) => /* @__PURE__ */ jsxs4(
368
+ "button",
369
+ {
370
+ ref,
371
+ type,
372
+ className: cn(
373
+ cardBaseClassName,
374
+ "flex w-full cursor-pointer flex-col items-center justify-center gap-4 p-6 text-center transition-all hover:bg-accent/30 hover:border-[var(--color-accent-blue)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
375
+ className
376
+ ),
377
+ ...props,
378
+ children: [
379
+ /* @__PURE__ */ jsx7("span", { className: "flex h-12 w-12 items-center justify-center rounded-xl bg-[var(--color-brand)]/10 text-[var(--color-brand)]", children: /* @__PURE__ */ jsx7(Icon2, { className: cn("h-6 w-6", iconClassName) }) }),
380
+ /* @__PURE__ */ jsx7("span", { className: "text-sm font-semibold text-foreground", children: title })
381
+ ]
382
+ }
383
+ )
384
+ );
385
+ CenteredIconCard.displayName = "CenteredIconCard";
386
+ var CardHeader = React2.forwardRef(
387
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx7("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
388
+ );
389
+ CardHeader.displayName = "CardHeader";
390
+ var CardTitle = React2.forwardRef(
391
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx7("div", { ref, className: cn("text-2xl font-semibold leading-none tracking-tight", className), ...props })
392
+ );
393
+ CardTitle.displayName = "CardTitle";
394
+ var CardDescription = React2.forwardRef(
395
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx7("div", { ref, className: cn("text-sm text-muted-foreground", className), ...props })
396
+ );
397
+ CardDescription.displayName = "CardDescription";
398
+ var CardContent = React2.forwardRef(
399
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx7("div", { ref, className: cn("p-6 pt-0", className), ...props })
400
+ );
401
+ CardContent.displayName = "CardContent";
402
+ var CardFooter = React2.forwardRef(
403
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx7("div", { ref, className: cn("flex items-center p-6 pt-0", className), ...props })
404
+ );
405
+ CardFooter.displayName = "CardFooter";
406
+
407
+ // src/components/feedback/skeleton.tsx
408
+ import { jsx as jsx8 } from "react/jsx-runtime";
409
+ function Skeleton({ className, ...props }) {
410
+ return /* @__PURE__ */ jsx8("div", { className: cn("animate-pulse rounded-md bg-muted", className), ...props });
411
+ }
412
+
413
+ // src/components/feedback/spinner.tsx
414
+ import { Loader2 } from "lucide-react";
415
+ import { jsx as jsx9 } from "react/jsx-runtime";
416
+ var sizeMap3 = {
417
+ sm: "h-4 w-4",
418
+ md: "h-5 w-5",
419
+ lg: "h-7 w-7"
420
+ };
421
+ function Spinner({ className, size = "md" }) {
422
+ return /* @__PURE__ */ jsx9(Loader2, { className: cn("animate-spin text-current", sizeMap3[size], className) });
423
+ }
424
+
425
+ // src/components/tables/table.tsx
426
+ import * as React3 from "react";
427
+ import { jsx as jsx10 } from "react/jsx-runtime";
428
+ var Table = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx10("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props }) }));
429
+ Table.displayName = "Table";
430
+ var TableHeader = React3.forwardRef(
431
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10("thead", { ref, className: cn("[&_tr]:border-b", className), ...props })
432
+ );
433
+ TableHeader.displayName = "TableHeader";
434
+ var TableBody = React3.forwardRef(
435
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props })
436
+ );
437
+ TableBody.displayName = "TableBody";
438
+ var TableFooter = React3.forwardRef(
439
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
440
+ "tfoot",
441
+ {
442
+ ref,
443
+ className: cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className),
444
+ ...props
445
+ }
446
+ )
447
+ );
448
+ TableFooter.displayName = "TableFooter";
449
+ var TableRow = React3.forwardRef(
450
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
451
+ "tr",
452
+ {
453
+ ref,
454
+ className: cn("border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", className),
455
+ ...props
456
+ }
457
+ )
458
+ );
459
+ TableRow.displayName = "TableRow";
460
+ var TableHead = React3.forwardRef(
461
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
462
+ "th",
463
+ {
464
+ ref,
465
+ className: cn("h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0", className),
466
+ ...props
467
+ }
468
+ )
469
+ );
470
+ TableHead.displayName = "TableHead";
471
+ var TableCell = React3.forwardRef(
472
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10("td", { ref, className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className), ...props })
473
+ );
474
+ TableCell.displayName = "TableCell";
475
+ var TableCaption = React3.forwardRef(
476
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx10("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props })
477
+ );
478
+ TableCaption.displayName = "TableCaption";
479
+
480
+ // src/components/feedback/loading-state.tsx
481
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
482
+ function LoadingState({
483
+ className,
484
+ title = "Cargando datos",
485
+ description = "Estamos preparando la informacion para ti.",
486
+ size = "md",
487
+ icon
488
+ }) {
489
+ return /* @__PURE__ */ jsxs5(
490
+ "div",
491
+ {
492
+ role: "status",
493
+ "aria-live": "polite",
494
+ className: cn("flex items-center gap-3 rounded-xl border border-border bg-card px-4 py-3 text-foreground", className),
495
+ children: [
496
+ icon ?? /* @__PURE__ */ jsx11(Spinner, { size, className: "text-primary" }),
497
+ /* @__PURE__ */ jsxs5("div", { className: "grid gap-0.5", children: [
498
+ /* @__PURE__ */ jsx11("p", { className: "text-sm font-medium", children: title }),
499
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-muted-foreground", children: description })
500
+ ] })
501
+ ]
502
+ }
503
+ );
504
+ }
505
+ function LoadingCard({ className, rows = 3 }) {
506
+ return /* @__PURE__ */ jsx11(Card, { className, children: /* @__PURE__ */ jsxs5(CardContent, { className: "grid gap-3 p-5", children: [
507
+ /* @__PURE__ */ jsx11(Skeleton, { className: "h-6 w-40" }),
508
+ Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsx11(Skeleton, { className: cn("h-4", index === rows - 1 ? "w-2/3" : "w-full") }, index)),
509
+ /* @__PURE__ */ jsx11(Skeleton, { className: "mt-1 h-10 w-full rounded-lg" })
510
+ ] }) });
511
+ }
512
+ function LoadingTableRows({ className, columns = 5, rows = 4 }) {
513
+ return /* @__PURE__ */ jsx11("div", { className: cn("rounded-xl border", className), children: /* @__PURE__ */ jsxs5(Table, { children: [
514
+ /* @__PURE__ */ jsx11(TableHeader, { children: /* @__PURE__ */ jsx11(TableRow, { children: Array.from({ length: columns }).map((_, index) => /* @__PURE__ */ jsx11(TableHead, { children: /* @__PURE__ */ jsx11(Skeleton, { className: "h-4 w-20" }) }, index)) }) }),
515
+ /* @__PURE__ */ jsx11(TableBody, { children: Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ jsx11(TableRow, { children: Array.from({ length: columns }).map((_2, columnIndex) => /* @__PURE__ */ jsx11(TableCell, { children: /* @__PURE__ */ jsx11(Skeleton, { className: cn("h-4", columnIndex === 0 ? "w-24" : "w-full") }) }, columnIndex)) }, rowIndex)) })
516
+ ] }) });
517
+ }
518
+
519
+ // src/components/feedback/notification.tsx
520
+ import { AlertCircle, AlertTriangle, CheckCircle2, Info, Loader2 as Loader22 } from "lucide-react";
521
+ import { toast } from "sonner";
522
+
523
+ // src/components/primitives/button.tsx
524
+ import * as React4 from "react";
525
+ import { Slot } from "@radix-ui/react-slot";
526
+ import { cva as cva2 } from "class-variance-authority";
527
+ import { jsx as jsx12 } from "react/jsx-runtime";
528
+ var buttonVariants = cva2(
529
+ "inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
530
+ {
531
+ variants: {
532
+ variant: {
533
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
534
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
535
+ outline: "border border-input bg-background text-foreground hover:bg-accent hover:text-accent-foreground",
536
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
537
+ ghost: "text-foreground shadow-none hover:bg-accent hover:text-accent-foreground",
538
+ link: "h-auto px-0 py-0 text-primary underline-offset-4 shadow-none hover:underline"
539
+ },
540
+ size: {
541
+ default: "h-10 px-4 py-2",
542
+ sm: "h-9 rounded-md px-3",
543
+ lg: "h-11 rounded-md px-8",
544
+ icon: "h-10 w-10"
545
+ }
546
+ },
547
+ defaultVariants: {
548
+ variant: "default",
549
+ size: "default"
550
+ }
551
+ }
552
+ );
553
+ var Button = React4.forwardRef(
554
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
555
+ const Comp = asChild ? Slot : "button";
556
+ return /* @__PURE__ */ jsx12(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
557
+ }
558
+ );
559
+ Button.displayName = "Button";
560
+
561
+ // src/components/feedback/notification.tsx
562
+ import { jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
563
+ var notificationStyles = {
564
+ info: "bg-[var(--color-info-bg)] text-[var(--color-accent-blue)] border-[var(--color-accent-blue)]/30",
565
+ success: "bg-[var(--color-success-bg)] text-[var(--color-success)] border-[var(--color-success)]/30",
566
+ warning: "bg-[var(--color-warning-bg)] text-[var(--color-warning)] border-[var(--color-warning)]/30",
567
+ danger: "bg-destructive/10 text-destructive border-destructive/30",
568
+ loading: "bg-[var(--color-info-bg)] text-[var(--color-accent-blue)] border-[var(--color-accent-blue)]/30"
569
+ };
570
+ var notificationIcons = {
571
+ info: Info,
572
+ success: CheckCircle2,
573
+ warning: AlertTriangle,
574
+ danger: AlertCircle,
575
+ loading: Loader22
576
+ };
577
+ function NotificationMessage({
578
+ className,
579
+ tone = "info",
580
+ title,
581
+ description,
582
+ action,
583
+ icon
584
+ }) {
585
+ const Icon2 = icon ?? notificationIcons[tone];
586
+ return /* @__PURE__ */ jsxs6(
587
+ "div",
588
+ {
589
+ role: "status",
590
+ className: cn("flex items-start justify-between gap-3 rounded-lg border px-4 py-3", notificationStyles[tone], className),
591
+ children: [
592
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-start gap-3", children: [
593
+ /* @__PURE__ */ jsx13(Icon2, { className: cn("mt-0.5 h-4 w-4 shrink-0", tone === "loading" && "animate-spin") }),
594
+ /* @__PURE__ */ jsxs6("div", { className: "grid gap-1", children: [
595
+ /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium", children: title }),
596
+ description ? /* @__PURE__ */ jsx13("div", { className: "text-xs opacity-85", children: description }) : null
597
+ ] })
598
+ ] }),
599
+ action ? /* @__PURE__ */ jsx13("div", { className: "shrink-0", children: action }) : null
600
+ ]
601
+ }
602
+ );
603
+ }
604
+ function buildToastOptions(payload) {
605
+ return {
606
+ description: payload.description,
607
+ action: payload.actionLabel ? {
608
+ label: payload.actionLabel,
609
+ onClick: payload.onAction ?? (() => void 0)
610
+ } : void 0
611
+ };
612
+ }
613
+ var notify = {
614
+ info: (payload) => toast(payload.title, buildToastOptions(payload)),
615
+ success: (payload) => toast.success(payload.title, buildToastOptions(payload)),
616
+ warning: (payload) => toast(payload.title, {
617
+ ...buildToastOptions(payload),
618
+ icon: /* @__PURE__ */ jsx13(AlertTriangle, { className: "h-4 w-4 text-[var(--color-warning)]" })
619
+ }),
620
+ danger: (payload) => toast.error(payload.title, buildToastOptions(payload)),
621
+ loading: (payload) => toast.loading(payload.title, buildToastOptions(payload))
622
+ };
623
+ function NotificationAction({ children, variant = "outline", size = "sm", ...props }) {
624
+ return /* @__PURE__ */ jsx13(Button, { variant, size, ...props, children });
625
+ }
626
+
627
+ // src/components/feedback/status-badge.tsx
628
+ import { AlertCircle as AlertCircle2, CheckCircle2 as CheckCircle22, Clock3, Loader2 as Loader23 } from "lucide-react";
629
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
630
+ var toneStyles2 = {
631
+ success: "border-transparent bg-[var(--color-success-bg)] text-[var(--color-success)]",
632
+ warning: "border-transparent bg-[var(--color-warning-bg)] text-[var(--color-warning)]",
633
+ danger: "border-transparent bg-destructive/10 text-destructive",
634
+ info: "border-transparent bg-[var(--color-info-bg)] text-[var(--color-accent-blue)]",
635
+ loading: "border-transparent bg-muted text-muted-foreground"
636
+ };
637
+ var toneIcons = {
638
+ success: CheckCircle22,
639
+ warning: Clock3,
640
+ danger: AlertCircle2,
641
+ info: CheckCircle22,
642
+ loading: Loader23
643
+ };
644
+ function StatusBadge({ children, tone = "info", className }) {
645
+ const Icon2 = toneIcons[tone];
646
+ return /* @__PURE__ */ jsxs7(
647
+ "span",
648
+ {
649
+ className: cn(
650
+ "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-medium",
651
+ toneStyles2[tone],
652
+ className
653
+ ),
654
+ children: [
655
+ /* @__PURE__ */ jsx14(Icon2, { className: cn("h-3.5 w-3.5", tone === "loading" && "animate-spin") }),
656
+ children
657
+ ]
658
+ }
659
+ );
660
+ }
661
+
662
+ // src/components/feedback/toaster.tsx
663
+ import { Toaster as Sonner } from "sonner";
664
+ import { jsx as jsx15 } from "react/jsx-runtime";
665
+ function Toaster(props) {
666
+ const { resolvedTheme } = useTheme();
667
+ return /* @__PURE__ */ jsx15(
668
+ Sonner,
669
+ {
670
+ theme: resolvedTheme,
671
+ className: "toaster group",
672
+ closeButton: true,
673
+ toastOptions: {
674
+ classNames: {
675
+ toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
676
+ description: "group-[.toast]:text-muted-foreground",
677
+ actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
678
+ cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground"
679
+ }
680
+ },
681
+ ...props
682
+ }
683
+ );
684
+ }
685
+
686
+ // src/components/forms/searchable-select.tsx
687
+ import * as React6 from "react";
688
+ import { Check, ChevronDown, ChevronUp, Loader2 as Loader24, Search } from "lucide-react";
689
+
690
+ // src/components/primitives/input.tsx
691
+ import * as React5 from "react";
692
+ import { jsx as jsx16 } from "react/jsx-runtime";
693
+ var Input = React5.forwardRef(
694
+ ({ className, type, ...props }, ref) => {
695
+ return /* @__PURE__ */ jsx16(
696
+ "input",
697
+ {
698
+ type,
699
+ className: cn(
700
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground 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 md:text-sm",
701
+ className
702
+ ),
703
+ ref,
704
+ ...props
705
+ }
706
+ );
707
+ }
708
+ );
709
+ Input.displayName = "Input";
710
+
711
+ // src/components/forms/searchable-select.tsx
712
+ import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
713
+ function normalize(str) {
714
+ return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
715
+ }
716
+ var SearchableSelect = React6.forwardRef(
717
+ ({
718
+ options: options2,
719
+ value,
720
+ onValueChange,
721
+ placeholder = "Select an option...",
722
+ searchPlaceholder = "Search...",
723
+ disabled = false,
724
+ loading = false,
725
+ emptyMessage = "No results found.",
726
+ id,
727
+ className
728
+ }, ref) => {
729
+ const [open, setOpen] = React6.useState(false);
730
+ const [search, setSearch] = React6.useState("");
731
+ const wrapperRef = React6.useRef(null);
732
+ const searchRef = React6.useRef(null);
733
+ const selected = React6.useMemo(() => options2.find((option) => option.value === value) ?? null, [options2, value]);
734
+ const filtered = React6.useMemo(() => {
735
+ if (!search.trim()) {
736
+ return options2;
737
+ }
738
+ const query = normalize(search);
739
+ return options2.filter(
740
+ (option) => normalize(option.label).includes(query) || normalize(option.sublabel ?? "").includes(query)
741
+ );
742
+ }, [options2, search]);
743
+ function handleOpen() {
744
+ if (disabled || loading) {
745
+ return;
746
+ }
747
+ setOpen((previous) => !previous);
748
+ }
749
+ function handleSelect(optionValue) {
750
+ onValueChange(optionValue);
751
+ setOpen(false);
752
+ setSearch("");
753
+ }
754
+ function handleKeyDown(event) {
755
+ if (event.key === "Escape") {
756
+ setOpen(false);
757
+ setSearch("");
758
+ }
759
+ }
760
+ React6.useEffect(() => {
761
+ if (!open) {
762
+ return;
763
+ }
764
+ function handleMouseDown(event) {
765
+ if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
766
+ setOpen(false);
767
+ setSearch("");
768
+ }
769
+ }
770
+ document.addEventListener("mousedown", handleMouseDown);
771
+ return () => document.removeEventListener("mousedown", handleMouseDown);
772
+ }, [open]);
773
+ React6.useEffect(() => {
774
+ if (!open) {
775
+ return;
776
+ }
777
+ const timer = setTimeout(() => searchRef.current?.focus(), 50);
778
+ return () => clearTimeout(timer);
779
+ }, [open]);
780
+ return /* @__PURE__ */ jsxs8("div", { ref: wrapperRef, className: cn("relative w-full", className), onKeyDown: handleKeyDown, children: [
781
+ /* @__PURE__ */ jsxs8(
782
+ "button",
783
+ {
784
+ ref,
785
+ id,
786
+ type: "button",
787
+ role: "combobox",
788
+ "aria-expanded": open,
789
+ "aria-haspopup": "listbox",
790
+ disabled: disabled || loading,
791
+ onClick: handleOpen,
792
+ className: cn(
793
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-left text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
794
+ ),
795
+ children: [
796
+ loading ? /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-2 text-muted-foreground", children: [
797
+ /* @__PURE__ */ jsx17(Loader24, { className: "h-4 w-4 animate-spin" }),
798
+ "Loading..."
799
+ ] }) : selected ? /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-2 truncate", children: [
800
+ selected.sublabel ? /* @__PURE__ */ jsx17("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: selected.sublabel }) : null,
801
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: selected.label })
802
+ ] }) : /* @__PURE__ */ jsx17("span", { className: "text-muted-foreground", children: placeholder }),
803
+ /* @__PURE__ */ jsx17("span", { className: "ml-2 shrink-0 opacity-50", children: open ? /* @__PURE__ */ jsx17(ChevronUp, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx17(ChevronDown, { className: "h-4 w-4" }) })
804
+ ]
805
+ }
806
+ ),
807
+ open ? /* @__PURE__ */ jsxs8(
808
+ "div",
809
+ {
810
+ role: "listbox",
811
+ className: "animate-in fade-in-0 zoom-in-95 absolute z-50 mt-1 w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md",
812
+ children: [
813
+ /* @__PURE__ */ jsxs8("div", { className: "sticky top-0 flex items-center gap-2 border-b border-border bg-popover px-3 py-2", children: [
814
+ /* @__PURE__ */ jsx17(Search, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
815
+ /* @__PURE__ */ jsx17(
816
+ Input,
817
+ {
818
+ ref: searchRef,
819
+ type: "text",
820
+ value: search,
821
+ onChange: (event) => setSearch(event.target.value),
822
+ placeholder: searchPlaceholder,
823
+ className: "h-7 border-0 bg-transparent px-0 text-sm shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 placeholder:text-muted-foreground"
824
+ }
825
+ )
826
+ ] }),
827
+ /* @__PURE__ */ jsx17("ul", { className: "max-h-60 overflow-y-auto overscroll-contain p-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx17("li", { className: "px-4 py-3 text-center text-xs text-muted-foreground", children: emptyMessage }) : filtered.map((option) => {
828
+ const isSelected = option.value === value;
829
+ return /* @__PURE__ */ jsxs8(
830
+ "li",
831
+ {
832
+ role: "option",
833
+ "aria-selected": isSelected,
834
+ onClick: () => handleSelect(option.value),
835
+ className: cn(
836
+ "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
837
+ isSelected && "bg-accent/50 font-medium"
838
+ ),
839
+ children: [
840
+ /* @__PURE__ */ jsx17("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: isSelected ? /* @__PURE__ */ jsx17(Check, { className: "h-4 w-4" }) : null }),
841
+ /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-2 truncate", children: [
842
+ option.sublabel ? /* @__PURE__ */ jsx17("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: option.sublabel }) : null,
843
+ /* @__PURE__ */ jsx17("span", { className: "truncate", children: option.label })
844
+ ] })
845
+ ]
846
+ },
847
+ option.value
848
+ );
849
+ }) })
850
+ ]
851
+ }
852
+ ) : null
853
+ ] });
854
+ }
855
+ );
856
+ SearchableSelect.displayName = "SearchableSelect";
857
+
858
+ // src/components/forms/select.tsx
859
+ import * as React7 from "react";
860
+ import * as SelectPrimitive from "@radix-ui/react-select";
861
+ import { Check as Check2, ChevronDown as ChevronDown2, ChevronUp as ChevronUp2 } from "lucide-react";
862
+ import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
863
+ var Select = SelectPrimitive.Root;
864
+ var SelectGroup = SelectPrimitive.Group;
865
+ var SelectValue = SelectPrimitive.Value;
866
+ var SelectTrigger = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs9(
867
+ SelectPrimitive.Trigger,
868
+ {
869
+ ref,
870
+ className: cn(
871
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
872
+ className
873
+ ),
874
+ ...props,
875
+ children: [
876
+ children,
877
+ /* @__PURE__ */ jsx18(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx18(ChevronDown2, { className: "h-4 w-4 opacity-50" }) })
878
+ ]
879
+ }
880
+ ));
881
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
882
+ var SelectScrollUpButton = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(SelectPrimitive.ScrollUpButton, { ref, className: cn("flex cursor-default items-center justify-center py-1", className), ...props, children: /* @__PURE__ */ jsx18(ChevronUp2, { className: "h-4 w-4" }) }));
883
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
884
+ var SelectScrollDownButton = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
885
+ SelectPrimitive.ScrollDownButton,
886
+ {
887
+ ref,
888
+ className: cn("flex cursor-default items-center justify-center py-1", className),
889
+ ...props,
890
+ children: /* @__PURE__ */ jsx18(ChevronDown2, { className: "h-4 w-4" })
891
+ }
892
+ ));
893
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
894
+ var SelectContent = React7.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx18(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs9(
895
+ SelectPrimitive.Content,
896
+ {
897
+ ref,
898
+ className: cn(
899
+ "relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-select-content-transform-origin]",
900
+ 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",
901
+ className
902
+ ),
903
+ position,
904
+ ...props,
905
+ children: [
906
+ /* @__PURE__ */ jsx18(SelectScrollUpButton, {}),
907
+ /* @__PURE__ */ jsx18(
908
+ SelectPrimitive.Viewport,
909
+ {
910
+ className: cn(
911
+ "p-1",
912
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
913
+ ),
914
+ children
915
+ }
916
+ ),
917
+ /* @__PURE__ */ jsx18(SelectScrollDownButton, {})
918
+ ]
919
+ }
920
+ ) }));
921
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
922
+ var SelectLabel = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(SelectPrimitive.Label, { ref, className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className), ...props }));
923
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
924
+ var SelectItem = React7.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs9(
925
+ SelectPrimitive.Item,
926
+ {
927
+ ref,
928
+ className: cn(
929
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
930
+ className
931
+ ),
932
+ ...props,
933
+ children: [
934
+ /* @__PURE__ */ jsx18("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx18(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx18(Check2, { className: "h-4 w-4" }) }) }),
935
+ /* @__PURE__ */ jsx18(SelectPrimitive.ItemText, { children })
936
+ ]
937
+ }
938
+ ));
939
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
940
+ var SelectSeparator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(SelectPrimitive.Separator, { ref, className: cn("-mx-1 my-1 h-px bg-muted", className), ...props }));
941
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
942
+
943
+ // src/components/layout/app-shell.tsx
944
+ import { useState as useState3 } from "react";
945
+
946
+ // src/components/overlays/drawer.tsx
947
+ import * as React8 from "react";
948
+ import { Drawer as DrawerPrimitive } from "vaul";
949
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
950
+ var Drawer = ({ shouldScaleBackground = true, ...props }) => /* @__PURE__ */ jsx19(DrawerPrimitive.Root, { shouldScaleBackground, ...props });
951
+ Drawer.displayName = "Drawer";
952
+ var DrawerTrigger = DrawerPrimitive.Trigger;
953
+ var DrawerPortal = DrawerPrimitive.Portal;
954
+ var DrawerClose = DrawerPrimitive.Close;
955
+ var DrawerOverlay = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(DrawerPrimitive.Overlay, { ref, className: cn("fixed inset-0 z-50 bg-black/80", className), ...props }));
956
+ DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
957
+ var DrawerContent = React8.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs10(DrawerPortal, { children: [
958
+ /* @__PURE__ */ jsx19(DrawerOverlay, {}),
959
+ /* @__PURE__ */ jsxs10(
960
+ DrawerPrimitive.Content,
961
+ {
962
+ ref,
963
+ className: cn("fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background", className),
964
+ ...props,
965
+ children: [
966
+ /* @__PURE__ */ jsx19("div", { className: "mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" }),
967
+ children
968
+ ]
969
+ }
970
+ )
971
+ ] }));
972
+ DrawerContent.displayName = "DrawerContent";
973
+ var DrawerHeader = ({ className, ...props }) => /* @__PURE__ */ jsx19("div", { className: cn("grid gap-1.5 p-4 text-center sm:text-left", className), ...props });
974
+ DrawerHeader.displayName = "DrawerHeader";
975
+ var DrawerFooter = ({ className, ...props }) => /* @__PURE__ */ jsx19("div", { className: cn("mt-auto flex flex-col gap-2 p-4", className), ...props });
976
+ DrawerFooter.displayName = "DrawerFooter";
977
+ var DrawerTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(DrawerPrimitive.Title, { ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props }));
978
+ DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
979
+ var DrawerDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx19(DrawerPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
980
+ DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
981
+
982
+ // src/components/navigation/navbar.tsx
983
+ import { Menu } from "lucide-react";
984
+ import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
985
+ function Navbar({ brand, actions, onMenuClick, className }) {
986
+ return /* @__PURE__ */ jsx20("header", { className: cn("h-14 shrink-0 border-b border-border bg-card/80 px-4 backdrop-blur-sm", className), children: /* @__PURE__ */ jsxs11("div", { className: "mx-auto flex h-full w-full max-w-7xl items-center justify-between gap-3", children: [
987
+ /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
988
+ onMenuClick ? /* @__PURE__ */ jsx20(Button, { type: "button", variant: "ghost", size: "icon", onClick: onMenuClick, "aria-label": "Open navigation", children: /* @__PURE__ */ jsx20(Menu, { size: 20 }) }) : null,
989
+ brand
990
+ ] }),
991
+ actions ? /* @__PURE__ */ jsx20("div", { className: "flex shrink-0 items-center gap-3", children: actions }) : null
992
+ ] }) });
993
+ }
994
+
995
+ // src/components/navigation/sidebar.tsx
996
+ import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
997
+ function getInitials2(name) {
998
+ return name.trim().split(" ").filter(Boolean).slice(0, 2).map((part) => part[0]?.toUpperCase() ?? "").join("");
999
+ }
1000
+ function Sidebar({ brand, groups, user, footerAction, className }) {
1001
+ return /* @__PURE__ */ jsxs12("aside", { className: cn("flex h-full w-72 max-w-[85vw] flex-col border-r border-border bg-background", className), children: [
1002
+ /* @__PURE__ */ jsx21("div", { className: "border-b border-border px-5 py-4", children: brand }),
1003
+ /* @__PURE__ */ jsx21("nav", { className: "flex-1 space-y-6 overflow-y-auto px-3 py-4", children: groups.map((group) => /* @__PURE__ */ jsxs12("div", { children: [
1004
+ /* @__PURE__ */ jsx21("p", { className: "mb-2 px-2 text-xs font-semibold uppercase tracking-widest text-muted-foreground", children: group.label }),
1005
+ /* @__PURE__ */ jsx21("ul", { className: "space-y-0.5", children: group.items.map((item) => {
1006
+ const Icon2 = item.icon;
1007
+ return /* @__PURE__ */ jsx21("li", { children: /* @__PURE__ */ jsxs12(
1008
+ "a",
1009
+ {
1010
+ href: item.href,
1011
+ onClick: item.onClick,
1012
+ className: cn(
1013
+ "flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors",
1014
+ item.active ? "bg-primary text-primary-foreground" : "text-foreground hover:bg-accent hover:text-accent-foreground"
1015
+ ),
1016
+ children: [
1017
+ Icon2 ? /* @__PURE__ */ jsx21(Icon2, { size: 17, className: "shrink-0" }) : null,
1018
+ /* @__PURE__ */ jsx21("span", { className: "flex-1", children: item.label })
1019
+ ]
1020
+ }
1021
+ ) }, `${group.label}-${item.label}`);
1022
+ }) })
1023
+ ] }, group.label)) }),
1024
+ user ? /* @__PURE__ */ jsx21("div", { className: "border-t border-border px-5 py-4", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
1025
+ /* @__PURE__ */ jsx21(Avatar, { className: "h-9 w-9 shrink-0", children: /* @__PURE__ */ jsx21(AvatarFallback, { className: "bg-primary text-xs font-semibold text-primary-foreground", children: user.initials ?? getInitials2(user.name) }) }),
1026
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
1027
+ /* @__PURE__ */ jsx21("p", { className: "truncate text-sm font-medium text-foreground", children: user.name }),
1028
+ user.role ? /* @__PURE__ */ jsx21("p", { className: "truncate text-xs text-muted-foreground", children: user.role }) : null
1029
+ ] }),
1030
+ footerAction ? /* @__PURE__ */ jsx21(Button, { type: "button", variant: "ghost", size: "sm", onClick: footerAction.onClick, children: footerAction.label }) : null
1031
+ ] }) }) : null
1032
+ ] });
1033
+ }
1034
+
1035
+ // src/components/layout/app-shell.tsx
1036
+ import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
1037
+ function AppShell({
1038
+ brand,
1039
+ actions,
1040
+ sidebarGroups,
1041
+ sidebarUser,
1042
+ sidebarFooterAction,
1043
+ children
1044
+ }) {
1045
+ const [open, setOpen] = useState3(false);
1046
+ return /* @__PURE__ */ jsxs13("div", { className: "min-h-screen bg-background", children: [
1047
+ /* @__PURE__ */ jsx22(Navbar, { brand, actions, onMenuClick: () => setOpen(true) }),
1048
+ /* @__PURE__ */ jsx22(Drawer, { open, onOpenChange: setOpen, direction: "left", children: /* @__PURE__ */ jsx22(DrawerContent, { className: "h-full w-72 rounded-none border-r border-border p-0", children: /* @__PURE__ */ jsx22(Sidebar, { brand, groups: sidebarGroups, user: sidebarUser, footerAction: sidebarFooterAction }) }) }),
1049
+ /* @__PURE__ */ jsx22("main", { className: "mx-auto w-full max-w-7xl px-4 py-6 sm:px-6", children })
1050
+ ] });
1051
+ }
1052
+
1053
+ // src/components/layout/form-section.tsx
1054
+ import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
1055
+ function FormSection({ title, description, children }) {
1056
+ return /* @__PURE__ */ jsxs14(Card, { children: [
1057
+ /* @__PURE__ */ jsxs14(CardHeader, { children: [
1058
+ /* @__PURE__ */ jsx23(CardTitle, { children: title }),
1059
+ description ? /* @__PURE__ */ jsx23(CardDescription, { children: description }) : null
1060
+ ] }),
1061
+ /* @__PURE__ */ jsx23(CardContent, { children })
1062
+ ] });
1063
+ }
1064
+
1065
+ // src/components/layout/page-header.tsx
1066
+ import { jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
1067
+ function PageHeader({ title, description, action }) {
1068
+ return /* @__PURE__ */ jsxs15("div", { className: "flex items-start justify-between gap-4 sm:flex-row sm:items-center", children: [
1069
+ /* @__PURE__ */ jsxs15("div", { children: [
1070
+ /* @__PURE__ */ jsx24("h1", { className: "text-2xl font-semibold text-foreground", style: { fontFamily: "var(--font-display)" }, children: title }),
1071
+ description ? /* @__PURE__ */ jsx24("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
1072
+ ] }),
1073
+ action ? /* @__PURE__ */ jsx24("div", { children: action }) : null
1074
+ ] });
1075
+ }
1076
+
1077
+ // src/components/layout/theme-toggle.tsx
1078
+ import { Moon, Sun } from "lucide-react";
1079
+ import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
1080
+ var options = [
1081
+ { value: "light", Icon: Sun, label: "Light" },
1082
+ { value: "dark", Icon: Moon, label: "Dark" }
1083
+ ];
1084
+ function ThemeToggle({ className }) {
1085
+ const { theme, setTheme } = useTheme();
1086
+ return /* @__PURE__ */ jsx25("div", { className: cn("flex items-center gap-1 rounded-lg border border-border bg-muted p-1", className), children: options.map(({ value, Icon: Icon2, label }) => /* @__PURE__ */ jsxs16(
1087
+ "button",
1088
+ {
1089
+ type: "button",
1090
+ onClick: () => setTheme(value),
1091
+ "aria-label": label,
1092
+ className: cn(
1093
+ "flex cursor-pointer items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-all",
1094
+ theme === value ? "bg-card text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
1095
+ ),
1096
+ children: [
1097
+ /* @__PURE__ */ jsx25(Icon2, { size: 13 }),
1098
+ /* @__PURE__ */ jsx25("span", { children: label })
1099
+ ]
1100
+ },
1101
+ value
1102
+ )) });
1103
+ }
1104
+
1105
+ // src/components/navigation/breadcrumb.tsx
1106
+ import * as React9 from "react";
1107
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
1108
+ import { ChevronRight, MoreHorizontal } from "lucide-react";
1109
+ import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
1110
+ var Breadcrumb = React9.forwardRef(({ ...props }, ref) => /* @__PURE__ */ jsx26("nav", { ref, "aria-label": "breadcrumb", ...props }));
1111
+ Breadcrumb.displayName = "Breadcrumb";
1112
+ var BreadcrumbList = React9.forwardRef(
1113
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
1114
+ "ol",
1115
+ {
1116
+ ref,
1117
+ className: cn("flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", className),
1118
+ ...props
1119
+ }
1120
+ )
1121
+ );
1122
+ BreadcrumbList.displayName = "BreadcrumbList";
1123
+ var BreadcrumbItem = React9.forwardRef(
1124
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx26("li", { ref, className: cn("inline-flex items-center gap-1.5", className), ...props })
1125
+ );
1126
+ BreadcrumbItem.displayName = "BreadcrumbItem";
1127
+ var BreadcrumbLink = React9.forwardRef(({ asChild, className, ...props }, ref) => {
1128
+ const Comp = asChild ? Slot2 : "a";
1129
+ return /* @__PURE__ */ jsx26(Comp, { ref, className: cn("transition-colors hover:text-foreground", className), ...props });
1130
+ });
1131
+ BreadcrumbLink.displayName = "BreadcrumbLink";
1132
+ var BreadcrumbPage = React9.forwardRef(
1133
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
1134
+ "span",
1135
+ {
1136
+ ref,
1137
+ role: "link",
1138
+ "aria-disabled": "true",
1139
+ "aria-current": "page",
1140
+ className: cn("font-normal text-foreground", className),
1141
+ ...props
1142
+ }
1143
+ )
1144
+ );
1145
+ BreadcrumbPage.displayName = "BreadcrumbPage";
1146
+ var BreadcrumbSeparator = ({ children, className, ...props }) => /* @__PURE__ */ jsx26("li", { role: "presentation", "aria-hidden": "true", className: cn("[&>svg]:h-3.5 [&>svg]:w-3.5", className), ...props, children: children ?? /* @__PURE__ */ jsx26(ChevronRight, {}) });
1147
+ BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
1148
+ var BreadcrumbEllipsis = ({ className, ...props }) => /* @__PURE__ */ jsxs17("span", { role: "presentation", "aria-hidden": "true", className: cn("flex h-9 w-9 items-center justify-center", className), ...props, children: [
1149
+ /* @__PURE__ */ jsx26(MoreHorizontal, { className: "h-4 w-4" }),
1150
+ /* @__PURE__ */ jsx26("span", { className: "sr-only", children: "More" })
1151
+ ] });
1152
+ BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";
1153
+
1154
+ // src/components/navigation/page-breadcrumb.tsx
1155
+ import { Fragment as Fragment2 } from "react";
1156
+ import { jsx as jsx27, jsxs as jsxs18 } from "react/jsx-runtime";
1157
+ function PageBreadcrumb({ items }) {
1158
+ return /* @__PURE__ */ jsx27(Breadcrumb, { children: /* @__PURE__ */ jsx27(BreadcrumbList, { children: items.map((item, index) => {
1159
+ const isLast = index === items.length - 1;
1160
+ return /* @__PURE__ */ jsxs18(Fragment2, { children: [
1161
+ /* @__PURE__ */ jsx27(BreadcrumbItem, { children: !isLast && item.href ? /* @__PURE__ */ jsx27(BreadcrumbLink, { href: item.href, children: item.label }) : /* @__PURE__ */ jsx27(BreadcrumbPage, { children: item.label }) }),
1162
+ !isLast ? /* @__PURE__ */ jsx27(BreadcrumbSeparator, {}) : null
1163
+ ] }, `${item.label}-${index}`);
1164
+ }) }) });
1165
+ }
1166
+
1167
+ // src/components/navigation/steps.tsx
1168
+ import { AlertCircle as AlertCircle3, Check as Check3 } from "lucide-react";
1169
+ import { jsx as jsx28, jsxs as jsxs19 } from "react/jsx-runtime";
1170
+ var indicatorStyles = {
1171
+ complete: "border-primary bg-primary text-primary-foreground",
1172
+ current: "border-primary bg-primary/10 text-primary",
1173
+ upcoming: "border-border bg-background text-muted-foreground",
1174
+ error: "border-destructive bg-destructive/10 text-destructive"
1175
+ };
1176
+ function Steps({ className, items, orientation = "horizontal" }) {
1177
+ return /* @__PURE__ */ jsx28("ol", { className: cn("flex", orientation === "horizontal" ? "flex-col gap-4 md:flex-row" : "flex-col", className), children: items.map((item, index) => {
1178
+ const status = item.status ?? "upcoming";
1179
+ const isLast = index === items.length - 1;
1180
+ return /* @__PURE__ */ jsxs19(
1181
+ "li",
1182
+ {
1183
+ className: cn("relative", orientation === "horizontal" ? "flex-1" : "pb-6 last:pb-0"),
1184
+ children: [
1185
+ !isLast ? /* @__PURE__ */ jsx28(
1186
+ "span",
1187
+ {
1188
+ "aria-hidden": "true",
1189
+ className: cn(
1190
+ "absolute bg-border",
1191
+ orientation === "horizontal" ? "left-[calc(50%+1rem)] top-4 hidden h-px w-[calc(100%-1rem)] md:block" : "left-4 top-9 h-[calc(100%-1rem)] w-px"
1192
+ )
1193
+ }
1194
+ ) : null,
1195
+ /* @__PURE__ */ jsxs19("div", { className: cn(
1196
+ orientation === "horizontal" ? "flex flex-col items-center gap-2 text-center" : "flex items-start gap-3"
1197
+ ), children: [
1198
+ /* @__PURE__ */ jsxs19(
1199
+ "span",
1200
+ {
1201
+ className: cn(
1202
+ "relative z-10 inline-flex h-8 w-8 items-center justify-center rounded-full border text-sm font-semibold shadow-sm",
1203
+ indicatorStyles[status]
1204
+ ),
1205
+ children: [
1206
+ status === "complete" ? /* @__PURE__ */ jsx28(Check3, { className: "h-4 w-4" }) : null,
1207
+ status === "error" ? /* @__PURE__ */ jsx28(AlertCircle3, { className: "h-4 w-4" }) : null,
1208
+ status === "current" || status === "upcoming" ? index + 1 : null
1209
+ ]
1210
+ }
1211
+ ),
1212
+ /* @__PURE__ */ jsxs19("div", { className: cn("grid gap-1", orientation === "vertical" && "pt-1"), children: [
1213
+ /* @__PURE__ */ jsx28("p", { className: cn("text-sm font-medium", status === "upcoming" ? "text-muted-foreground" : "text-foreground"), children: item.title }),
1214
+ item.description ? /* @__PURE__ */ jsx28("p", { className: "text-xs text-muted-foreground", children: item.description }) : null
1215
+ ] })
1216
+ ] })
1217
+ ]
1218
+ },
1219
+ item.id ?? item.title
1220
+ );
1221
+ }) });
1222
+ }
1223
+
1224
+ // src/components/overlays/dialog.tsx
1225
+ import * as React10 from "react";
1226
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
1227
+ import { X } from "lucide-react";
1228
+ import { jsx as jsx29, jsxs as jsxs20 } from "react/jsx-runtime";
1229
+ var Dialog = DialogPrimitive.Root;
1230
+ var DialogTrigger = DialogPrimitive.Trigger;
1231
+ var DialogPortal = DialogPrimitive.Portal;
1232
+ var DialogClose = DialogPrimitive.Close;
1233
+ var DialogOverlay = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(
1234
+ DialogPrimitive.Overlay,
1235
+ {
1236
+ ref,
1237
+ className: cn(
1238
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1239
+ className
1240
+ ),
1241
+ ...props
1242
+ }
1243
+ ));
1244
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
1245
+ var DialogContent = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs20(DialogPortal, { children: [
1246
+ /* @__PURE__ */ jsx29(DialogOverlay, {}),
1247
+ /* @__PURE__ */ jsxs20(
1248
+ DialogPrimitive.Content,
1249
+ {
1250
+ ref,
1251
+ className: cn(
1252
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg 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",
1253
+ className
1254
+ ),
1255
+ ...props,
1256
+ children: [
1257
+ children,
1258
+ /* @__PURE__ */ jsxs20(DialogPrimitive.Close, { className: "absolute right-4 top-4 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 data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
1259
+ /* @__PURE__ */ jsx29(X, { className: "h-4 w-4" }),
1260
+ /* @__PURE__ */ jsx29("span", { className: "sr-only", children: "Close" })
1261
+ ] })
1262
+ ]
1263
+ }
1264
+ )
1265
+ ] }));
1266
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
1267
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx29("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
1268
+ DialogHeader.displayName = "DialogHeader";
1269
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx29("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
1270
+ DialogFooter.displayName = "DialogFooter";
1271
+ var DialogTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props }));
1272
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
1273
+ var DialogDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1274
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
1275
+
1276
+ // src/components/overlays/dropdown-menu.tsx
1277
+ import * as React11 from "react";
1278
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
1279
+ import { Check as Check4, ChevronRight as ChevronRight2, Circle } from "lucide-react";
1280
+ import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
1281
+ var DropdownMenu = DropdownMenuPrimitive.Root;
1282
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1283
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
1284
+ var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
1285
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
1286
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
1287
+ var DropdownMenuSubTrigger = React11.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs21(
1288
+ DropdownMenuPrimitive.SubTrigger,
1289
+ {
1290
+ ref,
1291
+ className: cn(
1292
+ "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1293
+ inset && "pl-8",
1294
+ className
1295
+ ),
1296
+ ...props,
1297
+ children: [
1298
+ children,
1299
+ /* @__PURE__ */ jsx30(ChevronRight2, { className: "ml-auto" })
1300
+ ]
1301
+ }
1302
+ ));
1303
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
1304
+ var DropdownMenuSubContent = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(
1305
+ DropdownMenuPrimitive.SubContent,
1306
+ {
1307
+ ref,
1308
+ className: cn(
1309
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
1310
+ className
1311
+ ),
1312
+ ...props
1313
+ }
1314
+ ));
1315
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
1316
+ var DropdownMenuContent = React11.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx30(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx30(
1317
+ DropdownMenuPrimitive.Content,
1318
+ {
1319
+ ref,
1320
+ sideOffset,
1321
+ className: cn(
1322
+ "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
1323
+ className
1324
+ ),
1325
+ ...props
1326
+ }
1327
+ ) }));
1328
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
1329
+ var DropdownMenuItem = React11.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx30(
1330
+ DropdownMenuPrimitive.Item,
1331
+ {
1332
+ ref,
1333
+ className: cn(
1334
+ "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
1335
+ inset && "pl-8",
1336
+ className
1337
+ ),
1338
+ ...props
1339
+ }
1340
+ ));
1341
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
1342
+ var DropdownMenuCheckboxItem = React11.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs21(
1343
+ DropdownMenuPrimitive.CheckboxItem,
1344
+ {
1345
+ ref,
1346
+ className: cn(
1347
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1348
+ className
1349
+ ),
1350
+ ...checked !== void 0 ? { checked } : {},
1351
+ ...props,
1352
+ children: [
1353
+ /* @__PURE__ */ jsx30("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx30(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx30(Check4, { className: "h-4 w-4" }) }) }),
1354
+ children
1355
+ ]
1356
+ }
1357
+ ));
1358
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
1359
+ var DropdownMenuRadioItem = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs21(
1360
+ DropdownMenuPrimitive.RadioItem,
1361
+ {
1362
+ ref,
1363
+ className: cn(
1364
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1365
+ className
1366
+ ),
1367
+ ...props,
1368
+ children: [
1369
+ /* @__PURE__ */ jsx30("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx30(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx30(Circle, { className: "h-2 w-2 fill-current" }) }) }),
1370
+ children
1371
+ ]
1372
+ }
1373
+ ));
1374
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
1375
+ var DropdownMenuLabel = React11.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx30(DropdownMenuPrimitive.Label, { ref, className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className), ...props }));
1376
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
1377
+ var DropdownMenuSeparator = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx30(DropdownMenuPrimitive.Separator, { ref, className: cn("-mx-1 my-1 h-px bg-muted", className), ...props }));
1378
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
1379
+ var DropdownMenuShortcut = ({ className, ...props }) => /* @__PURE__ */ jsx30("span", { className: cn("ml-auto text-xs tracking-widest opacity-60", className), ...props });
1380
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
1381
+
1382
+ // src/components/overlays/sheet.tsx
1383
+ import * as React12 from "react";
1384
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
1385
+ import { cva as cva3 } from "class-variance-authority";
1386
+ import { X as X2 } from "lucide-react";
1387
+ import { jsx as jsx31, jsxs as jsxs22 } from "react/jsx-runtime";
1388
+ var Sheet = SheetPrimitive.Root;
1389
+ var SheetTrigger = SheetPrimitive.Trigger;
1390
+ var SheetClose = SheetPrimitive.Close;
1391
+ var SheetPortal = SheetPrimitive.Portal;
1392
+ var SheetOverlay = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
1393
+ SheetPrimitive.Overlay,
1394
+ {
1395
+ className: cn(
1396
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1397
+ className
1398
+ ),
1399
+ ...props,
1400
+ ref
1401
+ }
1402
+ ));
1403
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
1404
+ var sheetVariants = cva3(
1405
+ "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
1406
+ {
1407
+ variants: {
1408
+ side: {
1409
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
1410
+ bottom: "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
1411
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
1412
+ right: "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm"
1413
+ }
1414
+ },
1415
+ defaultVariants: {
1416
+ side: "right"
1417
+ }
1418
+ }
1419
+ );
1420
+ var SheetContent = React12.forwardRef(
1421
+ ({ side = "right", className, children, ...props }, ref) => /* @__PURE__ */ jsxs22(SheetPortal, { children: [
1422
+ /* @__PURE__ */ jsx31(SheetOverlay, {}),
1423
+ /* @__PURE__ */ jsxs22(SheetPrimitive.Content, { ref, className: cn(sheetVariants({ side }), className), ...props, children: [
1424
+ children,
1425
+ /* @__PURE__ */ jsxs22(SheetPrimitive.Close, { className: "absolute right-4 top-4 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 data-[state=open]:bg-secondary", children: [
1426
+ /* @__PURE__ */ jsx31(X2, { className: "h-4 w-4" }),
1427
+ /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "Close" })
1428
+ ] })
1429
+ ] })
1430
+ ] })
1431
+ );
1432
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
1433
+ var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx31("div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
1434
+ SheetHeader.displayName = "SheetHeader";
1435
+ var SheetFooter = ({ className, ...props }) => /* @__PURE__ */ jsx31("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
1436
+ SheetFooter.displayName = "SheetFooter";
1437
+ var SheetTitle = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(SheetPrimitive.Title, { ref, className: cn("text-lg font-semibold text-foreground", className), ...props }));
1438
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
1439
+ var SheetDescription = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(SheetPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
1440
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
1441
+
1442
+ // src/components/primitives/alert.tsx
1443
+ import * as React13 from "react";
1444
+ import { cva as cva4 } from "class-variance-authority";
1445
+ import { jsx as jsx32 } from "react/jsx-runtime";
1446
+ var alertVariants = cva4("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", {
1447
+ variants: {
1448
+ variant: {
1449
+ default: "bg-background text-foreground",
1450
+ destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive"
1451
+ }
1452
+ },
1453
+ defaultVariants: {
1454
+ variant: "default"
1455
+ }
1456
+ });
1457
+ var Alert = React13.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx32("div", { ref, role: "alert", className: cn(alertVariants({ variant }), className), ...props }));
1458
+ Alert.displayName = "Alert";
1459
+ var AlertTitle = React13.forwardRef(
1460
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx32("h5", { ref, className: cn("mb-1 font-medium leading-none tracking-tight", className), ...props })
1461
+ );
1462
+ AlertTitle.displayName = "AlertTitle";
1463
+ var AlertDescription = React13.forwardRef(
1464
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx32("div", { ref, className: cn("text-sm [&_p]:leading-relaxed", className), ...props })
1465
+ );
1466
+ AlertDescription.displayName = "AlertDescription";
1467
+
1468
+ // src/components/primitives/badge.tsx
1469
+ import { cva as cva5 } from "class-variance-authority";
1470
+ import { jsx as jsx33 } from "react/jsx-runtime";
1471
+ var badgeVariants = cva5("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
1472
+ variants: {
1473
+ variant: {
1474
+ default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
1475
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
1476
+ destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
1477
+ outline: "text-foreground"
1478
+ }
1479
+ },
1480
+ defaultVariants: {
1481
+ variant: "default"
1482
+ }
1483
+ });
1484
+ function Badge({ className, variant, ...props }) {
1485
+ return /* @__PURE__ */ jsx33("div", { className: cn(badgeVariants({ variant }), className), ...props });
1486
+ }
1487
+
1488
+ // src/components/primitives/checkbox.tsx
1489
+ import * as React14 from "react";
1490
+ import { Check as Check5 } from "lucide-react";
1491
+ import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
1492
+ var Checkbox = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs23("span", { className: "relative inline-flex h-4 w-4 shrink-0", children: [
1493
+ /* @__PURE__ */ jsx34(
1494
+ "input",
1495
+ {
1496
+ ref,
1497
+ type: "checkbox",
1498
+ className: cn(
1499
+ "peer absolute inset-0 h-4 w-4 cursor-pointer appearance-none rounded-[4px] border border-input bg-background shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 checked:border-primary checked:bg-primary",
1500
+ className
1501
+ ),
1502
+ ...props
1503
+ }
1504
+ ),
1505
+ /* @__PURE__ */ jsx34(
1506
+ Check5,
1507
+ {
1508
+ "aria-hidden": "true",
1509
+ className: "pointer-events-none absolute left-1/2 top-1/2 h-3 w-3 -translate-x-1/2 -translate-y-1/2 text-primary-foreground opacity-0 transition-opacity peer-checked:opacity-100"
1510
+ }
1511
+ )
1512
+ ] }));
1513
+ Checkbox.displayName = "Checkbox";
1514
+ function CheckboxField({ id, label, description, containerClassName, className, ...props }) {
1515
+ const generatedId = React14.useId();
1516
+ const inputId = id ?? generatedId;
1517
+ return /* @__PURE__ */ jsxs23(
1518
+ "label",
1519
+ {
1520
+ htmlFor: inputId,
1521
+ className: cn("flex items-center gap-3 rounded-lg border border-border bg-card p-3 transition-colors hover:bg-accent/30", containerClassName),
1522
+ children: [
1523
+ /* @__PURE__ */ jsx34(Checkbox, { id: inputId, className, ...props }),
1524
+ /* @__PURE__ */ jsxs23("span", { className: "grid gap-1", children: [
1525
+ /* @__PURE__ */ jsx34("span", { className: "text-sm font-medium text-foreground", children: label }),
1526
+ description ? /* @__PURE__ */ jsx34("span", { className: "text-xs text-muted-foreground", children: description }) : null
1527
+ ] })
1528
+ ]
1529
+ }
1530
+ );
1531
+ }
1532
+
1533
+ // src/components/primitives/label.tsx
1534
+ import * as React15 from "react";
1535
+ import * as LabelPrimitive from "@radix-ui/react-label";
1536
+ import { cva as cva6 } from "class-variance-authority";
1537
+ import { jsx as jsx35 } from "react/jsx-runtime";
1538
+ var labelVariants = cva6("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
1539
+ var Label3 = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(LabelPrimitive.Root, { ref, className: cn(labelVariants(), className), ...props }));
1540
+ Label3.displayName = LabelPrimitive.Root.displayName;
1541
+
1542
+ // src/components/primitives/radio-group.tsx
1543
+ import * as React16 from "react";
1544
+ import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
1545
+ var RadioGroup2 = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx36("div", { ref, role: "radiogroup", className: cn("grid gap-3", className), ...props }));
1546
+ RadioGroup2.displayName = "RadioGroup";
1547
+ var RadioGroupItem = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs24("span", { className: "relative inline-flex h-4 w-4 shrink-0", children: [
1548
+ /* @__PURE__ */ jsx36(
1549
+ "input",
1550
+ {
1551
+ ref,
1552
+ type: "radio",
1553
+ className: cn(
1554
+ "peer absolute inset-0 h-4 w-4 cursor-pointer appearance-none rounded-full border border-input bg-background shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 checked:border-primary",
1555
+ className
1556
+ ),
1557
+ ...props
1558
+ }
1559
+ ),
1560
+ /* @__PURE__ */ jsx36(
1561
+ "span",
1562
+ {
1563
+ "aria-hidden": "true",
1564
+ className: "pointer-events-none absolute left-1/2 top-1/2 h-2 w-2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary opacity-0 transition-opacity peer-checked:opacity-100"
1565
+ }
1566
+ )
1567
+ ] }));
1568
+ RadioGroupItem.displayName = "RadioGroupItem";
1569
+ function RadioField({ id, label, description, containerClassName, className, ...props }) {
1570
+ const generatedId = React16.useId();
1571
+ const inputId = id ?? generatedId;
1572
+ return /* @__PURE__ */ jsxs24(
1573
+ "label",
1574
+ {
1575
+ htmlFor: inputId,
1576
+ className: cn("flex items-center gap-3 rounded-lg border border-border bg-card p-3 transition-colors hover:bg-accent/30", containerClassName),
1577
+ children: [
1578
+ /* @__PURE__ */ jsx36(RadioGroupItem, { id: inputId, className, ...props }),
1579
+ /* @__PURE__ */ jsxs24("span", { className: "grid gap-1", children: [
1580
+ /* @__PURE__ */ jsx36("span", { className: "text-sm font-medium text-foreground", children: label }),
1581
+ description ? /* @__PURE__ */ jsx36("span", { className: "text-xs text-muted-foreground", children: description }) : null
1582
+ ] })
1583
+ ]
1584
+ }
1585
+ );
1586
+ }
1587
+
1588
+ // src/components/primitives/separator.tsx
1589
+ import * as React17 from "react";
1590
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
1591
+ import { jsx as jsx37 } from "react/jsx-runtime";
1592
+ var Separator3 = React17.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx37(
1593
+ SeparatorPrimitive.Root,
1594
+ {
1595
+ ref,
1596
+ decorative,
1597
+ orientation,
1598
+ className: cn("shrink-0 bg-border", orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", className),
1599
+ ...props
1600
+ }
1601
+ ));
1602
+ Separator3.displayName = SeparatorPrimitive.Root.displayName;
1603
+
1604
+ // src/components/primitives/switch.tsx
1605
+ import * as React18 from "react";
1606
+ import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
1607
+ var Switch = React18.forwardRef(({ className, size = "default", ...props }, ref) => {
1608
+ const isSm = size === "sm";
1609
+ return /* @__PURE__ */ jsxs25(
1610
+ "span",
1611
+ {
1612
+ className: cn(
1613
+ "relative inline-flex shrink-0",
1614
+ isSm ? "h-4 w-7" : "h-6 w-10"
1615
+ ),
1616
+ children: [
1617
+ /* @__PURE__ */ jsx38(
1618
+ "input",
1619
+ {
1620
+ ref,
1621
+ type: "checkbox",
1622
+ role: "switch",
1623
+ className: cn(
1624
+ "peer absolute inset-0 cursor-pointer appearance-none rounded-full border border-input bg-input",
1625
+ "transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
1626
+ "disabled:cursor-not-allowed disabled:opacity-50",
1627
+ "checked:border-primary checked:bg-primary",
1628
+ className
1629
+ ),
1630
+ ...props
1631
+ }
1632
+ ),
1633
+ /* @__PURE__ */ jsx38(
1634
+ "span",
1635
+ {
1636
+ "aria-hidden": "true",
1637
+ className: cn(
1638
+ "pointer-events-none absolute rounded-full bg-background shadow-sm transition-transform",
1639
+ isSm ? "top-0.5 left-0.5 h-3 w-3 peer-checked:translate-x-3" : "top-1 left-1 h-4 w-4 peer-checked:translate-x-4"
1640
+ )
1641
+ }
1642
+ )
1643
+ ]
1644
+ }
1645
+ );
1646
+ });
1647
+ Switch.displayName = "Switch";
1648
+ function SwitchField({ id, label, description, containerClassName, size, className, ...props }) {
1649
+ const generatedId = React18.useId();
1650
+ const inputId = id ?? generatedId;
1651
+ return /* @__PURE__ */ jsxs25(
1652
+ "label",
1653
+ {
1654
+ htmlFor: inputId,
1655
+ className: cn(
1656
+ "flex cursor-pointer items-center justify-between gap-4 rounded-lg border border-border bg-card p-3 transition-colors hover:bg-accent/30",
1657
+ props.disabled && "cursor-not-allowed opacity-50 hover:bg-card",
1658
+ containerClassName
1659
+ ),
1660
+ children: [
1661
+ /* @__PURE__ */ jsxs25("span", { className: "grid gap-0.5", children: [
1662
+ /* @__PURE__ */ jsx38("span", { className: "text-sm font-medium text-foreground", children: label }),
1663
+ description ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: description }) : null
1664
+ ] }),
1665
+ /* @__PURE__ */ jsx38(Switch, { id: inputId, size, className, ...props })
1666
+ ]
1667
+ }
1668
+ );
1669
+ }
1670
+
1671
+ // src/components/primitives/textarea.tsx
1672
+ import * as React19 from "react";
1673
+ import { jsx as jsx39 } from "react/jsx-runtime";
1674
+ var Textarea = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx39(
1675
+ "textarea",
1676
+ {
1677
+ ref,
1678
+ className: cn(
1679
+ "flex min-h-24 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",
1680
+ className
1681
+ ),
1682
+ ...props
1683
+ }
1684
+ ));
1685
+ Textarea.displayName = "Textarea";
1686
+
1687
+ // src/components/tables/data-table.tsx
1688
+ import { useMemo as useMemo3, useState as useState4 } from "react";
1689
+ import { ChevronLeft, ChevronRight as ChevronRight3, Search as Search2 } from "lucide-react";
1690
+ import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
1691
+ function getCellContent(row, column) {
1692
+ if (column.render) {
1693
+ return column.render(row);
1694
+ }
1695
+ const value = row[column.key];
1696
+ if (value === null || value === void 0) {
1697
+ return /* @__PURE__ */ jsx40("span", { className: "text-muted-foreground/40", children: "-" });
1698
+ }
1699
+ if (typeof value === "boolean") {
1700
+ return value ? "Yes" : "No";
1701
+ }
1702
+ return String(value);
1703
+ }
1704
+ var SKELETON_ROWS = 5;
1705
+ function DataTable({
1706
+ data,
1707
+ columns,
1708
+ isLoading = false,
1709
+ actions,
1710
+ emptyMessage = "No records found",
1711
+ pageSize = 10
1712
+ }) {
1713
+ const [search, setSearch] = useState4("");
1714
+ const [page, setPage] = useState4(0);
1715
+ const filtered = useMemo3(() => {
1716
+ const query = search.toLowerCase().trim();
1717
+ if (!query) {
1718
+ return data;
1719
+ }
1720
+ return data.filter(
1721
+ (row) => Object.values(row).some(
1722
+ (value) => value != null && String(value).toLowerCase().includes(query)
1723
+ )
1724
+ );
1725
+ }, [data, search]);
1726
+ const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
1727
+ const currentPage = Math.min(page, totalPages - 1);
1728
+ const paginated = filtered.slice(currentPage * pageSize, (currentPage + 1) * pageSize);
1729
+ const mobileColumns = columns.filter((column) => !column.mobileHide);
1730
+ function handleSearch(value) {
1731
+ setSearch(value);
1732
+ setPage(0);
1733
+ }
1734
+ return /* @__PURE__ */ jsxs26("div", { className: "space-y-4", children: [
1735
+ /* @__PURE__ */ jsxs26("div", { className: "relative", children: [
1736
+ /* @__PURE__ */ jsx40(Search2, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
1737
+ /* @__PURE__ */ jsx40(
1738
+ Input,
1739
+ {
1740
+ placeholder: "Search...",
1741
+ value: search,
1742
+ onChange: (event) => handleSearch(event.target.value),
1743
+ className: "pl-9"
1744
+ }
1745
+ )
1746
+ ] }),
1747
+ /* @__PURE__ */ jsx40("div", { className: "hidden rounded-lg border md:block", children: /* @__PURE__ */ jsxs26(Table, { children: [
1748
+ /* @__PURE__ */ jsx40(TableHeader, { children: /* @__PURE__ */ jsxs26(TableRow, { children: [
1749
+ columns.map((column) => /* @__PURE__ */ jsx40(TableHead, { children: column.label }, String(column.key))),
1750
+ actions ? /* @__PURE__ */ jsx40(TableHead, { className: "w-[100px] text-right", children: "Actions" }) : null
1751
+ ] }) }),
1752
+ /* @__PURE__ */ jsx40(TableBody, { children: isLoading ? Array.from({ length: SKELETON_ROWS }).map((_, index) => /* @__PURE__ */ jsxs26(TableRow, { children: [
1753
+ columns.map((column) => /* @__PURE__ */ jsx40(TableCell, { children: /* @__PURE__ */ jsx40(Skeleton, { className: "h-4 w-full" }) }, String(column.key))),
1754
+ actions ? /* @__PURE__ */ jsx40(TableCell, { children: /* @__PURE__ */ jsx40(Skeleton, { className: "ml-auto h-8 w-20" }) }) : null
1755
+ ] }, index)) : paginated.length === 0 ? /* @__PURE__ */ jsx40(TableRow, { children: /* @__PURE__ */ jsx40(TableCell, { colSpan: columns.length + (actions ? 1 : 0), className: "py-12 text-center text-muted-foreground", children: emptyMessage }) }) : paginated.map((row, index) => /* @__PURE__ */ jsxs26(TableRow, { children: [
1756
+ columns.map((column) => /* @__PURE__ */ jsx40(TableCell, { children: getCellContent(row, column) }, String(column.key))),
1757
+ actions ? /* @__PURE__ */ jsx40(TableCell, { children: /* @__PURE__ */ jsx40("div", { className: "flex justify-end gap-1.5", children: actions(row) }) }) : null
1758
+ ] }, index)) })
1759
+ ] }) }),
1760
+ /* @__PURE__ */ jsx40("div", { className: "space-y-3 md:hidden", children: isLoading ? Array.from({ length: SKELETON_ROWS }).map((_, index) => /* @__PURE__ */ jsx40(Card, { children: /* @__PURE__ */ jsxs26(CardContent, { className: "space-y-2 p-4", children: [
1761
+ /* @__PURE__ */ jsx40(Skeleton, { className: "h-5 w-1/2" }),
1762
+ /* @__PURE__ */ jsx40(Skeleton, { className: "h-4 w-2/3" }),
1763
+ /* @__PURE__ */ jsx40(Skeleton, { className: "h-4 w-1/3" })
1764
+ ] }) }, index)) : paginated.length === 0 ? /* @__PURE__ */ jsx40("p", { className: "py-10 text-center text-muted-foreground", children: emptyMessage }) : paginated.map((row, index) => /* @__PURE__ */ jsx40(Card, { children: /* @__PURE__ */ jsxs26(CardContent, { className: "space-y-3 p-4", children: [
1765
+ /* @__PURE__ */ jsx40("div", { className: "space-y-1.5", children: mobileColumns.map((column, mobileIndex) => /* @__PURE__ */ jsxs26(
1766
+ "div",
1767
+ {
1768
+ className: cn(
1769
+ "flex items-center gap-1.5",
1770
+ mobileIndex === 0 ? "text-sm font-medium text-foreground" : "text-xs text-muted-foreground"
1771
+ ),
1772
+ children: [
1773
+ mobileIndex > 0 ? /* @__PURE__ */ jsxs26("span", { className: "shrink-0 font-medium text-foreground/50", children: [
1774
+ column.label,
1775
+ ":"
1776
+ ] }) : null,
1777
+ /* @__PURE__ */ jsx40("span", { className: "truncate", children: getCellContent(row, column) })
1778
+ ]
1779
+ },
1780
+ String(column.key)
1781
+ )) }),
1782
+ actions ? /* @__PURE__ */ jsx40("div", { className: "flex gap-2 border-t border-border pt-2", children: actions(row) }) : null
1783
+ ] }) }, index)) }),
1784
+ !isLoading && filtered.length > pageSize ? /* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between", children: [
1785
+ /* @__PURE__ */ jsxs26("span", { className: "text-sm text-muted-foreground", children: [
1786
+ filtered.length,
1787
+ " records \xB7 Page ",
1788
+ currentPage + 1,
1789
+ " of ",
1790
+ totalPages
1791
+ ] }),
1792
+ /* @__PURE__ */ jsxs26("div", { className: "flex gap-1", children: [
1793
+ /* @__PURE__ */ jsx40(
1794
+ Button,
1795
+ {
1796
+ variant: "outline",
1797
+ size: "icon",
1798
+ className: "h-8 w-8",
1799
+ onClick: () => setPage((previous) => Math.max(0, previous - 1)),
1800
+ disabled: currentPage === 0,
1801
+ children: /* @__PURE__ */ jsx40(ChevronLeft, { className: "h-4 w-4" })
1802
+ }
1803
+ ),
1804
+ /* @__PURE__ */ jsx40(
1805
+ Button,
1806
+ {
1807
+ variant: "outline",
1808
+ size: "icon",
1809
+ className: "h-8 w-8",
1810
+ onClick: () => setPage((previous) => Math.min(totalPages - 1, previous + 1)),
1811
+ disabled: currentPage >= totalPages - 1,
1812
+ children: /* @__PURE__ */ jsx40(ChevronRight3, { className: "h-4 w-4" })
1813
+ }
1814
+ )
1815
+ ] })
1816
+ ] }) : null
1817
+ ] });
1818
+ }
1819
+
1820
+ // src/components/tables/table-row-actions.tsx
1821
+ import { MoreHorizontal as MoreHorizontal2 } from "lucide-react";
1822
+ import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
1823
+ function TableRowActions({ className, label = "Abrir acciones", menuLabel = "Acciones", items }) {
1824
+ return /* @__PURE__ */ jsxs27(DropdownMenu, { children: [
1825
+ /* @__PURE__ */ jsx41(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx41(Button, { variant: "ghost", size: "icon", className: cn("h-8 w-8 shadow-none", className), "aria-label": label, children: /* @__PURE__ */ jsx41(MoreHorizontal2, { className: "h-4 w-4" }) }) }),
1826
+ /* @__PURE__ */ jsxs27(DropdownMenuContent, { align: "end", className: "w-48", children: [
1827
+ /* @__PURE__ */ jsx41(DropdownMenuLabel, { children: menuLabel }),
1828
+ /* @__PURE__ */ jsx41(DropdownMenuSeparator, {}),
1829
+ items.map((item) => /* @__PURE__ */ jsxs27(
1830
+ DropdownMenuItem,
1831
+ {
1832
+ disabled: item.disabled,
1833
+ onSelect: item.onSelect,
1834
+ className: cn(item.destructive && "text-destructive focus:bg-destructive/10 focus:text-destructive"),
1835
+ children: [
1836
+ item.icon,
1837
+ item.label,
1838
+ item.shortcut ? /* @__PURE__ */ jsx41(DropdownMenuShortcut, { children: item.shortcut }) : null
1839
+ ]
1840
+ },
1841
+ item.label
1842
+ ))
1843
+ ] })
1844
+ ] });
1845
+ }
1846
+ export {
1847
+ Alert,
1848
+ AlertDescription,
1849
+ AlertTitle,
1850
+ AppShell,
1851
+ Avatar,
1852
+ AvatarFallback,
1853
+ AvatarGroup,
1854
+ AvatarImage,
1855
+ Badge,
1856
+ BrandLogo,
1857
+ Breadcrumb,
1858
+ BreadcrumbEllipsis,
1859
+ BreadcrumbItem,
1860
+ BreadcrumbLink,
1861
+ BreadcrumbList,
1862
+ BreadcrumbPage,
1863
+ BreadcrumbSeparator,
1864
+ Button,
1865
+ Card,
1866
+ CardContent,
1867
+ CardDescription,
1868
+ CardFooter,
1869
+ CardHeader,
1870
+ CardTitle,
1871
+ CenteredIconCard,
1872
+ Checkbox,
1873
+ CheckboxField,
1874
+ ClickableCard,
1875
+ DataTable,
1876
+ Dialog,
1877
+ DialogClose,
1878
+ DialogContent,
1879
+ DialogDescription,
1880
+ DialogFooter,
1881
+ DialogHeader,
1882
+ DialogOverlay,
1883
+ DialogPortal,
1884
+ DialogTitle,
1885
+ DialogTrigger,
1886
+ Drawer,
1887
+ DrawerClose,
1888
+ DrawerContent,
1889
+ DrawerDescription,
1890
+ DrawerFooter,
1891
+ DrawerHeader,
1892
+ DrawerOverlay,
1893
+ DrawerPortal,
1894
+ DrawerTitle,
1895
+ DrawerTrigger,
1896
+ DropdownMenu,
1897
+ DropdownMenuCheckboxItem,
1898
+ DropdownMenuContent,
1899
+ DropdownMenuGroup,
1900
+ DropdownMenuItem,
1901
+ DropdownMenuLabel,
1902
+ DropdownMenuPortal,
1903
+ DropdownMenuRadioGroup,
1904
+ DropdownMenuRadioItem,
1905
+ DropdownMenuSeparator,
1906
+ DropdownMenuShortcut,
1907
+ DropdownMenuSub,
1908
+ DropdownMenuSubContent,
1909
+ DropdownMenuSubTrigger,
1910
+ DropdownMenuTrigger,
1911
+ FeatureIcon,
1912
+ FormSection,
1913
+ Input,
1914
+ Label3 as Label,
1915
+ LoadingCard,
1916
+ LoadingState,
1917
+ LoadingTableRows,
1918
+ ModuleIconButton,
1919
+ Navbar,
1920
+ NotificationAction,
1921
+ NotificationMessage,
1922
+ PageBreadcrumb,
1923
+ PageHeader,
1924
+ ProfileAvatar,
1925
+ ProfileAvatarRow,
1926
+ RadioField,
1927
+ RadioGroup2 as RadioGroup,
1928
+ RadioGroupItem,
1929
+ SearchableSelect,
1930
+ Select,
1931
+ SelectContent,
1932
+ SelectGroup,
1933
+ SelectItem,
1934
+ SelectLabel,
1935
+ SelectScrollDownButton,
1936
+ SelectScrollUpButton,
1937
+ SelectSeparator,
1938
+ SelectTrigger,
1939
+ SelectValue,
1940
+ Separator3 as Separator,
1941
+ Sheet,
1942
+ SheetClose,
1943
+ SheetContent,
1944
+ SheetDescription,
1945
+ SheetFooter,
1946
+ SheetHeader,
1947
+ SheetOverlay,
1948
+ SheetPortal,
1949
+ SheetTitle,
1950
+ SheetTrigger,
1951
+ Sidebar,
1952
+ Skeleton,
1953
+ Spinner,
1954
+ StatusBadge,
1955
+ Steps,
1956
+ Switch,
1957
+ SwitchField,
1958
+ Table,
1959
+ TableBody,
1960
+ TableCaption,
1961
+ TableCell,
1962
+ TableFooter,
1963
+ TableHead,
1964
+ TableHeader,
1965
+ TableRow,
1966
+ TableRowActions,
1967
+ Textarea,
1968
+ ThemeProvider,
1969
+ ThemeToggle,
1970
+ Toaster,
1971
+ Typography,
1972
+ badgeVariants,
1973
+ buttonVariants,
1974
+ cn,
1975
+ notify,
1976
+ useTheme
1977
+ };