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.
- package/dist/index.js +30 -26
- 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
|
|
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
|
-
`,
|
|
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
|
|
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
|
-
`,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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();
|