@lsts_tech/ui 2.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,970 @@
1
+ "use client"
2
+
3
+ // src/components/alert.tsx
4
+ import * as React from "react";
5
+ import { cva } from "class-variance-authority";
6
+
7
+ // src/lib/utils.ts
8
+ import { clsx } from "clsx";
9
+ import { twMerge } from "tailwind-merge";
10
+ function cn(...inputs) {
11
+ return twMerge(clsx(inputs));
12
+ }
13
+ function formatDate(input) {
14
+ const date = new Date(input);
15
+ return date.toLocaleDateString("en-US", {
16
+ month: "long",
17
+ day: "numeric",
18
+ year: "numeric"
19
+ });
20
+ }
21
+ function formatCurrency(amount) {
22
+ return new Intl.NumberFormat("en-US", {
23
+ style: "currency",
24
+ currency: "USD"
25
+ }).format(amount);
26
+ }
27
+
28
+ // src/components/alert.tsx
29
+ import { X, CheckCircle, AlertCircle, Info, AlertTriangle } from "lucide-react";
30
+ import { jsx, jsxs } from "react/jsx-runtime";
31
+ var alertVariants = cva(
32
+ "relative w-full rounded-lg border p-4 [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7",
33
+ {
34
+ variants: {
35
+ variant: {
36
+ default: "bg-background text-foreground border-border",
37
+ muted: "bg-muted text-muted-foreground border-muted",
38
+ brand: "bg-brand-primary/10 text-brand-primary border-brand-primary/20 [&>svg]:text-brand-primary",
39
+ success: "bg-success/10 text-success border-success/20 [&>svg]:text-success",
40
+ warning: "bg-warning/10 text-warning border-warning/20 [&>svg]:text-warning",
41
+ info: "bg-info/10 text-info border-info/20 [&>svg]:text-info",
42
+ error: "bg-error/10 text-error border-error/20 [&>svg]:text-error",
43
+ destructive: "bg-destructive/10 text-destructive border-destructive/20 [&>svg]:text-destructive"
44
+ },
45
+ radius: {
46
+ default: "rounded-lg",
47
+ sm: "rounded-md",
48
+ lg: "rounded-xl",
49
+ none: "rounded-none"
50
+ }
51
+ },
52
+ defaultVariants: {
53
+ variant: "default",
54
+ radius: "default"
55
+ }
56
+ }
57
+ );
58
+ var alertIconMap = {
59
+ default: Info,
60
+ muted: Info,
61
+ brand: Info,
62
+ success: CheckCircle,
63
+ warning: AlertTriangle,
64
+ info: Info,
65
+ error: AlertCircle,
66
+ destructive: AlertCircle
67
+ };
68
+ var Alert = React.forwardRef(
69
+ ({
70
+ className,
71
+ variant = "default",
72
+ radius,
73
+ title,
74
+ children,
75
+ dismissible,
76
+ onDismiss,
77
+ icon,
78
+ showIcon = true,
79
+ ...props
80
+ }, ref) => {
81
+ const IconComponent = variant ? alertIconMap[variant] : Info;
82
+ return /* @__PURE__ */ jsxs(
83
+ "div",
84
+ {
85
+ ref,
86
+ role: "alert",
87
+ className: cn(alertVariants({ variant, radius, className })),
88
+ ...props,
89
+ children: [
90
+ showIcon && (icon || /* @__PURE__ */ jsx(IconComponent, { className: "h-4 w-4" })),
91
+ dismissible && /* @__PURE__ */ jsxs(
92
+ "button",
93
+ {
94
+ onClick: onDismiss,
95
+ className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
96
+ children: [
97
+ /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
98
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Dismiss" })
99
+ ]
100
+ }
101
+ ),
102
+ title && /* @__PURE__ */ jsx(AlertTitle, { children: title }),
103
+ children && /* @__PURE__ */ jsx(AlertDescription, { children })
104
+ ]
105
+ }
106
+ );
107
+ }
108
+ );
109
+ Alert.displayName = "Alert";
110
+ var AlertTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
111
+ "h5",
112
+ {
113
+ ref,
114
+ className: cn("mb-1 font-medium leading-none tracking-tight", className),
115
+ ...props
116
+ }
117
+ ));
118
+ AlertTitle.displayName = "AlertTitle";
119
+ var AlertDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
120
+ "div",
121
+ {
122
+ ref,
123
+ className: cn("text-sm [&_p]:leading-relaxed", className),
124
+ ...props
125
+ }
126
+ ));
127
+ AlertDescription.displayName = "AlertDescription";
128
+
129
+ // src/components/avatar.tsx
130
+ import * as React2 from "react";
131
+ import { jsx as jsx2 } from "react/jsx-runtime";
132
+ var Avatar = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
133
+ "div",
134
+ {
135
+ ref,
136
+ className: "relative flex h-10 w-10 shrink-0 cursor-pointer select-none items-center justify-center overflow-hidden rounded-full border border-gray-200 bg-gray-100 transition-colors hover:border-gray-300 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-950 focus-visible:ring-offset-2",
137
+ ...props
138
+ }
139
+ ));
140
+ Avatar.displayName = "Avatar";
141
+ var AvatarImage = React2.forwardRef(({ src, alt, className, ...props }, ref) => /* @__PURE__ */ jsx2(
142
+ "img",
143
+ {
144
+ ref,
145
+ src: src || void 0,
146
+ alt: alt || "",
147
+ className: `aspect-square h-full w-full rounded-full object-cover ${className}`,
148
+ ...props
149
+ }
150
+ ));
151
+ AvatarImage.displayName = "AvatarImage";
152
+ var AvatarFallback = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
153
+ "div",
154
+ {
155
+ ref,
156
+ className: "flex h-full w-full items-center justify-center rounded-full bg-muted",
157
+ ...props
158
+ }
159
+ ));
160
+ AvatarFallback.displayName = "AvatarFallback";
161
+
162
+ // src/components/badge.tsx
163
+ import { cva as cva2 } from "class-variance-authority";
164
+ import { jsx as jsx3 } from "react/jsx-runtime";
165
+ var badgeVariants = cva2(
166
+ "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
167
+ {
168
+ variants: {
169
+ variant: {
170
+ default: "border-transparent bg-primary text-primary-foreground hover:bg-primary-hover",
171
+ secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary-hover",
172
+ destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive-hover",
173
+ muted: "border-transparent bg-muted text-muted-foreground hover:bg-muted/80",
174
+ outline: "text-foreground border-border hover:bg-muted",
175
+ ghost: "border-transparent hover:bg-muted",
176
+ brand: "border-transparent bg-brand-primary text-brand-primary-foreground hover:bg-brand-primary-dark",
177
+ "brand-secondary": "border-transparent bg-brand-secondary text-brand-secondary-foreground hover:opacity-90",
178
+ success: "border-transparent bg-success text-success-foreground",
179
+ warning: "border-transparent bg-warning text-warning-foreground",
180
+ info: "border-transparent bg-info text-info-foreground",
181
+ error: "border-transparent bg-error text-error-foreground"
182
+ },
183
+ size: {
184
+ default: "px-2 py-0.5 text-xs",
185
+ sm: "px-1.5 py-0 text-[10px]",
186
+ lg: "px-3 py-1 text-sm",
187
+ xl: "px-4 py-1.5 text-base"
188
+ },
189
+ radius: {
190
+ default: "rounded-full",
191
+ sm: "rounded-sm",
192
+ md: "rounded-md",
193
+ lg: "rounded-lg",
194
+ full: "rounded-full",
195
+ none: "rounded-none"
196
+ }
197
+ },
198
+ defaultVariants: {
199
+ variant: "default",
200
+ size: "default",
201
+ radius: "default"
202
+ }
203
+ }
204
+ );
205
+ function Badge({ className, variant, size, radius, ...props }) {
206
+ return /* @__PURE__ */ jsx3(
207
+ "div",
208
+ {
209
+ className: cn(badgeVariants({ variant, size, radius, className })),
210
+ ...props
211
+ }
212
+ );
213
+ }
214
+
215
+ // src/providers/brand-provider.tsx
216
+ import * as React3 from "react";
217
+ import { jsx as jsx4 } from "react/jsx-runtime";
218
+ var BrandContext = React3.createContext(
219
+ void 0
220
+ );
221
+ function BrandProvider({
222
+ children,
223
+ defaultBrand = "lsts",
224
+ brands = ["lsts", "tlao"],
225
+ storageKey = "ui-brand"
226
+ }) {
227
+ const [brand, setBrandState] = React3.useState(defaultBrand);
228
+ React3.useEffect(() => {
229
+ const stored = localStorage.getItem(storageKey);
230
+ if (stored && brands.includes(stored)) {
231
+ setBrandState(stored);
232
+ }
233
+ }, [storageKey]);
234
+ const setBrand = React3.useCallback(
235
+ (newBrand) => {
236
+ setBrandState(newBrand);
237
+ if (typeof window !== "undefined") {
238
+ localStorage.setItem(storageKey, newBrand);
239
+ document.documentElement.setAttribute("data-brand", newBrand);
240
+ }
241
+ },
242
+ [storageKey]
243
+ );
244
+ React3.useEffect(() => {
245
+ if (typeof window !== "undefined") {
246
+ document.documentElement.setAttribute("data-brand", brand);
247
+ }
248
+ }, [brand]);
249
+ const value = React3.useMemo(
250
+ () => ({ brand, setBrand, brands }),
251
+ [brand, setBrand, brands]
252
+ );
253
+ return /* @__PURE__ */ jsx4(BrandContext.Provider, { value, children });
254
+ }
255
+ function useBrand() {
256
+ const context = React3.useContext(BrandContext);
257
+ if (context === void 0) {
258
+ throw new Error("useBrand must be used within a BrandProvider");
259
+ }
260
+ return context;
261
+ }
262
+
263
+ // src/components/button.tsx
264
+ import * as React4 from "react";
265
+ import { Slot } from "@radix-ui/react-slot";
266
+ import { cva as cva3 } from "class-variance-authority";
267
+ import { Loader2 } from "lucide-react";
268
+ import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
269
+ var buttonVariants = cva3(
270
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all duration-fast focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
271
+ {
272
+ variants: {
273
+ variant: {
274
+ default: "bg-primary text-primary-foreground hover:bg-primary-hover active:bg-primary-active shadow-sm",
275
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive-hover shadow-sm",
276
+ outline: "border border-input bg-background hover:bg-background-hover hover:text-accent-foreground shadow-sm",
277
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover shadow-sm",
278
+ ghost: "hover:bg-background-hover hover:text-foreground",
279
+ link: "text-primary underline-offset-4 hover:underline",
280
+ brand: "bg-brand-primary text-brand-primary-foreground hover:bg-brand-primary-dark shadow-sm",
281
+ "brand-secondary": "bg-brand-secondary text-brand-secondary-foreground hover:opacity-90 shadow-sm",
282
+ "brand-ghost": "hover:bg-brand-primary/10 text-brand-primary hover:text-brand-primary"
283
+ },
284
+ size: {
285
+ default: "h-9 px-4 py-2",
286
+ xs: "h-7 px-2 text-xs",
287
+ sm: "h-8 px-3 text-xs",
288
+ lg: "h-10 px-8",
289
+ xl: "h-12 px-8 text-base",
290
+ "2xl": "h-14 px-10 text-base",
291
+ icon: "h-9 w-9 p-0",
292
+ "icon-sm": "h-8 w-8 p-0",
293
+ "icon-lg": "h-10 w-10 p-0"
294
+ },
295
+ radius: {
296
+ default: "rounded-md",
297
+ none: "rounded-none",
298
+ sm: "rounded-sm",
299
+ lg: "rounded-lg",
300
+ xl: "rounded-xl",
301
+ "2xl": "rounded-2xl",
302
+ full: "rounded-full"
303
+ }
304
+ },
305
+ defaultVariants: {
306
+ variant: "default",
307
+ size: "default",
308
+ radius: "default"
309
+ }
310
+ }
311
+ );
312
+ var Button = React4.forwardRef(
313
+ ({
314
+ className,
315
+ variant,
316
+ size,
317
+ radius,
318
+ asChild = false,
319
+ loading = false,
320
+ leftIcon,
321
+ rightIcon,
322
+ children,
323
+ disabled,
324
+ ...props
325
+ }, ref) => {
326
+ const Comp = asChild ? Slot : "button";
327
+ const content = loading ? /* @__PURE__ */ jsxs2(Fragment, { children: [
328
+ /* @__PURE__ */ jsx5(Loader2, { className: "animate-spin" }),
329
+ children
330
+ ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
331
+ leftIcon,
332
+ children,
333
+ rightIcon
334
+ ] });
335
+ return /* @__PURE__ */ jsx5(
336
+ Comp,
337
+ {
338
+ className: cn(buttonVariants({ variant, size, radius, className })),
339
+ ref,
340
+ disabled: disabled || loading,
341
+ ...props,
342
+ children: content
343
+ }
344
+ );
345
+ }
346
+ );
347
+ Button.displayName = "Button";
348
+
349
+ // src/components/brand-switcher.tsx
350
+ import { Check, Building2, Landmark } from "lucide-react";
351
+ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
352
+ var defaultBrandOptions = [
353
+ {
354
+ value: "lsts",
355
+ label: "LSTS",
356
+ description: "LSTech Solutions",
357
+ icon: /* @__PURE__ */ jsx6(Building2, { className: "h-4 w-4" })
358
+ },
359
+ {
360
+ value: "tlao",
361
+ label: "TL\xC1O",
362
+ description: "TL\xC1O Project",
363
+ icon: /* @__PURE__ */ jsx6(Landmark, { className: "h-4 w-4" })
364
+ }
365
+ ];
366
+ function BrandSwitcher({
367
+ options = defaultBrandOptions,
368
+ variant = "buttons",
369
+ size = "md",
370
+ className,
371
+ showIcons = true,
372
+ showDescription = false
373
+ }) {
374
+ const { brand, setBrand } = useBrand();
375
+ const sizeClasses = {
376
+ sm: "h-7 px-2 text-xs",
377
+ md: "h-9 px-3 text-sm",
378
+ lg: "h-10 px-4 text-base"
379
+ };
380
+ if (variant === "buttons") {
381
+ return /* @__PURE__ */ jsx6("div", { className: cn("flex items-center gap-1", className), children: options.map((option) => {
382
+ const isActive = brand === option.value;
383
+ return /* @__PURE__ */ jsxs3(
384
+ Button,
385
+ {
386
+ variant: isActive ? "brand" : "ghost",
387
+ size: "sm",
388
+ onClick: () => setBrand(option.value),
389
+ className: cn(
390
+ "gap-2",
391
+ sizeClasses[size],
392
+ isActive && "ring-2 ring-ring ring-offset-2"
393
+ ),
394
+ children: [
395
+ showIcons && option.icon,
396
+ /* @__PURE__ */ jsx6("span", { children: option.label }),
397
+ isActive && /* @__PURE__ */ jsx6(Check, { className: "h-3 w-3 ml-1" })
398
+ ]
399
+ },
400
+ option.value
401
+ );
402
+ }) });
403
+ }
404
+ if (variant === "cards") {
405
+ return /* @__PURE__ */ jsx6("div", { className: cn("grid gap-3", className), children: options.map((option) => {
406
+ const isActive = brand === option.value;
407
+ return /* @__PURE__ */ jsxs3(
408
+ "button",
409
+ {
410
+ onClick: () => setBrand(option.value),
411
+ className: cn(
412
+ "flex items-start gap-3 rounded-lg border p-4 text-left transition-all duration-fast",
413
+ "hover:bg-muted/50 focus:outline-none focus:ring-2 focus:ring-ring",
414
+ isActive && "border-brand-primary bg-brand-primary/5"
415
+ ),
416
+ children: [
417
+ showIcons && /* @__PURE__ */ jsx6(
418
+ "div",
419
+ {
420
+ className: cn(
421
+ "flex h-10 w-10 shrink-0 items-center justify-center rounded-md",
422
+ isActive ? "bg-brand-primary text-brand-primary-foreground" : "bg-muted text-muted-foreground"
423
+ ),
424
+ children: option.icon
425
+ }
426
+ ),
427
+ /* @__PURE__ */ jsxs3("div", { className: "flex-1", children: [
428
+ /* @__PURE__ */ jsx6("div", { className: "font-medium", children: option.label }),
429
+ showDescription && option.description && /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: option.description })
430
+ ] }),
431
+ isActive && /* @__PURE__ */ jsx6(Check, { className: "h-5 w-5 text-brand-primary shrink-0" })
432
+ ]
433
+ },
434
+ option.value
435
+ );
436
+ }) });
437
+ }
438
+ return /* @__PURE__ */ jsx6(
439
+ "select",
440
+ {
441
+ value: brand,
442
+ onChange: (e) => setBrand(e.target.value),
443
+ className: cn(
444
+ "flex h-9 rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors",
445
+ "focus:outline-none focus:ring-1 focus:ring-ring",
446
+ className
447
+ ),
448
+ children: options.map((option) => /* @__PURE__ */ jsx6("option", { value: option.value, children: option.label }, option.value))
449
+ }
450
+ );
451
+ }
452
+
453
+ // src/components/card.tsx
454
+ import * as React5 from "react";
455
+ import { cva as cva4 } from "class-variance-authority";
456
+ import { jsx as jsx7 } from "react/jsx-runtime";
457
+ var cardVariants = cva4(
458
+ "rounded-lg border bg-card text-card-foreground shadow-sm transition-all duration-fast",
459
+ {
460
+ variants: {
461
+ variant: {
462
+ default: "",
463
+ elevated: "shadow-elevation-2 hover:shadow-elevation-3",
464
+ outline: "shadow-none",
465
+ ghost: "border-transparent bg-transparent shadow-none",
466
+ brand: "border-brand-primary/20 bg-brand-primary/5"
467
+ },
468
+ radius: {
469
+ default: "rounded-lg",
470
+ sm: "rounded-md",
471
+ lg: "rounded-xl",
472
+ xl: "rounded-2xl",
473
+ none: "rounded-none"
474
+ },
475
+ padding: {
476
+ default: "",
477
+ none: "",
478
+ sm: "p-4",
479
+ md: "p-6",
480
+ lg: "p-8"
481
+ }
482
+ },
483
+ defaultVariants: {
484
+ variant: "default",
485
+ radius: "default",
486
+ padding: "default"
487
+ }
488
+ }
489
+ );
490
+ var Card = React5.forwardRef(
491
+ ({ className, variant, radius, padding, ...props }, ref) => {
492
+ return /* @__PURE__ */ jsx7(
493
+ "div",
494
+ {
495
+ ref,
496
+ className: cn(cardVariants({ variant, radius, padding, className })),
497
+ ...props
498
+ }
499
+ );
500
+ }
501
+ );
502
+ Card.displayName = "Card";
503
+ var CardHeader = React5.forwardRef(({ className, ...props }, ref) => {
504
+ return /* @__PURE__ */ jsx7(
505
+ "div",
506
+ {
507
+ ref,
508
+ className: cn("flex flex-col space-y-1.5 p-6", className),
509
+ ...props
510
+ }
511
+ );
512
+ });
513
+ CardHeader.displayName = "CardHeader";
514
+ var CardTitle = React5.forwardRef(({ className, ...props }, ref) => {
515
+ return /* @__PURE__ */ jsx7(
516
+ "h3",
517
+ {
518
+ ref,
519
+ className: cn(
520
+ "text-2xl font-semibold leading-none tracking-tight",
521
+ className
522
+ ),
523
+ ...props
524
+ }
525
+ );
526
+ });
527
+ CardTitle.displayName = "CardTitle";
528
+ var CardDescription = React5.forwardRef(({ className, ...props }, ref) => {
529
+ return /* @__PURE__ */ jsx7(
530
+ "p",
531
+ {
532
+ ref,
533
+ className: cn("text-sm text-muted-foreground", className),
534
+ ...props
535
+ }
536
+ );
537
+ });
538
+ CardDescription.displayName = "CardDescription";
539
+ var CardContent = React5.forwardRef(({ className, ...props }, ref) => {
540
+ return /* @__PURE__ */ jsx7("div", { ref, className: cn("p-6 pt-0", className), ...props });
541
+ });
542
+ CardContent.displayName = "CardContent";
543
+ var CardFooter = React5.forwardRef(({ className, ...props }, ref) => {
544
+ return /* @__PURE__ */ jsx7(
545
+ "div",
546
+ {
547
+ ref,
548
+ className: cn("flex items-center p-6 pt-0", className),
549
+ ...props
550
+ }
551
+ );
552
+ });
553
+ CardFooter.displayName = "CardFooter";
554
+
555
+ // src/components/input.tsx
556
+ import * as React6 from "react";
557
+ import { cva as cva5 } from "class-variance-authority";
558
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
559
+ var inputVariants = cva5(
560
+ "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition-all duration-fast",
561
+ {
562
+ variants: {
563
+ variant: {
564
+ default: "",
565
+ filled: "bg-muted border-transparent",
566
+ ghost: "border-transparent bg-transparent",
567
+ brand: "focus-visible:ring-brand-primary/50"
568
+ },
569
+ size: {
570
+ default: "h-9 px-3 py-2",
571
+ sm: "h-8 px-2 py-1 text-xs",
572
+ lg: "h-10 px-4 py-2",
573
+ xl: "h-12 px-4 py-3 text-base"
574
+ },
575
+ radius: {
576
+ default: "rounded-md",
577
+ sm: "rounded-sm",
578
+ lg: "rounded-lg",
579
+ xl: "rounded-xl",
580
+ full: "rounded-full px-4",
581
+ none: "rounded-none"
582
+ },
583
+ state: {
584
+ default: "",
585
+ error: "border-error focus-visible:ring-error/50",
586
+ success: "border-success focus-visible:ring-success/50",
587
+ warning: "border-warning focus-visible:ring-warning/50"
588
+ }
589
+ },
590
+ defaultVariants: {
591
+ variant: "default",
592
+ size: "default",
593
+ radius: "default",
594
+ state: "default"
595
+ }
596
+ }
597
+ );
598
+ var Input = React6.forwardRef(
599
+ ({
600
+ className,
601
+ variant,
602
+ size: inputSize,
603
+ radius,
604
+ state,
605
+ leftIcon,
606
+ rightIcon,
607
+ type,
608
+ ...props
609
+ }, ref) => {
610
+ const input = /* @__PURE__ */ jsx8(
611
+ "input",
612
+ {
613
+ type,
614
+ className: cn(inputVariants({ variant, size: inputSize, radius, state, className })),
615
+ ref,
616
+ ...props
617
+ }
618
+ );
619
+ if (leftIcon || rightIcon) {
620
+ return /* @__PURE__ */ jsxs4("div", { className: "relative flex items-center", children: [
621
+ leftIcon && /* @__PURE__ */ jsx8("div", { className: "absolute left-3 text-muted-foreground pointer-events-none", children: leftIcon }),
622
+ /* @__PURE__ */ jsx8(
623
+ "input",
624
+ {
625
+ type,
626
+ className: cn(
627
+ inputVariants({ variant, size: inputSize, radius, state, className }),
628
+ leftIcon && "pl-10",
629
+ rightIcon && "pr-10"
630
+ ),
631
+ ref,
632
+ ...props
633
+ }
634
+ ),
635
+ rightIcon && /* @__PURE__ */ jsx8("div", { className: "absolute right-3 text-muted-foreground pointer-events-none", children: rightIcon })
636
+ ] });
637
+ }
638
+ return input;
639
+ }
640
+ );
641
+ Input.displayName = "Input";
642
+
643
+ // src/components/separator.tsx
644
+ import * as React7 from "react";
645
+ import { jsx as jsx9 } from "react/jsx-runtime";
646
+ var Separator = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
647
+ "hr",
648
+ {
649
+ ref,
650
+ className: cn("shrink-0 bg-border", className),
651
+ ...props
652
+ }
653
+ ));
654
+ Separator.displayName = "Separator";
655
+
656
+ // src/components/tabs.tsx
657
+ import * as React8 from "react";
658
+ import { jsx as jsx10 } from "react/jsx-runtime";
659
+ var Tabs = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
660
+ "div",
661
+ {
662
+ ref,
663
+ className: cn("inline-flex flex-col", className),
664
+ ...props
665
+ }
666
+ ));
667
+ Tabs.displayName = "Tabs";
668
+ var TabsList = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
669
+ "div",
670
+ {
671
+ ref,
672
+ role: "tablist",
673
+ className: cn(
674
+ "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
675
+ className
676
+ ),
677
+ ...props
678
+ }
679
+ ));
680
+ TabsList.displayName = "TabsList";
681
+ var TabsTrigger = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
682
+ "button",
683
+ {
684
+ ref,
685
+ className: cn(
686
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
687
+ className
688
+ ),
689
+ ...props
690
+ }
691
+ ));
692
+ TabsTrigger.displayName = "TabsTrigger";
693
+ var TabsContent = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx10(
694
+ "div",
695
+ {
696
+ ref,
697
+ className: cn(
698
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
699
+ className
700
+ ),
701
+ ...props
702
+ }
703
+ ));
704
+ TabsContent.displayName = "TabsContent";
705
+
706
+ // src/providers/theme-provider.tsx
707
+ import * as React9 from "react";
708
+ import { jsx as jsx11 } from "react/jsx-runtime";
709
+ var ThemeContext = React9.createContext(
710
+ void 0
711
+ );
712
+ function ThemeProvider({
713
+ children,
714
+ defaultTheme = "system",
715
+ storageKey = "ui-theme",
716
+ enableSystem = true,
717
+ disableTransitionOnChange = false
718
+ }) {
719
+ const [theme, setThemeState] = React9.useState(defaultTheme);
720
+ const [resolvedTheme, setResolvedTheme] = React9.useState("light");
721
+ React9.useEffect(() => {
722
+ const stored = localStorage.getItem(storageKey);
723
+ if (stored) {
724
+ setThemeState(stored);
725
+ }
726
+ }, [storageKey]);
727
+ const setTheme = React9.useCallback(
728
+ (newTheme) => {
729
+ setThemeState(newTheme);
730
+ if (typeof window !== "undefined") {
731
+ localStorage.setItem(storageKey, newTheme);
732
+ }
733
+ },
734
+ [storageKey]
735
+ );
736
+ React9.useEffect(() => {
737
+ if (typeof window === "undefined") return;
738
+ const root = document.documentElement;
739
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
740
+ const applyTheme = () => {
741
+ let resolved;
742
+ if (theme === "system" && enableSystem) {
743
+ resolved = mediaQuery.matches ? "dark" : "light";
744
+ } else {
745
+ resolved = theme === "dark" ? "dark" : "light";
746
+ }
747
+ setResolvedTheme(resolved);
748
+ if (disableTransitionOnChange) {
749
+ const css = document.createElement("style");
750
+ css.appendChild(
751
+ document.createTextNode(
752
+ "* { transition: none !important; }"
753
+ )
754
+ );
755
+ document.head.appendChild(css);
756
+ requestAnimationFrame(() => {
757
+ document.head.removeChild(css);
758
+ });
759
+ }
760
+ root.setAttribute("data-theme", resolved);
761
+ if (resolved === "dark") {
762
+ root.classList.add("dark");
763
+ } else {
764
+ root.classList.remove("dark");
765
+ }
766
+ };
767
+ applyTheme();
768
+ if (enableSystem && theme === "system") {
769
+ mediaQuery.addEventListener("change", applyTheme);
770
+ return () => mediaQuery.removeEventListener("change", applyTheme);
771
+ }
772
+ }, [theme, enableSystem, disableTransitionOnChange]);
773
+ const value = React9.useMemo(
774
+ () => ({ theme, setTheme, resolvedTheme }),
775
+ [theme, setTheme, resolvedTheme]
776
+ );
777
+ return /* @__PURE__ */ jsx11(ThemeContext.Provider, { value, children });
778
+ }
779
+ function useTheme() {
780
+ const context = React9.useContext(ThemeContext);
781
+ if (context === void 0) {
782
+ throw new Error("useTheme must be used within a ThemeProvider");
783
+ }
784
+ return context;
785
+ }
786
+
787
+ // src/components/theme-switcher.tsx
788
+ import { Sun, Moon, Monitor, Check as Check2 } from "lucide-react";
789
+ import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
790
+ var themeOptions = [
791
+ {
792
+ value: "light",
793
+ label: "Light",
794
+ description: "Always use light mode",
795
+ icon: /* @__PURE__ */ jsx12(Sun, { className: "h-4 w-4" })
796
+ },
797
+ {
798
+ value: "dark",
799
+ label: "Dark",
800
+ description: "Always use dark mode",
801
+ icon: /* @__PURE__ */ jsx12(Moon, { className: "h-4 w-4" })
802
+ },
803
+ {
804
+ value: "system",
805
+ label: "System",
806
+ description: "Follow system preference",
807
+ icon: /* @__PURE__ */ jsx12(Monitor, { className: "h-4 w-4" })
808
+ }
809
+ ];
810
+ function ThemeSwitcher({
811
+ variant = "segmented",
812
+ size = "md",
813
+ className,
814
+ showLabel = true,
815
+ showIcons = true
816
+ }) {
817
+ const { theme, setTheme, resolvedTheme } = useTheme();
818
+ const sizeClasses = {
819
+ sm: "h-7 px-2",
820
+ md: "h-9 px-3",
821
+ lg: "h-10 px-4"
822
+ };
823
+ if (variant === "buttons") {
824
+ return /* @__PURE__ */ jsx12("div", { className: cn("flex items-center gap-1", className), children: themeOptions.map((option) => {
825
+ const isActive = theme === option.value;
826
+ return /* @__PURE__ */ jsxs5(
827
+ Button,
828
+ {
829
+ variant: isActive ? "secondary" : "ghost",
830
+ size: "sm",
831
+ onClick: () => setTheme(option.value),
832
+ className: cn(
833
+ "gap-2",
834
+ sizeClasses[size],
835
+ isActive && "ring-2 ring-ring ring-offset-2"
836
+ ),
837
+ children: [
838
+ showIcons && option.icon,
839
+ showLabel && /* @__PURE__ */ jsx12("span", { children: option.label })
840
+ ]
841
+ },
842
+ option.value
843
+ );
844
+ }) });
845
+ }
846
+ if (variant === "segmented") {
847
+ return /* @__PURE__ */ jsx12(
848
+ "div",
849
+ {
850
+ className: cn(
851
+ "inline-flex items-center rounded-lg border bg-muted p-1",
852
+ className
853
+ ),
854
+ children: themeOptions.map((option) => {
855
+ const isActive = theme === option.value;
856
+ return /* @__PURE__ */ jsxs5(
857
+ "button",
858
+ {
859
+ onClick: () => setTheme(option.value),
860
+ className: cn(
861
+ "relative flex items-center justify-center gap-2 rounded-md px-3 py-1.5 text-sm font-medium transition-all duration-fast",
862
+ "hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
863
+ isActive ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:bg-muted"
864
+ ),
865
+ children: [
866
+ showIcons && option.icon,
867
+ showLabel && /* @__PURE__ */ jsx12("span", { children: option.label })
868
+ ]
869
+ },
870
+ option.value
871
+ );
872
+ })
873
+ }
874
+ );
875
+ }
876
+ if (variant === "cards") {
877
+ return /* @__PURE__ */ jsx12("div", { className: cn("grid gap-3", className), children: themeOptions.map((option) => {
878
+ const isActive = theme === option.value;
879
+ const isResolved = resolvedTheme === (option.value === "system" ? void 0 : option.value);
880
+ return /* @__PURE__ */ jsxs5(
881
+ "button",
882
+ {
883
+ onClick: () => setTheme(option.value),
884
+ className: cn(
885
+ "flex items-start gap-3 rounded-lg border p-4 text-left transition-all duration-fast",
886
+ "hover:bg-muted/50 focus:outline-none focus:ring-2 focus:ring-ring",
887
+ isActive && "border-primary bg-primary/5"
888
+ ),
889
+ children: [
890
+ showIcons && /* @__PURE__ */ jsx12(
891
+ "div",
892
+ {
893
+ className: cn(
894
+ "flex h-10 w-10 shrink-0 items-center justify-center rounded-md",
895
+ isActive ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
896
+ ),
897
+ children: option.icon
898
+ }
899
+ ),
900
+ /* @__PURE__ */ jsxs5("div", { className: "flex-1", children: [
901
+ /* @__PURE__ */ jsxs5("div", { className: "font-medium flex items-center gap-2", children: [
902
+ option.label,
903
+ option.value === "system" && /* @__PURE__ */ jsxs5("span", { className: "text-xs text-muted-foreground", children: [
904
+ "(",
905
+ resolvedTheme,
906
+ ")"
907
+ ] })
908
+ ] }),
909
+ option.description && /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: option.description })
910
+ ] }),
911
+ isActive && /* @__PURE__ */ jsx12(Check2, { className: "h-5 w-5 text-primary shrink-0" })
912
+ ]
913
+ },
914
+ option.value
915
+ );
916
+ }) });
917
+ }
918
+ return /* @__PURE__ */ jsx12(
919
+ "select",
920
+ {
921
+ value: theme,
922
+ onChange: (e) => setTheme(e.target.value),
923
+ className: cn(
924
+ "flex h-9 rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors",
925
+ "focus:outline-none focus:ring-1 focus:ring-ring",
926
+ className
927
+ ),
928
+ children: themeOptions.map((option) => /* @__PURE__ */ jsx12("option", { value: option.value, children: option.label }, option.value))
929
+ }
930
+ );
931
+ }
932
+ export {
933
+ Alert,
934
+ AlertDescription,
935
+ AlertTitle,
936
+ Avatar,
937
+ AvatarFallback,
938
+ AvatarImage,
939
+ Badge,
940
+ BrandProvider,
941
+ BrandSwitcher,
942
+ Button,
943
+ Card,
944
+ CardContent,
945
+ CardDescription,
946
+ CardFooter,
947
+ CardHeader,
948
+ CardTitle,
949
+ Input,
950
+ Separator,
951
+ Tabs,
952
+ TabsContent,
953
+ TabsList,
954
+ TabsTrigger,
955
+ ThemeProvider,
956
+ ThemeSwitcher,
957
+ alertVariants,
958
+ badgeVariants,
959
+ buttonVariants,
960
+ cardVariants,
961
+ cn,
962
+ defaultBrandOptions,
963
+ formatCurrency,
964
+ formatDate,
965
+ inputVariants,
966
+ themeOptions,
967
+ useBrand,
968
+ useTheme
969
+ };
970
+ //# sourceMappingURL=index.mjs.map