drivn 1.7.1 → 1.8.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.
- package/dist/index.js +161 -39
- package/package.json +4 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {Command}from'commander';import*as
|
|
2
|
+
import {Command}from'commander';import*as n from'@clack/prompts';import m from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';import {McpServer}from'@modelcontextprotocol/sdk/server/mcp.js';import {StdioServerTransport}from'@modelcontextprotocol/sdk/server/stdio.js';import {z as z$1}from'zod';var z={next:"Next.js",react:"React"};function $(e){let r=join(e,"package.json");if(!existsSync(r))throw new Error("package.json not found");let t=JSON.parse(readFileSync(r,"utf-8")),a={...t.dependencies,...t.devDependencies},l="react";a.next&&(l="next");let d=existsSync(join(e,"src")),p=existsSync(join(e,"tsconfig.json"));return {framework:l,srcDir:d,typescript:p}}var G="drivn.config.json";function U(e){let r=join(e,G);return existsSync(r)?JSON.parse(readFileSync(r,"utf-8")):null}function K(e,r){let t=join(e,G);writeFileSync(t,JSON.stringify(r,null,2));}function Ae(e){existsSync(e)||mkdirSync(e,{recursive:true});}function b(e,r){Ae(dirname(e)),writeFileSync(e,r);}function H(e){return readFileSync(e,"utf-8")}function x(e){return existsSync(e)}function I(e){return existsSync(join(e,"pnpm-lock.yaml"))?"pnpm":"npm"}function R(e,r){let t=r.join(" ");return e==="pnpm"?`pnpm add ${t}`:`npm install ${t}`}function W(e){return e==="pnpm"?"pnpm dlx":"npx"}var C=`@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
|
+
`,k=`
|
|
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 ze=`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
|
+
`,$e=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function Ve(e){for(let r of $e)if(x(join(e,r)))return r;return null}async function Y(){let e=process.cwd();console.log(""),console.log(m.bgCyan(m.bold(m.black(" Drivn "))));let r;try{r=$(e),n.log.success(`Detected ${m.cyan(z[r.framework])}`);}catch{n.log.error("No package.json found. Run this command in a project directory."),n.outro("Setup cancelled"),process.exit(1);}if(x(join(e,"drivn.config.json"))){let s=await n.confirm({message:"Config already exists. Overwrite?",initialValue:false});(n.isCancel(s)||!s)&&(n.cancel("Setup cancelled"),process.exit(0));}let t=r.srcDir?"src/components/ui":"components/ui",a=r.srcDir?"src/utils":"utils",l=await n.group({components:()=>n.text({message:"Where should components be installed?",placeholder:t,defaultValue:t}),utils:()=>n.text({message:"Where should utilities be placed?",placeholder:a,defaultValue:a})},{onCancel:()=>{n.cancel("Setup cancelled"),process.exit(0);}}),d={framework:r.framework,typescript:r.typescript,paths:{components:l.components,utils:l.utils},installed:[]},p=r.typescript?"ts":"js",f=join(e,l.utils,`cn.${p}`);x(f)||b(f,ze);let g=Ve(e);if(g){let s=await n.confirm({message:`Found ${m.cyan(g)}. Add Drivn color tokens?`,initialValue:true});!n.isCancel(s)&&s&&(b(join(e,g),C),d.paths.globals=g,n.log.success(`Color tokens written to ${m.cyan(g)}`));}else {let s=r.srcDir?"src/styles/globals.css":"styles/globals.css",i=await n.text({message:"Where should the globals CSS file be created?",placeholder:s,defaultValue:s});n.isCancel(i)||(b(join(e,i),C),d.paths.globals=i,n.log.success(`Color tokens written to ${m.cyan(i)}`));}K(e,d);let N=I(e),u=W(N),h=["clsx","tailwind-merge","lucide-react"],o=n.spinner();o.start("Installing dependencies");try{execSync(R(N,h),{cwd:e,stdio:"ignore"}),o.stop("Dependencies installed");}catch{o.stop("Failed to install dependencies"),n.log.warn(`Run manually: ${R(N,h)}`);}n.log.info(`Add components with: ${m.cyan(`${u} drivn add button`)}`),n.log.info(`Add dark/light theme: ${m.cyan(`${u} drivn add theme`)}`),n.outro("Drivn initialized");}var q=`'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 J=`'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
|
|
296
|
+
`;var X=`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
|
|
344
|
+
`;var Z=`import * as React from 'react'
|
|
345
345
|
import { cn } from '@/utils/cn'
|
|
346
346
|
|
|
347
347
|
interface AspectRatioProps {
|
|
@@ -364,7 +364,7 @@ export function AspectRatio({
|
|
|
364
364
|
</div>
|
|
365
365
|
)
|
|
366
366
|
}
|
|
367
|
-
`;var
|
|
367
|
+
`;var Q=`import * as React from 'react'
|
|
368
368
|
import { cn } from '@/utils/cn'
|
|
369
369
|
|
|
370
370
|
const styles = {
|
|
@@ -408,7 +408,7 @@ export function Avatar({
|
|
|
408
408
|
</div>
|
|
409
409
|
)
|
|
410
410
|
}
|
|
411
|
-
`;var
|
|
411
|
+
`;var ee=`import * as React from 'react'
|
|
412
412
|
import { cn } from '@/utils/cn'
|
|
413
413
|
|
|
414
414
|
const styles = {
|
|
@@ -438,7 +438,7 @@ export function Badge({ variant = 'default', className, children }: BadgeProps)
|
|
|
438
438
|
</span>
|
|
439
439
|
)
|
|
440
440
|
}
|
|
441
|
-
`;var
|
|
441
|
+
`;var te=`import * as React from 'react'
|
|
442
442
|
import { cn } from '@/utils/cn'
|
|
443
443
|
import { ChevronRight, MoreHorizontal } from 'lucide-react'
|
|
444
444
|
|
|
@@ -554,7 +554,7 @@ export const Breadcrumb = Object.assign(BreadcrumbRoot, {
|
|
|
554
554
|
Separator: BreadcrumbSeparator,
|
|
555
555
|
Ellipsis,
|
|
556
556
|
})
|
|
557
|
-
`;var
|
|
557
|
+
`;var ne=`import * as React from 'react'
|
|
558
558
|
import { Loader2 } from 'lucide-react'
|
|
559
559
|
import { cn } from '@/utils/cn'
|
|
560
560
|
|
|
@@ -634,7 +634,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(({
|
|
|
634
634
|
)
|
|
635
635
|
|
|
636
636
|
Button.displayName = 'Button'
|
|
637
|
-
`;var
|
|
637
|
+
`;var oe=`'use client'
|
|
638
638
|
|
|
639
639
|
import * as React from 'react'
|
|
640
640
|
import {
|
|
@@ -810,7 +810,7 @@ export { type DateRange, type Locale }
|
|
|
810
810
|
export const Calendar = Object.assign(CalendarRoot, {
|
|
811
811
|
Range
|
|
812
812
|
})
|
|
813
|
-
`;var
|
|
813
|
+
`;var re=`'use client'
|
|
814
814
|
|
|
815
815
|
import * as React from 'react'
|
|
816
816
|
import { CalendarDays } from 'lucide-react'
|
|
@@ -1034,7 +1034,7 @@ export { type DateRange, type Locale }
|
|
|
1034
1034
|
export const DatePicker = Object.assign(DatePickerRoot, {
|
|
1035
1035
|
Range,
|
|
1036
1036
|
})
|
|
1037
|
-
`;var
|
|
1037
|
+
`;var se=`'use client'
|
|
1038
1038
|
|
|
1039
1039
|
import * as React from 'react'
|
|
1040
1040
|
import { Command as CommandPrimitive } from 'cmdk'
|
|
@@ -1265,7 +1265,7 @@ export const Command = Object.assign(CommandRoot, {
|
|
|
1265
1265
|
Shortcut,
|
|
1266
1266
|
Dialog: CommandDialog,
|
|
1267
1267
|
})
|
|
1268
|
-
`;var
|
|
1268
|
+
`;var ae=`'use client'
|
|
1269
1269
|
|
|
1270
1270
|
import * as React from 'react'
|
|
1271
1271
|
import useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'
|
|
@@ -1514,7 +1514,7 @@ export const Carousel = Object.assign(CarouselRoot, {
|
|
|
1514
1514
|
Next,
|
|
1515
1515
|
Dots
|
|
1516
1516
|
})
|
|
1517
|
-
`;var
|
|
1517
|
+
`;var ie=`import * as React from 'react'
|
|
1518
1518
|
import { cn } from '@/utils/cn'
|
|
1519
1519
|
|
|
1520
1520
|
const styles = {
|
|
@@ -1581,7 +1581,7 @@ export const Card = Object.assign(CardRoot, {
|
|
|
1581
1581
|
Preview,
|
|
1582
1582
|
Info
|
|
1583
1583
|
})
|
|
1584
|
-
`;var
|
|
1584
|
+
`;var ce=`'use client'
|
|
1585
1585
|
|
|
1586
1586
|
import * as React from 'react'
|
|
1587
1587
|
import { Check } from 'lucide-react'
|
|
@@ -1644,7 +1644,7 @@ export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(({
|
|
|
1644
1644
|
)
|
|
1645
1645
|
|
|
1646
1646
|
Checkbox.displayName = 'Checkbox'
|
|
1647
|
-
`;var
|
|
1647
|
+
`;var le=`'use client'
|
|
1648
1648
|
|
|
1649
1649
|
import * as React from 'react'
|
|
1650
1650
|
import { X } from 'lucide-react'
|
|
@@ -1800,7 +1800,7 @@ export const Dialog = Object.assign(DialogRoot, {
|
|
|
1800
1800
|
Trigger,
|
|
1801
1801
|
Content,
|
|
1802
1802
|
})
|
|
1803
|
-
`;var
|
|
1803
|
+
`;var de=`'use client'
|
|
1804
1804
|
|
|
1805
1805
|
import * as React from 'react'
|
|
1806
1806
|
import { X } from 'lucide-react'
|
|
@@ -2019,7 +2019,7 @@ export const Drawer = Object.assign(DrawerRoot, {
|
|
|
2019
2019
|
Header,
|
|
2020
2020
|
Footer,
|
|
2021
2021
|
})
|
|
2022
|
-
`;var
|
|
2022
|
+
`;var pe=`'use client'
|
|
2023
2023
|
|
|
2024
2024
|
import * as React from 'react'
|
|
2025
2025
|
import { cn } from '@/utils/cn'
|
|
@@ -2217,7 +2217,7 @@ export const Dropdown = Object.assign(DropdownRoot, {
|
|
|
2217
2217
|
Label,
|
|
2218
2218
|
Separator: DropdownSeparator
|
|
2219
2219
|
})
|
|
2220
|
-
`;var
|
|
2220
|
+
`;var me=`import * as React from 'react'
|
|
2221
2221
|
import { cn } from '@/utils/cn'
|
|
2222
2222
|
|
|
2223
2223
|
const styles = {
|
|
@@ -2240,7 +2240,7 @@ export const Input = React.forwardRef<HTMLInputElement, InputProps>(({
|
|
|
2240
2240
|
)
|
|
2241
2241
|
|
|
2242
2242
|
Input.displayName = 'Input'
|
|
2243
|
-
`;var
|
|
2243
|
+
`;var ue=`import * as React from 'react'
|
|
2244
2244
|
import { cn } from '@/utils/cn'
|
|
2245
2245
|
|
|
2246
2246
|
const styles = {
|
|
@@ -2297,7 +2297,7 @@ function Group({
|
|
|
2297
2297
|
}
|
|
2298
2298
|
|
|
2299
2299
|
export const Kbd = Object.assign(KbdRoot, { Group })
|
|
2300
|
-
`;var
|
|
2300
|
+
`;var fe=`import * as React from 'react'
|
|
2301
2301
|
import { cn } from '@/utils/cn'
|
|
2302
2302
|
|
|
2303
2303
|
export function Label({
|
|
@@ -2314,7 +2314,7 @@ export function Label({
|
|
|
2314
2314
|
/>
|
|
2315
2315
|
)
|
|
2316
2316
|
}
|
|
2317
|
-
`;var
|
|
2317
|
+
`;var ge=`import * as React from 'react'
|
|
2318
2318
|
import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react'
|
|
2319
2319
|
import { cn } from '@/utils/cn'
|
|
2320
2320
|
|
|
@@ -2447,7 +2447,7 @@ export const Pagination = Object.assign(PaginationRoot, {
|
|
|
2447
2447
|
Next,
|
|
2448
2448
|
Ellipsis: PaginationEllipsis,
|
|
2449
2449
|
})
|
|
2450
|
-
`;var
|
|
2450
|
+
`;var he=`'use client'
|
|
2451
2451
|
|
|
2452
2452
|
import * as React from 'react'
|
|
2453
2453
|
import { cn } from '@/utils/cn'
|
|
@@ -2552,7 +2552,7 @@ export const Popover = Object.assign(PopoverRoot, {
|
|
|
2552
2552
|
Trigger,
|
|
2553
2553
|
Content
|
|
2554
2554
|
})
|
|
2555
|
-
`;var
|
|
2555
|
+
`;var be=`import * as React from 'react'
|
|
2556
2556
|
import { cn } from '@/utils/cn'
|
|
2557
2557
|
|
|
2558
2558
|
const styles = {
|
|
@@ -2590,7 +2590,7 @@ export function Progress({
|
|
|
2590
2590
|
</div>
|
|
2591
2591
|
)
|
|
2592
2592
|
}
|
|
2593
|
-
`;var
|
|
2593
|
+
`;var ve=`'use client'
|
|
2594
2594
|
|
|
2595
2595
|
import * as React from 'react'
|
|
2596
2596
|
import { cn } from '@/utils/cn'
|
|
@@ -2739,7 +2739,7 @@ function useRadioGroup() {
|
|
|
2739
2739
|
}
|
|
2740
2740
|
|
|
2741
2741
|
export const RadioGroup = Object.assign(RadioGroupRoot, { Item })
|
|
2742
|
-
`;var
|
|
2742
|
+
`;var xe=`'use client'
|
|
2743
2743
|
|
|
2744
2744
|
import * as React from 'react'
|
|
2745
2745
|
import { ChevronDown } from 'lucide-react'
|
|
@@ -2893,7 +2893,7 @@ export const Select = Object.assign(SelectRoot, {
|
|
|
2893
2893
|
Menu,
|
|
2894
2894
|
Option
|
|
2895
2895
|
})
|
|
2896
|
-
`;var
|
|
2896
|
+
`;var ye=`import * as React from 'react'
|
|
2897
2897
|
import { cn } from '@/utils/cn'
|
|
2898
2898
|
|
|
2899
2899
|
const styles = {
|
|
@@ -2917,7 +2917,7 @@ export function Separator({
|
|
|
2917
2917
|
/>
|
|
2918
2918
|
)
|
|
2919
2919
|
}
|
|
2920
|
-
`;var
|
|
2920
|
+
`;var Ne=`'use client'
|
|
2921
2921
|
|
|
2922
2922
|
import * as React from 'react'
|
|
2923
2923
|
import { ChevronDown, PanelLeft } from 'lucide-react'
|
|
@@ -3203,7 +3203,7 @@ export const Sidebar = Object.assign(SidebarRoot, {
|
|
|
3203
3203
|
Separator: SidebarSeparator,
|
|
3204
3204
|
CollapseButton,
|
|
3205
3205
|
})
|
|
3206
|
-
`;var
|
|
3206
|
+
`;var Ce=`'use client'
|
|
3207
3207
|
|
|
3208
3208
|
import * as React from 'react'
|
|
3209
3209
|
import { cn } from '@/utils/cn'
|
|
@@ -3348,7 +3348,7 @@ export const Slider = React.forwardRef<HTMLInputElement, SliderProps>(({
|
|
|
3348
3348
|
)
|
|
3349
3349
|
|
|
3350
3350
|
Slider.displayName = 'Slider'
|
|
3351
|
-
`;var
|
|
3351
|
+
`;var we=`'use client'
|
|
3352
3352
|
|
|
3353
3353
|
import * as React from 'react'
|
|
3354
3354
|
import { cn } from '@/utils/cn'
|
|
@@ -3389,7 +3389,7 @@ export function Switch({
|
|
|
3389
3389
|
</button>
|
|
3390
3390
|
)
|
|
3391
3391
|
}
|
|
3392
|
-
`;var
|
|
3392
|
+
`;var Re=`'use client'
|
|
3393
3393
|
|
|
3394
3394
|
import * as React from 'react'
|
|
3395
3395
|
import { cn } from '@/utils/cn'
|
|
@@ -3503,7 +3503,7 @@ export const Tabs = Object.assign(TabsRoot, {
|
|
|
3503
3503
|
Tab,
|
|
3504
3504
|
Panel
|
|
3505
3505
|
})
|
|
3506
|
-
`;var
|
|
3506
|
+
`;var ke=`import * as React from 'react'
|
|
3507
3507
|
import { cn } from '@/utils/cn'
|
|
3508
3508
|
|
|
3509
3509
|
const styles = {
|
|
@@ -3530,7 +3530,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({
|
|
|
3530
3530
|
))
|
|
3531
3531
|
|
|
3532
3532
|
Textarea.displayName = 'Textarea'
|
|
3533
|
-
`;var
|
|
3533
|
+
`;var Pe=`'use client'
|
|
3534
3534
|
|
|
3535
3535
|
import * as React from 'react'
|
|
3536
3536
|
import { Toaster as Sonner, toast } from 'sonner'
|
|
@@ -3573,7 +3573,7 @@ function Toaster() {
|
|
|
3573
3573
|
}
|
|
3574
3574
|
|
|
3575
3575
|
export { Toaster, toast }
|
|
3576
|
-
`;var
|
|
3576
|
+
`;var De=`import * as React from 'react'
|
|
3577
3577
|
import { cn } from '@/utils/cn'
|
|
3578
3578
|
|
|
3579
3579
|
const styles = {
|
|
@@ -3747,7 +3747,7 @@ export const Table = Object.assign(TableRoot, {
|
|
|
3747
3747
|
Head,
|
|
3748
3748
|
Cell,
|
|
3749
3749
|
})
|
|
3750
|
-
`;var
|
|
3750
|
+
`;var Se=`import * as React from 'react'
|
|
3751
3751
|
import { cn } from '@/utils/cn'
|
|
3752
3752
|
|
|
3753
3753
|
const styles = {
|
|
@@ -3792,7 +3792,7 @@ export function Tooltip({
|
|
|
3792
3792
|
</span>
|
|
3793
3793
|
)
|
|
3794
3794
|
}
|
|
3795
|
-
`;var
|
|
3795
|
+
`;var Te=`
|
|
3796
3796
|
/* react-day-picker theme integration */
|
|
3797
3797
|
.rdp-root {
|
|
3798
3798
|
--rdp-accent-color: var(--primary);
|
|
@@ -3803,4 +3803,126 @@ export function Tooltip({
|
|
|
3803
3803
|
--rdp-selected-border: none;
|
|
3804
3804
|
--rdp-day_button-border: none;
|
|
3805
3805
|
}
|
|
3806
|
-
`,
|
|
3806
|
+
`,v=[{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:[]}],w={accordion:J,alert:X,"aspect-ratio":Z,avatar:Q,badge:ee,breadcrumb:te,button:ne,calendar:oe,"date-picker":re,command:se,carousel:ae,card:ie,checkbox:ce,dialog:le,drawer:de,dropdown:pe,input:me,kbd:ue,label:fe,pagination:ge,popover:he,progress:be,"radio-group":ve,select:xe,separator:ye,sidebar:Ne,slider:Ce,switch:we,table:De,tabs:Re,textarea:ke,theme:q,toast:Pe,tooltip:Se};async function Ee(e){let r=process.cwd();n.intro("drivn add");let t=U(r);if(t||(n.log.error("Drivn is not initialized. Run npx drivn@latest create"),n.outro("Cancelled"),process.exit(1)),!e||!e.length){let o=await n.multiselect({message:"Select components to add",options:v.map(s=>({label:s.name,hint:s.description,value:s.name})),required:true});n.isCancel(o)&&(n.cancel("Cancelled"),process.exit(0)),e=o;}let a=e.filter(o=>!v.find(s=>s.name===o));a.length&&(n.log.error(`Unknown components: ${a.join(", ")}`),n.log.info("Available: "+v.map(o=>o.name).join(", ")),n.outro("Cancelled"),process.exit(1));let l=e.includes("theme"),d=e.filter(o=>o!=="theme"),p=new Set,f=new Set,g=o=>{if(p.has(o))return;let s=v.find(i=>i.name===o);s&&(s.dependencies.forEach(i=>g(i)),s.npmDependencies?.forEach(i=>f.add(i)),p.add(o));};d.forEach(g),l&&f.add("next-themes");let N=[...p].filter(o=>!d.includes(o));N.length&&n.log.info(`Required dependency: ${N.join(", ")}`);let u=t.typescript?"tsx":"jsx",h=join(r,t.paths.components);for(let o of p){let s=join(h,`${o}.${u}`);if(x(s)){let D=await n.confirm({message:`${o}.${u} exists. Overwrite?`,initialValue:false});if(n.isCancel(D)||!D){n.log.warn(`Skipped ${o}`);continue}}let i=w[o];i=i.replace(/@\/utils/g,`@/${t.paths.utils.replace(/^src\//,"")}`),b(s,i),n.log.success(`${o} \u2192 ${t.paths.components}/${o}.${u}`);}if(l){let o=join(h,`theme-provider.${u}`);if(x(o)){let i=await n.confirm({message:`theme-provider.${u} exists. Overwrite?`,initialValue:false});!n.isCancel(i)&&i?(b(o,w.theme),n.log.success(`theme-provider \u2192 ${t.paths.components}/theme-provider.${u}`)):n.log.warn("Skipped theme-provider");}else b(o,w.theme),n.log.success(`theme-provider \u2192 ${t.paths.components}/theme-provider.${u}`);if(t.paths.globals){let i=join(r,t.paths.globals);if(x(i)){let D=H(i);D.includes('[data-theme="dark"]')?n.log.warn("Theme tokens already exist in globals \u2014 skipped"):(b(i,D+k),n.log.success(`Theme tokens appended to ${m.cyan(t.paths.globals)}`));}else n.log.warn(`Globals file not found at ${t.paths.globals}`);}else n.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let s=t.paths.components.replace(/^src\//,"@/");n.log.message(""),n.log.info(m.bold("Complete the setup:")),n.log.message(""),n.log.message(m.bold(`${m.cyan("1.")} Import ThemeProvider in your root layout:`)),n.log.message(m.cyan(` import { ThemeProvider } from "${s}/theme-provider"`)),n.log.message(""),n.log.message(m.bold(`${m.cyan("2.")} Add suppressHydrationWarning to <html>:`)),n.log.message(m.cyan(" <html suppressHydrationWarning>")),n.log.message(""),n.log.message(m.bold(`${m.cyan("3.")} Wrap your app with ThemeProvider:`)),n.log.message(m.cyan(" <ThemeProvider>")),n.log.message(m.cyan(" {children}")),n.log.message(m.cyan(" </ThemeProvider>")),n.log.message("");}if(p.has("calendar")&&t.paths.globals){let o=join(r,t.paths.globals);if(x(o)){let s=H(o);s.includes(".rdp-root")?n.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(b(o,s+Te),n.log.success(`Calendar tokens appended to ${m.cyan(t.paths.globals)}`));}}if(f.size){let o=I(r),s=[...f],i=n.spinner();i.start("Installing packages");try{execSync(R(o,s),{cwd:r,stdio:"ignore"}),i.stop("Packages installed");}catch{i.stop("Failed to install packages"),n.log.warn(`Run manually: ${R(o,s)}`);}}n.outro("Done.");}var j=`# Drivn Component Conventions
|
|
3807
|
+
|
|
3808
|
+
## Core Philosophy
|
|
3809
|
+
- **Zero runtime UI deps** \u2014 No Radix, no cva, no external UI primitives. Pure React + Tailwind.
|
|
3810
|
+
- **Copy & own** \u2014 Components live in user's codebase. Full control after install.
|
|
3811
|
+
|
|
3812
|
+
## Import Convention
|
|
3813
|
+
\`\`\`tsx
|
|
3814
|
+
import * as React from 'react'
|
|
3815
|
+
\`\`\`
|
|
3816
|
+
One import, full access to all React APIs via \`React.*\` prefix.
|
|
3817
|
+
|
|
3818
|
+
## Dot Notation API
|
|
3819
|
+
Use compound sub-components via dot notation:
|
|
3820
|
+
\`\`\`tsx
|
|
3821
|
+
// Correct
|
|
3822
|
+
<Dialog.Content>
|
|
3823
|
+
<Dialog.Header>
|
|
3824
|
+
<Dialog.Title>Title</Dialog.Title>
|
|
3825
|
+
</Dialog.Header>
|
|
3826
|
+
</Dialog.Content>
|
|
3827
|
+
|
|
3828
|
+
// Wrong \u2014 never use flat names
|
|
3829
|
+
<DialogContent>
|
|
3830
|
+
<DialogHeader>
|
|
3831
|
+
<DialogTitle>Title</DialogTitle>
|
|
3832
|
+
</DialogHeader>
|
|
3833
|
+
</DialogContent>
|
|
3834
|
+
\`\`\`
|
|
3835
|
+
|
|
3836
|
+
## const styles Pattern
|
|
3837
|
+
All classes live in a \`const styles\` object at the top of the file, never inline in JSX:
|
|
3838
|
+
\`\`\`tsx
|
|
3839
|
+
const styles = {
|
|
3840
|
+
base: cn(
|
|
3841
|
+
'inline-flex items-center justify-center',
|
|
3842
|
+
'rounded-lg font-medium transition-colors',
|
|
3843
|
+
'focus-visible:outline-none focus-visible:ring-2'
|
|
3844
|
+
),
|
|
3845
|
+
sizes: {
|
|
3846
|
+
sm: 'h-8 px-3 text-sm gap-1.5',
|
|
3847
|
+
md: 'h-10 px-4 text-sm gap-2',
|
|
3848
|
+
lg: 'h-12 px-6 text-base gap-2.5',
|
|
3849
|
+
},
|
|
3850
|
+
variants: {
|
|
3851
|
+
default: 'bg-primary text-white hover:bg-primary/90',
|
|
3852
|
+
secondary: 'bg-muted text-foreground hover:bg-muted/80',
|
|
3853
|
+
outline: 'border border-border bg-transparent hover:bg-muted/50',
|
|
3854
|
+
destructive: 'bg-destructive text-white hover:bg-destructive/90',
|
|
3855
|
+
},
|
|
3856
|
+
}
|
|
3857
|
+
\`\`\`
|
|
3858
|
+
|
|
3859
|
+
## Type-Safe Variants
|
|
3860
|
+
Use \`keyof typeof\` for autocomplete, no magic strings:
|
|
3861
|
+
\`\`\`tsx
|
|
3862
|
+
interface ButtonProps {
|
|
3863
|
+
variant?: keyof typeof styles.variants
|
|
3864
|
+
size?: keyof typeof styles.sizes
|
|
3865
|
+
}
|
|
3866
|
+
\`\`\`
|
|
3867
|
+
|
|
3868
|
+
## Icon Props
|
|
3869
|
+
Pass component references, not JSX elements:
|
|
3870
|
+
\`\`\`tsx
|
|
3871
|
+
// Correct
|
|
3872
|
+
<Button leftIcon={Plus}>Add</Button>
|
|
3873
|
+
|
|
3874
|
+
// Wrong
|
|
3875
|
+
<Button leftIcon={<Plus />}>Add</Button>
|
|
3876
|
+
\`\`\`
|
|
3877
|
+
|
|
3878
|
+
## Class Merging
|
|
3879
|
+
Use the \`cn()\` utility from \`@/utils/cn\`:
|
|
3880
|
+
\`\`\`tsx
|
|
3881
|
+
import { cn } from '@/utils/cn'
|
|
3882
|
+
// cn is clsx + tailwind-merge
|
|
3883
|
+
\`\`\`
|
|
3884
|
+
|
|
3885
|
+
## Component Categories
|
|
3886
|
+
|
|
3887
|
+
### Simple Components (Button, Badge, Input)
|
|
3888
|
+
- Single file, direct props, \`const styles\` object
|
|
3889
|
+
- Form elements use \`React.forwardRef\`
|
|
3890
|
+
|
|
3891
|
+
### Compound Components (Dialog, Tabs, Dropdown)
|
|
3892
|
+
- Dot notation API with context
|
|
3893
|
+
- Parent manages state, children consume via context
|
|
3894
|
+
- Export pattern: \`const Dialog = Object.assign(DialogRoot, { Content, Header, ... })\`
|
|
3895
|
+
|
|
3896
|
+
### Form Components (Input, Textarea, Select)
|
|
3897
|
+
- Always use \`React.forwardRef\` for ref forwarding
|
|
3898
|
+
- Support \`className\` override via \`cn()\`
|
|
3899
|
+
|
|
3900
|
+
## Color System
|
|
3901
|
+
- HSL custom properties for all colors
|
|
3902
|
+
- Theme switching via \`data-theme\` attribute (not \`class\`)
|
|
3903
|
+
- Never use hardcoded hex/rgba \u2014 always reference design tokens
|
|
3904
|
+
- Tokens: \`--background\`, \`--foreground\`, \`--primary\`, \`--muted\`, \`--border\`, \`--accent\`, etc.
|
|
3905
|
+
- Tailwind usage: \`bg-primary\`, \`text-foreground\`, \`border-border\`
|
|
3906
|
+
|
|
3907
|
+
## File Naming
|
|
3908
|
+
- kebab-case: \`date-picker.tsx\`, \`radio-group.tsx\`
|
|
3909
|
+
- Import from: \`@/components/ui/{name}\`
|
|
3910
|
+
|
|
3911
|
+
## Line Width
|
|
3912
|
+
- 80 character lines maximum
|
|
3913
|
+
- Every component should fit on screen without horizontal scrolling
|
|
3914
|
+
|
|
3915
|
+
## Dependencies
|
|
3916
|
+
- Components declare internal deps (other Drivn components)
|
|
3917
|
+
- Some components need npm packages (react-day-picker, cmdk, embla-carousel-react, sonner)
|
|
3918
|
+
- The CLI resolves and installs all dependencies automatically
|
|
3919
|
+
`;var L={version:"1.8.0"};function O(e){return v.find(r=>r.name===e)}function Ke(e){let r=new Set,t=a=>{if(r.has(a))return;let l=O(a);l&&(l.dependencies.forEach(d=>t(d)),r.add(a));};return t(e),r.delete(e),[...r]}async function Ie(){let e=new McpServer({name:"drivn",version:L.version});e.tool("list_components","List all available Drivn UI components with descriptions",{},async()=>({content:[{type:"text",text:JSON.stringify(v.map(t=>({name:t.name,description:t.description})),null,2)}]})),e.tool("get_component","Get the full source code and metadata for a Drivn component",{name:z$1.string().describe('Component name (e.g. "button", "dialog")')},async({name:t})=>{let a=O(t);if(!a)return {content:[{type:"text",text:`Component "${t}" not found. Use list_components to see available components.`}],isError:true};let l=w[t];return {content:[{type:"text",text:JSON.stringify({name:a.name,description:a.description,dependencies:a.dependencies,npmDependencies:a.npmDependencies,source:l},null,2)}]}}),e.tool("get_component_metadata","Get metadata only (no source code) for a Drivn component \u2014 useful for planning",{name:z$1.string().describe("Component name")},async({name:t})=>{let a=O(t);if(!a)return {content:[{type:"text",text:`Component "${t}" not found. Use list_components to see available components.`}],isError:true};let l=Ke(t);return {content:[{type:"text",text:JSON.stringify({name:a.name,description:a.description,dependencies:a.dependencies,npmDependencies:a.npmDependencies,allResolvedDependencies:l},null,2)}]}}),e.tool("search_components","Search Drivn components by name or description",{query:z$1.string().describe("Search query")},async({query:t})=>{let a=t.toLowerCase(),l=v.filter(d=>d.name.includes(a)||d.description.toLowerCase().includes(a));return {content:[{type:"text",text:l.length?JSON.stringify(l.map(d=>({name:d.name,description:d.description})),null,2):`No components matching "${t}".`}]}}),e.tool("get_installation_instructions","Get step-by-step installation instructions for one or more components",{components:z$1.array(z$1.string()).describe("Component names to install"),packageManager:z$1.enum(["npm","pnpm"]).optional().describe("Package manager (default: npm)")},async({components:t,packageManager:a})=>{let l=a??"npm",d=new Set,p=new Set,f=[],g=o=>{if(d.has(o))return;let s=O(o);if(!s){f.push(o);return}s.dependencies.forEach(i=>g(i)),s.npmDependencies.forEach(i=>p.add(i)),d.add(o);};if(t.forEach(g),f.length)return {content:[{type:"text",text:`Unknown components: ${f.join(", ")}. Use list_components to see available components.`}],isError:true};let N=l==="pnpm"?"pnpm dlx":"npx",u=l==="pnpm"?"pnpm add":"npm install",h=[];return h.push(`# Install components via CLI
|
|
3920
|
+
${N} drivn@latest add ${[...d].join(" ")}`),p.size&&h.push(`# Install required npm dependencies
|
|
3921
|
+
${u} ${[...p].join(" ")}`),h.push(`# Components will be installed to your configured components directory
|
|
3922
|
+
# (default: src/components/ui/)`),{content:[{type:"text",text:JSON.stringify({componentsToInstall:[...d],npmDependencies:[...p],steps:h},null,2)}]}}),e.tool("get_design_tokens","Get the Drivn CSS design tokens (base globals and theme tokens)",{},async()=>({content:[{type:"text",text:`/* === Base Globals === */
|
|
3923
|
+
${C}
|
|
3924
|
+
|
|
3925
|
+
/* === Theme Tokens === */
|
|
3926
|
+
${k}`}]})),e.tool("get_drivn_rules","Get Drivn coding conventions and component patterns",{},async()=>({content:[{type:"text",text:j}]})),e.resource("drivn-rules","drivn://rules",{description:"Drivn coding conventions and component patterns"},async()=>({contents:[{uri:"drivn://rules",mimeType:"text/markdown",text:j}]})),e.resource("drivn-design-tokens","drivn://design-tokens",{description:"Drivn CSS globals and theme tokens"},async()=>({contents:[{uri:"drivn://design-tokens",mimeType:"text/css",text:`${C}
|
|
3927
|
+
|
|
3928
|
+
${k}`}]}));for(let t of v){let a=`drivn://components/${t.name}`;e.resource(`drivn-component-${t.name}`,a,{description:t.description},async()=>({contents:[{uri:a,mimeType:"text/plain",text:w[t.name]}]}));}let r=new StdioServerTransport;await e.connect(r);}var E=new Command;E.name("drivn").description("Drivn \u2014 Modern UI components").version(L.version);E.command("create").description("Initialize Drivn in your project").action(Y);E.command("add [components...]").description("Add components to your project").action(Ee);E.command("mcp").description("Start the Drivn MCP server").action(Ie);E.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drivn",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Modern UI components for React — add beautiful, accessible components to your project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -39,8 +39,10 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@clack/prompts": "^0.9.1",
|
|
42
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
42
43
|
"commander": "^12.1.0",
|
|
43
|
-
"picocolors": "^1.1.1"
|
|
44
|
+
"picocolors": "^1.1.1",
|
|
45
|
+
"zod": "^3.25.0"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
48
|
"@types/node": "^20.14.0",
|