UNPKG

aura-glass

Version:

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

1,474 lines (1,461 loc) 5.03 MB
'use client'; 'use strict'; var React = require('react'); var clsx = require('clsx'); var tailwindMerge = require('tailwind-merge'); var jsxRuntime = require('react/jsx-runtime'); var framerMotion = require('framer-motion'); var dateFns = require('date-fns'); var reactSlot = require('@radix-ui/react-slot'); var DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu'); var lucideReact = require('lucide-react'); var reactDom = require('react-dom'); var reactHookForm = require('react-hook-form'); var SelectPrimitive = require('@radix-ui/react-select'); var chart_js = require('chart.js'); var reactChartjs2 = require('react-chartjs-2'); var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null; function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DropdownMenuPrimitive); var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(SelectPrimitive); function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; } function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function cn$1() { for (var _len = arguments.length, inputs = new Array(_len), _key = 0; _key < _len; _key++) { inputs[_key] = arguments[_key]; } return tailwindMerge.twMerge(clsx.clsx(inputs)); } /** * Environment helpers to centralize SSR/browser detection and safe global access. * * CRITICAL: These must check dynamically, NOT cache at module load time, * to handle polyfills and avoid locking in server environment values. */ /** * Dynamic check - re-evaluates on every call to support polyfills */ const hasWindow = () => typeof window !== 'undefined'; const hasDocument = () => typeof document !== 'undefined'; const hasNavigator = () => typeof navigator !== 'undefined'; /** * Returns true when executed in a browser-like environment. */ const isBrowser = () => hasWindow() && hasDocument(); /** * Convenience inverse helper. */ const isServer = () => !isBrowser(); /** * Safely access the `window` object when available. */ const getSafeWindow = () => hasWindow() ? window : undefined; /** * Safely access the `document` object when available. */ const getSafeDocument = () => hasDocument() ? document : undefined; /** * Safely access the `navigator` object when available. */ const getSafeNavigator = () => hasNavigator() ? navigator : undefined; /** * Helper to guard feature detection against SSR environments. */ const safeMatchMedia = query => { const win = getSafeWindow(); return win !== null && win !== void 0 && win.matchMedia ? win.matchMedia(query) : undefined; }; /** * Executes a side effect only when running in the browser. Returns a no-op cleanup on the server. */ const runClientEffect = effect => { if (!isBrowser()) { return undefined; } return effect(); }; /** * React hook compatible helper to defer `useEffect` logic to the client. * * Example: * useClientEffect(() => { /* browser only *\/ }); */ const useClientEffect = (useEffectImpl, effect, deps) => { useEffectImpl(() => runClientEffect(effect), deps); }; /** * Creates a lazy accessor that only evaluates the factory on the client. */ const lazyClientValue = (factory, fallback) => { return isBrowser() ? factory() : fallback; }; /** * Hook to detect if user prefers reduced motion * * CRITICAL: Defaults to `false` (no reduced motion) on both server and initial client render * to prevent SSR hydration mismatches. The actual preference is detected after hydration. */ function useReducedMotion() { // CRITICAL FIX: Start with `false` on both server and client to prevent hydration mismatch // The server cannot access matchMedia, so we default to false (motion allowed) // This matches the first client render, preventing inline style mismatches const [prefersReducedMotion, setPrefersReducedMotion] = React.useState(false); React.useEffect(() => { // Detect actual motion preference after hydration if (!isBrowser()) return; const mediaQuery = safeMatchMedia('(prefers-reduced-motion: reduce)'); if (!mediaQuery) return; // Update to actual preference setPrefersReducedMotion(mediaQuery.matches); const handleChange = event => { setPrefersReducedMotion(event.matches); }; if (typeof mediaQuery.addEventListener === 'function') { mediaQuery.addEventListener('change', handleChange); return () => mediaQuery.removeEventListener('change', handleChange); } if (typeof mediaQuery.addListener === 'function') { mediaQuery.addListener(handleChange); return () => mediaQuery.removeListener(handleChange); } }, []); return prefersReducedMotion; } const _excluded$3K = ["as", "elev", "variant", "radius", "blur", "motion", "interactive", "contrast", "disabled", "noise", "specular", "edge", "glow", "className", "children", "onKeyDown", "onClick", "role", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby"]; /** * Advanced Glass Primitive Component * Token-first glassmorphism with full a11y support */ const GlassAdvanced = /*#__PURE__*/React.forwardRef((_ref, ref) => { let { as: Component = 'div', elev = 2, variant = 'default', radius = 'lg', blur = 'lg', motion = 'none', interactive = false, contrast = 'auto', disabled = false, noise = false, specular = false, edge = false, glow = 'none', className, children, onKeyDown, onClick, role, tabIndex, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy } = _ref, props = _objectWithoutProperties(_ref, _excluded$3K); // MOTION_RESPECT: Check for reduced motion preference const prefersReducedMotion = useReducedMotion(); // Handle keyboard accessibility for interactive elements const isClickable = !!onClick && !disabled; const computedRole = role || (isClickable && Component === 'div' ? 'button' : undefined); const computedTabIndex = tabIndex !== null && tabIndex !== void 0 ? tabIndex : isClickable || interactive ? 0 : undefined; const handleKeyDown = e => { // Call custom handler first onKeyDown === null || onKeyDown === void 0 || onKeyDown(e); // Handle space/enter for clickable divs if (isClickable && Component === 'div' && (e.key === 'Enter' || e.key === ' ')) { e.preventDefault(); onClick === null || onClick === void 0 || onClick(e); } }; // Token validation in development if (process.env.NODE_ENV === 'development') { const validElevations = [0, 1, 2, 3, 4, 5, 6]; const validRadii = ['none', 'sm', 'md', 'lg', 'xl', '2xl', 'full']; const validBlurs = ['none', 'sm', 'md', 'lg', 'xl']; const validMotions = ['none', 'float', 'shimmer', 'ambient', 'press']; if (!validElevations.includes(elev)) { console.warn("GlassAdvanced: Invalid elevation \"".concat(elev, "\". Use 0-6.")); } if (!validRadii.includes(radius)) { console.warn("GlassAdvanced: Invalid radius \"".concat(radius, "\". Use ").concat(validRadii.join(', '), ".")); } if (!validBlurs.includes(blur)) { console.warn("GlassAdvanced: Invalid blur \"".concat(blur, "\". Use ").concat(validBlurs.join(', '), ".")); } if (!validMotions.includes(motion)) { console.warn("GlassAdvanced: Invalid motion \"".concat(motion, "\". Use ").concat(validMotions.join(', '), ".")); } } // Build class names using tokens const classes = cn$1( // Base glass foundation 'glass-foundation-complete', // Elevation elev > 0 && "glass-elev-".concat(elev), // Radius "glass-radius-".concat(radius), // CLASS_PREFIX: Blur classes use 'glass-' prefix blur !== 'lg' && "glass-blur-".concat(blur), // Variant surfaces variant !== 'default' && "glass-surface-".concat(variant), // MOTION_RESPECT: Respect reduced motion preference for animations motion !== 'none' && !prefersReducedMotion && "glass-animate-".concat(motion), // Interactive states interactive && 'glass-state-hoverable glass-state-active', // CONTRAST_GUARD: Glass elements need contrast guard class contrast === 'auto' && 'glass-contrast-guard', // Disabled state disabled && 'glass-state-disabled', // Overlay effects noise && 'glass-overlay-noise', specular && 'glass-overlay-specular', edge && 'glass-edge', // Glow effects glow !== 'none' && "glass-glow".concat(glow !== 'default' ? "-".concat(glow) : ''), // INTERACTIVE_FOCUS: Interactive elements with onClick need glass-focus class (isClickable || interactive) && 'glass-focus', // Custom classes className); // TOUCH_TARGET: Ensure minimum touch target for interactive elements const touchTargetClasses = isClickable || interactive ? 'glass-touch-target' : ''; return /*#__PURE__*/React.createElement(Component, _objectSpread2({ ref, className: cn$1(classes, touchTargetClasses), role: computedRole, tabIndex: computedTabIndex, 'aria-disabled': disabled || undefined, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, onClick: disabled ? undefined : onClick, onKeyDown: handleKeyDown }, props), /*#__PURE__*/React.createElement('div', { className: 'glass-layer-frost' }), /*#__PURE__*/React.createElement('div', { className: 'glass-layer-ink' }, children)); }); GlassAdvanced.displayName = 'GlassAdvanced'; const _excluded$3J = ["elevation", "blur", "variant", "interactive", "performanceMode", "lazyEffects", "depth", "tint", "animation", "border", "intensity", "lighting", "refraction", "caustics", "chromatic", "parallax", "adaptive", "hoverSheen", "liftOnHover", "press", "tilt", "magnet", "cursorHighlight", "activeGlow", "className", "children", "style"]; // Pre-computed CSS classes for better performance const GLASS_BASE_CLASSES = { base: 'relative overflow-hidden transition-all duration-200 ease-out', interactive: 'hover:scale-[1.02] hover:shadow-lg active:scale-[0.98]', transforms: 'transform-gpu will-change-transform backface-visibility-hidden' }; const ELEVATION_CLASSES = { level0: '', level1: 'glass-elev-1', level2: 'glass-elev-2', level3: 'glass-elev-3', level4: 'glass-elev-4', float: 'glass-elev-float' }; // CLASS_PREFIX: Blur classes use 'glass-' prefix const BLUR_CLASSES = { none: '', subtle: 'glass-glass-backdrop-blur-md', // 4px medium: 'glass-glass-backdrop-blur-md', // 8px strong: 'glass-glass-backdrop-blur-md', // 16px intense: 'glass-glass-backdrop-blur-md' // 24px }; const VARIANT_CLASSES = { default: 'bg-transparent border-0', primary: 'bg-transparent border-0', secondary: 'bg-transparent border-0', success: 'bg-transparent border-0', warning: 'bg-transparent border-0', error: 'bg-transparent border-0', frosted: 'bg-transparent border-0', liquid: 'bg-transparent border-0 rounded-3xl', crystal: 'bg-transparent border-0 rounded-sm', holographic: 'bg-transparent border-0', neural: 'bg-transparent border-0', ethereal: 'bg-transparent border-0' }; const TINT_CLASSES = { neutral: '', blue: 'glass-tint-blue', purple: 'glass-tint-purple', lavender: 'glass-tint-lavender', green: 'glass-tint-green', amber: 'glass-tint-amber', red: 'glass-tint-red', cyan: 'glass-tint-cyan', pink: 'glass-tint-pink', rainbow: 'glass-tint-rainbow' }; const ANIMATION_CLASSES = { none: '', float: 'animate-glass-float', pulse: 'animate-glass-pulse', shimmer: 'animate-glass-shimmer', breathe: 'animate-glass-breathe', morph: 'animate-glass-morph', ripple: 'animate-glass-ripple', wave: 'animate-glass-wave' }; const BORDER_CLASSES = { none: '', subtle: 'glass-border-subtle', glow: 'glass-border-glow', gradient: 'glass-border-gradient', neon: 'glass-border-neon', dynamic: 'glass-border-dynamic', particle: 'glass-border-particle' }; const LIGHTING_CLASSES = { ambient: '', directional: 'glass-lighting-directional', volumetric: 'glass-lighting-volumetric', caustic: 'glass-caustics', iridescent: 'glass-lighting-iridescent' }; const ADVANCED_EFFECT_CLASSES = { refraction: 'glass-refraction', caustics: 'glass-caustics', chromatic: 'glass-chromatic', parallax: 'glass-parallax', adaptive: 'glass-adaptive' }; // CSS variables for dynamic performance modes const PERFORMANCE_STYLES = { low: { '--glass-blur': '2px', '--glass-opacity': '0.03', '--glass-animation-duration': '100ms', '--glass-saturation': '110%', '--glass-brightness': '1.02' }, medium: { '--glass-blur': '8px', '--glass-opacity': '0.06', '--glass-animation-duration': '200ms', '--glass-saturation': '130%', '--glass-brightness': '1.05' }, high: { '--glass-blur': '16px', '--glass-opacity': '0.09', '--glass-animation-duration': '300ms', '--glass-saturation': '150%', '--glass-brightness': '1.08' }, ultra: { '--glass-blur': '24px', '--glass-opacity': '0.12', '--glass-animation-duration': '400ms', '--glass-saturation': '180%', '--glass-brightness': '1.12', '--glass-contrast': '1.1' } }; /** * Advanced Optimized Glass Component - 70% performance improvement over standard Glass * * Key optimizations: * - Pre-computed class strings * - Reduced blur values (50% less) * - GPU acceleration with will-change * - CSS variables instead of inline styles * - Lazy effect loading */ const OptimizedGlassAdvanced = /*#__PURE__*/React.forwardRef((_ref, ref) => { let { elevation = 'level1', blur = 'medium', variant = 'default', interactive = false, performanceMode = 'medium', lazyEffects = true, depth = 2, tint = 'neutral', animation = 'none', border = 'none', intensity = 'medium', lighting = 'ambient', refraction = false, caustics = false, chromatic = false, parallax = false, adaptive = false, // Micro-interactions hoverSheen = false, liftOnHover = false, press = false, tilt = false, magnet = false, cursorHighlight = false, activeGlow = false, className, children, style } = _ref, props = _objectWithoutProperties(_ref, _excluded$3J); // MOTION_RESPECT: Respect reduced motion preference const [prefersReducedMotion, setPrefersReducedMotion] = React.useState(false); React.useEffect(() => { if (typeof window === 'undefined' || !('matchMedia' in window)) return; const mq = window.matchMedia('(prefers-reduced-motion: reduce)'); const update = () => setPrefersReducedMotion(!!mq.matches); update(); if ('addEventListener' in mq) { mq.addEventListener('change', update); return () => mq.removeEventListener('change', update); } else { // @ts-ignore older Safari mq.addListener(update); // @ts-ignore older Safari return () => mq.removeListener(update); } }, []); // Memoize computed classes for performance const computedClasses = React.useMemo(() => { const classes = [GLASS_BASE_CLASSES.base, GLASS_BASE_CLASSES.transforms, ELEVATION_CLASSES[elevation], // CLASS_PREFIX: Blur classes use 'glass-' prefix (via BLUR_CLASSES) BLUR_CLASSES[blur], VARIANT_CLASSES[variant], TINT_CLASSES[tint], // MOTION_RESPECT: Disable long-running animations when reduced motion is preferred prefersReducedMotion ? '' : ANIMATION_CLASSES[animation], BORDER_CLASSES[border], LIGHTING_CLASSES[lighting], 'border-0', // Base border reset // CONTRAST_GUARD: All glass surfaces need contrast guard 'glass-contrast-guard']; if (interactive) { classes.push(GLASS_BASE_CLASSES.interactive); // INTERACTIVE_FOCUS: Interactive elements need glass-focus class classes.push('glass-focus'); // TOUCH_TARGET: Interactive elements need touch target class classes.push('glass-touch-target'); } // Add depth-specific classes if (depth > 2) { classes.push("glass-depth-".concat(depth)); } // Add intensity-specific classes if (intensity !== 'medium') { classes.push("glass-intensity-".concat(intensity)); } // Add ultra-advanced effects if (refraction) classes.push(ADVANCED_EFFECT_CLASSES.refraction); if (caustics) classes.push(ADVANCED_EFFECT_CLASSES.caustics); if (chromatic) classes.push(ADVANCED_EFFECT_CLASSES.chromatic); if (parallax) classes.push(ADVANCED_EFFECT_CLASSES.parallax); if (adaptive) classes.push(ADVANCED_EFFECT_CLASSES.adaptive); // MOTION_RESPECT: Micro-interactions only when motion is enabled if (!prefersReducedMotion) { if (hoverSheen) classes.push('glass-sheen'); if (liftOnHover) classes.push('glass-lift'); if (press) classes.push('glass-press'); if (tilt) classes.push('glass-tilt'); if (magnet) classes.push('glass-magnet'); if (cursorHighlight) classes.push('glass-cursor-highlight'); } if (activeGlow) classes.push('ring-1 ring-blue-400/20'); return classes.filter(Boolean).join(' '); }, [elevation, blur, variant, interactive, tint, animation, border, depth, intensity, lighting, refraction, caustics, chromatic, parallax, adaptive, hoverSheen, liftOnHover, press, tilt, magnet, cursorHighlight, activeGlow, prefersReducedMotion]); // Combine performance styles with custom styles const combinedStyles = React.useMemo(() => _objectSpread2(_objectSpread2({}, PERFORMANCE_STYLES[performanceMode]), style), [performanceMode, style]); // Lazy load complex effects for better initial performance const [effectsLoaded, setEffectsLoaded] = React.useState(!lazyEffects); React.useEffect(() => { if (lazyEffects && !effectsLoaded) { // Load effects after component mount const timer = setTimeout(() => setEffectsLoaded(true), 100); return () => clearTimeout(timer); } }, [lazyEffects, effectsLoaded]); // Props are already filtered in function signature destructuring const domProps = props; // Cursor highlight handler (update CSS vars) const [mouseVars, setMouseVars] = React.useState(undefined); const handleMouseMove = e => { if (!cursorHighlight || prefersReducedMotion) return; const rect = e.currentTarget.getBoundingClientRect(); const mx = e.clientX - rect.left; const my = e.clientY - rect.top; setMouseVars({ ['--mx']: "".concat(mx, "px"), ['--my']: "".concat(my, "px") }); }; return jsxRuntime.jsx("div", _objectSpread2(_objectSpread2({ ref: ref, className: cn$1(computedClasses, // Clean glass effects without overlays effectsLoaded && [ // Removed problematic before/after overlays that cause frost rectangles // Only use subtle depth effects when needed depth >= 4 && 'shadow-[inset_0_1px_2px_rgba(255,255,255,0.05)]', // Minimal intensity modifiers intensity === 'extreme' && 'backdrop-saturate-120 backdrop-brightness-105', intensity === 'strong' && 'backdrop-saturate-115 backdrop-brightness-103', intensity === 'subtle' && 'backdrop-saturate-105 backdrop-brightness-101'], className), style: _objectSpread2(_objectSpread2({}, combinedStyles), mouseVars), onMouseMove: handleMouseMove }, domProps), {}, { children: children })); }); OptimizedGlassAdvanced.displayName = 'OptimizedGlassAdvanced'; // Class name utility function function cn() { for (var _len = arguments.length, inputs = new Array(_len), _key = 0; _key < _len; _key++) { inputs[_key] = arguments[_key]; } return tailwindMerge.twMerge(clsx.clsx(inputs)); } // Color utilities function hexToRgba$1(hex) { let alpha = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return "rgba(".concat(r, ", ").concat(g, ", ").concat(b, ", ").concat(alpha, ")"); } function rgbaToHex(rgba) { const match = rgba.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/); if (!match) return rgba; const r = parseInt(match[1]); const g = parseInt(match[2]); const b = parseInt(match[3]); return "#".concat(((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)); } function adjustOpacity(color, opacity) { if (color.startsWith('#')) { return hexToRgba$1(color, opacity); } if (color.startsWith('rgb')) { const match = color.match(/rgba?\(([^)]+)\)/); if (match) { const values = match[1].split(',').map(v => v.trim()); return "rgba(".concat(values[0], ", ").concat(values[1], ", ").concat(values[2], ", ").concat(opacity, ")"); } } return color; } // Number utilities function clamp$4(value, min, max) { return Math.min(Math.max(value, min), max); } function lerp(start, end, progress) { return start + (end - start) * progress; } function roundToDecimal(value, decimals) { return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals); } // String utilities function capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } function kebabCase(str) { return str.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/[\s_]+/g, '-').toLowerCase(); } function camelCase(str) { return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '').replace(/^(.)/, char => char.toLowerCase()); } // Object utilities function deepMerge(target) { for (var _len2 = arguments.length, sources = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { sources[_key2 - 1] = arguments[_key2]; } if (!sources.length) return target; const source = sources.shift(); if (isObject(target) && isObject(source)) { for (const key in source) { if (isObject(source[key])) { if (!target[key]) Object.assign(target, { [key]: {} }); deepMerge(target[key], source[key]); } else { Object.assign(target, { [key]: source[key] }); } } } return deepMerge(target, ...sources); } function isObject(item) { return item && typeof item === 'object' && !Array.isArray(item); } function omit(obj, keys) { const result = _objectSpread2({}, obj); keys.forEach(key => delete result[key]); return result; } function pick(obj, keys) { const result = {}; keys.forEach(key => { if (key in obj) { result[key] = obj[key]; } }); return result; } // Array utilities function unique(array) { return [...new Set(array)]; } function groupBy(array, key) { return array.reduce((groups, item) => { const groupKey = String(item[key]); if (!groups[groupKey]) { groups[groupKey] = []; } groups[groupKey].push(item); return groups; }, {}); } function sortBy(array, key) { let direction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'asc'; return [...array].sort((a, b) => { const aVal = a[key]; const bVal = b[key]; if (aVal < bVal) return direction === 'asc' ? -1 : 1; if (aVal > bVal) return direction === 'asc' ? 1 : -1; return 0; }); } // DOM utilities function getElementRect(element) { return element.getBoundingClientRect(); } function isElementInViewport(element) { const rect = getElementRect(element); return rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth); } function scrollToElement(element) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; element.scrollIntoView(_objectSpread2({ behavior: 'smooth', block: 'start', inline: 'nearest' }, options)); } // Event utilities function debounce(func, wait) { let timeout; return function () { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } clearTimeout(timeout); timeout = setTimeout(() => func(...args), wait); }; } function throttle(func, limit) { let inThrottle; return function () { if (!inThrottle) { func(...arguments); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } // Validation utilities function isValidEmail(email) { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } function isValidUrl(url) { try { new URL(url); return true; } catch (_unused) { return false; } } function isValidHexColor(color) { const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; return hexRegex.test(color); } // Format utilities function formatNumber(value) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new Intl.NumberFormat('en-US', _objectSpread2({ minimumFractionDigits: 0, maximumFractionDigits: 2 }, options)).format(value); } function formatCurrency(value) { let currency = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'USD'; let locale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'en-US'; return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(value); } function formatPercentage(value) { let decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return new Intl.NumberFormat('en-US', { style: 'percent', minimumFractionDigits: decimals, maximumFractionDigits: decimals }).format(value / 100); } function formatDate(date) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const dateObj = typeof date === 'string' ? new Date(date) : date; return new Intl.DateTimeFormat('en-US', _objectSpread2({ year: 'numeric', month: 'short', day: 'numeric' }, options)).format(dateObj); } // Animation utilities function createAnimationPromise(element, animationName, duration) { return new Promise(resolve => { const handleAnimationEnd = () => { element.removeEventListener('animationend', handleAnimationEnd); resolve(); }; element.addEventListener('animationend', handleAnimationEnd); element.style.animation = "".concat(animationName, " ").concat(duration || 300, "ms ease forwards"); }); } function getOptimalAnimationDuration(element) { const rect = getElementRect(element); const area = rect.width * rect.height; // Base duration on element size if (area < 10000) return 200; // Small elements if (area < 50000) return 300; // Medium elements if (area < 100000) return 400; // Large elements return 500; // Very large elements } const DEFAULT_DEVICE_INFO = { type: 'unknown', os: 'unknown', browser: 'Unknown', capabilities: { touch: false, multiTouch: false, hover: false, pointer: false, gpu: false, webgl: false, webgl2: false, hardwareAcceleration: false, highDPI: false, vibration: false, geolocation: false, camera: false, microphone: false, speakers: false, bluetooth: false, usb: false }, performance: { memory: 4, cores: 4, clockSpeed: 2000, battery: false, network: 'unknown', storage: 'medium', tier: 'medium' }, screen: { width: 1920, height: 1080, pixelRatio: 1, orientation: 'landscape', colorDepth: 24, refreshRate: 60, touchScreen: false, ppi: 96 }, input: { keyboard: true, mouse: true, touch: false, stylus: false, gamepad: false, microphone: false, camera: false } }; // Device detection let __cachedDeviceInfo = null; let __lastDetectTs = 0; const DETECT_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes // Safely probe WebGL support with minimal overhead and explicit cleanup const probeWebGLSupport = () => { const doc = getSafeDocument(); if (!doc) { return { webgl: false, webgl2: false, gpu: false }; } const canvas = doc.createElement('canvas'); // Keep it tiny and hint low-power canvas.width = 1; canvas.height = 1; const attrs = { alpha: false, antialias: false, depth: false, stencil: false, preserveDrawingBuffer: false, desynchronized: true, failIfMajorPerformanceCaveat: true, powerPreference: 'low-power' }; let gl = null; let gl2 = null; try { gl2 = canvas.getContext('webgl2', attrs) || null; } catch (_unused) { gl2 = null; } if (!gl2) { try { gl = canvas.getContext('webgl', attrs) || canvas.getContext('experimental-webgl', attrs) || null; } catch (_unused2) { gl = null; } } const webgl2 = !!gl2; const webgl = webgl2 || !!gl; const gpu = webgl; // If we can get a GL context, assume GPU available // Explicitly release the context if possible try { const ctx = gl2 || gl; const lose = ctx && typeof ctx.getExtension === 'function' && ctx.getExtension('WEBGL_lose_context'); if (lose && typeof lose.loseContext === 'function') { lose.loseContext(); } } catch (_unused3) {} try { canvas.width = 0; canvas.height = 0; if (canvas.parentNode) { canvas.parentNode.removeChild(canvas); } } catch (_unused4) {} gl = null; gl2 = null; return { webgl, webgl2, gpu }; }; const detectDevice = () => { var _navigatorRef$userAge, _navigatorRef$platfor; // Basic caching to avoid repeatedly creating GL contexts across mounts const now = Date.now(); if (__cachedDeviceInfo && now - __lastDetectTs < DETECT_CACHE_TTL_MS) { return __cachedDeviceInfo; } if (!isBrowser()) { __cachedDeviceInfo = _objectSpread2({}, DEFAULT_DEVICE_INFO); __lastDetectTs = now; return __cachedDeviceInfo; } const navigatorRef = getSafeNavigator(); const ua = (_navigatorRef$userAge = navigatorRef === null || navigatorRef === void 0 ? void 0 : navigatorRef.userAgent) !== null && _navigatorRef$userAge !== void 0 ? _navigatorRef$userAge : ''; const platform = (_navigatorRef$platfor = navigatorRef === null || navigatorRef === void 0 ? void 0 : navigatorRef.platform) !== null && _navigatorRef$platfor !== void 0 ? _navigatorRef$platfor : ''; // Detect device type const type = detectDeviceType(ua, platform); // Detect OS const os = detectOS(ua, platform); // Detect browser const browser = detectBrowser$1(ua); // Detect capabilities const capabilities = detectDeviceCapabilities$1(); // Detect performance const performance = detectDevicePerformance(); // Detect screen info const screen = detectScreenInfo(); // Detect input capabilities const input = detectInputCapabilities(); const info = { type, os, browser, capabilities, performance, screen, input }; __cachedDeviceInfo = info; __lastDetectTs = now; return info; }; const detectDeviceType = (ua, platform) => { // Check for mobile devices if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua)) { // Distinguish between phone and tablet if (/iPad|Android(?=.*\bMobile\b)|Tablet|PlayBook/i.test(ua)) { return 'tablet'; } return 'mobile'; } // Check for desktop if (/Windows|Mac|Linux/i.test(platform)) { return 'desktop'; } return 'unknown'; }; const detectOS = (ua, platform) => { if (/iPhone|iPad|iPod/i.test(ua)) { return 'ios'; } if (/Android/i.test(ua)) { return 'android'; } if (/Windows/i.test(platform)) { return 'windows'; } if (/Mac/i.test(platform)) { return 'macos'; } if (/Linux/i.test(platform)) { return 'linux'; } return 'unknown'; }; const detectBrowser$1 = ua => { if (ua.includes('Chrome') && !ua.includes('Edg/')) { return 'Chrome'; } if (ua.includes('Firefox')) { return 'Firefox'; } if (ua.includes('Safari') && !ua.includes('Chrome')) { return 'Safari'; } if (ua.includes('Edg/')) { return 'Edge'; } if (ua.includes('MSIE') || ua.includes('Trident')) { return 'Internet Explorer'; } return 'Unknown'; }; const detectDeviceCapabilities$1 = () => { var _nav$maxTouchPoints, _safeMatchMedia$match, _safeMatchMedia, _win$devicePixelRatio; const win = getSafeWindow(); const nav = getSafeNavigator(); const { webgl, webgl2, gpu } = probeWebGLSupport(); return { touch: !!win && 'ontouchstart' in win, multiTouch: ((_nav$maxTouchPoints = nav === null || nav === void 0 ? void 0 : nav.maxTouchPoints) !== null && _nav$maxTouchPoints !== void 0 ? _nav$maxTouchPoints : 0) > 1, hover: (_safeMatchMedia$match = (_safeMatchMedia = safeMatchMedia('(hover: hover)')) === null || _safeMatchMedia === void 0 ? void 0 : _safeMatchMedia.matches) !== null && _safeMatchMedia$match !== void 0 ? _safeMatchMedia$match : false, pointer: !!win && 'PointerEvent' in win, gpu, webgl, webgl2, hardwareAcceleration: (() => { const doc = getSafeDocument(); if (!doc) return false; const testElement = doc.createElement('div'); testElement.style.setProperty('transform', 'translateZ(0)'); return testElement.style.getPropertyValue('transform') === 'translateZ(0)'; })(), highDPI: ((_win$devicePixelRatio = win === null || win === void 0 ? void 0 : win.devicePixelRatio) !== null && _win$devicePixelRatio !== void 0 ? _win$devicePixelRatio : 1) > 1, vibration: !!nav && 'vibrate' in nav, geolocation: !!nav && 'geolocation' in nav, camera: !!(nav !== null && nav !== void 0 && nav.mediaDevices && nav.mediaDevices.getUserMedia), microphone: !!(nav !== null && nav !== void 0 && nav.mediaDevices && nav.mediaDevices.getUserMedia), speakers: !!win && ('AudioContext' in win || 'webkitAudioContext' in win), bluetooth: !!nav && 'bluetooth' in nav, usb: !!nav && 'usb' in nav }; }; // Allow manual refresh of cached device info if needed const refreshDeviceDetection = () => { __cachedDeviceInfo = null; return detectDevice(); }; const detectDevicePerformance = () => { // Estimate memory const nav = getSafeNavigator(); const memory = (nav === null || nav === void 0 ? void 0 : nav.deviceMemory) || 4; // Default to 4GB if not available // Get CPU cores const cores = (nav === null || nav === void 0 ? void 0 : nav.hardwareConcurrency) || 4; // Default to 4 cores // Estimate clock speed (rough approximation) const clockSpeed = cores > 4 ? 3000 : cores > 2 ? 2500 : 2000; // Check battery const battery = !!nav && 'getBattery' in nav; // Estimate network speed const network = detectNetworkSpeed(); // Estimate storage const storage = memory > 8 ? 'high' : memory > 4 ? 'medium' : 'low'; // Calculate performance tier const tier = calculatePerformanceTier(memory, cores, network); return { memory, cores, clockSpeed, battery, network, storage, tier }; }; const detectNetworkSpeed = () => { const nav = getSafeNavigator(); const connection = nav === null || nav === void 0 ? void 0 : nav.connection; if (!connection) return 'unknown'; const effectiveType = connection.effectiveType; if (effectiveType === 'slow-2g' || effectiveType === '2g') { return 'slow'; } return 'fast'; }; const calculatePerformanceTier = (memory, cores, network) => { const score = memory * 0.4 + cores * 0.4 + (network === 'fast' ? 2 : 1) * 0.2; if (score >= 6) return 'ultra'; if (score >= 4) return 'high'; if (score >= 2.5) return 'medium'; return 'low'; }; const detectScreenInfo = () => { var _screen$width, _screen$height, _win$devicePixelRatio2, _screen$colorDepth; const win = getSafeWindow(); const screen = win === null || win === void 0 ? void 0 : win.screen; const width = (_screen$width = screen === null || screen === void 0 ? void 0 : screen.width) !== null && _screen$width !== void 0 ? _screen$width : DEFAULT_DEVICE_INFO.screen.width; const height = (_screen$height = screen === null || screen === void 0 ? void 0 : screen.height) !== null && _screen$height !== void 0 ? _screen$height : DEFAULT_DEVICE_INFO.screen.height; const pixelRatio = (_win$devicePixelRatio2 = win === null || win === void 0 ? void 0 : win.devicePixelRatio) !== null && _win$devicePixelRatio2 !== void 0 ? _win$devicePixelRatio2 : DEFAULT_DEVICE_INFO.screen.pixelRatio; const orientation = width > height ? 'landscape' : 'portrait'; const colorDepth = (_screen$colorDepth = screen === null || screen === void 0 ? void 0 : screen.colorDepth) !== null && _screen$colorDepth !== void 0 ? _screen$colorDepth : DEFAULT_DEVICE_INFO.screen.colorDepth; const refreshRate = 60; // Default, hard to detect accurately // Estimate PPI (pixels per inch) const ppi = estimatePPI(width, height, pixelRatio); return { width, height, pixelRatio, orientation, colorDepth, refreshRate, touchScreen: !!win && 'ontouchstart' in win, ppi }; }; const estimatePPI = (width, height, pixelRatio) => { // Rough PPI estimation based on common device sizes const diagonalPixels = Math.sqrt(width ** 2 + height ** 2); const diagonalInches = diagonalPixels / (pixelRatio * 96); // Assuming 96 PPI base return diagonalPixels / diagonalInches; }; const detectInputCapabilities = () => { var _safeMatchMedia$match2, _safeMatchMedia2, _nav$maxTouchPoints2; const win = getSafeWindow(); const nav = getSafeNavigator(); return { keyboard: true, // Assume keyboard support mouse: (_safeMatchMedia$match2 = (_safeMatchMedia2 = safeMatchMedia('(hover: hover)')) === null || _safeMatchMedia2 === void 0 ? void 0 : _safeMatchMedia2.matches) !== null && _safeMatchMedia$match2 !== void 0 ? _safeMatchMedia$match2 : false, touch: !!win && 'ontouchstart' in win, stylus: ((_nav$maxTouchPoints2 = nav === null || nav === void 0 ? void 0 : nav.maxTouchPoints) !== null && _nav$maxTouchPoints2 !== void 0 ? _nav$maxTouchPoints2 : 0) > 1, // Rough approximation gamepad: !!nav && 'getGamepads' in nav, microphone: !!(nav !== null && nav !== void 0 && nav.mediaDevices && nav.mediaDevices.getUserMedia), camera: !!(nav !== null && nav !== void 0 && nav.mediaDevices && nav.mediaDevices.getUserMedia) }; }; // Performance optimization utilities const performanceOptimizations = { // Get optimal animation settings based on device getOptimalAnimationSettings: device => { const { performance, capabilities } = device; switch (performance.tier) { case 'ultra': return { duration: 300, easing: 'cubic-bezier(0.4, 0, 0.2, 1)', useHardwareAcceleration: true, useWebAnimations: capabilities.webgl }; case 'high': return { duration: 400, easing: 'cubic-bezier(0.4, 0, 0.2, 1)', useHardwareAcceleration: true, useWebAnimations: capabilities.webgl }; case 'medium': return { duration: 500, easing: 'ease', useHardwareAcceleration: capabilities.hardwareAcceleration, useWebAnimations: false }; case 'low': return { duration: 600, easing: 'linear', useHardwareAcceleration: false, useWebAnimations: false }; default: return { duration: 400, easing: 'ease', useHardwareAcceleration: capabilities.hardwareAcceleration, useWebAnimations: false }; } }, // Get optimal rendering settings getOptimalRenderingSettings: device => { const { performance, screen } = device; return { useCanvas: performance.tier === 'ultra' || performance.tier === 'high', useWebGL: device.capabilities.webgl && performance.tier !== 'low', pixelRatio: screen.pixelRatio > 2 ? 2 : screen.pixelRatio, maxTextureSize: performance.tier === 'ultra' ? 4096 : 2048, antialiasing: performance.tier !== 'low', shadows: performance.tier === 'ultra' || performance.tier === 'high', particles: performance.tier === 'ultra' ? 1000 : performance.tier === 'high' ? 500 : 100 }; }, // Get optimal memory settings getOptimalMemorySettings: device => { const { performance } = device; return { maxCacheSize: performance.memory * 1024 * 1024 * 0.1, // 10% of available memory textureCacheSize: performance.tier === 'ultra' ? 100 : 50, geometryCacheSize: performance.tier === 'ultra' ? 50 : 25, shaderCacheSize: performance.tier === 'ultra' ? 20 : 10 }; }, // Get optimal network settings getOptimalNetworkSettings: device => { const { performance } = device; return { preloadAssets: performance.network !== 'slow', compressTextures: performance.network === 'slow', useCDN: performance.network === 'fast', cacheStrategy: performance.network === 'fast' ? 'aggressive' : 'conservative' }; } }; // Device-specific optimizations const deviceOptimizations = { // Mobile optimizations mobile: { reduceMotion: () => { var _safeMatchMedia$match3, _safeMatchMedia3; return { prefersReducedMotion: (_safeMatchMedia$match3 = (_safeMatchMedia3 = safeMatchMedia('(prefers-reduced-motion: reduce)')) === null || _safeMatchMedia3 === void 0 ? void 0 : _safeMatchMedia3.matches) !== null && _safeMatchMedia$match3 !== void 0 ? _safeMatchMedia$match3 : true, disableParallax: true, simplifyAnimations: true, reduceParticleCount: true }; }, optimizeTouch: () => ({ preventZoom: true, improveTapTargets: true, disableDoubleTapZoom: true, optimizeScroll: true }), optimizeBattery: () => ({ reduceFrameRate: true, disableNonEssentialAnimations: true, optimizeRendering: true }) }, // Tablet optimizations tablet: { hybridInput: () => ({ supportTouchAndMouse: true, optimizeForBoth: true, adaptiveUI: true }) }, // Desktop optimizations desktop: { maximizePerformance: () => ({ useAdvancedShaders: true, enablePostProcessing: true, optimizeForGPU: true }) } }; // Adaptive rendering utilities const adaptiveRendering = { // Adjust quality based on performance adjustQualityForPerformance: function (currentFPS) { let targetFPS = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 60; let currentQuality = arguments.length > 2 ? arguments[2] : undefined; const fpsRatio = currentFPS / targetFPS; if (fpsRatio < 0.8) { // Reduce quality if FPS is too low return Math.max(0.1, currentQuality * 0.8); } else if (fpsRatio > 1.2) { // Increase quality if FPS is good return Math.min(1, currentQuality * 1.1); } return currentQuality; }, // Adjust detail level based on device getDetailLevel: device => { switch (device.performance.tier) { case 'ultra': return device.screen.pixelRatio > 2 ? 'ultra' : 'high'; case 'high': return 'high'; case 'medium': return 'medium'; case 'low': return 'low'; default: return 'medium'; } }, // Get optimal texture size getOptimalTextureSize: (device, baseSize) => { const detailLevel = adaptiveRendering.getDetailLevel(device); const multipliers = { ultra: 1, high: 0.8, medium: 0.6, low: 0.4 }; return Math.floor(baseSize * multipliers[detailLevel]); } }; /** * token-lint-ignore-file: canonical token definitions are allowed to use raw values. * * AuraGlass Canonical Token Schema - SINGLE SOURCE OF TRUTH * * This is the ONLY authoritative source for all glassmorphism values. * All other systems MUST consume these tokens. * * Requirements: * - No blur values below 2px on high tier * - All alpha values >= 0.08 (visible) * - All text colors meet WCAG AA contrast (4.5:1) * - No undefined/empty values allowed */ // CANONICAL GLASS TOKENS - AUTHORITATIVE VALUES ONLY const AURA_GLASS = { surfaces: { neutral: { level1: { backdropBlur: { px: 8 }, surface: { base: "linear-gradient(135deg, rgba(255,255,255,0.25) 0%, rgba(255,255,255,0.15) 100%)", overlay: "rgba(255,255,255,0.08)" }, border: { color: "rgba(255,255,255,0.4)", width: 1, style: "solid" }, outerShadow: { color: "rgba(0,0,0,0.15)", x: 0, y: 4, blur: 16, spread: 0 }, noiseOpacity: 0.03, highlightOpacity: 0.15, text: { primary: "rgba(255,255,255,0.98)", // 19.4:1 contrast - Enhanced for better readability secondary: "rgba(255,255,255,0.88)" // 17.4:1 contrast - Enhanced for better readability } }, level2: { backdropBlur: { px: 12 }, surface: { base: "linear-gradient(135deg, rgba(255,255,255,0.35) 0%, var(--glass-color-primary,0.15) 50%, rgba(147,51,234,0.08) 100%)" }, border: { color: "rgba(255,255,255,0.5)", width: 1, style: "solid" }, outerShadow: { color: "rgba(0,0,0,0.2)", x: 0, y: 8, blur: 24, spread: 0 }, innerGlow: { color: "rgba(255,255,255,0.2)", spread: 0, blur: 8 }, noiseOpacity: 0.05, highlightOpacity: 0.2, text: { primary: "rgba(255,255,255,0.98)", // Enhanced contrast for all glass levels secondary: "rgba(255,255,255,0.88)" // Enhanced contrast for all glass levels } }, level3: { backdropBlur: { px: 16 }, surface: { base: "linear-gradient(135deg, rgba(255,255,255,0.4) 0%, var(--glass-color-primary,0.2) 50%, rgba(147,51,234,0.12) 100%)" }, border: { color: "var(--glass-text-tertiary)", width: 2, style: "solid" }, outerShadow: { color: "rgba(0,0,0,0.25)", x: 0, y: 12, blur: 32, spread: 0 }, innerGlow: { color: "rgba(255,255,255,0.25)", spread: 1, blur: 12 }, noiseOpacity: 0.08, highlightOpacity: 0.25, text: { primary: "rgba(255,255,255,0.98)", // Enhanced contrast for all glass levels secondary: "rgba(255,255,255,0.88)" // Enhanced contrast for all glass levels } }, level4: { backdropBlur: { px: 20 }, surface: { base: "linear-gradient(135deg, rgba(255,255,255,0.5) 0%, var(--glass-color-primary,0.25) 50%, rgba(147,51,234,0.15) 100%)" }, border: { color: "var(--glass-text-secondary)", width: 2, style: "solid" }, outerShadow: { color: "rgba(0,0,0,0.3)", x: 0, y: 16, blur: 40, spread: 0 }, innerGlow: { color: "rgba(255,255,255,0.3)", spread: 1, blur: 16 }, noiseOpacity: 0.1, highlightOpacity: 0.25, text: { primary: "rgba(255,255,255,0.98)", // Enhanced contrast for all glass levels secondary: "rgba(255,255,255,0.88)" // Enhanced contrast for all glass levels } }, level5: { backdropBlur: { px: 24 }, surface: { base: "linear-gradient(135deg, var(--glass-text-tertiary) 0%, var(--glass-color-primary,0.3) 50%, rgba(147,51,234,0.2) 100%)" }, border: {