@polastack/design-system 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,3711 @@
1
+ // src/lib/cn.ts
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+
8
+ // src/lib/create-context.ts
9
+ import * as React from "react";
10
+ function createContext2(displayName) {
11
+ const Context = React.createContext(void 0);
12
+ Context.displayName = displayName;
13
+ function useContext4() {
14
+ const context = React.useContext(Context);
15
+ if (context === void 0) {
16
+ throw new Error(`use${displayName} must be used within a ${displayName}Provider`);
17
+ }
18
+ return context;
19
+ }
20
+ return [Context.Provider, useContext4];
21
+ }
22
+
23
+ // src/hooks/use-breakpoint.ts
24
+ import { useState, useEffect } from "react";
25
+ var BREAKPOINTS = {
26
+ sm: 640,
27
+ md: 768,
28
+ lg: 1024,
29
+ xl: 1280,
30
+ "2xl": 1536
31
+ };
32
+ function getBreakpoint(width) {
33
+ if (width >= BREAKPOINTS["2xl"]) return "2xl";
34
+ if (width >= BREAKPOINTS.xl) return "xl";
35
+ if (width >= BREAKPOINTS.lg) return "lg";
36
+ if (width >= BREAKPOINTS.md) return "md";
37
+ if (width >= BREAKPOINTS.sm) return "sm";
38
+ return "base";
39
+ }
40
+ function useBreakpoint() {
41
+ const [breakpoint, setBreakpoint] = useState("lg");
42
+ useEffect(() => {
43
+ function handleResize() {
44
+ setBreakpoint(getBreakpoint(window.innerWidth));
45
+ }
46
+ handleResize();
47
+ window.addEventListener("resize", handleResize);
48
+ return () => window.removeEventListener("resize", handleResize);
49
+ }, []);
50
+ return {
51
+ breakpoint,
52
+ isMobile: breakpoint === "base" || breakpoint === "sm",
53
+ isTablet: breakpoint === "md",
54
+ isDesktop: breakpoint === "lg" || breakpoint === "xl" || breakpoint === "2xl"
55
+ };
56
+ }
57
+
58
+ // src/hooks/use-display-mode.ts
59
+ import { useState as useState2, useEffect as useEffect2 } from "react";
60
+ function getDisplayMode() {
61
+ if (typeof window === "undefined") return "browser";
62
+ if (window.matchMedia("(display-mode: standalone)").matches) return "standalone";
63
+ if (window.matchMedia("(display-mode: minimal-ui)").matches) return "minimal-ui";
64
+ if (window.matchMedia("(display-mode: fullscreen)").matches) return "fullscreen";
65
+ return "browser";
66
+ }
67
+ function useDisplayMode() {
68
+ const [displayMode, setDisplayMode] = useState2(getDisplayMode);
69
+ useEffect2(() => {
70
+ const mediaQuery = window.matchMedia("(display-mode: standalone)");
71
+ function handleChange() {
72
+ setDisplayMode(getDisplayMode());
73
+ }
74
+ mediaQuery.addEventListener("change", handleChange);
75
+ return () => mediaQuery.removeEventListener("change", handleChange);
76
+ }, []);
77
+ return {
78
+ displayMode,
79
+ isStandalone: displayMode === "standalone",
80
+ isPWA: displayMode !== "browser"
81
+ };
82
+ }
83
+
84
+ // src/hooks/use-online-status.ts
85
+ import { useState as useState3, useEffect as useEffect3, useCallback } from "react";
86
+ function useOnlineStatus() {
87
+ const [isOnline, setIsOnline] = useState3(
88
+ () => typeof navigator !== "undefined" ? navigator.onLine : true
89
+ );
90
+ const handleOnline = useCallback(() => setIsOnline(true), []);
91
+ const handleOffline = useCallback(() => setIsOnline(false), []);
92
+ useEffect3(() => {
93
+ window.addEventListener("online", handleOnline);
94
+ window.addEventListener("offline", handleOffline);
95
+ return () => {
96
+ window.removeEventListener("online", handleOnline);
97
+ window.removeEventListener("offline", handleOffline);
98
+ };
99
+ }, [handleOnline, handleOffline]);
100
+ return { isOnline, isOffline: !isOnline };
101
+ }
102
+
103
+ // src/hooks/use-viewport-height.ts
104
+ import { useState as useState4, useEffect as useEffect4 } from "react";
105
+ function useViewportHeight() {
106
+ const [viewportHeight, setViewportHeight] = useState4(
107
+ () => typeof window !== "undefined" ? window.innerHeight : 0
108
+ );
109
+ useEffect4(() => {
110
+ function handleResize() {
111
+ setViewportHeight(window.innerHeight);
112
+ }
113
+ const viewport = window.visualViewport;
114
+ if (viewport) {
115
+ const handleViewportResize = () => {
116
+ setViewportHeight(viewport.height);
117
+ };
118
+ handleViewportResize();
119
+ viewport.addEventListener("resize", handleViewportResize);
120
+ return () => viewport.removeEventListener("resize", handleViewportResize);
121
+ }
122
+ handleResize();
123
+ window.addEventListener("resize", handleResize);
124
+ return () => window.removeEventListener("resize", handleResize);
125
+ }, []);
126
+ return viewportHeight;
127
+ }
128
+
129
+ // src/hooks/use-install-prompt.ts
130
+ import { useState as useState5, useEffect as useEffect5, useCallback as useCallback2 } from "react";
131
+ function useInstallPrompt() {
132
+ const [deferredPrompt, setDeferredPrompt] = useState5(null);
133
+ const [isInstalled, setIsInstalled] = useState5(false);
134
+ useEffect5(() => {
135
+ if (window.matchMedia("(display-mode: standalone)").matches) {
136
+ setIsInstalled(true);
137
+ return;
138
+ }
139
+ function handleBeforeInstallPrompt(e) {
140
+ e.preventDefault();
141
+ setDeferredPrompt(e);
142
+ }
143
+ function handleAppInstalled() {
144
+ setIsInstalled(true);
145
+ setDeferredPrompt(null);
146
+ }
147
+ window.addEventListener("beforeinstallprompt", handleBeforeInstallPrompt);
148
+ window.addEventListener("appinstalled", handleAppInstalled);
149
+ return () => {
150
+ window.removeEventListener(
151
+ "beforeinstallprompt",
152
+ handleBeforeInstallPrompt
153
+ );
154
+ window.removeEventListener("appinstalled", handleAppInstalled);
155
+ };
156
+ }, []);
157
+ const promptInstall = useCallback2(async () => {
158
+ if (!deferredPrompt) return null;
159
+ await deferredPrompt.prompt();
160
+ const { outcome } = await deferredPrompt.userChoice;
161
+ if (outcome === "accepted") {
162
+ setIsInstalled(true);
163
+ }
164
+ setDeferredPrompt(null);
165
+ return outcome;
166
+ }, [deferredPrompt]);
167
+ return {
168
+ canInstall: !!deferredPrompt && !isInstalled,
169
+ isInstalled,
170
+ promptInstall
171
+ };
172
+ }
173
+
174
+ // src/hooks/use-theme.ts
175
+ import { useState as useState6, useEffect as useEffect6, useCallback as useCallback3, useMemo } from "react";
176
+ var DEFAULT_STORAGE_KEY = "polastack-theme";
177
+ function getSystemTheme() {
178
+ if (typeof window === "undefined") return "light";
179
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
180
+ }
181
+ function getStoredTheme(storageKey) {
182
+ if (typeof window === "undefined") return null;
183
+ try {
184
+ const stored = localStorage.getItem(storageKey);
185
+ if (stored === "light" || stored === "dark" || stored === "system") {
186
+ return stored;
187
+ }
188
+ } catch {
189
+ }
190
+ return null;
191
+ }
192
+ function applyTheme(resolvedTheme) {
193
+ if (typeof document === "undefined") return;
194
+ const root = document.documentElement;
195
+ if (resolvedTheme === "dark") {
196
+ root.classList.add("dark");
197
+ } else {
198
+ root.classList.remove("dark");
199
+ }
200
+ }
201
+ function useTheme(options = {}) {
202
+ const {
203
+ storageKey = DEFAULT_STORAGE_KEY,
204
+ defaultTheme = "system"
205
+ } = options;
206
+ const [theme, setThemeState] = useState6(
207
+ () => getStoredTheme(storageKey) ?? defaultTheme
208
+ );
209
+ const [systemTheme, setSystemTheme] = useState6(getSystemTheme);
210
+ const resolvedTheme = theme === "system" ? systemTheme : theme;
211
+ const setTheme = useCallback3(
212
+ (newTheme) => {
213
+ setThemeState(newTheme);
214
+ try {
215
+ localStorage.setItem(storageKey, newTheme);
216
+ } catch {
217
+ }
218
+ },
219
+ [storageKey]
220
+ );
221
+ useEffect6(() => {
222
+ applyTheme(resolvedTheme);
223
+ }, [resolvedTheme]);
224
+ useEffect6(() => {
225
+ const mql = window.matchMedia("(prefers-color-scheme: dark)");
226
+ const handler = (e) => {
227
+ setSystemTheme(e.matches ? "dark" : "light");
228
+ };
229
+ mql.addEventListener("change", handler);
230
+ return () => mql.removeEventListener("change", handler);
231
+ }, []);
232
+ return useMemo(
233
+ () => ({ theme, setTheme, resolvedTheme }),
234
+ [theme, setTheme, resolvedTheme]
235
+ );
236
+ }
237
+
238
+ // src/components/theme-provider/theme-provider.tsx
239
+ import * as React2 from "react";
240
+ import { jsx } from "react/jsx-runtime";
241
+ var ThemeContext = React2.createContext(void 0);
242
+ ThemeContext.displayName = "ThemeContext";
243
+ function ThemeProvider({
244
+ children,
245
+ defaultTheme = "system",
246
+ storageKey
247
+ }) {
248
+ const themeValue = useTheme({ defaultTheme, storageKey });
249
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: themeValue, children });
250
+ }
251
+ ThemeProvider.displayName = "ThemeProvider";
252
+ function useTheme2() {
253
+ const context = React2.useContext(ThemeContext);
254
+ if (context === void 0) {
255
+ throw new Error("useTheme must be used within a ThemeProvider");
256
+ }
257
+ return context;
258
+ }
259
+
260
+ // src/components/button/button.tsx
261
+ import * as React3 from "react";
262
+ import { cva } from "class-variance-authority";
263
+ import { jsx as jsx2 } from "react/jsx-runtime";
264
+ var buttonVariants = cva(
265
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset] disabled:pointer-events-none disabled:opacity-50 touch:min-h-[--touch-target-min]",
266
+ {
267
+ variants: {
268
+ variant: {
269
+ default: "bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700",
270
+ destructive: "bg-error-500 text-white hover:bg-error-600 active:bg-error-700",
271
+ outline: "border border-[--color-border-input] bg-[--color-surface-raised] text-[--color-on-surface] hover:bg-[--color-surface-sunken] active:bg-[--color-surface-muted]",
272
+ ghost: "text-[--color-on-surface] hover:bg-[--color-surface-muted] active:bg-neutral-200 dark:active:bg-neutral-700",
273
+ link: "text-primary-500 underline-offset-4 hover:underline"
274
+ },
275
+ size: {
276
+ sm: "h-8 px-3 text-xs",
277
+ md: "h-9 px-4 text-sm",
278
+ lg: "h-10 px-6 text-base",
279
+ icon: "h-9 w-9 touch:min-w-[--touch-target-min]"
280
+ }
281
+ },
282
+ defaultVariants: {
283
+ variant: "default",
284
+ size: "md"
285
+ }
286
+ }
287
+ );
288
+ var Button = React3.forwardRef(
289
+ ({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx2(
290
+ "button",
291
+ {
292
+ ref,
293
+ className: cn(buttonVariants({ variant, size }), className),
294
+ ...props
295
+ }
296
+ )
297
+ );
298
+ Button.displayName = "Button";
299
+
300
+ // src/components/badge/badge.tsx
301
+ import * as React4 from "react";
302
+ import { cva as cva2 } from "class-variance-authority";
303
+ import { jsx as jsx3 } from "react/jsx-runtime";
304
+ var badgeVariants = cva2(
305
+ "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium transition-colors",
306
+ {
307
+ variants: {
308
+ variant: {
309
+ default: "bg-primary-100 text-primary-700 dark:bg-primary-950 dark:text-primary-300",
310
+ success: "bg-success-100 text-success-700 dark:bg-success-950 dark:text-success-300",
311
+ warning: "bg-warning-100 text-warning-700 dark:bg-warning-950 dark:text-warning-300",
312
+ error: "bg-error-100 text-error-700 dark:bg-error-950 dark:text-error-300",
313
+ info: "bg-info-100 text-info-700 dark:bg-info-950 dark:text-info-300",
314
+ outline: "border border-[--color-border-input] text-[--color-on-surface-secondary]"
315
+ }
316
+ },
317
+ defaultVariants: {
318
+ variant: "default"
319
+ }
320
+ }
321
+ );
322
+ var Badge = React4.forwardRef(
323
+ ({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx3(
324
+ "span",
325
+ {
326
+ ref,
327
+ className: cn(badgeVariants({ variant }), className),
328
+ ...props
329
+ }
330
+ )
331
+ );
332
+ Badge.displayName = "Badge";
333
+
334
+ // src/components/avatar/avatar.tsx
335
+ import * as React5 from "react";
336
+ import { cva as cva3 } from "class-variance-authority";
337
+ import { jsx as jsx4 } from "react/jsx-runtime";
338
+ var [AvatarContextProvider, useAvatarContext] = createContext2("Avatar");
339
+ var avatarVariants = cva3(
340
+ "relative flex shrink-0 overflow-hidden rounded-full",
341
+ {
342
+ variants: {
343
+ size: {
344
+ sm: "h-8 w-8 text-xs",
345
+ md: "h-10 w-10 text-sm",
346
+ lg: "h-12 w-12 text-base"
347
+ }
348
+ },
349
+ defaultVariants: {
350
+ size: "md"
351
+ }
352
+ }
353
+ );
354
+ var Avatar = React5.forwardRef(
355
+ ({ className, size, ...props }, ref) => {
356
+ const [imageLoaded, setImageLoaded] = React5.useState(false);
357
+ return /* @__PURE__ */ jsx4(AvatarContextProvider, { value: { imageLoaded, setImageLoaded }, children: /* @__PURE__ */ jsx4(
358
+ "span",
359
+ {
360
+ ref,
361
+ className: cn(avatarVariants({ size }), className),
362
+ ...props
363
+ }
364
+ ) });
365
+ }
366
+ );
367
+ Avatar.displayName = "Avatar";
368
+ var AvatarImage = React5.forwardRef(
369
+ ({ className, onLoad, onError, ...props }, ref) => {
370
+ const { imageLoaded, setImageLoaded } = useAvatarContext();
371
+ return /* @__PURE__ */ jsx4(
372
+ "img",
373
+ {
374
+ ref,
375
+ className: cn(
376
+ "aspect-square h-full w-full object-cover",
377
+ !imageLoaded && "hidden",
378
+ className
379
+ ),
380
+ onLoad: (e) => {
381
+ setImageLoaded(true);
382
+ onLoad?.(e);
383
+ },
384
+ onError: (e) => {
385
+ setImageLoaded(false);
386
+ onError?.(e);
387
+ },
388
+ ...props
389
+ }
390
+ );
391
+ }
392
+ );
393
+ AvatarImage.displayName = "AvatarImage";
394
+ var AvatarFallback = React5.forwardRef(({ className, ...props }, ref) => {
395
+ const { imageLoaded } = useAvatarContext();
396
+ if (imageLoaded) return null;
397
+ return /* @__PURE__ */ jsx4(
398
+ "span",
399
+ {
400
+ ref,
401
+ className: cn(
402
+ "flex h-full w-full items-center justify-center rounded-full bg-[--color-surface-muted] font-medium text-[--color-on-surface-secondary]",
403
+ className
404
+ ),
405
+ ...props
406
+ }
407
+ );
408
+ });
409
+ AvatarFallback.displayName = "AvatarFallback";
410
+
411
+ // src/components/separator/separator.tsx
412
+ import * as React6 from "react";
413
+ import { jsx as jsx5 } from "react/jsx-runtime";
414
+ var Separator = React6.forwardRef(
415
+ ({ className, orientation = "horizontal", decorative = false, ...props }, ref) => /* @__PURE__ */ jsx5(
416
+ "div",
417
+ {
418
+ ref,
419
+ role: decorative ? "none" : "separator",
420
+ "aria-orientation": decorative ? void 0 : orientation,
421
+ className: cn(
422
+ "shrink-0 bg-[--color-border]",
423
+ orientation === "horizontal" ? "h-px w-full" : "w-px self-stretch",
424
+ className
425
+ ),
426
+ ...props
427
+ }
428
+ )
429
+ );
430
+ Separator.displayName = "Separator";
431
+
432
+ // src/components/skeleton/skeleton.tsx
433
+ import * as React7 from "react";
434
+ import { jsx as jsx6 } from "react/jsx-runtime";
435
+ var Skeleton = React7.forwardRef(
436
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx6(
437
+ "div",
438
+ {
439
+ ref,
440
+ "aria-hidden": "true",
441
+ className: cn("animate-pulse rounded-md bg-[--color-skeleton]", className),
442
+ ...props
443
+ }
444
+ )
445
+ );
446
+ Skeleton.displayName = "Skeleton";
447
+
448
+ // src/components/spinner/spinner.tsx
449
+ import * as React8 from "react";
450
+ import { cva as cva4 } from "class-variance-authority";
451
+ import { jsx as jsx7, jsxs } from "react/jsx-runtime";
452
+ var spinnerVariants = cva4("animate-spin", {
453
+ variants: {
454
+ size: {
455
+ sm: "h-4 w-4",
456
+ md: "h-6 w-6",
457
+ lg: "h-8 w-8"
458
+ }
459
+ },
460
+ defaultVariants: {
461
+ size: "md"
462
+ }
463
+ });
464
+ var Spinner = React8.forwardRef(
465
+ ({ className, size, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, role: "status", "aria-label": "Loading", ...props, children: [
466
+ /* @__PURE__ */ jsxs(
467
+ "svg",
468
+ {
469
+ className: cn(spinnerVariants({ size }), className),
470
+ xmlns: "http://www.w3.org/2000/svg",
471
+ fill: "none",
472
+ viewBox: "0 0 24 24",
473
+ children: [
474
+ /* @__PURE__ */ jsx7(
475
+ "circle",
476
+ {
477
+ className: "opacity-25",
478
+ cx: "12",
479
+ cy: "12",
480
+ r: "10",
481
+ stroke: "currentColor",
482
+ strokeWidth: "4"
483
+ }
484
+ ),
485
+ /* @__PURE__ */ jsx7(
486
+ "path",
487
+ {
488
+ className: "opacity-75",
489
+ fill: "currentColor",
490
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
491
+ }
492
+ )
493
+ ]
494
+ }
495
+ ),
496
+ /* @__PURE__ */ jsx7("span", { className: "sr-only", children: "Loading..." })
497
+ ] })
498
+ );
499
+ Spinner.displayName = "Spinner";
500
+
501
+ // src/components/card/card.tsx
502
+ import * as React9 from "react";
503
+ import { jsx as jsx8 } from "react/jsx-runtime";
504
+ var Card = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
505
+ "div",
506
+ {
507
+ ref,
508
+ className: cn(
509
+ "rounded-xl border border-[--color-border] bg-[--color-surface-raised] shadow-sm",
510
+ className
511
+ ),
512
+ ...props
513
+ }
514
+ ));
515
+ Card.displayName = "Card";
516
+ var CardHeader = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
517
+ "div",
518
+ {
519
+ ref,
520
+ className: cn("flex flex-col gap-1.5 p-6", className),
521
+ ...props
522
+ }
523
+ ));
524
+ CardHeader.displayName = "CardHeader";
525
+ var CardTitle = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
526
+ "h3",
527
+ {
528
+ ref,
529
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
530
+ ...props
531
+ }
532
+ ));
533
+ CardTitle.displayName = "CardTitle";
534
+ var CardDescription = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
535
+ "p",
536
+ {
537
+ ref,
538
+ className: cn("text-sm text-[--color-on-surface-muted]", className),
539
+ ...props
540
+ }
541
+ ));
542
+ CardDescription.displayName = "CardDescription";
543
+ var CardContent = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8("div", { ref, className: cn("p-6 pt-0", className), ...props }));
544
+ CardContent.displayName = "CardContent";
545
+ var CardFooter = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
546
+ "div",
547
+ {
548
+ ref,
549
+ className: cn("flex items-center p-6 pt-0", className),
550
+ ...props
551
+ }
552
+ ));
553
+ CardFooter.displayName = "CardFooter";
554
+
555
+ // src/components/tooltip/tooltip.tsx
556
+ import * as React10 from "react";
557
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
558
+ import { jsx as jsx9 } from "react/jsx-runtime";
559
+ var TooltipProvider = TooltipPrimitive.Provider;
560
+ var Tooltip = TooltipPrimitive.Root;
561
+ var TooltipTrigger = TooltipPrimitive.Trigger;
562
+ var TooltipContent = React10.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx9(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx9(
563
+ TooltipPrimitive.Content,
564
+ {
565
+ ref,
566
+ sideOffset,
567
+ className: cn(
568
+ "z-tooltip overflow-hidden rounded-md bg-[--color-tooltip-bg] px-3 py-1.5 text-xs text-[--color-tooltip-text] shadow-md",
569
+ "animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
570
+ "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",
571
+ "touch:hidden",
572
+ className
573
+ ),
574
+ ...props
575
+ }
576
+ ) }));
577
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
578
+
579
+ // src/components/toast/toast.tsx
580
+ import * as React11 from "react";
581
+ import * as ToastPrimitive from "@radix-ui/react-toast";
582
+ import { cva as cva5 } from "class-variance-authority";
583
+ import { jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
584
+ var ToastProvider = ToastPrimitive.Provider;
585
+ var ToastViewport = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
586
+ ToastPrimitive.Viewport,
587
+ {
588
+ ref,
589
+ className: cn(
590
+ "fixed bottom-0 left-0 right-0 z-toast flex max-h-screen w-full flex-col-reverse gap-2 p-4 pb-[calc(1rem+var(--safe-area-bottom))] sm:left-auto sm:max-w-[420px]",
591
+ className
592
+ ),
593
+ ...props
594
+ }
595
+ ));
596
+ ToastViewport.displayName = "ToastViewport";
597
+ var toastVariants = cva5(
598
+ "group pointer-events-auto relative flex w-full items-center justify-between gap-4 overflow-hidden rounded-lg border p-4 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=open]:slide-in-from-right-full data-[state=closed]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full",
599
+ {
600
+ variants: {
601
+ variant: {
602
+ default: "border-[--color-border] bg-[--color-surface-raised] text-[--color-on-surface]",
603
+ success: "border-success-200 bg-success-50 text-success-900 dark:border-success-800 dark:bg-success-950 dark:text-success-200",
604
+ error: "border-error-200 bg-error-50 text-error-900 dark:border-error-800 dark:bg-error-950 dark:text-error-200"
605
+ }
606
+ },
607
+ defaultVariants: {
608
+ variant: "default"
609
+ }
610
+ }
611
+ );
612
+ var Toast = React11.forwardRef(({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx10(
613
+ ToastPrimitive.Root,
614
+ {
615
+ ref,
616
+ className: cn(toastVariants({ variant }), className),
617
+ ...props
618
+ }
619
+ ));
620
+ Toast.displayName = "Toast";
621
+ var ToastAction = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
622
+ ToastPrimitive.Action,
623
+ {
624
+ ref,
625
+ className: cn(
626
+ "inline-flex h-8 shrink-0 items-center justify-center rounded-md border border-[--color-border] bg-transparent px-3 text-xs font-medium transition-colors hover:bg-[--color-surface-muted] focus:outline-none focus:ring-2 focus:ring-[--color-ring] focus:ring-offset-2 ring-offset-[--color-ring-offset] disabled:pointer-events-none disabled:opacity-50",
627
+ className
628
+ ),
629
+ ...props
630
+ }
631
+ ));
632
+ ToastAction.displayName = "ToastAction";
633
+ var ToastClose = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
634
+ ToastPrimitive.Close,
635
+ {
636
+ ref,
637
+ className: cn(
638
+ "absolute right-2 top-2 rounded-md p-1 text-[--color-on-surface-muted] opacity-0 transition-opacity hover:text-[--color-on-surface] focus:opacity-100 focus:outline-none focus:ring-2 group-hover:opacity-100",
639
+ className
640
+ ),
641
+ "toast-close": "",
642
+ "aria-label": "Close",
643
+ ...props,
644
+ children: /* @__PURE__ */ jsxs2(
645
+ "svg",
646
+ {
647
+ xmlns: "http://www.w3.org/2000/svg",
648
+ width: "16",
649
+ height: "16",
650
+ viewBox: "0 0 24 24",
651
+ fill: "none",
652
+ stroke: "currentColor",
653
+ strokeWidth: "2",
654
+ strokeLinecap: "round",
655
+ strokeLinejoin: "round",
656
+ children: [
657
+ /* @__PURE__ */ jsx10("path", { d: "M18 6 6 18" }),
658
+ /* @__PURE__ */ jsx10("path", { d: "m6 6 12 12" })
659
+ ]
660
+ }
661
+ )
662
+ }
663
+ ));
664
+ ToastClose.displayName = "ToastClose";
665
+ var ToastTitle = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
666
+ ToastPrimitive.Title,
667
+ {
668
+ ref,
669
+ className: cn("text-sm font-semibold", className),
670
+ ...props
671
+ }
672
+ ));
673
+ ToastTitle.displayName = "ToastTitle";
674
+ var ToastDescription = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
675
+ ToastPrimitive.Description,
676
+ {
677
+ ref,
678
+ className: cn("text-sm opacity-90", className),
679
+ ...props
680
+ }
681
+ ));
682
+ ToastDescription.displayName = "ToastDescription";
683
+
684
+ // src/components/toast/use-toast.ts
685
+ import * as React12 from "react";
686
+ var TOAST_LIMIT = 5;
687
+ var TOAST_REMOVE_DELAY = 1e3;
688
+ var count = 0;
689
+ function genId() {
690
+ count = (count + 1) % Number.MAX_SAFE_INTEGER;
691
+ return count.toString();
692
+ }
693
+ var toastTimeouts = /* @__PURE__ */ new Map();
694
+ function addToRemoveQueue(toastId) {
695
+ if (toastTimeouts.has(toastId)) return;
696
+ const timeout = setTimeout(() => {
697
+ toastTimeouts.delete(toastId);
698
+ dispatch({ type: "REMOVE_TOAST", toastId });
699
+ }, TOAST_REMOVE_DELAY);
700
+ toastTimeouts.set(toastId, timeout);
701
+ }
702
+ function reducer(state, action) {
703
+ switch (action.type) {
704
+ case "ADD_TOAST":
705
+ return {
706
+ ...state,
707
+ toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT)
708
+ };
709
+ case "UPDATE_TOAST":
710
+ return {
711
+ ...state,
712
+ toasts: state.toasts.map(
713
+ (t) => t.id === action.toast.id ? { ...t, ...action.toast } : t
714
+ )
715
+ };
716
+ case "DISMISS_TOAST": {
717
+ const { toastId } = action;
718
+ if (toastId) {
719
+ addToRemoveQueue(toastId);
720
+ } else {
721
+ state.toasts.forEach((t) => addToRemoveQueue(t.id));
722
+ }
723
+ return {
724
+ ...state,
725
+ toasts: state.toasts.map(
726
+ (t) => t.id === toastId || toastId === void 0 ? { ...t, open: false } : t
727
+ )
728
+ };
729
+ }
730
+ case "REMOVE_TOAST":
731
+ if (action.toastId === void 0) {
732
+ return { ...state, toasts: [] };
733
+ }
734
+ return {
735
+ ...state,
736
+ toasts: state.toasts.filter((t) => t.id !== action.toastId)
737
+ };
738
+ }
739
+ }
740
+ var listeners = [];
741
+ var memoryState = { toasts: [] };
742
+ function dispatch(action) {
743
+ memoryState = reducer(memoryState, action);
744
+ listeners.forEach((listener) => listener(memoryState));
745
+ }
746
+ function toast(props) {
747
+ const id = genId();
748
+ const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
749
+ dispatch({
750
+ type: "ADD_TOAST",
751
+ toast: { ...props, id, open: true }
752
+ });
753
+ return { id, dismiss };
754
+ }
755
+ function useToast() {
756
+ const [state, setState] = React12.useState(memoryState);
757
+ React12.useEffect(() => {
758
+ listeners.push(setState);
759
+ return () => {
760
+ const index = listeners.indexOf(setState);
761
+ if (index > -1) listeners.splice(index, 1);
762
+ };
763
+ }, []);
764
+ return {
765
+ ...state,
766
+ toast,
767
+ dismiss: (toastId) => dispatch({ type: "DISMISS_TOAST", toastId })
768
+ };
769
+ }
770
+
771
+ // src/components/toast/toaster.tsx
772
+ import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
773
+ function Toaster() {
774
+ const { toasts } = useToast();
775
+ return /* @__PURE__ */ jsxs3(ToastProvider, { children: [
776
+ toasts.map(({ id, title, description, action, ...props }) => /* @__PURE__ */ jsxs3(Toast, { ...props, children: [
777
+ /* @__PURE__ */ jsxs3("div", { className: "grid gap-1", children: [
778
+ title && /* @__PURE__ */ jsx11(ToastTitle, { children: title }),
779
+ description && /* @__PURE__ */ jsx11(ToastDescription, { children: description })
780
+ ] }),
781
+ action,
782
+ /* @__PURE__ */ jsx11(ToastClose, {})
783
+ ] }, id)),
784
+ /* @__PURE__ */ jsx11(ToastViewport, {})
785
+ ] });
786
+ }
787
+
788
+ // src/components/label/label.tsx
789
+ import * as React13 from "react";
790
+ import * as LabelPrimitive from "@radix-ui/react-label";
791
+ import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
792
+ var Label = React13.forwardRef(({ className, required, children, ...props }, ref) => /* @__PURE__ */ jsxs4(
793
+ LabelPrimitive.Root,
794
+ {
795
+ ref,
796
+ className: cn(
797
+ "text-sm font-medium text-[--color-on-surface] peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
798
+ className
799
+ ),
800
+ ...props,
801
+ children: [
802
+ children,
803
+ required && /* @__PURE__ */ jsx12("span", { "aria-hidden": "true", className: "ml-0.5 text-error-500", children: "*" })
804
+ ]
805
+ }
806
+ ));
807
+ Label.displayName = "Label";
808
+
809
+ // src/components/input/input.tsx
810
+ import * as React14 from "react";
811
+ import { cva as cva6 } from "class-variance-authority";
812
+ import { jsx as jsx13 } from "react/jsx-runtime";
813
+ var inputVariants = cva6(
814
+ "flex w-full rounded-md border border-[--color-border-input] bg-[--color-surface-raised] px-3 text-[--color-on-surface] transition-colors duration-fast file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-[--color-on-surface-muted] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset] disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-error-500 aria-[invalid=true]:focus-visible:ring-error-500 touch:min-h-[--touch-target-min]",
815
+ {
816
+ variants: {
817
+ size: {
818
+ sm: "h-8 text-xs",
819
+ md: "h-9 text-sm",
820
+ lg: "h-10 text-base"
821
+ }
822
+ },
823
+ defaultVariants: {
824
+ size: "md"
825
+ }
826
+ }
827
+ );
828
+ var Input = React14.forwardRef(
829
+ ({ className, size, type, ...props }, ref) => /* @__PURE__ */ jsx13(
830
+ "input",
831
+ {
832
+ ref,
833
+ type,
834
+ className: cn(inputVariants({ size }), className),
835
+ ...props
836
+ }
837
+ )
838
+ );
839
+ Input.displayName = "Input";
840
+
841
+ // src/components/textarea/textarea.tsx
842
+ import * as React15 from "react";
843
+ import { cva as cva7 } from "class-variance-authority";
844
+ import { jsx as jsx14 } from "react/jsx-runtime";
845
+ var textareaVariants = cva7(
846
+ "flex w-full resize-y rounded-md border border-[--color-border-input] bg-[--color-surface-raised] px-3 py-2 text-[--color-on-surface] transition-colors duration-fast placeholder:text-[--color-on-surface-muted] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset] disabled:cursor-not-allowed disabled:opacity-50 aria-[invalid=true]:border-error-500 aria-[invalid=true]:focus-visible:ring-error-500",
847
+ {
848
+ variants: {
849
+ size: {
850
+ sm: "min-h-[60px] text-xs",
851
+ md: "min-h-[80px] text-sm",
852
+ lg: "min-h-[100px] text-base"
853
+ }
854
+ },
855
+ defaultVariants: {
856
+ size: "md"
857
+ }
858
+ }
859
+ );
860
+ var Textarea = React15.forwardRef(
861
+ ({ className, size, ...props }, ref) => /* @__PURE__ */ jsx14(
862
+ "textarea",
863
+ {
864
+ ref,
865
+ className: cn(textareaVariants({ size }), className),
866
+ ...props
867
+ }
868
+ )
869
+ );
870
+ Textarea.displayName = "Textarea";
871
+
872
+ // src/components/checkbox/checkbox.tsx
873
+ import * as React16 from "react";
874
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
875
+ import { jsx as jsx15 } from "react/jsx-runtime";
876
+ var Checkbox = React16.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx15(
877
+ CheckboxPrimitive.Root,
878
+ {
879
+ ref,
880
+ className: cn(
881
+ "peer h-4 w-4 shrink-0 rounded-sm border border-[--color-border-input] transition-colors duration-fast",
882
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset]",
883
+ "disabled:cursor-not-allowed disabled:opacity-50",
884
+ "data-[state=checked]:border-primary-500 data-[state=checked]:bg-primary-500 data-[state=checked]:text-white",
885
+ "data-[state=indeterminate]:border-primary-500 data-[state=indeterminate]:bg-primary-500 data-[state=indeterminate]:text-white",
886
+ "touch:min-h-[--touch-target-min] touch:min-w-[--touch-target-min]",
887
+ className
888
+ ),
889
+ ...props,
890
+ children: /* @__PURE__ */ jsx15(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center", children: props.checked === "indeterminate" ? /* @__PURE__ */ jsx15(
891
+ "svg",
892
+ {
893
+ width: "12",
894
+ height: "12",
895
+ viewBox: "0 0 24 24",
896
+ fill: "none",
897
+ stroke: "currentColor",
898
+ strokeWidth: "3",
899
+ strokeLinecap: "round",
900
+ children: /* @__PURE__ */ jsx15("path", { d: "M5 12h14" })
901
+ }
902
+ ) : /* @__PURE__ */ jsx15(
903
+ "svg",
904
+ {
905
+ width: "12",
906
+ height: "12",
907
+ viewBox: "0 0 24 24",
908
+ fill: "none",
909
+ stroke: "currentColor",
910
+ strokeWidth: "3",
911
+ strokeLinecap: "round",
912
+ strokeLinejoin: "round",
913
+ children: /* @__PURE__ */ jsx15("polyline", { points: "20 6 9 17 4 12" })
914
+ }
915
+ ) })
916
+ }
917
+ ));
918
+ Checkbox.displayName = "Checkbox";
919
+
920
+ // src/components/radio-group/radio-group.tsx
921
+ import * as React17 from "react";
922
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
923
+ import { jsx as jsx16 } from "react/jsx-runtime";
924
+ var RadioGroup = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
925
+ RadioGroupPrimitive.Root,
926
+ {
927
+ ref,
928
+ className: cn("flex flex-col gap-2", className),
929
+ ...props
930
+ }
931
+ ));
932
+ RadioGroup.displayName = "RadioGroup";
933
+ var RadioGroupItem = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx16(
934
+ RadioGroupPrimitive.Item,
935
+ {
936
+ ref,
937
+ className: cn(
938
+ "aspect-square h-4 w-4 rounded-full border border-[--color-border-input] transition-colors duration-fast",
939
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset]",
940
+ "disabled:cursor-not-allowed disabled:opacity-50",
941
+ "data-[state=checked]:border-primary-500",
942
+ "touch:min-h-[--touch-target-min] touch:min-w-[--touch-target-min]",
943
+ className
944
+ ),
945
+ ...props,
946
+ children: /* @__PURE__ */ jsx16(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx16(
947
+ "svg",
948
+ {
949
+ width: "8",
950
+ height: "8",
951
+ viewBox: "0 0 8 8",
952
+ fill: "currentColor",
953
+ className: "text-primary-500",
954
+ children: /* @__PURE__ */ jsx16("circle", { cx: "4", cy: "4", r: "4" })
955
+ }
956
+ ) })
957
+ }
958
+ ));
959
+ RadioGroupItem.displayName = "RadioGroupItem";
960
+
961
+ // src/components/switch/switch.tsx
962
+ import * as React18 from "react";
963
+ import * as SwitchPrimitive from "@radix-ui/react-switch";
964
+ import { cva as cva8 } from "class-variance-authority";
965
+ import { jsx as jsx17 } from "react/jsx-runtime";
966
+ var switchVariants = cva8(
967
+ "peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary-500 data-[state=unchecked]:bg-neutral-300 dark:data-[state=unchecked]:bg-neutral-600 touch:min-h-[--touch-target-min]",
968
+ {
969
+ variants: {
970
+ size: {
971
+ sm: "h-4 w-7",
972
+ md: "h-5 w-9",
973
+ lg: "h-6 w-11"
974
+ }
975
+ },
976
+ defaultVariants: {
977
+ size: "md"
978
+ }
979
+ }
980
+ );
981
+ var thumbVariants = cva8(
982
+ "pointer-events-none block rounded-full bg-white shadow-sm transition-transform duration-fast",
983
+ {
984
+ variants: {
985
+ size: {
986
+ sm: "h-3 w-3 data-[state=checked]:translate-x-3 data-[state=unchecked]:translate-x-0",
987
+ md: "h-4 w-4 data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
988
+ lg: "h-5 w-5 data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
989
+ }
990
+ },
991
+ defaultVariants: {
992
+ size: "md"
993
+ }
994
+ }
995
+ );
996
+ var Switch = React18.forwardRef(({ className, size, ...props }, ref) => /* @__PURE__ */ jsx17(
997
+ SwitchPrimitive.Root,
998
+ {
999
+ ref,
1000
+ className: cn(switchVariants({ size }), className),
1001
+ ...props,
1002
+ children: /* @__PURE__ */ jsx17(SwitchPrimitive.Thumb, { className: thumbVariants({ size }) })
1003
+ }
1004
+ ));
1005
+ Switch.displayName = "Switch";
1006
+
1007
+ // src/components/select/select.tsx
1008
+ import * as React19 from "react";
1009
+ import * as SelectPrimitive from "@radix-ui/react-select";
1010
+ import { jsx as jsx18, jsxs as jsxs5 } from "react/jsx-runtime";
1011
+ var Select = SelectPrimitive.Root;
1012
+ var SelectGroup = SelectPrimitive.Group;
1013
+ var SelectValue = SelectPrimitive.Value;
1014
+ var SelectTrigger = React19.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
1015
+ SelectPrimitive.Trigger,
1016
+ {
1017
+ ref,
1018
+ className: cn(
1019
+ "flex h-9 w-full items-center justify-between rounded-md border border-[--color-border-input] bg-[--color-surface-raised] px-3 text-sm text-[--color-on-surface] transition-colors duration-fast",
1020
+ "placeholder:text-[--color-on-surface-muted]",
1021
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[--color-ring] focus-visible:ring-offset-2 ring-offset-[--color-ring-offset]",
1022
+ "disabled:cursor-not-allowed disabled:opacity-50",
1023
+ "aria-[invalid=true]:border-error-500 aria-[invalid=true]:focus-visible:ring-error-500",
1024
+ "touch:min-h-[--touch-target-min]",
1025
+ className
1026
+ ),
1027
+ ...props,
1028
+ children: [
1029
+ children,
1030
+ /* @__PURE__ */ jsx18(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx18(
1031
+ "svg",
1032
+ {
1033
+ width: "16",
1034
+ height: "16",
1035
+ viewBox: "0 0 24 24",
1036
+ fill: "none",
1037
+ stroke: "currentColor",
1038
+ strokeWidth: "2",
1039
+ strokeLinecap: "round",
1040
+ strokeLinejoin: "round",
1041
+ className: "shrink-0 opacity-50",
1042
+ children: /* @__PURE__ */ jsx18("path", { d: "m6 9 6 6 6-6" })
1043
+ }
1044
+ ) })
1045
+ ]
1046
+ }
1047
+ ));
1048
+ SelectTrigger.displayName = "SelectTrigger";
1049
+ var SelectContent = React19.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx18(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx18(
1050
+ SelectPrimitive.Content,
1051
+ {
1052
+ ref,
1053
+ className: cn(
1054
+ "relative z-popover max-h-96 min-w-[8rem] overflow-hidden rounded-md border border-[--color-border] bg-[--color-surface-raised] shadow-md",
1055
+ "animate-in fade-in-0 zoom-in-95",
1056
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1057
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
1058
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=top]:-translate-y-1",
1059
+ className
1060
+ ),
1061
+ position,
1062
+ ...props,
1063
+ children: /* @__PURE__ */ jsx18(
1064
+ SelectPrimitive.Viewport,
1065
+ {
1066
+ className: cn(
1067
+ "p-1",
1068
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
1069
+ ),
1070
+ children
1071
+ }
1072
+ )
1073
+ }
1074
+ ) }));
1075
+ SelectContent.displayName = "SelectContent";
1076
+ var SelectItem = React19.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
1077
+ SelectPrimitive.Item,
1078
+ {
1079
+ ref,
1080
+ className: cn(
1081
+ "relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
1082
+ "focus:bg-[--color-surface-muted]",
1083
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1084
+ className
1085
+ ),
1086
+ ...props,
1087
+ children: [
1088
+ /* @__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(
1089
+ "svg",
1090
+ {
1091
+ width: "14",
1092
+ height: "14",
1093
+ viewBox: "0 0 24 24",
1094
+ fill: "none",
1095
+ stroke: "currentColor",
1096
+ strokeWidth: "2",
1097
+ strokeLinecap: "round",
1098
+ strokeLinejoin: "round",
1099
+ children: /* @__PURE__ */ jsx18("polyline", { points: "20 6 9 17 4 12" })
1100
+ }
1101
+ ) }) }),
1102
+ /* @__PURE__ */ jsx18(SelectPrimitive.ItemText, { children })
1103
+ ]
1104
+ }
1105
+ ));
1106
+ SelectItem.displayName = "SelectItem";
1107
+ var SelectLabel = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
1108
+ SelectPrimitive.Label,
1109
+ {
1110
+ ref,
1111
+ className: cn("px-2 py-1.5 text-xs font-medium text-[--color-on-surface-muted]", className),
1112
+ ...props
1113
+ }
1114
+ ));
1115
+ SelectLabel.displayName = "SelectLabel";
1116
+ var SelectSeparator = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx18(
1117
+ SelectPrimitive.Separator,
1118
+ {
1119
+ ref,
1120
+ className: cn("-mx-1 my-1 h-px bg-[--color-border]", className),
1121
+ ...props
1122
+ }
1123
+ ));
1124
+ SelectSeparator.displayName = "SelectSeparator";
1125
+
1126
+ // src/components/number-input/number-input.tsx
1127
+ import * as React20 from "react";
1128
+ import { cva as cva9 } from "class-variance-authority";
1129
+ import { jsx as jsx19, jsxs as jsxs6 } from "react/jsx-runtime";
1130
+ var numberInputVariants = cva9(
1131
+ "flex w-full rounded-md border border-[--color-border-input] bg-[--color-surface-raised] text-[--color-on-surface] transition-colors duration-fast focus-within:ring-2 focus-within:ring-[--color-ring] focus-within:ring-offset-2 ring-offset-[--color-ring-offset] aria-[invalid=true]:border-error-500 aria-[invalid=true]:focus-within:ring-error-500",
1132
+ {
1133
+ variants: {
1134
+ size: {
1135
+ sm: "h-8 text-xs",
1136
+ md: "h-9 text-sm",
1137
+ lg: "h-10 text-base"
1138
+ }
1139
+ },
1140
+ defaultVariants: {
1141
+ size: "md"
1142
+ }
1143
+ }
1144
+ );
1145
+ var NumberInput = React20.forwardRef(
1146
+ ({
1147
+ className,
1148
+ size,
1149
+ value: controlledValue,
1150
+ defaultValue,
1151
+ onChange,
1152
+ min,
1153
+ max,
1154
+ step = 1,
1155
+ precision,
1156
+ disabled,
1157
+ readOnly,
1158
+ ...props
1159
+ }, ref) => {
1160
+ const [internalValue, setInternalValue] = React20.useState(
1161
+ defaultValue != null ? formatValue(defaultValue, precision) : ""
1162
+ );
1163
+ const isControlled = controlledValue !== void 0;
1164
+ const displayValue = isControlled ? controlledValue != null ? formatValue(controlledValue, precision) : "" : internalValue;
1165
+ function formatValue(val, prec) {
1166
+ return prec != null ? val.toFixed(prec) : String(val);
1167
+ }
1168
+ function clamp(val) {
1169
+ let result = val;
1170
+ if (min != null) result = Math.max(min, result);
1171
+ if (max != null) result = Math.min(max, result);
1172
+ return result;
1173
+ }
1174
+ function updateValue(newValue) {
1175
+ if (newValue != null) {
1176
+ const clamped = clamp(newValue);
1177
+ if (!isControlled) {
1178
+ setInternalValue(formatValue(clamped, precision));
1179
+ }
1180
+ onChange?.(clamped);
1181
+ } else {
1182
+ if (!isControlled) {
1183
+ setInternalValue("");
1184
+ }
1185
+ onChange?.(void 0);
1186
+ }
1187
+ }
1188
+ function handleInputChange(e) {
1189
+ const raw = e.target.value;
1190
+ if (!isControlled) {
1191
+ setInternalValue(raw);
1192
+ }
1193
+ if (raw === "" || raw === "-") {
1194
+ onChange?.(void 0);
1195
+ return;
1196
+ }
1197
+ const num = parseFloat(raw);
1198
+ if (!isNaN(num)) {
1199
+ onChange?.(num);
1200
+ }
1201
+ }
1202
+ function handleBlur() {
1203
+ const num = parseFloat(displayValue);
1204
+ if (!isNaN(num)) {
1205
+ updateValue(num);
1206
+ } else {
1207
+ updateValue(void 0);
1208
+ }
1209
+ }
1210
+ function increment() {
1211
+ const current = parseFloat(displayValue) || 0;
1212
+ updateValue(current + step);
1213
+ }
1214
+ function decrement() {
1215
+ const current = parseFloat(displayValue) || 0;
1216
+ updateValue(current - step);
1217
+ }
1218
+ function handleKeyDown(e) {
1219
+ if (e.key === "ArrowUp") {
1220
+ e.preventDefault();
1221
+ increment();
1222
+ } else if (e.key === "ArrowDown") {
1223
+ e.preventDefault();
1224
+ decrement();
1225
+ }
1226
+ }
1227
+ return /* @__PURE__ */ jsxs6(
1228
+ "div",
1229
+ {
1230
+ className: cn(
1231
+ numberInputVariants({ size }),
1232
+ (disabled || readOnly) && "opacity-50 cursor-not-allowed",
1233
+ className
1234
+ ),
1235
+ "aria-invalid": props["aria-invalid"],
1236
+ children: [
1237
+ /* @__PURE__ */ jsx19(
1238
+ "input",
1239
+ {
1240
+ ref,
1241
+ type: "text",
1242
+ inputMode: "numeric",
1243
+ value: displayValue,
1244
+ onChange: handleInputChange,
1245
+ onBlur: handleBlur,
1246
+ onKeyDown: handleKeyDown,
1247
+ disabled,
1248
+ readOnly,
1249
+ className: "h-full w-full bg-transparent px-3 outline-none disabled:cursor-not-allowed",
1250
+ ...props
1251
+ }
1252
+ ),
1253
+ !readOnly && !disabled && /* @__PURE__ */ jsxs6("div", { className: "flex flex-col border-l border-[--color-border-input]", children: [
1254
+ /* @__PURE__ */ jsx19(
1255
+ "button",
1256
+ {
1257
+ type: "button",
1258
+ tabIndex: -1,
1259
+ onClick: increment,
1260
+ disabled: max != null && parseFloat(displayValue) >= max,
1261
+ className: "flex flex-1 items-center justify-center px-1.5 text-[--color-on-surface-muted] hover:bg-[--color-surface-muted] disabled:opacity-30",
1262
+ "aria-label": "Increment",
1263
+ children: /* @__PURE__ */ jsx19(
1264
+ "svg",
1265
+ {
1266
+ width: "10",
1267
+ height: "10",
1268
+ viewBox: "0 0 24 24",
1269
+ fill: "none",
1270
+ stroke: "currentColor",
1271
+ strokeWidth: "2.5",
1272
+ strokeLinecap: "round",
1273
+ strokeLinejoin: "round",
1274
+ children: /* @__PURE__ */ jsx19("path", { d: "m18 15-6-6-6 6" })
1275
+ }
1276
+ )
1277
+ }
1278
+ ),
1279
+ /* @__PURE__ */ jsx19(
1280
+ "button",
1281
+ {
1282
+ type: "button",
1283
+ tabIndex: -1,
1284
+ onClick: decrement,
1285
+ disabled: min != null && parseFloat(displayValue) <= min,
1286
+ className: "flex flex-1 items-center justify-center border-t border-[--color-border-input] px-1.5 text-[--color-on-surface-muted] hover:bg-[--color-surface-muted] disabled:opacity-30",
1287
+ "aria-label": "Decrement",
1288
+ children: /* @__PURE__ */ jsx19(
1289
+ "svg",
1290
+ {
1291
+ width: "10",
1292
+ height: "10",
1293
+ viewBox: "0 0 24 24",
1294
+ fill: "none",
1295
+ stroke: "currentColor",
1296
+ strokeWidth: "2.5",
1297
+ strokeLinecap: "round",
1298
+ strokeLinejoin: "round",
1299
+ children: /* @__PURE__ */ jsx19("path", { d: "m6 9 6 6 6-6" })
1300
+ }
1301
+ )
1302
+ }
1303
+ )
1304
+ ] })
1305
+ ]
1306
+ }
1307
+ );
1308
+ }
1309
+ );
1310
+ NumberInput.displayName = "NumberInput";
1311
+
1312
+ // src/components/date-picker/date-picker.tsx
1313
+ import * as React21 from "react";
1314
+ import { jsx as jsx20 } from "react/jsx-runtime";
1315
+ var DatePicker = React21.forwardRef(
1316
+ ({ className, size, ...props }, ref) => /* @__PURE__ */ jsx20(
1317
+ "input",
1318
+ {
1319
+ ref,
1320
+ type: "date",
1321
+ className: cn(
1322
+ inputVariants({ size }),
1323
+ "[&::-webkit-calendar-picker-indicator]:cursor-pointer",
1324
+ className
1325
+ ),
1326
+ ...props
1327
+ }
1328
+ )
1329
+ );
1330
+ DatePicker.displayName = "DatePicker";
1331
+
1332
+ // src/components/combobox/combobox.tsx
1333
+ import * as React22 from "react";
1334
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
1335
+ import { Command } from "cmdk";
1336
+ import { jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
1337
+ var Combobox = React22.forwardRef(
1338
+ ({
1339
+ options,
1340
+ value,
1341
+ onValueChange,
1342
+ placeholder = "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
1343
+ searchPlaceholder = "\u691C\u7D22...",
1344
+ emptyMessage = "\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F",
1345
+ disabled,
1346
+ className,
1347
+ ...props
1348
+ }, ref) => {
1349
+ const [open, setOpen] = React22.useState(false);
1350
+ const [search, setSearch] = React22.useState("");
1351
+ const selectedOption = options.find((o) => o.value === value);
1352
+ return /* @__PURE__ */ jsxs7(PopoverPrimitive.Root, { open, onOpenChange: setOpen, children: [
1353
+ /* @__PURE__ */ jsxs7(
1354
+ PopoverPrimitive.Trigger,
1355
+ {
1356
+ ref,
1357
+ role: "combobox",
1358
+ "aria-expanded": open,
1359
+ disabled,
1360
+ className: cn(
1361
+ "flex h-9 w-full items-center justify-between rounded-md border border-[--color-border-input] bg-[--color-surface-raised] px-3 text-sm text-[--color-on-surface] transition-colors duration-fast",
1362
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2",
1363
+ "disabled:cursor-not-allowed disabled:opacity-50",
1364
+ "aria-[invalid=true]:border-error-500 aria-[invalid=true]:focus-visible:ring-error-500",
1365
+ "touch:min-h-[--touch-target-min]",
1366
+ className
1367
+ ),
1368
+ ...props,
1369
+ children: [
1370
+ /* @__PURE__ */ jsx21("span", { className: cn(!selectedOption && "text-[--color-on-surface-muted]"), children: selectedOption?.label ?? placeholder }),
1371
+ /* @__PURE__ */ jsxs7(
1372
+ "svg",
1373
+ {
1374
+ width: "16",
1375
+ height: "16",
1376
+ viewBox: "0 0 24 24",
1377
+ fill: "none",
1378
+ stroke: "currentColor",
1379
+ strokeWidth: "2",
1380
+ strokeLinecap: "round",
1381
+ strokeLinejoin: "round",
1382
+ className: "shrink-0 opacity-50",
1383
+ children: [
1384
+ /* @__PURE__ */ jsx21("path", { d: "m7 15 5 5 5-5" }),
1385
+ /* @__PURE__ */ jsx21("path", { d: "m7 9 5-5 5 5" })
1386
+ ]
1387
+ }
1388
+ )
1389
+ ]
1390
+ }
1391
+ ),
1392
+ /* @__PURE__ */ jsx21(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx21(
1393
+ PopoverPrimitive.Content,
1394
+ {
1395
+ className: "z-popover w-[var(--radix-popover-trigger-width)] rounded-md border border-[--color-border] bg-[--color-surface-raised] p-0 shadow-md animate-in fade-in-0 zoom-in-95",
1396
+ sideOffset: 4,
1397
+ align: "start",
1398
+ children: /* @__PURE__ */ jsxs7(Command, { shouldFilter: true, children: [
1399
+ /* @__PURE__ */ jsx21(
1400
+ Command.Input,
1401
+ {
1402
+ value: search,
1403
+ onValueChange: setSearch,
1404
+ placeholder: searchPlaceholder,
1405
+ className: "flex h-9 w-full border-b border-[--color-border] bg-transparent px-3 text-sm outline-none placeholder:text-[--color-on-surface-muted]"
1406
+ }
1407
+ ),
1408
+ /* @__PURE__ */ jsxs7(Command.List, { className: "max-h-60 overflow-auto p-1", children: [
1409
+ /* @__PURE__ */ jsx21(Command.Empty, { className: "px-2 py-6 text-center text-sm text-[--color-on-surface-muted]", children: emptyMessage }),
1410
+ options.map((option) => /* @__PURE__ */ jsxs7(
1411
+ Command.Item,
1412
+ {
1413
+ value: option.label,
1414
+ disabled: option.disabled,
1415
+ onSelect: () => {
1416
+ onValueChange?.(
1417
+ option.value === value ? "" : option.value
1418
+ );
1419
+ setOpen(false);
1420
+ setSearch("");
1421
+ },
1422
+ className: cn(
1423
+ "relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
1424
+ "data-[selected=true]:bg-[--color-surface-muted]",
1425
+ "data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50"
1426
+ ),
1427
+ children: [
1428
+ /* @__PURE__ */ jsx21("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: option.value === value && /* @__PURE__ */ jsx21(
1429
+ "svg",
1430
+ {
1431
+ width: "14",
1432
+ height: "14",
1433
+ viewBox: "0 0 24 24",
1434
+ fill: "none",
1435
+ stroke: "currentColor",
1436
+ strokeWidth: "2",
1437
+ strokeLinecap: "round",
1438
+ strokeLinejoin: "round",
1439
+ children: /* @__PURE__ */ jsx21("polyline", { points: "20 6 9 17 4 12" })
1440
+ }
1441
+ ) }),
1442
+ option.label
1443
+ ]
1444
+ },
1445
+ option.value
1446
+ ))
1447
+ ] })
1448
+ ] })
1449
+ }
1450
+ ) })
1451
+ ] });
1452
+ }
1453
+ );
1454
+ Combobox.displayName = "Combobox";
1455
+
1456
+ // src/components/form-field/form-field.tsx
1457
+ import * as React23 from "react";
1458
+ import { jsx as jsx22 } from "react/jsx-runtime";
1459
+ var [FormFieldProvider, useFormField] = createContext2("FormField");
1460
+ var FormField = React23.forwardRef(
1461
+ ({ className, error, required, disabled, children, ...props }, ref) => {
1462
+ const id = React23.useId();
1463
+ const descriptionId = `${id}-description`;
1464
+ const messageId = `${id}-message`;
1465
+ return /* @__PURE__ */ jsx22(
1466
+ FormFieldProvider,
1467
+ {
1468
+ value: { id, error, required, disabled, descriptionId, messageId },
1469
+ children: /* @__PURE__ */ jsx22("div", { ref, className: cn("space-y-1.5", className), ...props, children })
1470
+ }
1471
+ );
1472
+ }
1473
+ );
1474
+ FormField.displayName = "FormField";
1475
+ var FormLabel = React23.forwardRef(
1476
+ ({ className, children, ...props }, ref) => {
1477
+ const { id, error, required } = useFormField();
1478
+ return /* @__PURE__ */ jsx22(
1479
+ Label,
1480
+ {
1481
+ ref,
1482
+ htmlFor: id,
1483
+ required,
1484
+ className: cn(error && "text-error-600", className),
1485
+ ...props,
1486
+ children
1487
+ }
1488
+ );
1489
+ }
1490
+ );
1491
+ FormLabel.displayName = "FormLabel";
1492
+ function FormControl({ children }) {
1493
+ const { id, error, disabled, descriptionId, messageId } = useFormField();
1494
+ const describedBy = [
1495
+ !error ? descriptionId : void 0,
1496
+ error ? messageId : void 0
1497
+ ].filter(Boolean).join(" ") || void 0;
1498
+ return React23.cloneElement(children, {
1499
+ id,
1500
+ "aria-invalid": error ? true : void 0,
1501
+ "aria-describedby": describedBy,
1502
+ disabled: children.props.disabled ?? disabled,
1503
+ required: children.props.required
1504
+ });
1505
+ }
1506
+ FormControl.displayName = "FormControl";
1507
+ var FormDescription = React23.forwardRef(({ className, ...props }, ref) => {
1508
+ const { descriptionId } = useFormField();
1509
+ return /* @__PURE__ */ jsx22(
1510
+ "p",
1511
+ {
1512
+ ref,
1513
+ id: descriptionId,
1514
+ className: cn("text-xs text-[--color-on-surface-muted]", className),
1515
+ ...props
1516
+ }
1517
+ );
1518
+ });
1519
+ FormDescription.displayName = "FormDescription";
1520
+ var FormMessage = React23.forwardRef(({ className, children, ...props }, ref) => {
1521
+ const { error, messageId } = useFormField();
1522
+ const message = error || children;
1523
+ if (!message) return null;
1524
+ return /* @__PURE__ */ jsx22(
1525
+ "p",
1526
+ {
1527
+ ref,
1528
+ id: messageId,
1529
+ role: "alert",
1530
+ className: cn("text-xs text-error-600", className),
1531
+ ...props,
1532
+ children: message
1533
+ }
1534
+ );
1535
+ });
1536
+ FormMessage.displayName = "FormMessage";
1537
+
1538
+ // src/components/dynamic-form-field/dynamic-form-field.tsx
1539
+ import * as React24 from "react";
1540
+ import { jsx as jsx23, jsxs as jsxs8 } from "react/jsx-runtime";
1541
+ function getFieldComponent(type) {
1542
+ const map = {
1543
+ text: "Input",
1544
+ email: "Input",
1545
+ url: "Input",
1546
+ tel: "Input",
1547
+ password: "Input",
1548
+ number: "NumberInput",
1549
+ textarea: "Textarea",
1550
+ select: "Select",
1551
+ combobox: "Combobox",
1552
+ checkbox: "Checkbox",
1553
+ radio: "RadioGroup",
1554
+ switch: "Switch",
1555
+ date: "DatePicker",
1556
+ datetime: "Input",
1557
+ time: "Input",
1558
+ file: "Input"
1559
+ };
1560
+ return map[type];
1561
+ }
1562
+ function isInlineField(type) {
1563
+ return type === "checkbox" || type === "switch";
1564
+ }
1565
+ var DynamicFormField = React24.forwardRef(
1566
+ ({
1567
+ type,
1568
+ name,
1569
+ label,
1570
+ description,
1571
+ error,
1572
+ required,
1573
+ disabled,
1574
+ placeholder,
1575
+ value,
1576
+ onChange,
1577
+ options = [],
1578
+ min,
1579
+ max,
1580
+ step,
1581
+ rows,
1582
+ className
1583
+ }, ref) => {
1584
+ if (isInlineField(type)) {
1585
+ return /* @__PURE__ */ jsxs8(FormField, { ref, error, disabled, className, children: [
1586
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
1587
+ /* @__PURE__ */ jsx23(FormControl, { children: type === "checkbox" ? /* @__PURE__ */ jsx23(
1588
+ Checkbox,
1589
+ {
1590
+ name,
1591
+ checked: value,
1592
+ onCheckedChange: (checked) => onChange?.(checked)
1593
+ }
1594
+ ) : /* @__PURE__ */ jsx23(
1595
+ Switch,
1596
+ {
1597
+ name,
1598
+ checked: value,
1599
+ onCheckedChange: (checked) => onChange?.(checked)
1600
+ }
1601
+ ) }),
1602
+ /* @__PURE__ */ jsxs8(Label, { className: "text-sm font-normal", children: [
1603
+ label,
1604
+ required && /* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "ml-0.5 text-error-500", children: "*" })
1605
+ ] })
1606
+ ] }),
1607
+ description && /* @__PURE__ */ jsx23(FormDescription, { children: description }),
1608
+ /* @__PURE__ */ jsx23(FormMessage, {})
1609
+ ] });
1610
+ }
1611
+ function renderControl() {
1612
+ switch (type) {
1613
+ case "textarea":
1614
+ return /* @__PURE__ */ jsx23(
1615
+ Textarea,
1616
+ {
1617
+ name,
1618
+ placeholder,
1619
+ value,
1620
+ onChange: (e) => onChange?.(e.target.value),
1621
+ rows
1622
+ }
1623
+ );
1624
+ case "number":
1625
+ return /* @__PURE__ */ jsx23(
1626
+ NumberInput,
1627
+ {
1628
+ name,
1629
+ placeholder,
1630
+ value,
1631
+ onChange: (v) => onChange?.(v),
1632
+ min,
1633
+ max,
1634
+ step
1635
+ }
1636
+ );
1637
+ case "date":
1638
+ return /* @__PURE__ */ jsx23(
1639
+ DatePicker,
1640
+ {
1641
+ name,
1642
+ value,
1643
+ onChange: (e) => onChange?.(e.target.value),
1644
+ min,
1645
+ max
1646
+ }
1647
+ );
1648
+ case "select":
1649
+ return /* @__PURE__ */ jsxs8(
1650
+ Select,
1651
+ {
1652
+ value,
1653
+ onValueChange: (v) => onChange?.(v),
1654
+ disabled,
1655
+ name,
1656
+ children: [
1657
+ /* @__PURE__ */ jsx23(SelectTrigger, { children: /* @__PURE__ */ jsx23(SelectValue, { placeholder }) }),
1658
+ /* @__PURE__ */ jsx23(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsx23(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
1659
+ ]
1660
+ }
1661
+ );
1662
+ case "combobox":
1663
+ return /* @__PURE__ */ jsx23(
1664
+ Combobox,
1665
+ {
1666
+ name,
1667
+ options,
1668
+ value,
1669
+ onValueChange: (v) => onChange?.(v),
1670
+ placeholder
1671
+ }
1672
+ );
1673
+ case "radio":
1674
+ return /* @__PURE__ */ jsx23(
1675
+ RadioGroup,
1676
+ {
1677
+ value,
1678
+ onValueChange: (v) => onChange?.(v),
1679
+ children: options.map((opt) => /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
1680
+ /* @__PURE__ */ jsx23(RadioGroupItem, { value: opt.value, id: `${name}-${opt.value}` }),
1681
+ /* @__PURE__ */ jsx23(Label, { htmlFor: `${name}-${opt.value}`, className: "font-normal", children: opt.label })
1682
+ ] }, opt.value))
1683
+ }
1684
+ );
1685
+ default:
1686
+ return /* @__PURE__ */ jsx23(
1687
+ Input,
1688
+ {
1689
+ type: type === "datetime" ? "datetime-local" : type,
1690
+ name,
1691
+ placeholder,
1692
+ value,
1693
+ onChange: (e) => onChange?.(e.target.value)
1694
+ }
1695
+ );
1696
+ }
1697
+ }
1698
+ return /* @__PURE__ */ jsxs8(FormField, { ref, error, required, disabled, className, children: [
1699
+ /* @__PURE__ */ jsx23(FormLabel, { children: label }),
1700
+ /* @__PURE__ */ jsx23(FormControl, { children: renderControl() }),
1701
+ description && /* @__PURE__ */ jsx23(FormDescription, { children: description }),
1702
+ /* @__PURE__ */ jsx23(FormMessage, {})
1703
+ ] });
1704
+ }
1705
+ );
1706
+ DynamicFormField.displayName = "DynamicFormField";
1707
+
1708
+ // src/components/form-layout/form-layout.tsx
1709
+ import * as React25 from "react";
1710
+ import { cva as cva10 } from "class-variance-authority";
1711
+ import { jsx as jsx24, jsxs as jsxs9 } from "react/jsx-runtime";
1712
+ var formLayoutVariants = cva10("", {
1713
+ variants: {
1714
+ layout: {
1715
+ vertical: "flex flex-col",
1716
+ horizontal: "grid grid-cols-[auto_1fr] items-start",
1717
+ grid: "grid"
1718
+ },
1719
+ size: {
1720
+ sm: "gap-3",
1721
+ md: "gap-4",
1722
+ lg: "gap-6"
1723
+ }
1724
+ },
1725
+ compoundVariants: [
1726
+ {
1727
+ layout: "horizontal",
1728
+ size: "sm",
1729
+ className: "gap-x-4 gap-y-3"
1730
+ },
1731
+ {
1732
+ layout: "horizontal",
1733
+ size: "md",
1734
+ className: "gap-x-6 gap-y-4"
1735
+ },
1736
+ {
1737
+ layout: "horizontal",
1738
+ size: "lg",
1739
+ className: "gap-x-8 gap-y-6"
1740
+ }
1741
+ ],
1742
+ defaultVariants: {
1743
+ layout: "vertical",
1744
+ size: "md"
1745
+ }
1746
+ });
1747
+ var FormLayout = React25.forwardRef(
1748
+ ({ className, layout, size, columns = 2, style, ...props }, ref) => /* @__PURE__ */ jsx24(
1749
+ "div",
1750
+ {
1751
+ ref,
1752
+ className: cn(formLayoutVariants({ layout, size }), className),
1753
+ style: layout === "grid" ? { gridTemplateColumns: `repeat(${columns}, 1fr)`, ...style } : style,
1754
+ ...props
1755
+ }
1756
+ )
1757
+ );
1758
+ FormLayout.displayName = "FormLayout";
1759
+ var FormSection = React25.forwardRef(({ className, title, description, children, ...props }, ref) => /* @__PURE__ */ jsxs9(
1760
+ "fieldset",
1761
+ {
1762
+ ref,
1763
+ className: cn("space-y-4 border-0 p-0", className),
1764
+ ...props,
1765
+ children: [
1766
+ /* @__PURE__ */ jsx24("legend", { className: "text-sm font-semibold text-[--color-on-surface]", children: title }),
1767
+ description && /* @__PURE__ */ jsx24("p", { className: "-mt-2 text-xs text-[--color-on-surface-muted]", children: description }),
1768
+ children
1769
+ ]
1770
+ }
1771
+ ));
1772
+ FormSection.displayName = "FormSection";
1773
+ var alignClasses = {
1774
+ left: "justify-start",
1775
+ right: "justify-end",
1776
+ center: "justify-center",
1777
+ between: "justify-between"
1778
+ };
1779
+ var FormActions = React25.forwardRef(
1780
+ ({ className, align = "right", ...props }, ref) => /* @__PURE__ */ jsx24(
1781
+ "div",
1782
+ {
1783
+ ref,
1784
+ className: cn(
1785
+ "flex items-center gap-3 pt-4 border-t border-[--color-border]",
1786
+ alignClasses[align],
1787
+ className
1788
+ ),
1789
+ ...props
1790
+ }
1791
+ )
1792
+ );
1793
+ FormActions.displayName = "FormActions";
1794
+
1795
+ // src/components/tabs/tabs.tsx
1796
+ import * as React26 from "react";
1797
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
1798
+ import { cva as cva11 } from "class-variance-authority";
1799
+ import { jsx as jsx25 } from "react/jsx-runtime";
1800
+ var [TabsVariantProvider, useTabsVariant] = createContext2("TabsVariant");
1801
+ var Tabs = TabsPrimitive.Root;
1802
+ var tabsListVariants = cva11(
1803
+ "inline-flex items-center justify-center",
1804
+ {
1805
+ variants: {
1806
+ variant: {
1807
+ default: "rounded-lg bg-[--color-surface-muted] p-1",
1808
+ underline: "border-b border-[--color-border] bg-transparent"
1809
+ }
1810
+ },
1811
+ defaultVariants: { variant: "default" }
1812
+ }
1813
+ );
1814
+ var TabsList = React26.forwardRef(({ className, variant = "default", ...props }, ref) => /* @__PURE__ */ jsx25(TabsVariantProvider, { value: { variant }, children: /* @__PURE__ */ jsx25(
1815
+ TabsPrimitive.List,
1816
+ {
1817
+ ref,
1818
+ className: cn(tabsListVariants({ variant }), className),
1819
+ ...props
1820
+ }
1821
+ ) }));
1822
+ TabsList.displayName = "TabsList";
1823
+ var tabsTriggerBase = "inline-flex items-center justify-center whitespace-nowrap px-3 py-1.5 text-sm font-medium transition-all duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 touch:min-h-[--touch-target-min]";
1824
+ var tabsTriggerVariantStyles = {
1825
+ default: "rounded-md data-[state=active]:bg-[--color-surface-raised] data-[state=active]:shadow-sm data-[state=active]:text-[--color-on-surface] text-[--color-on-surface-secondary]",
1826
+ underline: "border-b-2 border-transparent rounded-none data-[state=active]:border-primary-500 data-[state=active]:text-[--color-on-surface] text-[--color-on-surface-secondary]"
1827
+ };
1828
+ var TabsTrigger = React26.forwardRef(({ className, ...props }, ref) => {
1829
+ const { variant } = useTabsVariant();
1830
+ return /* @__PURE__ */ jsx25(
1831
+ TabsPrimitive.Trigger,
1832
+ {
1833
+ ref,
1834
+ className: cn(
1835
+ tabsTriggerBase,
1836
+ tabsTriggerVariantStyles[variant],
1837
+ className
1838
+ ),
1839
+ ...props
1840
+ }
1841
+ );
1842
+ });
1843
+ TabsTrigger.displayName = "TabsTrigger";
1844
+ var TabsContent = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx25(
1845
+ TabsPrimitive.Content,
1846
+ {
1847
+ ref,
1848
+ className: cn(
1849
+ "mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2",
1850
+ className
1851
+ ),
1852
+ ...props
1853
+ }
1854
+ ));
1855
+ TabsContent.displayName = "TabsContent";
1856
+
1857
+ // src/components/empty-state/empty-state.tsx
1858
+ import * as React27 from "react";
1859
+ import { cva as cva12 } from "class-variance-authority";
1860
+ import { jsx as jsx26 } from "react/jsx-runtime";
1861
+ var emptyStateVariants = cva12(
1862
+ "flex flex-col items-center justify-center text-center",
1863
+ {
1864
+ variants: {
1865
+ size: {
1866
+ sm: "py-8 gap-2",
1867
+ md: "py-12 gap-3",
1868
+ lg: "py-20 gap-4"
1869
+ }
1870
+ },
1871
+ defaultVariants: { size: "md" }
1872
+ }
1873
+ );
1874
+ var EmptyState = React27.forwardRef(
1875
+ ({ className, size, ...props }, ref) => /* @__PURE__ */ jsx26(
1876
+ "div",
1877
+ {
1878
+ ref,
1879
+ className: cn(emptyStateVariants({ size }), className),
1880
+ ...props
1881
+ }
1882
+ )
1883
+ );
1884
+ EmptyState.displayName = "EmptyState";
1885
+ var EmptyStateIcon = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
1886
+ "div",
1887
+ {
1888
+ ref,
1889
+ className: cn("text-[--color-on-surface-muted] [&>svg]:h-10 [&>svg]:w-10", className),
1890
+ ...props
1891
+ }
1892
+ ));
1893
+ EmptyStateIcon.displayName = "EmptyStateIcon";
1894
+ var EmptyStateTitle = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
1895
+ "h3",
1896
+ {
1897
+ ref,
1898
+ className: cn("text-base font-semibold text-[--color-on-surface]", className),
1899
+ ...props
1900
+ }
1901
+ ));
1902
+ EmptyStateTitle.displayName = "EmptyStateTitle";
1903
+ var EmptyStateDescription = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
1904
+ "p",
1905
+ {
1906
+ ref,
1907
+ className: cn("text-sm text-[--color-on-surface-muted] max-w-sm", className),
1908
+ ...props
1909
+ }
1910
+ ));
1911
+ EmptyStateDescription.displayName = "EmptyStateDescription";
1912
+ var EmptyStateActions = React27.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
1913
+ "div",
1914
+ {
1915
+ ref,
1916
+ className: cn("flex items-center gap-2 mt-2", className),
1917
+ ...props
1918
+ }
1919
+ ));
1920
+ EmptyStateActions.displayName = "EmptyStateActions";
1921
+
1922
+ // src/components/table/table.tsx
1923
+ import * as React28 from "react";
1924
+ import { jsx as jsx27 } from "react/jsx-runtime";
1925
+ var Table = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx27(
1926
+ "table",
1927
+ {
1928
+ ref,
1929
+ className: cn("w-full caption-bottom text-sm", className),
1930
+ ...props
1931
+ }
1932
+ ) }));
1933
+ Table.displayName = "Table";
1934
+ var TableHeader = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
1935
+ TableHeader.displayName = "TableHeader";
1936
+ var TableBody = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
1937
+ "tbody",
1938
+ {
1939
+ ref,
1940
+ className: cn("[&_tr:last-child]:border-0", className),
1941
+ ...props
1942
+ }
1943
+ ));
1944
+ TableBody.displayName = "TableBody";
1945
+ var TableFooter = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
1946
+ "tfoot",
1947
+ {
1948
+ ref,
1949
+ className: cn(
1950
+ "border-t bg-[--color-surface-sunken] font-medium [&>tr]:last:border-b-0",
1951
+ className
1952
+ ),
1953
+ ...props
1954
+ }
1955
+ ));
1956
+ TableFooter.displayName = "TableFooter";
1957
+ var TableRow = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
1958
+ "tr",
1959
+ {
1960
+ ref,
1961
+ className: cn(
1962
+ "border-b border-[--color-border] transition-colors hover:bg-[--color-surface-sunken] data-[state=selected]:bg-primary-50 dark:data-[state=selected]:bg-primary-950",
1963
+ className
1964
+ ),
1965
+ ...props
1966
+ }
1967
+ ));
1968
+ TableRow.displayName = "TableRow";
1969
+ var TableHead = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
1970
+ "th",
1971
+ {
1972
+ ref,
1973
+ className: cn(
1974
+ "h-10 px-3 text-left align-middle text-xs font-medium text-[--color-on-surface-muted] uppercase tracking-wider [&:has([role=checkbox])]:pr-0",
1975
+ className
1976
+ ),
1977
+ ...props
1978
+ }
1979
+ ));
1980
+ TableHead.displayName = "TableHead";
1981
+ var TableCell = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
1982
+ "td",
1983
+ {
1984
+ ref,
1985
+ className: cn(
1986
+ "px-3 py-2.5 align-middle text-sm [&:has([role=checkbox])]:pr-0",
1987
+ className
1988
+ ),
1989
+ ...props
1990
+ }
1991
+ ));
1992
+ TableCell.displayName = "TableCell";
1993
+ var TableCaption = React28.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
1994
+ "caption",
1995
+ {
1996
+ ref,
1997
+ className: cn("mt-4 text-sm text-[--color-on-surface-muted]", className),
1998
+ ...props
1999
+ }
2000
+ ));
2001
+ TableCaption.displayName = "TableCaption";
2002
+
2003
+ // src/components/data-table/data-table.tsx
2004
+ import * as React30 from "react";
2005
+ import {
2006
+ useReactTable,
2007
+ getCoreRowModel,
2008
+ getSortedRowModel,
2009
+ getPaginationRowModel,
2010
+ flexRender
2011
+ } from "@tanstack/react-table";
2012
+
2013
+ // src/components/data-table/data-table-pagination.tsx
2014
+ import { jsx as jsx28, jsxs as jsxs10 } from "react/jsx-runtime";
2015
+ function DataTablePagination({
2016
+ table,
2017
+ pageSizeOptions = [10, 20, 30, 50],
2018
+ className
2019
+ }) {
2020
+ const { pageIndex, pageSize } = table.getState().pagination;
2021
+ const totalRows = table.getFilteredRowModel().rows.length;
2022
+ const from = pageIndex * pageSize + 1;
2023
+ const to = Math.min((pageIndex + 1) * pageSize, totalRows);
2024
+ return /* @__PURE__ */ jsxs10(
2025
+ "div",
2026
+ {
2027
+ className: cn(
2028
+ "flex items-center justify-between px-3 py-3 text-sm text-[--color-on-surface-secondary]",
2029
+ className
2030
+ ),
2031
+ children: [
2032
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
2033
+ /* @__PURE__ */ jsx28("span", { children: "Rows per page" }),
2034
+ /* @__PURE__ */ jsx28(
2035
+ "select",
2036
+ {
2037
+ value: pageSize,
2038
+ onChange: (e) => table.setPageSize(Number(e.target.value)),
2039
+ className: "h-8 rounded-md border border-[--color-border-input] bg-[--color-surface-raised] px-2 text-sm",
2040
+ "aria-label": "Rows per page",
2041
+ children: pageSizeOptions.map((size) => /* @__PURE__ */ jsx28("option", { value: size, children: size }, size))
2042
+ }
2043
+ )
2044
+ ] }),
2045
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-4", children: [
2046
+ /* @__PURE__ */ jsx28("span", { children: totalRows > 0 ? `${from}-${to} of ${totalRows}` : "0 results" }),
2047
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1", children: [
2048
+ /* @__PURE__ */ jsx28(
2049
+ "button",
2050
+ {
2051
+ className: "inline-flex h-8 w-8 items-center justify-center rounded-md border border-[--color-border-input] bg-[--color-surface-raised] transition-colors hover:bg-[--color-surface-sunken] disabled:opacity-50 disabled:pointer-events-none",
2052
+ onClick: () => table.previousPage(),
2053
+ disabled: !table.getCanPreviousPage(),
2054
+ "aria-label": "Previous page",
2055
+ children: /* @__PURE__ */ jsx28(
2056
+ "svg",
2057
+ {
2058
+ width: "16",
2059
+ height: "16",
2060
+ viewBox: "0 0 24 24",
2061
+ fill: "none",
2062
+ stroke: "currentColor",
2063
+ strokeWidth: "2",
2064
+ strokeLinecap: "round",
2065
+ strokeLinejoin: "round",
2066
+ children: /* @__PURE__ */ jsx28("path", { d: "m15 18-6-6 6-6" })
2067
+ }
2068
+ )
2069
+ }
2070
+ ),
2071
+ /* @__PURE__ */ jsx28(
2072
+ "button",
2073
+ {
2074
+ className: "inline-flex h-8 w-8 items-center justify-center rounded-md border border-[--color-border-input] bg-[--color-surface-raised] transition-colors hover:bg-[--color-surface-sunken] disabled:opacity-50 disabled:pointer-events-none",
2075
+ onClick: () => table.nextPage(),
2076
+ disabled: !table.getCanNextPage(),
2077
+ "aria-label": "Next page",
2078
+ children: /* @__PURE__ */ jsx28(
2079
+ "svg",
2080
+ {
2081
+ width: "16",
2082
+ height: "16",
2083
+ viewBox: "0 0 24 24",
2084
+ fill: "none",
2085
+ stroke: "currentColor",
2086
+ strokeWidth: "2",
2087
+ strokeLinecap: "round",
2088
+ strokeLinejoin: "round",
2089
+ children: /* @__PURE__ */ jsx28("path", { d: "m9 18 6-6-6-6" })
2090
+ }
2091
+ )
2092
+ }
2093
+ )
2094
+ ] })
2095
+ ] })
2096
+ ]
2097
+ }
2098
+ );
2099
+ }
2100
+ DataTablePagination.displayName = "DataTablePagination";
2101
+
2102
+ // src/components/data-table/data-table-toolbar.tsx
2103
+ import * as React29 from "react";
2104
+ import { jsx as jsx29, jsxs as jsxs11 } from "react/jsx-runtime";
2105
+ function DataTableToolbar({
2106
+ table,
2107
+ enableColumnVisibility = false,
2108
+ className,
2109
+ children
2110
+ }) {
2111
+ const [showColumnMenu, setShowColumnMenu] = React29.useState(false);
2112
+ const menuRef = React29.useRef(null);
2113
+ const selectedCount = table.getFilteredSelectedRowModel().rows.length;
2114
+ React29.useEffect(() => {
2115
+ function handleClickOutside(event) {
2116
+ if (menuRef.current && !menuRef.current.contains(event.target)) {
2117
+ setShowColumnMenu(false);
2118
+ }
2119
+ }
2120
+ if (showColumnMenu) {
2121
+ document.addEventListener("mousedown", handleClickOutside);
2122
+ return () => document.removeEventListener("mousedown", handleClickOutside);
2123
+ }
2124
+ }, [showColumnMenu]);
2125
+ return /* @__PURE__ */ jsxs11(
2126
+ "div",
2127
+ {
2128
+ className: cn(
2129
+ "flex items-center justify-between px-3 py-2",
2130
+ className
2131
+ ),
2132
+ children: [
2133
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
2134
+ selectedCount > 0 && /* @__PURE__ */ jsxs11("span", { className: "text-sm text-[--color-on-surface-secondary]", children: [
2135
+ selectedCount,
2136
+ " selected"
2137
+ ] }),
2138
+ children
2139
+ ] }),
2140
+ enableColumnVisibility && /* @__PURE__ */ jsxs11("div", { className: "relative", ref: menuRef, children: [
2141
+ /* @__PURE__ */ jsxs11(
2142
+ "button",
2143
+ {
2144
+ className: "inline-flex items-center gap-1 rounded-md border border-[--color-border-input] bg-[--color-surface-raised] px-3 py-1.5 text-sm transition-colors hover:bg-[--color-surface-sunken]",
2145
+ onClick: () => setShowColumnMenu(!showColumnMenu),
2146
+ "aria-label": "Toggle columns",
2147
+ "aria-expanded": showColumnMenu,
2148
+ children: [
2149
+ /* @__PURE__ */ jsx29(
2150
+ "svg",
2151
+ {
2152
+ width: "14",
2153
+ height: "14",
2154
+ viewBox: "0 0 24 24",
2155
+ fill: "none",
2156
+ stroke: "currentColor",
2157
+ strokeWidth: "2",
2158
+ strokeLinecap: "round",
2159
+ strokeLinejoin: "round",
2160
+ children: /* @__PURE__ */ jsx29("path", { d: "M12 3v18M3 12h18" })
2161
+ }
2162
+ ),
2163
+ "Columns"
2164
+ ]
2165
+ }
2166
+ ),
2167
+ showColumnMenu && /* @__PURE__ */ jsx29("div", { className: "absolute right-0 top-full z-popover mt-1 min-w-[10rem] rounded-md border border-[--color-border] bg-[--color-surface-raised] p-2 shadow-md", children: table.getAllColumns().filter((col) => col.getCanHide()).map((col) => /* @__PURE__ */ jsxs11(
2168
+ "label",
2169
+ {
2170
+ className: "flex items-center gap-2 rounded px-2 py-1 text-sm hover:bg-[--color-surface-sunken] cursor-pointer capitalize",
2171
+ children: [
2172
+ /* @__PURE__ */ jsx29(
2173
+ "input",
2174
+ {
2175
+ type: "checkbox",
2176
+ checked: col.getIsVisible(),
2177
+ onChange: (e) => col.toggleVisibility(e.target.checked),
2178
+ className: "h-4 w-4"
2179
+ }
2180
+ ),
2181
+ col.id
2182
+ ]
2183
+ },
2184
+ col.id
2185
+ )) })
2186
+ ] })
2187
+ ]
2188
+ }
2189
+ );
2190
+ }
2191
+ DataTableToolbar.displayName = "DataTableToolbar";
2192
+
2193
+ // src/components/data-table/data-table.tsx
2194
+ import { jsx as jsx30, jsxs as jsxs12 } from "react/jsx-runtime";
2195
+ function DataTable({
2196
+ columns,
2197
+ data,
2198
+ enableSorting = false,
2199
+ enableRowSelection = false,
2200
+ enableColumnVisibility = false,
2201
+ enablePagination = false,
2202
+ pageSize = 10,
2203
+ pageSizeOptions,
2204
+ onRowSelectionChange,
2205
+ emptyState,
2206
+ className,
2207
+ "aria-label": ariaLabel
2208
+ }) {
2209
+ const [sorting, setSorting] = React30.useState([]);
2210
+ const [rowSelection, setRowSelection] = React30.useState({});
2211
+ const [columnVisibility, setColumnVisibility] = React30.useState({});
2212
+ const allColumns = React30.useMemo(() => {
2213
+ if (!enableRowSelection) return columns;
2214
+ const selectColumn = {
2215
+ id: "select",
2216
+ header: ({ table: table2 }) => /* @__PURE__ */ jsx30(
2217
+ Checkbox,
2218
+ {
2219
+ checked: table2.getIsAllPageRowsSelected() ? true : table2.getIsSomePageRowsSelected() ? "indeterminate" : false,
2220
+ onCheckedChange: (value) => table2.toggleAllPageRowsSelected(!!value),
2221
+ "aria-label": "Select all"
2222
+ }
2223
+ ),
2224
+ cell: ({ row }) => /* @__PURE__ */ jsx30(
2225
+ Checkbox,
2226
+ {
2227
+ checked: row.getIsSelected(),
2228
+ onCheckedChange: (value) => row.toggleSelected(!!value),
2229
+ "aria-label": "Select row"
2230
+ }
2231
+ ),
2232
+ enableSorting: false,
2233
+ enableHiding: false
2234
+ };
2235
+ return [selectColumn, ...columns];
2236
+ }, [columns, enableRowSelection]);
2237
+ const table = useReactTable({
2238
+ data,
2239
+ columns: allColumns,
2240
+ state: { sorting, rowSelection, columnVisibility },
2241
+ onSortingChange: setSorting,
2242
+ onRowSelectionChange: setRowSelection,
2243
+ onColumnVisibilityChange: setColumnVisibility,
2244
+ getCoreRowModel: getCoreRowModel(),
2245
+ ...enableSorting && { getSortedRowModel: getSortedRowModel() },
2246
+ ...enablePagination && {
2247
+ getPaginationRowModel: getPaginationRowModel()
2248
+ },
2249
+ enableRowSelection,
2250
+ initialState: { pagination: { pageSize } }
2251
+ });
2252
+ React30.useEffect(() => {
2253
+ if (onRowSelectionChange) {
2254
+ const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
2255
+ onRowSelectionChange(selectedRows);
2256
+ }
2257
+ }, [rowSelection, table, onRowSelectionChange]);
2258
+ const showToolbar = enableRowSelection || enableColumnVisibility;
2259
+ return /* @__PURE__ */ jsxs12("div", { className: cn("rounded-md border border-[--color-border]", className), children: [
2260
+ showToolbar && /* @__PURE__ */ jsx30(
2261
+ DataTableToolbar,
2262
+ {
2263
+ table,
2264
+ enableColumnVisibility
2265
+ }
2266
+ ),
2267
+ /* @__PURE__ */ jsxs12(Table, { "aria-label": ariaLabel, children: [
2268
+ /* @__PURE__ */ jsx30(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx30(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx30(TableHead, { children: header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ jsxs12(
2269
+ "button",
2270
+ {
2271
+ className: "flex items-center gap-1 -ml-2 px-2 py-1 rounded-md hover:bg-[--color-surface-muted] transition-colors duration-fast",
2272
+ onClick: header.column.getToggleSortingHandler(),
2273
+ "aria-label": `Sort by ${typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : header.column.id}`,
2274
+ children: [
2275
+ flexRender(
2276
+ header.column.columnDef.header,
2277
+ header.getContext()
2278
+ ),
2279
+ /* @__PURE__ */ jsx30(
2280
+ "svg",
2281
+ {
2282
+ width: "14",
2283
+ height: "14",
2284
+ viewBox: "0 0 24 24",
2285
+ fill: "none",
2286
+ stroke: "currentColor",
2287
+ strokeWidth: "2",
2288
+ strokeLinecap: "round",
2289
+ strokeLinejoin: "round",
2290
+ className: cn(
2291
+ "shrink-0",
2292
+ header.column.getIsSorted() ? "opacity-100" : "opacity-30"
2293
+ ),
2294
+ children: /* @__PURE__ */ jsx30("path", { d: "m7 15 5 5 5-5M7 9l5-5 5 5" })
2295
+ }
2296
+ )
2297
+ ]
2298
+ }
2299
+ ) : flexRender(
2300
+ header.column.columnDef.header,
2301
+ header.getContext()
2302
+ ) }, header.id)) }, headerGroup.id)) }),
2303
+ /* @__PURE__ */ jsx30(TableBody, { children: table.getRowModel().rows.length > 0 ? table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx30(
2304
+ TableRow,
2305
+ {
2306
+ "data-state": row.getIsSelected() ? "selected" : void 0,
2307
+ children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx30(TableCell, { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
2308
+ },
2309
+ row.id
2310
+ )) : /* @__PURE__ */ jsx30(TableRow, { children: /* @__PURE__ */ jsx30(
2311
+ TableCell,
2312
+ {
2313
+ colSpan: allColumns.length,
2314
+ className: "h-24 text-center",
2315
+ children: emptyState ?? "No results."
2316
+ }
2317
+ ) }) })
2318
+ ] }),
2319
+ enablePagination && /* @__PURE__ */ jsx30(
2320
+ DataTablePagination,
2321
+ {
2322
+ table,
2323
+ pageSizeOptions
2324
+ }
2325
+ )
2326
+ ] });
2327
+ }
2328
+ DataTable.displayName = "DataTable";
2329
+
2330
+ // src/components/data-table/data-table-column-header.tsx
2331
+ import { jsx as jsx31, jsxs as jsxs13 } from "react/jsx-runtime";
2332
+ function DataTableColumnHeader({
2333
+ column,
2334
+ title,
2335
+ className
2336
+ }) {
2337
+ if (!column.getCanSort()) {
2338
+ return /* @__PURE__ */ jsx31("div", { className: cn(className), children: title });
2339
+ }
2340
+ const sorted = column.getIsSorted();
2341
+ return /* @__PURE__ */ jsxs13(
2342
+ "button",
2343
+ {
2344
+ className: cn(
2345
+ "flex items-center gap-1 -ml-2 px-2 py-1 rounded-md hover:bg-[--color-surface-muted] transition-colors duration-fast",
2346
+ className
2347
+ ),
2348
+ onClick: () => column.toggleSorting(sorted === "asc"),
2349
+ "aria-label": `Sort by ${title}`,
2350
+ children: [
2351
+ title,
2352
+ /* @__PURE__ */ jsx31(
2353
+ "svg",
2354
+ {
2355
+ width: "14",
2356
+ height: "14",
2357
+ viewBox: "0 0 24 24",
2358
+ fill: "none",
2359
+ stroke: "currentColor",
2360
+ strokeWidth: "2",
2361
+ strokeLinecap: "round",
2362
+ strokeLinejoin: "round",
2363
+ className: cn(
2364
+ "shrink-0 transition-opacity",
2365
+ sorted ? "opacity-100" : "opacity-30"
2366
+ ),
2367
+ children: sorted === "desc" ? /* @__PURE__ */ jsx31("path", { d: "m7 15 5 5 5-5M7 9l5-5 5 5" }) : sorted === "asc" ? /* @__PURE__ */ jsx31("path", { d: "m7 15 5 5 5-5M7 9l5-5 5 5" }) : /* @__PURE__ */ jsx31("path", { d: "m7 15 5 5 5-5M7 9l5-5 5 5" })
2368
+ }
2369
+ ),
2370
+ sorted === "asc" && /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "sorted ascending" }),
2371
+ sorted === "desc" && /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "sorted descending" })
2372
+ ]
2373
+ }
2374
+ );
2375
+ }
2376
+ DataTableColumnHeader.displayName = "DataTableColumnHeader";
2377
+
2378
+ // src/components/filter-bar/filter-bar.tsx
2379
+ import * as React31 from "react";
2380
+ import { cva as cva13 } from "class-variance-authority";
2381
+ import { jsx as jsx32, jsxs as jsxs14 } from "react/jsx-runtime";
2382
+ var FilterBar = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
2383
+ "div",
2384
+ {
2385
+ ref,
2386
+ className: cn(
2387
+ "flex flex-wrap items-center gap-2 rounded-lg border border-[--color-border] bg-[--color-surface-raised] p-3",
2388
+ className
2389
+ ),
2390
+ role: "toolbar",
2391
+ "aria-label": "Filters",
2392
+ ...props
2393
+ }
2394
+ ));
2395
+ FilterBar.displayName = "FilterBar";
2396
+ var FilterBarGroup = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
2397
+ "div",
2398
+ {
2399
+ ref,
2400
+ className: cn("flex items-center gap-2", className),
2401
+ role: "group",
2402
+ ...props
2403
+ }
2404
+ ));
2405
+ FilterBarGroup.displayName = "FilterBarGroup";
2406
+ var filterChipVariants = cva13(
2407
+ "inline-flex items-center gap-1 rounded-full px-3 py-1 text-sm font-medium transition-colors duration-fast",
2408
+ {
2409
+ variants: {
2410
+ variant: {
2411
+ default: "bg-primary-50 text-primary-700",
2412
+ outline: "border border-[--color-border-input] text-[--color-on-surface-secondary]"
2413
+ }
2414
+ },
2415
+ defaultVariants: { variant: "default" }
2416
+ }
2417
+ );
2418
+ var FilterChip = React31.forwardRef(
2419
+ ({ className, variant, label, value, onRemove, ...props }, ref) => /* @__PURE__ */ jsxs14(
2420
+ "span",
2421
+ {
2422
+ ref,
2423
+ className: cn(filterChipVariants({ variant }), className),
2424
+ ...props,
2425
+ children: [
2426
+ /* @__PURE__ */ jsxs14("span", { className: "text-xs opacity-70", children: [
2427
+ label,
2428
+ ":"
2429
+ ] }),
2430
+ /* @__PURE__ */ jsx32("span", { children: value }),
2431
+ onRemove && /* @__PURE__ */ jsx32(
2432
+ "button",
2433
+ {
2434
+ type: "button",
2435
+ onClick: onRemove,
2436
+ className: "ml-0.5 rounded-full p-0.5 hover:bg-black/10 transition-colors",
2437
+ "aria-label": `Remove ${label} filter`,
2438
+ children: /* @__PURE__ */ jsx32(
2439
+ "svg",
2440
+ {
2441
+ width: "12",
2442
+ height: "12",
2443
+ viewBox: "0 0 24 24",
2444
+ fill: "none",
2445
+ stroke: "currentColor",
2446
+ strokeWidth: "2",
2447
+ strokeLinecap: "round",
2448
+ strokeLinejoin: "round",
2449
+ children: /* @__PURE__ */ jsx32("path", { d: "M18 6 6 18M6 6l12 12" })
2450
+ }
2451
+ )
2452
+ }
2453
+ )
2454
+ ]
2455
+ }
2456
+ )
2457
+ );
2458
+ FilterChip.displayName = "FilterChip";
2459
+ var ActiveFilters = React31.forwardRef(({ className, onClearAll, clearAllLabel = "Clear all", children, ...props }, ref) => /* @__PURE__ */ jsxs14(
2460
+ "div",
2461
+ {
2462
+ ref,
2463
+ className: cn("flex flex-wrap items-center gap-2", className),
2464
+ ...props,
2465
+ children: [
2466
+ children,
2467
+ onClearAll && /* @__PURE__ */ jsx32(
2468
+ "button",
2469
+ {
2470
+ type: "button",
2471
+ onClick: onClearAll,
2472
+ className: "text-sm text-[--color-on-surface-muted] hover:text-[--color-on-surface-secondary] underline transition-colors",
2473
+ children: clearAllLabel
2474
+ }
2475
+ )
2476
+ ]
2477
+ }
2478
+ ));
2479
+ ActiveFilters.displayName = "ActiveFilters";
2480
+ var FilterBarActions = React31.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx32(
2481
+ "div",
2482
+ {
2483
+ ref,
2484
+ className: cn("ml-auto flex items-center gap-2", className),
2485
+ ...props
2486
+ }
2487
+ ));
2488
+ FilterBarActions.displayName = "FilterBarActions";
2489
+
2490
+ // src/components/popover/popover.tsx
2491
+ import * as React32 from "react";
2492
+ import * as PopoverPrimitive2 from "@radix-ui/react-popover";
2493
+ import { jsx as jsx33 } from "react/jsx-runtime";
2494
+ var Popover = PopoverPrimitive2.Root;
2495
+ var PopoverTrigger = PopoverPrimitive2.Trigger;
2496
+ var PopoverAnchor = PopoverPrimitive2.Anchor;
2497
+ var PopoverContent = React32.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx33(PopoverPrimitive2.Portal, { children: /* @__PURE__ */ jsx33(
2498
+ PopoverPrimitive2.Content,
2499
+ {
2500
+ ref,
2501
+ align,
2502
+ sideOffset,
2503
+ className: cn(
2504
+ "z-popover w-72 rounded-md border border-[--color-border] bg-[--color-surface-raised] p-4 shadow-md outline-none",
2505
+ "animate-in fade-in-0 zoom-in-95",
2506
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
2507
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
2508
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
2509
+ className
2510
+ ),
2511
+ ...props
2512
+ }
2513
+ ) }));
2514
+ PopoverContent.displayName = "PopoverContent";
2515
+
2516
+ // src/components/dropdown-menu/dropdown-menu.tsx
2517
+ import * as React33 from "react";
2518
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
2519
+ import { jsx as jsx34, jsxs as jsxs15 } from "react/jsx-runtime";
2520
+ var DropdownMenu = DropdownMenuPrimitive.Root;
2521
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
2522
+ var DropdownMenuGroup = DropdownMenuPrimitive.Group;
2523
+ var DropdownMenuPortal = DropdownMenuPrimitive.Portal;
2524
+ var DropdownMenuSub = DropdownMenuPrimitive.Sub;
2525
+ var DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
2526
+ var DropdownMenuContent = React33.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx34(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx34(
2527
+ DropdownMenuPrimitive.Content,
2528
+ {
2529
+ ref,
2530
+ sideOffset,
2531
+ className: cn(
2532
+ "z-dropdown min-w-[8rem] overflow-hidden rounded-md border border-[--color-border] bg-[--color-surface-raised] p-1 shadow-md",
2533
+ "animate-in fade-in-0 zoom-in-95",
2534
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
2535
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
2536
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
2537
+ className
2538
+ ),
2539
+ ...props
2540
+ }
2541
+ ) }));
2542
+ DropdownMenuContent.displayName = "DropdownMenuContent";
2543
+ var DropdownMenuSubTrigger = React33.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs15(
2544
+ DropdownMenuPrimitive.SubTrigger,
2545
+ {
2546
+ ref,
2547
+ className: cn(
2548
+ "flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none",
2549
+ "focus:bg-[--color-surface-muted]",
2550
+ "data-[state=open]:bg-[--color-surface-muted]",
2551
+ "touch:min-h-[--touch-target-min]",
2552
+ inset && "pl-8",
2553
+ className
2554
+ ),
2555
+ ...props,
2556
+ children: [
2557
+ children,
2558
+ /* @__PURE__ */ jsx34(
2559
+ "svg",
2560
+ {
2561
+ width: "14",
2562
+ height: "14",
2563
+ viewBox: "0 0 24 24",
2564
+ fill: "none",
2565
+ stroke: "currentColor",
2566
+ strokeWidth: "2",
2567
+ strokeLinecap: "round",
2568
+ strokeLinejoin: "round",
2569
+ className: "ml-auto",
2570
+ children: /* @__PURE__ */ jsx34("path", { d: "m9 18 6-6-6-6" })
2571
+ }
2572
+ )
2573
+ ]
2574
+ }
2575
+ ));
2576
+ DropdownMenuSubTrigger.displayName = "DropdownMenuSubTrigger";
2577
+ var DropdownMenuSubContent = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx34(
2578
+ DropdownMenuPrimitive.SubContent,
2579
+ {
2580
+ ref,
2581
+ className: cn(
2582
+ "z-dropdown min-w-[8rem] overflow-hidden rounded-md border border-[--color-border] bg-[--color-surface-raised] p-1 shadow-md",
2583
+ "animate-in fade-in-0 zoom-in-95",
2584
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2",
2585
+ "data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
2586
+ className
2587
+ ),
2588
+ ...props
2589
+ }
2590
+ ));
2591
+ DropdownMenuSubContent.displayName = "DropdownMenuSubContent";
2592
+ var DropdownMenuItem = React33.forwardRef(({ className, inset, destructive, ...props }, ref) => /* @__PURE__ */ jsx34(
2593
+ DropdownMenuPrimitive.Item,
2594
+ {
2595
+ ref,
2596
+ className: cn(
2597
+ "relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors",
2598
+ "focus:bg-[--color-surface-muted] focus:text-[--color-on-surface]",
2599
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
2600
+ "touch:min-h-[--touch-target-min]",
2601
+ destructive && "text-error-600 focus:bg-error-50 focus:text-error-600",
2602
+ inset && "pl-8",
2603
+ className
2604
+ ),
2605
+ ...props
2606
+ }
2607
+ ));
2608
+ DropdownMenuItem.displayName = "DropdownMenuItem";
2609
+ var DropdownMenuCheckboxItem = React33.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs15(
2610
+ DropdownMenuPrimitive.CheckboxItem,
2611
+ {
2612
+ ref,
2613
+ className: cn(
2614
+ "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors",
2615
+ "focus:bg-[--color-surface-muted]",
2616
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
2617
+ "touch:min-h-[--touch-target-min]",
2618
+ className
2619
+ ),
2620
+ checked,
2621
+ ...props,
2622
+ children: [
2623
+ /* @__PURE__ */ jsx34("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(
2624
+ "svg",
2625
+ {
2626
+ width: "14",
2627
+ height: "14",
2628
+ viewBox: "0 0 24 24",
2629
+ fill: "none",
2630
+ stroke: "currentColor",
2631
+ strokeWidth: "2",
2632
+ strokeLinecap: "round",
2633
+ strokeLinejoin: "round",
2634
+ children: /* @__PURE__ */ jsx34("polyline", { points: "20 6 9 17 4 12" })
2635
+ }
2636
+ ) }) }),
2637
+ children
2638
+ ]
2639
+ }
2640
+ ));
2641
+ DropdownMenuCheckboxItem.displayName = "DropdownMenuCheckboxItem";
2642
+ var DropdownMenuRadioItem = React33.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs15(
2643
+ DropdownMenuPrimitive.RadioItem,
2644
+ {
2645
+ ref,
2646
+ className: cn(
2647
+ "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors",
2648
+ "focus:bg-[--color-surface-muted]",
2649
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
2650
+ "touch:min-h-[--touch-target-min]",
2651
+ className
2652
+ ),
2653
+ ...props,
2654
+ children: [
2655
+ /* @__PURE__ */ jsx34("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "currentColor", children: /* @__PURE__ */ jsx34("circle", { cx: "4", cy: "4", r: "4" }) }) }) }),
2656
+ children
2657
+ ]
2658
+ }
2659
+ ));
2660
+ DropdownMenuRadioItem.displayName = "DropdownMenuRadioItem";
2661
+ var DropdownMenuLabel = React33.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx34(
2662
+ DropdownMenuPrimitive.Label,
2663
+ {
2664
+ ref,
2665
+ className: cn(
2666
+ "px-2 py-1.5 text-xs font-medium text-[--color-on-surface-muted]",
2667
+ inset && "pl-8",
2668
+ className
2669
+ ),
2670
+ ...props
2671
+ }
2672
+ ));
2673
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
2674
+ var DropdownMenuSeparator = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx34(
2675
+ DropdownMenuPrimitive.Separator,
2676
+ {
2677
+ ref,
2678
+ className: cn("-mx-1 my-1 h-px bg-[--color-border]", className),
2679
+ ...props
2680
+ }
2681
+ ));
2682
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
2683
+ var DropdownMenuShortcut = ({
2684
+ className,
2685
+ ...props
2686
+ }) => /* @__PURE__ */ jsx34(
2687
+ "span",
2688
+ {
2689
+ className: cn(
2690
+ "ml-auto text-xs tracking-widest text-[--color-on-surface-muted]",
2691
+ className
2692
+ ),
2693
+ ...props
2694
+ }
2695
+ );
2696
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
2697
+
2698
+ // src/components/dialog/dialog.tsx
2699
+ import * as React34 from "react";
2700
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
2701
+ import { jsx as jsx35, jsxs as jsxs16 } from "react/jsx-runtime";
2702
+ var Dialog = DialogPrimitive.Root;
2703
+ var DialogTrigger = DialogPrimitive.Trigger;
2704
+ var DialogClose = DialogPrimitive.Close;
2705
+ var DialogOverlay = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(
2706
+ DialogPrimitive.Overlay,
2707
+ {
2708
+ ref,
2709
+ className: cn(
2710
+ "fixed inset-0 z-modal bg-black/50",
2711
+ "animate-in fade-in-0",
2712
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
2713
+ className
2714
+ ),
2715
+ ...props
2716
+ }
2717
+ ));
2718
+ DialogOverlay.displayName = "DialogOverlay";
2719
+ var DialogContent = React34.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs16(DialogPrimitive.Portal, { children: [
2720
+ /* @__PURE__ */ jsx35(DialogOverlay, {}),
2721
+ /* @__PURE__ */ jsxs16(
2722
+ DialogPrimitive.Content,
2723
+ {
2724
+ ref,
2725
+ className: cn(
2726
+ "fixed z-modal bg-[--color-surface-raised] p-6 shadow-xl",
2727
+ "focus-visible:outline-none",
2728
+ // Mobile: full-screen
2729
+ "inset-0",
2730
+ // Desktop: centered modal
2731
+ "sm:inset-auto sm:left-1/2 sm:top-1/2 sm:-translate-x-1/2 sm:-translate-y-1/2",
2732
+ "sm:w-full sm:max-w-lg sm:rounded-xl sm:border sm:border-[--color-border]",
2733
+ // Animations
2734
+ "animate-in fade-in-0",
2735
+ "sm:zoom-in-95 sm:slide-in-from-left-1/2 sm:slide-in-from-top-[48%]",
2736
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
2737
+ "data-[state=closed]:sm:zoom-out-95",
2738
+ className
2739
+ ),
2740
+ ...props,
2741
+ children: [
2742
+ children,
2743
+ /* @__PURE__ */ jsxs16(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2 disabled:pointer-events-none", children: [
2744
+ /* @__PURE__ */ jsx35(
2745
+ "svg",
2746
+ {
2747
+ width: "16",
2748
+ height: "16",
2749
+ viewBox: "0 0 24 24",
2750
+ fill: "none",
2751
+ stroke: "currentColor",
2752
+ strokeWidth: "2",
2753
+ strokeLinecap: "round",
2754
+ strokeLinejoin: "round",
2755
+ children: /* @__PURE__ */ jsx35("path", { d: "M18 6 6 18M6 6l12 12" })
2756
+ }
2757
+ ),
2758
+ /* @__PURE__ */ jsx35("span", { className: "sr-only", children: "Close" })
2759
+ ] })
2760
+ ]
2761
+ }
2762
+ )
2763
+ ] }));
2764
+ DialogContent.displayName = "DialogContent";
2765
+ var DialogHeader = ({
2766
+ className,
2767
+ ...props
2768
+ }) => /* @__PURE__ */ jsx35(
2769
+ "div",
2770
+ {
2771
+ className: cn("flex flex-col gap-1.5 text-center sm:text-left", className),
2772
+ ...props
2773
+ }
2774
+ );
2775
+ DialogHeader.displayName = "DialogHeader";
2776
+ var DialogFooter = ({
2777
+ className,
2778
+ ...props
2779
+ }) => /* @__PURE__ */ jsx35(
2780
+ "div",
2781
+ {
2782
+ className: cn(
2783
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
2784
+ className
2785
+ ),
2786
+ ...props
2787
+ }
2788
+ );
2789
+ DialogFooter.displayName = "DialogFooter";
2790
+ var DialogTitle = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(
2791
+ DialogPrimitive.Title,
2792
+ {
2793
+ ref,
2794
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
2795
+ ...props
2796
+ }
2797
+ ));
2798
+ DialogTitle.displayName = "DialogTitle";
2799
+ var DialogDescription = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx35(
2800
+ DialogPrimitive.Description,
2801
+ {
2802
+ ref,
2803
+ className: cn("text-sm text-[--color-on-surface-muted]", className),
2804
+ ...props
2805
+ }
2806
+ ));
2807
+ DialogDescription.displayName = "DialogDescription";
2808
+
2809
+ // src/components/command-palette/command-palette.tsx
2810
+ import * as DialogPrimitive2 from "@radix-ui/react-dialog";
2811
+ import { Command as Command2 } from "cmdk";
2812
+ import { jsx as jsx36, jsxs as jsxs17 } from "react/jsx-runtime";
2813
+ function CommandPalette({
2814
+ open,
2815
+ onOpenChange,
2816
+ placeholder = "Type a command or search...",
2817
+ className,
2818
+ children
2819
+ }) {
2820
+ return /* @__PURE__ */ jsx36(DialogPrimitive2.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(DialogPrimitive2.Portal, { children: [
2821
+ /* @__PURE__ */ jsx36(DialogPrimitive2.Overlay, { className: "fixed inset-0 z-modal bg-black/50 animate-in fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0" }),
2822
+ /* @__PURE__ */ jsx36(
2823
+ DialogPrimitive2.Content,
2824
+ {
2825
+ className: cn(
2826
+ "fixed left-1/2 top-[20%] z-modal w-full max-w-xl -translate-x-1/2 overflow-hidden rounded-xl border border-[--color-border] bg-[--color-surface-raised] shadow-2xl",
2827
+ "animate-in fade-in-0 zoom-in-95 slide-in-from-left-1/2",
2828
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
2829
+ className
2830
+ ),
2831
+ children: /* @__PURE__ */ jsxs17(Command2, { shouldFilter: true, className: "flex flex-col", children: [
2832
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center border-b border-[--color-border] px-4", children: [
2833
+ /* @__PURE__ */ jsxs17(
2834
+ "svg",
2835
+ {
2836
+ width: "18",
2837
+ height: "18",
2838
+ viewBox: "0 0 24 24",
2839
+ fill: "none",
2840
+ stroke: "currentColor",
2841
+ strokeWidth: "2",
2842
+ strokeLinecap: "round",
2843
+ strokeLinejoin: "round",
2844
+ className: "shrink-0 text-[--color-on-surface-muted]",
2845
+ children: [
2846
+ /* @__PURE__ */ jsx36("circle", { cx: "11", cy: "11", r: "8" }),
2847
+ /* @__PURE__ */ jsx36("path", { d: "m21 21-4.3-4.3" })
2848
+ ]
2849
+ }
2850
+ ),
2851
+ /* @__PURE__ */ jsx36(
2852
+ Command2.Input,
2853
+ {
2854
+ placeholder,
2855
+ className: "flex h-12 w-full bg-transparent px-3 text-base outline-none placeholder:text-[--color-on-surface-muted]"
2856
+ }
2857
+ )
2858
+ ] }),
2859
+ /* @__PURE__ */ jsx36(Command2.List, { className: "max-h-80 overflow-auto p-2", children })
2860
+ ] })
2861
+ }
2862
+ )
2863
+ ] }) });
2864
+ }
2865
+ CommandPalette.displayName = "CommandPalette";
2866
+ function CommandPaletteGroup({
2867
+ heading,
2868
+ children
2869
+ }) {
2870
+ return /* @__PURE__ */ jsx36(
2871
+ Command2.Group,
2872
+ {
2873
+ heading,
2874
+ className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-[--color-on-surface-muted]",
2875
+ children
2876
+ }
2877
+ );
2878
+ }
2879
+ CommandPaletteGroup.displayName = "CommandPaletteGroup";
2880
+ function CommandPaletteItem({
2881
+ icon,
2882
+ shortcut,
2883
+ onSelect,
2884
+ disabled,
2885
+ className,
2886
+ children
2887
+ }) {
2888
+ return /* @__PURE__ */ jsxs17(
2889
+ Command2.Item,
2890
+ {
2891
+ onSelect,
2892
+ disabled,
2893
+ className: cn(
2894
+ "relative flex cursor-pointer select-none items-center rounded-md px-2 py-2 text-sm outline-none",
2895
+ "data-[selected=true]:bg-[--color-surface-muted]",
2896
+ "data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50",
2897
+ className
2898
+ ),
2899
+ children: [
2900
+ icon && /* @__PURE__ */ jsx36("span", { className: "mr-2 flex h-4 w-4 items-center justify-center text-[--color-on-surface-muted]", children: icon }),
2901
+ /* @__PURE__ */ jsx36("span", { className: "flex-1", children }),
2902
+ shortcut && /* @__PURE__ */ jsx36(CommandPaletteShortcut, { children: shortcut })
2903
+ ]
2904
+ }
2905
+ );
2906
+ }
2907
+ CommandPaletteItem.displayName = "CommandPaletteItem";
2908
+ function CommandPaletteSeparator({
2909
+ className,
2910
+ ...props
2911
+ }) {
2912
+ return /* @__PURE__ */ jsx36(
2913
+ Command2.Separator,
2914
+ {
2915
+ className: cn("-mx-1 my-1 h-px bg-[--color-border]", className),
2916
+ ...props
2917
+ }
2918
+ );
2919
+ }
2920
+ CommandPaletteSeparator.displayName = "CommandPaletteSeparator";
2921
+ function CommandPaletteEmpty({
2922
+ className,
2923
+ children = "No results found.",
2924
+ ...props
2925
+ }) {
2926
+ return /* @__PURE__ */ jsx36(
2927
+ Command2.Empty,
2928
+ {
2929
+ className: cn("px-2 py-6 text-center text-sm text-[--color-on-surface-muted]", className),
2930
+ ...props,
2931
+ children
2932
+ }
2933
+ );
2934
+ }
2935
+ CommandPaletteEmpty.displayName = "CommandPaletteEmpty";
2936
+ function CommandPaletteShortcut({
2937
+ className,
2938
+ ...props
2939
+ }) {
2940
+ return /* @__PURE__ */ jsx36(
2941
+ "span",
2942
+ {
2943
+ className: cn(
2944
+ "ml-auto text-xs tracking-widest text-[--color-on-surface-muted]",
2945
+ className
2946
+ ),
2947
+ ...props
2948
+ }
2949
+ );
2950
+ }
2951
+ CommandPaletteShortcut.displayName = "CommandPaletteShortcut";
2952
+
2953
+ // src/components/drawer/drawer.tsx
2954
+ import * as React35 from "react";
2955
+ import * as DialogPrimitive3 from "@radix-ui/react-dialog";
2956
+ import { cva as cva14 } from "class-variance-authority";
2957
+ import { jsx as jsx37, jsxs as jsxs18 } from "react/jsx-runtime";
2958
+ var [DrawerContextProvider, useDrawerContext] = createContext2("Drawer");
2959
+ var DrawerStackContext = React35.createContext(
2960
+ null
2961
+ );
2962
+ function DrawerProvider({ children }) {
2963
+ const stackRef = React35.useRef([]);
2964
+ const [, forceUpdate] = React35.useState(0);
2965
+ const register = React35.useCallback((id) => {
2966
+ const level = stackRef.current.length;
2967
+ stackRef.current = [...stackRef.current, { id, level }];
2968
+ forceUpdate((n) => n + 1);
2969
+ return level;
2970
+ }, []);
2971
+ const unregister = React35.useCallback((id) => {
2972
+ stackRef.current = stackRef.current.filter((e) => e.id !== id);
2973
+ forceUpdate((n) => n + 1);
2974
+ }, []);
2975
+ const ctx = React35.useMemo(
2976
+ () => ({ stack: stackRef.current, register, unregister }),
2977
+ [register, unregister]
2978
+ );
2979
+ return /* @__PURE__ */ jsx37(DrawerStackContext.Provider, { value: ctx, children });
2980
+ }
2981
+ DrawerProvider.displayName = "DrawerProvider";
2982
+ function Drawer({
2983
+ open,
2984
+ onOpenChange,
2985
+ side = "right",
2986
+ pinnable = false,
2987
+ pinned = false,
2988
+ onPinnedChange,
2989
+ children
2990
+ }) {
2991
+ return /* @__PURE__ */ jsx37(DrawerContextProvider, { value: { side, pinnable, pinned, onPinnedChange }, children: /* @__PURE__ */ jsx37(DialogPrimitive3.Root, { open, onOpenChange, children }) });
2992
+ }
2993
+ Drawer.displayName = "Drawer";
2994
+ var DrawerTrigger = DialogPrimitive3.Trigger;
2995
+ var DrawerClose = DialogPrimitive3.Close;
2996
+ var drawerSizeVariants = cva14("", {
2997
+ variants: {
2998
+ size: {
2999
+ sm: "w-80",
3000
+ // 320px
3001
+ md: "w-[480px]",
3002
+ lg: "w-[640px]",
3003
+ xl: "w-[800px]"
3004
+ }
3005
+ },
3006
+ defaultVariants: { size: "md" }
3007
+ });
3008
+ var DrawerContent = React35.forwardRef(({ className, size, children, ...props }, ref) => {
3009
+ const { side, pinned } = useDrawerContext();
3010
+ const stackCtx = React35.useContext(DrawerStackContext);
3011
+ const drawerId = React35.useId();
3012
+ const [level, setLevel] = React35.useState(0);
3013
+ React35.useEffect(() => {
3014
+ if (stackCtx) {
3015
+ const l = stackCtx.register(drawerId);
3016
+ setLevel(l);
3017
+ return () => stackCtx.unregister(drawerId);
3018
+ }
3019
+ }, [stackCtx, drawerId]);
3020
+ const stackOffset = stackCtx ? level * 2 : 0;
3021
+ if (pinned) {
3022
+ return /* @__PURE__ */ jsx37(
3023
+ "div",
3024
+ {
3025
+ className: cn(
3026
+ "flex flex-col border-[--color-border] bg-[--color-surface-raised]",
3027
+ side === "right" ? "border-l" : "border-r",
3028
+ drawerSizeVariants({ size }),
3029
+ className
3030
+ ),
3031
+ children
3032
+ }
3033
+ );
3034
+ }
3035
+ return /* @__PURE__ */ jsxs18(DialogPrimitive3.Portal, { children: [
3036
+ /* @__PURE__ */ jsx37(
3037
+ DialogPrimitive3.Overlay,
3038
+ {
3039
+ className: cn(
3040
+ "fixed inset-0 bg-black/30",
3041
+ "animate-in fade-in-0",
3042
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0"
3043
+ ),
3044
+ style: { zIndex: 200 + stackOffset }
3045
+ }
3046
+ ),
3047
+ /* @__PURE__ */ jsx37(
3048
+ DialogPrimitive3.Content,
3049
+ {
3050
+ ref,
3051
+ className: cn(
3052
+ "fixed top-0 h-full bg-[--color-surface-raised] shadow-xl",
3053
+ "focus-visible:outline-none",
3054
+ side === "right" && "right-0 border-l border-[--color-border] animate-slide-in-right data-[state=closed]:animate-slide-out-right",
3055
+ side === "left" && "left-0 border-r border-[--color-border] animate-slide-in-left data-[state=closed]:animate-slide-out-left",
3056
+ drawerSizeVariants({ size }),
3057
+ className
3058
+ ),
3059
+ style: { zIndex: 201 + stackOffset },
3060
+ ...props,
3061
+ children: /* @__PURE__ */ jsx37("div", { className: "flex h-full flex-col", children })
3062
+ }
3063
+ )
3064
+ ] });
3065
+ });
3066
+ DrawerContent.displayName = "DrawerContent";
3067
+ var DrawerHeader = React35.forwardRef(({ className, ...props }, ref) => {
3068
+ const { pinnable, pinned, onPinnedChange } = useDrawerContext();
3069
+ return /* @__PURE__ */ jsxs18(
3070
+ "div",
3071
+ {
3072
+ ref,
3073
+ className: cn(
3074
+ "flex items-center justify-between border-b border-[--color-border] px-6 py-4",
3075
+ className
3076
+ ),
3077
+ ...props,
3078
+ children: [
3079
+ /* @__PURE__ */ jsx37("div", { className: "flex-1", children: props.children }),
3080
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1", children: [
3081
+ pinnable && /* @__PURE__ */ jsx37(
3082
+ "button",
3083
+ {
3084
+ type: "button",
3085
+ onClick: () => onPinnedChange?.(!pinned),
3086
+ className: cn(
3087
+ "rounded-sm p-1 transition-opacity hover:opacity-100",
3088
+ pinned ? "opacity-100 text-primary-500" : "opacity-50"
3089
+ ),
3090
+ "aria-label": pinned ? "Unpin drawer" : "Pin drawer",
3091
+ children: /* @__PURE__ */ jsx37(
3092
+ "svg",
3093
+ {
3094
+ width: "16",
3095
+ height: "16",
3096
+ viewBox: "0 0 24 24",
3097
+ fill: pinned ? "currentColor" : "none",
3098
+ stroke: "currentColor",
3099
+ strokeWidth: "2",
3100
+ strokeLinecap: "round",
3101
+ strokeLinejoin: "round",
3102
+ children: /* @__PURE__ */ jsx37("path", { d: "M12 17v5M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1 1 1 0 0 1 1 1z" })
3103
+ }
3104
+ )
3105
+ }
3106
+ ),
3107
+ /* @__PURE__ */ jsxs18(DialogPrimitive3.Close, { className: "rounded-sm p-1 opacity-50 transition-opacity hover:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500", children: [
3108
+ /* @__PURE__ */ jsx37(
3109
+ "svg",
3110
+ {
3111
+ width: "16",
3112
+ height: "16",
3113
+ viewBox: "0 0 24 24",
3114
+ fill: "none",
3115
+ stroke: "currentColor",
3116
+ strokeWidth: "2",
3117
+ strokeLinecap: "round",
3118
+ strokeLinejoin: "round",
3119
+ children: /* @__PURE__ */ jsx37("path", { d: "M18 6 6 18M6 6l12 12" })
3120
+ }
3121
+ ),
3122
+ /* @__PURE__ */ jsx37("span", { className: "sr-only", children: "Close" })
3123
+ ] })
3124
+ ] })
3125
+ ]
3126
+ }
3127
+ );
3128
+ });
3129
+ DrawerHeader.displayName = "DrawerHeader";
3130
+ var DrawerTitle = React35.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
3131
+ DialogPrimitive3.Title,
3132
+ {
3133
+ ref,
3134
+ className: cn("text-lg font-semibold", className),
3135
+ ...props
3136
+ }
3137
+ ));
3138
+ DrawerTitle.displayName = "DrawerTitle";
3139
+ var DrawerDescription = React35.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
3140
+ DialogPrimitive3.Description,
3141
+ {
3142
+ ref,
3143
+ className: cn("text-sm text-[--color-on-surface-muted]", className),
3144
+ ...props
3145
+ }
3146
+ ));
3147
+ DrawerDescription.displayName = "DrawerDescription";
3148
+ var DrawerFooter = React35.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx37(
3149
+ "div",
3150
+ {
3151
+ ref,
3152
+ className: cn(
3153
+ "flex items-center justify-end gap-2 border-t border-[--color-border] px-6 py-4",
3154
+ className
3155
+ ),
3156
+ ...props
3157
+ }
3158
+ ));
3159
+ DrawerFooter.displayName = "DrawerFooter";
3160
+
3161
+ // src/components/app-shell/app-shell.tsx
3162
+ import * as React36 from "react";
3163
+ import { jsx as jsx38, jsxs as jsxs19 } from "react/jsx-runtime";
3164
+ var [AppShellProvider, useAppShell] = createContext2("AppShell");
3165
+ var AppShell = React36.forwardRef(
3166
+ ({
3167
+ className,
3168
+ sidebarCollapsed: controlledCollapsed,
3169
+ onSidebarCollapsedChange,
3170
+ sidebarWidth = 256,
3171
+ sidebarCollapsedWidth = 64,
3172
+ withBottomNav = false,
3173
+ children,
3174
+ ...props
3175
+ }, ref) => {
3176
+ const { isMobile } = useBreakpoint();
3177
+ const [internalCollapsed, setInternalCollapsed] = React36.useState(false);
3178
+ const [mobileSidebarOpen, setMobileSidebarOpen] = React36.useState(false);
3179
+ const collapsed = controlledCollapsed ?? internalCollapsed;
3180
+ const setCollapsed = onSidebarCollapsedChange ?? setInternalCollapsed;
3181
+ return /* @__PURE__ */ jsx38(
3182
+ AppShellProvider,
3183
+ {
3184
+ value: {
3185
+ sidebarCollapsed: collapsed,
3186
+ setSidebarCollapsed: setCollapsed,
3187
+ isMobile,
3188
+ withBottomNav,
3189
+ mobileSidebarOpen,
3190
+ setMobileSidebarOpen
3191
+ },
3192
+ children: /* @__PURE__ */ jsx38(
3193
+ "div",
3194
+ {
3195
+ ref,
3196
+ className: cn("flex h-dvh", className),
3197
+ style: {
3198
+ "--sidebar-width": `${sidebarWidth}px`,
3199
+ "--sidebar-collapsed-width": `${sidebarCollapsedWidth}px`
3200
+ },
3201
+ ...props,
3202
+ children
3203
+ }
3204
+ )
3205
+ }
3206
+ );
3207
+ }
3208
+ );
3209
+ AppShell.displayName = "AppShell";
3210
+ var AppShellSidebar = React36.forwardRef(({ className, children, ...props }, ref) => {
3211
+ const { sidebarCollapsed, isMobile, mobileSidebarOpen, setMobileSidebarOpen } = useAppShell();
3212
+ if (isMobile) {
3213
+ return /* @__PURE__ */ jsx38(
3214
+ Drawer,
3215
+ {
3216
+ open: mobileSidebarOpen,
3217
+ onOpenChange: setMobileSidebarOpen,
3218
+ side: "left",
3219
+ children: /* @__PURE__ */ jsx38(DrawerContent, { size: "sm", className, children })
3220
+ }
3221
+ );
3222
+ }
3223
+ return /* @__PURE__ */ jsx38(
3224
+ "aside",
3225
+ {
3226
+ ref,
3227
+ className: cn(
3228
+ "hidden md:flex md:flex-col shrink-0 border-r border-[--color-border] bg-[--color-surface-raised] overflow-y-auto transition-[width] duration-slow",
3229
+ className
3230
+ ),
3231
+ style: {
3232
+ width: sidebarCollapsed ? "var(--sidebar-collapsed-width)" : "var(--sidebar-width)"
3233
+ },
3234
+ ...props,
3235
+ children
3236
+ }
3237
+ );
3238
+ });
3239
+ AppShellSidebar.displayName = "AppShellSidebar";
3240
+ var AppShellHeader = React36.forwardRef(({ className, children, ...props }, ref) => {
3241
+ const { isMobile, setMobileSidebarOpen } = useAppShell();
3242
+ return /* @__PURE__ */ jsxs19(
3243
+ "header",
3244
+ {
3245
+ ref,
3246
+ className: cn(
3247
+ "flex h-14 items-center gap-3 border-b border-[--color-border] bg-[--color-surface-raised] px-4 shrink-0",
3248
+ className
3249
+ ),
3250
+ ...props,
3251
+ children: [
3252
+ isMobile && /* @__PURE__ */ jsx38(
3253
+ "button",
3254
+ {
3255
+ type: "button",
3256
+ onClick: () => setMobileSidebarOpen(true),
3257
+ className: "rounded-md p-1.5 hover:bg-[--color-surface-muted] transition-colors touch:min-h-[--touch-target-min] touch:min-w-[--touch-target-min] flex items-center justify-center",
3258
+ "aria-label": "Open menu",
3259
+ children: /* @__PURE__ */ jsx38(
3260
+ "svg",
3261
+ {
3262
+ width: "20",
3263
+ height: "20",
3264
+ viewBox: "0 0 24 24",
3265
+ fill: "none",
3266
+ stroke: "currentColor",
3267
+ strokeWidth: "2",
3268
+ strokeLinecap: "round",
3269
+ strokeLinejoin: "round",
3270
+ children: /* @__PURE__ */ jsx38("path", { d: "M4 6h16M4 12h16M4 18h16" })
3271
+ }
3272
+ )
3273
+ }
3274
+ ),
3275
+ children
3276
+ ]
3277
+ }
3278
+ );
3279
+ });
3280
+ AppShellHeader.displayName = "AppShellHeader";
3281
+ var AppShellContent = React36.forwardRef(({ className, ...props }, ref) => {
3282
+ const { withBottomNav } = useAppShell();
3283
+ return /* @__PURE__ */ jsx38(
3284
+ "main",
3285
+ {
3286
+ ref,
3287
+ className: cn(
3288
+ "flex-1 overflow-auto",
3289
+ withBottomNav && "pb-[calc(var(--bottom-nav-height)+var(--safe-area-bottom))]",
3290
+ className
3291
+ ),
3292
+ ...props
3293
+ }
3294
+ );
3295
+ });
3296
+ AppShellContent.displayName = "AppShellContent";
3297
+ var AppShellFooter = React36.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx38(
3298
+ "footer",
3299
+ {
3300
+ ref,
3301
+ className: cn(
3302
+ "flex items-center border-t border-[--color-border] bg-[--color-surface-raised] px-4 py-2 shrink-0",
3303
+ className
3304
+ ),
3305
+ ...props
3306
+ }
3307
+ ));
3308
+ AppShellFooter.displayName = "AppShellFooter";
3309
+
3310
+ // src/components/bottom-navigation/bottom-navigation.tsx
3311
+ import * as React37 from "react";
3312
+ import { jsx as jsx39, jsxs as jsxs20 } from "react/jsx-runtime";
3313
+ var BottomNavigation = React37.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx39(
3314
+ "nav",
3315
+ {
3316
+ ref,
3317
+ className: cn(
3318
+ "fixed bottom-0 left-0 right-0 z-sticky flex items-center justify-around border-t border-[--color-border] bg-[--color-surface-raised] pb-[--safe-area-bottom]",
3319
+ "h-[calc(var(--bottom-nav-height)+var(--safe-area-bottom))]",
3320
+ className
3321
+ ),
3322
+ ...props
3323
+ }
3324
+ ));
3325
+ BottomNavigation.displayName = "BottomNavigation";
3326
+ var BottomNavigationItem = React37.forwardRef(({ className, icon, label, active = false, ...props }, ref) => /* @__PURE__ */ jsxs20(
3327
+ "button",
3328
+ {
3329
+ ref,
3330
+ className: cn(
3331
+ "flex min-w-[--touch-target-min] flex-1 flex-col items-center justify-center gap-0.5 py-1 text-xs transition-colors",
3332
+ active ? "text-primary-500 font-medium" : "text-[--color-on-surface-muted] hover:text-[--color-on-surface-secondary]",
3333
+ className
3334
+ ),
3335
+ "aria-current": active ? "page" : void 0,
3336
+ ...props,
3337
+ children: [
3338
+ /* @__PURE__ */ jsx39("span", { className: "flex h-6 w-6 items-center justify-center", children: icon }),
3339
+ /* @__PURE__ */ jsx39("span", { children: label })
3340
+ ]
3341
+ }
3342
+ ));
3343
+ BottomNavigationItem.displayName = "BottomNavigationItem";
3344
+
3345
+ // src/components/offline-indicator/offline-indicator.tsx
3346
+ import * as React38 from "react";
3347
+ import { jsx as jsx40, jsxs as jsxs21 } from "react/jsx-runtime";
3348
+ var OfflineIndicator = React38.forwardRef(
3349
+ ({
3350
+ className,
3351
+ isOffline,
3352
+ message = "\u30AA\u30D5\u30E9\u30A4\u30F3\u3067\u3059\u3002\u4E00\u90E8\u306E\u6A5F\u80FD\u304C\u5236\u9650\u3055\u308C\u307E\u3059\u3002",
3353
+ ...props
3354
+ }, ref) => {
3355
+ if (!isOffline) return null;
3356
+ return /* @__PURE__ */ jsxs21(
3357
+ "div",
3358
+ {
3359
+ ref,
3360
+ role: "alert",
3361
+ className: cn(
3362
+ "fixed top-0 left-0 right-0 z-toast flex items-center justify-center bg-warning-500 px-4 py-2 text-xs font-medium text-white pt-[calc(0.5rem+var(--safe-area-top))]",
3363
+ className
3364
+ ),
3365
+ ...props,
3366
+ children: [
3367
+ /* @__PURE__ */ jsxs21(
3368
+ "svg",
3369
+ {
3370
+ xmlns: "http://www.w3.org/2000/svg",
3371
+ width: "14",
3372
+ height: "14",
3373
+ viewBox: "0 0 24 24",
3374
+ fill: "none",
3375
+ stroke: "currentColor",
3376
+ strokeWidth: "2",
3377
+ strokeLinecap: "round",
3378
+ strokeLinejoin: "round",
3379
+ className: "mr-2 shrink-0",
3380
+ "aria-hidden": "true",
3381
+ children: [
3382
+ /* @__PURE__ */ jsx40("line", { x1: "2", x2: "22", y1: "2", y2: "22" }),
3383
+ /* @__PURE__ */ jsx40("path", { d: "M8.5 16.5a5 5 0 0 1 7 0" }),
3384
+ /* @__PURE__ */ jsx40("path", { d: "M2 8.82a15 15 0 0 1 4.17-2.65" }),
3385
+ /* @__PURE__ */ jsx40("path", { d: "M10.66 5c4.01-.36 8.14.9 11.34 3.76" }),
3386
+ /* @__PURE__ */ jsx40("path", { d: "M16.85 11.25a10 10 0 0 1 2.22 1.68" }),
3387
+ /* @__PURE__ */ jsx40("path", { d: "M5 12.859a10 10 0 0 1 5.17-2.69" }),
3388
+ /* @__PURE__ */ jsx40("line", { x1: "12", x2: "12.01", y1: "20", y2: "20" })
3389
+ ]
3390
+ }
3391
+ ),
3392
+ message
3393
+ ]
3394
+ }
3395
+ );
3396
+ }
3397
+ );
3398
+ OfflineIndicator.displayName = "OfflineIndicator";
3399
+
3400
+ // src/components/install-prompt/install-prompt.tsx
3401
+ import * as React39 from "react";
3402
+ import { jsx as jsx41, jsxs as jsxs22 } from "react/jsx-runtime";
3403
+ var InstallPrompt = React39.forwardRef(
3404
+ ({
3405
+ className,
3406
+ canInstall,
3407
+ onInstall,
3408
+ onDismiss,
3409
+ title = "\u30A2\u30D7\u30EA\u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB",
3410
+ description = "\u30DB\u30FC\u30E0\u753B\u9762\u306B\u8FFD\u52A0\u3059\u308B\u3068\u3001\u3059\u3050\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u3059\u3002",
3411
+ installLabel = "\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB",
3412
+ dismissLabel = "\u5F8C\u3067",
3413
+ ...props
3414
+ }, ref) => {
3415
+ if (!canInstall) return null;
3416
+ return /* @__PURE__ */ jsx41(
3417
+ "div",
3418
+ {
3419
+ ref,
3420
+ role: "dialog",
3421
+ "aria-label": title,
3422
+ className: cn(
3423
+ "fixed bottom-0 left-0 right-0 z-modal border-t border-[--color-border] bg-[--color-surface-raised] p-4 shadow-lg pb-[calc(1rem+var(--safe-area-bottom))]",
3424
+ className
3425
+ ),
3426
+ ...props,
3427
+ children: /* @__PURE__ */ jsxs22("div", { className: "mx-auto max-w-md", children: [
3428
+ /* @__PURE__ */ jsx41("p", { className: "text-sm font-semibold text-[--color-on-surface]", children: title }),
3429
+ /* @__PURE__ */ jsx41("p", { className: "mt-1 text-xs text-[--color-on-surface-muted]", children: description }),
3430
+ /* @__PURE__ */ jsxs22("div", { className: "mt-3 flex gap-2", children: [
3431
+ /* @__PURE__ */ jsx41(Button, { size: "sm", onClick: onInstall, className: "flex-1", children: installLabel }),
3432
+ /* @__PURE__ */ jsx41(
3433
+ Button,
3434
+ {
3435
+ size: "sm",
3436
+ variant: "ghost",
3437
+ onClick: onDismiss,
3438
+ className: "flex-1",
3439
+ children: dismissLabel
3440
+ }
3441
+ )
3442
+ ] })
3443
+ ] })
3444
+ }
3445
+ );
3446
+ }
3447
+ );
3448
+ InstallPrompt.displayName = "InstallPrompt";
3449
+
3450
+ // src/components/pull-to-refresh/pull-to-refresh.tsx
3451
+ import * as React40 from "react";
3452
+ import { jsx as jsx42, jsxs as jsxs23 } from "react/jsx-runtime";
3453
+ var PullToRefresh = React40.forwardRef(
3454
+ ({ className, onRefresh, threshold = 80, disabled = false, children, ...props }, ref) => {
3455
+ const [pullDistance, setPullDistance] = React40.useState(0);
3456
+ const [isRefreshing, setIsRefreshing] = React40.useState(false);
3457
+ const startYRef = React40.useRef(0);
3458
+ const containerRef = React40.useRef(null);
3459
+ React40.useImperativeHandle(ref, () => containerRef.current);
3460
+ const handleTouchStart = React40.useCallback(
3461
+ (e) => {
3462
+ if (disabled || isRefreshing) return;
3463
+ const container = containerRef.current;
3464
+ if (container && container.scrollTop === 0) {
3465
+ startYRef.current = e.touches[0].clientY;
3466
+ }
3467
+ },
3468
+ [disabled, isRefreshing]
3469
+ );
3470
+ const handleTouchMove = React40.useCallback(
3471
+ (e) => {
3472
+ if (disabled || isRefreshing || startYRef.current === 0) return;
3473
+ const distance = Math.max(
3474
+ 0,
3475
+ (e.touches[0].clientY - startYRef.current) * 0.5
3476
+ );
3477
+ if (distance > 0) {
3478
+ setPullDistance(Math.min(distance, threshold * 1.5));
3479
+ }
3480
+ },
3481
+ [disabled, isRefreshing, threshold]
3482
+ );
3483
+ const handleTouchEnd = React40.useCallback(async () => {
3484
+ if (disabled || isRefreshing) return;
3485
+ if (pullDistance >= threshold) {
3486
+ setIsRefreshing(true);
3487
+ try {
3488
+ await onRefresh();
3489
+ } finally {
3490
+ setIsRefreshing(false);
3491
+ }
3492
+ }
3493
+ setPullDistance(0);
3494
+ startYRef.current = 0;
3495
+ }, [disabled, isRefreshing, pullDistance, threshold, onRefresh]);
3496
+ const indicatorOpacity = Math.min(pullDistance / threshold, 1);
3497
+ const shouldTrigger = pullDistance >= threshold;
3498
+ return /* @__PURE__ */ jsxs23(
3499
+ "div",
3500
+ {
3501
+ ref: containerRef,
3502
+ className: cn("relative overflow-auto", className),
3503
+ onTouchStart: handleTouchStart,
3504
+ onTouchMove: handleTouchMove,
3505
+ onTouchEnd: handleTouchEnd,
3506
+ ...props,
3507
+ children: [
3508
+ /* @__PURE__ */ jsx42(
3509
+ "div",
3510
+ {
3511
+ className: "flex items-center justify-center overflow-hidden transition-[height] duration-normal",
3512
+ style: { height: isRefreshing ? threshold * 0.6 : pullDistance },
3513
+ "aria-hidden": "true",
3514
+ children: /* @__PURE__ */ jsx42(
3515
+ "div",
3516
+ {
3517
+ className: "transition-opacity",
3518
+ style: { opacity: isRefreshing ? 1 : indicatorOpacity },
3519
+ children: isRefreshing ? /* @__PURE__ */ jsx42(Spinner, { size: "sm" }) : /* @__PURE__ */ jsxs23(
3520
+ "svg",
3521
+ {
3522
+ xmlns: "http://www.w3.org/2000/svg",
3523
+ width: "20",
3524
+ height: "20",
3525
+ viewBox: "0 0 24 24",
3526
+ fill: "none",
3527
+ stroke: "currentColor",
3528
+ strokeWidth: "2",
3529
+ strokeLinecap: "round",
3530
+ strokeLinejoin: "round",
3531
+ className: cn(
3532
+ "text-[--color-on-surface-muted] transition-transform duration-normal",
3533
+ shouldTrigger && "rotate-180 text-primary-500"
3534
+ ),
3535
+ children: [
3536
+ /* @__PURE__ */ jsx42("path", { d: "M12 5v14" }),
3537
+ /* @__PURE__ */ jsx42("path", { d: "m19 12-7 7-7-7" })
3538
+ ]
3539
+ }
3540
+ )
3541
+ }
3542
+ )
3543
+ }
3544
+ ),
3545
+ children
3546
+ ]
3547
+ }
3548
+ );
3549
+ }
3550
+ );
3551
+ PullToRefresh.displayName = "PullToRefresh";
3552
+ export {
3553
+ ActiveFilters,
3554
+ AppShell,
3555
+ AppShellContent,
3556
+ AppShellFooter,
3557
+ AppShellHeader,
3558
+ AppShellSidebar,
3559
+ Avatar,
3560
+ AvatarFallback,
3561
+ AvatarImage,
3562
+ BREAKPOINTS,
3563
+ Badge,
3564
+ BottomNavigation,
3565
+ BottomNavigationItem,
3566
+ Button,
3567
+ Card,
3568
+ CardContent,
3569
+ CardDescription,
3570
+ CardFooter,
3571
+ CardHeader,
3572
+ CardTitle,
3573
+ Checkbox,
3574
+ Combobox,
3575
+ CommandPalette,
3576
+ CommandPaletteEmpty,
3577
+ CommandPaletteGroup,
3578
+ CommandPaletteItem,
3579
+ CommandPaletteSeparator,
3580
+ CommandPaletteShortcut,
3581
+ DataTable,
3582
+ DataTableColumnHeader,
3583
+ DataTablePagination,
3584
+ DataTableToolbar,
3585
+ DatePicker,
3586
+ Dialog,
3587
+ DialogClose,
3588
+ DialogContent,
3589
+ DialogDescription,
3590
+ DialogFooter,
3591
+ DialogHeader,
3592
+ DialogOverlay,
3593
+ DialogTitle,
3594
+ DialogTrigger,
3595
+ Drawer,
3596
+ DrawerClose,
3597
+ DrawerContent,
3598
+ DrawerDescription,
3599
+ DrawerFooter,
3600
+ DrawerHeader,
3601
+ DrawerProvider,
3602
+ DrawerTitle,
3603
+ DrawerTrigger,
3604
+ DropdownMenu,
3605
+ DropdownMenuCheckboxItem,
3606
+ DropdownMenuContent,
3607
+ DropdownMenuGroup,
3608
+ DropdownMenuItem,
3609
+ DropdownMenuLabel,
3610
+ DropdownMenuPortal,
3611
+ DropdownMenuRadioGroup,
3612
+ DropdownMenuRadioItem,
3613
+ DropdownMenuSeparator,
3614
+ DropdownMenuShortcut,
3615
+ DropdownMenuSub,
3616
+ DropdownMenuSubContent,
3617
+ DropdownMenuSubTrigger,
3618
+ DropdownMenuTrigger,
3619
+ DynamicFormField,
3620
+ EmptyState,
3621
+ EmptyStateActions,
3622
+ EmptyStateDescription,
3623
+ EmptyStateIcon,
3624
+ EmptyStateTitle,
3625
+ FilterBar,
3626
+ FilterBarActions,
3627
+ FilterBarGroup,
3628
+ FilterChip,
3629
+ FormActions,
3630
+ FormControl,
3631
+ FormDescription,
3632
+ FormField,
3633
+ FormLabel,
3634
+ FormLayout,
3635
+ FormMessage,
3636
+ FormSection,
3637
+ Input,
3638
+ InstallPrompt,
3639
+ Label,
3640
+ NumberInput,
3641
+ OfflineIndicator,
3642
+ Popover,
3643
+ PopoverAnchor,
3644
+ PopoverContent,
3645
+ PopoverTrigger,
3646
+ PullToRefresh,
3647
+ RadioGroup,
3648
+ RadioGroupItem,
3649
+ Select,
3650
+ SelectContent,
3651
+ SelectGroup,
3652
+ SelectItem,
3653
+ SelectLabel,
3654
+ SelectSeparator,
3655
+ SelectTrigger,
3656
+ SelectValue,
3657
+ Separator,
3658
+ Skeleton,
3659
+ Spinner,
3660
+ Switch,
3661
+ Table,
3662
+ TableBody,
3663
+ TableCaption,
3664
+ TableCell,
3665
+ TableFooter,
3666
+ TableHead,
3667
+ TableHeader,
3668
+ TableRow,
3669
+ Tabs,
3670
+ TabsContent,
3671
+ TabsList,
3672
+ TabsTrigger,
3673
+ Textarea,
3674
+ ThemeProvider,
3675
+ Toast,
3676
+ ToastAction,
3677
+ ToastClose,
3678
+ ToastDescription,
3679
+ ToastProvider,
3680
+ ToastTitle,
3681
+ ToastViewport,
3682
+ Toaster,
3683
+ Tooltip,
3684
+ TooltipContent,
3685
+ TooltipProvider,
3686
+ TooltipTrigger,
3687
+ avatarVariants,
3688
+ badgeVariants,
3689
+ buttonVariants,
3690
+ cn,
3691
+ createContext2 as createContext,
3692
+ formLayoutVariants,
3693
+ getFieldComponent,
3694
+ inputVariants,
3695
+ spinnerVariants,
3696
+ switchVariants,
3697
+ textareaVariants,
3698
+ toast,
3699
+ toastVariants,
3700
+ useAppShell,
3701
+ useBreakpoint,
3702
+ useDisplayMode,
3703
+ useFormField,
3704
+ useInstallPrompt,
3705
+ useOnlineStatus,
3706
+ useTheme,
3707
+ useTheme2 as useThemeContext,
3708
+ useToast,
3709
+ useViewportHeight
3710
+ };
3711
+ //# sourceMappingURL=index.js.map