drivn 1.1.0 → 1.3.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.
Files changed (2) hide show
  1. package/dist/index.js +1514 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {Command}from'commander';import*as e from'@clack/prompts';import i from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';var M={next:"Next.js",react:"React"};function B(t){let n=join(t,"package.json");if(!existsSync(n))throw new Error("package.json not found");let c=JSON.parse(readFileSync(n,"utf-8")),v={...c.dependencies,...c.devDependencies},d="react";v.next&&(d="next");let m=existsSync(join(t,"src")),f=existsSync(join(t,"tsconfig.json"));return {framework:d,srcDir:m,typescript:f}}var H="drivn.config.json";function V(t){let n=join(t,H);return existsSync(n)?JSON.parse(readFileSync(n,"utf-8")):null}function z(t,n){let c=join(t,H);writeFileSync(c,JSON.stringify(n,null,2));}function he(t){existsSync(t)||mkdirSync(t,{recursive:true});}function p(t,n){he(dirname(t)),writeFileSync(t,n);}function F(t){return readFileSync(t,"utf-8")}function h(t){return existsSync(t)}function k(t){return existsSync(join(t,"pnpm-lock.yaml"))?"pnpm":"npm"}function y(t,n){let c=n.join(" ");return t==="pnpm"?`pnpm add ${c}`:`npm install ${c}`}function _(t){return t==="pnpm"?"pnpm dlx":"npx"}var T=`@import "tailwindcss";
2
+ import {Command}from'commander';import*as e from'@clack/prompts';import i from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';var A={next:"Next.js",react:"React"};function B(t){let n=join(t,"package.json");if(!existsSync(n))throw new Error("package.json not found");let a=JSON.parse(readFileSync(n,"utf-8")),b={...a.dependencies,...a.devDependencies},p="react";b.next&&(p="next");let g=existsSync(join(t,"src")),u=existsSync(join(t,"tsconfig.json"));return {framework:p,srcDir:g,typescript:u}}var V="drivn.config.json";function _(t){let n=join(t,V);return existsSync(n)?JSON.parse(readFileSync(n,"utf-8")):null}function $(t,n){let a=join(t,V);writeFileSync(a,JSON.stringify(n,null,2));}function Pe(t){existsSync(t)||mkdirSync(t,{recursive:true});}function d(t,n){Pe(dirname(t)),writeFileSync(t,n);}function M(t){return readFileSync(t,"utf-8")}function m(t){return existsSync(t)}function P(t){return existsSync(join(t,"pnpm-lock.yaml"))?"pnpm":"npm"}function y(t,n){let a=n.join(" ");return t==="pnpm"?`pnpm add ${a}`:`npm install ${a}`}function F(t){return t==="pnpm"?"pnpm dlx":"npx"}var D=`@import "tailwindcss";
3
3
 
4
4
  :root {
5
5
  /* Surfaces */
@@ -70,7 +70,7 @@ body {
70
70
  color: var(--color-foreground);
71
71
  font-family: system-ui, -apple-system, sans-serif;
72
72
  }
73
- `,L=`
73
+ `,O=`
74
74
  /* Drivn Dark/Light Theme */
75
75
  :root,
76
76
  [data-theme="dark"] {
@@ -136,13 +136,13 @@ body {
136
136
  /* Special Surfaces */
137
137
  --overlay: hsl(0 0% 0% / 0.18);
138
138
  }
139
- `;var ye=`import { type ClassValue, clsx } from 'clsx'
139
+ `;var Ee=`import { type ClassValue, clsx } from 'clsx'
140
140
  import { twMerge } from 'tailwind-merge'
141
141
 
142
142
  export function cn(...inputs: ClassValue[]) {
143
143
  return twMerge(clsx(inputs))
144
144
  }
145
- `,Ne=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function we(t){for(let n of Ne)if(h(join(t,n)))return n;return null}async function U(){let t=process.cwd();console.log(""),console.log(i.bgCyan(i.bold(i.black(" Drivn "))));let n;try{n=B(t),e.log.success(`Detected ${i.cyan(M[n.framework])}`);}catch{e.log.error("No package.json found. Run this command in a project directory."),e.outro("Setup cancelled"),process.exit(1);}if(h(join(t,"drivn.config.json"))){let s=await e.confirm({message:"Config already exists. Overwrite?",initialValue:false});(e.isCancel(s)||!s)&&(e.cancel("Setup cancelled"),process.exit(0));}let c=n.srcDir?"src/components/ui":"components/ui",v=n.srcDir?"src/utils":"utils",d=await e.group({components:()=>e.text({message:"Where should components be installed?",placeholder:c,defaultValue:c}),utils:()=>e.text({message:"Where should utilities be placed?",placeholder:v,defaultValue:v})},{onCancel:()=>{e.cancel("Setup cancelled"),process.exit(0);}}),m={framework:n.framework,typescript:n.typescript,paths:{components:d.components,utils:d.utils},installed:[]},f=n.typescript?"ts":"js",b=join(t,d.utils,`cn.${f}`);h(b)||p(b,ye);let g=we(t);if(g){let s=await e.confirm({message:`Found ${i.cyan(g)}. Add Drivn color tokens?`,initialValue:true});!e.isCancel(s)&&s&&(p(join(t,g),T),m.paths.globals=g,e.log.success(`Color tokens written to ${i.cyan(g)}`));}else {let s=n.srcDir?"src/styles/globals.css":"styles/globals.css",a=await e.text({message:"Where should the globals CSS file be created?",placeholder:s,defaultValue:s});e.isCancel(a)||(p(join(t,a),T),m.paths.globals=a,e.log.success(`Color tokens written to ${i.cyan(a)}`));}z(t,m);let x=k(t),l=_(x),N=["clsx","tailwind-merge","lucide-react"],o=e.spinner();o.start("Installing dependencies");try{execSync(y(x,N),{cwd:t,stdio:"ignore"}),o.stop("Dependencies installed");}catch{o.stop("Failed to install dependencies"),e.log.warn(`Run manually: ${y(x,N)}`);}e.log.info(`Add components with: ${i.cyan(`${l} drivn add button`)}`),e.log.info(`Add dark/light theme: ${i.cyan(`${l} drivn add theme`)}`),e.outro("Drivn initialized");}var G=`'use client'
145
+ `,Le=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function Ie(t){for(let n of Le)if(m(join(t,n)))return n;return null}async function G(){let t=process.cwd();console.log(""),console.log(i.bgCyan(i.bold(i.black(" Drivn "))));let n;try{n=B(t),e.log.success(`Detected ${i.cyan(A[n.framework])}`);}catch{e.log.error("No package.json found. Run this command in a project directory."),e.outro("Setup cancelled"),process.exit(1);}if(m(join(t,"drivn.config.json"))){let r=await e.confirm({message:"Config already exists. Overwrite?",initialValue:false});(e.isCancel(r)||!r)&&(e.cancel("Setup cancelled"),process.exit(0));}let a=n.srcDir?"src/components/ui":"components/ui",b=n.srcDir?"src/utils":"utils",p=await e.group({components:()=>e.text({message:"Where should components be installed?",placeholder:a,defaultValue:a}),utils:()=>e.text({message:"Where should utilities be placed?",placeholder:b,defaultValue:b})},{onCancel:()=>{e.cancel("Setup cancelled"),process.exit(0);}}),g={framework:n.framework,typescript:n.typescript,paths:{components:p.components,utils:p.utils},installed:[]},u=n.typescript?"ts":"js",v=join(t,p.utils,`cn.${u}`);m(v)||d(v,Ee);let h=Ie(t);if(h){let r=await e.confirm({message:`Found ${i.cyan(h)}. Add Drivn color tokens?`,initialValue:true});!e.isCancel(r)&&r&&(d(join(t,h),D),g.paths.globals=h,e.log.success(`Color tokens written to ${i.cyan(h)}`));}else {let r=n.srcDir?"src/styles/globals.css":"styles/globals.css",c=await e.text({message:"Where should the globals CSS file be created?",placeholder:r,defaultValue:r});e.isCancel(c)||(d(join(t,c),D),g.paths.globals=c,e.log.success(`Color tokens written to ${i.cyan(c)}`));}$(t,g);let x=P(t),l=F(x),N=["clsx","tailwind-merge","lucide-react"],o=e.spinner();o.start("Installing dependencies");try{execSync(y(x,N),{cwd:t,stdio:"ignore"}),o.stop("Dependencies installed");}catch{o.stop("Failed to install dependencies"),e.log.warn(`Run manually: ${y(x,N)}`);}e.log.info(`Add components with: ${i.cyan(`${l} drivn add button`)}`),e.log.info(`Add dark/light theme: ${i.cyan(`${l} drivn add theme`)}`),e.outro("Drivn initialized");}var K=`'use client'
146
146
 
147
147
  import { ThemeProvider as NextThemesProvider } from 'next-themes'
148
148
 
@@ -161,7 +161,7 @@ export function ThemeProvider({
161
161
  </NextThemesProvider>
162
162
  )
163
163
  }
164
- `;var W=`'use client'
164
+ `;var Y=`'use client'
165
165
 
166
166
  import * as React from 'react'
167
167
  import { ChevronDown } from 'lucide-react'
@@ -289,9 +289,11 @@ function useCtx() {
289
289
  }
290
290
 
291
291
  export const Accordion = Object.assign(AccordionRoot, {
292
- Item, Trigger, Content,
292
+ Item,
293
+ Trigger,
294
+ Content
293
295
  })
294
- `;var X=`import * as React from 'react'
296
+ `;var W=`import * as React from 'react'
295
297
  import { cn } from '@/utils/cn'
296
298
 
297
299
  const styles = {
@@ -339,7 +341,7 @@ export function Alert({
339
341
  </div>
340
342
  )
341
343
  }
342
- `;var q=`import * as React from 'react'
344
+ `;var U=`import * as React from 'react'
343
345
  import { cn } from '@/utils/cn'
344
346
 
345
347
  const styles = {
@@ -383,7 +385,7 @@ export function Avatar({
383
385
  </div>
384
386
  )
385
387
  }
386
- `;var J=`import * as React from 'react'
388
+ `;var q=`import * as React from 'react'
387
389
  import { cn } from '@/utils/cn'
388
390
 
389
391
  const styles = {
@@ -413,7 +415,123 @@ export function Badge({ variant = 'default', className, children }: BadgeProps)
413
415
  </span>
414
416
  )
415
417
  }
416
- `;var K=`import * as React from 'react'
418
+ `;var X=`import * as React from 'react'
419
+ import { cn } from '@/utils/cn'
420
+ import { ChevronRight, MoreHorizontal } from 'lucide-react'
421
+
422
+ const styles = {
423
+ list: cn(
424
+ 'flex items-center gap-1.5',
425
+ 'flex-wrap text-sm text-muted-foreground'
426
+ ),
427
+ link: cn(
428
+ 'transition-colors hover:text-foreground',
429
+ 'inline-flex items-center gap-1'
430
+ ),
431
+ page: 'font-medium text-foreground',
432
+ separator: 'text-muted-foreground/60 [&>svg]:size-3.5',
433
+ ellipsis: cn(
434
+ 'flex size-9 items-center justify-center',
435
+ 'text-muted-foreground'
436
+ ),
437
+ }
438
+
439
+ function BreadcrumbRoot({
440
+ separator,
441
+ className,
442
+ children,
443
+ }: {
444
+ separator?: React.ReactNode
445
+ className?: string
446
+ children: React.ReactNode
447
+ }) {
448
+ return (
449
+ <nav aria-label="Breadcrumb">
450
+ <ol className={cn(styles.list, className)}>
451
+ {React.Children.toArray(children).flatMap((child, i) => {
452
+ return !(React.isValidElement(child) &&
453
+ child.type === BreadcrumbSeparator) && i > 0 ? [
454
+ <BreadcrumbSeparator key={\`sep-\${i}\`}>
455
+ {separator}
456
+ </BreadcrumbSeparator>,
457
+ child,
458
+ ] : [child]
459
+ })}
460
+ </ol>
461
+ </nav>
462
+ )
463
+ }
464
+
465
+ function Item({
466
+ href,
467
+ className,
468
+ children,
469
+ ...props
470
+ }: React.AnchorHTMLAttributes<HTMLAnchorElement> & {
471
+ href: string
472
+ children: React.ReactNode
473
+ }) {
474
+ return (
475
+ <li>
476
+ <a
477
+ href={href}
478
+ className={cn(styles.link, className)}
479
+ {...props}
480
+ >
481
+ {children}
482
+ </a>
483
+ </li>
484
+ )
485
+ }
486
+
487
+ function Page({
488
+ className,
489
+ children,
490
+ }: {
491
+ className?: string
492
+ children: React.ReactNode
493
+ }) {
494
+ return (
495
+ <li aria-current="page">
496
+ <span className={cn(styles.page, className)}>
497
+ {children}
498
+ </span>
499
+ </li>
500
+ )
501
+ }
502
+
503
+ function BreadcrumbSeparator({
504
+ children,
505
+ }: {
506
+ children?: React.ReactNode
507
+ }) {
508
+ return (
509
+ <li role="presentation" aria-hidden="true">
510
+ <span className={styles.separator}>
511
+ {children ?? <ChevronRight />}
512
+ </span>
513
+ </li>
514
+ )
515
+ }
516
+
517
+ function Ellipsis() {
518
+ return (
519
+ <li>
520
+ <span className={styles.ellipsis}>
521
+ <MoreHorizontal className="size-4" />
522
+ <span className="sr-only">More pages</span>
523
+ </span>
524
+ </li>
525
+ )
526
+ }
527
+
528
+ export const Breadcrumb = Object.assign(BreadcrumbRoot, {
529
+ Item,
530
+ Page,
531
+ Separator: BreadcrumbSeparator,
532
+ Ellipsis,
533
+ })
534
+ `;var J=`import * as React from 'react'
417
535
  import { Loader2 } from 'lucide-react'
418
536
  import { cn } from '@/utils/cn'
419
537
 
@@ -492,8 +610,888 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(({
492
610
  )
493
611
  )
494
612
 
495
- Button.displayName = 'Button'
496
- `;var Q=`import * as React from 'react'
613
+ Button.displayName = 'Button'
614
+ `;var Q=`'use client'
615
+
616
+ import * as React from 'react'
617
+ import {
618
+ DayPicker,
619
+ type DateRange,
620
+ type Locale,
621
+ type PropsBase,
622
+ type PropsSingle,
623
+ type PropsRange,
624
+ } from 'react-day-picker'
625
+ import { ChevronDown, ChevronLeft, ChevronRight } from 'lucide-react'
626
+ import { cn } from '@/utils/cn'
627
+
628
+ const styles = {
629
+ root: 'p-3 bg-card border border-border rounded-[10px] text-sm',
630
+ classNames: {
631
+ months: 'relative flex gap-4',
632
+ month: 'flex flex-col gap-4',
633
+ month_caption: 'flex items-center justify-center h-7',
634
+ caption_label: 'text-sm font-medium text-foreground',
635
+ nav: 'absolute inset-x-0 top-0 flex items-center justify-between h-7',
636
+ button_previous: cn(
637
+ 'inline-flex items-center justify-center',
638
+ 'w-7 h-7 rounded-md text-muted-foreground',
639
+ 'hover:text-foreground hover:bg-accent',
640
+ 'transition-colors cursor-pointer'
641
+ ),
642
+ button_next: cn(
643
+ 'inline-flex items-center justify-center',
644
+ 'w-7 h-7 rounded-md text-muted-foreground',
645
+ 'hover:text-foreground hover:bg-accent',
646
+ 'transition-colors cursor-pointer'
647
+ ),
648
+ month_grid: 'border-collapse border-spacing-0',
649
+ weekdays: '',
650
+ weekday: cn(
651
+ 'w-8 pb-2 text-[0.8rem] font-medium',
652
+ 'text-muted-foreground text-center'
653
+ ),
654
+ week: '',
655
+ day: 'p-0 text-center',
656
+ day_button: cn(
657
+ 'inline-flex items-center justify-center',
658
+ 'w-8 h-8 rounded-md text-sm cursor-pointer',
659
+ 'hover:bg-accent hover:text-accent-foreground',
660
+ 'focus-visible:outline-none'
661
+ ),
662
+ today: 'font-semibold text-primary',
663
+ selected: cn(
664
+ '[&>button]:bg-primary',
665
+ '[&>button]:text-primary-foreground',
666
+ '[&>button]:hover:bg-primary',
667
+ '[&>button]:hover:text-primary-foreground'
668
+ ),
669
+ outside: 'text-muted-foreground/40',
670
+ disabled: 'text-muted-foreground/30 cursor-not-allowed',
671
+ range_middle: cn(
672
+ 'bg-accent text-accent-foreground',
673
+ 'hover:bg-accent hover:text-accent-foreground',
674
+ 'rounded-none [&>button]:rounded-none'
675
+ ),
676
+ chevron: 'w-4 h-4',
677
+ dropdown: cn(
678
+ 'appearance-none bg-transparent text-sm',
679
+ 'font-medium text-foreground cursor-pointer',
680
+ 'border-none outline-none'
681
+ ),
682
+ week_number: cn(
683
+ 'w-8 text-[0.75rem]',
684
+ 'text-muted-foreground/50 text-center font-normal'
685
+ ),
686
+ hidden: 'invisible',
687
+ },
688
+ dropdownOverrides: {
689
+ dropdowns: 'flex items-center gap-2 justify-center',
690
+ dropdown_root: 'relative inline-flex items-center',
691
+ dropdown: 'absolute inset-0 opacity-0 cursor-pointer w-full z-10',
692
+ caption_label: cn(
693
+ 'inline-flex items-center text-sm',
694
+ 'font-medium text-foreground',
695
+ 'pointer-events-none whitespace-nowrap'
696
+ ),
697
+ chevron: 'w-3 h-3 ml-0.5 text-muted-foreground',
698
+ },
699
+ rangeActive: {
700
+ range_start: cn(
701
+ 'bg-primary text-primary-foreground',
702
+ 'rounded-l-md [&>button]:rounded-r-none'
703
+ ),
704
+ range_end: cn(
705
+ 'bg-primary text-primary-foreground',
706
+ 'rounded-r-md [&>button]:rounded-l-none'
707
+ ),
708
+ },
709
+ }
710
+
711
+ const variantConfig = {
712
+ default: {},
713
+ weekNumbers: { showWeekNumber: true },
714
+ dropdown: { captionLayout: 'dropdown' as const },
715
+ }
716
+
717
+ export type CalendarVariant = keyof typeof variantConfig
718
+
719
+ type CalendarProps = Omit<PropsBase, 'mode'> & Omit<PropsSingle, 'mode'> & { variant?: CalendarVariant; fromYear?: number; toYear?: number }
720
+
721
+ type RangeProps = Omit<PropsBase, 'mode'> & Omit<PropsRange, 'mode'>
722
+
723
+ function Chevron(props: { orientation?: 'left' | 'right' | 'up' | 'down'; size?: number; disabled?: boolean; className?: string }) {
724
+ const icons = { left: ChevronLeft, right: ChevronRight, down: ChevronDown, up: ChevronRight }
725
+ const Icon = icons[props.orientation ?? 'right']
726
+ return <Icon className={props.className} />
727
+ }
728
+
729
+ const currentYear = new Date().getFullYear()
730
+
731
+ function CalendarRoot({
732
+ variant = 'default',
733
+ fromYear = currentYear - 20,
734
+ toYear = currentYear + 20,
735
+ className,
736
+ classNames: userClassNames,
737
+ ...props
738
+ }: CalendarProps) {
739
+ const dropdownRange = variant === 'dropdown' ? {
740
+ startMonth: new Date(fromYear, 0),
741
+ endMonth: new Date(toYear, 11),
742
+ } : {}
743
+
744
+ return (
745
+ <DayPicker
746
+ mode="single"
747
+ {...variantConfig[variant]}
748
+ {...dropdownRange}
749
+ classNames={{
750
+ ...styles.classNames,
751
+ ...(variant === 'dropdown' && styles.dropdownOverrides),
752
+ ...userClassNames,
753
+ }}
754
+ components={{ Chevron }}
755
+ className={cn(styles.root, className)}
756
+ {...props}
757
+ />
758
+ )
759
+ }
760
+
761
+ function Range({
762
+ className,
763
+ classNames: userClassNames,
764
+ selected,
765
+ ...props
766
+ }: RangeProps) {
767
+ const hasRange = selected?.from && selected?.to && selected.from.getTime() !== selected.to.getTime()
768
+
769
+ return (
770
+ <DayPicker
771
+ mode="range"
772
+ selected={selected}
773
+ classNames={{
774
+ ...styles.classNames,
775
+ ...(hasRange && styles.rangeActive),
776
+ ...userClassNames,
777
+ }}
778
+ components={{ Chevron }}
779
+ className={cn(styles.root, className)}
780
+ {...props}
781
+ />
782
+ )
783
+ }
784
+
785
+ export { type DateRange, type Locale }
786
+
787
+ export const Calendar = Object.assign(CalendarRoot, {
788
+ Range
789
+ })
790
+ `;var Z=`'use client'
791
+
792
+ import * as React from 'react'
793
+ import { CalendarDays } from 'lucide-react'
794
+ import { cn } from '@/utils/cn'
795
+ import {
796
+ Calendar,
797
+ type CalendarVariant,
798
+ type DateRange,
799
+ type Locale,
800
+ } from '@/components/ui/calendar'
801
+
802
+ const styles = {
803
+ base: 'relative',
804
+ trigger: cn(
805
+ 'flex items-center gap-2 w-full h-10 px-3',
806
+ 'border border-input rounded-[10px] text-sm',
807
+ 'text-foreground transition-colors cursor-pointer',
808
+ 'focus:outline-none',
809
+ 'disabled:opacity-50 disabled:cursor-default'
810
+ ),
811
+ placeholder: 'text-muted-foreground',
812
+ icon: 'w-4 h-4 text-muted-foreground shrink-0',
813
+ text: 'flex-1 truncate text-left',
814
+ content: cn(
815
+ 'absolute top-full left-0 mt-1 z-50',
816
+ 'transition-[opacity,scale] duration-150 ease-out'
817
+ ),
818
+ }
819
+
820
+ type FormatDateFn = (date: Date) => string
821
+
822
+ interface DatePickerBaseProps {
823
+ placeholder?: string
824
+ formatDate?: FormatDateFn
825
+ disabled?: boolean
826
+ locale?: Partial<Locale>
827
+ defaultMonth?: Date
828
+ className?: string
829
+ }
830
+
831
+ interface DatePickerProps extends DatePickerBaseProps {
832
+ selected?: Date
833
+ onSelect?: (date: Date | undefined) => void
834
+ variant?: CalendarVariant
835
+ fromYear?: number
836
+ toYear?: number
837
+ }
838
+
839
+ interface DatePickerRangeProps extends DatePickerBaseProps {
840
+ selected?: DateRange
841
+ onSelect?: (range: DateRange | undefined) => void
842
+ }
843
+
844
+ function formatRangeLabel(
845
+ range: DateRange,
846
+ fmt: FormatDateFn
847
+ ): string {
848
+ if (!range.from) return ''
849
+ if (!range.to) return fmt(range.from)
850
+ return \\\`\\\${fmt(range.from)} \u2013 \\\${fmt(range.to)}\\\`
851
+ }
852
+
853
+ function DatePickerRoot({
854
+ selected,
855
+ onSelect,
856
+ placeholder = 'Pick a date',
857
+ formatDate,
858
+ disabled = false,
859
+ locale,
860
+ variant = 'default',
861
+ fromYear,
862
+ toYear,
863
+ defaultMonth,
864
+ className,
865
+ }: DatePickerProps) {
866
+ const fmt = formatDate ?? ((d: Date) =>
867
+ d.toLocaleDateString(locale?.code ?? 'en-US', { month: 'short', day: 'numeric', year: 'numeric' }))
868
+ const [open, setOpen] = React.useState(false)
869
+ const ref = React.useRef<HTMLDivElement>(null)
870
+
871
+ React.useEffect(() => {
872
+ if (!open) return
873
+ const onMouseDown = (e: MouseEvent) => {
874
+ if (!ref.current?.contains(e.target as Node)) {
875
+ setOpen(false)
876
+ }
877
+ }
878
+ document.addEventListener('mousedown', onMouseDown)
879
+ return () => {
880
+ document.removeEventListener('mousedown', onMouseDown)
881
+ }
882
+ }, [open])
883
+
884
+ React.useEffect(() => {
885
+ if (!open) return
886
+ const onKeyDown = (e: KeyboardEvent) => {
887
+ if (e.key === 'Escape') setOpen(false)
888
+ }
889
+ document.addEventListener('keydown', onKeyDown)
890
+ return () => {
891
+ document.removeEventListener('keydown', onKeyDown)
892
+ }
893
+ }, [open])
894
+
895
+ const handleSelect = React.useCallback(
896
+ (date: Date | undefined) => {
897
+ onSelect?.(date)
898
+ setOpen(false)
899
+ },
900
+ [onSelect]
901
+ )
902
+
903
+ return (
904
+ <div ref={ref} className={cn(styles.base, className)}>
905
+ <button
906
+ type="button"
907
+ className={styles.trigger}
908
+ disabled={disabled}
909
+ onClick={() => setOpen((v) => !v)}
910
+ >
911
+ <CalendarDays className={styles.icon} />
912
+ <span className={cn(styles.text, !selected && styles.placeholder)}>
913
+ {selected ? fmt(selected) : placeholder}
914
+ </span>
915
+ </button>
916
+ <div className={cn(styles.content, open ? 'opacity-100 scale-100' : 'opacity-0 scale-95 pointer-events-none')}>
917
+ <Calendar
918
+ variant={variant}
919
+ locale={locale}
920
+ selected={selected}
921
+ onSelect={handleSelect}
922
+ defaultMonth={defaultMonth ?? selected}
923
+ {...(fromYear !== undefined && { fromYear })}
924
+ {...(toYear !== undefined && { toYear })}
925
+ />
926
+ </div>
927
+ </div>
928
+ )
929
+ }
930
+
931
+ function Range({
932
+ selected,
933
+ onSelect,
934
+ placeholder = 'Pick a date range',
935
+ formatDate,
936
+ disabled = false,
937
+ locale,
938
+ defaultMonth,
939
+ className,
940
+ }: DatePickerRangeProps) {
941
+ const fmt = formatDate ?? ((d: Date) =>
942
+ d.toLocaleDateString(locale?.code ?? 'en-US', { month: 'short', day: 'numeric', year: 'numeric' }))
943
+ const [open, setOpen] = React.useState(false)
944
+ const ref = React.useRef<HTMLDivElement>(null)
945
+
946
+ React.useEffect(() => {
947
+ if (!open) return
948
+ const onMouseDown = (e: MouseEvent) => {
949
+ if (!ref.current?.contains(e.target as Node)) {
950
+ setOpen(false)
951
+ }
952
+ }
953
+ document.addEventListener('mousedown', onMouseDown)
954
+ return () => {
955
+ document.removeEventListener('mousedown', onMouseDown)
956
+ }
957
+ }, [open])
958
+
959
+ React.useEffect(() => {
960
+ if (!open) return
961
+ const onKeyDown = (e: KeyboardEvent) => {
962
+ if (e.key === 'Escape') setOpen(false)
963
+ }
964
+ document.addEventListener('keydown', onKeyDown)
965
+ return () => {
966
+ document.removeEventListener('keydown', onKeyDown)
967
+ }
968
+ }, [open])
969
+
970
+ const handleSelect = React.useCallback(
971
+ (range: DateRange | undefined) => {
972
+ onSelect?.(range)
973
+ const complete = range?.from && range?.to
974
+ && range.from.getTime() !== range.to.getTime()
975
+ if (complete) setOpen(false)
976
+ },
977
+ [onSelect]
978
+ )
979
+
980
+ const label = selected
981
+ ? formatRangeLabel(selected, fmt)
982
+ : undefined
983
+
984
+ return (
985
+ <div ref={ref} className={cn(styles.base, className)}>
986
+ <button
987
+ type="button"
988
+ className={styles.trigger}
989
+ disabled={disabled}
990
+ onClick={() => setOpen((v) => !v)}
991
+ >
992
+ <CalendarDays className={styles.icon} />
993
+ <span className={cn(styles.text, !label && styles.placeholder)}>
994
+ {label ?? placeholder}
995
+ </span>
996
+ </button>
997
+ <div className={cn(styles.content, open ? 'opacity-100 scale-100' : 'opacity-0 scale-95 pointer-events-none')}>
998
+ <Calendar.Range
999
+ locale={locale}
1000
+ selected={selected}
1001
+ onSelect={handleSelect}
1002
+ defaultMonth={defaultMonth ?? selected?.from}
1003
+ />
1004
+ </div>
1005
+ </div>
1006
+ )
1007
+ }
1008
+
1009
+ export { type DateRange, type Locale }
1010
+
1011
+ export const DatePicker = Object.assign(DatePickerRoot, {
1012
+ Range,
1013
+ })
1014
+ `;var ee=`'use client'
1015
+
1016
+ import * as React from 'react'
1017
+ import { Command as CommandPrimitive } from 'cmdk'
1018
+ import { Search } from 'lucide-react'
1019
+ import { cn } from '@/utils/cn'
1020
+ import { Dialog } from '@/components/ui/dialog'
1021
+
1022
+ const styles = {
1023
+ root: cn(
1024
+ 'flex flex-col overflow-hidden',
1025
+ 'bg-card border border-border rounded-[10px]'
1026
+ ),
1027
+ input: {
1028
+ wrapper: cn(
1029
+ 'flex items-center gap-2 px-3',
1030
+ 'border-b border-border'
1031
+ ),
1032
+ icon: 'w-4 h-4 shrink-0 text-muted-foreground',
1033
+ field: cn(
1034
+ 'flex h-10 w-full bg-transparent py-2',
1035
+ 'text-sm text-foreground outline-none',
1036
+ 'placeholder:text-muted-foreground',
1037
+ 'disabled:cursor-not-allowed disabled:opacity-50'
1038
+ ),
1039
+ },
1040
+ list: cn(
1041
+ 'h-[300px] overflow-y-auto overflow-x-hidden p-1',
1042
+ '[&_[cmdk-list-sizer]]:space-y-1'
1043
+ ),
1044
+ empty: cn(
1045
+ 'py-6 text-center text-sm',
1046
+ 'text-muted-foreground'
1047
+ ),
1048
+ loading: cn(
1049
+ 'py-6 text-center text-sm',
1050
+ 'text-muted-foreground'
1051
+ ),
1052
+ group: cn(
1053
+ 'overflow-hidden',
1054
+ '[&_[cmdk-group-heading]]:px-2',
1055
+ '[&_[cmdk-group-heading]]:py-1.5',
1056
+ '[&_[cmdk-group-heading]]:text-xs',
1057
+ '[&_[cmdk-group-heading]]:font-medium',
1058
+ '[&_[cmdk-group-heading]]:text-muted-foreground'
1059
+ ),
1060
+ item: cn(
1061
+ 'relative flex items-center gap-2 px-2 py-1.5',
1062
+ 'text-sm rounded-lg cursor-default select-none',
1063
+ 'data-[selected=true]:bg-accent',
1064
+ 'data-[selected=true]:text-accent-foreground',
1065
+ 'data-[disabled=true]:pointer-events-none',
1066
+ 'data-[disabled=true]:opacity-50'
1067
+ ),
1068
+ separator: '-mx-1 h-px bg-border',
1069
+ shortcut: cn(
1070
+ 'ml-auto text-xs tracking-widest',
1071
+ 'text-muted-foreground'
1072
+ ),
1073
+ }
1074
+
1075
+ function CommandRoot({
1076
+ className,
1077
+ ...props
1078
+ }: React.ComponentProps<typeof CommandPrimitive>) {
1079
+ return (
1080
+ <CommandPrimitive
1081
+ className={cn(styles.root, className)}
1082
+ {...props}
1083
+ />
1084
+ )
1085
+ }
1086
+
1087
+ function Input({
1088
+ className,
1089
+ ...props
1090
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
1091
+ return (
1092
+ <div className={styles.input.wrapper}>
1093
+ <Search className={styles.input.icon} />
1094
+ <CommandPrimitive.Input
1095
+ className={cn(styles.input.field, className)}
1096
+ {...props}
1097
+ />
1098
+ </div>
1099
+ )
1100
+ }
1101
+
1102
+ function List({
1103
+ className,
1104
+ ...props
1105
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
1106
+ return (
1107
+ <CommandPrimitive.List
1108
+ className={cn(styles.list, className)}
1109
+ {...props}
1110
+ />
1111
+ )
1112
+ }
1113
+
1114
+ function Empty({
1115
+ className,
1116
+ children,
1117
+ ...props
1118
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
1119
+ return (
1120
+ <CommandPrimitive.Empty
1121
+ className={cn(styles.empty, className)}
1122
+ {...props}
1123
+ >
1124
+ {children ?? 'No results found.'}
1125
+ </CommandPrimitive.Empty>
1126
+ )
1127
+ }
1128
+
1129
+ function Group({
1130
+ className,
1131
+ ...props
1132
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
1133
+ return (
1134
+ <CommandPrimitive.Group
1135
+ className={cn(styles.group, className)}
1136
+ {...props}
1137
+ />
1138
+ )
1139
+ }
1140
+
1141
+ function Item({
1142
+ className,
1143
+ ...props
1144
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
1145
+ return (
1146
+ <CommandPrimitive.Item
1147
+ className={cn(styles.item, className)}
1148
+ {...props}
1149
+ />
1150
+ )
1151
+ }
1152
+
1153
+ function Separator({
1154
+ className,
1155
+ ...props
1156
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
1157
+ return (
1158
+ <CommandPrimitive.Separator
1159
+ className={cn(styles.separator, className)}
1160
+ {...props}
1161
+ />
1162
+ )
1163
+ }
1164
+
1165
+ function Loading({
1166
+ className,
1167
+ ...props
1168
+ }: React.ComponentProps<typeof CommandPrimitive.Loading>) {
1169
+ return (
1170
+ <CommandPrimitive.Loading
1171
+ className={cn(styles.loading, className)}
1172
+ {...props}
1173
+ />
1174
+ )
1175
+ }
1176
+
1177
+ function Shortcut({
1178
+ className,
1179
+ ...props
1180
+ }: React.HTMLAttributes<HTMLElement>) {
1181
+ return (
1182
+ <kbd
1183
+ className={cn(styles.shortcut, className)}
1184
+ {...props}
1185
+ />
1186
+ )
1187
+ }
1188
+
1189
+ function CommandDialog({
1190
+ open,
1191
+ onOpenChange,
1192
+ label,
1193
+ className,
1194
+ children,
1195
+ }: {
1196
+ open: boolean
1197
+ onOpenChange: (open: boolean) => void
1198
+ label?: string
1199
+ className?: string
1200
+ children: React.ReactNode
1201
+ }) {
1202
+ React.useEffect(() => {
1203
+ const onKeyDown = (e: KeyboardEvent) => {
1204
+ if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
1205
+ e.preventDefault()
1206
+ onOpenChange(!open)
1207
+ }
1208
+ }
1209
+ document.addEventListener('keydown', onKeyDown)
1210
+ return () => {
1211
+ document.removeEventListener('keydown', onKeyDown)
1212
+ }
1213
+ }, [open, onOpenChange])
1214
+
1215
+ return (
1216
+ <Dialog open={open} onOpenChange={onOpenChange}>
1217
+ <Dialog.Content
1218
+ className={cn(
1219
+ 'p-0 max-w-lg rounded-[10px]',
1220
+ className
1221
+ )}
1222
+ >
1223
+ <CommandPrimitive
1224
+ label={label}
1225
+ className="flex flex-col overflow-hidden"
1226
+ >
1227
+ {children}
1228
+ </CommandPrimitive>
1229
+ </Dialog.Content>
1230
+ </Dialog>
1231
+ )
1232
+ }
1233
+
1234
+ export const Command = Object.assign(CommandRoot, {
1235
+ Input,
1236
+ List,
1237
+ Empty,
1238
+ Group,
1239
+ Item,
1240
+ Separator,
1241
+ Loading,
1242
+ Shortcut,
1243
+ Dialog: CommandDialog,
1244
+ })
1245
+ `;var te=`'use client'
1246
+
1247
+ import * as React from 'react'
1248
+ import useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'
1249
+ import { ChevronLeft, ChevronRight } from 'lucide-react'
1250
+ import { cn } from '@/utils/cn'
1251
+ import { Button } from '@/components/ui/button'
1252
+
1253
+ type CarouselApi = UseEmblaCarouselType[1]
1254
+ type CarouselOptions = Parameters<typeof useEmblaCarousel>[0]
1255
+ type CarouselPlugins = Parameters<typeof useEmblaCarousel>[1]
1256
+
1257
+ const styles = {
1258
+ root: 'relative focus-visible:outline-none',
1259
+ content: {
1260
+ viewport: 'overflow-hidden',
1261
+ container: 'flex',
1262
+ horizontal: '-ml-4',
1263
+ vertical: '-mt-4 flex-col h-full',
1264
+ },
1265
+ item: {
1266
+ base: 'min-w-0 shrink-0 grow-0 basis-full',
1267
+ horizontal: 'pl-4',
1268
+ vertical: 'pt-4',
1269
+ },
1270
+ arrow: cn(
1271
+ 'absolute top-1/2 -translate-y-1/2',
1272
+ 'w-8 px-0 bg-card/80 backdrop-blur-sm'
1273
+ ),
1274
+ dots: {
1275
+ wrapper: 'flex justify-center gap-1.5 mt-3',
1276
+ dot: cn(
1277
+ 'w-2 h-2 rounded-full transition-colors',
1278
+ 'bg-border cursor-pointer'
1279
+ ),
1280
+ active: 'bg-foreground',
1281
+ },
1282
+ }
1283
+
1284
+ interface CarouselCtx {
1285
+ emblaRef: UseEmblaCarouselType[0]
1286
+ api: CarouselApi
1287
+ canScrollPrev: boolean
1288
+ canScrollNext: boolean
1289
+ selectedIndex: number
1290
+ scrollSnaps: number[]
1291
+ orientation: 'horizontal' | 'vertical'
1292
+ }
1293
+
1294
+ interface CarouselRootProps
1295
+ extends React.HTMLAttributes<HTMLDivElement> {
1296
+ opts?: CarouselOptions
1297
+ plugins?: CarouselPlugins
1298
+ orientation?: 'horizontal' | 'vertical'
1299
+ setApi?: (api: CarouselApi) => void
1300
+ }
1301
+
1302
+ function CarouselRoot({
1303
+ opts,
1304
+ plugins,
1305
+ orientation = 'horizontal',
1306
+ setApi,
1307
+ className,
1308
+ children,
1309
+ ...props
1310
+ }: CarouselRootProps) {
1311
+ const [emblaRef, api] = useEmblaCarousel({ ...opts, axis: orientation === 'vertical' ? 'y' : 'x' }, plugins)
1312
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false)
1313
+ const [canScrollNext, setCanScrollNext] = React.useState(false)
1314
+ const [selectedIndex, setSelectedIndex] = React.useState(0)
1315
+ const [scrollSnaps, setScrollSnaps] = React.useState<number[]>([])
1316
+
1317
+ const onSelect = React.useCallback((emblaApi: NonNullable<CarouselApi>) => {
1318
+ setCanScrollPrev(emblaApi.canScrollPrev())
1319
+ setCanScrollNext(emblaApi.canScrollNext())
1320
+ setSelectedIndex(emblaApi.selectedScrollSnap())
1321
+ }, [])
1322
+
1323
+ React.useEffect(() => {
1324
+ if (!api) return
1325
+ setScrollSnaps(api.scrollSnapList())
1326
+ onSelect(api)
1327
+ api.on('reInit', onSelect)
1328
+ api.on('select', onSelect)
1329
+ return () => {
1330
+ api.off('reInit', onSelect)
1331
+ api.off('select', onSelect)
1332
+ }
1333
+ }, [api, onSelect])
1334
+
1335
+ React.useEffect(() => {
1336
+ if (setApi && api) setApi(api)
1337
+ }, [api, setApi])
1338
+
1339
+ const handleKeyDown = React.useCallback((e: React.KeyboardEvent) => {
1340
+ if (!api) return
1341
+ if (e.key === 'ArrowLeft') {
1342
+ e.preventDefault()
1343
+ api.scrollPrev()
1344
+ } else if (e.key === 'ArrowRight') {
1345
+ e.preventDefault()
1346
+ api.scrollNext()
1347
+ }
1348
+ }, [api])
1349
+
1350
+ return (
1351
+ <Ctx.Provider
1352
+ value={{
1353
+ emblaRef,
1354
+ api,
1355
+ canScrollPrev,
1356
+ canScrollNext,
1357
+ selectedIndex,
1358
+ scrollSnaps,
1359
+ orientation,
1360
+ }}
1361
+ >
1362
+ <div
1363
+ role="region"
1364
+ aria-roledescription="carousel"
1365
+ tabIndex={0}
1366
+ onKeyDown={handleKeyDown}
1367
+ className={cn(styles.root, className)}
1368
+ {...props}
1369
+ >
1370
+ {children}
1371
+ </div>
1372
+ </Ctx.Provider>
1373
+ )
1374
+ }
1375
+
1376
+ function Content({
1377
+ className,
1378
+ children,
1379
+ }: {
1380
+ className?: string
1381
+ children: React.ReactNode
1382
+ }) {
1383
+ const { emblaRef, orientation } = useCarousel()
1384
+ return (
1385
+ <div className={cn(styles.content.viewport, className)} ref={emblaRef}>
1386
+ <div className={cn(styles.content.container, orientation === 'vertical' ? styles.content.vertical : styles.content.horizontal)}>
1387
+ {children}
1388
+ </div>
1389
+ </div>
1390
+ )
1391
+ }
1392
+
1393
+ function Item({
1394
+ className,
1395
+ children,
1396
+ }: {
1397
+ className?: string
1398
+ children: React.ReactNode
1399
+ }) {
1400
+ const { orientation } = useCarousel()
1401
+ return (
1402
+ <div
1403
+ role="group"
1404
+ aria-roledescription="slide"
1405
+ className={cn(styles.item.base, orientation === 'vertical' ? styles.item.vertical : styles.item.horizontal, className)}
1406
+ >
1407
+ {children}
1408
+ </div>
1409
+ )
1410
+ }
1411
+
1412
+ function Previous({
1413
+ className,
1414
+ variant = 'secondary',
1415
+ size = 'sm',
1416
+ ...props
1417
+ }: React.ComponentProps<typeof Button>) {
1418
+ const { api, canScrollPrev } = useCarousel()
1419
+ return (
1420
+ <Button
1421
+ variant={variant}
1422
+ size={size}
1423
+ aria-label="Previous slide"
1424
+ className={cn(styles.arrow, '-left-12', className)}
1425
+ disabled={!canScrollPrev}
1426
+ onClick={() => api?.scrollPrev()}
1427
+ {...props}
1428
+ >
1429
+ <ChevronLeft className="w-4 h-4" />
1430
+ </Button>
1431
+ )
1432
+ }
1433
+
1434
+ function Next({
1435
+ className,
1436
+ variant = 'secondary',
1437
+ size = 'sm',
1438
+ ...props
1439
+ }: React.ComponentProps<typeof Button>) {
1440
+ const { api, canScrollNext } = useCarousel()
1441
+ return (
1442
+ <Button
1443
+ variant={variant}
1444
+ size={size}
1445
+ aria-label="Next slide"
1446
+ className={cn(styles.arrow, '-right-12', className)}
1447
+ disabled={!canScrollNext}
1448
+ onClick={() => api?.scrollNext()}
1449
+ {...props}
1450
+ >
1451
+ <ChevronRight className="w-4 h-4" />
1452
+ </Button>
1453
+ )
1454
+ }
1455
+
1456
+ function Dots({
1457
+ className,
1458
+ }: {
1459
+ className?: string
1460
+ }) {
1461
+ const { api, scrollSnaps, selectedIndex } = useCarousel()
1462
+ return (
1463
+ <div className={cn(styles.dots.wrapper, className)}>
1464
+ {scrollSnaps.map((_, i) => (
1465
+ <button
1466
+ key={i}
1467
+ type="button"
1468
+ aria-label={\`Go to slide \${i + 1}\`}
1469
+ className={cn(styles.dots.dot, i === selectedIndex && styles.dots.active)}
1470
+ onClick={() => api?.scrollTo(i)}
1471
+ />
1472
+ ))}
1473
+ </div>
1474
+ )
1475
+ }
1476
+
1477
+ const Ctx = React.createContext<CarouselCtx | null>(null)
1478
+
1479
+ function useCarousel() {
1480
+ const ctx = React.useContext(Ctx)
1481
+ if (!ctx) throw new Error('Carousel.* used outside <Carousel>')
1482
+ return ctx
1483
+ }
1484
+
1485
+ export type { CarouselApi }
1486
+
1487
+ export const Carousel = Object.assign(CarouselRoot, {
1488
+ Content,
1489
+ Item,
1490
+ Previous,
1491
+ Next,
1492
+ Dots
1493
+ })
1494
+ `;var oe=`import * as React from 'react'
497
1495
  import { cn } from '@/utils/cn'
498
1496
 
499
1497
  const styles = {
@@ -558,9 +1556,9 @@ function Info({
558
1556
 
559
1557
  export const Card = Object.assign(CardRoot, {
560
1558
  Preview,
561
- Info,
1559
+ Info
562
1560
  })
563
- `;var Y=`'use client'
1561
+ `;var ne=`'use client'
564
1562
 
565
1563
  import * as React from 'react'
566
1564
  import { Check } from 'lucide-react'
@@ -623,7 +1621,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(({
623
1621
  )
624
1622
 
625
1623
  Checkbox.displayName = 'Checkbox'
626
- `;var Z=`'use client'
1624
+ `;var re=`'use client'
627
1625
 
628
1626
  import * as React from 'react'
629
1627
  import { X } from 'lucide-react'
@@ -780,9 +1778,9 @@ function useDialog() {
780
1778
  export const Dialog = Object.assign(DialogRoot, {
781
1779
  Trigger,
782
1780
  Content,
783
- Close,
1781
+ Close
784
1782
  })
785
- `;var ee=`'use client'
1783
+ `;var se=`'use client'
786
1784
 
787
1785
  import * as React from 'react'
788
1786
  import { cn } from '@/utils/cn'
@@ -978,9 +1976,9 @@ export const Dropdown = Object.assign(DropdownRoot, {
978
1976
  Item,
979
1977
  Group,
980
1978
  Label,
981
- Separator: DropdownSeparator,
1979
+ Separator: DropdownSeparator
982
1980
  })
983
- `;var te=`import * as React from 'react'
1981
+ `;var ae=`import * as React from 'react'
984
1982
  import { cn } from '@/utils/cn'
985
1983
 
986
1984
  const styles = {
@@ -1003,7 +2001,157 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(({
1003
2001
  )
1004
2002
 
1005
2003
  Input.displayName = 'Input'
1006
- `;var oe=`'use client'
2004
+ `;var ce=`import * as React from 'react'
2005
+ import { cn } from '@/utils/cn'
2006
+
2007
+ export function Label({
2008
+ className,
2009
+ ...props
2010
+ }: React.LabelHTMLAttributes<HTMLLabelElement>) {
2011
+ return (
2012
+ <label
2013
+ className={cn(
2014
+ 'text-sm font-medium text-foreground',
2015
+ className
2016
+ )}
2017
+ {...props}
2018
+ />
2019
+ )
2020
+ }
2021
+ `;var ie=`import * as React from 'react'
2022
+ import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react'
2023
+ import { cn } from '@/utils/cn'
2024
+
2025
+ const styles = {
2026
+ nav: 'mx-auto flex w-full justify-center',
2027
+ content: 'flex flex-row items-center gap-1',
2028
+ link: cn(
2029
+ 'inline-flex items-center justify-center',
2030
+ 'h-9 min-w-9 px-3 rounded-[10px] text-sm',
2031
+ 'text-muted-foreground hover:text-foreground',
2032
+ 'hover:bg-accent transition-colors cursor-pointer'
2033
+ ),
2034
+ active: cn(
2035
+ 'bg-foreground text-background',
2036
+ 'hover:bg-foreground hover:text-background'
2037
+ ),
2038
+ nav_link: cn(
2039
+ 'inline-flex items-center justify-center',
2040
+ 'h-9 px-3 gap-1 rounded-[10px] text-sm',
2041
+ 'text-muted-foreground hover:text-foreground',
2042
+ 'hover:bg-accent transition-colors cursor-pointer'
2043
+ ),
2044
+ ellipsis: cn(
2045
+ 'flex h-9 w-9 items-center justify-center',
2046
+ 'text-muted-foreground'
2047
+ ),
2048
+ }
2049
+
2050
+ function PaginationRoot({
2051
+ className,
2052
+ ...props
2053
+ }: React.ComponentProps<'nav'>) {
2054
+ return (
2055
+ <nav
2056
+ role="navigation"
2057
+ aria-label="pagination"
2058
+ className={cn(styles.nav, className)}
2059
+ {...props}
2060
+ />
2061
+ )
2062
+ }
2063
+
2064
+ function Content({
2065
+ className,
2066
+ ...props
2067
+ }: React.ComponentProps<'ul'>) {
2068
+ return (
2069
+ <ul
2070
+ className={cn(styles.content, className)}
2071
+ {...props}
2072
+ />
2073
+ )
2074
+ }
2075
+
2076
+ function Item({
2077
+ className,
2078
+ ...props
2079
+ }: React.ComponentProps<'li'>) {
2080
+ return <li className={className} {...props} />
2081
+ }
2082
+
2083
+ function Link({
2084
+ isActive,
2085
+ className,
2086
+ ...props
2087
+ }: React.AnchorHTMLAttributes<HTMLAnchorElement> & {
2088
+ isActive?: boolean
2089
+ }) {
2090
+ return (
2091
+ <a
2092
+ aria-current={isActive ? 'page' : undefined}
2093
+ className={cn(styles.link, isActive && styles.active, className)}
2094
+ {...props}
2095
+ />
2096
+ )
2097
+ }
2098
+
2099
+ function Previous({
2100
+ className,
2101
+ children,
2102
+ ...props
2103
+ }: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
2104
+ return (
2105
+ <a
2106
+ aria-label="Go to previous page"
2107
+ className={cn(styles.nav_link, className)}
2108
+ {...props}
2109
+ >
2110
+ <ChevronLeft className="h-4 w-4" />
2111
+ {children ?? <span>Previous</span>}
2112
+ </a>
2113
+ )
2114
+ }
2115
+
2116
+ function Next({
2117
+ className,
2118
+ children,
2119
+ ...props
2120
+ }: React.AnchorHTMLAttributes<HTMLAnchorElement>) {
2121
+ return (
2122
+ <a
2123
+ aria-label="Go to next page"
2124
+ className={cn(styles.nav_link, className)}
2125
+ {...props}
2126
+ >
2127
+ {children ?? <span>Next</span>}
2128
+ <ChevronRight className="h-4 w-4" />
2129
+ </a>
2130
+ )
2131
+ }
2132
+
2133
+ function PaginationEllipsis({
2134
+ className,
2135
+ }: {
2136
+ className?: string
2137
+ }) {
2138
+ return (
2139
+ <span className={cn(styles.ellipsis, className)}>
2140
+ <MoreHorizontal className="h-4 w-4" />
2141
+ <span className="sr-only">More pages</span>
2142
+ </span>
2143
+ )
2144
+ }
2145
+
2146
+ export const Pagination = Object.assign(PaginationRoot, {
2147
+ Content,
2148
+ Item,
2149
+ Link,
2150
+ Previous,
2151
+ Next,
2152
+ Ellipsis: PaginationEllipsis,
2153
+ })
2154
+ `;var le=`'use client'
1007
2155
 
1008
2156
  import * as React from 'react'
1009
2157
  import { cn } from '@/utils/cn'
@@ -1106,9 +2254,9 @@ function usePopover() {
1106
2254
 
1107
2255
  export const Popover = Object.assign(PopoverRoot, {
1108
2256
  Trigger,
1109
- Content,
2257
+ Content
1110
2258
  })
1111
- `;var ne=`import * as React from 'react'
2259
+ `;var de=`import * as React from 'react'
1112
2260
  import { cn } from '@/utils/cn'
1113
2261
 
1114
2262
  const styles = {
@@ -1146,7 +2294,156 @@ export function Progress({
1146
2294
  </div>
1147
2295
  )
1148
2296
  }
1149
- `;var re=`'use client'
2297
+ `;var pe=`'use client'
2298
+
2299
+ import * as React from 'react'
2300
+ import { cn } from '@/utils/cn'
2301
+
2302
+ const styles = {
2303
+ group: 'flex flex-col gap-3',
2304
+ horizontal: 'flex-row gap-4',
2305
+ item: 'flex items-start gap-2 cursor-pointer',
2306
+ radio: cn(
2307
+ 'aspect-square w-4 mt-[3px] border border-input shadow-xs',
2308
+ 'transition-[color,box-shadow] flex-shrink-0',
2309
+ 'flex items-center justify-center',
2310
+ 'peer-focus-visible:ring-[3px]',
2311
+ 'peer-focus-visible:ring-ring/50',
2312
+ 'peer-focus-visible:border-ring'
2313
+ ),
2314
+ checked: 'bg-foreground border-foreground',
2315
+ indicator: 'w-2 h-2 bg-background',
2316
+ label: 'text-sm font-medium text-foreground select-none',
2317
+ description: 'text-sm text-muted-foreground select-none',
2318
+ variants: {
2319
+ circle: 'rounded-full',
2320
+ square: 'rounded-[4px]',
2321
+ },
2322
+ indicators: {
2323
+ circle: 'rounded-full',
2324
+ square: 'rounded-[2px]',
2325
+ },
2326
+ }
2327
+
2328
+ interface RadioGroupCtx {
2329
+ value: string
2330
+ onSelect: (v: string) => void
2331
+ disabled?: boolean
2332
+ variant: 'circle' | 'square'
2333
+ }
2334
+
2335
+ function RadioGroupRoot({
2336
+ children,
2337
+ defaultValue,
2338
+ value: controlledValue,
2339
+ onValueChange,
2340
+ orientation = 'vertical',
2341
+ variant = 'circle',
2342
+ disabled,
2343
+ className,
2344
+ }: {
2345
+ children: React.ReactNode
2346
+ defaultValue?: string
2347
+ value?: string
2348
+ onValueChange?: (value: string) => void
2349
+ orientation?: 'vertical' | 'horizontal'
2350
+ variant?: 'circle' | 'square'
2351
+ disabled?: boolean
2352
+ className?: string
2353
+ }) {
2354
+ const [internal, setInternal] = React.useState(
2355
+ defaultValue ?? ''
2356
+ )
2357
+ const isControlled = controlledValue !== undefined
2358
+ const current = isControlled ? controlledValue : internal
2359
+
2360
+ const onSelect = (v: string) => {
2361
+ if (!isControlled) setInternal(v)
2362
+ onValueChange?.(v)
2363
+ }
2364
+
2365
+ return (
2366
+ <Ctx.Provider value={{ value: current, onSelect, disabled, variant }}>
2367
+ <div
2368
+ role="radiogroup"
2369
+ className={cn(
2370
+ styles.group,
2371
+ orientation === 'horizontal' && styles.horizontal,
2372
+ className
2373
+ )}
2374
+ >
2375
+ {children}
2376
+ </div>
2377
+ </Ctx.Provider>
2378
+ )
2379
+ }
2380
+
2381
+ const Item = React.forwardRef<
2382
+ HTMLInputElement,
2383
+ {
2384
+ value: string
2385
+ label?: string
2386
+ description?: string
2387
+ children?: React.ReactNode
2388
+ disabled?: boolean
2389
+ className?: string
2390
+ } & Omit<
2391
+ React.InputHTMLAttributes<HTMLInputElement>,
2392
+ 'type' | 'value'
2393
+ >
2394
+ >(({ value, label, description, children, disabled, className, ...props }, ref) => {
2395
+ const ctx = useRadioGroup()
2396
+ const isDisabled = disabled ?? ctx.disabled
2397
+ const isChecked = ctx.value === value
2398
+
2399
+ return (
2400
+ <label
2401
+ className={cn(
2402
+ styles.item,
2403
+ isDisabled && 'opacity-50 cursor-not-allowed',
2404
+ className
2405
+ )}
2406
+ >
2407
+ <input
2408
+ ref={ref}
2409
+ type="radio"
2410
+ className="peer sr-only"
2411
+ checked={isChecked}
2412
+ disabled={isDisabled}
2413
+ onChange={() => {
2414
+ if (!isDisabled) ctx.onSelect(value)
2415
+ }}
2416
+ {...props}
2417
+ />
2418
+ <span className={cn(styles.radio, styles.variants[ctx.variant], isChecked && styles.checked)}>
2419
+ {isChecked && <span className={cn(styles.indicator, styles.indicators[ctx.variant])} />}
2420
+ </span>
2421
+ {children ?? (label && (
2422
+ <div className="flex flex-col gap-0.5">
2423
+ <span className={styles.label}>{label}</span>
2424
+ {description && (
2425
+ <span className={styles.description}>
2426
+ {description}
2427
+ </span>
2428
+ )}
2429
+ </div>
2430
+ ))}
2431
+ </label>
2432
+ )
2433
+ })
2434
+
2435
+ Item.displayName = 'RadioGroup.Item'
2436
+
2437
+ const Ctx = React.createContext<RadioGroupCtx | null>(null)
2438
+
2439
+ function useRadioGroup() {
2440
+ const ctx = React.useContext(Ctx)
2441
+ if (!ctx) throw new Error('RadioGroup compound used outside <RadioGroup>')
2442
+ return ctx
2443
+ }
2444
+
2445
+ export const RadioGroup = Object.assign(RadioGroupRoot, { Item })
2446
+ `;var ue=`'use client'
1150
2447
 
1151
2448
  import * as React from 'react'
1152
2449
  import { ChevronDown } from 'lucide-react'
@@ -1298,9 +2595,9 @@ function useSelect() {
1298
2595
  export const Select = Object.assign(SelectRoot, {
1299
2596
  Trigger,
1300
2597
  Menu,
1301
- Option,
2598
+ Option
1302
2599
  })
1303
- `;var se=`import * as React from 'react'
2600
+ `;var me=`import * as React from 'react'
1304
2601
  import { cn } from '@/utils/cn'
1305
2602
 
1306
2603
  const styles = {
@@ -1324,7 +2621,7 @@ export function Separator({
1324
2621
  />
1325
2622
  )
1326
2623
  }
1327
- `;var ae=`'use client'
2624
+ `;var fe=`'use client'
1328
2625
 
1329
2626
  import * as React from 'react'
1330
2627
  import { cn } from '@/utils/cn'
@@ -1365,7 +2662,7 @@ export function Switch({
1365
2662
  </button>
1366
2663
  )
1367
2664
  }
1368
- `;var ce=`'use client'
2665
+ `;var ge=`'use client'
1369
2666
 
1370
2667
  import * as React from 'react'
1371
2668
  import { cn } from '@/utils/cn'
@@ -1477,9 +2774,9 @@ function useTabs() {
1477
2774
  export const Tabs = Object.assign(TabsRoot, {
1478
2775
  List,
1479
2776
  Tab,
1480
- Panel,
2777
+ Panel
1481
2778
  })
1482
- `;var ie=`import * as React from 'react'
2779
+ `;var he=`import * as React from 'react'
1483
2780
  import { cn } from '@/utils/cn'
1484
2781
 
1485
2782
  const styles = {
@@ -1506,7 +2803,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({
1506
2803
  ))
1507
2804
 
1508
2805
  Textarea.displayName = 'Textarea'
1509
- `;var le=`'use client'
2806
+ `;var be=`'use client'
1510
2807
 
1511
2808
  import * as React from 'react'
1512
2809
  import { Toaster as Sonner, toast } from 'sonner'
@@ -1549,7 +2846,181 @@ function Toaster() {
1549
2846
  }
1550
2847
 
1551
2848
  export { Toaster, toast }
1552
- `;var de=`import * as React from 'react'
2849
+ `;var ve=`import * as React from 'react'
2850
+ import { cn } from '@/utils/cn'
2851
+
2852
+ const styles = {
2853
+ wrapper: 'w-full overflow-x-auto',
2854
+ base: 'w-full caption-bottom text-sm border-collapse',
2855
+ variants: {
2856
+ default: '',
2857
+ striped: '[&_tbody_tr:nth-child(even)]:bg-muted/30',
2858
+ bordered: '[&_th]:border [&_td]:border',
2859
+ },
2860
+ caption: 'mt-3 text-sm text-muted-foreground',
2861
+ header: '[&_tr]:border-b [&_tr]:border-border',
2862
+ body: '[&_tr:last-child]:border-0',
2863
+ footer: 'border-t border-border bg-muted/30 font-medium',
2864
+ row: 'border-b border-border transition-colors hover:bg-muted/40',
2865
+ head: cn(
2866
+ 'px-4 py-2.5 text-left font-semibold',
2867
+ 'text-muted-foreground',
2868
+ '[&[align=center]]:text-center',
2869
+ '[&[align=right]]:text-right'
2870
+ ),
2871
+ cell: cn(
2872
+ 'px-4 py-2.5 text-foreground',
2873
+ '[&[align=center]]:text-center',
2874
+ '[&[align=right]]:text-right'
2875
+ ),
2876
+ }
2877
+
2878
+ function TableRoot({
2879
+ variant = 'default',
2880
+ className,
2881
+ children,
2882
+ ...props
2883
+ }: {
2884
+ variant?: keyof typeof styles.variants
2885
+ className?: string
2886
+ children: React.ReactNode
2887
+ } & Omit<
2888
+ React.ComponentPropsWithoutRef<'table'>,
2889
+ 'className' | 'children'
2890
+ >) {
2891
+ return (
2892
+ <div className={styles.wrapper}>
2893
+ <table
2894
+ className={cn(
2895
+ styles.base,
2896
+ styles.variants[variant],
2897
+ className
2898
+ )}
2899
+ {...props}
2900
+ >
2901
+ {children}
2902
+ </table>
2903
+ </div>
2904
+ )
2905
+ }
2906
+
2907
+ function Caption({
2908
+ className,
2909
+ children,
2910
+ ...props
2911
+ }: React.ComponentPropsWithoutRef<'caption'>) {
2912
+ return (
2913
+ <caption
2914
+ className={cn(styles.caption, className)}
2915
+ {...props}
2916
+ >
2917
+ {children}
2918
+ </caption>
2919
+ )
2920
+ }
2921
+
2922
+ function Header({
2923
+ className,
2924
+ children,
2925
+ ...props
2926
+ }: React.ComponentPropsWithoutRef<'thead'>) {
2927
+ return (
2928
+ <thead
2929
+ className={cn(styles.header, className)}
2930
+ {...props}
2931
+ >
2932
+ {children}
2933
+ </thead>
2934
+ )
2935
+ }
2936
+
2937
+ function Body({
2938
+ className,
2939
+ children,
2940
+ ...props
2941
+ }: React.ComponentPropsWithoutRef<'tbody'>) {
2942
+ return (
2943
+ <tbody
2944
+ className={cn(styles.body, className)}
2945
+ {...props}
2946
+ >
2947
+ {children}
2948
+ </tbody>
2949
+ )
2950
+ }
2951
+
2952
+ function Footer({
2953
+ className,
2954
+ children,
2955
+ ...props
2956
+ }: React.ComponentPropsWithoutRef<'tfoot'>) {
2957
+ return (
2958
+ <tfoot
2959
+ className={cn(styles.footer, className)}
2960
+ {...props}
2961
+ >
2962
+ {children}
2963
+ </tfoot>
2964
+ )
2965
+ }
2966
+
2967
+ function Row({
2968
+ className,
2969
+ children,
2970
+ ...props
2971
+ }: React.ComponentPropsWithoutRef<'tr'>) {
2972
+ return (
2973
+ <tr
2974
+ className={cn(styles.row, className)}
2975
+ {...props}
2976
+ >
2977
+ {children}
2978
+ </tr>
2979
+ )
2980
+ }
2981
+
2982
+ function Head({
2983
+ scope = 'col',
2984
+ className,
2985
+ children,
2986
+ ...props
2987
+ }: React.ComponentPropsWithoutRef<'th'>) {
2988
+ return (
2989
+ <th
2990
+ scope={scope}
2991
+ className={cn(styles.head, className)}
2992
+ {...props}
2993
+ >
2994
+ {children}
2995
+ </th>
2996
+ )
2997
+ }
2998
+
2999
+ function Cell({
3000
+ className,
3001
+ children,
3002
+ ...props
3003
+ }: React.ComponentPropsWithoutRef<'td'>) {
3004
+ return (
3005
+ <td
3006
+ className={cn(styles.cell, className)}
3007
+ {...props}
3008
+ >
3009
+ {children}
3010
+ </td>
3011
+ )
3012
+ }
3013
+
3014
+ export const Table = Object.assign(TableRoot, {
3015
+ Caption,
3016
+ Header,
3017
+ Body,
3018
+ Footer,
3019
+ Row,
3020
+ Head,
3021
+ Cell,
3022
+ })
3023
+ `;var xe=`import * as React from 'react'
1553
3024
  import { cn } from '@/utils/cn'
1554
3025
 
1555
3026
  const styles = {
@@ -1594,4 +3065,15 @@ export function Tooltip({
1594
3065
  </span>
1595
3066
  )
1596
3067
  }
1597
- `;var R=[{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:[]}],P={accordion:W,alert:X,avatar:q,badge:J,button:K,card:Q,checkbox:Y,dialog:Z,dropdown:ee,input:te,popover:oe,progress:ne,select:re,separator:se,switch:ae,tabs:ce,textarea:ie,theme:G,toast:le,tooltip:de};async function pe(t){let n=process.cwd();e.intro("drivn add");let c=V(n);if(c||(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:R.map(s=>({label:s.name,hint:s.description,value:s.name})),required:true});e.isCancel(o)&&(e.cancel("Cancelled"),process.exit(0)),t=o;}let v=t.filter(o=>!R.find(s=>s.name===o));v.length&&(e.log.error(`Unknown components: ${v.join(", ")}`),e.log.info("Available: "+R.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,b=new Set,g=o=>{if(f.has(o))return;let s=R.find(a=>a.name===o);s&&(s.dependencies.forEach(a=>g(a)),s.npmDependencies?.forEach(a=>b.add(a)),f.add(o));};m.forEach(g),d&&b.add("next-themes");let x=[...f].filter(o=>!m.includes(o));x.length&&e.log.info(`Required dependency: ${x.join(", ")}`);let l=c.typescript?"tsx":"jsx",N=join(n,c.paths.components);for(let o of f){let s=join(N,`${o}.${l}`);if(h(s)){let w=await e.confirm({message:`${o}.${l} exists. Overwrite?`,initialValue:false});if(e.isCancel(w)||!w){e.log.warn(`Skipped ${o}`);continue}}let a=P[o];a=a.replace(/@\/utils/g,`@/${c.paths.utils.replace(/^src\//,"")}`),p(s,a),e.log.success(`${o} \u2192 ${c.paths.components}/${o}.${l}`);}if(d){let o=join(N,`theme-provider.${l}`);if(h(o)){let a=await e.confirm({message:`theme-provider.${l} exists. Overwrite?`,initialValue:false});!e.isCancel(a)&&a?(p(o,P.theme),e.log.success(`theme-provider \u2192 ${c.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else p(o,P.theme),e.log.success(`theme-provider \u2192 ${c.paths.components}/theme-provider.${l}`);if(c.paths.globals){let a=join(n,c.paths.globals);if(h(a)){let w=F(a);w.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(p(a,w+L),e.log.success(`Theme tokens appended to ${i.cyan(c.paths.globals)}`));}else e.log.warn(`Globals file not found at ${c.paths.globals}`);}else e.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let s=c.paths.components.replace(/^src\//,"@/");e.log.message(""),e.log.info(i.bold("Complete the setup:")),e.log.message(""),e.log.message(i.bold(`${i.cyan("1.")} Import ThemeProvider in your root layout:`)),e.log.message(i.cyan(` import { ThemeProvider } from "${s}/theme-provider"`)),e.log.message(""),e.log.message(i.bold(`${i.cyan("2.")} Add suppressHydrationWarning to <html>:`)),e.log.message(i.cyan(" <html suppressHydrationWarning>")),e.log.message(""),e.log.message(i.bold(`${i.cyan("3.")} Wrap your app with ThemeProvider:`)),e.log.message(i.cyan(" <ThemeProvider>")),e.log.message(i.cyan(" {children}")),e.log.message(i.cyan(" </ThemeProvider>")),e.log.message("");}if(b.size){let o=k(n),s=[...b],a=e.spinner();a.start("Installing packages");try{execSync(y(o,s),{cwd:n,stdio:"ignore"}),a.stop("Packages installed");}catch{a.stop("Failed to install packages"),e.log.warn(`Run manually: ${y(o,s)}`);}}e.outro("Done.");}var ue={version:"1.1.0"};var D=new Command;D.name("drivn").description("Drivn \u2014 Modern UI components").version(ue.version);D.command("create").description("Initialize Drivn in your project").action(U);D.command("add [components...]").description("Add components to your project").action(pe);D.parse();
3068
+ `;var ye=`
3069
+ /* react-day-picker theme integration */
3070
+ .rdp-root {
3071
+ --rdp-accent-color: var(--primary);
3072
+ --rdp-accent-background-color: var(--accent);
3073
+ --rdp-day-height: 36px;
3074
+ --rdp-day-width: 36px;
3075
+ --rdp-selected-font: inherit;
3076
+ --rdp-selected-border: none;
3077
+ --rdp-day_button-border: none;
3078
+ }
3079
+ `,w=[{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:"breadcrumb",description:"Breadcrumb navigation with auto-separators, ellipsis, and dot notation",dependencies:[],npmDependencies:[]},{name:"button",description:"Button with variants, sizes, loading state, and icon slots",dependencies:[],npmDependencies:[]},{name:"calendar",description:"Date picker powered by react-day-picker with single, range, and dropdown modes",dependencies:[],npmDependencies:["react-day-picker"]},{name:"date-picker",description:"Date picker input with Calendar dropdown for single date and range selection",dependencies:["calendar"],npmDependencies:[]},{name:"command",description:"Searchable command menu with filtering, keyboard navigation, and dialog mode",dependencies:["dialog"],npmDependencies:["cmdk"]},{name:"carousel",description:"Carousel with touch/swipe, navigation arrows, dot indicators, and loop mode",dependencies:["button"],npmDependencies:["embla-carousel-react"]},{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:"label",description:"Accessible form label for inputs, checkboxes, and selects",dependencies:[],npmDependencies:[]},{name:"pagination",description:"Page navigation with dot notation, Previous/Next, ellipsis, and active 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:"radio-group",description:"Radio group with dot notation, orientation support, and controlled/uncontrolled selection",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:"table",description:"Data table with dot notation, striped/bordered variants, and responsive overflow",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:[]}],S={accordion:Y,alert:W,avatar:U,badge:q,breadcrumb:X,button:J,calendar:Q,"date-picker":Z,command:ee,carousel:te,card:oe,checkbox:ne,dialog:re,dropdown:se,input:ae,label:ce,pagination:ie,popover:le,progress:de,"radio-group":pe,select:ue,separator:me,switch:fe,table:ve,tabs:ge,textarea:he,theme:K,toast:be,tooltip:xe};async function Ne(t){let n=process.cwd();e.intro("drivn add");let a=_(n);if(a||(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:w.map(r=>({label:r.name,hint:r.description,value:r.name})),required:true});e.isCancel(o)&&(e.cancel("Cancelled"),process.exit(0)),t=o;}let b=t.filter(o=>!w.find(r=>r.name===o));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+w.map(o=>o.name).join(", ")),e.outro("Cancelled"),process.exit(1));let p=t.includes("theme"),g=t.filter(o=>o!=="theme"),u=new Set,v=new Set,h=o=>{if(u.has(o))return;let r=w.find(c=>c.name===o);r&&(r.dependencies.forEach(c=>h(c)),r.npmDependencies?.forEach(c=>v.add(c)),u.add(o));};g.forEach(h),p&&v.add("next-themes");let x=[...u].filter(o=>!g.includes(o));x.length&&e.log.info(`Required dependency: ${x.join(", ")}`);let l=a.typescript?"tsx":"jsx",N=join(n,a.paths.components);for(let o of u){let r=join(N,`${o}.${l}`);if(m(r)){let C=await e.confirm({message:`${o}.${l} exists. Overwrite?`,initialValue:false});if(e.isCancel(C)||!C){e.log.warn(`Skipped ${o}`);continue}}let c=S[o];c=c.replace(/@\/utils/g,`@/${a.paths.utils.replace(/^src\//,"")}`),d(r,c),e.log.success(`${o} \u2192 ${a.paths.components}/${o}.${l}`);}if(p){let o=join(N,`theme-provider.${l}`);if(m(o)){let c=await e.confirm({message:`theme-provider.${l} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(d(o,S.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else d(o,S.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`);if(a.paths.globals){let c=join(n,a.paths.globals);if(m(c)){let C=M(c);C.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(d(c,C+O),e.log.success(`Theme tokens appended to ${i.cyan(a.paths.globals)}`));}else e.log.warn(`Globals file not found at ${a.paths.globals}`);}else e.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let r=a.paths.components.replace(/^src\//,"@/");e.log.message(""),e.log.info(i.bold("Complete the setup:")),e.log.message(""),e.log.message(i.bold(`${i.cyan("1.")} Import ThemeProvider in your root layout:`)),e.log.message(i.cyan(` import { ThemeProvider } from "${r}/theme-provider"`)),e.log.message(""),e.log.message(i.bold(`${i.cyan("2.")} Add suppressHydrationWarning to <html>:`)),e.log.message(i.cyan(" <html suppressHydrationWarning>")),e.log.message(""),e.log.message(i.bold(`${i.cyan("3.")} Wrap your app with ThemeProvider:`)),e.log.message(i.cyan(" <ThemeProvider>")),e.log.message(i.cyan(" {children}")),e.log.message(i.cyan(" </ThemeProvider>")),e.log.message("");}if(u.has("calendar")&&a.paths.globals){let o=join(n,a.paths.globals);if(m(o)){let r=M(o);r.includes(".rdp-root")?e.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(d(o,r+ye),e.log.success(`Calendar tokens appended to ${i.cyan(a.paths.globals)}`));}}if(v.size){let o=P(n),r=[...v],c=e.spinner();c.start("Installing packages");try{execSync(y(o,r),{cwd:n,stdio:"ignore"}),c.stop("Packages installed");}catch{c.stop("Failed to install packages"),e.log.warn(`Run manually: ${y(o,r)}`);}}e.outro("Done.");}var Ce={version:"1.3.0"};var T=new Command;T.name("drivn").description("Drivn \u2014 Modern UI components").version(Ce.version);T.command("create").description("Initialize Drivn in your project").action(G);T.command("add [components...]").description("Add components to your project").action(Ne);T.parse();