aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
170 lines (167 loc) • 4.78 kB
JavaScript
'use client';
import { jsxs, jsx } from 'react/jsx-runtime';
import { forwardRef, useRef, useState, useEffect, useMemo } from 'react';
import { cn } from '../../lib/utilsComprehensive.js';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
import { createGlassStyle } from '../../core/mixins/glassMixins.js';
import styles from './VisualFeedback.module.css.js';
// Convert color string to RGB values
const colorToRgb = color => {
// Convert named colors to their RGB values
switch (color) {
case 'primary':
return '99, 102, 241';
// Indigo
case 'secondary':
return '156, 39, 176';
// Purple
case 'error':
return '240, 82, 82';
// Red
case 'info':
return '3, 169, 244';
// Light Blue
case 'success':
return '76, 175, 80';
// Green
case 'warning':
return '255, 152, 0';
// Orange
default:
// If it's already an RGB value in format 'r, g, b'
if (/^\d+,\s*\d+,\s*\d+$/.test(color)) {
return color;
}
// Default color (white)
return '255, 255, 255';
}
};
/**
* VisualFeedback Component Implementation
*/
function VisualFeedbackComponent(props, ref) {
const {
children,
effect = 'highlight',
active = false,
color = 'primary',
duration = 1000,
glass = false,
intensity = 0.5,
className,
style,
...rest
} = props;
// Check if reduced motion is preferred
const prefersReducedMotion = useReducedMotion();
// Refs
const containerRef = useRef(null);
// State for ripple effect
const [ripples, setRipples] = useState([]);
const rippleCount = useRef(0);
// Handle ripple effect
const handleRipple = event => {
if (effect !== 'ripple' || !active || prefersReducedMotion) return;
const container = containerRef.current;
if (!container) return;
const rect = container.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
// Add new ripple
const id = rippleCount.current;
rippleCount.current += 1;
const newRipple = {
id,
x,
y,
size
};
setRipples(prevRipples => [...prevRipples, newRipple]);
// Remove ripple after animation completes
setTimeout(() => {
setRipples(prevRipples => prevRipples.filter(r => r.id !== id));
}, duration);
};
// Clean up ripples when component unmounts
useEffect(() => {
return () => {
setRipples([]);
};
}, []);
// Handle forwarded ref
const setRefs = element => {
containerRef.current = element;
// Handle the forwarded ref
if (typeof ref === 'function') {
ref(element);
} else if (ref) {
ref.current = element;
}
};
const animationClass = useMemo(() => {
if (!active || effect === 'none' || prefersReducedMotion) {
return undefined;
}
switch (effect) {
case 'pulse':
return styles.pulse;
case 'glow':
return styles.glow;
case 'highlight':
return styles.highlight;
case 'bounce':
return styles.bounce;
case 'shake':
return styles.shake;
default:
return undefined;
}
}, [active, effect, prefersReducedMotion]);
const containerClassName = cn(styles.container, effect === 'ripple' && styles.rippleOverflow, animationClass, 'glass-visual-feedback', className);
const containerStyle = useMemo(() => ({
'--feedback-color-rgb': colorToRgb(color),
animationDuration: `${duration}ms`,
...style
}), [color, duration, style]);
return jsxs("div", {
ref: setRefs,
className: containerClassName,
style: containerStyle,
onClick: effect === 'ripple' ? handleRipple : undefined,
...rest,
children: [glass && active && !prefersReducedMotion ? jsx("div", {
className: styles.glassOverlay,
style: {
opacity: intensity * 0.5,
...createGlassStyle({
intent: 'neutral',
elevation: 'level2'
})
}
}) : null, jsx("div", {
className: styles.content,
children: children
}), effect === 'ripple' && jsx("div", {
className: styles.ripples,
children: ripples.map(ripple => jsx("div", {
className: styles.ripple,
style: {
top: ripple.y,
left: ripple.x,
width: ripple.size,
height: ripple.size,
animationDuration: `${duration}ms`
}
}, ripple.id))
})]
});
}
/**
* VisualFeedback Component
*
* A component that provides visual feedback effects.
*/
const VisualFeedback = /*#__PURE__*/forwardRef(VisualFeedbackComponent);
export { VisualFeedback as default };
//# sourceMappingURL=VisualFeedback.js.map