aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
178 lines (175 loc) • 5.49 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import { forwardRef, useState, useEffect, useMemo } from 'react';
import { cn } from '../../lib/utilsComprehensive.js';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { GlassButton } from '../button/GlassButton.js';
import '../button/GlassFab.js';
import '../button/GlassMagneticButton.js';
import { Typography } from '../data-display/Typography.js';
import { useGalileoStateSpring } from '../../hooks/useGalileoStateSpring.js';
import { useAnimationContext } from '../../contexts/AnimationContext.js';
import { SpringPresets } from '../../animations/physics/springPhysics.js';
import styles from './CompactCookieNotice.module.css.js';
// Cookie management utility
const setCookie = (name, value, days) => {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
const expires = `expires=${date.toUTCString()}`;
document.cookie = `${name}=${value};${expires};path=/`;
};
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.positionBottom,
top: styles.positionTop,
'bottom-left': styles.positionBottomLeft,
'bottom-right': styles.positionBottomRight,
'top-left': styles.positionTopLeft,
'top-right': styles.positionTopRight
};
/**
* A compact cookie consent notice that takes minimal screen space
*/
const CompactCookieNotice = /*#__PURE__*/forwardRef(({
message = 'We use cookies for a better experience.',
acceptText = 'Accept',
moreInfoText = 'More Info',
onAccept,
onMoreInfo,
style,
className,
glassIntensity = 0.6,
position = 'bottom-left',
animate = true,
...rest
}, ref) => {
const [visible, setVisible] = useState(false);
const prefersReducedMotion = useReducedMotion();
const {
defaultSpring
} = useAnimationContext();
const shouldAnimate = animate && !prefersReducedMotion;
useEffect(() => {
// Check if user has already made a choice
const consentValue = getCookie('cookie-consent');
if (!consentValue) {
// Show the notice
setVisible(true);
}
}, []);
const handleAccept = () => {
setCookie('cookie-consent', 'accepted', 365);
setVisible(false);
if (onAccept) {
onAccept();
}
};
const handleMoreInfo = () => {
if (onMoreInfo) {
onMoreInfo();
}
};
// --- Animation Setup ---
const finalSpringConfig = useMemo(() => {
const baseConfig = SpringPresets.default;
let contextConfig = {};
if (typeof defaultSpring === 'string' && defaultSpring in SpringPresets) {
contextConfig = SpringPresets[defaultSpring];
} else if (typeof defaultSpring === 'object') {
contextConfig = defaultSpring ?? {};
}
return {
...baseConfig,
...contextConfig
};
}, [defaultSpring]);
const isTop = position?.startsWith('top');
const exitY = isTop ? -15 : 15;
// Spring for Opacity
const {
value: animatedOpacity
} = useGalileoStateSpring(visible ? 1 : 0, {
...finalSpringConfig,
immediate: !shouldAnimate
});
// Spring for TranslateY
const {
value: animatedTranslateY
} = useGalileoStateSpring(visible ? 0 : exitY, {
...finalSpringConfig,
immediate: !shouldAnimate
});
// Calculate transform
const isCentered = position === 'top' || position === 'bottom';
const animatedStyle = {
opacity: animatedOpacity,
transform: `translateY(${animatedTranslateY}px)${isCentered ? ' translateX(-50%)' : ''}`
};
const positionClass = POSITION_CLASS_MAP[position ?? 'bottom-left'] ?? styles.positionBottomLeft;
const depth = Math.max(0.5, Math.min(2, glassIntensity));
const shadowDepth = (24 * depth).toFixed(2);
const containerStyleVars = {
'--cookie-blur-scale': depth,
'--cookie-box-shadow': `0 10px ${shadowDepth}px rgba(15, 23, 42, 0.16)`
};
if (!visible) {
return jsx("div", {
ref: ref,
className: cn(styles.container, positionClass, className),
style: {
...containerStyleVars,
display: 'none',
...style
},
"aria-hidden": true,
...rest
});
}
return jsxs("div", {
ref: ref,
className: cn(styles.container, positionClass, className),
style: {
...containerStyleVars,
...animatedStyle,
...style
},
"aria-hidden": !visible,
...rest,
children: [jsx(Typography, {
variant: "p",
children: message
}), jsxs("div", {
className: styles.buttonGroup,
children: [jsx(GlassButton, {
variant: "link",
onClick: handleMoreInfo,
size: "sm",
children: moreInfoText
}), jsx(GlassButton, {
variant: "primary",
onClick: handleAccept,
size: "sm",
children: acceptText
})]
})]
});
});
CompactCookieNotice.displayName = 'CompactCookieNotice';
// Glass version of the CompactCookieNotice
const GlassCompactCookieNotice = /*#__PURE__*/forwardRef((props, ref) => jsx(CompactCookieNotice, {
ref: ref,
glassIntensity: 0.75,
...props
}));
GlassCompactCookieNotice.displayName = 'GlassCompactCookieNotice';
export { CompactCookieNotice, GlassCompactCookieNotice };
//# sourceMappingURL=CompactCookieNotice.js.map