UNPKG

aura-glass

Version:

A comprehensive glassmorphism design system for React applications with 142+ production-ready components

371 lines (368 loc) 14 kB
'use client'; import { jsx } from 'react/jsx-runtime'; import { cn } from '../../lib/utilsComprehensive.js'; import { forwardRef, useState, useRef, useImperativeHandle, useEffect, useCallback } from 'react'; import '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import '../../primitives/motion/MotionFramer.js'; import { LiquidGlassMaterial } from '../../primitives/LiquidGlassMaterial.js'; import { useAchievements } from '../advanced/GlassAchievementSystem.js'; import { useBiometricAdaptation } from '../advanced/GlassBiometricAdaptation.js'; import { useEyeTracking } from '../advanced/GlassEyeTracking.js'; import { usePredictiveEngine, useInteractionRecorder } from '../advanced/GlassPredictiveEngine.js'; import { useSpatialAudio } from '../advanced/GlassSpatialAudio.js'; /** * GlassContainer component * Responsive container with glassmorphism styling, flexible sizing, and consciousness interface integration */ const GlassContainer = /*#__PURE__*/forwardRef(({ // TODO: Integrate ContrastGuard for any section titles, labels, and helper text for WCAG AA compliance size = 'lg', centered = true, padding = 'md', responsivePadding, variant = 'default', glass = false, elevation = 'level1', radius = 'none', material = 'glass', materialProps, className, children, // Consciousness features predictive = false, preloadContent = false, eyeTracking = false, gazeResponsive = false, adaptive = false, biometricResponsive = false, spatialAudio = false, audioFeedback = false, trackAchievements = false, achievementId, usageContext = 'main', ...props }, ref) => { const [containerElement, setContainerElement] = useState(null); const localRef = useRef(null); const [isVisible, setIsVisible] = useState(false); // Forward ref to parent useImperativeHandle(ref, () => localRef.current); const [adaptiveSize, setAdaptiveSize] = useState(size); const [adaptivePadding, setAdaptivePadding] = useState(padding); // Consciousness feature hooks - only initialize if features are enabled predictive ? usePredictiveEngine() : null; const eyeTracker = eyeTracking ? useEyeTracking() : null; const biometricAdapter = adaptive ? useBiometricAdaptation() : null; const spatialAudioEngine = spatialAudio ? useSpatialAudio() : null; const achievementTracker = trackAchievements ? useAchievements() : null; const interactionRecorder = predictive || trackAchievements ? useInteractionRecorder(`glass-container-${usageContext}`) : null; // Visibility tracking for predictive preloading useEffect(() => { if (!containerElement || !preloadContent) return; const observer = new IntersectionObserver(([entry]) => { setIsVisible(entry.isIntersecting); if (entry.isIntersecting && interactionRecorder) { // Create synthetic scroll event const syntheticEvent = { currentTarget: { id: `container-${usageContext}` }, type: 'scroll' }; interactionRecorder.recordFocus(syntheticEvent); } }, { threshold: 0.1 }); observer.observe(containerElement); return () => observer.disconnect(); }, [preloadContent, usageContext, interactionRecorder]); // Biometric adaptation effects useEffect(() => { if (!biometricResponsive || !biometricAdapter) return; const adaptContainer = () => { const stressLevel = biometricAdapter.currentStressLevel; // For now, assume desktop capabilities const deviceCapabilities = { isMobile: false, isDesktop: true }; // Adapt size based on device and stress if (stressLevel < 0.3 && deviceCapabilities.isDesktop) { setAdaptiveSize('md'); // Compact size when relaxed on desktop setAdaptivePadding('sm'); // Less padding for efficiency } else { setAdaptiveSize(size); // Use original size setAdaptivePadding(padding); // Use original padding } }; // Initial adaptation adaptContainer(); // Listen for biometric changes const interval = setInterval(adaptContainer, 5000); return () => clearInterval(interval); }, [biometricResponsive, biometricAdapter, size, padding]); // Eye tracking effects useEffect(() => { if (!gazeResponsive || !eyeTracker || !containerElement) return; // Note: Eye tracking event handlers not yet implemented // eyeTracker.onGazeEnter(containerRef.current, handleGazeEnter); // eyeTracker.onGazeExit(containerRef.current, handleGazeExit); return () => { // Note: Eye tracking cleanup not yet implemented // if (containerRef.current) { // eyeTracker.offGazeEnter(containerRef.current, handleGazeEnter); // eyeTracker.offGazeExit(containerRef.current, handleGazeExit); // } }; }, [gazeResponsive, eyeTracker, spatialAudioEngine, audioFeedback, achievementTracker, trackAchievements, usageContext]); // Predictive interaction tracking const handleInteraction = useCallback(event => { if (!interactionRecorder) return; if (event.type === 'click') { interactionRecorder.recordClick(event); } if (achievementTracker && trackAchievements) { achievementTracker.recordAction(achievementId || 'container_interaction', { context: usageContext, timestamp: Date.now() }); } }, [interactionRecorder, achievementTracker, trackAchievements, achievementId, usageContext]); // Filter out component-specific props and consciousness features that shouldn't be passed to DOM const { maxWidth, minWidth, maxHeight, minHeight, // Prevent leaking master toggle to DOM consciousness: _consciousness, predictive: _predictive, preloadContent: _preloadContent, eyeTracking: _eyeTracking, gazeResponsive: _gazeResponsive, adaptive: _adaptive, biometricResponsive: _biometricResponsive, spatialAudio: _spatialAudio, audioFeedback: _audioFeedback, trackAchievements: _trackAchievements, achievementId: _achievementId, usageContext: _usageContext, ...domProps } = props; // Use adaptive values if biometric adaptation is enabled, otherwise use original values const effectiveSize = biometricResponsive ? adaptiveSize : size; const effectivePadding = biometricResponsive ? adaptivePadding : padding; const sizeClasses = { xs: 'max-w-xs', // 320px sm: 'max-w-sm', // 384px md: 'max-w-md', // 448px lg: 'max-w-4xl', // 896px xl: 'max-w-6xl', // 1152px '2xl': 'max-w-7xl', // 1280px full: 'max-w-full' }; const paddingClasses = { none: 'glass-p-0', xs: 'glass-p-2', sm: 'glass-p-4', md: 'glass-p-6', lg: 'glass-p-8', xl: 'glass-p-12', '2xl': 'glass-p-16' }; const variantClasses = { default: '', fluid: 'w-full', breakout: 'w-screen relative left-1/2 right-1/2 -mx-[50vw]' }; // Map elevation to OptimizedGlass elevation values const getGlassElevation = elevation => { if (elevation === 'float') return 'level3'; if (elevation === 'modal') return 'level4'; if (typeof elevation === 'number') { const level = Math.min(5, Math.max(1, elevation + 1)); switch (level) { case 1: return 'level1'; case 2: return 'level2'; case 3: return 'level3'; case 4: return 'level4'; case 5: return 'level5'; default: return 'level1'; } } // Handle string values that aren't the expected literals if (typeof elevation === 'string') { // Try to parse as number const numValue = parseInt(elevation, 10); if (!isNaN(numValue)) { return getGlassElevation(numValue); } // Default for unrecognized strings return 'level1'; } return 'level1'; }; const responsivePaddingClasses = responsivePadding ? [responsivePadding.sm && `sm:${paddingClasses[responsivePadding.sm]}`, responsivePadding.md && `md:${paddingClasses[responsivePadding.md]}`, responsivePadding.lg && `lg:${paddingClasses[responsivePadding.lg]}`, responsivePadding.xl && `xl:${paddingClasses[responsivePadding.xl]}`, responsivePadding['2xl'] && `2xl:${paddingClasses[responsivePadding['2xl']]}`].filter(Boolean) : []; if (glass) { return material === 'liquid' ? jsx(LiquidGlassMaterial, { ior: materialProps?.ior || (elevation === 'modal' ? 1.50 : elevation === 'float' ? 1.48 : 1.45), thickness: materialProps?.thickness || (size === 'xs' ? 6 : size === 'sm' ? 8 : size === 'md' ? 12 : 16), tint: materialProps?.tint || (usageContext === 'modal' ? { r: 0, g: 0, b: 0, a: 0.08 } : { r: 0, g: 0, b: 0, a: 0.05 }), variant: materialProps?.variant || (usageContext === 'modal' ? 'regular' : 'clear'), quality: materialProps?.quality || 'high', environmentAdaptation: true, motionResponsive: true, interactive: usageContext === 'card' || usageContext === 'form', className: cn( // Base container styles 'w-full transition-all duration-300 liquid-glass-container-surface', // Size and centering sizeClasses[effectiveSize], centered && 'mx-auto', // Variant variantClasses[variant], // Padding paddingClasses[effectivePadding], ...responsivePaddingClasses, // Radius radius === 'none' ? 'rounded-none' : radius === 'sm' ? 'glass-radius-sm' : radius === 'md' ? 'glass-radius-md' : radius === 'lg' ? 'glass-radius-lg' : radius === 'xl' ? 'glass-radius-xl' : radius === '2xl' ? 'rounded-2xl' : radius === 'full' ? 'glass-radius-full' : 'glass-radius-lg', // Consciousness feature styles isVisible && preloadContent && 'animate-pulse', biometricResponsive && 'transform-gpu', className), style: { '--liquid-glass-container-density': usageContext === 'modal' ? '0.95' : '0.88', '--liquid-glass-environment-adapt': '0.7' }, "data-liquid-glass-container": "true", "data-container-context": usageContext, "data-container-size": effectiveSize, onClick: handleInteraction, onFocus: handleInteraction, ref: node => { const divNode = node ?? null; setContainerElement(divNode); if (ref) { if (typeof ref === 'function') { ref(divNode); } else if ('current' in ref) { ref.current = divNode; } } }, ...domProps, children: children }) : jsx(OptimizedGlassCore, { intent: "neutral", elevation: getGlassElevation(elevation), intensity: "medium", depth: 2, tint: "neutral", border: "subtle", animation: "none", performanceMode: "medium", className: cn( // Base container styles 'w-full transition-all duration-300', // Size and centering sizeClasses[effectiveSize], centered && 'mx-auto', // Variant variantClasses[variant], // Padding paddingClasses[effectivePadding], ...responsivePaddingClasses, // Radius radius === 'none' ? 'rounded-none' : radius === 'sm' ? 'glass-radius-sm' : radius === 'md' ? 'glass-radius-md' : radius === 'lg' ? 'glass-radius-lg' : radius === 'xl' ? 'glass-radius-xl' : radius === '2xl' ? 'rounded-2xl' : radius === 'full' ? 'glass-radius-full' : 'glass-radius-lg', // Consciousness feature styles // gazeResponsive && eyeTracker?.isGazing && 'ring-2 ring-blue-400/50 shadow-lg shadow-blue-400/25', isVisible && preloadContent && 'animate-pulse', biometricResponsive && 'transform-gpu', // Motion preferences - already handled by consciousness features className), onClick: handleInteraction, onFocus: handleInteraction, ref: node => { setContainerElement(node); if (ref) { if (typeof ref === 'function') { ref(node); } else if ('current' in ref) { ref.current = node; } } }, ...domProps, children: children }); } return jsx("div", { "data-glass-component": true, className: cn( // Base container styles 'w-full transition-all duration-300', // Size and centering sizeClasses[effectiveSize], centered && 'mx-auto', // Variant variantClasses[variant], // Padding paddingClasses[effectivePadding], ...responsivePaddingClasses, // Consciousness feature styles // gazeResponsive && eyeTracker?.isGazing && 'ring-1 ring-blue-400/30 shadow-md shadow-blue-400/10', isVisible && preloadContent && 'animate-pulse opacity-75', biometricResponsive && 'transform-gpu', // Motion preferences - already handled by consciousness features className), onClick: handleInteraction, onFocus: handleInteraction, ref: node => { setContainerElement(node); if (ref) { if (typeof ref === 'function') { ref(node); } else { ref.current = node; } } }, ...domProps, children: children }); }); GlassContainer.displayName = 'GlassContainer'; /** * Enhanced GlassContainer with consciousness features enabled by default * Use this for containers that should be intelligent and adaptive */ const ConsciousGlassContainer = /*#__PURE__*/forwardRef((props, ref) => jsx(GlassContainer, { ref: ref, predictive: true, preloadContent: true, adaptive: true, biometricResponsive: true, trackAchievements: true, achievementId: "conscious_container_usage", ...props })); ConsciousGlassContainer.displayName = 'ConsciousGlassContainer'; export { ConsciousGlassContainer, GlassContainer }; //# sourceMappingURL=GlassContainer.js.map