nexoreui-cli 0.1.1 → 0.1.3

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 CHANGED
@@ -1935,180 +1935,350 @@ function Badge({ className, variant, size, pulse = false, dot = false, children,
1935
1935
  )
1936
1936
  }
1937
1937
 
1938
- export { Badge, badgeVariants }
1939
-
1940
- // ----------------------------------------------------
1941
- // Consolidated Badge Components
1942
- // ----------------------------------------------------
1943
-
1944
- export const GlowBadge = ({ children, className, ...props }: BadgeProps) => (
1945
- <Badge variant="neon" className={className} {...props}>{children}</Badge>
1946
- )
1947
-
1948
- export const GlassBadge = ({ children, className, ...props }: BadgeProps) => (
1949
- <Badge variant="outline" className={cn("backdrop-blur-md bg-white/10 dark:bg-black/20 border-white/20 dark:border-white/10", className)} {...props}>{children}</Badge>
1950
- )
1951
-
1952
- export const DotBadge = ({ children, className, ...props }: BadgeProps) => (
1953
- <Badge dot={true} className={className} {...props}>{children}</Badge>
1954
- )
1955
-
1956
- export const GradientBadge = ({ children, className, ...props }: BadgeProps) => (
1957
- <Badge variant="gradient" className={className} {...props}>{children}</Badge>
1958
- )
1938
+ export { Badge, badgeVariants }`
1939
+ };
1959
1940
 
1960
- export const OutlineGlowBadge = ({ children, className, ...props }: BadgeProps) => (
1961
- <Badge variant="neon" className={cn("bg-transparent border border-purple-500/50", className)} {...props}>{children}</Badge>
1962
- )
1941
+ // src/registry/morphing-geometry.ts
1942
+ var morphingGeometry = {
1943
+ name: "morphing-geometry",
1944
+ dependencies: [
1945
+ "clsx",
1946
+ "tailwind-merge",
1947
+ "framer-motion",
1948
+ "lucide-react"
1949
+ ],
1950
+ fileName: "morphing-geometry.tsx",
1951
+ content: `'use client';
1963
1952
 
1964
- export const PulseBadge = ({ children, className, ...props }: BadgeProps) => (
1965
- <Badge pulse={true} className={className} {...props}>{children}</Badge>
1966
- )
1953
+ import * as React from 'react';
1954
+ import { motion, HTMLMotionProps } from 'framer-motion';
1955
+ import { Sparkles } from 'lucide-react';
1956
+ import { cn } from '../utils/cn';
1967
1957
 
1968
- export const SoftBadge = ({ children, className, ...props }: BadgeProps) => (
1969
- <Badge variant="secondary" className={className} {...props}>{children}</Badge>
1970
- )
1958
+ export type MorphingShape = 'pill' | 'circle' | 'square' | 'squircle' | 'custom';
1959
+ export type MorphingVariant = 'gradient' | 'aurora' | 'neon' | 'glass' | 'outline' | 'subtle';
1960
+ export type MorphingColor = 'violet' | 'cyan' | 'emerald' | 'rose' | 'amber' | 'rainbow' | 'mono';
1961
+ export type MorphingSize = 'sm' | 'md' | 'lg' | 'xl' | 'custom';
1962
+
1963
+ export interface MorphingGeometryProps extends Omit<HTMLMotionProps<'div'>, 'children'> {
1964
+ shape?: MorphingShape;
1965
+ radius?: number | string;
1966
+ variant?: MorphingVariant;
1967
+ color?: MorphingColor;
1968
+ size?: MorphingSize;
1969
+ dimension?: number;
1970
+ spin?: boolean;
1971
+ spinDuration?: number;
1972
+ interactive?: boolean;
1973
+ glow?: boolean;
1974
+ icon?: React.ReactNode;
1975
+ children?: React.ReactNode;
1976
+ }
1971
1977
 
1972
- export const TagBadge = ({ children, className, ...props }: BadgeProps) => (
1973
- <Badge className={cn("rounded-md", className)} {...props}>{children}</Badge>
1974
- )
1978
+ export const MorphingGeometry = React.forwardRef<HTMLDivElement, MorphingGeometryProps>(
1979
+ (
1980
+ {
1981
+ shape = 'squircle',
1982
+ radius,
1983
+ variant = 'gradient',
1984
+ color = 'violet',
1985
+ size = 'md',
1986
+ dimension,
1987
+ spin = false,
1988
+ spinDuration = 6,
1989
+ interactive = false,
1990
+ glow = true,
1991
+ icon,
1992
+ children,
1993
+ className,
1994
+ style,
1995
+ onClick,
1996
+ ...props
1997
+ },
1998
+ ref
1999
+ ) => {
2000
+ return (
2001
+ <motion.div
2002
+ ref={ref}
2003
+ animate={spin ? { rotate: [0, 90, 180, 270, 360] } : { rotate: 0 }}
2004
+ transition={{ rotate: { duration: spinDuration, repeat: Infinity, ease: 'linear' }, borderRadius: { duration: 0.4 } }}
2005
+ className={cn('relative flex items-center justify-center select-none overflow-hidden transition-all duration-300 w-24 h-24', className)}
2006
+ style={{ borderRadius: radius || '24%', ...style }}
2007
+ {...props}
2008
+ >
2009
+ <div className="relative z-10 flex flex-col items-center justify-center p-2 text-center">
2010
+ {icon || children || <Sparkles className="w-6 h-6 text-white" />}
2011
+ </div>
2012
+ </motion.div>
2013
+ );
2014
+ }
2015
+ );
1975
2016
 
1976
- export const PremiumBadge = ({ children, className, ...props }: BadgeProps) => (
1977
- <Badge variant="gradient" className={cn("bg-gradient-to-r from-yellow-500 via-amber-500 to-orange-500", className)} {...props}>{children}</Badge>
1978
- )
2017
+ MorphingGeometry.displayName = 'MorphingGeometry';
2018
+ export default MorphingGeometry;
2019
+ `
2020
+ };
1979
2021
 
1980
- export const MinimalBadge = ({ children, className, ...props }: BadgeProps) => (
1981
- <Badge size="sm" variant="outline" className={className} {...props}>{children}</Badge>
1982
- )
2022
+ // src/registry/aurora-border-fx.ts
2023
+ var auroraBorderFX = {
2024
+ name: "aurora-border-fx",
2025
+ dependencies: [
2026
+ "clsx",
2027
+ "tailwind-merge",
2028
+ "framer-motion",
2029
+ "lucide-react"
2030
+ ],
2031
+ fileName: "aurora-border-fx.tsx",
2032
+ content: `'use client';
1983
2033
 
1984
- export const NotificationBadge = ({ count, className }: { count: number; className?: string }) => (
1985
- <div className={cn("flex h-5 min-w-[20px] px-1 items-center justify-center rounded-full bg-destructive text-[10px] font-bold text-destructive-foreground shadow-sm", className)}>
1986
- {count}
1987
- </div>
1988
- )
2034
+ import * as React from 'react';
2035
+ import { motion, useReducedMotion } from 'framer-motion';
2036
+ import { Sparkles } from 'lucide-react';
2037
+ import { cn } from '../utils/cn';
1989
2038
 
1990
- export const RibbonBadge = ({ children, text, className }: { children?: React.ReactNode; text?: string; className?: string }) => (
1991
- <div className={cn("absolute top-0 right-0 bg-primary text-primary-foreground text-[10px] font-bold px-3 py-1 rounded-bl-xl uppercase tracking-wider", className)}>
1992
- {children || text}
1993
- </div>
1994
- )
2039
+ export type AuroraFXColor = 'violet' | 'cyan' | 'emerald' | 'rose' | 'amber' | string;
2040
+ export type AuroraFXGlow = 'none' | 'subtle' | 'medium' | 'strong';
2041
+ export type AuroraFXRadius = 'sm' | 'md' | 'lg' | 'xl' | 'full';
1995
2042
 
1996
- export interface OutlineDotBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
1997
- status?: string;
1998
- text?: string;
2043
+ export interface AuroraColorOption {
2044
+ name: string;
2045
+ hex: string;
1999
2046
  }
2000
2047
 
2001
- export const OutlineDotBadge = ({ children, className, status, text, ...props }: OutlineDotBadgeProps) => {
2002
- const statusColors: Record<string, string> = {
2003
- online: "bg-emerald-500",
2004
- offline: "bg-muted-foreground/50",
2005
- away: "bg-amber-500",
2006
- busy: "bg-red-500",
2007
- }
2008
- const dotColor = status ? statusColors[status] || "bg-emerald-500" : "bg-primary"
2009
- return (
2010
- <Badge variant="outline" className={className} {...props}>
2011
- <span className={cn("h-1.5 w-1.5 rounded-full mr-1.5", dotColor)} />
2012
- {children || text}
2013
- </Badge>
2014
- )
2015
- }
2048
+ export const defaultAuroraColors: AuroraColorOption[] = [
2049
+ { name: 'Violet', hex: '#8b5cf6' },
2050
+ { name: 'Cyan', hex: '#06b6d4' },
2051
+ { name: 'Emerald', hex: '#10b981' },
2052
+ { name: 'Rose', hex: '#f43f5e' },
2053
+ { name: 'Amber', hex: '#f59e0b' },
2054
+ ];
2055
+
2056
+ const colorPresetMap: Record<string, string> = {
2057
+ violet: '#8b5cf6',
2058
+ cyan: '#06b6d4',
2059
+ emerald: '#10b981',
2060
+ rose: '#f43f5e',
2061
+ amber: '#f59e0b',
2062
+ };
2016
2063
 
2017
- export interface GradientOutlineBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
2018
- text?: string;
2019
- }
2064
+ const radiusMap: Record<AuroraFXRadius, { outer: string; inner: string }> = {
2065
+ sm: { outer: 'rounded-lg', inner: 'rounded-[calc(0.5rem-1px)]' },
2066
+ md: { outer: 'rounded-xl', inner: 'rounded-[calc(0.75rem-1px)]' },
2067
+ lg: { outer: 'rounded-2xl', inner: 'rounded-[calc(1rem-1px)]' },
2068
+ xl: { outer: 'rounded-3xl', inner: 'rounded-[calc(1.5rem-1.5px)]' },
2069
+ full: { outer: 'rounded-full', inner: 'rounded-full' },
2070
+ };
2020
2071
 
2021
- export const GradientOutlineBadge = ({ children, text, className, ...props }: GradientOutlineBadgeProps) => (
2022
- <Badge className={cn("p-[1px] bg-gradient-to-r from-violet-500 to-pink-500 rounded-full border-0", className)} {...props}>
2023
- <div className="bg-background text-foreground rounded-full px-2.5 py-0.5 text-xs font-semibold">
2024
- {children || text}
2025
- </div>
2026
- </Badge>
2027
- )
2072
+ const glowOpacityMap: Record<AuroraFXGlow, number> = {
2073
+ none: 0,
2074
+ subtle: 0.25,
2075
+ medium: 0.45,
2076
+ strong: 0.75,
2077
+ };
2028
2078
 
2029
- export interface IconBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
2030
- icon?: React.ReactNode;
2031
- text?: string;
2079
+ export interface AuroraBorderFXProps extends React.HTMLAttributes<HTMLDivElement> {
2080
+ color?: AuroraFXColor;
2081
+ glow?: AuroraFXGlow;
2082
+ radius?: AuroraFXRadius;
2083
+ badgeText?: string;
2084
+ badgeIcon?: React.ReactNode;
2085
+ title?: string;
2086
+ description?: string;
2087
+ showColorPicker?: boolean;
2088
+ colors?: AuroraColorOption[];
2089
+ activeColor?: string;
2090
+ onColorChange?: (colorHex: string) => void;
2091
+ previewSlot?: React.ReactNode;
2092
+ footerSlot?: React.ReactNode;
2093
+ children?: React.ReactNode;
2032
2094
  }
2033
2095
 
2034
- export const IconBadge = ({ children, icon, text, className, ...props }: IconBadgeProps) => {
2035
- const renderIcon = () => {
2036
- if (!icon) return null;
2037
- if (typeof icon === "string") {
2038
- if (icon.toLowerCase() === "star") {
2039
- return <Star className="h-3 w-3 mr-1" />
2096
+ export const AuroraBorderFX = React.forwardRef<HTMLDivElement, AuroraBorderFXProps>(
2097
+ (
2098
+ {
2099
+ color = 'violet',
2100
+ glow = 'medium',
2101
+ radius = 'lg',
2102
+ badgeText = 'Aurora Border FX',
2103
+ badgeIcon = <Sparkles className="w-3 h-3" />,
2104
+ title = 'Reactive Aurora Borders',
2105
+ description = 'Smooth multi-color conic gradients that dynamically track and react with zero JavaScript canvas lag.',
2106
+ showColorPicker = true,
2107
+ colors = defaultAuroraColors,
2108
+ activeColor: controlledColor,
2109
+ onColorChange,
2110
+ previewSlot,
2111
+ footerSlot,
2112
+ className,
2113
+ children,
2114
+ ...props
2115
+ },
2116
+ ref
2117
+ ) => {
2118
+ const resolvedInitialColor = colorPresetMap[color] || color || '#8b5cf6';
2119
+ const [internalColor, setInternalColor] = React.useState<string>(resolvedInitialColor);
2120
+
2121
+ React.useEffect(() => {
2122
+ if (colorPresetMap[color]) {
2123
+ setInternalColor(colorPresetMap[color]);
2124
+ } else if (color) {
2125
+ setInternalColor(color);
2040
2126
  }
2041
- return <span className="mr-1">{icon}</span>
2042
- }
2043
- return <span className="mr-1">{icon}</span>
2044
- }
2045
-
2046
- return (
2047
- <Badge className={cn("inline-flex items-center gap-1", className)} {...props}>
2048
- {renderIcon()}
2049
- {children || text}
2050
- </Badge>
2051
- )
2052
- }
2053
-
2054
- export interface FloatingBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
2055
- text?: string;
2056
- }
2127
+ }, [color]);
2057
2128
 
2058
- export const FloatingBadge = ({ children, text, className, ...props }: FloatingBadgeProps) => (
2059
- <Badge className={cn("absolute -top-2 -right-2 z-10 animate-[bounce_3s_infinite]", className)} {...props}>
2060
- {children || text}
2061
- </Badge>
2062
- )
2129
+ const currentColor = controlledColor !== undefined ? controlledColor : internalColor;
2130
+ const radiusConfig = radiusMap[radius] || radiusMap.lg;
2131
+ const glowOpacity = glowOpacityMap[glow] ?? 0.45;
2063
2132
 
2064
- export interface ProgressBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
2065
- progress?: number;
2066
- text?: string;
2067
- }
2133
+ const handleSelectColor = (hex: string) => {
2134
+ if (controlledColor === undefined) {
2135
+ setInternalColor(hex);
2136
+ }
2137
+ onColorChange?.(hex);
2138
+ };
2068
2139
 
2069
- export const ProgressBadge = ({ children, progress = 50, text, className, ...props }: ProgressBadgeProps) => (
2070
- <Badge variant="outline" className={cn("relative overflow-hidden", className)} {...props}>
2071
- <div className="absolute inset-y-0 left-0 bg-primary/10 transition-all duration-300" style={{ width: \`\${progress}%\` }} />
2072
- <span className="relative z-10">{children || (text ? \`\${text} (\${progress}%)\` : \`\${progress}%\`)}</span>
2073
- </Badge>
2074
- )
2140
+ return (
2141
+ <div
2142
+ ref={ref}
2143
+ className={cn(
2144
+ 'relative isolate p-5 sm:p-6 overflow-hidden flex flex-col justify-between group transition-all duration-300',
2145
+ 'border border-border/80 bg-card/60 backdrop-blur-xl shadow-xl',
2146
+ radiusConfig.outer,
2147
+ className
2148
+ )}
2149
+ {...props}
2150
+ >
2151
+ {glow !== 'none' && (
2152
+ <div
2153
+ className="absolute -top-12 -right-12 w-48 h-48 rounded-full blur-[85px] pointer-events-none transition-colors duration-500 -z-10"
2154
+ style={{
2155
+ backgroundColor: currentColor,
2156
+ opacity: glowOpacity,
2157
+ }}
2158
+ />
2159
+ )}
2075
2160
 
2076
- export interface StatusRingBadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
2077
- status?: "success" | "error" | "warning" | "active" | string;
2078
- }
2161
+ {glow !== 'none' && glow !== 'subtle' && (
2162
+ <div
2163
+ className="absolute -bottom-10 -left-10 w-40 h-40 rounded-full blur-[90px] pointer-events-none transition-colors duration-700 -z-10"
2164
+ style={{
2165
+ backgroundColor: currentColor,
2166
+ opacity: glowOpacity * 0.4,
2167
+ }}
2168
+ />
2169
+ )}
2079
2170
 
2080
- export const StatusRingBadge = ({ status = "success", children, className, ...props }: StatusRingBadgeProps) => {
2081
- const ringColors: Record<string, string> = {
2082
- success: "border-emerald-500/30 ring-emerald-500/20 bg-emerald-500",
2083
- active: "border-emerald-500/30 ring-emerald-500/20 bg-emerald-500",
2084
- error: "border-red-500/30 ring-red-500/20 bg-red-500",
2085
- warning: "border-amber-500/30 ring-amber-500/20 bg-amber-500",
2086
- }
2087
- const colorClass = ringColors[status] || ringColors.success;
2088
- return (
2089
- <span className={cn("relative flex h-2.5 w-2.5 rounded-full ring-4 border-2 border-transparent", colorClass, className)} {...props} />
2090
- )
2091
- }
2171
+ {children ? (
2172
+ <div className="relative z-10 w-full h-full">{children}</div>
2173
+ ) : (
2174
+ <div className="relative z-10 flex flex-col justify-between h-full space-y-5">
2175
+ <div className="space-y-3">
2176
+ <div className="flex items-center justify-between gap-3">
2177
+ {badgeText && (
2178
+ <div
2179
+ className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[11px] font-semibold border transition-all duration-300 shadow-xs"
2180
+ style={{
2181
+ backgroundColor: \`\${currentColor}18\`,
2182
+ borderColor: \`\${currentColor}40\`,
2183
+ color: currentColor,
2184
+ }}
2185
+ >
2186
+ {badgeIcon}
2187
+ <span>{badgeText}</span>
2188
+ </div>
2189
+ )}
2190
+
2191
+ {showColorPicker && colors && colors.length > 0 && (
2192
+ <div className="flex items-center gap-1.5 bg-muted/60 dark:bg-muted/40 p-1 rounded-full border border-border/60 backdrop-blur-md">
2193
+ {colors.map((c) => {
2194
+ const isActive = currentColor.toLowerCase() === c.hex.toLowerCase();
2195
+ return (
2196
+ <button
2197
+ key={c.name}
2198
+ type="button"
2199
+ onClick={() => handleSelectColor(c.hex)}
2200
+ className={cn(
2201
+ 'w-3.5 h-3.5 rounded-full transition-all duration-200 cursor-pointer',
2202
+ isActive
2203
+ ? 'scale-125 ring-2 ring-foreground/40 shadow-xs'
2204
+ : 'hover:scale-110 opacity-70 hover:opacity-100'
2205
+ )}
2206
+ style={{ backgroundColor: c.hex }}
2207
+ title={\`Switch to \${c.name}\`}
2208
+ aria-label={\`Switch glow to \${c.name}\`}
2209
+ />
2210
+ );
2211
+ })}
2212
+ </div>
2213
+ )}
2214
+ </div>
2092
2215
 
2093
- export interface NeonOutlineBadgeProps extends React.HTMLAttributes<HTMLDivElement> {
2094
- text?: string;
2095
- }
2216
+ <div>
2217
+ {title && (
2218
+ <h3 className="text-base sm:text-lg font-bold tracking-tight text-foreground">
2219
+ {title}
2220
+ </h3>
2221
+ )}
2222
+ {description && (
2223
+ <p className="text-xs sm:text-sm text-muted-foreground leading-relaxed mt-1">
2224
+ {description}
2225
+ </p>
2226
+ )}
2227
+ </div>
2228
+ </div>
2096
2229
 
2097
- export const NeonOutlineBadge = ({ children, text, className, ...props }: NeonOutlineBadgeProps) => (
2098
- <Badge variant="outline" className={cn("border-2 border-primary text-primary shadow-[0_0_10px_rgba(var(--primary-rgb),0.4)] bg-transparent", className)} {...props}>
2099
- {children || text}
2100
- </Badge>
2101
- )
2230
+ <div className="pt-2 flex items-center justify-center">
2231
+ {previewSlot ? (
2232
+ previewSlot
2233
+ ) : (
2234
+ <div
2235
+ className={cn(
2236
+ 'relative p-[1.5px] overflow-hidden transition-all duration-300 w-full max-w-[280px]',
2237
+ radiusConfig.inner
2238
+ )}
2239
+ style={{
2240
+ background: \`linear-gradient(135deg, \${currentColor}, transparent 60%, \${currentColor}90)\`,
2241
+ }}
2242
+ >
2243
+ <div
2244
+ className={cn(
2245
+ 'bg-card/90 dark:bg-card/80 px-4 py-3 flex items-center justify-between backdrop-blur-md shadow-inner',
2246
+ radiusConfig.inner
2247
+ )}
2248
+ >
2249
+ <div className="flex items-center gap-2.5">
2250
+ <div
2251
+ className="w-2.5 h-2.5 rounded-full animate-pulse shrink-0"
2252
+ style={{ backgroundColor: currentColor }}
2253
+ />
2254
+ <span className="text-xs font-mono font-semibold text-foreground">
2255
+ Interactive Aurora Pill
2256
+ </span>
2257
+ </div>
2258
+ <span
2259
+ className="text-[10px] font-mono px-2 py-0.5 rounded-md font-medium border"
2260
+ style={{
2261
+ backgroundColor: \`\${currentColor}12\`,
2262
+ borderColor: \`\${currentColor}30\`,
2263
+ color: currentColor,
2264
+ }}
2265
+ >
2266
+ {currentColor.toUpperCase()}
2267
+ </span>
2268
+ </div>
2269
+ </div>
2270
+ )}
2271
+ </div>
2102
2272
 
2103
- export interface TagLabelProps extends React.HTMLAttributes<HTMLSpanElement> {
2104
- text?: string;
2105
- }
2273
+ {footerSlot && <div className="pt-2 border-t border-border/50">{footerSlot}</div>}
2274
+ </div>
2275
+ )}
2276
+ </div>
2277
+ );
2278
+ }
2279
+ );
2106
2280
 
2107
- export const TagLabel = ({ children, text, className, ...props }: TagLabelProps) => (
2108
- <span className={cn("px-2 py-1 bg-muted text-muted-foreground rounded-md text-xs font-medium text-muted-foreground hover:bg-muted/80 hover:text-foreground cursor-pointer transition-colors before:content-['#'] before:mr-0.5 before:opacity-50", className)} {...props}>
2109
- {children || text}
2110
- </span>
2111
- )
2281
+ AuroraBorderFX.displayName = 'AuroraBorderFX';
2112
2282
  `
2113
2283
  };
2114
2284
 
@@ -2118,7 +2288,9 @@ var registry = {
2118
2288
  modal,
2119
2289
  card,
2120
2290
  alert,
2121
- badge
2291
+ badge,
2292
+ "morphing-geometry": morphingGeometry,
2293
+ "aurora-border-fx": auroraBorderFX
2122
2294
  };
2123
2295
 
2124
2296
  // src/commands/add.ts
@@ -2128,16 +2300,23 @@ function askQuestion(query) {
2128
2300
  output: process.stdout
2129
2301
  });
2130
2302
  return new Promise(
2131
- (resolve2) => rl.question(query, (ans) => {
2303
+ (resolve4) => rl.question(query, (ans) => {
2132
2304
  rl.close();
2133
- resolve2(ans);
2305
+ resolve4(ans);
2134
2306
  })
2135
2307
  );
2136
2308
  }
2137
- async function addCommand(components, options) {
2138
- if (components.length === 0) {
2139
- console.error("\x1B[31mError: Please specify components to add.\x1B[0m");
2140
- console.log("Example: npx nexoreui add button modal");
2309
+ async function addCommand(components, options = {}) {
2310
+ const allRegistryKeys = Object.keys(registry);
2311
+ let targetComponents = [...components];
2312
+ if (options.all || targetComponents.includes("--all")) {
2313
+ targetComponents = allRegistryKeys;
2314
+ console.log(`
2315
+ \x1B[36m\u26A1 Adding all ${targetComponents.length} components from NexoreUI registry...\x1B[0m`);
2316
+ }
2317
+ if (targetComponents.length === 0) {
2318
+ console.error("\x1B[31mError: Please specify components to add or use --all.\x1B[0m");
2319
+ console.log("Example: npx nexoreui add button modal table --all");
2141
2320
  return;
2142
2321
  }
2143
2322
  const project = detectProject(process.cwd());
@@ -2145,9 +2324,25 @@ async function addCommand(components, options) {
2145
2324
  \x1B[34mDetected project type:\x1B[0m ${project.projectType.toUpperCase()}`);
2146
2325
  console.log(`\x1B[34mDetected package manager:\x1B[0m ${project.packageManager}
2147
2326
  `);
2327
+ let customComponentsDir;
2328
+ let customUtilsFile;
2329
+ try {
2330
+ const configPath = path3.join(project.baseDir, "nexore.json");
2331
+ if (fs3.existsSync(configPath)) {
2332
+ const cfg = JSON.parse(fs3.readFileSync(configPath, "utf8"));
2333
+ if (cfg.aliases?.components) {
2334
+ customComponentsDir = cfg.aliases.components.replace(/^@\//, project.hasSrcDir ? "src/" : "");
2335
+ }
2336
+ if (cfg.aliases?.utils) {
2337
+ const utilBase = cfg.aliases.utils.replace(/^@\//, project.hasSrcDir ? "src/" : "");
2338
+ customUtilsFile = utilBase.endsWith(".ts") || utilBase.endsWith(".js") ? utilBase : `${utilBase}.ts`;
2339
+ }
2340
+ }
2341
+ } catch {
2342
+ }
2148
2343
  const componentsToInstall = /* @__PURE__ */ new Set();
2149
2344
  const invalidComponents = [];
2150
- const queue = [...components];
2345
+ const queue = [...targetComponents.filter((c) => c !== "--all")];
2151
2346
  while (queue.length > 0) {
2152
2347
  const compName = queue.shift();
2153
2348
  const registryItem = registry[compName];
@@ -2169,14 +2364,11 @@ async function addCommand(components, options) {
2169
2364
  console.log("Run \x1B[32mnpx nexoreui list\x1B[0m to see all available components.");
2170
2365
  return;
2171
2366
  }
2172
- const defaultComponentsDir = project.hasSrcDir ? "src/components/ui" : "components/ui";
2173
- const defaultUtilsFile = project.hasSrcDir ? "src/lib/utils.ts" : "lib/utils.ts";
2174
- let componentsDirInput = "";
2175
- let utilsFileInput = "";
2176
- if (options.yes) {
2177
- componentsDirInput = defaultComponentsDir;
2178
- utilsFileInput = defaultUtilsFile;
2179
- } else {
2367
+ const defaultComponentsDir = customComponentsDir || (project.hasSrcDir ? "src/components/ui" : "components/ui");
2368
+ const defaultUtilsFile = customUtilsFile || (project.hasSrcDir ? "src/lib/utils.ts" : "lib/utils.ts");
2369
+ let componentsDirInput = defaultComponentsDir;
2370
+ let utilsFileInput = defaultUtilsFile;
2371
+ if (!options.yes && !customComponentsDir) {
2180
2372
  const compPrompt = await askQuestion(`Where would you like to install the components? (default: ${defaultComponentsDir}): `);
2181
2373
  componentsDirInput = compPrompt.trim() || defaultComponentsDir;
2182
2374
  const utilsPrompt = await askQuestion(`Where should we create the utilities file (cn helper)? (default: ${defaultUtilsFile}): `);
@@ -2184,25 +2376,24 @@ async function addCommand(components, options) {
2184
2376
  }
2185
2377
  const absoluteComponentsDir = path3.resolve(project.baseDir, componentsDirInput);
2186
2378
  const absoluteUtilsFile = path3.resolve(project.baseDir, utilsFileInput);
2187
- console.log(`
2188
- \x1B[33mInstalling components to:\x1B[0m ${absoluteComponentsDir}`);
2379
+ console.log(`\x1B[33mInstalling components to:\x1B[0m ${absoluteComponentsDir}`);
2189
2380
  console.log(`\x1B[33mUsing cn helper from:\x1B[0m ${absoluteUtilsFile}
2190
2381
  `);
2191
2382
  ensureDir(absoluteComponentsDir);
2192
2383
  const didCreateCn = ensureCnUtil(absoluteUtilsFile);
2193
2384
  if (didCreateCn) {
2194
- console.log(`\x1B[32mCreated utilities file (cn helper) at:\x1B[0m ${utilsFileInput}`);
2195
- } else {
2196
- console.log(`\x1B[90mUtilities file already exists at:\x1B[0m ${utilsFileInput}`);
2385
+ console.log(`\x1B[32m\u2714 Created utilities file (cn helper) at:\x1B[0m ${utilsFileInput}`);
2197
2386
  }
2198
2387
  const npmDependencies = /* @__PURE__ */ new Set();
2199
2388
  npmDependencies.add("clsx");
2200
2389
  npmDependencies.add("tailwind-merge");
2390
+ npmDependencies.add("lucide-react");
2391
+ npmDependencies.add("framer-motion");
2201
2392
  for (const compName of componentsToInstall) {
2202
2393
  const registryItem = registry[compName];
2203
2394
  const targetPath = path3.join(absoluteComponentsDir, registryItem.fileName);
2204
2395
  copyComponentFile(registryItem.content, targetPath, absoluteUtilsFile);
2205
- console.log(`\x1B[32mAdded component:\x1B[0m ${compName} -> ${path3.join(componentsDirInput, registryItem.fileName)}`);
2396
+ console.log(`\x1B[32m\u2714 Added component:\x1B[0m ${compName} -> ${path3.join(componentsDirInput, registryItem.fileName)}`);
2206
2397
  registryItem.dependencies.forEach((dep) => npmDependencies.add(dep));
2207
2398
  }
2208
2399
  const depsArray = Array.from(npmDependencies);
@@ -2214,33 +2405,29 @@ async function addCommand(components, options) {
2214
2405
  const existingDeps = { ...packageJson.dependencies, ...packageJson.devDependencies };
2215
2406
  depsToInstall = depsArray.filter((dep) => !existingDeps[dep]);
2216
2407
  }
2217
- } catch (e) {
2408
+ } catch {
2218
2409
  }
2219
2410
  if (depsToInstall.length > 0) {
2220
2411
  console.log(`
2221
2412
  \x1B[33mInstalling external dependencies:\x1B[0m ${depsToInstall.join(", ")}...`);
2222
2413
  let installCmd = "npm install";
2223
- if (project.packageManager === "pnpm") {
2224
- installCmd = "pnpm add";
2225
- } else if (project.packageManager === "yarn") {
2226
- installCmd = "yarn add";
2227
- } else if (project.packageManager === "bun") {
2228
- installCmd = "bun add";
2229
- }
2414
+ if (project.packageManager === "pnpm") installCmd = "pnpm add";
2415
+ else if (project.packageManager === "yarn") installCmd = "yarn add";
2416
+ else if (project.packageManager === "bun") installCmd = "bun add";
2230
2417
  try {
2231
2418
  (0, import_child_process.execSync)(`${installCmd} ${depsToInstall.join(" ")}`, {
2232
2419
  stdio: "inherit",
2233
2420
  cwd: project.baseDir
2234
2421
  });
2235
- console.log("\x1B[32mDependencies installed successfully!\x1B[0m");
2236
- } catch (err) {
2237
- console.error("\x1B[31mFailed to install dependencies. Please run the command manually:\x1B[0m");
2422
+ console.log("\x1B[32m\u2714 Dependencies installed successfully!\x1B[0m");
2423
+ } catch {
2424
+ console.error("\x1B[31mFailed to install dependencies automatically. Please run:\x1B[0m");
2238
2425
  console.log(` ${installCmd} ${depsToInstall.join(" ")}`);
2239
2426
  }
2240
- } else {
2241
- console.log("\n\x1B[90mAll external dependencies are already installed.\x1B[0m");
2242
2427
  }
2243
- console.log("\n\x1B[32m\x1B[1mDone! NexoreUI components are ready to use.\x1B[0m\n");
2428
+ console.log(`
2429
+ \x1B[32m\x1B[1m\u{1F389} Done! ${componentsToInstall.size} NexoreUI component(s) ready to use.\x1B[0m
2430
+ `);
2244
2431
  }
2245
2432
 
2246
2433
  // src/commands/list.ts
@@ -2259,6 +2446,299 @@ function listCommand() {
2259
2446
  });
2260
2447
  }
2261
2448
 
2449
+ // src/commands/init.ts
2450
+ var fs5 = __toESM(require("fs"));
2451
+ var path5 = __toESM(require("path"));
2452
+ var readline2 = __toESM(require("readline"));
2453
+
2454
+ // src/utils/config.ts
2455
+ var fs4 = __toESM(require("fs"));
2456
+ var path4 = __toESM(require("path"));
2457
+ var import_child_process2 = require("child_process");
2458
+ var THEME_PALETTES = {
2459
+ indigo: { light: "hsl(250 85% 50%)", dark: "hsl(250 85% 65%)", rgb: "99 60 220" },
2460
+ violet: { light: "hsl(262.1 83.3% 57.8%)", dark: "hsl(263.4 70% 50.4%)", rgb: "139 92 246" },
2461
+ emerald: { light: "hsl(142.1 76.2% 36.3%)", dark: "hsl(142.1 70.6% 45.3%)", rgb: "16 185 129" },
2462
+ rose: { light: "hsl(346.8 77.2% 49.8%)", dark: "hsl(346.8 77.2% 55%)", rgb: "244 63 94" },
2463
+ amber: { light: "hsl(37.7 92.1% 50.2%)", dark: "hsl(37.7 92.1% 55%)", rgb: "245 158 11" },
2464
+ cyan: { light: "hsl(190.4 95% 39%)", dark: "hsl(188.7 94.5% 42.7%)", rgb: "6 182 212" },
2465
+ slate: { light: "hsl(240 5.9% 10%)", dark: "hsl(0 0% 98%)", rgb: "244 244 245" },
2466
+ neon: { light: "hsl(173 80% 40%)", dark: "hsl(173 100% 50%)", rgb: "0 255 220" }
2467
+ };
2468
+ function ensurePathAlias(baseDir, projectType, hasSrcDir) {
2469
+ let updated = false;
2470
+ const tsConfigPath = path4.join(baseDir, "tsconfig.json");
2471
+ const jsConfigPath = path4.join(baseDir, "jsconfig.json");
2472
+ const targetConfig = fs4.existsSync(tsConfigPath) ? tsConfigPath : fs4.existsSync(jsConfigPath) ? jsConfigPath : null;
2473
+ if (targetConfig) {
2474
+ try {
2475
+ const content = fs4.readFileSync(targetConfig, "utf8");
2476
+ const parsed = JSON.parse(content);
2477
+ parsed.compilerOptions = parsed.compilerOptions || {};
2478
+ parsed.compilerOptions.baseUrl = parsed.compilerOptions.baseUrl || ".";
2479
+ parsed.compilerOptions.paths = parsed.compilerOptions.paths || {};
2480
+ const aliasTarget = hasSrcDir ? ["./src/*"] : ["./*"];
2481
+ if (!parsed.compilerOptions.paths["@/*"]) {
2482
+ parsed.compilerOptions.paths["@/*"] = aliasTarget;
2483
+ fs4.writeFileSync(targetConfig, JSON.stringify(parsed, null, 2), "utf8");
2484
+ updated = true;
2485
+ }
2486
+ } catch {
2487
+ }
2488
+ }
2489
+ if (projectType === "vite") {
2490
+ const viteConfigFiles = ["vite.config.ts", "vite.config.js", "vite.config.mjs"];
2491
+ for (const fileName of viteConfigFiles) {
2492
+ const vitePath = path4.join(baseDir, fileName);
2493
+ if (fs4.existsSync(vitePath)) {
2494
+ let viteContent = fs4.readFileSync(vitePath, "utf8");
2495
+ if (!viteContent.includes("alias") && !viteContent.includes("'@'")) {
2496
+ const hasPathImport = viteContent.includes("from 'path'") || viteContent.includes('from "path"');
2497
+ let headerAdditions = "";
2498
+ if (!hasPathImport) {
2499
+ headerAdditions += `import path from 'path'
2500
+ import { fileURLToPath } from 'url'
2501
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
2502
+ `;
2503
+ }
2504
+ if (viteContent.includes("defineConfig({")) {
2505
+ viteContent = headerAdditions + viteContent.replace(
2506
+ "defineConfig({",
2507
+ `defineConfig({
2508
+ resolve: {
2509
+ alias: {
2510
+ '@': path.resolve(__dirname, './${hasSrcDir ? "src" : "."}'),
2511
+ },
2512
+ },`
2513
+ );
2514
+ fs4.writeFileSync(vitePath, viteContent, "utf8");
2515
+ updated = true;
2516
+ }
2517
+ }
2518
+ break;
2519
+ }
2520
+ }
2521
+ }
2522
+ return updated;
2523
+ }
2524
+ function injectThemeCss(baseDir, cssRelativePath, themeName, radiusValue) {
2525
+ const cssAbsolutePath = path4.join(baseDir, cssRelativePath);
2526
+ const palette = THEME_PALETTES[themeName] || THEME_PALETTES.cyan;
2527
+ const radius = typeof radiusValue === "number" ? radiusValue : parseFloat(radiusValue) || 1;
2528
+ const themeBlock = `
2529
+ @source "../node_modules/nexoreui/dist/**/*.{js,mjs}";
2530
+
2531
+ @theme {
2532
+ --color-background: var(--background);
2533
+ --color-foreground: var(--foreground);
2534
+ --color-card: var(--card);
2535
+ --color-card-foreground: var(--card-foreground);
2536
+ --color-primary: var(--primary);
2537
+ --color-primary-foreground: var(--primary-foreground);
2538
+ --color-border: var(--border);
2539
+ --radius-lg: var(--radius);
2540
+ --radius-md: calc(var(--radius) - 2px);
2541
+ --radius-sm: calc(var(--radius) - 4px);
2542
+ --font-sans: system-ui, -apple-system, sans-serif;
2543
+ }
2544
+
2545
+ :root {
2546
+ --background: hsl(0 0% 100%);
2547
+ --foreground: hsl(240 10% 3.9%);
2548
+ --card: hsl(0 0% 100%);
2549
+ --card-foreground: hsl(240 10% 3.9%);
2550
+ --primary: ${palette.light};
2551
+ --primary-foreground: hsl(0 0% 100%);
2552
+ --border: hsl(240 5.9% 90%);
2553
+ --radius: ${radius}rem;
2554
+ }
2555
+
2556
+ .dark {
2557
+ --background: hsl(240 10% 3.9%);
2558
+ --foreground: hsl(0 0% 98%);
2559
+ --card: hsl(240 10% 3.9%);
2560
+ --card-foreground: hsl(0 0% 98%);
2561
+ --primary: ${palette.dark};
2562
+ --primary-foreground: hsl(0 0% 100%);
2563
+ --border: hsl(240 3.7% 15.9%);
2564
+ --radius: ${radius}rem;
2565
+ }
2566
+ `;
2567
+ if (fs4.existsSync(cssAbsolutePath)) {
2568
+ const existingContent = fs4.readFileSync(cssAbsolutePath, "utf8");
2569
+ if (!existingContent.includes("--color-primary") && !existingContent.includes("nexoreui/dist")) {
2570
+ fs4.writeFileSync(cssAbsolutePath, existingContent.trim() + "\n" + themeBlock, "utf8");
2571
+ return true;
2572
+ }
2573
+ } else {
2574
+ const cssDir = path4.dirname(cssAbsolutePath);
2575
+ if (!fs4.existsSync(cssDir)) fs4.mkdirSync(cssDir, { recursive: true });
2576
+ fs4.writeFileSync(cssAbsolutePath, `@import "tailwindcss";
2577
+ ` + themeBlock, "utf8");
2578
+ return true;
2579
+ }
2580
+ return false;
2581
+ }
2582
+ function installPeerDependencies(baseDir, packageManager, dependencies = ["clsx", "tailwind-merge", "lucide-react", "framer-motion"]) {
2583
+ try {
2584
+ const packageJsonPath = path4.join(baseDir, "package.json");
2585
+ let missingDeps = [...dependencies];
2586
+ if (fs4.existsSync(packageJsonPath)) {
2587
+ const pkg = JSON.parse(fs4.readFileSync(packageJsonPath, "utf8"));
2588
+ const installed = { ...pkg.dependencies, ...pkg.devDependencies };
2589
+ missingDeps = dependencies.filter((dep) => !installed[dep]);
2590
+ }
2591
+ if (missingDeps.length === 0) return true;
2592
+ let installCmd = "npm install";
2593
+ if (packageManager === "pnpm") installCmd = "pnpm add";
2594
+ else if (packageManager === "yarn") installCmd = "yarn add";
2595
+ else if (packageManager === "bun") installCmd = "bun add";
2596
+ console.log(`
2597
+ \x1B[33m\u26A1 Installing peer dependencies:\x1B[0m ${missingDeps.join(", ")}...`);
2598
+ (0, import_child_process2.execSync)(`${installCmd} ${missingDeps.join(" ")}`, {
2599
+ stdio: "inherit",
2600
+ cwd: baseDir
2601
+ });
2602
+ return true;
2603
+ } catch (err) {
2604
+ console.warn("\x1B[33mWarning: Automatic peer dependency installation skipped.\x1B[0m");
2605
+ return false;
2606
+ }
2607
+ }
2608
+
2609
+ // src/commands/init.ts
2610
+ function askQuestion2(query) {
2611
+ const rl = readline2.createInterface({
2612
+ input: process.stdin,
2613
+ output: process.stdout
2614
+ });
2615
+ return new Promise(
2616
+ (resolve4) => rl.question(query, (ans) => {
2617
+ rl.close();
2618
+ resolve4(ans);
2619
+ })
2620
+ );
2621
+ }
2622
+ async function initCommand(options = {}) {
2623
+ console.log(`
2624
+ \x1B[36m\x1B[1m=== Initializing NexoreUI in your project ===\x1B[0m
2625
+ `);
2626
+ const project = detectProject(process.cwd());
2627
+ console.log(`\x1B[32m\u2714 Detected Project:\x1B[0m ${project.projectType.toUpperCase()} (${project.packageManager})`);
2628
+ let theme = options.theme || "cyan";
2629
+ let radius = options.radius || "1.0";
2630
+ const defaultComponentsDir = project.hasSrcDir ? "src/components/ui" : "components/ui";
2631
+ const defaultUtilsFile = project.hasSrcDir ? "src/lib/utils.ts" : "lib/utils.ts";
2632
+ const defaultCssFile = project.projectType === "next" ? project.hasSrcDir ? "src/app/globals.css" : "app/globals.css" : project.hasSrcDir ? "src/index.css" : "src/index.css";
2633
+ let componentsDir = defaultComponentsDir;
2634
+ let utilsFile = defaultUtilsFile;
2635
+ if (!options.yes) {
2636
+ if (!options.theme) {
2637
+ const themeAns = await askQuestion2(`Which color theme would you like to use? (cyan, indigo, violet, emerald, rose, amber, slate, neon) [default: cyan]: `);
2638
+ if (themeAns.trim() && THEME_PALETTES[themeAns.trim().toLowerCase()]) {
2639
+ theme = themeAns.trim().toLowerCase();
2640
+ }
2641
+ }
2642
+ if (!options.radius) {
2643
+ const radiusAns = await askQuestion2(`Which radius value would you like to use? (0, 0.3, 0.5, 0.75, 1.0) [default: 1.0]: `);
2644
+ if (radiusAns.trim()) {
2645
+ radius = radiusAns.trim();
2646
+ }
2647
+ }
2648
+ const compAns = await askQuestion2(`Where should UI components be created? (default: ${defaultComponentsDir}): `);
2649
+ if (compAns.trim()) componentsDir = compAns.trim();
2650
+ const utilsAns = await askQuestion2(`Where should utility functions (cn helper) be placed? (default: ${defaultUtilsFile}): `);
2651
+ if (utilsAns.trim()) utilsFile = utilsAns.trim();
2652
+ }
2653
+ const absoluteComponentsDir = path5.resolve(project.baseDir, componentsDir);
2654
+ const absoluteUtilsFile = path5.resolve(project.baseDir, utilsFile);
2655
+ ensureDir(absoluteComponentsDir);
2656
+ ensureCnUtil(absoluteUtilsFile);
2657
+ const didUpdateAlias = ensurePathAlias(project.baseDir, project.projectType, project.hasSrcDir);
2658
+ if (didUpdateAlias) {
2659
+ console.log(`\x1B[32m\u2714\x1B[0m Configured path alias \x1B[1m'@/*'\x1B[0m in project config`);
2660
+ }
2661
+ const didInjectCss = injectThemeCss(project.baseDir, defaultCssFile, theme, radius);
2662
+ if (didInjectCss) {
2663
+ console.log(`\x1B[32m\u2714\x1B[0m Injected Tailwind CSS v4 @theme tokens into \x1B[1m${defaultCssFile}\x1B[0m`);
2664
+ }
2665
+ installPeerDependencies(project.baseDir, project.packageManager);
2666
+ const config = {
2667
+ $schema: "https://nexoreui.site/schema.json",
2668
+ style: "default",
2669
+ theme,
2670
+ radius: Number(radius),
2671
+ framework: project.projectType,
2672
+ packageManager: project.packageManager,
2673
+ font: "system",
2674
+ density: "default",
2675
+ animation: "energetic",
2676
+ defaultMode: "light",
2677
+ tailwind: {
2678
+ config: "tailwind.config.js",
2679
+ css: defaultCssFile,
2680
+ baseColor: "zinc",
2681
+ cssVariables: true
2682
+ },
2683
+ aliases: {
2684
+ components: `@/${componentsDir.replace(/^src\//, "")}`,
2685
+ utils: `@/${utilsFile.replace(/^src\//, "").replace(/\.(ts|js)$/, "")}`
2686
+ }
2687
+ };
2688
+ const configPath = path5.join(project.baseDir, "nexore.json");
2689
+ fs5.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
2690
+ console.log(`\x1B[32m\u2714\x1B[0m Generated \x1B[1mnexore.json\x1B[0m (Theme: ${theme}, Radius: ${radius}rem)`);
2691
+ console.log(`\x1B[32m\u2714\x1B[0m Utilities ready at \x1B[1m${utilsFile}\x1B[0m`);
2692
+ console.log(`\x1B[32m\u2714\x1B[0m Components directory ready at \x1B[1m${componentsDir}\x1B[0m`);
2693
+ console.log(`
2694
+ \x1B[32m\x1B[1m\u{1F389} NexoreUI initialized successfully! You can now add components:\x1B[0m`);
2695
+ console.log(` \x1B[36mnpx nexoreui add button card modal table --all\x1B[0m
2696
+ `);
2697
+ }
2698
+
2699
+ // src/commands/create.ts
2700
+ var fs6 = __toESM(require("fs"));
2701
+ var path6 = __toESM(require("path"));
2702
+ var import_child_process3 = require("child_process");
2703
+ async function createCommand(projectName, options = {}) {
2704
+ const name = projectName || "my-nexore-app";
2705
+ const targetDir = path6.resolve(process.cwd(), name);
2706
+ console.log(`
2707
+ \x1B[36m\x1B[1m\u{1F680} Creating a new NexoreUI Project:\x1B[0m \x1B[32m${name}\x1B[0m
2708
+ `);
2709
+ if (fs6.existsSync(targetDir) && fs6.readdirSync(targetDir).length > 0) {
2710
+ console.error(`\x1B[31mError: Target directory ${name} already exists and is not empty.\x1B[0m`);
2711
+ return;
2712
+ }
2713
+ console.log(`\x1B[33m\u26A1 Scaffolding React + Vite + Tailwind CSS template...\x1B[0m`);
2714
+ try {
2715
+ (0, import_child_process3.execSync)(`npm create vite@latest ${name} -- --template react-ts`, { stdio: "inherit" });
2716
+ } catch (err) {
2717
+ console.error(`\x1B[31mFailed to scaffold Vite project.\x1B[0m`);
2718
+ return;
2719
+ }
2720
+ process.chdir(targetDir);
2721
+ console.log(`
2722
+ \x1B[33m\u{1F4E6} Installing NexoreUI, Tailwind CSS, and core packages...\x1B[0m`);
2723
+ (0, import_child_process3.execSync)(`npm install nexoreui lucide-react clsx tailwind-merge framer-motion @tailwindcss/vite tailwindcss`, {
2724
+ stdio: "inherit"
2725
+ });
2726
+ await initCommand({
2727
+ yes: true,
2728
+ theme: options.theme || "cyan",
2729
+ radius: options.radius || "1.0"
2730
+ });
2731
+ console.log(`
2732
+ \x1B[32m\x1B[1m\u2728 Project ${name} is ready!\x1B[0m`);
2733
+ console.log(`
2734
+ To get started:
2735
+ `);
2736
+ console.log(` \x1B[36mcd ${name}\x1B[0m`);
2737
+ console.log(` \x1B[36mnpx nexoreui add button card modal table --all\x1B[0m`);
2738
+ console.log(` \x1B[36mnpm run dev\x1B[0m
2739
+ `);
2740
+ }
2741
+
2262
2742
  // src/index.ts
2263
2743
  async function main() {
2264
2744
  const args = process.argv.slice(2);
@@ -2267,20 +2747,59 @@ async function main() {
2267
2747
  printHelp();
2268
2748
  return;
2269
2749
  }
2270
- if (command === "list") {
2750
+ if (command === "create") {
2751
+ const projectName = args[1] && !args[1].startsWith("-") ? args[1] : void 0;
2752
+ let theme;
2753
+ let radius;
2754
+ for (let i = 1; i < args.length; i++) {
2755
+ const arg = args[i];
2756
+ if (arg === "--theme" && args[i + 1]) {
2757
+ theme = args[++i];
2758
+ } else if (arg.startsWith("--theme=")) {
2759
+ theme = arg.split("=")[1];
2760
+ } else if (arg === "--radius" && args[i + 1]) {
2761
+ radius = args[++i];
2762
+ } else if (arg.startsWith("--radius=")) {
2763
+ radius = arg.split("=")[1];
2764
+ }
2765
+ }
2766
+ await createCommand(projectName, { theme, radius });
2767
+ } else if (command === "init") {
2768
+ let yes = false;
2769
+ let theme;
2770
+ let radius;
2771
+ for (let i = 1; i < args.length; i++) {
2772
+ const arg = args[i];
2773
+ if (arg === "-y" || arg === "--yes") {
2774
+ yes = true;
2775
+ } else if (arg === "--theme" && args[i + 1]) {
2776
+ theme = args[++i];
2777
+ } else if (arg.startsWith("--theme=")) {
2778
+ theme = arg.split("=")[1];
2779
+ } else if (arg === "--radius" && args[i + 1]) {
2780
+ radius = args[++i];
2781
+ } else if (arg.startsWith("--radius=")) {
2782
+ radius = arg.split("=")[1];
2783
+ }
2784
+ }
2785
+ await initCommand({ yes, theme, radius });
2786
+ } else if (command === "list") {
2271
2787
  listCommand();
2272
2788
  } else if (command === "add") {
2273
2789
  const components = [];
2274
2790
  let yes = false;
2791
+ let all = false;
2275
2792
  for (let i = 1; i < args.length; i++) {
2276
2793
  const arg = args[i];
2277
2794
  if (arg === "-y" || arg === "--yes") {
2278
2795
  yes = true;
2796
+ } else if (arg === "--all" || arg === "-a") {
2797
+ all = true;
2279
2798
  } else if (!arg.startsWith("-")) {
2280
2799
  components.push(arg);
2281
2800
  }
2282
2801
  }
2283
- await addCommand(components, { yes });
2802
+ await addCommand(components, { yes, all });
2284
2803
  } else {
2285
2804
  console.error(`\x1B[31mUnknown command: ${command}\x1B[0m`);
2286
2805
  printHelp();
@@ -2288,16 +2807,23 @@ async function main() {
2288
2807
  }
2289
2808
  function printHelp() {
2290
2809
  console.log(`
2291
- \x1B[34m\x1B[1mNexoreUI CLI\x1B[0m
2810
+ \x1B[36m\x1B[1mNexoreUI CLI\x1B[0m
2811
+ \x1B[90mModern, animated, production-ready React components with Tailwind CSS v4\x1B[0m
2812
+
2292
2813
  Usage:
2293
2814
  npx nexoreui [command] [options]
2294
2815
 
2295
2816
  Commands:
2296
- \x1B[32madd [components...]\x1B[0m Add components to your project (e.g., button, modal, card, alert, badge)
2297
- \x1B[32mlist\x1B[0m List all available components
2817
+ \x1B[32mcreate [name]\x1B[0m Create a new fully configured NexoreUI starter project
2818
+ \x1B[32minit\x1B[0m Initialize NexoreUI in your project (configure theme, aliases, and CSS)
2819
+ \x1B[32madd [components...]\x1B[0m Add components to your project (use --all to install all 40+ components)
2820
+ \x1B[32mlist\x1B[0m List all available components in registry
2298
2821
 
2299
2822
  Options:
2300
- \x1B[33m-y, --yes\x1B[0m Skip prompts and use default paths
2823
+ \x1B[33m--theme <name>\x1B[0m Set color palette (cyan, indigo, violet, emerald, rose, amber, slate, neon)
2824
+ \x1B[33m--radius <val>\x1B[0m Set border radius (0, 0.3, 0.5, 0.75, 1.0)
2825
+ \x1B[33m--all, -a\x1B[0m Install all available components at once
2826
+ \x1B[33m-y, --yes\x1B[0m Skip prompts and use defaults automatically
2301
2827
  \x1B[33m-h, --help\x1B[0m Show help information
2302
2828
  `);
2303
2829
  }