drivn 1.2.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 +618 -29
  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 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")),v={...a.dependencies,...a.devDependencies},p="react";v.next&&(p="next");let g=existsSync(join(t,"src")),u=existsSync(join(t,"tsconfig.json"));return {framework:p,srcDir:g,typescript:u}}var $="drivn.config.json";function V(t){let n=join(t,$);return existsSync(n)?JSON.parse(readFileSync(n,"utf-8")):null}function _(t,n){let a=join(t,$);writeFileSync(a,JSON.stringify(n,null,2));}function Ne(t){existsSync(t)||mkdirSync(t,{recursive:true});}function d(t,n){Ne(dirname(t)),writeFileSync(t,n);}function O(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";
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
- `,M=`
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 ke=`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
- `,Pe=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function De(t){for(let n of Pe)if(m(join(t,n)))return n;return null}async function K(){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",v=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:v,defaultValue:v})},{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",b=join(t,p.utils,`cn.${u}`);m(b)||d(b,ke);let h=De(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 Y=`'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 U=`'use client'
164
+ `;var Y=`'use client'
165
165
 
166
166
  import * as React from 'react'
167
167
  import { ChevronDown } from 'lucide-react'
@@ -293,7 +293,7 @@ export const Accordion = Object.assign(AccordionRoot, {
293
293
  Trigger,
294
294
  Content
295
295
  })
296
- `;var G=`import * as React from 'react'
296
+ `;var W=`import * as React from 'react'
297
297
  import { cn } from '@/utils/cn'
298
298
 
299
299
  const styles = {
@@ -341,7 +341,7 @@ export function Alert({
341
341
  </div>
342
342
  )
343
343
  }
344
- `;var W=`import * as React from 'react'
344
+ `;var U=`import * as React from 'react'
345
345
  import { cn } from '@/utils/cn'
346
346
 
347
347
  const styles = {
@@ -385,7 +385,7 @@ export function Avatar({
385
385
  </div>
386
386
  )
387
387
  }
388
- `;var X=`import * as React from 'react'
388
+ `;var q=`import * as React from 'react'
389
389
  import { cn } from '@/utils/cn'
390
390
 
391
391
  const styles = {
@@ -415,7 +415,123 @@ export function Badge({ variant = 'default', className, children }: BadgeProps)
415
415
  </span>
416
416
  )
417
417
  }
418
- `;var q=`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'
419
535
  import { Loader2 } from 'lucide-react'
420
536
  import { cn } from '@/utils/cn'
421
537
 
@@ -495,7 +611,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(({
495
611
  )
496
612
 
497
613
  Button.displayName = 'Button'
498
- `;var J=`'use client'
614
+ `;var Q=`'use client'
499
615
 
500
616
  import * as React from 'react'
501
617
  import {
@@ -671,7 +787,7 @@ export { type DateRange, type Locale }
671
787
  export const Calendar = Object.assign(CalendarRoot, {
672
788
  Range
673
789
  })
674
- `;var Q=`'use client'
790
+ `;var Z=`'use client'
675
791
 
676
792
  import * as React from 'react'
677
793
  import { CalendarDays } from 'lucide-react'
@@ -895,7 +1011,7 @@ export { type DateRange, type Locale }
895
1011
  export const DatePicker = Object.assign(DatePickerRoot, {
896
1012
  Range,
897
1013
  })
898
- `;var Z=`'use client'
1014
+ `;var ee=`'use client'
899
1015
 
900
1016
  import * as React from 'react'
901
1017
  import { Command as CommandPrimitive } from 'cmdk'
@@ -1126,7 +1242,7 @@ export const Command = Object.assign(CommandRoot, {
1126
1242
  Shortcut,
1127
1243
  Dialog: CommandDialog,
1128
1244
  })
1129
- `;var ee=`'use client'
1245
+ `;var te=`'use client'
1130
1246
 
1131
1247
  import * as React from 'react'
1132
1248
  import useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'
@@ -1375,7 +1491,7 @@ export const Carousel = Object.assign(CarouselRoot, {
1375
1491
  Next,
1376
1492
  Dots
1377
1493
  })
1378
- `;var te=`import * as React from 'react'
1494
+ `;var oe=`import * as React from 'react'
1379
1495
  import { cn } from '@/utils/cn'
1380
1496
 
1381
1497
  const styles = {
@@ -1442,7 +1558,7 @@ export const Card = Object.assign(CardRoot, {
1442
1558
  Preview,
1443
1559
  Info
1444
1560
  })
1445
- `;var oe=`'use client'
1561
+ `;var ne=`'use client'
1446
1562
 
1447
1563
  import * as React from 'react'
1448
1564
  import { Check } from 'lucide-react'
@@ -1505,7 +1621,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(({
1505
1621
  )
1506
1622
 
1507
1623
  Checkbox.displayName = 'Checkbox'
1508
- `;var ne=`'use client'
1624
+ `;var re=`'use client'
1509
1625
 
1510
1626
  import * as React from 'react'
1511
1627
  import { X } from 'lucide-react'
@@ -1664,7 +1780,7 @@ export const Dialog = Object.assign(DialogRoot, {
1664
1780
  Content,
1665
1781
  Close
1666
1782
  })
1667
- `;var re=`'use client'
1783
+ `;var se=`'use client'
1668
1784
 
1669
1785
  import * as React from 'react'
1670
1786
  import { cn } from '@/utils/cn'
@@ -1862,7 +1978,7 @@ export const Dropdown = Object.assign(DropdownRoot, {
1862
1978
  Label,
1863
1979
  Separator: DropdownSeparator
1864
1980
  })
1865
- `;var se=`import * as React from 'react'
1981
+ `;var ae=`import * as React from 'react'
1866
1982
  import { cn } from '@/utils/cn'
1867
1983
 
1868
1984
  const styles = {
@@ -1885,7 +2001,157 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(({
1885
2001
  )
1886
2002
 
1887
2003
  Input.displayName = 'Input'
1888
- `;var ae=`'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'
1889
2155
 
1890
2156
  import * as React from 'react'
1891
2157
  import { cn } from '@/utils/cn'
@@ -1990,7 +2256,7 @@ export const Popover = Object.assign(PopoverRoot, {
1990
2256
  Trigger,
1991
2257
  Content
1992
2258
  })
1993
- `;var ce=`import * as React from 'react'
2259
+ `;var de=`import * as React from 'react'
1994
2260
  import { cn } from '@/utils/cn'
1995
2261
 
1996
2262
  const styles = {
@@ -2028,7 +2294,156 @@ export function Progress({
2028
2294
  </div>
2029
2295
  )
2030
2296
  }
2031
- `;var ie=`'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'
2032
2447
 
2033
2448
  import * as React from 'react'
2034
2449
  import { ChevronDown } from 'lucide-react'
@@ -2182,7 +2597,7 @@ export const Select = Object.assign(SelectRoot, {
2182
2597
  Menu,
2183
2598
  Option
2184
2599
  })
2185
- `;var le=`import * as React from 'react'
2600
+ `;var me=`import * as React from 'react'
2186
2601
  import { cn } from '@/utils/cn'
2187
2602
 
2188
2603
  const styles = {
@@ -2206,7 +2621,7 @@ export function Separator({
2206
2621
  />
2207
2622
  )
2208
2623
  }
2209
- `;var de=`'use client'
2624
+ `;var fe=`'use client'
2210
2625
 
2211
2626
  import * as React from 'react'
2212
2627
  import { cn } from '@/utils/cn'
@@ -2247,7 +2662,7 @@ export function Switch({
2247
2662
  </button>
2248
2663
  )
2249
2664
  }
2250
- `;var pe=`'use client'
2665
+ `;var ge=`'use client'
2251
2666
 
2252
2667
  import * as React from 'react'
2253
2668
  import { cn } from '@/utils/cn'
@@ -2361,7 +2776,7 @@ export const Tabs = Object.assign(TabsRoot, {
2361
2776
  Tab,
2362
2777
  Panel
2363
2778
  })
2364
- `;var ue=`import * as React from 'react'
2779
+ `;var he=`import * as React from 'react'
2365
2780
  import { cn } from '@/utils/cn'
2366
2781
 
2367
2782
  const styles = {
@@ -2388,7 +2803,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({
2388
2803
  ))
2389
2804
 
2390
2805
  Textarea.displayName = 'Textarea'
2391
- `;var me=`'use client'
2806
+ `;var be=`'use client'
2392
2807
 
2393
2808
  import * as React from 'react'
2394
2809
  import { Toaster as Sonner, toast } from 'sonner'
@@ -2431,7 +2846,181 @@ function Toaster() {
2431
2846
  }
2432
2847
 
2433
2848
  export { Toaster, toast }
2434
- `;var fe=`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'
2435
3024
  import { cn } from '@/utils/cn'
2436
3025
 
2437
3026
  const styles = {
@@ -2476,7 +3065,7 @@ export function Tooltip({
2476
3065
  </span>
2477
3066
  )
2478
3067
  }
2479
- `;var ge=`
3068
+ `;var ye=`
2480
3069
  /* react-day-picker theme integration */
2481
3070
  .rdp-root {
2482
3071
  --rdp-accent-color: var(--primary);
@@ -2487,4 +3076,4 @@ export function Tooltip({
2487
3076
  --rdp-selected-border: none;
2488
3077
  --rdp-day_button-border: none;
2489
3078
  }
2490
- `,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:"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:"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:[]}],S={accordion:U,alert:G,avatar:W,badge:X,button:q,calendar:J,"date-picker":Q,command:Z,carousel:ee,card:te,checkbox:oe,dialog:ne,dropdown:re,input:se,popover:ae,progress:ce,select:ie,separator:le,switch:de,tabs:pe,textarea:ue,theme:Y,toast:me,tooltip:fe};async function he(t){let n=process.cwd();e.intro("drivn add");let a=V(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:R.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 v=t.filter(o=>!R.find(r=>r.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 p=t.includes("theme"),g=t.filter(o=>o!=="theme"),u=new Set,b=new Set,h=o=>{if(u.has(o))return;let r=R.find(c=>c.name===o);r&&(r.dependencies.forEach(c=>h(c)),r.npmDependencies?.forEach(c=>b.add(c)),u.add(o));};g.forEach(h),p&&b.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=O(c);C.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(d(c,C+M),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=O(o);r.includes(".rdp-root")?e.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(d(o,r+ge),e.log.success(`Calendar tokens appended to ${i.cyan(a.paths.globals)}`));}}if(b.size){let o=P(n),r=[...b],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 ve={version:"1.2.0"};var T=new Command;T.name("drivn").description("Drivn \u2014 Modern UI components").version(ve.version);T.command("create").description("Initialize Drivn in your project").action(K);T.command("add [components...]").description("Add components to your project").action(he);T.parse();
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drivn",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Modern UI components for React — add beautiful, accessible components to your project",
5
5
  "license": "MIT",
6
6
  "type": "module",