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/README.md +65 -0
- package/dist/index.js +716 -190
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
- package/LICENSE +0 -21
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
|
-
|
|
1961
|
-
|
|
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
|
-
|
|
1965
|
-
|
|
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
|
|
1969
|
-
|
|
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
|
|
1973
|
-
|
|
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
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
2017
|
+
MorphingGeometry.displayName = 'MorphingGeometry';
|
|
2018
|
+
export default MorphingGeometry;
|
|
2019
|
+
`
|
|
2020
|
+
};
|
|
1979
2021
|
|
|
1980
|
-
|
|
1981
|
-
|
|
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
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
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
|
|
1991
|
-
|
|
1992
|
-
|
|
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
|
|
1997
|
-
|
|
1998
|
-
|
|
2043
|
+
export interface AuroraColorOption {
|
|
2044
|
+
name: string;
|
|
2045
|
+
hex: string;
|
|
1999
2046
|
}
|
|
2000
2047
|
|
|
2001
|
-
export const
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
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
|
-
|
|
2018
|
-
|
|
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
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
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
|
|
2030
|
-
|
|
2031
|
-
|
|
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
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
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
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
}
|
|
2133
|
+
const handleSelectColor = (hex: string) => {
|
|
2134
|
+
if (controlledColor === undefined) {
|
|
2135
|
+
setInternalColor(hex);
|
|
2136
|
+
}
|
|
2137
|
+
onColorChange?.(hex);
|
|
2138
|
+
};
|
|
2068
2139
|
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
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
|
-
|
|
2077
|
-
|
|
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
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
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
|
-
|
|
2094
|
-
|
|
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
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
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
|
-
|
|
2104
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
2303
|
+
(resolve4) => rl.question(query, (ans) => {
|
|
2132
2304
|
rl.close();
|
|
2133
|
-
|
|
2305
|
+
resolve4(ans);
|
|
2134
2306
|
})
|
|
2135
2307
|
);
|
|
2136
2308
|
}
|
|
2137
|
-
async function addCommand(components, options) {
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
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 = [...
|
|
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[
|
|
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[
|
|
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
|
|
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
|
-
|
|
2225
|
-
|
|
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[
|
|
2236
|
-
} catch
|
|
2237
|
-
console.error("\x1B[31mFailed to install dependencies. Please run
|
|
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(
|
|
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 === "
|
|
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[
|
|
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[
|
|
2297
|
-
\x1B[
|
|
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
|
|
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
|
}
|