aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
227 lines (224 loc) • 7.19 kB
JavaScript
'use client';
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
import { cn } from '../../lib/utilsComprehensive.js';
import { memo, useState, useEffect, useCallback } from 'react';
import { useAccessibleAnimation } from '../../hooks/useAccessibilitySettings.js';
import '../../primitives/GlassCore.js';
import '../../primitives/glass/GlassAdvanced.js';
import { OptimizedGlassCore } from '../../primitives/OptimizedGlassCore.js';
import '../../primitives/glass/OptimizedGlassAdvanced.js';
import '../../primitives/MotionNative.js';
import '../../primitives/motion/MotionFramer.js';
import { GlassComponentErrorBoundary } from '../../utils/errorBoundary.js';
/** Animation keyframes for different variants */
const pulseKeyframes = `
@keyframes glass-pulse {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.7;
transform: scale(1.02);
}
}
`;
const waveKeyframes = `
@keyframes glass-wave {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(100%);
}
}
`;
const shimmerKeyframes = `
@keyframes glass-shimmer {
0% {
background-position: -200px 0;
}
100% {
background-position: calc(200px + 100%) 0;
}
}
`;
const sheenKeyframes = `
@keyframes glass-sheen-move {
0% { transform: translateX(-150%) rotate(15deg); }
100% { transform: translateX(150%) rotate(15deg); }
}
@keyframes glass-depth-pulse {
0%, 100% { box-shadow: var(--glass-elev-2); }
50% { box-shadow: var(--glass-elev-2); }
}
`;
const GlassSkeletonLoader = /*#__PURE__*/memo(({
// TODO: Integrate ContrastGuard for table cells, list items, badges, card titles, and other text content for WCAG AA compliance
loading = true,
text = "Loading...",
size = "md",
variant = "pulse",
className = "",
children
}) => {
const [mounted, setMounted] = useState(false);
const {
shouldAnimate,
animationDuration
} = useAccessibleAnimation();
useEffect(() => {
setMounted(true);
}, []);
const renderContent = useCallback(() => {
if (!loading && mounted) {
return jsx(Fragment, {
children: children
});
}
const sizeClasses = {
sm: "glass-w-6 glass-h-6",
md: "glass-w-8 glass-h-8",
lg: "glass-w-12 glass-h-12",
xl: "glass-w-16 glass-h-16"
};
const getAnimationStyle = () => {
if (!shouldAnimate) return {};
switch (variant) {
case "wave":
return {
position: "relative",
overflow: "hidden",
background: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */',
backgroundSize: "200px 100%",
animation: `glass-wave ${animationDuration * 5}ms infinite`
};
case "shimmer":
return {
position: "relative",
overflow: "hidden",
background: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */',
backgroundSize: "200px 100%",
animation: `glass-shimmer ${animationDuration * 7}ms infinite, glass-depth-pulse ${animationDuration * 14}ms ease-in-out infinite`
};
case "sheen":
return {
position: "relative",
overflow: "hidden",
background: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */'
// sheen drawn by a before-like overlay via extra element below
};
case "pulse":
default:
return {
animation: `glass-pulse ${animationDuration * 7}ms ease-in-out infinite`
};
}
};
return jsxs("div", {
"data-glass-component": true,
className: cn("glass-flex glass-flex-col glass-items-center glass-justify-center glass-gap-4", className),
children: [jsxs("div", {
style: {
position: "relative"
},
children: [jsx(OptimizedGlassCore, {
className: cn("glass-radius-full", sizeClasses[size]),
style: getAnimationStyle(),
intensity: "medium",
elevation: "level1",
interactive: false
}), shouldAnimate && variant === "sheen" && jsx("span", {
"aria-hidden": true,
style: {
position: "absolute",
inset: 0,
borderRadius: "9999px",
background: '/* Use createGlassStyle({ intent: "neutral", elevation: "level2" }) */',
filter: "blur(6px) saturate(120%)",
transform: "translateX(-150%) rotate(15deg)",
animation: `glass-sheen-move ${animationDuration * 6}ms ease-in-out infinite`,
pointerEvents: "none"
}
})]
}), text && jsx(OptimizedGlassCore, {
className: "glass-px-4 glass-py-2 glass-radius-lg",
intensity: "subtle",
elevation: "level1",
children: jsx("span", {
className: cn("glass-text-sm glass-text-primary-70 glass-font-medium"),
children: text
})
})]
});
}, [loading, mounted, children, size, variant, className, text, shouldAnimate, animationDuration]);
return jsx(GlassComponentErrorBoundary, {
componentName: "GlassSkeletonLoader",
children: jsxs(Fragment, {
children: [jsxs("style", {
children: [pulseKeyframes, waveKeyframes, shimmerKeyframes, sheenKeyframes]
}), renderContent()]
})
});
});
const GlassSkeletonText = ({
lines = 1,
width = "100%",
className = ""
}) => {
useAccessibleAnimation();
const widths = Array.isArray(width) ? width : [width];
return jsx("div", {
className: cn("glass-gap-2", className),
children: Array.from({
length: lines
}, (_, i) => jsx(OptimizedGlassCore, {
className: cn("glass-h-4 glass-radius-md"),
style: {
width: widths[i % widths.length],
animation: "glass-pulse 2s ease-in-out infinite",
animationDelay: `${i * 0.1}s`
},
intensity: "subtle",
elevation: "level1",
interactive: false
}, i))
});
};
// Compound component for skeleton card
const GlassSkeletonCard = ({
className = ""
}) => {
return jsxs(OptimizedGlassCore, {
className: cn("glass-p-6 glass-gap-4", className),
intensity: "medium",
elevation: "level1",
children: [jsx(GlassSkeletonText, {
lines: 1,
width: "60%"
}), jsx(GlassSkeletonText, {
lines: 2,
width: ["100%", "80%"]
}), jsxs("div", {
className: cn("glass-flex glass-gap-2"),
children: [jsx(OptimizedGlassCore, {
className: cn("glass-h-8 glass-w-16 glass-radius-md"),
style: {
animation: "glass-pulse 2s ease-in-out infinite"
},
intensity: "subtle",
elevation: "level1"
}), jsx(OptimizedGlassCore, {
className: cn("glass-h-8 glass-w-16 glass-radius-md"),
style: {
animation: "glass-pulse 2s ease-in-out infinite",
animationDelay: "0.2s"
},
intensity: "subtle",
elevation: "level1"
})]
})]
});
};
export { GlassSkeletonCard, GlassSkeletonLoader, GlassSkeletonText };
//# sourceMappingURL=GlassSkeletonLoader.js.map