aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
216 lines (213 loc) • 6.98 kB
JavaScript
'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