UNPKG

aura-glass

Version:

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

216 lines (213 loc) 6.98 kB
'use client'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import { forwardRef, useState, useEffect, useMemo } from 'react'; import { cn } from '../../lib/utilsComprehensive.js'; import { useReducedMotion } from '../../hooks/useReducedMotion.js'; import { Box } from '../layout/Box.js'; import { GlassButton } from '../button/GlassButton.js'; import '../button/GlassFab.js'; import '../button/GlassMagneticButton.js'; import { Typography } from '../data-display/Typography.js'; import styles from './CookieConsent.module.css.js'; import { useGalileoStateSpring } from '../../hooks/useGalileoStateSpring.js'; import { useAnimationContext } from '../../contexts/AnimationContext.js'; import { SpringPresets } from '../../animations/physics/springPhysics.js'; const getCookie = name => { const nameEQ = `${name}=`; const ca = document.cookie.split(";"); for (let i = 0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) === " ") c = c.substring(1, c.length); if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); } return null; }; const POSITION_CLASS_MAP = { bottom: styles.positionCenterBottom, top: styles.positionCenterTop, "bottom-left": styles.positionBottomLeft, "bottom-right": styles.positionBottomRight, "top-left": styles.positionTopLeft, "top-right": styles.positionTopRight }; /** * Cookie Consent component for displaying cookie consent banners */ const CookieConsent = /*#__PURE__*/forwardRef(({ title = "Cookie Consent", message = "We use cookies to improve your experience on our site.", position = "bottom-right", acceptButtonText = "Accept", declineButtonText = "Decline", settingsButtonText = "Customize", onAccept, onDecline, onSettings, enableSettings = false, glassIntensity = 0.7, privacyPolicyUrl, privacyPolicyText = "Privacy Policy", className, animate = true, delay = 500, timeout = 0, onTimeout, dismissible = true, cookieExpiration = 365, style, animationConfig, disableAnimation, motionSensitivity, ...rest }, ref) => { const [visible, setVisible] = useState(false); const prefersReducedMotion = useReducedMotion(); const { defaultSpring } = useAnimationContext(); const finalDisableAnimation = disableAnimation ?? prefersReducedMotion; const shouldAnimate = animate && !finalDisableAnimation; useEffect(() => { // Check if user has already made a choice const consentValue = getCookie("cookie-consent"); if (!consentValue) { // Show the consent banner after delay const timer = setTimeout(() => { setVisible(true); }, delay); return () => clearTimeout(timer); } }, [delay]); useEffect(() => { if (visible && timeout > 0) { const timer = setTimeout(() => { setVisible(false); if (onTimeout) { onTimeout(); } }, timeout); return () => clearTimeout(timer); } }, [visible, timeout, onTimeout]); const finalSpringConfig = useMemo(() => { const baseConfig = SpringPresets.default; let contextConfig = {}; const contextSource = defaultSpring; if (typeof contextSource === "string" && contextSource in SpringPresets) { contextConfig = SpringPresets[contextSource]; } else if (typeof contextSource === "object") { contextConfig = contextSource ?? {}; } let propConfig = {}; const propSource = animationConfig; if (typeof propSource === "string" && propSource in SpringPresets) { propConfig = SpringPresets[propSource]; } else if (typeof propSource === "object" && ("tension" in propSource || "friction" in propSource)) { propConfig = propSource; } return { ...baseConfig, ...contextConfig, ...propConfig }; }, [defaultSpring, animationConfig]); const isTop = position?.startsWith("top"); const exitY = isTop ? -20 : 20; const { value: animatedOpacity } = useGalileoStateSpring(visible ? 1 : 0, { ...finalSpringConfig, immediate: !shouldAnimate }); const { value: animatedTranslateY } = useGalileoStateSpring(visible ? 0 : exitY, { ...finalSpringConfig, immediate: !shouldAnimate }); const positionClass = POSITION_CLASS_MAP[position ?? "bottom-right"] ?? styles.positionBottomRight; const depth = Math.max(0.5, Math.min(2, glassIntensity)); const shadowDepth = (28 * depth).toFixed(2); const containerStyleVars = { "--cookie-blur-scale": depth, "--cookie-box-shadow": `0 12px ${shadowDepth}px rgba(15, 23, 42, 0.18)` }; const isCentered = position === "top" || position === "bottom"; const animatedStyle = { opacity: animatedOpacity, transform: `translateY(${animatedTranslateY}px)${isCentered ? " translateX(-50%)" : ""}` }; if (!visible) { return jsx("div", { ref: ref, className: cn(styles.container, positionClass, className), style: { ...containerStyleVars, display: "none", ...style }, "aria-hidden": true, ...rest }); } return jsx("div", { ref: ref, className: cn(styles.container, positionClass, className), style: { ...containerStyleVars, ...animatedStyle, ...style }, "aria-hidden": !visible, ...rest, children: jsxs(Box, { children: [title && jsx(Typography, { variant: "h6", className: 'mb-2 font-semibold', children: title }), jsxs(Typography, { variant: "p", children: [message, privacyPolicyUrl && jsxs(Fragment, { children: [" ", jsx("a", { href: privacyPolicyUrl, target: "_blank", rel: "noopener noreferrer", className: "glass-focus glass-touch-target glass-contrast-guard", children: privacyPolicyText })] })] }), jsxs("div", { className: styles.buttonContainer, children: [dismissible && jsx(GlassButton, { variant: "outline", onClick: onDecline, size: "sm", className: "glass-focus glass-touch-target", children: declineButtonText }), enableSettings && jsx(GlassButton, { variant: "outline", onClick: onSettings, size: "sm", className: "glass-focus glass-touch-target", children: settingsButtonText }), jsx(GlassButton, { variant: "primary", onClick: onAccept, size: "sm", className: "glass-focus glass-touch-target", children: acceptButtonText })] })] }) }); }); CookieConsent.displayName = "CookieConsent"; // Glass version of the CookieConsent component const GlassCookieConsent = /*#__PURE__*/forwardRef((props, ref) => jsx(CookieConsent, { ref: ref, glassIntensity: 0.8, ...props })); GlassCookieConsent.displayName = "GlassCookieConsent"; export { CookieConsent, GlassCookieConsent }; //# sourceMappingURL=CookieConsent.js.map