drivn 1.5.2 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +277 -37
  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 o=join(t,"package.json");if(!existsSync(o))throw new Error("package.json not found");let a=JSON.parse(readFileSync(o,"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 o=join(t,V);return existsSync(o)?JSON.parse(readFileSync(o,"utf-8")):null}function _(t,o){let a=join(t,V);writeFileSync(a,JSON.stringify(o,null,2));}function Te(t){existsSync(t)||mkdirSync(t,{recursive:true});}function d(t,o){Te(dirname(t)),writeFileSync(t,o);}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,o){let a=o.join(" ");return t==="pnpm"?`pnpm add ${a}`:`npm install ${a}`}function F(t){return t==="pnpm"?"pnpm dlx":"npx"}var S=`@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 o=join(t,"package.json");if(!existsSync(o))throw new Error("package.json not found");let a=JSON.parse(readFileSync(o,"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 o=join(t,V);return existsSync(o)?JSON.parse(readFileSync(o,"utf-8")):null}function _(t,o){let a=join(t,V);writeFileSync(a,JSON.stringify(o,null,2));}function Le(t){existsSync(t)||mkdirSync(t,{recursive:true});}function d(t,o){Le(dirname(t)),writeFileSync(t,o);}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,o){let a=o.join(" ");return t==="pnpm"?`pnpm add ${a}`:`npm install ${a}`}function F(t){return t==="pnpm"?"pnpm dlx":"npx"}var S=`@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
- `,O=`
73
+ `,M=`
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 Me=`import { type ClassValue, clsx } from 'clsx'
139
+ `;var Ae=`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
- `,Oe=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function Ae(t){for(let o of Oe)if(m(join(t,o)))return o;return null}async function G(){let t=process.cwd();console.log(""),console.log(i.bgCyan(i.bold(i.black(" Drivn "))));let o;try{o=B(t),e.log.success(`Detected ${i.cyan(A[o.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=o.srcDir?"src/components/ui":"components/ui",b=o.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:o.framework,typescript:o.typescript,paths:{components:p.components,utils:p.utils},installed:[]},u=o.typescript?"ts":"js",v=join(t,p.utils,`cn.${u}`);m(v)||d(v,Me);let h=Ae(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),S),g.paths.globals=h,e.log.success(`Color tokens written to ${i.cyan(h)}`));}else {let r=o.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),S),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"],n=e.spinner();n.start("Installing dependencies");try{execSync(y(x,N),{cwd:t,stdio:"ignore"}),n.stop("Dependencies installed");}catch{n.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'
145
+ `,Be=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function He(t){for(let o of Be)if(m(join(t,o)))return o;return null}async function G(){let t=process.cwd();console.log(""),console.log(i.bgCyan(i.bold(i.black(" Drivn "))));let o;try{o=B(t),e.log.success(`Detected ${i.cyan(A[o.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=o.srcDir?"src/components/ui":"components/ui",b=o.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:o.framework,typescript:o.typescript,paths:{components:p.components,utils:p.utils},installed:[]},u=o.typescript?"ts":"js",v=join(t,p.utils,`cn.${u}`);m(v)||d(v,Ae);let h=He(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),S),g.paths.globals=h,e.log.success(`Color tokens written to ${i.cyan(h)}`));}else {let r=o.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),S),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"],n=e.spinner();n.start("Installing dependencies");try{execSync(y(x,N),{cwd:t,stdio:"ignore"}),n.stop("Dependencies installed");}catch{n.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
 
@@ -344,6 +344,29 @@ export function Alert({
344
344
  `;var W=`import * as React from 'react'
345
345
  import { cn } from '@/utils/cn'
346
346
 
347
+ interface AspectRatioProps {
348
+ ratio?: '16/9' | '4/3' | '1/1' | number
349
+ className?: string
350
+ children?: React.ReactNode
351
+ }
352
+
353
+ export function AspectRatio({
354
+ ratio = '16/9',
355
+ className,
356
+ children,
357
+ }: AspectRatioProps) {
358
+ return (
359
+ <div
360
+ className={cn('relative w-full overflow-hidden', className)}
361
+ style={{ aspectRatio: ratio }}
362
+ >
363
+ {children}
364
+ </div>
365
+ )
366
+ }
367
+ `;var q=`import * as React from 'react'
368
+ import { cn } from '@/utils/cn'
369
+
347
370
  const styles = {
348
371
  base: cn(
349
372
  'relative inline-flex items-center justify-center',
@@ -385,7 +408,7 @@ export function Avatar({
385
408
  </div>
386
409
  )
387
410
  }
388
- `;var q=`import * as React from 'react'
411
+ `;var X=`import * as React from 'react'
389
412
  import { cn } from '@/utils/cn'
390
413
 
391
414
  const styles = {
@@ -415,7 +438,7 @@ export function Badge({ variant = 'default', className, children }: BadgeProps)
415
438
  </span>
416
439
  )
417
440
  }
418
- `;var X=`import * as React from 'react'
441
+ `;var J=`import * as React from 'react'
419
442
  import { cn } from '@/utils/cn'
420
443
  import { ChevronRight, MoreHorizontal } from 'lucide-react'
421
444
 
@@ -531,13 +554,13 @@ export const Breadcrumb = Object.assign(BreadcrumbRoot, {
531
554
  Separator: BreadcrumbSeparator,
532
555
  Ellipsis,
533
556
  })
534
- `;var J=`import * as React from 'react'
557
+ `;var Q=`import * as React from 'react'
535
558
  import { Loader2 } from 'lucide-react'
536
559
  import { cn } from '@/utils/cn'
537
560
 
538
561
  const styles = {
539
562
  base: cn(
540
- 'inline-flex items-center justify-center',
563
+ 'inline-flex items-center justify-center outline-none',
541
564
  'font-semibold transition-all duration-150',
542
565
  'cursor-pointer disabled:opacity-50',
543
566
  'disabled:pointer-events-none'
@@ -611,7 +634,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(({
611
634
  )
612
635
 
613
636
  Button.displayName = 'Button'
614
- `;var Q=`'use client'
637
+ `;var Z=`'use client'
615
638
 
616
639
  import * as React from 'react'
617
640
  import {
@@ -787,7 +810,7 @@ export { type DateRange, type Locale }
787
810
  export const Calendar = Object.assign(CalendarRoot, {
788
811
  Range
789
812
  })
790
- `;var Z=`'use client'
813
+ `;var ee=`'use client'
791
814
 
792
815
  import * as React from 'react'
793
816
  import { CalendarDays } from 'lucide-react'
@@ -1011,7 +1034,7 @@ export { type DateRange, type Locale }
1011
1034
  export const DatePicker = Object.assign(DatePickerRoot, {
1012
1035
  Range,
1013
1036
  })
1014
- `;var ee=`'use client'
1037
+ `;var te=`'use client'
1015
1038
 
1016
1039
  import * as React from 'react'
1017
1040
  import { Command as CommandPrimitive } from 'cmdk'
@@ -1242,7 +1265,7 @@ export const Command = Object.assign(CommandRoot, {
1242
1265
  Shortcut,
1243
1266
  Dialog: CommandDialog,
1244
1267
  })
1245
- `;var te=`'use client'
1268
+ `;var ne=`'use client'
1246
1269
 
1247
1270
  import * as React from 'react'
1248
1271
  import useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'
@@ -1491,7 +1514,7 @@ export const Carousel = Object.assign(CarouselRoot, {
1491
1514
  Next,
1492
1515
  Dots
1493
1516
  })
1494
- `;var ne=`import * as React from 'react'
1517
+ `;var oe=`import * as React from 'react'
1495
1518
  import { cn } from '@/utils/cn'
1496
1519
 
1497
1520
  const styles = {
@@ -1558,7 +1581,7 @@ export const Card = Object.assign(CardRoot, {
1558
1581
  Preview,
1559
1582
  Info
1560
1583
  })
1561
- `;var oe=`'use client'
1584
+ `;var re=`'use client'
1562
1585
 
1563
1586
  import * as React from 'react'
1564
1587
  import { Check } from 'lucide-react'
@@ -1621,7 +1644,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(({
1621
1644
  )
1622
1645
 
1623
1646
  Checkbox.displayName = 'Checkbox'
1624
- `;var re=`'use client'
1647
+ `;var se=`'use client'
1625
1648
 
1626
1649
  import * as React from 'react'
1627
1650
  import { X } from 'lucide-react'
@@ -1630,7 +1653,7 @@ import { Button } from '@/components/ui/button'
1630
1653
 
1631
1654
  const styles = {
1632
1655
  base: cn(
1633
- 'fixed inset-0 m-0 p-0 border-none',
1656
+ 'fixed inset-0 m-0 p-0 border-none outline-none',
1634
1657
  'max-w-none max-h-none w-screen h-dvh',
1635
1658
  'flex items-center justify-center bg-overlay',
1636
1659
  'backdrop-blur-sm transition-opacity duration-150',
@@ -1644,7 +1667,7 @@ const styles = {
1644
1667
  title: 'text-lg font-semibold text-foreground mb-4',
1645
1668
  close: cn(
1646
1669
  'absolute top-4 right-4 w-8 h-8 cursor-pointer',
1647
- 'flex items-center justify-center rounded-full',
1670
+ 'flex items-center justify-center rounded-full outline-none',
1648
1671
  'text-muted-foreground hover:text-foreground',
1649
1672
  'hover:bg-accent transition-colors'
1650
1673
  ),
@@ -1780,7 +1803,224 @@ export const Dialog = Object.assign(DialogRoot, {
1780
1803
  Content,
1781
1804
  Close
1782
1805
  })
1783
- `;var se=`'use client'
1806
+ `;var ae=`'use client'
1807
+
1808
+ import * as React from 'react'
1809
+ import { X } from 'lucide-react'
1810
+ import { cn } from '@/utils/cn'
1811
+ import { Button } from '@/components/ui/button'
1812
+
1813
+ type Side = 'left' | 'right' | 'top' | 'bottom'
1814
+
1815
+ const styles = {
1816
+ overlay: cn(
1817
+ 'group fixed inset-0 m-0 p-0 border-none outline-none',
1818
+ 'max-w-none max-h-none w-screen h-dvh overflow-clip',
1819
+ 'bg-transparent backdrop-blur-none',
1820
+ 'open:bg-overlay open:backdrop-blur-sm',
1821
+ 'starting:open:bg-transparent starting:open:backdrop-blur-none',
1822
+ 'transition-[display,overlay,background-color,backdrop-filter]',
1823
+ 'duration-300 ease-out transition-discrete'
1824
+ ),
1825
+ content: cn(
1826
+ 'fixed flex flex-col',
1827
+ 'bg-card shadow-xl',
1828
+ 'transition-[translate,display,overlay] duration-300',
1829
+ 'ease-out transition-discrete'
1830
+ ),
1831
+ sides: {
1832
+ right: cn(
1833
+ 'right-0 top-0 h-dvh w-[400px] border-l border-border',
1834
+ 'translate-x-[100%] group-open:translate-x-[0%]',
1835
+ 'starting:group-open:translate-x-[100%]'
1836
+ ),
1837
+ left: cn(
1838
+ 'left-0 top-0 h-dvh w-[400px] border-r border-border',
1839
+ 'translate-x-[-100%] group-open:translate-x-[0%]',
1840
+ 'starting:group-open:translate-x-[-100%]'
1841
+ ),
1842
+ top: cn(
1843
+ 'top-0 left-0 w-screen h-[400px] border-b border-border',
1844
+ 'translate-y-[-100%] group-open:translate-y-[0%]',
1845
+ 'starting:group-open:translate-y-[-100%]'
1846
+ ),
1847
+ bottom: cn(
1848
+ 'bottom-0 left-0 w-screen h-[400px] border-t border-border',
1849
+ 'translate-y-[100%] group-open:translate-y-[0%]',
1850
+ 'starting:group-open:translate-y-[100%]'
1851
+ ),
1852
+ },
1853
+ header: cn(
1854
+ 'flex flex-col gap-1.5 px-6 py-4',
1855
+ 'border-b border-border'
1856
+ ),
1857
+ title: 'text-lg font-semibold text-foreground',
1858
+ description: 'text-sm text-muted-foreground',
1859
+ footer: cn(
1860
+ 'flex items-center gap-2 px-6 py-4',
1861
+ 'border-t border-border mt-auto'
1862
+ ),
1863
+ close: cn(
1864
+ 'absolute top-4 right-4 w-8 h-8 cursor-pointer',
1865
+ 'flex items-center justify-center rounded-full outline-none',
1866
+ 'text-muted-foreground hover:text-foreground',
1867
+ 'hover:bg-accent transition-colors'
1868
+ ),
1869
+ }
1870
+
1871
+ interface DrawerCtx {
1872
+ open: boolean
1873
+ setOpen: (v: boolean) => void
1874
+ }
1875
+
1876
+ function DrawerRoot({
1877
+ children,
1878
+ open: controlled,
1879
+ onOpenChange,
1880
+ }: {
1881
+ children: React.ReactNode
1882
+ open?: boolean
1883
+ onOpenChange?: (open: boolean) => void
1884
+ }) {
1885
+ const [uncontrolled, setUncontrolled] = React.useState(false)
1886
+ const open = controlled ?? uncontrolled
1887
+ const setOpen = (v: boolean) => {
1888
+ onOpenChange?.(v)
1889
+ if (controlled === undefined) setUncontrolled(v)
1890
+ }
1891
+
1892
+ return (
1893
+ <Ctx.Provider value={{ open, setOpen }}>
1894
+ {children}
1895
+ </Ctx.Provider>
1896
+ )
1897
+ }
1898
+
1899
+ function Trigger({
1900
+ children,
1901
+ className,
1902
+ ...props
1903
+ }: React.ButtonHTMLAttributes<HTMLButtonElement>) {
1904
+ const { setOpen } = useDrawer()
1905
+ return (
1906
+ <Button
1907
+ variant="outline"
1908
+ rounded="md"
1909
+ className={className}
1910
+ onClick={() => setOpen(true)}
1911
+ {...props}
1912
+ >
1913
+ {children}
1914
+ </Button>
1915
+ )
1916
+ }
1917
+
1918
+ function Content({
1919
+ children,
1920
+ side = 'right',
1921
+ className,
1922
+ }: {
1923
+ children: React.ReactNode
1924
+ side?: Side
1925
+ className?: string
1926
+ }) {
1927
+ const { open, setOpen } = useDrawer()
1928
+ const ref = React.useRef<HTMLDialogElement>(null)
1929
+
1930
+ React.useEffect(() => {
1931
+ const el = ref.current
1932
+ if (!el) return
1933
+ const onCancel = (e: Event) => {
1934
+ e.preventDefault()
1935
+ setOpen(false)
1936
+ }
1937
+ el.addEventListener('cancel', onCancel)
1938
+ if (open) {
1939
+ if (!el.open) el.showModal()
1940
+ document.body.style.overflow = 'hidden'
1941
+ } else if (el.open) {
1942
+ el.close()
1943
+ document.body.style.overflow = ''
1944
+ }
1945
+ return () => el.removeEventListener('cancel', onCancel)
1946
+ }, [open, setOpen])
1947
+
1948
+ return (
1949
+ <dialog
1950
+ ref={ref}
1951
+ className={styles.overlay}
1952
+ onClick={(e) => {
1953
+ if (e.target === e.currentTarget) setOpen(false)
1954
+ }}
1955
+ >
1956
+ <div className={cn(styles.content, styles.sides[side], className)}>
1957
+ {children}
1958
+ </div>
1959
+ </dialog>
1960
+ )
1961
+ }
1962
+
1963
+ function Close({ className }: { className?: string }) {
1964
+ const { setOpen } = useDrawer()
1965
+ return (
1966
+ <button
1967
+ className={cn(styles.close, className)}
1968
+ onClick={() => setOpen(false)}
1969
+ >
1970
+ <X className="w-3.5 h-3.5" />
1971
+ </button>
1972
+ )
1973
+ }
1974
+
1975
+ function Header({
1976
+ title,
1977
+ description,
1978
+ className,
1979
+ }: {
1980
+ title: string
1981
+ description?: string
1982
+ className?: string
1983
+ }) {
1984
+ return (
1985
+ <div className={cn(styles.header, className)}>
1986
+ <h2 className={styles.title}>{title}</h2>
1987
+ {description && (
1988
+ <p className={styles.description}>{description}</p>
1989
+ )}
1990
+ </div>
1991
+ )
1992
+ }
1993
+
1994
+ function Footer({
1995
+ children,
1996
+ className,
1997
+ }: {
1998
+ children: React.ReactNode
1999
+ className?: string
2000
+ }) {
2001
+ return (
2002
+ <div className={cn(styles.footer, className)}>
2003
+ {children}
2004
+ </div>
2005
+ )
2006
+ }
2007
+
2008
+ const Ctx = React.createContext<DrawerCtx | null>(null)
2009
+
2010
+ function useDrawer() {
2011
+ const ctx = React.useContext(Ctx)
2012
+ if (!ctx) throw new Error('Drawer compound used outside <Drawer>')
2013
+ return ctx
2014
+ }
2015
+
2016
+ export const Drawer = Object.assign(DrawerRoot, {
2017
+ Trigger,
2018
+ Content,
2019
+ Close,
2020
+ Header,
2021
+ Footer,
2022
+ })
2023
+ `;var ce=`'use client'
1784
2024
 
1785
2025
  import * as React from 'react'
1786
2026
  import { cn } from '@/utils/cn'
@@ -1978,7 +2218,7 @@ export const Dropdown = Object.assign(DropdownRoot, {
1978
2218
  Label,
1979
2219
  Separator: DropdownSeparator
1980
2220
  })
1981
- `;var ae=`import * as React from 'react'
2221
+ `;var ie=`import * as React from 'react'
1982
2222
  import { cn } from '@/utils/cn'
1983
2223
 
1984
2224
  const styles = {
@@ -2001,7 +2241,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(({
2001
2241
  )
2002
2242
 
2003
2243
  Input.displayName = 'Input'
2004
- `;var ce=`import * as React from 'react'
2244
+ `;var le=`import * as React from 'react'
2005
2245
  import { cn } from '@/utils/cn'
2006
2246
 
2007
2247
  const styles = {
@@ -2058,7 +2298,7 @@ function Group({
2058
2298
  }
2059
2299
 
2060
2300
  export const Kbd = Object.assign(KbdRoot, { Group })
2061
- `;var ie=`import * as React from 'react'
2301
+ `;var de=`import * as React from 'react'
2062
2302
  import { cn } from '@/utils/cn'
2063
2303
 
2064
2304
  export function Label({
@@ -2075,7 +2315,7 @@ export function Label({
2075
2315
  />
2076
2316
  )
2077
2317
  }
2078
- `;var le=`import * as React from 'react'
2318
+ `;var pe=`import * as React from 'react'
2079
2319
  import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react'
2080
2320
  import { cn } from '@/utils/cn'
2081
2321
 
@@ -2208,7 +2448,7 @@ export const Pagination = Object.assign(PaginationRoot, {
2208
2448
  Next,
2209
2449
  Ellipsis: PaginationEllipsis,
2210
2450
  })
2211
- `;var de=`'use client'
2451
+ `;var ue=`'use client'
2212
2452
 
2213
2453
  import * as React from 'react'
2214
2454
  import { cn } from '@/utils/cn'
@@ -2313,7 +2553,7 @@ export const Popover = Object.assign(PopoverRoot, {
2313
2553
  Trigger,
2314
2554
  Content
2315
2555
  })
2316
- `;var pe=`import * as React from 'react'
2556
+ `;var me=`import * as React from 'react'
2317
2557
  import { cn } from '@/utils/cn'
2318
2558
 
2319
2559
  const styles = {
@@ -2351,7 +2591,7 @@ export function Progress({
2351
2591
  </div>
2352
2592
  )
2353
2593
  }
2354
- `;var ue=`'use client'
2594
+ `;var fe=`'use client'
2355
2595
 
2356
2596
  import * as React from 'react'
2357
2597
  import { cn } from '@/utils/cn'
@@ -2500,7 +2740,7 @@ function useRadioGroup() {
2500
2740
  }
2501
2741
 
2502
2742
  export const RadioGroup = Object.assign(RadioGroupRoot, { Item })
2503
- `;var me=`'use client'
2743
+ `;var ge=`'use client'
2504
2744
 
2505
2745
  import * as React from 'react'
2506
2746
  import { ChevronDown } from 'lucide-react'
@@ -2654,7 +2894,7 @@ export const Select = Object.assign(SelectRoot, {
2654
2894
  Menu,
2655
2895
  Option
2656
2896
  })
2657
- `;var fe=`import * as React from 'react'
2897
+ `;var he=`import * as React from 'react'
2658
2898
  import { cn } from '@/utils/cn'
2659
2899
 
2660
2900
  const styles = {
@@ -2678,7 +2918,7 @@ export function Separator({
2678
2918
  />
2679
2919
  )
2680
2920
  }
2681
- `;var ge=`'use client'
2921
+ `;var be=`'use client'
2682
2922
 
2683
2923
  import * as React from 'react'
2684
2924
  import { ChevronDown, PanelLeft } from 'lucide-react'
@@ -2964,7 +3204,7 @@ export const Sidebar = Object.assign(SidebarRoot, {
2964
3204
  Separator: SidebarSeparator,
2965
3205
  CollapseButton,
2966
3206
  })
2967
- `;var he=`'use client'
3207
+ `;var ve=`'use client'
2968
3208
 
2969
3209
  import * as React from 'react'
2970
3210
  import { cn } from '@/utils/cn'
@@ -3109,7 +3349,7 @@ export const Slider = React.forwardRef<HTMLInputElement, SliderProps>(({
3109
3349
  )
3110
3350
 
3111
3351
  Slider.displayName = 'Slider'
3112
- `;var be=`'use client'
3352
+ `;var xe=`'use client'
3113
3353
 
3114
3354
  import * as React from 'react'
3115
3355
  import { cn } from '@/utils/cn'
@@ -3150,7 +3390,7 @@ export function Switch({
3150
3390
  </button>
3151
3391
  )
3152
3392
  }
3153
- `;var ve=`'use client'
3393
+ `;var ye=`'use client'
3154
3394
 
3155
3395
  import * as React from 'react'
3156
3396
  import { cn } from '@/utils/cn'
@@ -3264,7 +3504,7 @@ export const Tabs = Object.assign(TabsRoot, {
3264
3504
  Tab,
3265
3505
  Panel
3266
3506
  })
3267
- `;var xe=`import * as React from 'react'
3507
+ `;var Ne=`import * as React from 'react'
3268
3508
  import { cn } from '@/utils/cn'
3269
3509
 
3270
3510
  const styles = {
@@ -3291,7 +3531,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({
3291
3531
  ))
3292
3532
 
3293
3533
  Textarea.displayName = 'Textarea'
3294
- `;var ye=`'use client'
3534
+ `;var Ce=`'use client'
3295
3535
 
3296
3536
  import * as React from 'react'
3297
3537
  import { Toaster as Sonner, toast } from 'sonner'
@@ -3334,7 +3574,7 @@ function Toaster() {
3334
3574
  }
3335
3575
 
3336
3576
  export { Toaster, toast }
3337
- `;var Ne=`import * as React from 'react'
3577
+ `;var Re=`import * as React from 'react'
3338
3578
  import { cn } from '@/utils/cn'
3339
3579
 
3340
3580
  const styles = {
@@ -3508,7 +3748,7 @@ export const Table = Object.assign(TableRoot, {
3508
3748
  Head,
3509
3749
  Cell,
3510
3750
  })
3511
- `;var Ce=`import * as React from 'react'
3751
+ `;var we=`import * as React from 'react'
3512
3752
  import { cn } from '@/utils/cn'
3513
3753
 
3514
3754
  const styles = {
@@ -3553,7 +3793,7 @@ export function Tooltip({
3553
3793
  </span>
3554
3794
  )
3555
3795
  }
3556
- `;var Re=`
3796
+ `;var ke=`
3557
3797
  /* react-day-picker theme integration */
3558
3798
  .rdp-root {
3559
3799
  --rdp-accent-color: var(--primary);
@@ -3564,4 +3804,4 @@ export function Tooltip({
3564
3804
  --rdp-selected-border: none;
3565
3805
  --rdp-day_button-border: none;
3566
3806
  }
3567
- `,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:"kbd",description:"Keyboard key display for shortcuts and hotkeys",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:"sidebar",description:"Collapsible sidebar with dot notation, icon items, groups, and layout variants",dependencies:[],npmDependencies:[]},{name:"slider",description:"Range slider with pointer drag, step snapping, and size variants",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:[]}],D={accordion:U,alert:Y,avatar:W,badge:q,breadcrumb:X,button:J,calendar:Q,"date-picker":Z,command:ee,carousel:te,card:ne,checkbox:oe,dialog:re,dropdown:se,input:ae,kbd:ce,label:ie,pagination:le,popover:de,progress:pe,"radio-group":ue,select:me,separator:fe,sidebar:ge,slider:he,switch:be,table:Ne,tabs:ve,textarea:xe,theme:K,toast:ye,tooltip:Ce};async function we(t){let o=process.cwd();e.intro("drivn add");let a=$(o);if(a||(e.log.error("Drivn is not initialized. Run npx drivn@latest create"),e.outro("Cancelled"),process.exit(1)),!t||!t.length){let n=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(n)&&(e.cancel("Cancelled"),process.exit(0)),t=n;}let b=t.filter(n=>!w.find(r=>r.name===n));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+w.map(n=>n.name).join(", ")),e.outro("Cancelled"),process.exit(1));let p=t.includes("theme"),g=t.filter(n=>n!=="theme"),u=new Set,v=new Set,h=n=>{if(u.has(n))return;let r=w.find(c=>c.name===n);r&&(r.dependencies.forEach(c=>h(c)),r.npmDependencies?.forEach(c=>v.add(c)),u.add(n));};g.forEach(h),p&&v.add("next-themes");let x=[...u].filter(n=>!g.includes(n));x.length&&e.log.info(`Required dependency: ${x.join(", ")}`);let l=a.typescript?"tsx":"jsx",N=join(o,a.paths.components);for(let n of u){let r=join(N,`${n}.${l}`);if(m(r)){let C=await e.confirm({message:`${n}.${l} exists. Overwrite?`,initialValue:false});if(e.isCancel(C)||!C){e.log.warn(`Skipped ${n}`);continue}}let c=D[n];c=c.replace(/@\/utils/g,`@/${a.paths.utils.replace(/^src\//,"")}`),d(r,c),e.log.success(`${n} \u2192 ${a.paths.components}/${n}.${l}`);}if(p){let n=join(N,`theme-provider.${l}`);if(m(n)){let c=await e.confirm({message:`theme-provider.${l} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(d(n,D.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else d(n,D.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`);if(a.paths.globals){let c=join(o,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 n=join(o,a.paths.globals);if(m(n)){let r=M(n);r.includes(".rdp-root")?e.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(d(n,r+Re),e.log.success(`Calendar tokens appended to ${i.cyan(a.paths.globals)}`));}}if(v.size){let n=P(o),r=[...v],c=e.spinner();c.start("Installing packages");try{execSync(y(n,r),{cwd:o,stdio:"ignore"}),c.stop("Packages installed");}catch{c.stop("Failed to install packages"),e.log.warn(`Run manually: ${y(n,r)}`);}}e.outro("Done.");}var ke={version:"1.5.2"};var T=new Command;T.name("drivn").description("Drivn \u2014 Modern UI components").version(ke.version);T.command("create").description("Initialize Drivn in your project").action(G);T.command("add [components...]").description("Add components to your project").action(we);T.parse();
3807
+ `,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:"aspect-ratio",description:"Maintain consistent width-to-height ratios for images, videos, and embedded content",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:"drawer",description:"Slide-in panel with side positioning, header/footer, and overlay",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:"kbd",description:"Keyboard key display for shortcuts and hotkeys",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:"sidebar",description:"Collapsible sidebar with dot notation, icon items, groups, and layout variants",dependencies:[],npmDependencies:[]},{name:"slider",description:"Range slider with pointer drag, step snapping, and size variants",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:[]}],D={accordion:U,alert:Y,"aspect-ratio":W,avatar:q,badge:X,breadcrumb:J,button:Q,calendar:Z,"date-picker":ee,command:te,carousel:ne,card:oe,checkbox:re,dialog:se,drawer:ae,dropdown:ce,input:ie,kbd:le,label:de,pagination:pe,popover:ue,progress:me,"radio-group":fe,select:ge,separator:he,sidebar:be,slider:ve,switch:xe,table:Re,tabs:ye,textarea:Ne,theme:K,toast:Ce,tooltip:we};async function Pe(t){let o=process.cwd();e.intro("drivn add");let a=$(o);if(a||(e.log.error("Drivn is not initialized. Run npx drivn@latest create"),e.outro("Cancelled"),process.exit(1)),!t||!t.length){let n=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(n)&&(e.cancel("Cancelled"),process.exit(0)),t=n;}let b=t.filter(n=>!w.find(r=>r.name===n));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+w.map(n=>n.name).join(", ")),e.outro("Cancelled"),process.exit(1));let p=t.includes("theme"),g=t.filter(n=>n!=="theme"),u=new Set,v=new Set,h=n=>{if(u.has(n))return;let r=w.find(c=>c.name===n);r&&(r.dependencies.forEach(c=>h(c)),r.npmDependencies?.forEach(c=>v.add(c)),u.add(n));};g.forEach(h),p&&v.add("next-themes");let x=[...u].filter(n=>!g.includes(n));x.length&&e.log.info(`Required dependency: ${x.join(", ")}`);let l=a.typescript?"tsx":"jsx",N=join(o,a.paths.components);for(let n of u){let r=join(N,`${n}.${l}`);if(m(r)){let C=await e.confirm({message:`${n}.${l} exists. Overwrite?`,initialValue:false});if(e.isCancel(C)||!C){e.log.warn(`Skipped ${n}`);continue}}let c=D[n];c=c.replace(/@\/utils/g,`@/${a.paths.utils.replace(/^src\//,"")}`),d(r,c),e.log.success(`${n} \u2192 ${a.paths.components}/${n}.${l}`);}if(p){let n=join(N,`theme-provider.${l}`);if(m(n)){let c=await e.confirm({message:`theme-provider.${l} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(d(n,D.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else d(n,D.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`);if(a.paths.globals){let c=join(o,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 n=join(o,a.paths.globals);if(m(n)){let r=O(n);r.includes(".rdp-root")?e.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(d(n,r+ke),e.log.success(`Calendar tokens appended to ${i.cyan(a.paths.globals)}`));}}if(v.size){let n=P(o),r=[...v],c=e.spinner();c.start("Installing packages");try{execSync(y(n,r),{cwd:o,stdio:"ignore"}),c.stop("Packages installed");}catch{c.stop("Failed to install packages"),e.log.warn(`Run manually: ${y(n,r)}`);}}e.outro("Done.");}var Se={version:"1.6.1"};var T=new Command;T.name("drivn").description("Drivn \u2014 Modern UI components").version(Se.version);T.command("create").description("Initialize Drivn in your project").action(G);T.command("add [components...]").description("Add components to your project").action(Pe);T.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drivn",
3
- "version": "1.5.2",
3
+ "version": "1.6.1",
4
4
  "description": "Modern UI components for React — add beautiful, accessible components to your project",
5
5
  "license": "MIT",
6
6
  "type": "module",