UNPKG

aura-glass

Version:

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

329 lines (326 loc) 11.6 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { forwardRef, useRef, useState, useImperativeHandle, useEffect, useCallback } from 'react'; 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 { 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'; // Get variant classes const getVariantClasses = (variant, selected, color) => { const baseClasses = "transition-all duration-200 ease-in-out"; switch (variant) { case "primary": return cn(baseClasses, selected ? "bg-primary-500 glass-text-primary border-primary-600 shadow-md" : "bg-transparent text-primary-400 border-primary-300 hover:bg-primary-500/10"); case "secondary": return cn(baseClasses, selected ? "bg-secondary-500 glass-text-primary border-secondary-600 shadow-md" : "bg-transparent text-secondary-400 border-secondary-300 hover:bg-secondary-500/10"); case "outlined": return cn(baseClasses, "border-2", selected ? `bg-${color}-500 glass-text-primary border-${color}-600` : `bg-transparent text-${color}-400 border-${color}-300 hover:bg-${color}-500/10`); default: return cn(baseClasses, selected ? "bg-gray-600 glass-text-primary border-gray-700 shadow-md" : "bg-transparent glass-text-secondary border-gray-500 hover:bg-gray-600/10"); } }; // Get size classes const getSizeClasses = size => { switch (size) { case "sm": return "h-8 px-3 text-sm min-w-16"; case "lg": return "h-12 px-6 text-base min-w-24"; case "md": case "medium": default: return "h-10 px-4 text-sm min-w-20"; } }; // Get group classes const getGroupClasses = (grouped, groupOrientation = "horizontal", isGroupStart = false, isGroupEnd = false) => { if (!grouped) return ""; const classes = []; if (groupOrientation === "horizontal") { if (!isGroupStart) classes.push("rounded-l-none border-l-0 -ml-px"); if (!isGroupEnd) classes.push("rounded-r-none"); } else { if (!isGroupStart) classes.push("rounded-t-none border-t-0 -mt-px"); if (!isGroupEnd) classes.push("rounded-b-none"); } return classes.join(" "); }; /** * ToggleButton Component Implementation */ function ToggleButtonComponent(props, ref) { const { value, selected = false, disabled = false, onChange, children, className, style, glass = false, // Prevent custom props from leaking to DOM glassVariant, blurStrength, color = "default", size = "medium", fullWidth = false, variant = "outlined", // Group props grouped = false, groupOrientation = "horizontal", isGroupStart = false, isGroupEnd = false, // Glass props intent = "neutral", elevation = "level2", tier = "medium", // Accessibility props description, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-describedby": ariaDescribedBy, "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 = "toggle", ...rest } = props; const buttonRef = useRef(null); const [isHovered, setIsHovered] = useState(false); const [clickCount, setClickCount] = useState(0); // 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 { recordInteraction } = usePredictiveEngine(); const interactionRecorder = predictive || trackAchievements ? useInteractionRecorder(`glass-toggle-${variant}-${usageContext}`) : null; // Generate unique ID for accessibility const componentId = useA11yId("glass-toggle"); const descriptionId = description ? useA11yId("glass-toggle-desc") : undefined; // Handle ref forwarding useImperativeHandle(ref, () => buttonRef.current); // Eye tracking effects useEffect(() => { if (!gazeResponsive || !eyeTracker || !buttonRef.current) return; // Eye tracking methods not available in current implementation // eyeTracker.onGazeEnter(buttonRef.current, handleGazeEnter); // eyeTracker.onGazeExit(buttonRef.current, handleGazeExit); return () => { if (buttonRef.current) ; }; }, [gazeResponsive, eyeTracker, disabled, spatialAudioEngine, audioFeedback]); // Enhanced interaction tracking const handleClick = useCallback(event => { if (disabled) return; setClickCount(prev => prev + 1); // Record interaction for predictive learning if (recordInteraction) { recordInteraction({ type: "click", element: "toggle-button", context: { viewport: { width: window.innerWidth, height: window.innerHeight }, timeOfDay: new Date().getHours(), deviceType: window.innerWidth < 768 ? "mobile" : window.innerWidth < 1024 ? "tablet" : "desktop" }, metadata: { action: "toggle-click", selected: !selected } }); } // Play spatial audio feedback if (spatialAudioEngine && audioFeedback) { spatialAudioEngine.playGlassSound("toggle_click", { x: buttonRef.current?.offsetLeft || 0, y: buttonRef.current?.offsetTop || 0, z: 0 }); } // Track achievements if (achievementTracker && trackAchievements) { achievementTracker.recordAction(achievementId || "toggle_interaction", { variant, context: usageContext, selected: !selected, clickCount, timestamp: Date.now() }); } // Call original onChange handler if (onChange && value !== undefined) { onChange(event, value); } }, [disabled, interactionRecorder, spatialAudioEngine, audioFeedback, achievementTracker, trackAchievements, achievementId, variant, usageContext, selected, clickCount, onChange, value]); // Create accessibility attributes const a11yProps = createButtonA11y({ id: componentId, label: ariaLabel, description, pressed: selected, expanded: typeof ariaExpanded === "boolean" ? ariaExpanded : ariaExpanded === "true" ? true : ariaExpanded === "false" ? false : undefined, controls: ariaControls, haspopup: ariaHaspopup === "false" ? false : ariaHaspopup === "true" ? true : ariaHaspopup, disabled: disabled, descriptionId }); const variantClasses = getVariantClasses(variant, selected, color); const sizeClasses = getSizeClasses(size); const groupClasses = getGroupClasses(grouped, groupOrientation, isGroupStart, isGroupEnd); const baseClasses = cn( // Base styles "inline-flex items-center justify-center relative", "box-border outline-none border-0 m-0", "select-none align-middle appearance-none no-underline", "font-medium leading-7", "glass-radius-md border", // Size classes sizeClasses, // Variant classes variantClasses, // Group classes groupClasses, // Full width fullWidth && "w-full", // Disabled state disabled && "cursor-default pointer-events-none opacity-50", !disabled && "cursor-pointer glass-focus glass-touch-target", // Consciousness feature styles gazeResponsive && isHovered /* || (eyeTracker?.isGazing && !disabled) */ && "ring-2 ring-blue-400/40", className); const combinedStyle = { ...style }; if (glass) { return jsx(MotionFramer, { "data-glass-component": true, preset: "scaleIn", animateOnHover: true, duration: 0.2, className: 'inline-block', children: jsxs(OptimizedGlassCore, { ref: node => { if (ref) { if (typeof ref === "function") { ref(node); } else { ref.current = node; } } if (buttonRef.current !== undefined) { buttonRef.current = node; } }, as: "button", intent: intent, elevation: elevation, tier: tier, variant: "frosted", intensity: "medium", border: "subtle", interactive: true, hoverSheen: true, liftOnHover: true, press: true, className: baseClasses, style: combinedStyle, type: "button", disabled: disabled, onClick: handleClick, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), ...a11yProps, ...rest, children: [jsx("span", { className: 'relative z-10', children: children }), description && jsx("span", { id: descriptionId, className: 'sr-only', children: description })] }) }); } return jsx(MotionFramer, { preset: "scaleIn", animateOnHover: true, duration: 0.2, className: 'inline-block', children: jsxs("button", { ref: node => { if (ref) { if (typeof ref === "function") { ref(node); } else { ref.current = node; } } if (buttonRef.current !== undefined) { buttonRef.current = node; } }, className: baseClasses, style: combinedStyle, type: "button", disabled: disabled, onClick: handleClick, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), ...a11yProps, ...rest, children: [children, description && jsx("span", { id: descriptionId, className: 'sr-only', children: description })] }) }); } /** * ToggleButton Component * * A button that can be toggled on/off, with glass morphism styling. */ const ToggleButton = /*#__PURE__*/forwardRef(ToggleButtonComponent); /** * GlassToggleButton Component * * Glass variant of the ToggleButton component. */ const GlassToggleButton = /*#__PURE__*/forwardRef((props, ref) => { // Convert Booleanish aria-expanded to boolean const processedProps = { ...props, "aria-expanded": typeof props["aria-expanded"] === "boolean" ? props["aria-expanded"] : props["aria-expanded"] === "true" ? true : props["aria-expanded"] === "false" ? false : props["aria-expanded"] }; return jsx(ToggleButton, { ...processedProps, glass: true, ref: ref }); }); GlassToggleButton.displayName = "GlassToggleButton"; export { GlassToggleButton, ToggleButton, ToggleButton as default }; //# sourceMappingURL=ToggleButton.js.map