drivn 1.0.1

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,1667 @@
1
+ #!/usr/bin/env node
2
+ import {Command}from'commander';import*as e from'@clack/prompts';import l from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';var E={next:"Next.js",react:"React"};function A(t){let s=join(t,"package.json");if(!existsSync(s))throw new Error("package.json not found");let r=JSON.parse(readFileSync(s,"utf-8")),b={...r.dependencies,...r.devDependencies},d="react";b.next&&(d="next");let m=existsSync(join(t,"src")),f=existsSync(join(t,"tsconfig.json"));return {framework:d,srcDir:m,typescript:f}}var M="drivn.config.json";function V(t){let s=join(t,M);return existsSync(s)?JSON.parse(readFileSync(s,"utf-8")):null}function $(t,s){let r=join(t,M);writeFileSync(r,JSON.stringify(s,null,2));}function me(t){existsSync(t)||mkdirSync(t,{recursive:true});}function p(t,s){me(dirname(t)),writeFileSync(t,s);}function z(t){return readFileSync(t,"utf-8")}function v(t){return existsSync(t)}var R=`@import "tailwindcss";
3
+
4
+ :root {
5
+ /* Surfaces */
6
+ --background: hsl(0 0% 100%);
7
+ --foreground: hsl(222 47% 11%);
8
+ --card: hsl(0 0% 100%);
9
+ --card-foreground: hsl(222 47% 11%);
10
+ --muted: hsl(212 30% 93.5%);
11
+ --muted-foreground: hsl(220 17% 17%);
12
+ --accent: hsl(210 40% 96%);
13
+ --accent-foreground: hsl(222 47% 11%);
14
+
15
+ /* Brand */
16
+ --primary: hsl(239 84% 67%);
17
+ --primary-light: hsl(239 84% 74%);
18
+ --primary-foreground: hsl(0 0% 100%);
19
+ --secondary: hsl(189 90% 36%);
20
+ --secondary-foreground: hsl(0 0% 100%);
21
+
22
+ /* Semantic */
23
+ --success: hsl(142 76% 36%);
24
+ --success-foreground: hsl(0 0% 100%);
25
+ --destructive: hsl(0 72% 51%);
26
+ --destructive-foreground: hsl(0 0% 100%);
27
+
28
+ /* Borders & Inputs */
29
+ --border: hsl(214 32% 91%);
30
+ --input: hsl(214 32% 91%);
31
+
32
+ /* Special Surfaces */
33
+ --overlay: hsl(0 0% 0% / 0.18);
34
+ }
35
+
36
+ @theme inline {
37
+ /* Surfaces */
38
+ --color-background: var(--background);
39
+ --color-foreground: var(--foreground);
40
+ --color-card: var(--card);
41
+ --color-card-foreground: var(--card-foreground);
42
+ --color-muted: var(--muted);
43
+ --color-muted-foreground: var(--muted-foreground);
44
+ --color-accent: var(--accent);
45
+ --color-accent-foreground: var(--accent-foreground);
46
+
47
+ /* Brand */
48
+ --color-primary: var(--primary);
49
+ --color-primary-light: var(--primary-light);
50
+ --color-primary-foreground: var(--primary-foreground);
51
+ --color-secondary: var(--secondary);
52
+ --color-secondary-foreground: var(--secondary-foreground);
53
+
54
+ /* Semantic */
55
+ --color-destructive: var(--destructive);
56
+ --color-destructive-foreground: var(--destructive-foreground);
57
+ --color-success: var(--success);
58
+ --color-success-foreground: var(--success-foreground);
59
+
60
+ /* Borders & Inputs */
61
+ --color-border: var(--border);
62
+ --color-input: var(--input);
63
+
64
+ /* Special Surfaces */
65
+ --color-overlay: var(--overlay);
66
+ }
67
+
68
+ body {
69
+ background: var(--color-background);
70
+ color: var(--color-foreground);
71
+ font-family: system-ui, -apple-system, sans-serif;
72
+ }
73
+ `,O=`
74
+ /* Drivn Dark/Light Theme */
75
+ :root,
76
+ [data-theme="dark"] {
77
+ /* Surfaces */
78
+ --background: hsl(240 6% 4%);
79
+ --foreground: hsl(0 0% 98%);
80
+ --card: hsl(240 5% 7%);
81
+ --card-foreground: hsl(0 0% 98%);
82
+ --muted: hsl(240 4% 16%);
83
+ --muted-foreground: hsl(220, 17%, 83%);
84
+ --accent: hsl(240 4% 10%);
85
+ --accent-foreground: hsl(0 0% 98%);
86
+
87
+ /* Brand */
88
+ --primary: hsl(239 84% 67%);
89
+ --primary-light: hsl(239 84% 74%);
90
+ --primary-foreground: hsl(0 0% 100%);
91
+ --secondary: hsl(189 94% 53%);
92
+ --secondary-foreground: hsl(0 0% 100%);
93
+
94
+ /* Semantic */
95
+ --success: hsl(142 71% 59%);
96
+ --success-foreground: hsl(0 0% 100%);
97
+ --destructive: hsl(0 84% 60%);
98
+ --destructive-foreground: hsl(0 0% 100%);
99
+
100
+ /* Borders & Inputs */
101
+ --border: hsl(240 4% 16%);
102
+ --input: hsl(240 4% 16%);
103
+
104
+ /* Special Surfaces */
105
+ --overlay: hsl(0 0% 0% / 0.5);
106
+ }
107
+
108
+ [data-theme="light"] {
109
+ /* Surfaces */
110
+ --background: hsl(0 0% 100%);
111
+ --foreground: hsl(222 47% 11%);
112
+ --card: hsl(0 0% 100%);
113
+ --card-foreground: hsl(222 47% 11%);
114
+ --muted: hsl(212 30% 93.5%);
115
+ --muted-foreground: hsl(220 17% 17%);
116
+ --accent: hsl(210 40% 96%);
117
+ --accent-foreground: hsl(222 47% 11%);
118
+
119
+ /* Brand */
120
+ --primary: hsl(239 84% 67%);
121
+ --primary-light: hsl(239 84% 74%);
122
+ --primary-foreground: hsl(0 0% 100%);
123
+ --secondary: hsl(189 90% 36%);
124
+ --secondary-foreground: hsl(0 0% 100%);
125
+
126
+ /* Semantic */
127
+ --success: hsl(142 76% 36%);
128
+ --success-foreground: hsl(0 0% 100%);
129
+ --destructive: hsl(0 72% 51%);
130
+ --destructive-foreground: hsl(0 0% 100%);
131
+
132
+ /* Borders & Inputs */
133
+ --border: hsl(214 32% 91%);
134
+ --input: hsl(214 32% 91%);
135
+
136
+ /* Special Surfaces */
137
+ --overlay: hsl(0 0% 0% / 0.18);
138
+ }
139
+ `;var ge=`import { type ClassValue, clsx } from 'clsx'
140
+ import { twMerge } from 'tailwind-merge'
141
+
142
+ export function cn(...inputs: ClassValue[]) {
143
+ return twMerge(clsx(inputs))
144
+ }
145
+ `,he=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function ve(t){for(let s of he)if(v(join(t,s)))return s;return null}async function H(){let t=process.cwd();console.log(""),console.log(l.bgCyan(l.bold(l.black(" Drivn "))));let s;try{s=A(t),e.log.success(`Detected ${l.cyan(E[s.framework])}`);}catch{e.log.error("No package.json found. Run this command in a project directory."),e.outro("Setup cancelled"),process.exit(1);}if(v(join(t,"drivn.config.json"))){let a=await e.confirm({message:"Config already exists. Overwrite?",initialValue:false});(e.isCancel(a)||!a)&&(e.cancel("Setup cancelled"),process.exit(0));}let r=s.srcDir?"src/components/ui":"components/ui",b=s.srcDir?"src/utils":"utils",d=await e.group({components:()=>e.text({message:"Where should components be installed?",placeholder:r,defaultValue:r}),utils:()=>e.text({message:"Where should utilities be placed?",placeholder:b,defaultValue:b})},{onCancel:()=>{e.cancel("Setup cancelled"),process.exit(0);}}),m={framework:s.framework,typescript:s.typescript,paths:{components:d.components,utils:d.utils},installed:[]},f=s.typescript?"ts":"js",g=join(t,d.utils,`cn.${f}`);v(g)||p(g,ge);let h=ve(t);if(h){let a=await e.confirm({message:`Found ${l.cyan(h)}. Add Drivn color tokens?`,initialValue:true});!e.isCancel(a)&&a&&(p(join(t,h),R),m.paths.globals=h,e.log.success(`Color tokens written to ${l.cyan(h)}`));}else {let a=s.srcDir?"src/styles/globals.css":"styles/globals.css",x=await e.text({message:"Where should the globals CSS file be created?",placeholder:a,defaultValue:a});e.isCancel(x)||(p(join(t,x),R),m.paths.globals=x,e.log.success(`Color tokens written to ${l.cyan(x)}`));}$(t,m);let y=e.spinner();y.start("Installing dependencies");try{execSync("npm install clsx tailwind-merge lucide-react",{cwd:t,stdio:"ignore"}),y.stop("Dependencies installed");}catch{y.stop("Failed to install dependencies"),e.log.warn("Run manually: npm install clsx tailwind-merge lucide-react");}e.log.info(`Add components with: ${l.cyan("npx drivn add button")}`),e.log.info(`Add dark/light theme: ${l.cyan("npx drivn add theme")}`),e.outro("Drivn initialized");}var F=`'use client'
146
+
147
+ import { ThemeProvider as NextThemesProvider } from 'next-themes'
148
+
149
+ export function ThemeProvider({
150
+ children,
151
+ }: {
152
+ children: React.ReactNode
153
+ }) {
154
+ return (
155
+ <NextThemesProvider
156
+ attribute="data-theme"
157
+ defaultTheme="dark"
158
+ disableTransitionOnChange={false}
159
+ >
160
+ {children}
161
+ </NextThemesProvider>
162
+ )
163
+ }
164
+ `;var _=`'use client'
165
+
166
+ import * as React from 'react'
167
+ import { ChevronDown } from 'lucide-react'
168
+ import { cn } from '@/utils/cn'
169
+
170
+ const styles = {
171
+ base: 'w-full divide-y divide-border border-y border-border',
172
+ trigger: cn(
173
+ 'flex items-center justify-between w-full py-4',
174
+ 'text-sm font-medium text-foreground',
175
+ 'hover:text-foreground/80 transition-colors cursor-pointer'
176
+ ),
177
+ icon: cn(
178
+ 'w-4 h-4 text-muted-foreground',
179
+ 'transition-transform duration-200'
180
+ ),
181
+ panel: 'grid transition-[grid-template-rows] duration-200',
182
+ content: 'overflow-hidden text-sm text-muted-foreground',
183
+ }
184
+
185
+ interface AccordionCtx {
186
+ openItem: string | null
187
+ toggle: (value: string) => void
188
+ }
189
+
190
+ const Ctx = React.createContext<AccordionCtx | null>(null)
191
+ const ItemCtx = React.createContext<string | null>(null)
192
+
193
+ function useAccordion() {
194
+ const ctx = React.useContext(Ctx)
195
+ if (!ctx) throw new Error('Accordion compound used outside <Accordion>')
196
+ return ctx
197
+ }
198
+
199
+ function useItemValue() {
200
+ const value = React.useContext(ItemCtx)
201
+ if (!value) throw new Error(
202
+ 'Accordion sub-component used outside <Accordion.Item>'
203
+ )
204
+ return value
205
+ }
206
+
207
+ function AccordionRoot({
208
+ children,
209
+ defaultValue,
210
+ className,
211
+ }: {
212
+ children: React.ReactNode
213
+ defaultValue?: string
214
+ className?: string
215
+ }) {
216
+ const [openItem, setOpenItem] = React.useState<string | null>(
217
+ defaultValue ?? null
218
+ )
219
+ const toggle = React.useCallback(
220
+ (value: string) =>
221
+ setOpenItem((prev) => (prev === value ? null : value)),
222
+ []
223
+ )
224
+
225
+ return (
226
+ <Ctx.Provider value={{ openItem, toggle }}>
227
+ <div className={cn(styles.base, className)}>
228
+ {children}
229
+ </div>
230
+ </Ctx.Provider>
231
+ )
232
+ }
233
+
234
+ function Item({
235
+ value,
236
+ children,
237
+ className,
238
+ }: {
239
+ value: string
240
+ children: React.ReactNode
241
+ className?: string
242
+ }) {
243
+ return (
244
+ <ItemCtx.Provider value={value}>
245
+ <div className={className}>{children}</div>
246
+ </ItemCtx.Provider>
247
+ )
248
+ }
249
+
250
+ function Trigger({
251
+ children,
252
+ className,
253
+ }: {
254
+ children: React.ReactNode
255
+ className?: string
256
+ }) {
257
+ const { openItem, toggle } = useAccordion()
258
+ const value = useItemValue()
259
+ const isOpen = openItem === value
260
+ return (
261
+ <button
262
+ className={cn(styles.trigger, className)}
263
+ onClick={() => toggle(value)}
264
+ >
265
+ {children}
266
+ <ChevronDown className={cn(styles.icon, isOpen && 'rotate-180')} />
267
+ </button>
268
+ )
269
+ }
270
+
271
+ function Content({
272
+ children,
273
+ className,
274
+ }: {
275
+ children: React.ReactNode
276
+ className?: string
277
+ }) {
278
+ const { openItem } = useAccordion()
279
+ const value = useItemValue()
280
+ const isOpen = openItem === value
281
+ return (
282
+ <div
283
+ className={styles.panel}
284
+ style={{ gridTemplateRows: isOpen ? '1fr' : '0fr' }}
285
+ >
286
+ <div className={cn(styles.content, className)}>
287
+ <div className="pb-4">{children}</div>
288
+ </div>
289
+ </div>
290
+ )
291
+ }
292
+
293
+ export const Accordion = Object.assign(AccordionRoot, {
294
+ Item,
295
+ Trigger,
296
+ Content,
297
+ })
298
+ `;var U=`import * as React from 'react'
299
+ import { cn } from '@/utils/cn'
300
+
301
+ const styles = {
302
+ base: 'flex gap-3 p-4 rounded-[10px] border text-sm',
303
+ variants: {
304
+ default: 'bg-accent/50 border-border text-foreground',
305
+ info: 'bg-primary/10 border-primary/20 text-primary-light',
306
+ success: 'bg-success/10 border-success/20 text-success',
307
+ destructive: 'bg-destructive/10 border-destructive/20 text-destructive',
308
+ },
309
+ title: 'font-semibold mb-1',
310
+ description: 'text-sm opacity-90',
311
+ }
312
+
313
+ type IconProp =
314
+ | React.ComponentType<{ className?: string }>
315
+ | React.ReactElement
316
+
317
+ interface AlertProps {
318
+ variant?: keyof typeof styles.variants
319
+ icon?: IconProp
320
+ title?: string
321
+ className?: string
322
+ children: React.ReactNode
323
+ }
324
+
325
+ export function Alert({
326
+ variant = 'default',
327
+ icon: Icon,
328
+ title,
329
+ className,
330
+ children,
331
+ }: AlertProps) {
332
+ return (
333
+ <div className={cn(styles.base, styles.variants[variant], className)}>
334
+ {Icon && (
335
+ <span className="flex-shrink-0 mt-0.5">
336
+ {React.isValidElement(Icon)
337
+ ? Icon
338
+ : <Icon />}
339
+ </span>
340
+ )}
341
+ <div>
342
+ {title && <p className={styles.title}>{title}</p>}
343
+ <div className={styles.description}>{children}</div>
344
+ </div>
345
+ </div>
346
+ )
347
+ }
348
+ `;var G=`import * as React from 'react'
349
+ import { cn } from '@/utils/cn'
350
+
351
+ const styles = {
352
+ base: cn(
353
+ 'relative inline-flex items-center justify-center',
354
+ 'rounded-full overflow-hidden',
355
+ 'bg-gradient-to-br from-primary to-secondary'
356
+ ),
357
+ sizes: {
358
+ sm: 'w-8 h-8 text-xs',
359
+ md: 'w-10 h-10 text-sm',
360
+ lg: 'w-12 h-12 text-base',
361
+ xl: 'w-16 h-16 text-lg',
362
+ },
363
+ }
364
+
365
+ interface AvatarProps {
366
+ src?: string
367
+ alt?: string
368
+ fallback?: string
369
+ size?: keyof typeof styles.sizes
370
+ className?: string
371
+ }
372
+
373
+ export function Avatar({
374
+ src,
375
+ alt,
376
+ fallback,
377
+ size = 'md',
378
+ className,
379
+ }: AvatarProps) {
380
+ return (
381
+ <div className={cn(styles.base, styles.sizes[size], className)}>
382
+ {src ? (
383
+ <img src={src} alt={alt} className="w-full h-full object-cover" />
384
+ ) : (
385
+ <span className="font-medium text-primary-foreground">
386
+ {fallback?.slice(0, 2).toUpperCase()}
387
+ </span>
388
+ )}
389
+ </div>
390
+ )
391
+ }
392
+ `;var W=`import * as React from 'react'
393
+ import { cn } from '@/utils/cn'
394
+
395
+ const styles = {
396
+ base: cn(
397
+ 'inline-flex items-center gap-1.5 px-2.5 py-0.5',
398
+ 'text-xs font-semibold rounded-full'
399
+ ),
400
+ variants: {
401
+ default: 'bg-primary/15 text-primary-light border border-primary/20',
402
+ secondary: 'bg-secondary/15 text-secondary border border-secondary/30',
403
+ success: 'bg-success/15 text-success border border-success/20',
404
+ outline: 'border border-border text-muted-foreground',
405
+ destructive: 'bg-destructive/15 text-destructive border border-destructive/20',
406
+ },
407
+ }
408
+
409
+ interface BadgeProps {
410
+ variant?: keyof typeof styles.variants
411
+ className?: string
412
+ children: React.ReactNode
413
+ }
414
+
415
+ export function Badge({ variant = 'default', className, children }: BadgeProps) {
416
+ return (
417
+ <span className={cn(styles.base, styles.variants[variant], className)}>
418
+ {children}
419
+ </span>
420
+ )
421
+ }
422
+ `;var K=`import * as React from 'react'
423
+ import { Loader2 } from 'lucide-react'
424
+ import { cn } from '@/utils/cn'
425
+
426
+ const styles = {
427
+ base: cn(
428
+ 'inline-flex items-center justify-center',
429
+ 'font-semibold transition-all duration-150',
430
+ 'cursor-pointer disabled:opacity-50',
431
+ 'disabled:pointer-events-none'
432
+ ),
433
+ sizes: {
434
+ sm: 'h-8 px-3 text-sm gap-1.5',
435
+ md: 'h-10 px-4 text-sm gap-2',
436
+ lg: 'h-12 px-6 text-base gap-2',
437
+ },
438
+ variants: {
439
+ default: 'bg-foreground text-background hover:scale-[1.02]',
440
+ secondary: cn(
441
+ 'bg-card text-foreground border border-border',
442
+ 'hover:bg-accent hover:border-border'
443
+ ),
444
+ outline: 'border border-border text-foreground hover:border-foreground/20',
445
+ destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
446
+ },
447
+ rounded: {
448
+ md: 'rounded-md',
449
+ full: 'rounded-full',
450
+ },
451
+ }
452
+
453
+ type IconProp =
454
+ | React.ComponentType<{ className?: string }>
455
+ | React.ReactElement
456
+
457
+ interface ButtonProps
458
+ extends React.ButtonHTMLAttributes<HTMLButtonElement> {
459
+ variant?: keyof typeof styles.variants
460
+ size?: keyof typeof styles.sizes
461
+ rounded?: keyof typeof styles.rounded
462
+ loading?: boolean
463
+ leftIcon?: IconProp
464
+ rightIcon?: IconProp
465
+ }
466
+
467
+ export const Button = React.forwardRef<
468
+ HTMLButtonElement,
469
+ ButtonProps
470
+ >(({
471
+ className,
472
+ variant = 'default',
473
+ size = 'md',
474
+ rounded = 'full',
475
+ loading,
476
+ disabled,
477
+ leftIcon: LeftIcon,
478
+ rightIcon: RightIcon,
479
+ children,
480
+ ...props
481
+ },
482
+ ref
483
+ ) => (
484
+ <button
485
+ ref={ref}
486
+ disabled={loading || disabled}
487
+ className={cn(
488
+ styles.base,
489
+ styles.sizes[size],
490
+ styles.variants[variant],
491
+ styles.rounded[rounded],
492
+ className
493
+ )}
494
+ {...props}
495
+ >
496
+ {loading && (
497
+ <Loader2 className="h-4 w-4 animate-spin" />
498
+ )}
499
+ {!loading && LeftIcon && (
500
+ React.isValidElement(LeftIcon)
501
+ ? LeftIcon
502
+ : <LeftIcon />
503
+ )}
504
+ {children}
505
+ {!loading && RightIcon && (
506
+ React.isValidElement(RightIcon)
507
+ ? RightIcon
508
+ : <RightIcon />
509
+ )}
510
+ </button>
511
+ )
512
+ )
513
+
514
+ Button.displayName = 'Button'
515
+ `;var X=`import * as React from 'react'
516
+ import { cn } from '@/utils/cn'
517
+
518
+ const styles = {
519
+ base: cn(
520
+ 'bg-card border border-border rounded-[20px]',
521
+ 'overflow-hidden transition-all duration-200'
522
+ ),
523
+ hover: 'hover:bg-accent hover:border-border hover:-translate-y-1',
524
+ preview: cn(
525
+ 'h-[140px] flex items-center justify-center',
526
+ 'border-b border-border p-6',
527
+ 'bg-[radial-gradient(ellipse_at_50%_50%,hsl(239_84%_67%_/_0.08)_0%,transparent_70%)]'
528
+ ),
529
+ info: 'p-5 flex justify-between items-center',
530
+ }
531
+
532
+ function CardRoot({
533
+ hover = true,
534
+ className,
535
+ children,
536
+ }: {
537
+ hover?: boolean
538
+ className?: string
539
+ children: React.ReactNode
540
+ }) {
541
+ return (
542
+ <div
543
+ className={cn(styles.base, hover && styles.hover, className)}
544
+ >
545
+ {children}
546
+ </div>
547
+ )
548
+ }
549
+
550
+ function Preview({
551
+ className,
552
+ children,
553
+ }: {
554
+ className?: string
555
+ children: React.ReactNode
556
+ }) {
557
+ return (
558
+ <div className={cn(styles.preview, className)}>
559
+ {children}
560
+ </div>
561
+ )
562
+ }
563
+
564
+ function Info({
565
+ className,
566
+ children,
567
+ }: {
568
+ className?: string
569
+ children: React.ReactNode
570
+ }) {
571
+ return (
572
+ <div className={cn(styles.info, className)}>
573
+ {children}
574
+ </div>
575
+ )
576
+ }
577
+
578
+ export const Card = Object.assign(CardRoot, {
579
+ Preview,
580
+ Info,
581
+ })
582
+ `;var J=`'use client'
583
+
584
+ import * as React from 'react'
585
+ import { Check } from 'lucide-react'
586
+ import { cn } from '@/utils/cn'
587
+
588
+ const styles = {
589
+ base: 'flex items-center gap-2 cursor-pointer',
590
+ box: cn(
591
+ 'w-4 h-4 rounded-[4px] border border-border',
592
+ 'transition-colors flex-shrink-0',
593
+ 'flex items-center justify-center'
594
+ ),
595
+ checked: 'bg-primary border-primary',
596
+ label: 'text-sm text-foreground select-none',
597
+ }
598
+
599
+ interface CheckboxProps
600
+ extends Omit<
601
+ React.InputHTMLAttributes<HTMLInputElement>,
602
+ 'type'
603
+ > {
604
+ label?: string
605
+ }
606
+
607
+ export const Checkbox = React.forwardRef<
608
+ HTMLInputElement,
609
+ CheckboxProps
610
+ >(({
611
+ className,
612
+ label,
613
+ checked,
614
+ defaultChecked,
615
+ onChange,
616
+ disabled,
617
+ ...props
618
+ },
619
+ ref
620
+ ) => {
621
+ const [internal, setInternal] = React.useState(
622
+ defaultChecked ?? false
623
+ )
624
+ const isControlled = checked !== undefined
625
+ const isChecked = isControlled ? checked : internal
626
+
627
+ return (
628
+ <label
629
+ className={cn(
630
+ styles.base,
631
+ disabled && 'opacity-50 cursor-default',
632
+ className
633
+ )}
634
+ >
635
+ <input
636
+ ref={ref}
637
+ type="checkbox"
638
+ className="sr-only"
639
+ checked={isChecked}
640
+ disabled={disabled}
641
+ onChange={(e) => {
642
+ if (!isControlled)
643
+ setInternal(e.target.checked)
644
+ onChange?.(e)
645
+ }}
646
+ {...props}
647
+ />
648
+ <span
649
+ className={cn(
650
+ styles.box,
651
+ isChecked && styles.checked
652
+ )}
653
+ >
654
+ {isChecked && (
655
+ <Check className="w-2.5 h-2.5 text-primary-foreground" />
656
+ )}
657
+ </span>
658
+ {label && (
659
+ <span className={styles.label}>{label}</span>
660
+ )}
661
+ </label>
662
+ )
663
+ }
664
+ )
665
+
666
+ Checkbox.displayName = 'Checkbox'
667
+ `;var q=`'use client'
668
+
669
+ import * as React from 'react'
670
+ import { X } from 'lucide-react'
671
+ import { cn } from '@/utils/cn'
672
+ import { Button } from '@/components/ui/button'
673
+
674
+ const styles = {
675
+ overlay: cn(
676
+ 'fixed inset-0 z-[200] flex items-center justify-center',
677
+ 'bg-overlay backdrop-blur-sm',
678
+ 'transition-opacity duration-150 ease-out'
679
+ ),
680
+ content: cn(
681
+ 'relative w-full max-w-md mx-4 p-6',
682
+ 'bg-card border border-border rounded-[20px]',
683
+ 'shadow-xl',
684
+ 'transition-[scale] duration-150 ease-out'
685
+ ),
686
+ title: 'text-lg font-semibold text-foreground mb-4',
687
+ close: cn(
688
+ 'absolute top-4 right-4 w-8 h-8',
689
+ 'flex items-center justify-center rounded-full',
690
+ 'text-muted-foreground hover:text-foreground',
691
+ 'hover:bg-accent transition-colors cursor-pointer'
692
+ ),
693
+ }
694
+
695
+ interface DialogCtx {
696
+ open: boolean
697
+ setOpen: (v: boolean) => void
698
+ }
699
+
700
+ const Ctx = React.createContext<DialogCtx | null>(null)
701
+
702
+ function useDialog() {
703
+ const ctx = React.useContext(Ctx)
704
+ if (!ctx) throw new Error('Dialog compound used outside <Dialog>')
705
+ return ctx
706
+ }
707
+
708
+ function DialogRoot({
709
+ children,
710
+ open: controlled,
711
+ onOpenChange,
712
+ }: {
713
+ children: React.ReactNode
714
+ open?: boolean
715
+ onOpenChange?: (open: boolean) => void
716
+ }) {
717
+ const [uncontrolled, setUncontrolled] = React.useState(false)
718
+ const open = controlled ?? uncontrolled
719
+ const setOpen = React.useCallback(
720
+ (v: boolean) => {
721
+ onOpenChange?.(v)
722
+ if (controlled === undefined) setUncontrolled(v)
723
+ },
724
+ [controlled, onOpenChange]
725
+ )
726
+
727
+ return <Ctx.Provider value={{ open, setOpen }}>{children}</Ctx.Provider>
728
+ }
729
+
730
+ function Trigger({
731
+ children,
732
+ className,
733
+ ...props
734
+ }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
735
+ const { setOpen } = useDialog()
736
+ return (
737
+ <Button
738
+ variant="outline"
739
+ rounded="md"
740
+ className={className}
741
+ onClick={() => setOpen(true)}
742
+ {...props}
743
+ >
744
+ {children}
745
+ </Button>
746
+ )
747
+ }
748
+
749
+ function Content({
750
+ children,
751
+ title,
752
+ className,
753
+ }: {
754
+ children: React.ReactNode
755
+ title?: string
756
+ className?: string
757
+ }) {
758
+ const { open, setOpen } = useDialog()
759
+
760
+ React.useEffect(() => {
761
+ if (!open) return
762
+ const onKey = (e: KeyboardEvent) => {
763
+ if (e.key === 'Escape') setOpen(false)
764
+ }
765
+ document.addEventListener('keydown', onKey)
766
+ document.body.style.overflow = 'hidden'
767
+ return () => {
768
+ document.removeEventListener('keydown', onKey)
769
+ document.body.style.overflow = ''
770
+ }
771
+ }, [open, setOpen])
772
+
773
+ return (
774
+ <div
775
+ className={cn(
776
+ styles.overlay,
777
+ open
778
+ ? 'opacity-100'
779
+ : 'opacity-0 pointer-events-none'
780
+ )}
781
+ onClick={(e) => {
782
+ if (e.target === e.currentTarget) setOpen(false)
783
+ }}
784
+ >
785
+ <div
786
+ className={cn(
787
+ styles.content,
788
+ open ? 'scale-100' : 'scale-95',
789
+ className
790
+ )}
791
+ >
792
+ {title && <h2 className={styles.title}>{title}</h2>}
793
+ {children}
794
+ </div>
795
+ </div>
796
+ )
797
+ }
798
+
799
+ function Close({ className }: { className?: string }) {
800
+ const { setOpen } = useDialog()
801
+ return (
802
+ <button
803
+ className={cn(styles.close, className)}
804
+ onClick={() => setOpen(false)}
805
+ >
806
+ <X className="w-3.5 h-3.5" />
807
+ </button>
808
+ )
809
+ }
810
+
811
+ export const Dialog = Object.assign(DialogRoot, {
812
+ Trigger,
813
+ Content,
814
+ Close,
815
+ })
816
+ `;var Q=`'use client'
817
+
818
+ import * as React from 'react'
819
+ import { cn } from '@/utils/cn'
820
+ import { Button } from '@/components/ui/button'
821
+
822
+ const styles = {
823
+ base: 'relative inline-flex',
824
+ content: cn(
825
+ 'absolute top-full mt-1 min-w-[180px] z-50',
826
+ 'bg-card border border-border rounded-[10px] p-1',
827
+ 'shadow-lg',
828
+ 'transition-[opacity,scale] duration-150 ease-out'
829
+ ),
830
+ item: cn(
831
+ 'flex items-center gap-2 w-full px-3 py-2',
832
+ 'text-sm text-foreground rounded-lg',
833
+ 'hover:bg-accent transition-colors cursor-pointer'
834
+ ),
835
+ destructive: 'text-destructive hover:bg-destructive/10',
836
+ group: 'py-1',
837
+ label: cn(
838
+ 'px-3 py-1.5 text-xs font-medium',
839
+ 'text-muted-foreground'
840
+ ),
841
+ separator: 'my-1 h-px bg-border',
842
+ align: {
843
+ left: 'left-0',
844
+ right: 'right-0',
845
+ },
846
+ }
847
+
848
+ interface DropdownCtx {
849
+ open: boolean
850
+ setOpen: (v: boolean) => void
851
+ align: keyof typeof styles.align
852
+ }
853
+
854
+ const Ctx = React.createContext<DropdownCtx | null>(null)
855
+
856
+ function useDropdown() {
857
+ const ctx = React.useContext(Ctx)
858
+ if (!ctx) throw new Error(
859
+ 'Dropdown compound used outside <Dropdown>'
860
+ )
861
+ return ctx
862
+ }
863
+
864
+ function DropdownRoot({
865
+ children,
866
+ align = 'left',
867
+ className,
868
+ }: {
869
+ children: React.ReactNode
870
+ align?: keyof typeof styles.align
871
+ className?: string
872
+ }) {
873
+ const [open, setOpen] = React.useState(false)
874
+ const ref = React.useRef<HTMLDivElement>(null)
875
+
876
+ const close = React.useCallback(
877
+ () => setOpen(false),
878
+ []
879
+ )
880
+
881
+ React.useEffect(() => {
882
+ const onClick = (e: MouseEvent) => {
883
+ if (!ref.current?.contains(e.target as Node))
884
+ close()
885
+ }
886
+ document.addEventListener('mousedown', onClick)
887
+ return () =>
888
+ document.removeEventListener('mousedown', onClick)
889
+ }, [close])
890
+
891
+ return (
892
+ <Ctx.Provider value={{ open, setOpen, align }}>
893
+ <div ref={ref} className={cn(styles.base, className)}>
894
+ {children}
895
+ </div>
896
+ </Ctx.Provider>
897
+ )
898
+ }
899
+
900
+ function Trigger({
901
+ children,
902
+ className,
903
+ ...props
904
+ }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
905
+ const { open, setOpen } = useDropdown()
906
+ return (
907
+ <Button
908
+ variant="outline"
909
+ rounded="md"
910
+ className={className}
911
+ onClick={() => setOpen(!open)}
912
+ {...props}
913
+ >
914
+ {children}
915
+ </Button>
916
+ )
917
+ }
918
+
919
+ function Content({
920
+ children,
921
+ className,
922
+ }: {
923
+ children: React.ReactNode
924
+ className?: string
925
+ }) {
926
+ const { open, align } = useDropdown()
927
+ return (
928
+ <div
929
+ className={cn(
930
+ styles.content,
931
+ styles.align[align],
932
+ open
933
+ ? 'opacity-100 scale-100'
934
+ : 'opacity-0 scale-95 pointer-events-none',
935
+ className
936
+ )}
937
+ >
938
+ {children}
939
+ </div>
940
+ )
941
+ }
942
+
943
+ type IconProp =
944
+ | React.ComponentType<{ className?: string }>
945
+ | React.ReactElement
946
+
947
+ function Item({
948
+ children,
949
+ onClick,
950
+ icon: Icon,
951
+ destructive,
952
+ className,
953
+ }: {
954
+ children: React.ReactNode
955
+ onClick?: () => void
956
+ icon?: IconProp
957
+ destructive?: boolean
958
+ className?: string
959
+ }) {
960
+ const { setOpen } = useDropdown()
961
+ return (
962
+ <button
963
+ className={cn(
964
+ styles.item,
965
+ destructive && styles.destructive,
966
+ className
967
+ )}
968
+ onClick={() => {
969
+ onClick?.()
970
+ setOpen(false)
971
+ }}
972
+ >
973
+ {Icon && (
974
+ React.isValidElement(Icon)
975
+ ? Icon
976
+ : <Icon className="w-4 h-4" />
977
+ )}
978
+ {children}
979
+ </button>
980
+ )
981
+ }
982
+
983
+ function Group({
984
+ children,
985
+ className,
986
+ }: {
987
+ children: React.ReactNode
988
+ className?: string
989
+ }) {
990
+ return (
991
+ <div className={cn(styles.group, className)}>
992
+ {children}
993
+ </div>
994
+ )
995
+ }
996
+
997
+ function Label({
998
+ children,
999
+ className,
1000
+ }: {
1001
+ children: React.ReactNode
1002
+ className?: string
1003
+ }) {
1004
+ return (
1005
+ <div className={cn(styles.label, className)}>
1006
+ {children}
1007
+ </div>
1008
+ )
1009
+ }
1010
+
1011
+ function DropdownSeparator({
1012
+ className,
1013
+ }: {
1014
+ className?: string
1015
+ }) {
1016
+ return (
1017
+ <div className={cn(styles.separator, className)} />
1018
+ )
1019
+ }
1020
+
1021
+ export const Dropdown = Object.assign(DropdownRoot, {
1022
+ Trigger,
1023
+ Content,
1024
+ Item,
1025
+ Group,
1026
+ Label,
1027
+ Separator: DropdownSeparator,
1028
+ })
1029
+ `;var Y=`import * as React from 'react'
1030
+ import { cn } from '@/utils/cn'
1031
+
1032
+ const styles = {
1033
+ base: cn(
1034
+ 'w-full h-10 px-4 border border-input rounded-[10px]',
1035
+ 'text-foreground placeholder:text-muted-foreground text-sm',
1036
+ 'focus:outline-none transition-colors',
1037
+ 'disabled:opacity-50 disabled:cursor-default'
1038
+ ),
1039
+ }
1040
+
1041
+ type InputProps = React.InputHTMLAttributes<HTMLInputElement>
1042
+
1043
+ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
1044
+ ({ className, ...props }, ref) => (
1045
+ <input ref={ref} className={cn(styles.base, className)} {...props} />
1046
+ )
1047
+ )
1048
+
1049
+ Input.displayName = 'Input'
1050
+ `;var Z=`'use client'
1051
+
1052
+ import * as React from 'react'
1053
+ import { cn } from '@/utils/cn'
1054
+ import { Button } from '@/components/ui/button'
1055
+
1056
+ const styles = {
1057
+ base: 'relative inline-flex',
1058
+ content: cn(
1059
+ 'absolute z-50 min-w-[200px] p-4',
1060
+ 'bg-card border border-border rounded-[12px]',
1061
+ 'shadow-lg',
1062
+ 'transition-[opacity,scale] duration-150 ease-out'
1063
+ ),
1064
+ positions: {
1065
+ top: 'bottom-full mb-2 left-1/2 -translate-x-1/2',
1066
+ bottom: 'top-full mt-2 left-1/2 -translate-x-1/2',
1067
+ left: 'right-full mr-2 top-1/2 -translate-y-1/2',
1068
+ right: 'left-full ml-2 top-1/2 -translate-y-1/2',
1069
+ },
1070
+ }
1071
+
1072
+ interface PopoverCtx {
1073
+ open: boolean
1074
+ setOpen: (v: boolean) => void
1075
+ position: keyof typeof styles.positions
1076
+ }
1077
+
1078
+ const Ctx = React.createContext<PopoverCtx | null>(null)
1079
+
1080
+ function usePopover() {
1081
+ const ctx = React.useContext(Ctx)
1082
+ if (!ctx) throw new Error('Popover compound used outside <Popover>')
1083
+ return ctx
1084
+ }
1085
+
1086
+ function PopoverRoot({
1087
+ children,
1088
+ position = 'bottom',
1089
+ className,
1090
+ }: {
1091
+ children: React.ReactNode
1092
+ position?: keyof typeof styles.positions
1093
+ className?: string
1094
+ }) {
1095
+ const [open, setOpen] = React.useState(false)
1096
+ const ref = React.useRef<HTMLDivElement>(null)
1097
+
1098
+ const close = React.useCallback(() => setOpen(false), [])
1099
+
1100
+ React.useEffect(() => {
1101
+ const onClick = (e: MouseEvent) => {
1102
+ if (!ref.current?.contains(e.target as Node)) close()
1103
+ }
1104
+ document.addEventListener('mousedown', onClick)
1105
+ return () => document.removeEventListener('mousedown', onClick)
1106
+ }, [close])
1107
+
1108
+ return (
1109
+ <Ctx.Provider value={{ open, setOpen, position }}>
1110
+ <div ref={ref} className={cn(styles.base, className)}>
1111
+ {children}
1112
+ </div>
1113
+ </Ctx.Provider>
1114
+ )
1115
+ }
1116
+
1117
+ function Trigger({
1118
+ children,
1119
+ className,
1120
+ ...props
1121
+ }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
1122
+ const { open, setOpen } = usePopover()
1123
+ return (
1124
+ <Button
1125
+ variant="outline"
1126
+ rounded="md"
1127
+ className={className}
1128
+ onClick={() => setOpen(!open)}
1129
+ {...props}
1130
+ >
1131
+ {children}
1132
+ </Button>
1133
+ )
1134
+ }
1135
+
1136
+ function Content({
1137
+ children,
1138
+ className,
1139
+ }: {
1140
+ children: React.ReactNode
1141
+ className?: string
1142
+ }) {
1143
+ const { open, position } = usePopover()
1144
+ return (
1145
+ <div
1146
+ className={cn(
1147
+ styles.content,
1148
+ styles.positions[position],
1149
+ open
1150
+ ? 'opacity-100 scale-100'
1151
+ : 'opacity-0 scale-95 pointer-events-none',
1152
+ className
1153
+ )}
1154
+ >
1155
+ {children}
1156
+ </div>
1157
+ )
1158
+ }
1159
+
1160
+ export const Popover = Object.assign(PopoverRoot, {
1161
+ Trigger,
1162
+ Content,
1163
+ })
1164
+ `;var ee=`import * as React from 'react'
1165
+ import { cn } from '@/utils/cn'
1166
+
1167
+ const styles = {
1168
+ track: 'w-full h-2 bg-accent rounded-full overflow-hidden',
1169
+ bar: cn(
1170
+ 'h-full bg-primary rounded-full',
1171
+ 'transition-all duration-300 ease-out'
1172
+ ),
1173
+ }
1174
+
1175
+ interface ProgressProps {
1176
+ value?: number
1177
+ max?: number
1178
+ className?: string
1179
+ }
1180
+
1181
+ export function Progress({
1182
+ value = 0,
1183
+ max = 100,
1184
+ className,
1185
+ }: ProgressProps) {
1186
+ const pct = Math.min(100, Math.max(0, (value / max) * 100))
1187
+ return (
1188
+ <div
1189
+ role="progressbar"
1190
+ aria-valuenow={value}
1191
+ aria-valuemin={0}
1192
+ aria-valuemax={max}
1193
+ className={cn(styles.track, className)}
1194
+ >
1195
+ <div
1196
+ className={styles.bar}
1197
+ style={{ width: \`\${pct}%\` }}
1198
+ />
1199
+ </div>
1200
+ )
1201
+ }
1202
+ `;var te=`'use client'
1203
+
1204
+ import * as React from 'react'
1205
+ import { ChevronDown } from 'lucide-react'
1206
+ import { cn } from '@/utils/cn'
1207
+
1208
+ const styles = {
1209
+ base: 'relative',
1210
+ trigger: cn(
1211
+ 'flex items-center justify-between w-full h-10 px-4',
1212
+ 'border border-input rounded-[10px] text-sm',
1213
+ 'focus:outline-none transition-colors',
1214
+ 'cursor-pointer'
1215
+ ),
1216
+ placeholder: 'text-muted-foreground',
1217
+ chevron: cn(
1218
+ 'w-4 h-4 text-muted-foreground',
1219
+ 'transition-transform duration-200'
1220
+ ),
1221
+ menu: cn(
1222
+ 'absolute top-full left-0 right-0 mt-1 z-50',
1223
+ 'bg-card border border-border rounded-[10px] p-1',
1224
+ 'shadow-lg max-h-[200px] overflow-y-auto',
1225
+ 'transition-[opacity,scale] duration-150 ease-out'
1226
+ ),
1227
+ option: cn(
1228
+ 'flex items-center w-full px-3 py-2 text-sm rounded-lg',
1229
+ 'hover:bg-accent transition-colors cursor-pointer'
1230
+ ),
1231
+ selected: 'text-primary font-medium',
1232
+ }
1233
+
1234
+ interface SelectCtx {
1235
+ open: boolean
1236
+ setOpen: (v: boolean) => void
1237
+ value: string | undefined
1238
+ onSelect: (v: string) => void
1239
+ }
1240
+
1241
+ const Ctx = React.createContext<SelectCtx | null>(null)
1242
+
1243
+ function useSelect() {
1244
+ const ctx = React.useContext(Ctx)
1245
+ if (!ctx) throw new Error('Select compound used outside <Select>')
1246
+ return ctx
1247
+ }
1248
+
1249
+ function SelectRoot({
1250
+ children,
1251
+ value,
1252
+ onChange,
1253
+ className,
1254
+ }: {
1255
+ children: React.ReactNode
1256
+ value?: string
1257
+ onChange?: (value: string) => void
1258
+ className?: string
1259
+ }) {
1260
+ const [open, setOpen] = React.useState(false)
1261
+ const ref = React.useRef<HTMLDivElement>(null)
1262
+
1263
+ const close = React.useCallback(() => setOpen(false), [])
1264
+ const onSelect = React.useCallback(
1265
+ (v: string) => {
1266
+ onChange?.(v)
1267
+ close()
1268
+ },
1269
+ [onChange, close]
1270
+ )
1271
+
1272
+ React.useEffect(() => {
1273
+ const onClick = (e: MouseEvent) => {
1274
+ if (!ref.current?.contains(e.target as Node)) close()
1275
+ }
1276
+ document.addEventListener('mousedown', onClick)
1277
+ return () => document.removeEventListener('mousedown', onClick)
1278
+ }, [close])
1279
+
1280
+ return (
1281
+ <Ctx.Provider value={{ open, setOpen, value, onSelect }}>
1282
+ <div ref={ref} className={cn(styles.base, className)}>
1283
+ {children}
1284
+ </div>
1285
+ </Ctx.Provider>
1286
+ )
1287
+ }
1288
+
1289
+ function Trigger({
1290
+ placeholder = 'Select...',
1291
+ children,
1292
+ className,
1293
+ }: {
1294
+ placeholder?: string
1295
+ children?: React.ReactNode
1296
+ className?: string
1297
+ }) {
1298
+ const { open, setOpen } = useSelect()
1299
+ return (
1300
+ <button
1301
+ className={cn(styles.trigger, className)}
1302
+ onClick={() => setOpen(!open)}
1303
+ >
1304
+ <span className={!children ? styles.placeholder : undefined}>
1305
+ {children ?? placeholder}
1306
+ </span>
1307
+ <ChevronDown className={cn(styles.chevron, open && 'rotate-180')} />
1308
+ </button>
1309
+ )
1310
+ }
1311
+
1312
+ function Menu({
1313
+ children,
1314
+ className,
1315
+ }: {
1316
+ children: React.ReactNode
1317
+ className?: string
1318
+ }) {
1319
+ const { open } = useSelect()
1320
+ return (
1321
+ <div
1322
+ className={cn(
1323
+ styles.menu,
1324
+ open
1325
+ ? 'opacity-100 scale-100'
1326
+ : 'opacity-0 scale-95 pointer-events-none',
1327
+ className
1328
+ )}
1329
+ >
1330
+ {children}
1331
+ </div>
1332
+ )
1333
+ }
1334
+
1335
+ function Option({
1336
+ value: optValue,
1337
+ children,
1338
+ className,
1339
+ }: {
1340
+ value: string
1341
+ children: React.ReactNode
1342
+ className?: string
1343
+ }) {
1344
+ const { value, onSelect } = useSelect()
1345
+ return (
1346
+ <button
1347
+ className={cn(
1348
+ styles.option,
1349
+ optValue === value && styles.selected,
1350
+ className
1351
+ )}
1352
+ onClick={() => onSelect(optValue)}
1353
+ >
1354
+ {children}
1355
+ </button>
1356
+ )
1357
+ }
1358
+
1359
+ export const Select = Object.assign(SelectRoot, {
1360
+ Trigger,
1361
+ Menu,
1362
+ Option,
1363
+ })
1364
+ `;var oe=`import * as React from 'react'
1365
+ import { cn } from '@/utils/cn'
1366
+
1367
+ const styles = {
1368
+ horizontal: 'w-full h-px bg-border',
1369
+ vertical: 'h-full w-px bg-border',
1370
+ }
1371
+
1372
+ interface SeparatorProps {
1373
+ orientation?: 'horizontal' | 'vertical'
1374
+ className?: string
1375
+ }
1376
+
1377
+ export function Separator({
1378
+ orientation = 'horizontal',
1379
+ className,
1380
+ }: SeparatorProps) {
1381
+ return (
1382
+ <div
1383
+ role="separator"
1384
+ className={cn(styles[orientation], className)}
1385
+ />
1386
+ )
1387
+ }
1388
+ `;var ne=`'use client'
1389
+
1390
+ import * as React from 'react'
1391
+ import { cn } from '@/utils/cn'
1392
+
1393
+ const styles = {
1394
+ base: cn(
1395
+ 'relative w-12 h-[26px] rounded-full',
1396
+ 'transition-colors duration-200 overflow-hidden'
1397
+ ),
1398
+ thumb: cn(
1399
+ 'absolute left-0 top-[3px] w-5 h-5',
1400
+ 'bg-white rounded-full shadow-md',
1401
+ 'transition-transform duration-200'
1402
+ ),
1403
+ }
1404
+
1405
+ interface SwitchProps {
1406
+ checked?: boolean
1407
+ onChange?: (checked: boolean) => void
1408
+ className?: string
1409
+ }
1410
+
1411
+ export function Switch({
1412
+ checked = false,
1413
+ onChange,
1414
+ className,
1415
+ }: SwitchProps) {
1416
+ return (
1417
+ <button
1418
+ role="switch"
1419
+ aria-checked={checked}
1420
+ onClick={() => onChange?.(!checked)}
1421
+ className={cn(
1422
+ styles.base,
1423
+ checked ? 'bg-primary' : 'bg-border',
1424
+ className
1425
+ )}
1426
+ >
1427
+ <span
1428
+ className={cn(
1429
+ styles.thumb,
1430
+ checked
1431
+ ? 'translate-x-[25px]'
1432
+ : 'translate-x-[3px]'
1433
+ )}
1434
+ />
1435
+ </button>
1436
+ )
1437
+ }
1438
+ `;var se=`'use client'
1439
+
1440
+ import * as React from 'react'
1441
+ import { cn } from '@/utils/cn'
1442
+
1443
+ const styles = {
1444
+ list: 'flex w-fit bg-accent border border-border rounded-[10px] p-1',
1445
+ tab: cn(
1446
+ 'px-4 py-2 text-sm font-medium rounded-lg',
1447
+ 'transition-colors cursor-pointer'
1448
+ ),
1449
+ active: 'bg-background text-foreground',
1450
+ inactive: 'text-muted-foreground hover:text-foreground',
1451
+ }
1452
+
1453
+ interface TabsCtx {
1454
+ value: string
1455
+ setValue: (v: string) => void
1456
+ }
1457
+
1458
+ const Ctx = React.createContext<TabsCtx | null>(null)
1459
+
1460
+ function useTabs() {
1461
+ const ctx = React.useContext(Ctx)
1462
+ if (!ctx) throw new Error('Tabs compound used outside <Tabs>')
1463
+ return ctx
1464
+ }
1465
+
1466
+ function TabsRoot({
1467
+ children,
1468
+ defaultValue,
1469
+ value: controlled,
1470
+ onChange,
1471
+ className,
1472
+ }: {
1473
+ children: React.ReactNode
1474
+ defaultValue?: string
1475
+ value?: string
1476
+ onChange?: (value: string) => void
1477
+ className?: string
1478
+ }) {
1479
+ const [uncontrolled, setUncontrolled] = React.useState(
1480
+ defaultValue ?? ''
1481
+ )
1482
+ const value = controlled ?? uncontrolled
1483
+ const setValue = React.useCallback(
1484
+ (v: string) => {
1485
+ onChange?.(v)
1486
+ if (controlled === undefined) setUncontrolled(v)
1487
+ },
1488
+ [controlled, onChange]
1489
+ )
1490
+
1491
+ return (
1492
+ <Ctx.Provider value={{ value, setValue }}>
1493
+ <div className={className}>{children}</div>
1494
+ </Ctx.Provider>
1495
+ )
1496
+ }
1497
+
1498
+ function List({
1499
+ children,
1500
+ className,
1501
+ }: {
1502
+ children: React.ReactNode
1503
+ className?: string
1504
+ }) {
1505
+ return (
1506
+ <div className={cn(styles.list, className)}>
1507
+ {children}
1508
+ </div>
1509
+ )
1510
+ }
1511
+
1512
+ function Tab({
1513
+ value: tabValue,
1514
+ children,
1515
+ className,
1516
+ }: {
1517
+ value: string
1518
+ children: React.ReactNode
1519
+ className?: string
1520
+ }) {
1521
+ const { value, setValue } = useTabs()
1522
+ const isActive = value === tabValue
1523
+ return (
1524
+ <button
1525
+ className={cn(
1526
+ styles.tab,
1527
+ isActive ? styles.active : styles.inactive,
1528
+ className
1529
+ )}
1530
+ onClick={() => setValue(tabValue)}
1531
+ >
1532
+ {children}
1533
+ </button>
1534
+ )
1535
+ }
1536
+
1537
+ function Panel({
1538
+ value: panelValue,
1539
+ children,
1540
+ className,
1541
+ }: {
1542
+ value: string
1543
+ children: React.ReactNode
1544
+ className?: string
1545
+ }) {
1546
+ const { value } = useTabs()
1547
+ if (value !== panelValue) return null
1548
+ return <div className={className}>{children}</div>
1549
+ }
1550
+
1551
+ export const Tabs = Object.assign(TabsRoot, {
1552
+ List,
1553
+ Tab,
1554
+ Panel,
1555
+ })
1556
+ `;var re=`import * as React from 'react'
1557
+ import { cn } from '@/utils/cn'
1558
+
1559
+ const styles = {
1560
+ base: cn(
1561
+ 'w-full min-h-[80px] px-4 py-3',
1562
+ 'border border-input rounded-[10px]',
1563
+ 'text-foreground placeholder:text-muted-foreground text-sm',
1564
+ 'focus:outline-none transition-colors',
1565
+ 'resize-y disabled:opacity-50 disabled:cursor-default'
1566
+ ),
1567
+ }
1568
+
1569
+ type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>
1570
+
1571
+ export const Textarea = React.forwardRef<
1572
+ HTMLTextAreaElement,
1573
+ TextareaProps
1574
+ >(({ className, ...props }, ref) => (
1575
+ <textarea
1576
+ ref={ref}
1577
+ className={cn(styles.base, className)}
1578
+ {...props}
1579
+ />
1580
+ ))
1581
+
1582
+ Textarea.displayName = 'Textarea'
1583
+ `;var ae=`'use client'
1584
+
1585
+ import * as React from 'react'
1586
+ import { Toaster as Sonner, toast } from 'sonner'
1587
+ import {
1588
+ CheckCircle2,
1589
+ XCircle,
1590
+ Info,
1591
+ AlertTriangle,
1592
+ Loader2,
1593
+ } from 'lucide-react'
1594
+
1595
+ function Toaster() {
1596
+ return (
1597
+ <Sonner
1598
+ icons={{
1599
+ success: (
1600
+ <CheckCircle2 className="w-4 h-4" />
1601
+ ),
1602
+ info: (
1603
+ <Info className="w-4 h-4" />
1604
+ ),
1605
+ warning: (
1606
+ <AlertTriangle className="w-4 h-4" />
1607
+ ),
1608
+ error: (
1609
+ <XCircle className="w-4 h-4" />
1610
+ ),
1611
+ loading: (
1612
+ <Loader2 className="w-4 h-4 animate-spin" />
1613
+ ),
1614
+ }}
1615
+ style={{
1616
+ '--normal-bg': 'var(--card)',
1617
+ '--normal-text': 'var(--card-foreground)',
1618
+ '--normal-border': 'var(--border)',
1619
+ '--border-radius': '12px',
1620
+ }}
1621
+ />
1622
+ )
1623
+ }
1624
+
1625
+ export { Toaster, toast }
1626
+ `;var ce=`import * as React from 'react'
1627
+ import { cn } from '@/utils/cn'
1628
+
1629
+ const styles = {
1630
+ base: 'relative inline-flex group',
1631
+ tip: cn(
1632
+ 'absolute z-50 px-2.5 py-1.5 text-xs font-medium',
1633
+ 'rounded-lg bg-foreground text-background',
1634
+ 'whitespace-nowrap pointer-events-none',
1635
+ 'opacity-0 group-hover:opacity-100 transition-opacity'
1636
+ ),
1637
+ positions: {
1638
+ top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
1639
+ bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
1640
+ left: 'right-full top-1/2 -translate-y-1/2 mr-2',
1641
+ right: 'left-full top-1/2 -translate-y-1/2 ml-2',
1642
+ },
1643
+ }
1644
+
1645
+ interface TooltipProps {
1646
+ content: string
1647
+ position?: keyof typeof styles.positions
1648
+ className?: string
1649
+ children: React.ReactNode
1650
+ }
1651
+
1652
+ export function Tooltip({
1653
+ content,
1654
+ position = 'top',
1655
+ className,
1656
+ children,
1657
+ }: TooltipProps) {
1658
+ return (
1659
+ <span className={cn(styles.base, className)}>
1660
+ {children}
1661
+ <span className={cn(styles.tip, styles.positions[position])}>
1662
+ {content}
1663
+ </span>
1664
+ </span>
1665
+ )
1666
+ }
1667
+ `;var C=[{name:"accordion",description:"Collapsible content sections with dot notation and smooth animation",dependencies:[],npmDependencies:[]},{name:"alert",description:"Contextual feedback messages with variants and icons",dependencies:[],npmDependencies:[]},{name:"avatar",description:"User avatar with image support and fallback initials",dependencies:[],npmDependencies:[]},{name:"badge",description:"Small status indicator with color variants",dependencies:[],npmDependencies:[]},{name:"button",description:"Button with variants, sizes, loading state, and icon slots",dependencies:[],npmDependencies:[]},{name:"card",description:"Container with dot notation preview and info sub-components",dependencies:[],npmDependencies:[]},{name:"checkbox",description:"Checkbox input with label and CSS-only checkmark",dependencies:[],npmDependencies:[]},{name:"dialog",description:"Modal dialog with dot notation, overlay, and escape key",dependencies:["button"],npmDependencies:[]},{name:"dropdown",description:"Dropdown menu with dot notation, groups, separators, and click-outside",dependencies:["button"],npmDependencies:[]},{name:"input",description:"Text input with focus ring and disabled state",dependencies:[],npmDependencies:[]},{name:"popover",description:"Floating content panel with dot notation and click-outside",dependencies:["button"],npmDependencies:[]},{name:"progress",description:"Progress bar with animated fill and ARIA attributes",dependencies:[],npmDependencies:[]},{name:"select",description:"Custom select with dot notation and composable options",dependencies:[],npmDependencies:[]},{name:"separator",description:"Visual divider with horizontal and vertical orientation",dependencies:[],npmDependencies:[]},{name:"switch",description:"Toggle switch with smooth transition",dependencies:[],npmDependencies:[]},{name:"tabs",description:"Tab navigation with dot notation and panel content",dependencies:[],npmDependencies:[]},{name:"textarea",description:"Multi-line text input with consistent styling",dependencies:[],npmDependencies:[]},{name:"theme",description:"Dark/light theme support with next-themes and ThemeProvider",dependencies:[],npmDependencies:["next-themes"]},{name:"toast",description:"Toast notifications powered by Sonner",dependencies:[],npmDependencies:["sonner"]},{name:"tooltip",description:"Pure CSS tooltip with 4 position options",dependencies:[],npmDependencies:[]}],k={accordion:_,alert:U,avatar:G,badge:W,button:K,card:X,checkbox:J,dialog:q,dropdown:Q,input:Y,popover:Z,progress:ee,select:te,separator:oe,switch:ne,tabs:se,textarea:re,theme:F,toast:ae,tooltip:ce};async function ie(t){let s=process.cwd();e.intro("drivn add");let r=V(s);if(r||(e.log.error("Drivn is not initialized. Run npx drivn@latest create"),e.outro("Cancelled"),process.exit(1)),!t||!t.length){let o=await e.multiselect({message:"Select components to add",options:C.map(i=>({label:i.name,hint:i.description,value:i.name})),required:true});e.isCancel(o)&&(e.cancel("Cancelled"),process.exit(0)),t=o;}let b=t.filter(o=>!C.find(i=>i.name===o));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+C.map(o=>o.name).join(", ")),e.outro("Cancelled"),process.exit(1));let d=t.includes("theme"),m=t.filter(o=>o!=="theme"),f=new Set,g=new Set,h=o=>{if(f.has(o))return;let i=C.find(c=>c.name===o);i&&(i.dependencies.forEach(c=>h(c)),i.npmDependencies?.forEach(c=>g.add(c)),f.add(o));};m.forEach(h),d&&g.add("next-themes");let y=[...f].filter(o=>!m.includes(o));y.length&&e.log.info(`Required dependency: ${y.join(", ")}`);let a=r.typescript?"tsx":"jsx",x=join(s,r.paths.components);for(let o of f){let i=join(x,`${o}.${a}`);if(v(i)){let N=await e.confirm({message:`${o}.${a} exists. Overwrite?`,initialValue:false});if(e.isCancel(N)||!N){e.log.warn(`Skipped ${o}`);continue}}let c=k[o];c=c.replace(/@\/utils/g,`@/${r.paths.utils.replace(/^src\//,"")}`),p(i,c),e.log.success(`${o} \u2192 ${r.paths.components}/${o}.${a}`);}if(d){let o=join(x,`theme-provider.${a}`);if(v(o)){let c=await e.confirm({message:`theme-provider.${a} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(p(o,k.theme),e.log.success(`theme-provider \u2192 ${r.paths.components}/theme-provider.${a}`)):e.log.warn("Skipped theme-provider");}else p(o,k.theme),e.log.success(`theme-provider \u2192 ${r.paths.components}/theme-provider.${a}`);if(r.paths.globals){let c=join(s,r.paths.globals);if(v(c)){let N=z(c);N.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(p(c,N+O),e.log.success(`Theme tokens appended to ${l.cyan(r.paths.globals)}`));}else e.log.warn(`Globals file not found at ${r.paths.globals}`);}else e.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let i=r.paths.components.replace(/^src\//,"@/");e.log.message(""),e.log.info(l.bold("Complete the setup:")),e.log.message(""),e.log.message(l.bold(`${l.cyan("1.")} Import ThemeProvider in your root layout:`)),e.log.message(l.cyan(` import { ThemeProvider } from "${i}/theme-provider"`)),e.log.message(""),e.log.message(l.bold(`${l.cyan("2.")} Add suppressHydrationWarning to <html>:`)),e.log.message(l.cyan(" <html suppressHydrationWarning>")),e.log.message(""),e.log.message(l.bold(`${l.cyan("3.")} Wrap your app with ThemeProvider:`)),e.log.message(l.cyan(" <ThemeProvider>")),e.log.message(l.cyan(" {children}")),e.log.message(l.cyan(" </ThemeProvider>")),e.log.message("");}if(g.size){let o=e.spinner();o.start("Installing packages");try{execSync(`npm install ${[...g].join(" ")}`,{cwd:s,stdio:"ignore"}),o.stop("Packages installed");}catch{o.stop("Failed to install packages"),e.log.warn(`Run manually: npm install ${[...g].join(" ")}`);}}e.outro("Done.");}var le={version:"1.0.1"};var I=new Command;I.name("drivn").description("Drivn \u2014 Modern UI components").version(le.version);I.command("create").description("Initialize Drivn in your project").action(H);I.command("add [components...]").description("Add components to your project").action(ie);I.parse();