drivn 1.0.1 → 1.0.2

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 +30 -26
  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 l from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';var E={next:"Next.js",react:"React"};function A(t){let s=join(t,"package.json");if(!existsSync(s))throw new Error("package.json not found");let r=JSON.parse(readFileSync(s,"utf-8")),b={...r.dependencies,...r.devDependencies},d="react";b.next&&(d="next");let m=existsSync(join(t,"src")),f=existsSync(join(t,"tsconfig.json"));return {framework:d,srcDir:m,typescript:f}}var M="drivn.config.json";function V(t){let s=join(t,M);return existsSync(s)?JSON.parse(readFileSync(s,"utf-8")):null}function $(t,s){let r=join(t,M);writeFileSync(r,JSON.stringify(s,null,2));}function me(t){existsSync(t)||mkdirSync(t,{recursive:true});}function p(t,s){me(dirname(t)),writeFileSync(t,s);}function z(t){return readFileSync(t,"utf-8")}function v(t){return existsSync(t)}var R=`@import "tailwindcss";
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 L={next:"Next.js",react:"React"};function M(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 V="drivn.config.json";function z(t){let n=join(t,V);return existsSync(n)?JSON.parse(readFileSync(n,"utf-8")):null}function H(t,n){let c=join(t,V);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 P=`@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
+ `,A=`
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 ge=`import { type ClassValue, clsx } from 'clsx'
139
+ `;var ye=`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
- `,he=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function ve(t){for(let s of he)if(v(join(t,s)))return s;return null}async function H(){let t=process.cwd();console.log(""),console.log(l.bgCyan(l.bold(l.black(" Drivn "))));let s;try{s=A(t),e.log.success(`Detected ${l.cyan(E[s.framework])}`);}catch{e.log.error("No package.json found. Run this command in a project directory."),e.outro("Setup cancelled"),process.exit(1);}if(v(join(t,"drivn.config.json"))){let a=await e.confirm({message:"Config already exists. Overwrite?",initialValue:false});(e.isCancel(a)||!a)&&(e.cancel("Setup cancelled"),process.exit(0));}let r=s.srcDir?"src/components/ui":"components/ui",b=s.srcDir?"src/utils":"utils",d=await e.group({components:()=>e.text({message:"Where should components be installed?",placeholder:r,defaultValue:r}),utils:()=>e.text({message:"Where should utilities be placed?",placeholder:b,defaultValue:b})},{onCancel:()=>{e.cancel("Setup cancelled"),process.exit(0);}}),m={framework:s.framework,typescript:s.typescript,paths:{components:d.components,utils:d.utils},installed:[]},f=s.typescript?"ts":"js",g=join(t,d.utils,`cn.${f}`);v(g)||p(g,ge);let h=ve(t);if(h){let a=await e.confirm({message:`Found ${l.cyan(h)}. Add Drivn color tokens?`,initialValue:true});!e.isCancel(a)&&a&&(p(join(t,h),R),m.paths.globals=h,e.log.success(`Color tokens written to ${l.cyan(h)}`));}else {let a=s.srcDir?"src/styles/globals.css":"styles/globals.css",x=await e.text({message:"Where should the globals CSS file be created?",placeholder:a,defaultValue:a});e.isCancel(x)||(p(join(t,x),R),m.paths.globals=x,e.log.success(`Color tokens written to ${l.cyan(x)}`));}$(t,m);let y=e.spinner();y.start("Installing dependencies");try{execSync("npm install clsx tailwind-merge lucide-react",{cwd:t,stdio:"ignore"}),y.stop("Dependencies installed");}catch{y.stop("Failed to install dependencies"),e.log.warn("Run manually: npm install clsx tailwind-merge lucide-react");}e.log.info(`Add components with: ${l.cyan("npx drivn add button")}`),e.log.info(`Add dark/light theme: ${l.cyan("npx drivn add theme")}`),e.outro("Drivn initialized");}var F=`'use client'
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=M(t),e.log.success(`Detected ${i.cyan(L[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),P),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),P),m.paths.globals=a,e.log.success(`Color tokens written to ${i.cyan(a)}`));}H(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'
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 _=`'use client'
164
+ `;var W=`'use client'
165
165
 
166
166
  import * as React from 'react'
167
167
  import { ChevronDown } from 'lucide-react'
@@ -295,7 +295,7 @@ export const Accordion = Object.assign(AccordionRoot, {
295
295
  Trigger,
296
296
  Content,
297
297
  })
298
- `;var U=`import * as React from 'react'
298
+ `;var K=`import * as React from 'react'
299
299
  import { cn } from '@/utils/cn'
300
300
 
301
301
  const styles = {
@@ -345,7 +345,7 @@ export function Alert({
345
345
  </div>
346
346
  )
347
347
  }
348
- `;var G=`import * as React from 'react'
348
+ `;var X=`import * as React from 'react'
349
349
  import { cn } from '@/utils/cn'
350
350
 
351
351
  const styles = {
@@ -389,7 +389,7 @@ export function Avatar({
389
389
  </div>
390
390
  )
391
391
  }
392
- `;var W=`import * as React from 'react'
392
+ `;var J=`import * as React from 'react'
393
393
  import { cn } from '@/utils/cn'
394
394
 
395
395
  const styles = {
@@ -419,7 +419,7 @@ export function Badge({ variant = 'default', className, children }: BadgeProps)
419
419
  </span>
420
420
  )
421
421
  }
422
- `;var K=`import * as React from 'react'
422
+ `;var q=`import * as React from 'react'
423
423
  import { Loader2 } from 'lucide-react'
424
424
  import { cn } from '@/utils/cn'
425
425
 
@@ -512,7 +512,7 @@ export const Button = React.forwardRef<
512
512
  )
513
513
 
514
514
  Button.displayName = 'Button'
515
- `;var X=`import * as React from 'react'
515
+ `;var Q=`import * as React from 'react'
516
516
  import { cn } from '@/utils/cn'
517
517
 
518
518
  const styles = {
@@ -579,7 +579,7 @@ export const Card = Object.assign(CardRoot, {
579
579
  Preview,
580
580
  Info,
581
581
  })
582
- `;var J=`'use client'
582
+ `;var Y=`'use client'
583
583
 
584
584
  import * as React from 'react'
585
585
  import { Check } from 'lucide-react'
@@ -664,7 +664,7 @@ export const Checkbox = React.forwardRef<
664
664
  )
665
665
 
666
666
  Checkbox.displayName = 'Checkbox'
667
- `;var q=`'use client'
667
+ `;var Z=`'use client'
668
668
 
669
669
  import * as React from 'react'
670
670
  import { X } from 'lucide-react'
@@ -813,7 +813,7 @@ export const Dialog = Object.assign(DialogRoot, {
813
813
  Content,
814
814
  Close,
815
815
  })
816
- `;var Q=`'use client'
816
+ `;var ee=`'use client'
817
817
 
818
818
  import * as React from 'react'
819
819
  import { cn } from '@/utils/cn'
@@ -1026,7 +1026,7 @@ export const Dropdown = Object.assign(DropdownRoot, {
1026
1026
  Label,
1027
1027
  Separator: DropdownSeparator,
1028
1028
  })
1029
- `;var Y=`import * as React from 'react'
1029
+ `;var te=`import * as React from 'react'
1030
1030
  import { cn } from '@/utils/cn'
1031
1031
 
1032
1032
  const styles = {
@@ -1047,7 +1047,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(
1047
1047
  )
1048
1048
 
1049
1049
  Input.displayName = 'Input'
1050
- `;var Z=`'use client'
1050
+ `;var oe=`'use client'
1051
1051
 
1052
1052
  import * as React from 'react'
1053
1053
  import { cn } from '@/utils/cn'
@@ -1161,7 +1161,7 @@ export const Popover = Object.assign(PopoverRoot, {
1161
1161
  Trigger,
1162
1162
  Content,
1163
1163
  })
1164
- `;var ee=`import * as React from 'react'
1164
+ `;var ne=`import * as React from 'react'
1165
1165
  import { cn } from '@/utils/cn'
1166
1166
 
1167
1167
  const styles = {
@@ -1199,7 +1199,7 @@ export function Progress({
1199
1199
  </div>
1200
1200
  )
1201
1201
  }
1202
- `;var te=`'use client'
1202
+ `;var re=`'use client'
1203
1203
 
1204
1204
  import * as React from 'react'
1205
1205
  import { ChevronDown } from 'lucide-react'
@@ -1361,7 +1361,7 @@ export const Select = Object.assign(SelectRoot, {
1361
1361
  Menu,
1362
1362
  Option,
1363
1363
  })
1364
- `;var oe=`import * as React from 'react'
1364
+ `;var se=`import * as React from 'react'
1365
1365
  import { cn } from '@/utils/cn'
1366
1366
 
1367
1367
  const styles = {
@@ -1385,7 +1385,7 @@ export function Separator({
1385
1385
  />
1386
1386
  )
1387
1387
  }
1388
- `;var ne=`'use client'
1388
+ `;var ae=`'use client'
1389
1389
 
1390
1390
  import * as React from 'react'
1391
1391
  import { cn } from '@/utils/cn'
@@ -1435,7 +1435,7 @@ export function Switch({
1435
1435
  </button>
1436
1436
  )
1437
1437
  }
1438
- `;var se=`'use client'
1438
+ `;var ce=`'use client'
1439
1439
 
1440
1440
  import * as React from 'react'
1441
1441
  import { cn } from '@/utils/cn'
@@ -1553,7 +1553,7 @@ export const Tabs = Object.assign(TabsRoot, {
1553
1553
  Tab,
1554
1554
  Panel,
1555
1555
  })
1556
- `;var re=`import * as React from 'react'
1556
+ `;var ie=`import * as React from 'react'
1557
1557
  import { cn } from '@/utils/cn'
1558
1558
 
1559
1559
  const styles = {
@@ -1580,7 +1580,7 @@ export const Textarea = React.forwardRef<
1580
1580
  ))
1581
1581
 
1582
1582
  Textarea.displayName = 'Textarea'
1583
- `;var ae=`'use client'
1583
+ `;var le=`'use client'
1584
1584
 
1585
1585
  import * as React from 'react'
1586
1586
  import { Toaster as Sonner, toast } from 'sonner'
@@ -1623,7 +1623,7 @@ function Toaster() {
1623
1623
  }
1624
1624
 
1625
1625
  export { Toaster, toast }
1626
- `;var ce=`import * as React from 'react'
1626
+ `;var de=`import * as React from 'react'
1627
1627
  import { cn } from '@/utils/cn'
1628
1628
 
1629
1629
  const styles = {
@@ -1632,7 +1632,8 @@ const styles = {
1632
1632
  'absolute z-50 px-2.5 py-1.5 text-xs font-medium',
1633
1633
  'rounded-lg bg-foreground text-background',
1634
1634
  'whitespace-nowrap pointer-events-none',
1635
- 'opacity-0 group-hover:opacity-100 transition-opacity'
1635
+ 'opacity-0 group-hover:opacity-100',
1636
+ 'group-focus-within:opacity-100 transition-opacity'
1636
1637
  ),
1637
1638
  positions: {
1638
1639
  top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
@@ -1656,7 +1657,10 @@ export function Tooltip({
1656
1657
  children,
1657
1658
  }: TooltipProps) {
1658
1659
  return (
1659
- <span className={cn(styles.base, className)}>
1660
+ <span
1661
+ tabIndex={0}
1662
+ className={cn(styles.base, 'outline-none', className)}
1663
+ >
1660
1664
  {children}
1661
1665
  <span className={cn(styles.tip, styles.positions[position])}>
1662
1666
  {content}
@@ -1664,4 +1668,4 @@ export function Tooltip({
1664
1668
  </span>
1665
1669
  )
1666
1670
  }
1667
- `;var C=[{name:"accordion",description:"Collapsible content sections with dot notation and smooth animation",dependencies:[],npmDependencies:[]},{name:"alert",description:"Contextual feedback messages with variants and icons",dependencies:[],npmDependencies:[]},{name:"avatar",description:"User avatar with image support and fallback initials",dependencies:[],npmDependencies:[]},{name:"badge",description:"Small status indicator with color variants",dependencies:[],npmDependencies:[]},{name:"button",description:"Button with variants, sizes, loading state, and icon slots",dependencies:[],npmDependencies:[]},{name:"card",description:"Container with dot notation preview and info sub-components",dependencies:[],npmDependencies:[]},{name:"checkbox",description:"Checkbox input with label and CSS-only checkmark",dependencies:[],npmDependencies:[]},{name:"dialog",description:"Modal dialog with dot notation, overlay, and escape key",dependencies:["button"],npmDependencies:[]},{name:"dropdown",description:"Dropdown menu with dot notation, groups, separators, and click-outside",dependencies:["button"],npmDependencies:[]},{name:"input",description:"Text input with focus ring and disabled state",dependencies:[],npmDependencies:[]},{name:"popover",description:"Floating content panel with dot notation and click-outside",dependencies:["button"],npmDependencies:[]},{name:"progress",description:"Progress bar with animated fill and ARIA attributes",dependencies:[],npmDependencies:[]},{name:"select",description:"Custom select with dot notation and composable options",dependencies:[],npmDependencies:[]},{name:"separator",description:"Visual divider with horizontal and vertical orientation",dependencies:[],npmDependencies:[]},{name:"switch",description:"Toggle switch with smooth transition",dependencies:[],npmDependencies:[]},{name:"tabs",description:"Tab navigation with dot notation and panel content",dependencies:[],npmDependencies:[]},{name:"textarea",description:"Multi-line text input with consistent styling",dependencies:[],npmDependencies:[]},{name:"theme",description:"Dark/light theme support with next-themes and ThemeProvider",dependencies:[],npmDependencies:["next-themes"]},{name:"toast",description:"Toast notifications powered by Sonner",dependencies:[],npmDependencies:["sonner"]},{name:"tooltip",description:"Pure CSS tooltip with 4 position options",dependencies:[],npmDependencies:[]}],k={accordion:_,alert:U,avatar:G,badge:W,button:K,card:X,checkbox:J,dialog:q,dropdown:Q,input:Y,popover:Z,progress:ee,select:te,separator:oe,switch:ne,tabs:se,textarea:re,theme:F,toast:ae,tooltip:ce};async function ie(t){let s=process.cwd();e.intro("drivn add");let r=V(s);if(r||(e.log.error("Drivn is not initialized. Run npx drivn@latest create"),e.outro("Cancelled"),process.exit(1)),!t||!t.length){let o=await e.multiselect({message:"Select components to add",options:C.map(i=>({label:i.name,hint:i.description,value:i.name})),required:true});e.isCancel(o)&&(e.cancel("Cancelled"),process.exit(0)),t=o;}let b=t.filter(o=>!C.find(i=>i.name===o));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+C.map(o=>o.name).join(", ")),e.outro("Cancelled"),process.exit(1));let d=t.includes("theme"),m=t.filter(o=>o!=="theme"),f=new Set,g=new Set,h=o=>{if(f.has(o))return;let i=C.find(c=>c.name===o);i&&(i.dependencies.forEach(c=>h(c)),i.npmDependencies?.forEach(c=>g.add(c)),f.add(o));};m.forEach(h),d&&g.add("next-themes");let y=[...f].filter(o=>!m.includes(o));y.length&&e.log.info(`Required dependency: ${y.join(", ")}`);let a=r.typescript?"tsx":"jsx",x=join(s,r.paths.components);for(let o of f){let i=join(x,`${o}.${a}`);if(v(i)){let N=await e.confirm({message:`${o}.${a} exists. Overwrite?`,initialValue:false});if(e.isCancel(N)||!N){e.log.warn(`Skipped ${o}`);continue}}let c=k[o];c=c.replace(/@\/utils/g,`@/${r.paths.utils.replace(/^src\//,"")}`),p(i,c),e.log.success(`${o} \u2192 ${r.paths.components}/${o}.${a}`);}if(d){let o=join(x,`theme-provider.${a}`);if(v(o)){let c=await e.confirm({message:`theme-provider.${a} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(p(o,k.theme),e.log.success(`theme-provider \u2192 ${r.paths.components}/theme-provider.${a}`)):e.log.warn("Skipped theme-provider");}else p(o,k.theme),e.log.success(`theme-provider \u2192 ${r.paths.components}/theme-provider.${a}`);if(r.paths.globals){let c=join(s,r.paths.globals);if(v(c)){let N=z(c);N.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(p(c,N+O),e.log.success(`Theme tokens appended to ${l.cyan(r.paths.globals)}`));}else e.log.warn(`Globals file not found at ${r.paths.globals}`);}else e.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let i=r.paths.components.replace(/^src\//,"@/");e.log.message(""),e.log.info(l.bold("Complete the setup:")),e.log.message(""),e.log.message(l.bold(`${l.cyan("1.")} Import ThemeProvider in your root layout:`)),e.log.message(l.cyan(` import { ThemeProvider } from "${i}/theme-provider"`)),e.log.message(""),e.log.message(l.bold(`${l.cyan("2.")} Add suppressHydrationWarning to <html>:`)),e.log.message(l.cyan(" <html suppressHydrationWarning>")),e.log.message(""),e.log.message(l.bold(`${l.cyan("3.")} Wrap your app with ThemeProvider:`)),e.log.message(l.cyan(" <ThemeProvider>")),e.log.message(l.cyan(" {children}")),e.log.message(l.cyan(" </ThemeProvider>")),e.log.message("");}if(g.size){let o=e.spinner();o.start("Installing packages");try{execSync(`npm install ${[...g].join(" ")}`,{cwd:s,stdio:"ignore"}),o.stop("Packages installed");}catch{o.stop("Failed to install packages"),e.log.warn(`Run manually: npm install ${[...g].join(" ")}`);}}e.outro("Done.");}var le={version:"1.0.1"};var I=new Command;I.name("drivn").description("Drivn \u2014 Modern UI components").version(le.version);I.command("create").description("Initialize Drivn in your project").action(H);I.command("add [components...]").description("Add components to your project").action(ie);I.parse();
1671
+ `;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:[]}],I={accordion:W,alert:K,avatar:X,badge:J,button:q,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=z(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=I[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,I.theme),e.log.success(`theme-provider \u2192 ${c.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else p(o,I.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+A),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.0.2"};var S=new Command;S.name("drivn").description("Drivn \u2014 Modern UI components").version(ue.version);S.command("create").description("Initialize Drivn in your project").action(U);S.command("add [components...]").description("Add components to your project").action(pe);S.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drivn",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Modern UI components for React — add beautiful, accessible components to your project",
5
5
  "license": "MIT",
6
6
  "type": "module",