UNPKG

aura-glass

Version:

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

92 lines (89 loc) 2.77 kB
'use client'; import { jsx } from 'react/jsx-runtime'; import { cn } from '../../lib/utilsComprehensive.js'; import { forwardRef, useRef, useEffect } from 'react'; import { useReducedMotion } from '../../hooks/useReducedMotion.js'; import { useA11yId } from '../../utils/a11y.js'; /** * CursorGlow * Renders a pointer-following radial glow. Pointer-events: none. * Uses rAF to throttle updates. Respects reduced motion. */ const CursorGlow = /*#__PURE__*/forwardRef(({ size = 280, intensity = 0.6, color = 'var(--glass-white)', opacity = 0.18, global = true, respectMotionPreference = true, className, 'aria-label': ariaLabel, id, ...props }, ref) => { const reduce = useReducedMotion(); const componentId = useA11yId(id || 'cursor-glow'); const localRef = useRef(null); const frame = useRef(null); const latest = useRef({ x: -9999, y: -9999 }); // Combine refs const combinedRef = node => { localRef.current = node; if (typeof ref === 'function') { ref(node); } else if (ref) { ref.current = node; } }; useEffect(() => { if (respectMotionPreference && reduce) return; // respect reduced motion const handleMove = e => { latest.current = { x: e.clientX, y: e.clientY }; if (frame.current) return; frame.current = requestAnimationFrame(() => { frame.current = null; const el = localRef.current; if (!el) return; const { x, y } = latest.current; el.style.background = `radial-gradient(${size}px ${size}px at ${x}px ${y}px, ${color}${toAlpha(opacity)}, transparent ${Math.round(100 * (1 - opacity))}%)`; }); }; window.addEventListener('pointermove', handleMove, { passive: true }); return () => { window.removeEventListener('pointermove', handleMove); if (frame.current) cancelAnimationFrame(frame.current); }; }, [size, color, opacity, reduce, respectMotionPreference]); return jsx("div", { ref: combinedRef, id: componentId, className: cn(global ? 'glass-fixed' : 'glass-absolute', 'glass-inset-0 glass-pointer-events-none glass-z-2', className), "aria-hidden": !ariaLabel, "aria-label": ariaLabel, role: ariaLabel ? "img" : undefined, style: { mixBlendMode: 'screen', filter: `blur(${Math.round(size / 16)}px) saturate(${100 + intensity * 60}%)` }, ...props }); }); function toAlpha(opacity) { const a = Math.max(0, Math.min(1, opacity)); const hex = Math.round(a * 255).toString(16).padStart(2, '0'); return hex.length === 2 ? hex : '2d'; } CursorGlow.displayName = 'CursorGlow'; export { CursorGlow, CursorGlow as default }; //# sourceMappingURL=CursorGlow.js.map