UNPKG

ui-aesthetic-utils

Version:

A lightweight utility library for modern UI aesthetics including glassmorphism, neumorphism, glow effects, and soft shadows

1,354 lines (1,346 loc) 50.4 kB
/** * Default glass configuration */ const defaultGlassConfig = { blur: { sm: '8px', md: '15px', lg: '25px', xl: '40px' }}; /** * Resolves blur size to pixel value */ function resolveBlurSize(blur, config) { if (typeof blur === 'string' && blur.endsWith('px')) { return blur; } const blurConfig = config?.blur || defaultGlassConfig.blur; switch (blur) { case 'sm': return blurConfig.sm; case 'md': return blurConfig.md; case 'lg': return blurConfig.lg; case 'xl': return blurConfig.xl; default: return typeof blur === 'string' ? blur : blurConfig.md; } } /** * Generates glassmorphism CSS properties */ function generateGlassStyles(options = {}) { const { blur = 'md', opacity = 0.6, background, border, borderRadius = '12px' } = options; const blurValue = resolveBlurSize(blur); const finalBackground = background || `rgba(255, 255, 255, ${opacity})`; const finalBorder = border || `1px solid rgba(255, 255, 255, ${Math.min(opacity + 0.1, 1)})`; return { backdropFilter: `blur(${blurValue})`, WebkitBackdropFilter: `blur(${blurValue})`, // Safari support background: finalBackground, border: finalBorder, borderRadius, position: 'relative', overflow: 'hidden' }; } /** * Generates glass CSS class name based on options */ function generateGlassClassName(options = {}) { const { blur = 'md', opacity } = options; let className = `glass-${blur}`; if (opacity && opacity !== 0.6) { const opacityPercent = Math.round(opacity * 100); className += `-opacity-${opacityPercent}`; } return className; } /** * Creates CSS variables for glass configuration */ function createGlassCSSVariables(config) { return { '--glass-blur-sm': config.blur.sm, '--glass-blur-md': config.blur.md, '--glass-blur-lg': config.blur.lg, '--glass-blur-xl': config.blur.xl, '--glass-background-light': config.glassmorphic.variants.light, '--glass-background-dark': config.glassmorphic.variants.dark, '--glass-background-primary': config.glassmorphic.variants.primary, '--glass-background-secondary': config.glassmorphic.variants.secondary, '--glass-border-opacity': config.glassmorphic.borderOpacity.toString(), '--glass-backdrop-blur': config.glassmorphic.backdropBlur }; } /** * Validates glass style options */ function validateGlassOptions(options) { const errors = []; if (options.opacity && (options.opacity < 0 || options.opacity > 1)) { errors.push('Opacity must be between 0 and 1'); } if (options.blur && typeof options.blur === 'string' && !['sm', 'md', 'lg', 'xl'].includes(options.blur) && !options.blur.endsWith('px')) { errors.push('Blur must be a valid size (sm, md, lg, xl) or a pixel value'); } return { isValid: errors.length === 0, errors }; } /** * Creates responsive glass styles for different breakpoints */ function createResponsiveGlassStyles(breakpoints) { const responsiveStyles = {}; Object.entries(breakpoints).forEach(([breakpoint, options]) => { responsiveStyles[breakpoint] = generateGlassStyles(options); }); return responsiveStyles; } /** * Merges glass styles with custom styles */ function mergeGlassStyles(glassOptions, customStyles = {}) { const glassStyles = generateGlassStyles(glassOptions); return { ...glassStyles, ...customStyles }; } /** * Creates glass effect with animation */ function createAnimatedGlassStyles(options) { const baseStyles = generateGlassStyles(options); const { animation } = options; if (!animation) return baseStyles; return { ...baseStyles, transition: `${animation.property || 'all'} ${animation.duration || '0.3s'} ${animation.easing || 'ease-in-out'}` }; } /** * Default neumorphic configuration */ const defaultNeumorphicConfig = { baseColor: '#e0e5ec', lightSource: '145deg', darkShadow: 'rgba(163, 177, 198, 0.6)', lightShadow: 'rgba(255, 255, 255, 0.8)', depth: { sm: '2px 2px 4px', md: '4px 4px 8px', lg: '8px 8px 16px', xl: '12px 12px 24px' } }; /** * Resolves depth size to shadow values */ function resolveNeumorphicDepth(depth, config) { const depthConfig = config?.neumorphic.depth || defaultNeumorphicConfig.depth; switch (depth) { case 'sm': return depthConfig.sm; case 'md': return depthConfig.md; case 'lg': return depthConfig.lg; case 'xl': return depthConfig.xl; default: return depthConfig.md; } } /** * Generates neumorphic shadow based on shape and depth */ function generateNeumorphicShadow(shape, depth, config) { const neuroConfig = config?.neumorphic || defaultNeumorphicConfig; const depthValue = resolveNeumorphicDepth(depth, config); const [x, y, blur] = depthValue.split(' '); const darkShadow = `${x} ${y} ${blur} ${neuroConfig.darkShadow}`; const lightShadow = `${x.replace('-', '')} ${y.replace('-', '')} ${blur} ${neuroConfig.lightShadow}`; switch (shape) { case 'flat': return `${darkShadow}, -${lightShadow}`; case 'concave': return `inset ${darkShadow}, inset -${lightShadow}`; case 'convex': return `${darkShadow}, -${lightShadow}, inset 1px 1px 2px ${neuroConfig.lightShadow}`; default: return `${darkShadow}, -${lightShadow}`; } } /** * Generates neumorphism CSS properties */ function generateNeumorphicStyles(options = {}) { const { depth = 'md', shape = 'flat', baseColor, borderRadius = '12px' } = options; const config = { neumorphic: { ...defaultNeumorphicConfig, ...(baseColor && { baseColor }) } }; const boxShadow = generateNeumorphicShadow(shape, depth, config); const background = baseColor || defaultNeumorphicConfig.baseColor; return { background, borderRadius, boxShadow, border: 'none', position: 'relative', cursor: shape === 'flat' ? 'pointer' : 'default' }; } /** * Generates neumorphic CSS class name based on options */ function generateNeumorphicClassName(options = {}) { const { depth = 'md', shape = 'flat' } = options; return `neuro-${shape}-${depth}`; } /** * Creates CSS variables for neumorphic configuration */ function createNeumorphicCSSVariables(config) { return { '--neuro-base-color': config.neumorphic.baseColor, '--neuro-light-source': config.neumorphic.lightSource, '--neuro-dark-shadow': config.neumorphic.darkShadow, '--neuro-light-shadow': config.neumorphic.lightShadow, '--neuro-depth-sm': config.neumorphic.depth.sm, '--neuro-depth-md': config.neumorphic.depth.md, '--neuro-depth-lg': config.neumorphic.depth.lg, '--neuro-depth-xl': config.neumorphic.depth.xl }; } /** * Creates neumorphic button states (normal, hover, active) */ function createNeumorphicButtonStates(options) { const baseStyles = generateNeumorphicStyles(options); const { depth = 'md', shape = 'flat' } = options; // Create hover state with slightly reduced depth const hoverDepth = depth === 'sm' ? 'sm' : depth === 'md' ? 'sm' : depth === 'lg' ? 'md' : 'lg'; const hoverStyles = generateNeumorphicStyles({ ...options, depth: hoverDepth }); // Create active state (pressed/inset effect) const activeStyles = generateNeumorphicStyles({ ...options, shape: 'concave', depth: 'sm' }); return { normal: baseStyles, hover: { ...hoverStyles, transform: 'translateY(-1px)' }, active: { ...activeStyles, transform: 'translateY(1px)' } }; } /** * Validates neumorphic style options */ function validateNeumorphicOptions(options) { const errors = []; if (options.shape && !['flat', 'concave', 'convex'].includes(options.shape)) { errors.push('Shape must be one of: flat, concave, convex'); } if (options.depth && !['sm', 'md', 'lg', 'xl'].includes(options.depth)) { errors.push('Depth must be one of: sm, md, lg, xl'); } if (options.baseColor && !isValidColor(options.baseColor)) { errors.push('Base color must be a valid CSS color value'); } return { isValid: errors.length === 0, errors }; } /** * Utility function to validate CSS color values */ function isValidColor(color) { const colorRegex = /^(#[0-9A-F]{6}|#[0-9A-F]{3}|rgb\(|rgba\(|hsl\(|hsla\()/i; return colorRegex.test(color) || CSS.supports('color', color); } /** * Creates adaptive neumorphic styles based on background color */ function createAdaptiveNeumorphicStyles(backgroundColor, options) { // Convert background color to determine if it's light or dark isLightColor(backgroundColor); // Adjust shadow colors based on background const adaptedConfig = { ...options, baseColor: backgroundColor }; return generateNeumorphicStyles(adaptedConfig); } /** * Utility function to determine if a color is light or dark */ function isLightColor(color) { // Simple implementation - can be enhanced with proper color parsing const hex = color.replace('#', ''); const r = parseInt(hex.substr(0, 2), 16); const g = parseInt(hex.substr(2, 2), 16); const b = parseInt(hex.substr(4, 2), 16); const brightness = ((r * 299) + (g * 587) + (b * 114)) / 1000; return brightness > 155; } /** * Creates neumorphic input field styles */ function createNeumorphicInputStyles(options) { const baseStyles = generateNeumorphicStyles({ ...options, shape: options.focused ? 'concave' : 'flat' }); return { ...baseStyles, padding: '12px 16px', border: 'none', outline: 'none', fontSize: '14px', fontFamily: 'inherit', color: 'inherit', backgroundColor: 'transparent', transition: 'box-shadow 0.3s ease' }; } /** * Default glow configuration */ const defaultGlowConfig = { primary: '#3b82f6'}; /** * Resolves glow intensity to blur and opacity values */ function resolveGlowIntensity(intensity) { switch (intensity) { case 'subtle': return { blur: 10, opacity: 0.3, spread: 0 }; case 'medium': return { blur: 20, opacity: 0.5, spread: 0 }; case 'strong': return { blur: 30, opacity: 0.7, spread: 2 }; case 'neon': return { blur: 40, opacity: 0.9, spread: 4 }; default: return { blur: 20, opacity: 0.5, spread: 0 }; } } /** * Converts color to rgba format with opacity */ function colorToRgba(color, opacity) { // Handle hex colors if (color.startsWith('#')) { const hex = color.replace('#', ''); const r = parseInt(hex.substr(0, 2), 16); const g = parseInt(hex.substr(2, 2), 16); const b = parseInt(hex.substr(4, 2), 16); return `rgba(${r}, ${g}, ${b}, ${opacity})`; } // Handle rgb/rgba colors if (color.startsWith('rgb')) { const match = color.match(/\d+/g); if (match && match.length >= 3) { return `rgba(${match[0]}, ${match[1]}, ${match[2]}, ${opacity})`; } } // Handle named colors (basic support) const namedColors = { red: '255, 0, 0', green: '0, 255, 0', blue: '0, 0, 255', white: '255, 255, 255', black: '0, 0, 0' }; if (namedColors[color.toLowerCase()]) { return `rgba(${namedColors[color.toLowerCase()]}, ${opacity})`; } // Fallback - return as is (might not work for all cases) return color; } /** * Generates glow CSS properties */ function generateGlowStyles(options = {}) { const { color = defaultGlowConfig.primary, intensity = 'medium', spread, blur, inset = false } = options; const resolvedIntensity = resolveGlowIntensity(intensity); const finalBlur = blur ?? resolvedIntensity.blur; const finalSpread = spread ?? resolvedIntensity.spread; const glowColor = colorToRgba(color, resolvedIntensity.opacity); const shadowPrefix = inset ? 'inset ' : ''; const boxShadow = `${shadowPrefix}0 0 ${finalBlur}px ${finalSpread}px ${glowColor}`; return { boxShadow, transition: 'box-shadow 0.3s ease-in-out' }; } /** * Generates glow CSS class name based on options */ function generateGlowClassName(options = {}) { const { intensity = 'medium', color } = options; let className = `glow-${intensity}`; if (color) { // Convert color to a class-safe name const colorName = getColorName(color); if (colorName) { className += `-${colorName}`; } } return className; } /** * Gets a safe class name from a color value */ function getColorName(color) { const colorMap = { '#3b82f6': 'blue', '#8b5cf6': 'purple', '#f59e0b': 'amber', '#00ff88': 'neon', '#ef4444': 'red', '#22c55e': 'green', '#06b6d4': 'cyan', '#f97316': 'orange' }; return colorMap[color.toLowerCase()] || null; } /** * Creates CSS variables for glow configuration */ function createGlowCSSVariables(config) { return { '--glow-primary': config.glow.primary, '--glow-secondary': config.glow.secondary, '--glow-accent': config.glow.accent, '--glow-neon': config.glow.neon, '--glow-subtle': config.glow.subtle, '--glow-medium': config.glow.medium, '--glow-strong': config.glow.strong }; } /** * Creates animated glow effect with pulsing */ function createAnimatedGlowStyles(options) { const baseStyles = generateGlowStyles(options); const { animation } = options; if (!animation) return baseStyles; const duration = animation.duration || '2s'; const pulseIntensity = animation.pulseIntensity || 1.5; // Create stronger glow for animation peak generateGlowStyles({ ...options, blur: (options.blur || 20) * pulseIntensity, spread: (options.spread || 0) * pulseIntensity }); return { ...baseStyles, animation: `glowPulse ${duration} ease-in-out infinite alternate`, // CSS keyframes would need to be injected separately }; } /** * Creates multi-layered glow effect */ function createLayeredGlowStyles(layers) { const shadows = layers.map(layer => { const styles = generateGlowStyles(layer); return styles.boxShadow; }).join(', '); return { boxShadow: shadows, transition: 'box-shadow 0.3s ease-in-out' }; } /** * Creates glow hover effect */ function createGlowHoverStyles(normalOptions, hoverOptions) { const normal = generateGlowStyles(normalOptions); const hoverConfig = { ...normalOptions, ...hoverOptions, intensity: hoverOptions?.intensity || 'strong' }; const hover = generateGlowStyles(hoverConfig); return { normal, hover }; } /** * Creates text glow effect */ function createTextGlowStyles(options = {}) { const { color = defaultGlowConfig.primary, intensity = 'medium' } = options; const resolvedIntensity = resolveGlowIntensity(intensity); const glowColor = colorToRgba(color, resolvedIntensity.opacity); return { textShadow: `0 0 ${resolvedIntensity.blur}px ${glowColor}`, color: color, transition: 'text-shadow 0.3s ease-in-out' }; } /** * Creates neon glow effect with inner glow */ function createNeonGlowStyles(color, intensity = 'neon') { const outerGlow = generateGlowStyles({ color, intensity }); const innerGlow = generateGlowStyles({ color, intensity: 'subtle', inset: true, blur: 5, spread: 1 }); return { boxShadow: `${outerGlow.boxShadow}, ${innerGlow.boxShadow}`, border: `1px solid ${colorToRgba(color, 0.5)}`, transition: 'box-shadow 0.3s ease-in-out' }; } /** * Validates glow style options */ function validateGlowOptions(options) { const errors = []; if (options.intensity && !['subtle', 'medium', 'strong', 'neon'].includes(options.intensity)) { errors.push('Intensity must be one of: subtle, medium, strong, neon'); } if (options.blur && (options.blur < 0 || options.blur > 100)) { errors.push('Blur must be between 0 and 100 pixels'); } if (options.spread && (options.spread < 0 || options.spread > 20)) { errors.push('Spread must be between 0 and 20 pixels'); } return { isValid: errors.length === 0, errors }; } /** * Default shadow configuration */ const defaultShadowConfig = { elevation: { sm: '0 1px 3px rgba(0, 0, 0, 0.1)', md: '0 4px 12px rgba(0, 0, 0, 0.15)', lg: '0 8px 24px rgba(0, 0, 0, 0.2)', xl: '0 16px 48px rgba(0, 0, 0, 0.25)', xxl: '0 32px 64px rgba(0, 0, 0, 0.3)' }}; /** * Resolves shadow size to shadow values */ function resolveShadowSize(size, config) { const shadowConfig = config?.shadow.elevation || defaultShadowConfig.elevation; switch (size) { case 'sm': return shadowConfig.sm; case 'md': return shadowConfig.md; case 'lg': return shadowConfig.lg; case 'xl': return shadowConfig.xl; case 'xxl': return shadowConfig.xxl; default: return shadowConfig.md; } } /** * Adjusts shadow opacity based on softness */ function adjustShadowSoftness(shadowValue, softness) { const softnessMultiplier = { soft: 0.7, medium: 1.0, hard: 1.3 }; const multiplier = softnessMultiplier[softness] || 1.0; // Extract rgba opacity and adjust it return shadowValue.replace(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/g, (match, r, g, b, a) => { const newOpacity = Math.min(parseFloat(a) * multiplier, 1); return `rgba(${r}, ${g}, ${b}, ${newOpacity})`; }); } /** * Generates directional shadow based on direction */ function generateDirectionalShadow(baseShadow, direction) { // Parse shadow values (assumes format: "x y blur spread color") const shadowParts = baseShadow.split(' '); if (shadowParts.length < 3) return baseShadow; const [x, y, blur, ...rest] = shadowParts; const spread = rest.length > 1 ? rest[0] : '0'; const color = rest.length > 1 ? rest.slice(1).join(' ') : rest[0]; let newX = x; let newY = y; switch (direction) { case 'top': newY = `-${Math.abs(parseInt(y))}px`; newX = '0'; break; case 'bottom': newY = `${Math.abs(parseInt(y))}px`; newX = '0'; break; case 'left': newX = `-${Math.abs(parseInt(x))}px`; newY = '0'; break; case 'right': newX = `${Math.abs(parseInt(x))}px`; newY = '0'; break; case 'center': newX = '0'; newY = '0'; break; } return `${newX} ${newY} ${blur} ${spread !== '0' ? spread + ' ' : ''}${color}`; } /** * Generates shadow CSS properties */ function generateShadowStyles(options = {}) { const { elevation = 'md', softness = 'soft', direction = 'center', color } = options; let shadowValue = resolveShadowSize(elevation); // Adjust softness shadowValue = adjustShadowSoftness(shadowValue, softness); // Apply custom color if provided if (color) { shadowValue = shadowValue.replace(/rgba\(\d+,\s*\d+,\s*\d+,\s*[\d.]+\)/g, color); } // Apply direction shadowValue = generateDirectionalShadow(shadowValue, direction); return { boxShadow: shadowValue, transition: 'box-shadow 0.3s ease' }; } /** * Generates shadow CSS class name based on options */ function generateShadowClassName(options = {}) { const { elevation = 'md', softness = 'soft', direction = 'center' } = options; let className = `shadow-${elevation}-${softness}`; if (direction !== 'center') { className += `-${direction}`; } return className; } /** * Creates CSS variables for shadow configuration */ function createShadowCSSVariables(config) { return { '--shadow-sm': config.shadow.elevation.sm, '--shadow-md': config.shadow.elevation.md, '--shadow-lg': config.shadow.elevation.lg, '--shadow-xl': config.shadow.elevation.xl, '--shadow-xxl': config.shadow.elevation.xxl, '--shadow-soft': config.shadow.soft, '--shadow-medium': config.shadow.medium, '--shadow-hard': config.shadow.hard }; } /** * Creates layered shadow effect */ function createLayeredShadowStyles(layers) { const shadows = layers.map(layer => { const styles = generateShadowStyles(layer); return styles.boxShadow; }).join(', '); return { boxShadow: shadows, transition: 'box-shadow 0.3s ease' }; } /** * Creates hover shadow effect with elevation change */ function createHoverShadowStyles(normalOptions, hoverElevationIncrease = 1) { const normal = generateShadowStyles(normalOptions); // Increase elevation for hover const elevationMap = { sm: 'md', md: 'lg', lg: 'xl', xl: 'xxl', xxl: 'xxl' }; const currentElevation = normalOptions.elevation || 'md'; const hoverElevation = elevationMap[currentElevation] || currentElevation; const hover = generateShadowStyles({ ...normalOptions, elevation: hoverElevation }); return { normal, hover }; } /** * Creates animated shadow with floating effect */ function createFloatingShadowStyles(options) { const baseStyles = generateShadowStyles(options); const { floatHeight = '4px', animationDuration = '3s' } = options; return { ...baseStyles, animation: `float ${animationDuration} ease-in-out infinite`, // Transform would be handled by keyframes '--float-height': floatHeight }; } /** * Creates card-style shadow with multiple layers */ function createCardShadowStyles(elevation = 'md', interactive = false) { const baseShadow = generateShadowStyles({ elevation, softness: 'soft' }); if (!interactive) { return baseShadow; } // Add subtle ambient shadow for interactive cards const ambientShadow = generateShadowStyles({ elevation: 'sm', softness: 'soft', color: 'rgba(0, 0, 0, 0.05)' }); return { boxShadow: `${baseShadow.boxShadow}, ${ambientShadow.boxShadow}`, transition: 'box-shadow 0.3s ease, transform 0.3s ease' }; } /** * Creates inset shadow effect */ function createInsetShadowStyles(options = {}) { const shadowStyles = generateShadowStyles(options); const insetShadow = `inset ${shadowStyles.boxShadow}`; return { boxShadow: insetShadow, transition: 'box-shadow 0.3s ease' }; } /** * Validates shadow style options */ function validateShadowOptions(options) { const errors = []; if (options.elevation && !['sm', 'md', 'lg', 'xl', 'xxl'].includes(options.elevation)) { errors.push('Elevation must be one of: sm, md, lg, xl, xxl'); } if (options.softness && !['soft', 'medium', 'hard'].includes(options.softness)) { errors.push('Softness must be one of: soft, medium, hard'); } if (options.direction && !['top', 'bottom', 'left', 'right', 'center'].includes(options.direction)) { errors.push('Direction must be one of: top, bottom, left, right, center'); } return { isValid: errors.length === 0, errors }; } /** * Creates responsive shadow styles */ function createResponsiveShadowStyles(breakpoints) { const responsiveStyles = {}; Object.entries(breakpoints).forEach(([breakpoint, options]) => { responsiveStyles[breakpoint] = generateShadowStyles(options); }); return responsiveStyles; } /** * Default configuration loader */ let defaultConfig = null; /** * Loads the default configuration */ function loadDefaultConfig() { if (defaultConfig) { return defaultConfig; } try { // Try to load from aesthetic.config.js defaultConfig = require('../../aesthetic.config.js'); } catch (error) { // Fallback to built-in default configuration defaultConfig = { blur: { sm: "8px", md: "15px", lg: "25px", xl: "40px", default: "15px", heavy: "50px" }, shadow: { soft: "0 4px 12px rgba(0, 0, 0, 0.1)", medium: "0 8px 24px rgba(0, 0, 0, 0.15)", hard: "0 12px 36px rgba(0, 0, 0, 0.25)", elevation: { sm: "0 1px 3px rgba(0, 0, 0, 0.1)", md: "0 4px 12px rgba(0, 0, 0, 0.15)", lg: "0 8px 24px rgba(0, 0, 0, 0.2)", xl: "0 16px 48px rgba(0, 0, 0, 0.25)", xxl: "0 32px 64px rgba(0, 0, 0, 0.3)" } }, glow: { primary: "0 0 15px #3b82f6", secondary: "0 0 15px #8b5cf6", accent: "0 0 15px #f59e0b", neon: "0 0 25px #00ff88", subtle: "0 0 10px rgba(59, 130, 246, 0.3)", medium: "0 0 20px rgba(59, 130, 246, 0.5)", strong: "0 0 30px rgba(59, 130, 246, 0.7)" }, neumorphic: { baseColor: "#e0e5ec", lightSource: "145deg", darkShadow: "rgba(163, 177, 198, 0.6)", lightShadow: "rgba(255, 255, 255, 0.8)", depth: { sm: "2px 2px 4px", md: "4px 4px 8px", lg: "8px 8px 16px", xl: "12px 12px 24px" } }, glassmorphic: { background: "rgba(255, 255, 255, 0.1)", borderOpacity: 0.2, backdropBlur: "15px", variants: { light: "rgba(255, 255, 255, 0.1)", dark: "rgba(0, 0, 0, 0.1)", primary: "rgba(59, 130, 246, 0.1)", secondary: "rgba(139, 92, 246, 0.1)" } }, borderRadius: { sm: "4px", md: "8px", lg: "12px", xl: "16px", full: "9999px" }, colors: { primary: { 50: "#eff6ff", 500: "#3b82f6", 600: "#2563eb", 900: "#1e3a8a" }, secondary: { 50: "#f5f3ff", 500: "#8b5cf6", 600: "#7c3aed", 900: "#581c87" }, accent: { 50: "#fffbeb", 500: "#f59e0b", 600: "#d97706", 900: "#92400e" } } }; } return defaultConfig; } /** * Configuration manager class */ class AestheticConfigManager { constructor(customConfig) { this.cssVariablesApplied = false; this.config = this.mergeConfig(customConfig); } /** * Merges custom configuration with defaults */ mergeConfig(customConfig) { const defaultConfig = loadDefaultConfig(); if (!customConfig) { return { ...defaultConfig }; } return { blur: { ...defaultConfig.blur, ...customConfig.blur }, shadow: { ...defaultConfig.shadow, ...customConfig.shadow, elevation: { ...defaultConfig.shadow.elevation, ...customConfig.shadow?.elevation } }, glow: { ...defaultConfig.glow, ...customConfig.glow }, neumorphic: { ...defaultConfig.neumorphic, ...customConfig.neumorphic, depth: { ...defaultConfig.neumorphic.depth, ...customConfig.neumorphic?.depth } }, glassmorphic: { ...defaultConfig.glassmorphic, ...customConfig.glassmorphic, variants: { ...defaultConfig.glassmorphic.variants, ...customConfig.glassmorphic?.variants } }, borderRadius: { ...defaultConfig.borderRadius, ...customConfig.borderRadius }, colors: { ...defaultConfig.colors, ...customConfig.colors, primary: { ...defaultConfig.colors.primary, ...customConfig.colors?.primary }, secondary: { ...defaultConfig.colors.secondary, ...customConfig.colors?.secondary }, accent: { ...defaultConfig.colors.accent, ...customConfig.colors?.accent } } }; } /** * Gets the current configuration */ getConfig() { return { ...this.config }; } /** * Updates the configuration */ updateConfig(updates) { this.config = this.mergeConfig(updates); if (this.cssVariablesApplied) { this.applyCSSVariables(); } } /** * Applies configuration as CSS custom properties */ applyCSSVariables(rootElement) { if (typeof document === 'undefined') { // Server-side rendering support return; } const root = rootElement || document.documentElement; const config = this.config; // Apply blur variables root.style.setProperty('--aesthetic-blur-sm', config.blur.sm); root.style.setProperty('--aesthetic-blur-md', config.blur.md); root.style.setProperty('--aesthetic-blur-lg', config.blur.lg); root.style.setProperty('--aesthetic-blur-xl', config.blur.xl); root.style.setProperty('--aesthetic-blur-default', config.blur.default); root.style.setProperty('--aesthetic-blur-heavy', config.blur.heavy); // Apply shadow variables root.style.setProperty('--aesthetic-shadow-soft', config.shadow.soft); root.style.setProperty('--aesthetic-shadow-medium', config.shadow.medium); root.style.setProperty('--aesthetic-shadow-hard', config.shadow.hard); root.style.setProperty('--aesthetic-shadow-sm', config.shadow.elevation.sm); root.style.setProperty('--aesthetic-shadow-md', config.shadow.elevation.md); root.style.setProperty('--aesthetic-shadow-lg', config.shadow.elevation.lg); root.style.setProperty('--aesthetic-shadow-xl', config.shadow.elevation.xl); root.style.setProperty('--aesthetic-shadow-xxl', config.shadow.elevation.xxl); // Apply glow variables root.style.setProperty('--aesthetic-glow-primary', config.glow.primary); root.style.setProperty('--aesthetic-glow-secondary', config.glow.secondary); root.style.setProperty('--aesthetic-glow-accent', config.glow.accent); root.style.setProperty('--aesthetic-glow-neon', config.glow.neon); root.style.setProperty('--aesthetic-glow-subtle', config.glow.subtle); root.style.setProperty('--aesthetic-glow-medium', config.glow.medium); root.style.setProperty('--aesthetic-glow-strong', config.glow.strong); // Apply neumorphic variables root.style.setProperty('--aesthetic-neuro-base', config.neumorphic.baseColor); root.style.setProperty('--aesthetic-neuro-light-source', config.neumorphic.lightSource); root.style.setProperty('--aesthetic-neuro-dark-shadow', config.neumorphic.darkShadow); root.style.setProperty('--aesthetic-neuro-light-shadow', config.neumorphic.lightShadow); root.style.setProperty('--aesthetic-neuro-depth-sm', config.neumorphic.depth.sm); root.style.setProperty('--aesthetic-neuro-depth-md', config.neumorphic.depth.md); root.style.setProperty('--aesthetic-neuro-depth-lg', config.neumorphic.depth.lg); root.style.setProperty('--aesthetic-neuro-depth-xl', config.neumorphic.depth.xl); // Apply glassmorphic variables root.style.setProperty('--aesthetic-glass-background', config.glassmorphic.background); root.style.setProperty('--aesthetic-glass-border-opacity', config.glassmorphic.borderOpacity.toString()); root.style.setProperty('--aesthetic-glass-backdrop-blur', config.glassmorphic.backdropBlur); root.style.setProperty('--aesthetic-glass-light', config.glassmorphic.variants.light); root.style.setProperty('--aesthetic-glass-dark', config.glassmorphic.variants.dark); root.style.setProperty('--aesthetic-glass-primary', config.glassmorphic.variants.primary); root.style.setProperty('--aesthetic-glass-secondary', config.glassmorphic.variants.secondary); // Apply border radius variables root.style.setProperty('--aesthetic-radius-sm', config.borderRadius.sm); root.style.setProperty('--aesthetic-radius-md', config.borderRadius.md); root.style.setProperty('--aesthetic-radius-lg', config.borderRadius.lg); root.style.setProperty('--aesthetic-radius-xl', config.borderRadius.xl); root.style.setProperty('--aesthetic-radius-full', config.borderRadius.full); // Apply color variables root.style.setProperty('--aesthetic-primary-50', config.colors.primary[50]); root.style.setProperty('--aesthetic-primary-500', config.colors.primary[500]); root.style.setProperty('--aesthetic-primary-600', config.colors.primary[600]); root.style.setProperty('--aesthetic-primary-900', config.colors.primary[900]); root.style.setProperty('--aesthetic-secondary-50', config.colors.secondary[50]); root.style.setProperty('--aesthetic-secondary-500', config.colors.secondary[500]); root.style.setProperty('--aesthetic-secondary-600', config.colors.secondary[600]); root.style.setProperty('--aesthetic-secondary-900', config.colors.secondary[900]); root.style.setProperty('--aesthetic-accent-50', config.colors.accent[50]); root.style.setProperty('--aesthetic-accent-500', config.colors.accent[500]); root.style.setProperty('--aesthetic-accent-600', config.colors.accent[600]); root.style.setProperty('--aesthetic-accent-900', config.colors.accent[900]); this.cssVariablesApplied = true; } /** * Generates CSS string with all utility classes */ generateCSS() { const config = this.config; const classes = []; // Add CSS variables classes.push(`:root {`); // Blur variables classes.push(` --aesthetic-blur-sm: ${config.blur.sm};`); classes.push(` --aesthetic-blur-md: ${config.blur.md};`); classes.push(` --aesthetic-blur-lg: ${config.blur.lg};`); classes.push(` --aesthetic-blur-xl: ${config.blur.xl};`); // Shadow variables classes.push(` --aesthetic-shadow-sm: ${config.shadow.elevation.sm};`); classes.push(` --aesthetic-shadow-md: ${config.shadow.elevation.md};`); classes.push(` --aesthetic-shadow-lg: ${config.shadow.elevation.lg};`); classes.push(` --aesthetic-shadow-xl: ${config.shadow.elevation.xl};`); classes.push(` --aesthetic-shadow-xxl: ${config.shadow.elevation.xxl};`); // Glow variables classes.push(` --aesthetic-glow-subtle: ${config.glow.subtle};`); classes.push(` --aesthetic-glow-medium: ${config.glow.medium};`); classes.push(` --aesthetic-glow-strong: ${config.glow.strong};`); // Neumorphic variables classes.push(` --aesthetic-neuro-base: ${config.neumorphic.baseColor};`); classes.push(` --aesthetic-neuro-depth-sm: ${config.neumorphic.depth.sm};`); classes.push(` --aesthetic-neuro-depth-md: ${config.neumorphic.depth.md};`); classes.push(` --aesthetic-neuro-depth-lg: ${config.neumorphic.depth.lg};`); classes.push(` --aesthetic-neuro-depth-xl: ${config.neumorphic.depth.xl};`); classes.push(`}`); return classes.join('\n'); } /** * Validates the configuration */ validate() { const errors = []; const config = this.config; // Validate blur values Object.entries(config.blur).forEach(([key, value]) => { if (!value.endsWith('px')) { errors.push(`Blur ${key} must be a pixel value`); } }); // Validate border radius values Object.entries(config.borderRadius).forEach(([key, value]) => { if (!value.endsWith('px') && value !== '9999px') { errors.push(`Border radius ${key} must be a pixel value`); } }); // Validate opacity if (config.glassmorphic.borderOpacity < 0 || config.glassmorphic.borderOpacity > 1) { errors.push('Glassmorphic border opacity must be between 0 and 1'); } return { isValid: errors.length === 0, errors }; } /** * Resets configuration to defaults */ reset() { this.config = loadDefaultConfig(); if (this.cssVariablesApplied) { this.applyCSSVariables(); } } /** * Exports configuration as JSON */ export() { return JSON.stringify(this.config, null, 2); } /** * Imports configuration from JSON */ import(jsonConfig) { try { const parsedConfig = JSON.parse(jsonConfig); this.updateConfig(parsedConfig); } catch (error) { throw new Error('Invalid JSON configuration'); } } } /** * Global configuration manager instance */ let globalConfigManager = null; /** * Gets or creates the global configuration manager */ function getGlobalConfig() { if (!globalConfigManager) { globalConfigManager = new AestheticConfigManager(); } return globalConfigManager; } /** * Sets up the global configuration */ function setupGlobalConfig(customConfig) { globalConfigManager = new AestheticConfigManager(customConfig); return globalConfigManager; } /** * Auto-initialization function (runs when imported) */ function autoInit() { if (typeof window !== 'undefined' && !globalConfigManager) { // Auto-initialize in browser environment globalConfigManager = new AestheticConfigManager(); globalConfigManager.applyCSSVariables(); } } var config = /*#__PURE__*/Object.freeze({ __proto__: null, AestheticConfigManager: AestheticConfigManager, autoInit: autoInit, getGlobalConfig: getGlobalConfig, setupGlobalConfig: setupGlobalConfig }); // Core utility exports /** * Creates a new aesthetic configuration by merging with defaults */ function createAestheticConfig(customConfig = {}) { const defaultConfig = require('../../aesthetic.config.js'); return { ...defaultConfig, ...customConfig, // Deep merge nested objects blur: { ...defaultConfig.blur, ...customConfig.blur }, shadow: { ...defaultConfig.shadow, ...customConfig.shadow, elevation: { ...defaultConfig.shadow.elevation, ...customConfig.shadow?.elevation } }, glow: { ...defaultConfig.glow, ...customConfig.glow }, neumorphic: { ...defaultConfig.neumorphic, ...customConfig.neumorphic, depth: { ...defaultConfig.neumorphic.depth, ...customConfig.neumorphic?.depth } }, glassmorphic: { ...defaultConfig.glassmorphic, ...customConfig.glassmorphic, variants: { ...defaultConfig.glassmorphic.variants, ...customConfig.glassmorphic?.variants } }, borderRadius: { ...defaultConfig.borderRadius, ...customConfig.borderRadius }, colors: { ...defaultConfig.colors, ...customConfig.colors, primary: { ...defaultConfig.colors.primary, ...customConfig.colors?.primary }, secondary: { ...defaultConfig.colors.secondary, ...customConfig.colors?.secondary }, accent: { ...defaultConfig.colors.accent, ...customConfig.colors?.accent } } }; } /** * Applies aesthetic tokens to CSS custom properties */ function applyAestheticTokens(config, rootElement) { const root = rootElement || document.documentElement; // Apply blur tokens root.style.setProperty('--aesthetic-blur-sm', config.blur.sm); root.style.setProperty('--aesthetic-blur-md', config.blur.md); root.style.setProperty('--aesthetic-blur-lg', config.blur.lg); root.style.setProperty('--aesthetic-blur-xl', config.blur.xl); root.style.setProperty('--aesthetic-blur-default', config.blur.default); root.style.setProperty('--aesthetic-blur-heavy', config.blur.heavy); // Apply shadow tokens root.style.setProperty('--aesthetic-shadow-soft', config.shadow.soft); root.style.setProperty('--aesthetic-shadow-medium', config.shadow.medium); root.style.setProperty('--aesthetic-shadow-hard', config.shadow.hard); root.style.setProperty('--aesthetic-shadow-sm', config.shadow.elevation.sm); root.style.setProperty('--aesthetic-shadow-md', config.shadow.elevation.md); root.style.setProperty('--aesthetic-shadow-lg', config.shadow.elevation.lg); root.style.setProperty('--aesthetic-shadow-xl', config.shadow.elevation.xl); root.style.setProperty('--aesthetic-shadow-xxl', config.shadow.elevation.xxl); // Apply glow tokens root.style.setProperty('--aesthetic-glow-primary', config.glow.primary); root.style.setProperty('--aesthetic-glow-secondary', config.glow.secondary); root.style.setProperty('--aesthetic-glow-accent', config.glow.accent); root.style.setProperty('--aesthetic-glow-neon', config.glow.neon); root.style.setProperty('--aesthetic-glow-subtle', config.glow.subtle); root.style.setProperty('--aesthetic-glow-medium', config.glow.medium); root.style.setProperty('--aesthetic-glow-strong', config.glow.strong); // Apply neumorphic tokens root.style.setProperty('--aesthetic-neuro-base', config.neumorphic.baseColor); root.style.setProperty('--aesthetic-neuro-light-source', config.neumorphic.lightSource); root.style.setProperty('--aesthetic-neuro-dark-shadow', config.neumorphic.darkShadow); root.style.setProperty('--aesthetic-neuro-light-shadow', config.neumorphic.lightShadow); root.style.setProperty('--aesthetic-neuro-depth-sm', config.neumorphic.depth.sm); root.style.setProperty('--aesthetic-neuro-depth-md', config.neumorphic.depth.md); root.style.setProperty('--aesthetic-neuro-depth-lg', config.neumorphic.depth.lg); root.style.setProperty('--aesthetic-neuro-depth-xl', config.neumorphic.depth.xl); // Apply glassmorphic tokens root.style.setProperty('--aesthetic-glass-background', config.glassmorphic.background); root.style.setProperty('--aesthetic-glass-border-opacity', config.glassmorphic.borderOpacity.toString()); root.style.setProperty('--aesthetic-glass-backdrop-blur', config.glassmorphic.backdropBlur); root.style.setProperty('--aesthetic-glass-light', config.glassmorphic.variants.light); root.style.setProperty('--aesthetic-glass-dark', config.glassmorphic.variants.dark); root.style.setProperty('--aesthetic-glass-primary', config.glassmorphic.variants.primary); root.style.setProperty('--aesthetic-glass-secondary', config.glassmorphic.variants.secondary); // Apply border radius tokens root.style.setProperty('--aesthetic-radius-sm', config.borderRadius.sm); root.style.setProperty('--aesthetic-radius-md', config.borderRadius.md); root.style.setProperty('--aesthetic-radius-lg', config.borderRadius.lg); root.style.setProperty('--aesthetic-radius-xl', config.borderRadius.xl); root.style.setProperty('--aesthetic-radius-full', config.borderRadius.full); // Apply color tokens root.style.setProperty('--aesthetic-primary-50', config.colors.primary[50]); root.style.setProperty('--aesthetic-primary-500', config.colors.primary[500]); root.style.setProperty('--aesthetic-primary-600', config.colors.primary[600]); root.style.setProperty('--aesthetic-primary-900', config.colors.primary[900]); root.style.setProperty('--aesthetic-secondary-50', config.colors.secondary[50]); root.style.setProperty('--aesthetic-secondary-500', config.colors.secondary[500]); root.style.setProperty('--aesthetic-secondary-600', config.colors.secondary[600]); root.style.setProperty('--aesthetic-secondary-900', config.colors.secondary[900]); root.style.setProperty('--aesthetic-accent-50', config.colors.accent[50]); root.style.setProperty('--aesthetic-accent-500', config.colors.accent[500]); root.style.setProperty('--aesthetic-accent-600', config.colors.accent[600]); root.style.setProperty('--aesthetic-accent-900', config.colors.accent[900]); } /** * Generates all CSS utility classes based on configuration */ function generateAllCSSClasses(config) { const classes = []; // Generate glass classes ['sm', 'md', 'lg', 'xl'].forEach(size => { classes.push(` .glass-${size} { backdrop-filter: blur(var(--aesthetic-blur-${size})); -webkit-backdrop-filter: blur(var(--aesthetic-blur-${size})); background: var(--aesthetic-glass-background); border: 1px solid rgba(255, 255, 255, var(--aesthetic-glass-border-opacity)); border-radius: var(--aesthetic-radius-md); } `.trim()); }); // Generate neumorphic classes ['flat', 'concave', 'convex'].forEach(shape => { ['sm', 'md', 'lg', 'xl'].forEach(depth => { const shadowType = shape === 'concave' ? 'inset ' : shape === 'convex' ? '' : ''; classes.push(` .neuro-${shape}-${depth} { background: var(--aesthetic-neuro-base); border-radius: var(--aesthetic-radius-md); box-shadow: ${shadowType}var(--aesthetic-neuro-depth-${depth}) var(--aesthetic-neuro-dark-shadow), ${shadowType === 'inset ' ? 'inset ' : ''}-var(--aesthetic-neuro-depth-${depth}) var(--aesthetic-neuro-light-shadow); } `.trim()); }); }); // Generate glow classes ['subtle', 'medium', 'strong', 'neon'].forEach(intensity => { classes.push(` .glow-${intensity} { box-shadow: var(--aesthetic-glow-${intensity}); transition: box-shadow 0.3s ease-in-out; } `.trim()); }); // Generate shadow classes ['sm', 'md', 'lg', 'xl', 'xxl'].forEach(size => { ['soft', 'medium', 'hard'].forEach(type => { classes.push(` .shadow-${size}-${type} { box-shadow: var(--aesthetic-shadow-${size}); transition: box-shadow 0.3s ease; } `.trim()); }); }); return classes.join('\n\n'); } /** * Validates aesthetic configuration */ function validateAestheticConfig(config) { const errors = []; // Validate blur values if (config.blur) { Object.entries(config.blur).forEach(([key, value]) => { if (typeof value !== 'string' || !value.endsWith('px')) { errors.push(`Blur ${key} must be a pixel value (e.g., "15px")`); } }); } // Validate colors if (config.colors) { Object.entries(config.colors).forEach(([colorName, shades]) => { if (typeof shades === 'object') { Object.entries(shades).forEach(([shade, color]) => { if (typeof color !== 'string' || !isValidCSSColor(color)) { errors.push(`Color ${colorName}.${shade} must be a valid CSS color`); } }); } }); } return { isValid: errors.length === 0, errors }; } /** * Utility function to validate CSS color */ function isValidCSSColor(color) { const colorRegex = /^(#[0-9A-F]{6}|#[0-9A-F]{3}|rgb\(|rgba\(|hsl\(|hsla\()/i; return colorRegex.test(color); } // Core utilities and configuration // Auto-initialize in browser environment if (typeof window !== 'undefined') { Promise.resolve().then(function () { return config; }).then(({ autoInit }) => { autoInit(); }); } // CSS import (users can import this separately) // import './css/index.css'; export { AestheticConfigManager, adjustShadowSoftness, applyAestheticTokens, autoInit, colorToRgba, createAdaptiveNeumorphicStyles, createAestheticConfig, createAnimatedGlassStyles, createAnimatedGlowStyles, createCardShadowStyles, createFloatingShadowStyles, createGlassCSSVariables, createGlowCSSVariables, createGlowHoverStyles, createHoverShadowStyles, createInsetShadowStyles, createLayeredGlowStyles, createLayeredShadowStyles, createNeonGlowStyles, createNeumorphicButtonStates, createNeumorphicCSSVariables, createNeumorphicInputStyles, createResponsiveGlassStyles, createResponsiveShadowStyles, createShadowCSSVariables, createTextGlowStyles, generateAllCSSClasses, generateDirectionalShadow, generateGlassClassName, generateGlassStyles, generateGlowClassName, generateGlowStyles, generateNeumorphicClassName, generateNeumorphicShadow