drivn 1.14.0 → 1.15.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 +234 -11
- 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 n from'@clack/prompts';import u 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 j={next:"Next.js",react:"React"};function V(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 F="drivn.config.json";function U(e){let r=join(e,F);return existsSync(r)?JSON.parse(readFileSync(r,"utf-8")):null}function K(e,r){let t=join(e,F);writeFileSync(t,JSON.stringify(r,null,2));}function
|
|
2
|
+
import {Command}from'commander';import*as n from'@clack/prompts';import u 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 j={next:"Next.js",react:"React"};function V(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 F="drivn.config.json";function U(e){let r=join(e,F);return existsSync(r)?JSON.parse(readFileSync(r,"utf-8")):null}function K(e,r){let t=join(e,F);writeFileSync(t,JSON.stringify(r,null,2));}function Fe(e){existsSync(e)||mkdirSync(e,{recursive:true});}function h(e,r){Fe(dirname(e)),writeFileSync(e,r);}function B(e){return readFileSync(e,"utf-8")}function x(e){return existsSync(e)}function E(e){return existsSync(join(e,"pnpm-lock.yaml"))?"pnpm":"npm"}function w(e,r){let t=r.join(" ");return e==="pnpm"?`pnpm add ${t}`:`npm install ${t}`}function Y(e){return e==="pnpm"?"pnpm dlx":"npx"}var C=`@import "tailwindcss";
|
|
3
3
|
|
|
4
4
|
:root {
|
|
5
5
|
/* Surfaces */
|
|
@@ -136,13 +136,13 @@ body {
|
|
|
136
136
|
/* Special Surfaces */
|
|
137
137
|
--overlay: hsl(0 0% 0% / 0.18);
|
|
138
138
|
}
|
|
139
|
-
`;var
|
|
139
|
+
`;var We=`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
|
+
`,Xe=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function qe(e){for(let r of Xe)if(x(join(e,r)))return r;return null}async function W(){let e=process.cwd();console.log(""),console.log(u.bgCyan(u.bold(u.black(" Drivn "))));let r;try{r=V(e),n.log.success(`Detected ${u.cyan(j[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}},p=r.typescript?"ts":"js",f=join(e,l.utils,`cn.${p}`);x(f)||h(f,We);let g=qe(e);if(g){let s=await n.confirm({message:`Found ${u.cyan(g)}. Add Drivn color tokens?`,initialValue:true});!n.isCancel(s)&&s&&(h(join(e,g),C),d.paths.globals=g,n.log.success(`Color tokens written to ${u.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)||(h(join(e,i),C),d.paths.globals=i,n.log.success(`Color tokens written to ${u.cyan(i)}`));}K(e,d);let N=E(e),m=Y(N),b=["clsx","tailwind-merge","lucide-react"],o=n.spinner();o.start("Installing dependencies");try{execSync(w(N,b),{cwd:e,stdio:"ignore"}),o.stop("Dependencies installed");}catch{o.stop("Failed to install dependencies"),n.log.warn(`Run manually: ${w(N,b)}`);}n.log.info(`Add components with: ${u.cyan(`${m} drivn add button`)}`),n.log.info(`Add dark/light theme: ${u.cyan(`${m} drivn add theme`)}`),n.outro("Drivn initialized");}var X=`'use client'
|
|
146
146
|
|
|
147
147
|
import { ThemeProvider as NextThemesProvider } from 'next-themes'
|
|
148
148
|
|
|
@@ -3451,6 +3451,7 @@ function Trigger({
|
|
|
3451
3451
|
const { open, setOpen } = usePopover()
|
|
3452
3452
|
return (
|
|
3453
3453
|
<Button
|
|
3454
|
+
type="button"
|
|
3454
3455
|
variant="outline"
|
|
3455
3456
|
rounded="md"
|
|
3456
3457
|
className={className}
|
|
@@ -3902,7 +3903,7 @@ export function Separator({
|
|
|
3902
3903
|
/>
|
|
3903
3904
|
)
|
|
3904
3905
|
}
|
|
3905
|
-
`;var
|
|
3906
|
+
`;var Se=`import * as React from 'react'
|
|
3906
3907
|
import { cn } from '@/utils/cn'
|
|
3907
3908
|
|
|
3908
3909
|
export function Skeleton({
|
|
@@ -3919,7 +3920,7 @@ export function Skeleton({
|
|
|
3919
3920
|
/>
|
|
3920
3921
|
)
|
|
3921
3922
|
}
|
|
3922
|
-
`;var
|
|
3923
|
+
`;var Pe=`'use client'
|
|
3923
3924
|
|
|
3924
3925
|
import * as React from 'react'
|
|
3925
3926
|
import { ChevronDown, PanelLeft } from 'lucide-react'
|
|
@@ -4684,6 +4685,228 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({
|
|
|
4684
4685
|
Textarea.displayName = 'Textarea'
|
|
4685
4686
|
`;var Me=`'use client'
|
|
4686
4687
|
|
|
4688
|
+
import * as React from 'react'
|
|
4689
|
+
import { Clock } from 'lucide-react'
|
|
4690
|
+
import { cn } from '@/utils/cn'
|
|
4691
|
+
import { Popover } from '@/components/ui/popover'
|
|
4692
|
+
import { Input } from '@/components/ui/input'
|
|
4693
|
+
|
|
4694
|
+
const styles = {
|
|
4695
|
+
base: 'relative block max-w-xs',
|
|
4696
|
+
trigger: cn(
|
|
4697
|
+
'flex items-center gap-2 w-full h-10 px-3',
|
|
4698
|
+
'border border-input rounded-[10px] text-sm',
|
|
4699
|
+
'text-foreground transition-colors',
|
|
4700
|
+
'font-normal hover:scale-100',
|
|
4701
|
+
'focus:outline-none',
|
|
4702
|
+
'disabled:opacity-50 disabled:cursor-default'
|
|
4703
|
+
),
|
|
4704
|
+
placeholder: 'text-muted-foreground',
|
|
4705
|
+
icon: 'w-4 h-4 text-muted-foreground shrink-0',
|
|
4706
|
+
text: 'flex-1 truncate text-left',
|
|
4707
|
+
content: 'p-2',
|
|
4708
|
+
columns: 'flex gap-1',
|
|
4709
|
+
column: cn(
|
|
4710
|
+
'flex flex-col items-center',
|
|
4711
|
+
'h-[220px] overflow-y-auto px-1',
|
|
4712
|
+
'[&::-webkit-scrollbar]:w-1',
|
|
4713
|
+
'[&::-webkit-scrollbar-thumb]:rounded-full',
|
|
4714
|
+
'[&::-webkit-scrollbar-thumb]:bg-border',
|
|
4715
|
+
'[&::-webkit-scrollbar-track]:bg-transparent'
|
|
4716
|
+
),
|
|
4717
|
+
columnLabel: cn(
|
|
4718
|
+
'text-xs font-medium text-muted-foreground',
|
|
4719
|
+
'pb-1'
|
|
4720
|
+
),
|
|
4721
|
+
cell: cn(
|
|
4722
|
+
'flex items-center justify-center w-14 h-12',
|
|
4723
|
+
'text-base rounded-lg hover:bg-accent',
|
|
4724
|
+
'transition-colors cursor-pointer'
|
|
4725
|
+
),
|
|
4726
|
+
cellActive: cn(
|
|
4727
|
+
'bg-foreground text-background font-medium',
|
|
4728
|
+
'hover:bg-foreground hover:text-background'
|
|
4729
|
+
),
|
|
4730
|
+
period: 'flex flex-col gap-0.5 pt-5 pl-1',
|
|
4731
|
+
periodBtn: cn(
|
|
4732
|
+
'flex items-center justify-center w-14 h-12',
|
|
4733
|
+
'text-xs font-medium rounded-lg',
|
|
4734
|
+
'hover:bg-accent transition-colors cursor-pointer'
|
|
4735
|
+
),
|
|
4736
|
+
}
|
|
4737
|
+
|
|
4738
|
+
interface TimePickerProps {
|
|
4739
|
+
selected?: Date
|
|
4740
|
+
onSelect?: (date: Date | undefined) => void
|
|
4741
|
+
format?: '12h' | '24h'
|
|
4742
|
+
showSeconds?: boolean
|
|
4743
|
+
placeholder?: string
|
|
4744
|
+
formatTime?: (date: Date) => string
|
|
4745
|
+
disabled?: boolean
|
|
4746
|
+
className?: string
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4749
|
+
function to24(v: number, period: 'AM' | 'PM' | undefined) {
|
|
4750
|
+
if (!period) return v
|
|
4751
|
+
if (period === 'AM') return v === 12 ? 0 : v
|
|
4752
|
+
return v === 12 ? 12 : v + 12
|
|
4753
|
+
}
|
|
4754
|
+
|
|
4755
|
+
function Column({
|
|
4756
|
+
items,
|
|
4757
|
+
selected,
|
|
4758
|
+
onSelect,
|
|
4759
|
+
label,
|
|
4760
|
+
}: {
|
|
4761
|
+
items: number[]
|
|
4762
|
+
selected: number | undefined
|
|
4763
|
+
onSelect: (v: number) => void
|
|
4764
|
+
label: string
|
|
4765
|
+
}) {
|
|
4766
|
+
const ref = React.useRef<HTMLDivElement>(null)
|
|
4767
|
+
React.useEffect(() => {
|
|
4768
|
+
const col = ref.current
|
|
4769
|
+
const el = col?.querySelector('[data-selected]') as HTMLElement | null
|
|
4770
|
+
if (!col || !el) return
|
|
4771
|
+
col.scrollTop = el.offsetTop - col.offsetTop - col.clientHeight / 2 + el.clientHeight / 2
|
|
4772
|
+
}, [selected])
|
|
4773
|
+
|
|
4774
|
+
return (
|
|
4775
|
+
<div className="flex flex-col items-center">
|
|
4776
|
+
<span className={styles.columnLabel}>{label}</span>
|
|
4777
|
+
<div ref={ref} className={styles.column}>
|
|
4778
|
+
{items.map((v) => (
|
|
4779
|
+
<button
|
|
4780
|
+
key={v}
|
|
4781
|
+
type="button"
|
|
4782
|
+
data-selected={v === selected || undefined}
|
|
4783
|
+
className={cn(
|
|
4784
|
+
styles.cell,
|
|
4785
|
+
v === selected && styles.cellActive
|
|
4786
|
+
)}
|
|
4787
|
+
onClick={() => onSelect(v)}
|
|
4788
|
+
>
|
|
4789
|
+
{String(v).padStart(2, '0')}
|
|
4790
|
+
</button>
|
|
4791
|
+
))}
|
|
4792
|
+
</div>
|
|
4793
|
+
</div>
|
|
4794
|
+
)
|
|
4795
|
+
}
|
|
4796
|
+
|
|
4797
|
+
function TimePickerRoot({
|
|
4798
|
+
selected,
|
|
4799
|
+
onSelect,
|
|
4800
|
+
format = '24h',
|
|
4801
|
+
showSeconds = false,
|
|
4802
|
+
placeholder = 'Pick a time',
|
|
4803
|
+
formatTime,
|
|
4804
|
+
disabled = false,
|
|
4805
|
+
className,
|
|
4806
|
+
}: TimePickerProps) {
|
|
4807
|
+
const is12 = format === '12h'
|
|
4808
|
+
const h = selected?.getHours()
|
|
4809
|
+
const m = selected?.getMinutes()
|
|
4810
|
+
const s = selected?.getSeconds()
|
|
4811
|
+
const period = h !== undefined ? (h >= 12 ? 'PM' : 'AM') : undefined
|
|
4812
|
+
const h12 = h !== undefined ? (h % 12 || 12) : undefined
|
|
4813
|
+
const hours = is12 ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 24 }, (_, i) => i)
|
|
4814
|
+
const values = Array.from({ length: 60 }, (_, i) => i)
|
|
4815
|
+
|
|
4816
|
+
return (
|
|
4817
|
+
<Popover className={cn(styles.base, className)}>
|
|
4818
|
+
<Popover.Trigger disabled={disabled} className={styles.trigger}>
|
|
4819
|
+
<Clock className={styles.icon} />
|
|
4820
|
+
<span className={cn(styles.text, !selected && styles.placeholder)}>
|
|
4821
|
+
{selected ? (formatTime?.(selected) ?? selected.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', ...(showSeconds && { second: '2-digit' }), hour12: is12 })) : placeholder}
|
|
4822
|
+
</span>
|
|
4823
|
+
</Popover.Trigger>
|
|
4824
|
+
<Popover.Content className={styles.content}>
|
|
4825
|
+
<div className={styles.columns}>
|
|
4826
|
+
<Column
|
|
4827
|
+
label="Hr"
|
|
4828
|
+
items={hours}
|
|
4829
|
+
selected={is12 ? h12 : h}
|
|
4830
|
+
onSelect={(v) =>
|
|
4831
|
+
onSelect?.(new Date(0, 0, 0, is12 ? to24(v, period) : v, m ?? 0, s ?? 0))
|
|
4832
|
+
}
|
|
4833
|
+
/>
|
|
4834
|
+
<Column
|
|
4835
|
+
label="Min"
|
|
4836
|
+
items={values}
|
|
4837
|
+
selected={m}
|
|
4838
|
+
onSelect={(v) =>
|
|
4839
|
+
onSelect?.(new Date(0, 0, 0, h ?? 0, v, s ?? 0))
|
|
4840
|
+
}
|
|
4841
|
+
/>
|
|
4842
|
+
{showSeconds && (
|
|
4843
|
+
<Column
|
|
4844
|
+
label="Sec"
|
|
4845
|
+
items={values}
|
|
4846
|
+
selected={s}
|
|
4847
|
+
onSelect={(v) =>
|
|
4848
|
+
onSelect?.(new Date(0, 0, 0, h ?? 0, m ?? 0, v))
|
|
4849
|
+
}
|
|
4850
|
+
/>
|
|
4851
|
+
)}
|
|
4852
|
+
{is12 && (
|
|
4853
|
+
<div className={styles.period}>
|
|
4854
|
+
{(['AM', 'PM'] as const).map((p) => (
|
|
4855
|
+
<button
|
|
4856
|
+
key={p}
|
|
4857
|
+
type="button"
|
|
4858
|
+
className={cn(
|
|
4859
|
+
styles.periodBtn,
|
|
4860
|
+
period === p && styles.cellActive
|
|
4861
|
+
)}
|
|
4862
|
+
onClick={() => onSelect?.(new Date(0, 0, 0, to24(h12 ?? 12, p), m ?? 0, s ?? 0))}
|
|
4863
|
+
>
|
|
4864
|
+
{p}
|
|
4865
|
+
</button>
|
|
4866
|
+
))}
|
|
4867
|
+
</div>
|
|
4868
|
+
)}
|
|
4869
|
+
</div>
|
|
4870
|
+
</Popover.Content>
|
|
4871
|
+
</Popover>
|
|
4872
|
+
)
|
|
4873
|
+
}
|
|
4874
|
+
|
|
4875
|
+
function TimePickerInput({
|
|
4876
|
+
selected,
|
|
4877
|
+
onSelect,
|
|
4878
|
+
className,
|
|
4879
|
+
...props
|
|
4880
|
+
}: Omit<
|
|
4881
|
+
React.InputHTMLAttributes<HTMLInputElement>,
|
|
4882
|
+
'type' | 'onChange' | 'value' | 'onSelect'
|
|
4883
|
+
> & {
|
|
4884
|
+
selected?: Date
|
|
4885
|
+
onSelect?: (date: Date | undefined) => void
|
|
4886
|
+
}) {
|
|
4887
|
+
const value = selected ? String(selected.getHours()).padStart(2, '0') + ':' + String(selected.getMinutes()).padStart(2, '0') : ''
|
|
4888
|
+
|
|
4889
|
+
return (
|
|
4890
|
+
<Input
|
|
4891
|
+
type="time"
|
|
4892
|
+
value={value}
|
|
4893
|
+
onChange={(e) => {
|
|
4894
|
+
const v = (e.target as HTMLInputElement).value
|
|
4895
|
+
if (!v) return onSelect?.(undefined)
|
|
4896
|
+
const [h, m] = v.split(':').map(Number)
|
|
4897
|
+
onSelect?.(new Date(0, 0, 0, h, m))
|
|
4898
|
+
}}
|
|
4899
|
+
className={className}
|
|
4900
|
+
{...props}
|
|
4901
|
+
/>
|
|
4902
|
+
)
|
|
4903
|
+
}
|
|
4904
|
+
|
|
4905
|
+
export const TimePicker = Object.assign(TimePickerRoot, {
|
|
4906
|
+
Input: TimePickerInput
|
|
4907
|
+
})
|
|
4908
|
+
`;var Oe=`'use client'
|
|
4909
|
+
|
|
4687
4910
|
import * as React from 'react'
|
|
4688
4911
|
import { Toaster as Sonner, toast } from 'sonner'
|
|
4689
4912
|
import {
|
|
@@ -4725,7 +4948,7 @@ function Toaster() {
|
|
|
4725
4948
|
}
|
|
4726
4949
|
|
|
4727
4950
|
export { Toaster, toast }
|
|
4728
|
-
`;var
|
|
4951
|
+
`;var Ae=`'use client'
|
|
4729
4952
|
|
|
4730
4953
|
import * as React from 'react'
|
|
4731
4954
|
import { cn } from '@/utils/cn'
|
|
@@ -4887,7 +5110,7 @@ const Ctx = React.createContext<ToggleGroupCtx | null>(null)
|
|
|
4887
5110
|
export const Toggle = Object.assign(ToggleButton, {
|
|
4888
5111
|
Group: ToggleGroupRoot,
|
|
4889
5112
|
})
|
|
4890
|
-
`;var
|
|
5113
|
+
`;var He=`import * as React from 'react'
|
|
4891
5114
|
import { cn } from '@/utils/cn'
|
|
4892
5115
|
|
|
4893
5116
|
const styles = {
|
|
@@ -5106,7 +5329,7 @@ export function Tooltip({
|
|
|
5106
5329
|
</span>
|
|
5107
5330
|
)
|
|
5108
5331
|
}
|
|
5109
|
-
`;var
|
|
5332
|
+
`;var ze=`
|
|
5110
5333
|
/* react-day-picker theme integration */
|
|
5111
5334
|
.rdp-root {
|
|
5112
5335
|
--rdp-accent-color: var(--primary);
|
|
@@ -5117,7 +5340,7 @@ export function Tooltip({
|
|
|
5117
5340
|
--rdp-selected-border: none;
|
|
5118
5341
|
--rdp-day_button-border: none;
|
|
5119
5342
|
}
|
|
5120
|
-
`,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:"combobox",description:"Searchable select with filtering, single/multi selection, and keyboard navigation",dependencies:[],npmDependencies:["cmdk"]},{name:"collapsible",description:"Toggle content visibility with smooth animation and accessible controls",dependencies:[],npmDependencies:[]},{name:"context-menu",description:"Right-click context menu with submenus, keyboard shortcuts, icons, and dot notation",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:"navigation-menu",description:"Horizontal navigation menu with dropdown content panels and dot notation",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:"scroll-area",description:"Themed scrollable container with custom scrollbar styling and orientation control",dependencies:[],npmDependencies:[]},{name:"separator",description:"Visual divider with horizontal and vertical orientation",dependencies:[],npmDependencies:[]},{name:"skeleton",description:"Loading placeholder with pulse animation, sized and shaped via className",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:"stepper",description:"Multi-step progress indicator with horizontal/vertical orientation, connecting lines, and dot notation",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:"toggle",description:"Toggle button with pressed state, single and multiple selection groups",dependencies:[],npmDependencies:[]},{name:"tooltip",description:"Pure CSS tooltip with 4 position options",dependencies:[],npmDependencies:[]}],R={accordion:q,alert:J,"aspect-ratio":Z,avatar:Q,badge:ee,breadcrumb:te,button:ne,calendar:oe,"date-picker":re,command:se,carousel:ae,card:ie,checkbox:ce,combobox:le,collapsible:de,"context-menu":pe,dialog:ue,drawer:me,dropdown:fe,input:ge,kbd:be,label:he,"navigation-menu":ve,pagination:xe,popover:ye,progress:Ne,"radio-group":Ce,select:Re,"scroll-area":we,separator:ke,skeleton:
|
|
5343
|
+
`,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:"combobox",description:"Searchable select with filtering, single/multi selection, and keyboard navigation",dependencies:[],npmDependencies:["cmdk"]},{name:"collapsible",description:"Toggle content visibility with smooth animation and accessible controls",dependencies:[],npmDependencies:[]},{name:"context-menu",description:"Right-click context menu with submenus, keyboard shortcuts, icons, and dot notation",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:"navigation-menu",description:"Horizontal navigation menu with dropdown content panels and dot notation",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:"scroll-area",description:"Themed scrollable container with custom scrollbar styling and orientation control",dependencies:[],npmDependencies:[]},{name:"separator",description:"Visual divider with horizontal and vertical orientation",dependencies:[],npmDependencies:[]},{name:"skeleton",description:"Loading placeholder with pulse animation, sized and shaped via className",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:"stepper",description:"Multi-step progress indicator with horizontal/vertical orientation, connecting lines, and dot notation",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:"time-picker",description:"Time picker with scrollable dropdown columns and native input mode",dependencies:["popover","input"],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:"toggle",description:"Toggle button with pressed state, single and multiple selection groups",dependencies:[],npmDependencies:[]},{name:"tooltip",description:"Pure CSS tooltip with 4 position options",dependencies:[],npmDependencies:[]}],R={accordion:q,alert:J,"aspect-ratio":Z,avatar:Q,badge:ee,breadcrumb:te,button:ne,calendar:oe,"date-picker":re,command:se,carousel:ae,card:ie,checkbox:ce,combobox:le,collapsible:de,"context-menu":pe,dialog:ue,drawer:me,dropdown:fe,input:ge,kbd:be,label:he,"navigation-menu":ve,pagination:xe,popover:ye,progress:Ne,"radio-group":Ce,select:Re,"scroll-area":we,separator:ke,skeleton:Se,sidebar:Pe,slider:De,stepper:Te,switch:Ie,table:He,tabs:Ee,textarea:Le,"time-picker":Me,theme:X,toast:Oe,toggle:Ae,tooltip:Be};async function je(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 m=t.typescript?"tsx":"jsx",b=join(r,t.paths.components);for(let o of p){let s=join(b,`${o}.${m}`);if(x(s)){let P=await n.confirm({message:`${o}.${m} exists. Overwrite?`,initialValue:false});if(n.isCancel(P)||!P){n.log.warn(`Skipped ${o}`);continue}}let i=R[o];i=i.replace(/@\/utils/g,`@/${t.paths.utils.replace(/^src\//,"")}`),h(s,i),n.log.success(`${o} \u2192 ${t.paths.components}/${o}.${m}`);}if(l){let o=join(b,`theme-provider.${m}`);if(x(o)){let i=await n.confirm({message:`theme-provider.${m} exists. Overwrite?`,initialValue:false});!n.isCancel(i)&&i?(h(o,R.theme),n.log.success(`theme-provider \u2192 ${t.paths.components}/theme-provider.${m}`)):n.log.warn("Skipped theme-provider");}else h(o,R.theme),n.log.success(`theme-provider \u2192 ${t.paths.components}/theme-provider.${m}`);if(t.paths.globals){let i=join(r,t.paths.globals);if(x(i)){let P=B(i);P.includes('[data-theme="dark"]')?n.log.warn("Theme tokens already exist in globals \u2014 skipped"):(h(i,P+k),n.log.success(`Theme tokens appended to ${u.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(u.bold("Complete the setup:")),n.log.message(""),n.log.message(u.bold(`${u.cyan("1.")} Import ThemeProvider in your root layout:`)),n.log.message(u.cyan(` import { ThemeProvider } from "${s}/theme-provider"`)),n.log.message(""),n.log.message(u.bold(`${u.cyan("2.")} Add suppressHydrationWarning to <html>:`)),n.log.message(u.cyan(" <html suppressHydrationWarning>")),n.log.message(""),n.log.message(u.bold(`${u.cyan("3.")} Wrap your app with ThemeProvider:`)),n.log.message(u.cyan(" <ThemeProvider>")),n.log.message(u.cyan(" {children}")),n.log.message(u.cyan(" </ThemeProvider>")),n.log.message("");}if(p.has("calendar")&&t.paths.globals){let o=join(r,t.paths.globals);if(x(o)){let s=B(o);s.includes(".rdp-root")?n.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(h(o,s+ze),n.log.success(`Calendar tokens appended to ${u.cyan(t.paths.globals)}`));}}if(f.size){let o=E(r),s=[...f],i=n.spinner();i.start("Installing packages");try{execSync(w(o,s),{cwd:r,stdio:"ignore"}),i.stop("Packages installed");}catch{i.stop("Failed to install packages"),n.log.warn(`Run manually: ${w(o,s)}`);}}n.outro("Done.");}var z=`# Drivn Component Conventions
|
|
5121
5344
|
|
|
5122
5345
|
## Core Philosophy
|
|
5123
5346
|
- **Zero runtime UI deps** \u2014 No Radix, no cva, no external UI primitives. Pure React + Tailwind.
|
|
@@ -5230,7 +5453,7 @@ import { cn } from '@/utils/cn'
|
|
|
5230
5453
|
- Components declare internal deps (other Drivn components)
|
|
5231
5454
|
- Some components need npm packages (react-day-picker, cmdk, embla-carousel-react, sonner)
|
|
5232
5455
|
- The CLI resolves and installs all dependencies automatically
|
|
5233
|
-
`;var L={version:"1.
|
|
5456
|
+
`;var L={version:"1.15.0"};function M(e){return v.find(r=>r.name===e)}function tt(e){let r=new Set,t=a=>{if(r.has(a))return;let l=M(a);l&&(l.dependencies.forEach(d=>t(d)),r.add(a));};return t(e),r.delete(e),[...r]}async function Ve(){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=M(t);if(!a)return {content:[{type:"text",text:`Component "${t}" not found. Use list_components to see available components.`}],isError:true};let l=R[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=M(t);if(!a)return {content:[{type:"text",text:`Component "${t}" not found. Use list_components to see available components.`}],isError:true};let l=tt(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=M(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",m=l==="pnpm"?"pnpm add":"npm install",b=[];return b.push(`# Install components via CLI
|
|
5234
5457
|
${N} drivn@latest add ${[...d].join(" ")}`),p.size&&b.push(`# Install required npm dependencies
|
|
5235
5458
|
${m} ${[...p].join(" ")}`),b.push(`# Components will be installed to your configured components directory
|
|
5236
5459
|
# (default: src/components/ui/)`),{content:[{type:"text",text:JSON.stringify({componentsToInstall:[...d],npmDependencies:[...p],steps:b},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 === */
|
|
@@ -5239,4 +5462,4 @@ ${C}
|
|
|
5239
5462
|
/* === Theme Tokens === */
|
|
5240
5463
|
${k}`}]})),e.tool("get_drivn_rules","Get Drivn coding conventions and component patterns",{},async()=>({content:[{type:"text",text:z}]})),e.resource("drivn-rules","drivn://rules",{description:"Drivn coding conventions and component patterns"},async()=>({contents:[{uri:"drivn://rules",mimeType:"text/markdown",text:z}]})),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}
|
|
5241
5464
|
|
|
5242
|
-
${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:R[t.name]}]}));}let r=new StdioServerTransport;await e.connect(r);}var I=new Command;I.name("drivn").description("Drivn \u2014 Modern UI components").version(L.version);I.command("create").description("Initialize Drivn in your project").action(W);I.command("add [components...]").description("Add components to your project").action(
|
|
5465
|
+
${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:R[t.name]}]}));}let r=new StdioServerTransport;await e.connect(r);}var I=new Command;I.name("drivn").description("Drivn \u2014 Modern UI components").version(L.version);I.command("create").description("Initialize Drivn in your project").action(W);I.command("add [components...]").description("Add components to your project").action(je);I.command("mcp").description("Start the Drivn MCP server").action(Ve);I.parse();
|