UNPKG

aura-glass

Version:

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

443 lines (440 loc) 14.2 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { forwardRef, useRef, useState, useEffect, useCallback } from 'react'; import { useReducedMotion } from '../../hooks/useReducedMotion.js'; import { cn } from '../../lib/utilsComprehensive.js'; 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 { MotionFramer } from '../../primitives/motion/MotionFramer.js'; import { useA11yId, createButtonA11y } from '../../utils/a11y.js'; import { usePredictiveEngine, useInteractionRecorder } from '../advanced/GlassPredictiveEngine.js'; import { useAchievements } from '../advanced/GlassAchievementSystem.js'; import { useBiometricAdaptation } from '../advanced/GlassBiometricAdaptation.js'; import { useEyeTracking } from '../advanced/GlassEyeTracking.js'; import { useSpatialAudio } from '../advanced/GlassSpatialAudio.js'; // Get size classes const getSizeClasses = (size, variant) => { const isExtended = variant === "extended"; switch (size) { case "small": return { width: isExtended ? "w-auto min-w-20" : "w-10", height: "h-10", padding: isExtended ? "px-3 py-2" : "p-0", fontSize: "glass-text-xl" }; case "large": return { width: isExtended ? "w-auto min-w-32" : "w-16", height: "h-16", padding: isExtended ? "px-5 py-3" : "p-0", fontSize: "text-3xl" }; default: // medium return { width: isExtended ? "w-auto min-w-28" : "w-14", height: "h-14", padding: isExtended ? "px-4 py-2.5" : "p-0", fontSize: "glass-text-2xl" }; } }; // Get position classes const getPositionClasses = position => { switch (position) { case "bottomRight": return "fixed bottom-4 right-4"; case "bottomLeft": return "fixed bottom-4 left-4"; case "topRight": return "fixed top-4 right-4"; case "topLeft": return "fixed top-4 left-4"; case "center": return "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2"; case "none": default: return ""; } }; // Get color classes for variants const getColorClasses = (color, variant) => { if (variant === "glass") { return "glass-text-primary bg-white/10 glass-glass-backdrop-blur-md border border-white/20"; } switch (color) { case "primary": return "bg-primary-500 glass-text-primary hover:bg-primary-600"; case "secondary": return "bg-secondary-500 glass-text-primary hover:bg-secondary-600"; case "success": return "bg-success-500 glass-text-primary hover:bg-success-600"; case "error": return "bg-danger-500 glass-text-primary hover:bg-danger-600"; case "warning": return "bg-warning-500 glass-text-primary hover:bg-warning-600"; case "info": return "bg-info-500 glass-text-primary hover:bg-info-600"; default: return "bg-gray-700 glass-text-primary hover:bg-gray-600"; } }; // Get pulse animation classes const getPulseClasses = (pulse, color) => { if (!pulse) return ""; const baseClasses = "animate-pulse-ring"; switch (color) { case "primary": return `${baseClasses} ring-primary-400`; case "secondary": return `${baseClasses} ring-secondary-400`; case "success": return `${baseClasses} ring-success-400`; case "error": return `${baseClasses} ring-danger-400`; case "warning": return `${baseClasses} ring-warning-400`; case "info": return `${baseClasses} ring-info-400`; default: return `${baseClasses} ring-gray-400`; } }; // Get variant-specific glass props const getGlassVariantProps = (variant, enhanced) => { if (variant === "glass") { return { variant: "frosted", intensity: enhanced ? "ultra" : "strong", border: "glow", lighting: "volumetric", caustics: enhanced, refraction: enhanced }; } return { variant: "clear", intensity: "medium", border: "subtle", lighting: "ambient" }; }; // Tooltip component const TooltipComponent = ({ tooltip, position, show }) => { const getTooltipPosition = position => { if (position === "bottomRight" || position === "bottomLeft") { return "absolute -top-8 left-1/2 -translate-x-1/2"; } if (position === "topRight" || position === "topLeft") { return "absolute -bottom-8 left-1/2 -translate-x-1/2"; } return "absolute -top-8 left-1/2 -translate-x-1/2"; }; return jsx("span", { "data-glass-component": true, className: cn("bg-gray-900/90 glass-text-primary px-2 py-1 glass-radius-md glass-text-xs whitespace-nowrap", "pointer-events-none z-50 transition-opacity duration-200", getTooltipPosition(position), show ? "opacity-100 visible" : "opacity-0 invisible"), children: tooltip }); }; // Wrapper component to handle tooltip const FabWrapper = ({ position, children, className }) => { return jsx("div", { className: cn(position === "none" ? "relative" : "static", "inline-block", className), children: children }); }; /** * Fab Component * * A floating action button (FAB) performs the primary action in an application. */ const Fab = /*#__PURE__*/forwardRef((props, ref) => { useReducedMotion(); const { children, color = "primary", disabled = false, href, size = "medium", variant = "standard", onClick, position = "bottomRight", tooltip, pulse = false, className, enhanced = false, zIndex = 1050, type = "button", isVisible = true, animationConfig, disableAnimation, style, intent = "primary", elevation = "level4", tier = "high", description, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "aria-pressed": ariaPressed, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, "aria-haspopup": ariaHaspopup, // Consciousness features predictive = false, preloadContent = false, eyeTracking = false, gazeResponsive = false, adaptive = false, biometricResponsive = false, spatialAudio = false, audioFeedback = false, trackAchievements = false, achievementId, usageContext = "fab", ...rest } = props; const fabRef = useRef(null); const [isHovered, setIsHovered] = useState(false); const [clickCount, setClickCount] = useState(0); const [shouldRender, setShouldRender] = useState(isVisible); // Consciousness feature hooks - only initialize if features are enabled predictive ? usePredictiveEngine() : null; const eyeTracker = eyeTracking ? useEyeTracking() : null; adaptive ? useBiometricAdaptation() : null; const spatialAudioEngine = spatialAudio ? useSpatialAudio() : null; const achievementTracker = trackAchievements ? useAchievements() : null; const interactionRecorder = predictive || trackAchievements ? useInteractionRecorder(`glass-fab-${variant}-${usageContext}`) : null; // Generate unique ID for accessibility const componentId = useA11yId("glass-fab"); const descriptionId = description ? useA11yId("glass-fab-desc") : undefined; // Handle visibility changes useEffect(() => { if (isVisible) { setShouldRender(true); } else { // Delay hiding to allow exit animation const timeout = setTimeout(() => setShouldRender(false), 300); return () => clearTimeout(timeout); } }, [isVisible]); // Eye tracking effects useEffect(() => { if (!gazeResponsive || !eyeTracker || !fabRef.current) return; // Note: Eye tracking event handlers not yet implemented // eyeTracker.onGazeEnter?.(fabRef.current, handleGazeEnter); // eyeTracker.onGazeLeave?.(fabRef.current, handleGazeExit); return () => { // Note: Eye tracking cleanup not yet implemented // if (fabRef.current) { // eyeTracker.offGazeEnter?.(fabRef.current, handleGazeEnter); // eyeTracker.offGazeLeave?.(fabRef.current, handleGazeExit); // } }; }, [gazeResponsive, eyeTracker, disabled, spatialAudioEngine, audioFeedback]); // Enhanced interaction tracking const handleInteraction = useCallback(event => { if (disabled) return; setClickCount(prev => prev + 1); // Record interaction for predictive learning if (interactionRecorder) { interactionRecorder.recordClick(event); } // Play spatial audio feedback if (spatialAudioEngine && audioFeedback) { spatialAudioEngine.playGlassSound("fab_click_success", { x: fabRef.current?.offsetLeft || 0, y: fabRef.current?.offsetTop || 0, z: 0 // Default z position }); } // Track achievements if (achievementTracker && trackAchievements) { achievementTracker.recordAction(achievementId || "fab_interaction", { variant, context: usageContext, clickCount, timestamp: Date.now() }); } // Call original onClick handler onClick?.(event); }, [disabled, interactionRecorder, spatialAudioEngine, audioFeedback, achievementTracker, trackAchievements, achievementId, variant, usageContext, clickCount, onClick]); // Create accessibility attributes const a11yProps = createButtonA11y({ id: componentId, label: ariaLabel, description, pressed: ariaPressed, expanded: ariaExpanded, controls: ariaControls, haspopup: ariaHaspopup === "true" ? true : ariaHaspopup === "false" ? false : ariaHaspopup, disabled: disabled, descriptionId }); const sizeClasses = getSizeClasses(size, variant); const positionClasses = getPositionClasses(position); const colorClasses = getColorClasses(color, variant); const pulseClasses = getPulseClasses(pulse, color); const glassVariantProps = getGlassVariantProps(variant, enhanced); const baseClasses = cn( // Base styles "inline-flex items-center justify-center", "font-medium cursor-pointer outline-none", "select-none box-border transition-all duration-200", "will-change-transform", // Size classes sizeClasses.width, sizeClasses.height, sizeClasses.padding, sizeClasses.fontSize, // Position classes positionClasses, // Shape variant === "extended" ? "glass-radius-full" : "glass-radius-full", // Color classes (for non-glass variants) variant !== "glass" && colorClasses, // Pulse classes pulseClasses, // Hover and interaction states !disabled && "hover:scale-105 active:scale-95", // Disabled state disabled && "opacity-50 cursor-not-allowed pointer-events-none", // Visibility animation isVisible ? "opacity-100 scale-100" : "opacity-0 scale-75", // Consciousness feature styles gazeResponsive && isHovered && "ring-2 ring-blue-400/40 shadow-lg shadow-blue-400/20", className); const combinedStyle = { ...style, zIndex, transition: "opacity 0.3s ease-in-out, transform 0.3s ease-in-out" }; const Component = href ? "a" : "button"; const fabButton = jsx(MotionFramer, { preset: "scaleIn", duration: 0.3, animateOnMount: isVisible, animateOnHover: !disabled, className: 'inline-block', children: variant === "glass" ? jsxs(OptimizedGlassCore, { as: href ? "a" : "button", type: href ? undefined : type, ...(href ? { href } : {}), ...(!href ? { disabled } : {}), intent: intent, elevation: elevation, tier: tier, ...glassVariantProps, interactive: true, hoverSheen: true, liftOnHover: true, press: true, className: baseClasses, style: combinedStyle, onClick: handleInteraction, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), ref: node => { if (typeof ref === "function") { ref(node); } else if (ref) { ref.current = node; } if (fabRef.current !== undefined) { fabRef.current = node; } }, ...a11yProps, ...rest, children: [jsx("span", { className: 'relative z-10 glass-focus glass-touch-target glass-contrast-guard', children: children }), description && jsx("span", { id: descriptionId, className: 'sr-only', children: description })] }) : jsxs(Component, { className: baseClasses, style: combinedStyle, href: href, disabled: disabled, onClick: handleInteraction, type: href ? undefined : type, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), ref: node => { if (typeof ref === "function") { ref(node); } else if (ref) { ref.current = node; } if (fabRef.current !== undefined) { fabRef.current = node; } }, ...a11yProps, ...rest, children: [children, description && jsx("span", { id: descriptionId, className: 'sr-only glass-focus glass-touch-target glass-contrast-guard', children: description })] }) }); // --- Conditional Rendering Logic --- if (!shouldRender) { return null; } if (!tooltip) { return fabButton; } return jsxs(FabWrapper, { position: position, children: [fabButton, jsx(TooltipComponent, { tooltip: tooltip, position: position, show: isHovered })] }); }); Fab.displayName = "Fab"; /** * GlassFab Component * * A floating action button with glass morphism styling. */ const GlassFab = /*#__PURE__*/forwardRef((props, ref) => { const { className, variant = "glass", intent = "primary", elevation = "level4", tier = "high", enhanced = true, ...rest } = props; return jsx(Fab, { ref: ref, className: cn("glass-fab", className), variant: variant, intent: intent, elevation: elevation, tier: tier, enhanced: enhanced, ...rest }); }); GlassFab.displayName = "GlassFab"; export { Fab, GlassFab, Fab as default }; //# sourceMappingURL=GlassFab.js.map