drivn 1.3.1 → 1.5.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.
Files changed (2) hide show
  1. package/dist/index.js +513 -25
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {Command}from'commander';import*as e from'@clack/prompts';import i from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';var A={next:"Next.js",react:"React"};function B(t){let n=join(t,"package.json");if(!existsSync(n))throw new Error("package.json not found");let a=JSON.parse(readFileSync(n,"utf-8")),b={...a.dependencies,...a.devDependencies},p="react";b.next&&(p="next");let g=existsSync(join(t,"src")),u=existsSync(join(t,"tsconfig.json"));return {framework:p,srcDir:g,typescript:u}}var V="drivn.config.json";function _(t){let n=join(t,V);return existsSync(n)?JSON.parse(readFileSync(n,"utf-8")):null}function $(t,n){let a=join(t,V);writeFileSync(a,JSON.stringify(n,null,2));}function Pe(t){existsSync(t)||mkdirSync(t,{recursive:true});}function d(t,n){Pe(dirname(t)),writeFileSync(t,n);}function M(t){return readFileSync(t,"utf-8")}function m(t){return existsSync(t)}function P(t){return existsSync(join(t,"pnpm-lock.yaml"))?"pnpm":"npm"}function y(t,n){let a=n.join(" ");return t==="pnpm"?`pnpm add ${a}`:`npm install ${a}`}function F(t){return t==="pnpm"?"pnpm dlx":"npx"}var D=`@import "tailwindcss";
2
+ import {Command}from'commander';import*as e from'@clack/prompts';import i from'picocolors';import {join,dirname}from'path';import {execSync}from'child_process';import {existsSync,readFileSync,writeFileSync,mkdirSync}from'fs';var A={next:"Next.js",react:"React"};function B(t){let o=join(t,"package.json");if(!existsSync(o))throw new Error("package.json not found");let a=JSON.parse(readFileSync(o,"utf-8")),b={...a.dependencies,...a.devDependencies},p="react";b.next&&(p="next");let g=existsSync(join(t,"src")),u=existsSync(join(t,"tsconfig.json"));return {framework:p,srcDir:g,typescript:u}}var V="drivn.config.json";function $(t){let o=join(t,V);return existsSync(o)?JSON.parse(readFileSync(o,"utf-8")):null}function _(t,o){let a=join(t,V);writeFileSync(a,JSON.stringify(o,null,2));}function Te(t){existsSync(t)||mkdirSync(t,{recursive:true});}function d(t,o){Te(dirname(t)),writeFileSync(t,o);}function M(t){return readFileSync(t,"utf-8")}function m(t){return existsSync(t)}function P(t){return existsSync(join(t,"pnpm-lock.yaml"))?"pnpm":"npm"}function y(t,o){let a=o.join(" ");return t==="pnpm"?`pnpm add ${a}`:`npm install ${a}`}function F(t){return t==="pnpm"?"pnpm dlx":"npx"}var S=`@import "tailwindcss";
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 Ee=`import { type ClassValue, clsx } from 'clsx'
139
+ `;var Me=`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
- `,Le=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function Ie(t){for(let n of Le)if(m(join(t,n)))return n;return null}async function G(){let t=process.cwd();console.log(""),console.log(i.bgCyan(i.bold(i.black(" Drivn "))));let n;try{n=B(t),e.log.success(`Detected ${i.cyan(A[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(m(join(t,"drivn.config.json"))){let r=await e.confirm({message:"Config already exists. Overwrite?",initialValue:false});(e.isCancel(r)||!r)&&(e.cancel("Setup cancelled"),process.exit(0));}let a=n.srcDir?"src/components/ui":"components/ui",b=n.srcDir?"src/utils":"utils",p=await e.group({components:()=>e.text({message:"Where should components be installed?",placeholder:a,defaultValue:a}),utils:()=>e.text({message:"Where should utilities be placed?",placeholder:b,defaultValue:b})},{onCancel:()=>{e.cancel("Setup cancelled"),process.exit(0);}}),g={framework:n.framework,typescript:n.typescript,paths:{components:p.components,utils:p.utils},installed:[]},u=n.typescript?"ts":"js",v=join(t,p.utils,`cn.${u}`);m(v)||d(v,Ee);let h=Ie(t);if(h){let r=await e.confirm({message:`Found ${i.cyan(h)}. Add Drivn color tokens?`,initialValue:true});!e.isCancel(r)&&r&&(d(join(t,h),D),g.paths.globals=h,e.log.success(`Color tokens written to ${i.cyan(h)}`));}else {let r=n.srcDir?"src/styles/globals.css":"styles/globals.css",c=await e.text({message:"Where should the globals CSS file be created?",placeholder:r,defaultValue:r});e.isCancel(c)||(d(join(t,c),D),g.paths.globals=c,e.log.success(`Color tokens written to ${i.cyan(c)}`));}$(t,g);let x=P(t),l=F(x),N=["clsx","tailwind-merge","lucide-react"],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 K=`'use client'
145
+ `,Oe=["src/app/globals.css","src/styles/globals.css","src/styles/globals.scss","app/globals.css"];function Ae(t){for(let o of Oe)if(m(join(t,o)))return o;return null}async function G(){let t=process.cwd();console.log(""),console.log(i.bgCyan(i.bold(i.black(" Drivn "))));let o;try{o=B(t),e.log.success(`Detected ${i.cyan(A[o.framework])}`);}catch{e.log.error("No package.json found. Run this command in a project directory."),e.outro("Setup cancelled"),process.exit(1);}if(m(join(t,"drivn.config.json"))){let r=await e.confirm({message:"Config already exists. Overwrite?",initialValue:false});(e.isCancel(r)||!r)&&(e.cancel("Setup cancelled"),process.exit(0));}let a=o.srcDir?"src/components/ui":"components/ui",b=o.srcDir?"src/utils":"utils",p=await e.group({components:()=>e.text({message:"Where should components be installed?",placeholder:a,defaultValue:a}),utils:()=>e.text({message:"Where should utilities be placed?",placeholder:b,defaultValue:b})},{onCancel:()=>{e.cancel("Setup cancelled"),process.exit(0);}}),g={framework:o.framework,typescript:o.typescript,paths:{components:p.components,utils:p.utils},installed:[]},u=o.typescript?"ts":"js",v=join(t,p.utils,`cn.${u}`);m(v)||d(v,Me);let h=Ae(t);if(h){let r=await e.confirm({message:`Found ${i.cyan(h)}. Add Drivn color tokens?`,initialValue:true});!e.isCancel(r)&&r&&(d(join(t,h),S),g.paths.globals=h,e.log.success(`Color tokens written to ${i.cyan(h)}`));}else {let r=o.srcDir?"src/styles/globals.css":"styles/globals.css",c=await e.text({message:"Where should the globals CSS file be created?",placeholder:r,defaultValue:r});e.isCancel(c)||(d(join(t,c),S),g.paths.globals=c,e.log.success(`Color tokens written to ${i.cyan(c)}`));}_(t,g);let x=P(t),l=F(x),N=["clsx","tailwind-merge","lucide-react"],n=e.spinner();n.start("Installing dependencies");try{execSync(y(x,N),{cwd:t,stdio:"ignore"}),n.stop("Dependencies installed");}catch{n.stop("Failed to install dependencies"),e.log.warn(`Run manually: ${y(x,N)}`);}e.log.info(`Add components with: ${i.cyan(`${l} drivn add button`)}`),e.log.info(`Add dark/light theme: ${i.cyan(`${l} drivn add theme`)}`),e.outro("Drivn initialized");}var K=`'use client'
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 Y=`'use client'
164
+ `;var U=`'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 W=`import * as React from 'react'
296
+ `;var Y=`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 U=`import * as React from 'react'
344
+ `;var W=`import * as React from 'react'
345
345
  import { cn } from '@/utils/cn'
346
346
 
347
347
  const styles = {
@@ -1491,19 +1491,19 @@ export const Carousel = Object.assign(CarouselRoot, {
1491
1491
  Next,
1492
1492
  Dots
1493
1493
  })
1494
- `;var oe=`import * as React from 'react'
1494
+ `;var ne=`import * as React from 'react'
1495
1495
  import { cn } from '@/utils/cn'
1496
1496
 
1497
1497
  const styles = {
1498
1498
  base: cn(
1499
+ 'w-48 aspect-square flex flex-col',
1499
1500
  'bg-card border border-border rounded-[20px]',
1500
1501
  'overflow-hidden transition-all duration-200'
1501
1502
  ),
1502
1503
  hover: 'hover:bg-accent hover:border-border hover:-translate-y-1',
1503
1504
  preview: cn(
1504
- 'h-[140px] flex items-center justify-center',
1505
- 'border-b border-border p-6',
1506
- 'bg-[radial-gradient(ellipse_at_50%_50%,hsl(239_84%_67%_/_0.08)_0%,transparent_70%)]'
1505
+ 'flex-1 flex items-center justify-center',
1506
+ 'border-b border-border p-6'
1507
1507
  ),
1508
1508
  info: 'p-5 flex justify-between items-center',
1509
1509
  }
@@ -1558,7 +1558,7 @@ export const Card = Object.assign(CardRoot, {
1558
1558
  Preview,
1559
1559
  Info
1560
1560
  })
1561
- `;var ne=`'use client'
1561
+ `;var oe=`'use client'
1562
1562
 
1563
1563
  import * as React from 'react'
1564
1564
  import { Check } from 'lucide-react'
@@ -2004,6 +2004,63 @@ Input.displayName = 'Input'
2004
2004
  `;var ce=`import * as React from 'react'
2005
2005
  import { cn } from '@/utils/cn'
2006
2006
 
2007
+ const styles = {
2008
+ base: cn(
2009
+ 'pointer-events-none inline-flex items-center',
2010
+ 'justify-center select-none',
2011
+ 'h-5 w-fit min-w-5 gap-1 rounded-sm px-1',
2012
+ 'font-mono text-xs font-medium',
2013
+ '[&_svg:not([class*=size-])]:size-3'
2014
+ ),
2015
+ variants: {
2016
+ default: 'bg-muted text-muted-foreground',
2017
+ outline: 'border border-border text-muted-foreground',
2018
+ },
2019
+ group: 'inline-flex items-center gap-1',
2020
+ }
2021
+
2022
+ interface KbdProps {
2023
+ variant?: keyof typeof styles.variants
2024
+ className?: string
2025
+ children: React.ReactNode
2026
+ }
2027
+
2028
+ function KbdRoot({
2029
+ variant = 'default',
2030
+ className,
2031
+ children,
2032
+ }: KbdProps) {
2033
+ return (
2034
+ <kbd
2035
+ className={cn(
2036
+ styles.base,
2037
+ styles.variants[variant],
2038
+ className,
2039
+ )}
2040
+ >
2041
+ {children}
2042
+ </kbd>
2043
+ )
2044
+ }
2045
+
2046
+ function Group({
2047
+ className,
2048
+ children,
2049
+ }: {
2050
+ className?: string
2051
+ children: React.ReactNode
2052
+ }) {
2053
+ return (
2054
+ <kbd className={cn(styles.group, className)}>
2055
+ {children}
2056
+ </kbd>
2057
+ )
2058
+ }
2059
+
2060
+ export const Kbd = Object.assign(KbdRoot, { Group })
2061
+ `;var ie=`import * as React from 'react'
2062
+ import { cn } from '@/utils/cn'
2063
+
2007
2064
  export function Label({
2008
2065
  className,
2009
2066
  ...props
@@ -2018,7 +2075,7 @@ export function Label({
2018
2075
  />
2019
2076
  )
2020
2077
  }
2021
- `;var ie=`import * as React from 'react'
2078
+ `;var le=`import * as React from 'react'
2022
2079
  import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react'
2023
2080
  import { cn } from '@/utils/cn'
2024
2081
 
@@ -2151,7 +2208,7 @@ export const Pagination = Object.assign(PaginationRoot, {
2151
2208
  Next,
2152
2209
  Ellipsis: PaginationEllipsis,
2153
2210
  })
2154
- `;var le=`'use client'
2211
+ `;var de=`'use client'
2155
2212
 
2156
2213
  import * as React from 'react'
2157
2214
  import { cn } from '@/utils/cn'
@@ -2256,7 +2313,7 @@ export const Popover = Object.assign(PopoverRoot, {
2256
2313
  Trigger,
2257
2314
  Content
2258
2315
  })
2259
- `;var de=`import * as React from 'react'
2316
+ `;var pe=`import * as React from 'react'
2260
2317
  import { cn } from '@/utils/cn'
2261
2318
 
2262
2319
  const styles = {
@@ -2294,7 +2351,7 @@ export function Progress({
2294
2351
  </div>
2295
2352
  )
2296
2353
  }
2297
- `;var pe=`'use client'
2354
+ `;var ue=`'use client'
2298
2355
 
2299
2356
  import * as React from 'react'
2300
2357
  import { cn } from '@/utils/cn'
@@ -2443,7 +2500,7 @@ function useRadioGroup() {
2443
2500
  }
2444
2501
 
2445
2502
  export const RadioGroup = Object.assign(RadioGroupRoot, { Item })
2446
- `;var ue=`'use client'
2503
+ `;var me=`'use client'
2447
2504
 
2448
2505
  import * as React from 'react'
2449
2506
  import { ChevronDown } from 'lucide-react'
@@ -2597,7 +2654,7 @@ export const Select = Object.assign(SelectRoot, {
2597
2654
  Menu,
2598
2655
  Option
2599
2656
  })
2600
- `;var me=`import * as React from 'react'
2657
+ `;var fe=`import * as React from 'react'
2601
2658
  import { cn } from '@/utils/cn'
2602
2659
 
2603
2660
  const styles = {
@@ -2621,7 +2678,438 @@ export function Separator({
2621
2678
  />
2622
2679
  )
2623
2680
  }
2624
- `;var fe=`'use client'
2681
+ `;var ge=`'use client'
2682
+
2683
+ import * as React from 'react'
2684
+ import { ChevronDown, PanelLeft } from 'lucide-react'
2685
+ import { cn } from '@/utils/cn'
2686
+
2687
+ const styles = {
2688
+ base: cn(
2689
+ 'flex flex-col h-full bg-card border-border overflow-hidden',
2690
+ 'transition-[width] duration-200 ease-in-out'
2691
+ ),
2692
+ variants: {
2693
+ default: 'border-r',
2694
+ floating: cn(
2695
+ 'border rounded-xl shadow-lg m-2',
2696
+ 'h-[calc(100%-16px)]'
2697
+ ),
2698
+ },
2699
+ width: {
2700
+ expanded: 'w-[240px]',
2701
+ collapsed: 'w-[60px]',
2702
+ },
2703
+ header: cn(
2704
+ 'flex items-center gap-2 px-3 py-3',
2705
+ 'border-b border-border shrink-0'
2706
+ ),
2707
+ content: 'flex-1 overflow-y-auto px-2 py-2 flex flex-col gap-1',
2708
+ footer: cn(
2709
+ 'flex items-center mt-auto px-3 py-3',
2710
+ 'border-t border-border shrink-0'
2711
+ ),
2712
+ group: 'py-2',
2713
+ groupHeading: cn(
2714
+ 'flex items-center justify-between w-full',
2715
+ 'px-2 py-1.5 text-xs font-medium text-muted-foreground',
2716
+ 'hover:text-foreground/80 transition-colors cursor-pointer'
2717
+ ),
2718
+ groupIcon: cn(
2719
+ 'w-3 h-3 text-muted-foreground/60',
2720
+ 'transition-transform duration-200'
2721
+ ),
2722
+ groupPanel: 'grid transition-[grid-template-rows] duration-200',
2723
+ groupContent: 'overflow-hidden flex flex-col gap-1',
2724
+ item: cn(
2725
+ 'flex items-center gap-3 w-full px-2 py-2',
2726
+ 'text-sm text-muted-foreground rounded-lg',
2727
+ 'hover:bg-accent hover:text-foreground',
2728
+ 'transition-colors cursor-pointer'
2729
+ ),
2730
+ itemActive: 'bg-accent text-foreground font-medium',
2731
+ itemIcon: 'w-4 h-4 shrink-0',
2732
+ itemBadge: cn(
2733
+ 'ml-auto text-xs font-medium px-1.5 py-0.5',
2734
+ 'rounded-md bg-primary/10 text-primary'
2735
+ ),
2736
+ separator: 'mx-2 my-2 h-px border-0 bg-muted',
2737
+ collapseBtn: cn(
2738
+ 'flex items-center justify-center',
2739
+ 'w-7 h-7 rounded-md ml-auto shrink-0',
2740
+ 'text-muted-foreground hover:text-foreground',
2741
+ 'hover:bg-accent transition-colors cursor-pointer'
2742
+ ),
2743
+ }
2744
+
2745
+ type Variant = keyof typeof styles.variants
2746
+ type Side = 'left' | 'right'
2747
+ type IconProp = React.ComponentType<{ className?: string }> | React.ReactElement
2748
+
2749
+ interface SidebarCtx {
2750
+ collapsed: boolean
2751
+ setCollapsed: (v: boolean) => void
2752
+ variant: Variant
2753
+ side: Side
2754
+ }
2755
+
2756
+ function SidebarRoot({
2757
+ children,
2758
+ defaultCollapsed = false,
2759
+ collapsed: controlled,
2760
+ onCollapsedChange,
2761
+ variant = 'default',
2762
+ side = 'left',
2763
+ className,
2764
+ }: {
2765
+ children: React.ReactNode
2766
+ defaultCollapsed?: boolean
2767
+ collapsed?: boolean
2768
+ onCollapsedChange?: (collapsed: boolean) => void
2769
+ variant?: Variant
2770
+ side?: Side
2771
+ className?: string
2772
+ }) {
2773
+ const [uncontrolled, setUncontrolled] = React.useState(defaultCollapsed)
2774
+ const collapsed = controlled ?? uncontrolled
2775
+ const setCollapsed = React.useCallback(
2776
+ (v: boolean) => {
2777
+ onCollapsedChange?.(v)
2778
+ if (controlled === undefined) setUncontrolled(v)
2779
+ },
2780
+ [controlled, onCollapsedChange]
2781
+ )
2782
+
2783
+ return (
2784
+ <Ctx.Provider value={{ collapsed, setCollapsed, variant, side }}>
2785
+ <aside
2786
+ className={cn(styles.base, styles.variants[variant], collapsed ? styles.width.collapsed : styles.width.expanded, className)}
2787
+ >
2788
+ {children}
2789
+ </aside>
2790
+ </Ctx.Provider>
2791
+ )
2792
+ }
2793
+
2794
+ function Header({
2795
+ children,
2796
+ className,
2797
+ }: {
2798
+ children: React.ReactNode
2799
+ className?: string
2800
+ }) {
2801
+ const { collapsed } = useSidebar()
2802
+ return (
2803
+ <div className={cn(styles.header, collapsed && 'justify-center px-2 gap-0', className)}>
2804
+ {children}
2805
+ </div>
2806
+ )
2807
+ }
2808
+
2809
+ function CollapseButton({
2810
+ className,
2811
+ }: {
2812
+ className?: string
2813
+ }) {
2814
+ const { collapsed, setCollapsed } = useSidebar()
2815
+ return (
2816
+ <button
2817
+ aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
2818
+ className={cn(styles.collapseBtn, collapsed && 'ml-0', className)}
2819
+ onClick={() => setCollapsed(!collapsed)}
2820
+ >
2821
+ <PanelLeft className={cn('w-4 h-4 transition-transform duration-200', collapsed && 'rotate-180')} />
2822
+ </button>
2823
+ )
2824
+ }
2825
+
2826
+ function SidebarContent({
2827
+ children,
2828
+ className,
2829
+ }: {
2830
+ children: React.ReactNode
2831
+ className?: string
2832
+ }) {
2833
+ return (
2834
+ <div className={cn(styles.content, className)}>
2835
+ {children}
2836
+ </div>
2837
+ )
2838
+ }
2839
+
2840
+ function Footer({
2841
+ children,
2842
+ className,
2843
+ }: {
2844
+ children: React.ReactNode
2845
+ className?: string
2846
+ }) {
2847
+ const { collapsed } = useSidebar()
2848
+ return (
2849
+ <div className={cn(styles.footer, collapsed && 'px-2 justify-center overflow-hidden', className)}>
2850
+ {children}
2851
+ </div>
2852
+ )
2853
+ }
2854
+
2855
+ function Group({
2856
+ children,
2857
+ heading,
2858
+ defaultOpen = true,
2859
+ collapsible = true,
2860
+ className,
2861
+ }: {
2862
+ children: React.ReactNode
2863
+ heading?: string
2864
+ defaultOpen?: boolean
2865
+ collapsible?: boolean
2866
+ className?: string
2867
+ }) {
2868
+ const [open, setOpen] = React.useState(defaultOpen)
2869
+ const { collapsed } = useSidebar()
2870
+
2871
+ return (
2872
+ <div className={cn(styles.group, className)}>
2873
+ {heading && !collapsed && (
2874
+ collapsible ? (
2875
+ <button
2876
+ className={styles.groupHeading}
2877
+ onClick={() => setOpen(!open)}
2878
+ >
2879
+ {heading}
2880
+ <ChevronDown className={cn(styles.groupIcon, open && 'rotate-180')} />
2881
+ </button>
2882
+ ) : (
2883
+ <span className={styles.groupHeading}>
2884
+ {heading}
2885
+ </span>
2886
+ )
2887
+ )}
2888
+ <div
2889
+ className={styles.groupPanel}
2890
+ style={{ gridTemplateRows: !heading || open || collapsed ? '1fr' : '0fr' }}
2891
+ >
2892
+ <div className={styles.groupContent}>
2893
+ {children}
2894
+ </div>
2895
+ </div>
2896
+ </div>
2897
+ )
2898
+ }
2899
+
2900
+ function Item({
2901
+ children,
2902
+ icon: Icon,
2903
+ active,
2904
+ badge,
2905
+ className,
2906
+ ...props
2907
+ }: {
2908
+ children: React.ReactNode
2909
+ icon?: IconProp
2910
+ active?: boolean
2911
+ badge?: string | number
2912
+ className?: string
2913
+ } & React.ButtonHTMLAttributes<HTMLButtonElement>) {
2914
+ const { collapsed } = useSidebar()
2915
+ return (
2916
+ <button
2917
+ className={cn(styles.item, active && styles.itemActive, collapsed && 'justify-center px-0', className)}
2918
+ title={collapsed ? String(children) : undefined}
2919
+ {...props}
2920
+ >
2921
+ {Icon && (
2922
+ React.isValidElement(Icon)
2923
+ ? Icon
2924
+ : <Icon className={styles.itemIcon} />
2925
+ )}
2926
+ {!collapsed && (
2927
+ <>
2928
+ <span className="truncate">{children}</span>
2929
+ {badge !== undefined && (
2930
+ <span className={styles.itemBadge}>
2931
+ {badge}
2932
+ </span>
2933
+ )}
2934
+ </>
2935
+ )}
2936
+ </button>
2937
+ )
2938
+ }
2939
+
2940
+ function SidebarSeparator({
2941
+ className,
2942
+ }: {
2943
+ className?: string
2944
+ }) {
2945
+ return <hr className={cn(styles.separator, className)} />
2946
+ }
2947
+
2948
+ const Ctx = React.createContext<SidebarCtx | null>(null)
2949
+
2950
+ function useSidebar() {
2951
+ const ctx = React.useContext(Ctx)
2952
+ if (!ctx) throw new Error('Sidebar compound used outside <Sidebar>')
2953
+ return ctx
2954
+ }
2955
+
2956
+ export { useSidebar }
2957
+
2958
+ export const Sidebar = Object.assign(SidebarRoot, {
2959
+ Header,
2960
+ Content: SidebarContent,
2961
+ Footer,
2962
+ Group,
2963
+ Item,
2964
+ Separator: SidebarSeparator,
2965
+ CollapseButton,
2966
+ })
2967
+ `;var he=`'use client'
2968
+
2969
+ import * as React from 'react'
2970
+ import { cn } from '@/utils/cn'
2971
+
2972
+ const styles = {
2973
+ base: 'relative cursor-pointer touch-none select-none',
2974
+ track: 'relative bg-border rounded-full',
2975
+ range: 'absolute bg-foreground rounded-full',
2976
+ thumb: cn(
2977
+ 'absolute rounded-full bg-foreground shadow-sm',
2978
+ 'cursor-grab active:cursor-grabbing'
2979
+ ),
2980
+ horizontal: {
2981
+ base: 'w-full',
2982
+ track: 'w-full',
2983
+ range: 'inset-y-0 left-0',
2984
+ thumb: 'top-1/2 -translate-x-1/2 -translate-y-1/2',
2985
+ },
2986
+ vertical: {
2987
+ base: 'h-48',
2988
+ track: 'h-full',
2989
+ range: 'inset-x-0 bottom-0',
2990
+ thumb: 'left-1/2 -translate-x-1/2 translate-y-1/2',
2991
+ },
2992
+ sizes: {
2993
+ sm: { track: 'h-1', thumb: 'w-3 h-3', vTrack: 'w-1' },
2994
+ md: { track: 'h-1.5', thumb: 'w-4 h-4', vTrack: 'w-1.5' },
2995
+ lg: { track: 'h-2', thumb: 'w-5 h-5', vTrack: 'w-2' },
2996
+ },
2997
+ disabled: 'opacity-50 cursor-default pointer-events-none',
2998
+ }
2999
+
3000
+ interface SliderProps extends Omit<
3001
+ React.HTMLAttributes<HTMLDivElement>,
3002
+ 'onChange' | 'defaultValue'
3003
+ > {
3004
+ value?: number
3005
+ defaultValue?: number
3006
+ min?: number
3007
+ max?: number
3008
+ step?: number
3009
+ orientation?: 'horizontal' | 'vertical'
3010
+ onChange?: (value: number) => void
3011
+ disabled?: boolean
3012
+ size?: keyof typeof styles.sizes
3013
+ name?: string
3014
+ }
3015
+
3016
+ function snap(val: number, min: number, step: number) {
3017
+ return Math.round((val - min) / step) * step + min
3018
+ }
3019
+
3020
+ export const Slider = React.forwardRef<HTMLInputElement, SliderProps>(({
3021
+ value,
3022
+ defaultValue = 0,
3023
+ min = 0,
3024
+ max = 100,
3025
+ step = 1,
3026
+ orientation = 'horizontal',
3027
+ onChange,
3028
+ disabled,
3029
+ size = 'md',
3030
+ name,
3031
+ className,
3032
+ ...props
3033
+ }, ref) => {
3034
+ const [internal, setInternal] = React.useState(defaultValue)
3035
+ const isControlled = value !== undefined
3036
+ const current = isControlled ? value : internal
3037
+ const trackRef = React.useRef<HTMLDivElement>(null)
3038
+
3039
+ const isH = orientation === 'horizontal'
3040
+ const s = styles.sizes[size]
3041
+ const dir = isH ? styles.horizontal : styles.vertical
3042
+ const pct = (Math.min(Math.max(current, min), max) - min) / (max - min) * 100
3043
+
3044
+ function resolve(x: number, y: number) {
3045
+ const el = trackRef.current
3046
+ if (!el) return
3047
+ const r = el.getBoundingClientRect()
3048
+ const ratio = isH
3049
+ ? (x - r.left) / r.width
3050
+ : 1 - (y - r.top) / r.height
3051
+ const raw = min + ratio * (max - min)
3052
+ const clamped = Math.min(Math.max(snap(raw, min, step), min), max)
3053
+ if (!isControlled) setInternal(clamped)
3054
+ onChange?.(clamped)
3055
+ }
3056
+
3057
+ function handlePointerDown(e: React.PointerEvent) {
3058
+ if (disabled) return
3059
+ e.preventDefault()
3060
+ resolve(e.clientX, e.clientY)
3061
+ const onMove = (ev: PointerEvent) =>
3062
+ resolve(ev.clientX, ev.clientY)
3063
+ const onUp = () => {
3064
+ document.removeEventListener('pointermove', onMove)
3065
+ document.removeEventListener('pointerup', onUp)
3066
+ }
3067
+ document.addEventListener('pointermove', onMove)
3068
+ document.addEventListener('pointerup', onUp)
3069
+ }
3070
+
3071
+ return (
3072
+ <div
3073
+ className={cn(styles.base, dir.base, disabled && styles.disabled, className)}
3074
+ {...props}
3075
+ >
3076
+ <div
3077
+ ref={trackRef}
3078
+ className={cn(styles.track, dir.track, isH ? s.track : s.vTrack)}
3079
+ onPointerDown={handlePointerDown}
3080
+ >
3081
+ <div
3082
+ className={cn(styles.range, dir.range)}
3083
+ style={isH ? { width: \`\${pct}%\` } : { height: \`\${pct}%\` }}
3084
+ />
3085
+ <div
3086
+ role="slider"
3087
+ aria-valuenow={current}
3088
+ aria-valuemin={min}
3089
+ aria-valuemax={max}
3090
+ className={cn(styles.thumb, dir.thumb, s.thumb)}
3091
+ style={isH ? { left: \`\${pct}%\` } : { bottom: \`\${pct}%\` }}
3092
+ />
3093
+ </div>
3094
+ <input
3095
+ ref={ref}
3096
+ type="range"
3097
+ name={name}
3098
+ value={current}
3099
+ min={min}
3100
+ max={max}
3101
+ step={step}
3102
+ className="sr-only"
3103
+ tabIndex={-1}
3104
+ readOnly
3105
+ />
3106
+ </div>
3107
+ )
3108
+ }
3109
+ )
3110
+
3111
+ Slider.displayName = 'Slider'
3112
+ `;var be=`'use client'
2625
3113
 
2626
3114
  import * as React from 'react'
2627
3115
  import { cn } from '@/utils/cn'
@@ -2662,7 +3150,7 @@ export function Switch({
2662
3150
  </button>
2663
3151
  )
2664
3152
  }
2665
- `;var ge=`'use client'
3153
+ `;var ve=`'use client'
2666
3154
 
2667
3155
  import * as React from 'react'
2668
3156
  import { cn } from '@/utils/cn'
@@ -2776,7 +3264,7 @@ export const Tabs = Object.assign(TabsRoot, {
2776
3264
  Tab,
2777
3265
  Panel
2778
3266
  })
2779
- `;var he=`import * as React from 'react'
3267
+ `;var xe=`import * as React from 'react'
2780
3268
  import { cn } from '@/utils/cn'
2781
3269
 
2782
3270
  const styles = {
@@ -2803,7 +3291,7 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({
2803
3291
  ))
2804
3292
 
2805
3293
  Textarea.displayName = 'Textarea'
2806
- `;var be=`'use client'
3294
+ `;var ye=`'use client'
2807
3295
 
2808
3296
  import * as React from 'react'
2809
3297
  import { Toaster as Sonner, toast } from 'sonner'
@@ -2846,7 +3334,7 @@ function Toaster() {
2846
3334
  }
2847
3335
 
2848
3336
  export { Toaster, toast }
2849
- `;var ve=`import * as React from 'react'
3337
+ `;var Ne=`import * as React from 'react'
2850
3338
  import { cn } from '@/utils/cn'
2851
3339
 
2852
3340
  const styles = {
@@ -3020,7 +3508,7 @@ export const Table = Object.assign(TableRoot, {
3020
3508
  Head,
3021
3509
  Cell,
3022
3510
  })
3023
- `;var xe=`import * as React from 'react'
3511
+ `;var Ce=`import * as React from 'react'
3024
3512
  import { cn } from '@/utils/cn'
3025
3513
 
3026
3514
  const styles = {
@@ -3065,7 +3553,7 @@ export function Tooltip({
3065
3553
  </span>
3066
3554
  )
3067
3555
  }
3068
- `;var ye=`
3556
+ `;var Re=`
3069
3557
  /* react-day-picker theme integration */
3070
3558
  .rdp-root {
3071
3559
  --rdp-accent-color: var(--primary);
@@ -3076,4 +3564,4 @@ export function Tooltip({
3076
3564
  --rdp-selected-border: none;
3077
3565
  --rdp-day_button-border: none;
3078
3566
  }
3079
- `,w=[{name:"accordion",description:"Collapsible content sections with dot notation and smooth animation",dependencies:[],npmDependencies:[]},{name:"alert",description:"Contextual feedback messages with variants and icons",dependencies:[],npmDependencies:[]},{name:"avatar",description:"User avatar with image support and fallback initials",dependencies:[],npmDependencies:[]},{name:"badge",description:"Small status indicator with color variants",dependencies:[],npmDependencies:[]},{name:"breadcrumb",description:"Breadcrumb navigation with auto-separators, ellipsis, and dot notation",dependencies:[],npmDependencies:[]},{name:"button",description:"Button with variants, sizes, loading state, and icon slots",dependencies:[],npmDependencies:[]},{name:"calendar",description:"Date picker powered by react-day-picker with single, range, and dropdown modes",dependencies:[],npmDependencies:["react-day-picker"]},{name:"date-picker",description:"Date picker input with Calendar dropdown for single date and range selection",dependencies:["calendar"],npmDependencies:[]},{name:"command",description:"Searchable command menu with filtering, keyboard navigation, and dialog mode",dependencies:["dialog"],npmDependencies:["cmdk"]},{name:"carousel",description:"Carousel with touch/swipe, navigation arrows, dot indicators, and loop mode",dependencies:["button"],npmDependencies:["embla-carousel-react"]},{name:"card",description:"Container with dot notation preview and info sub-components",dependencies:[],npmDependencies:[]},{name:"checkbox",description:"Checkbox input with label and CSS-only checkmark",dependencies:[],npmDependencies:[]},{name:"dialog",description:"Modal dialog with dot notation, overlay, and escape key",dependencies:["button"],npmDependencies:[]},{name:"dropdown",description:"Dropdown menu with dot notation, groups, separators, and click-outside",dependencies:["button"],npmDependencies:[]},{name:"input",description:"Text input with focus ring and disabled state",dependencies:[],npmDependencies:[]},{name:"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:"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:[]}],S={accordion:Y,alert:W,avatar:U,badge:q,breadcrumb:X,button:J,calendar:Q,"date-picker":Z,command:ee,carousel:te,card:oe,checkbox:ne,dialog:re,dropdown:se,input:ae,label:ce,pagination:ie,popover:le,progress:de,"radio-group":pe,select:ue,separator:me,switch:fe,table:ve,tabs:ge,textarea:he,theme:K,toast:be,tooltip:xe};async function Ne(t){let n=process.cwd();e.intro("drivn add");let a=_(n);if(a||(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:w.map(r=>({label:r.name,hint:r.description,value:r.name})),required:true});e.isCancel(o)&&(e.cancel("Cancelled"),process.exit(0)),t=o;}let b=t.filter(o=>!w.find(r=>r.name===o));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+w.map(o=>o.name).join(", ")),e.outro("Cancelled"),process.exit(1));let p=t.includes("theme"),g=t.filter(o=>o!=="theme"),u=new Set,v=new Set,h=o=>{if(u.has(o))return;let r=w.find(c=>c.name===o);r&&(r.dependencies.forEach(c=>h(c)),r.npmDependencies?.forEach(c=>v.add(c)),u.add(o));};g.forEach(h),p&&v.add("next-themes");let x=[...u].filter(o=>!g.includes(o));x.length&&e.log.info(`Required dependency: ${x.join(", ")}`);let l=a.typescript?"tsx":"jsx",N=join(n,a.paths.components);for(let o of u){let r=join(N,`${o}.${l}`);if(m(r)){let C=await e.confirm({message:`${o}.${l} exists. Overwrite?`,initialValue:false});if(e.isCancel(C)||!C){e.log.warn(`Skipped ${o}`);continue}}let c=S[o];c=c.replace(/@\/utils/g,`@/${a.paths.utils.replace(/^src\//,"")}`),d(r,c),e.log.success(`${o} \u2192 ${a.paths.components}/${o}.${l}`);}if(p){let o=join(N,`theme-provider.${l}`);if(m(o)){let c=await e.confirm({message:`theme-provider.${l} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(d(o,S.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else d(o,S.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`);if(a.paths.globals){let c=join(n,a.paths.globals);if(m(c)){let C=M(c);C.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(d(c,C+O),e.log.success(`Theme tokens appended to ${i.cyan(a.paths.globals)}`));}else e.log.warn(`Globals file not found at ${a.paths.globals}`);}else e.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let r=a.paths.components.replace(/^src\//,"@/");e.log.message(""),e.log.info(i.bold("Complete the setup:")),e.log.message(""),e.log.message(i.bold(`${i.cyan("1.")} Import ThemeProvider in your root layout:`)),e.log.message(i.cyan(` import { ThemeProvider } from "${r}/theme-provider"`)),e.log.message(""),e.log.message(i.bold(`${i.cyan("2.")} Add suppressHydrationWarning to <html>:`)),e.log.message(i.cyan(" <html suppressHydrationWarning>")),e.log.message(""),e.log.message(i.bold(`${i.cyan("3.")} Wrap your app with ThemeProvider:`)),e.log.message(i.cyan(" <ThemeProvider>")),e.log.message(i.cyan(" {children}")),e.log.message(i.cyan(" </ThemeProvider>")),e.log.message("");}if(u.has("calendar")&&a.paths.globals){let o=join(n,a.paths.globals);if(m(o)){let r=M(o);r.includes(".rdp-root")?e.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(d(o,r+ye),e.log.success(`Calendar tokens appended to ${i.cyan(a.paths.globals)}`));}}if(v.size){let o=P(n),r=[...v],c=e.spinner();c.start("Installing packages");try{execSync(y(o,r),{cwd:n,stdio:"ignore"}),c.stop("Packages installed");}catch{c.stop("Failed to install packages"),e.log.warn(`Run manually: ${y(o,r)}`);}}e.outro("Done.");}var Ce={version:"1.3.1"};var T=new Command;T.name("drivn").description("Drivn \u2014 Modern UI components").version(Ce.version);T.command("create").description("Initialize Drivn in your project").action(G);T.command("add [components...]").description("Add components to your project").action(Ne);T.parse();
3567
+ `,w=[{name:"accordion",description:"Collapsible content sections with dot notation and smooth animation",dependencies:[],npmDependencies:[]},{name:"alert",description:"Contextual feedback messages with variants and icons",dependencies:[],npmDependencies:[]},{name:"avatar",description:"User avatar with image support and fallback initials",dependencies:[],npmDependencies:[]},{name:"badge",description:"Small status indicator with color variants",dependencies:[],npmDependencies:[]},{name:"breadcrumb",description:"Breadcrumb navigation with auto-separators, ellipsis, and dot notation",dependencies:[],npmDependencies:[]},{name:"button",description:"Button with variants, sizes, loading state, and icon slots",dependencies:[],npmDependencies:[]},{name:"calendar",description:"Date picker powered by react-day-picker with single, range, and dropdown modes",dependencies:[],npmDependencies:["react-day-picker"]},{name:"date-picker",description:"Date picker input with Calendar dropdown for single date and range selection",dependencies:["calendar"],npmDependencies:[]},{name:"command",description:"Searchable command menu with filtering, keyboard navigation, and dialog mode",dependencies:["dialog"],npmDependencies:["cmdk"]},{name:"carousel",description:"Carousel with touch/swipe, navigation arrows, dot indicators, and loop mode",dependencies:["button"],npmDependencies:["embla-carousel-react"]},{name:"card",description:"Container with dot notation preview and info sub-components",dependencies:[],npmDependencies:[]},{name:"checkbox",description:"Checkbox input with label and CSS-only checkmark",dependencies:[],npmDependencies:[]},{name:"dialog",description:"Modal dialog with dot notation, overlay, and escape key",dependencies:["button"],npmDependencies:[]},{name:"dropdown",description:"Dropdown menu with dot notation, groups, separators, and click-outside",dependencies:["button"],npmDependencies:[]},{name:"input",description:"Text input with focus ring and disabled state",dependencies:[],npmDependencies:[]},{name:"kbd",description:"Keyboard key display for shortcuts and hotkeys",dependencies:[],npmDependencies:[]},{name:"label",description:"Accessible form label for inputs, checkboxes, and selects",dependencies:[],npmDependencies:[]},{name:"pagination",description:"Page navigation with dot notation, Previous/Next, ellipsis, and active state",dependencies:[],npmDependencies:[]},{name:"popover",description:"Floating content panel with dot notation and click-outside",dependencies:["button"],npmDependencies:[]},{name:"progress",description:"Progress bar with animated fill and ARIA attributes",dependencies:[],npmDependencies:[]},{name:"radio-group",description:"Radio group with dot notation, orientation support, and controlled/uncontrolled selection",dependencies:[],npmDependencies:[]},{name:"select",description:"Custom select with dot notation and composable options",dependencies:[],npmDependencies:[]},{name:"separator",description:"Visual divider with horizontal and vertical orientation",dependencies:[],npmDependencies:[]},{name:"sidebar",description:"Collapsible sidebar with dot notation, icon items, groups, and layout variants",dependencies:[],npmDependencies:[]},{name:"slider",description:"Range slider with pointer drag, step snapping, and size variants",dependencies:[],npmDependencies:[]},{name:"switch",description:"Toggle switch with smooth transition",dependencies:[],npmDependencies:[]},{name:"tabs",description:"Tab navigation with dot notation and panel content",dependencies:[],npmDependencies:[]},{name:"table",description:"Data table with dot notation, striped/bordered variants, and responsive overflow",dependencies:[],npmDependencies:[]},{name:"textarea",description:"Multi-line text input with consistent styling",dependencies:[],npmDependencies:[]},{name:"theme",description:"Dark/light theme support with next-themes and ThemeProvider",dependencies:[],npmDependencies:["next-themes"]},{name:"toast",description:"Toast notifications powered by Sonner",dependencies:[],npmDependencies:["sonner"]},{name:"tooltip",description:"Pure CSS tooltip with 4 position options",dependencies:[],npmDependencies:[]}],D={accordion:U,alert:Y,avatar:W,badge:q,breadcrumb:X,button:J,calendar:Q,"date-picker":Z,command:ee,carousel:te,card:ne,checkbox:oe,dialog:re,dropdown:se,input:ae,kbd:ce,label:ie,pagination:le,popover:de,progress:pe,"radio-group":ue,select:me,separator:fe,sidebar:ge,slider:he,switch:be,table:Ne,tabs:ve,textarea:xe,theme:K,toast:ye,tooltip:Ce};async function we(t){let o=process.cwd();e.intro("drivn add");let a=$(o);if(a||(e.log.error("Drivn is not initialized. Run npx drivn@latest create"),e.outro("Cancelled"),process.exit(1)),!t||!t.length){let n=await e.multiselect({message:"Select components to add",options:w.map(r=>({label:r.name,hint:r.description,value:r.name})),required:true});e.isCancel(n)&&(e.cancel("Cancelled"),process.exit(0)),t=n;}let b=t.filter(n=>!w.find(r=>r.name===n));b.length&&(e.log.error(`Unknown components: ${b.join(", ")}`),e.log.info("Available: "+w.map(n=>n.name).join(", ")),e.outro("Cancelled"),process.exit(1));let p=t.includes("theme"),g=t.filter(n=>n!=="theme"),u=new Set,v=new Set,h=n=>{if(u.has(n))return;let r=w.find(c=>c.name===n);r&&(r.dependencies.forEach(c=>h(c)),r.npmDependencies?.forEach(c=>v.add(c)),u.add(n));};g.forEach(h),p&&v.add("next-themes");let x=[...u].filter(n=>!g.includes(n));x.length&&e.log.info(`Required dependency: ${x.join(", ")}`);let l=a.typescript?"tsx":"jsx",N=join(o,a.paths.components);for(let n of u){let r=join(N,`${n}.${l}`);if(m(r)){let C=await e.confirm({message:`${n}.${l} exists. Overwrite?`,initialValue:false});if(e.isCancel(C)||!C){e.log.warn(`Skipped ${n}`);continue}}let c=D[n];c=c.replace(/@\/utils/g,`@/${a.paths.utils.replace(/^src\//,"")}`),d(r,c),e.log.success(`${n} \u2192 ${a.paths.components}/${n}.${l}`);}if(p){let n=join(N,`theme-provider.${l}`);if(m(n)){let c=await e.confirm({message:`theme-provider.${l} exists. Overwrite?`,initialValue:false});!e.isCancel(c)&&c?(d(n,D.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`)):e.log.warn("Skipped theme-provider");}else d(n,D.theme),e.log.success(`theme-provider \u2192 ${a.paths.components}/theme-provider.${l}`);if(a.paths.globals){let c=join(o,a.paths.globals);if(m(c)){let C=M(c);C.includes('[data-theme="dark"]')?e.log.warn("Theme tokens already exist in globals \u2014 skipped"):(d(c,C+O),e.log.success(`Theme tokens appended to ${i.cyan(a.paths.globals)}`));}else e.log.warn(`Globals file not found at ${a.paths.globals}`);}else e.log.warn('No globals path in drivn.config.json. Add "globals" to paths');let r=a.paths.components.replace(/^src\//,"@/");e.log.message(""),e.log.info(i.bold("Complete the setup:")),e.log.message(""),e.log.message(i.bold(`${i.cyan("1.")} Import ThemeProvider in your root layout:`)),e.log.message(i.cyan(` import { ThemeProvider } from "${r}/theme-provider"`)),e.log.message(""),e.log.message(i.bold(`${i.cyan("2.")} Add suppressHydrationWarning to <html>:`)),e.log.message(i.cyan(" <html suppressHydrationWarning>")),e.log.message(""),e.log.message(i.bold(`${i.cyan("3.")} Wrap your app with ThemeProvider:`)),e.log.message(i.cyan(" <ThemeProvider>")),e.log.message(i.cyan(" {children}")),e.log.message(i.cyan(" </ThemeProvider>")),e.log.message("");}if(u.has("calendar")&&a.paths.globals){let n=join(o,a.paths.globals);if(m(n)){let r=M(n);r.includes(".rdp-root")?e.log.warn("Calendar tokens already exist in globals \u2014 skipped"):(d(n,r+Re),e.log.success(`Calendar tokens appended to ${i.cyan(a.paths.globals)}`));}}if(v.size){let n=P(o),r=[...v],c=e.spinner();c.start("Installing packages");try{execSync(y(n,r),{cwd:o,stdio:"ignore"}),c.stop("Packages installed");}catch{c.stop("Failed to install packages"),e.log.warn(`Run manually: ${y(n,r)}`);}}e.outro("Done.");}var ke={version:"1.5.0"};var T=new Command;T.name("drivn").description("Drivn \u2014 Modern UI components").version(ke.version);T.command("create").description("Initialize Drivn in your project").action(G);T.command("add [components...]").description("Add components to your project").action(we);T.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drivn",
3
- "version": "1.3.1",
3
+ "version": "1.5.0",
4
4
  "description": "Modern UI components for React — add beautiful, accessible components to your project",
5
5
  "license": "MIT",
6
6
  "type": "module",