UNPKG

aura-glass

Version:

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

269 lines (266 loc) 10.2 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { cn } from '../../lib/utilsComprehensive.js'; import { Minus, ArrowDownIcon, ArrowUpIcon } from 'lucide-react'; import '../../primitives/GlassCore.js'; import '../../primitives/glass/GlassAdvanced.js'; import '../../primitives/OptimizedGlassCore.js'; import '../../primitives/glass/OptimizedGlassAdvanced.js'; import '../../primitives/MotionNative.js'; import { MotionFramer } from '../../primitives/motion/MotionFramer.js'; import { CardHeader, CardTitle, CardContent } from '../card/index.js'; import { GlassCard } from '../card/GlassCard.js'; /** * GlassKPICard component * A glassmorphism KPI card for displaying key performance indicators */ const GlassKPICard = ({ // TODO: Integrate ContrastGuard for table cells, list items, badges, card titles, and other text content for WCAG AA compliance title = "KPI", value = "--", unit = "", previousValue, trend = "none", trendPercentage, description, icon, variant = "default", size = "md", showTrend = true, trendLabel, formatValue, children, loading = false, onClick, className, ...props }) => { // Size configurations const sizeConfigs = { sm: { cardClass: "glass-p-4", titleClass: "glass-text-sm font-medium", valueClass: "glass-text-2xl font-bold", iconSize: "w-6 h-6", trendIconSize: "w-4 h-4", trendTextSize: "glass-text-xs" }, md: { cardClass: "glass-p-6", titleClass: "glass-text-base font-medium", valueClass: "text-3xl font-bold", iconSize: "w-8 h-8", trendIconSize: "w-5 h-5", trendTextSize: "glass-text-sm" }, lg: { cardClass: "p-8", titleClass: "glass-text-lg font-semibold", valueClass: "text-4xl font-bold", iconSize: "w-10 h-10", trendIconSize: "w-6 h-6", trendTextSize: "glass-text-base" }, xl: { cardClass: "glass-p-10", titleClass: "glass-text-xl font-semibold", valueClass: "text-5xl font-bold", iconSize: "w-12 h-12", trendIconSize: "w-7 h-7", trendTextSize: "glass-text-lg" } }; const config = sizeConfigs[size] ?? sizeConfigs.md; // Variant color configurations const variantConfigs = { default: { iconColor: "glass-text-primary/70", trendUpColor: "text-green-400", trendDownColor: "text-red-400", trendNeutralColor: "text-yellow-400", valueColor: "glass-text-primary" }, success: { iconColor: "text-green-400", trendUpColor: "text-green-300", trendDownColor: "text-red-400", trendNeutralColor: "text-yellow-400", valueColor: "text-green-200" }, warning: { iconColor: "text-yellow-400", trendUpColor: "text-green-400", trendDownColor: "text-red-400", trendNeutralColor: "text-yellow-300", valueColor: "text-yellow-200" }, error: { iconColor: "text-red-400", trendUpColor: "text-red-400", trendDownColor: "text-red-300", trendNeutralColor: "text-yellow-400", valueColor: "text-red-200" }, info: { iconColor: "text-blue-400", trendUpColor: "text-green-400", trendDownColor: "text-red-400", trendNeutralColor: "text-yellow-400", valueColor: "text-blue-200" }, primary: { iconColor: "text-primary", trendUpColor: "text-green-400", trendDownColor: "text-red-400", trendNeutralColor: "text-yellow-400", valueColor: "text-primary-foreground" } }; const variantConfig = variantConfigs[variant] ?? variantConfigs.default; // Format the display value const displayValue = formatValue ? formatValue(value ?? "--") : String(value ?? "--"); // Calculate trend information const getTrendInfo = () => { if (trend === "none" || !showTrend) return null; let trendIcon; let trendColor; let trendText = ""; switch (trend) { case "up": trendIcon = jsx(ArrowUpIcon, { className: cn(config.trendIconSize, variantConfig.trendUpColor) }); trendColor = variantConfig.trendUpColor; break; case "down": trendIcon = jsx(ArrowDownIcon, { className: cn(config.trendIconSize, variantConfig.trendDownColor) }); trendColor = variantConfig.trendDownColor; break; case "neutral": trendIcon = jsx(Minus, { className: cn(config.trendIconSize, variantConfig.trendNeutralColor) }); trendColor = variantConfig.trendNeutralColor; break; } if (trendPercentage !== undefined) { trendText = `${trend === "up" ? "+" : trend === "down" ? "-" : ""}${Math.abs(trendPercentage)}%`; } else if (trendLabel) { trendText = trendLabel; } return { trendIcon, trendColor, trendText }; }; const trendInfo = getTrendInfo(); // Loading skeleton if (loading) { return jsx(GlassCard, { "data-glass-component": true, className: cn("animate-pulse", config.cardClass, className), children: jsxs("div", { className: "glass-gap-4", children: [jsxs("div", { className: "glass-flex glass-items-center glass-justify-between", children: [jsx("div", { className: 'h-4 glass-surface-subtle/20 glass-radius-md w-24' }), jsx("div", { className: 'w-8 h-8 glass-surface-subtle/20 glass-radius-md' })] }), jsxs("div", { className: "glass-gap-2", children: [jsx("div", { className: 'h-8 glass-surface-subtle/20 glass-radius-md w-32' }), jsx("div", { className: 'h-4 glass-surface-subtle/20 glass-radius-md w-20' })] })] }) }); } return jsx(MotionFramer, { preset: "fadeIn", className: "glass-w-full glass-kpi-card", children: jsxs(GlassCard, { elevation: "level2", intensity: "medium", depth: 2, tint: "neutral", border: "subtle", animation: "none", performanceMode: "medium", hoverable: !!onClick, clickable: !!onClick, onClick: onClick, className: cn(config.cardClass, "group relative overflow-hidden", onClick && ["cursor-pointer", "hover:shadow-2xl hover:shadow-purple-500/20", "transition-all duration-500 ease-out"], className), ...props, children: [jsxs(CardHeader, { className: 'pb-2', children: [jsxs("div", { className: "glass-flex glass-items-center glass-justify-between", children: [jsxs(CardTitle, { className: cn(config.titleClass, "glass-text-primary/90 flex items-center glass-gap-2"), children: [icon && jsxs("div", { className: cn("inline-flex items-center justify-center glass-radius-lg glass-p-2 mr-3", "bg-gradient-to-br from-white/10 to-white/5 border border-white/20", "group-hover:from-white/15 group-hover:to-white/8", "group-hover:border-white/30 group-hover:shadow-lg", "group-hover:scale-110 group-hover:rotate-2", "transition-all duration-300 ease-out", variantConfig.iconColor), children: [jsx("div", { className: 'absolute inset-0 glass-gradient-primary glass-gradient-primary glass-gradient-primary glass-radius-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300' }), jsx("span", { className: cn(config.iconSize, "relative z-10 transition-transform duration-300 group-hover:scale-110"), children: icon })] }), title] }), trendInfo && trendInfo.trendIcon && jsxs("div", { className: 'glass-flex glass-items-center glass-gap-1 trend-indicator', children: [jsx("div", { className: 'glass-p-1 glass-radius-md glass-surface-subtle/10 group-hover:glass-surface-subtle/20 transition-colors duration-300', children: jsx("span", { "data-icon": true, className: 'transition-all duration-300', children: trendInfo.trendIcon }) }), trendInfo.trendText && jsx("span", { className: cn(config.trendTextSize, trendInfo.trendColor, "font-medium transition-all duration-300", "group-hover:scale-105 group-hover:brightness-110"), children: trendInfo.trendText })] })] }), description && jsx("p", { className: 'glass-text-sm text-primary/60 glass-mt-1', children: description })] }), jsxs(CardContent, { className: 'pt-0', children: [jsxs("div", { className: 'glass-flex items-baseline glass-gap-2 relative', children: [jsxs("div", { className: 'relative premium-glow', children: [jsx("div", { className: 'absolute inset-0 glass-gradient-primary glass-gradient-primary via-purple-400/30 glass-gradient-primary glass-blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-500 -z-10 scale-150' }), jsx("span", { "data-value": true, className: cn(config.valueClass, variantConfig.valueColor, "relative z-10 font-bold tracking-tight", "group-hover:glass-text-primary transition-all duration-300", "drop-shadow-sm group-hover:drop-shadow-lg"), children: displayValue })] }), unit && jsx("span", { className: cn("glass-text-lg glass-text-primary/70 font-medium", "group-hover:glass-text-primary/90 transition-colors duration-300"), children: unit })] }), previousValue && jsx("div", { className: "glass-mt-2", children: jsxs("span", { className: 'glass-text-sm text-primary/50', children: ["Previous:", " ", formatValue ? formatValue(previousValue) : String(previousValue), unit] }) }), children && jsx("div", { className: "glass-mt-4", children: children })] })] }) }); }; export { GlassKPICard, GlassKPICard as default }; //# sourceMappingURL=GlassKPICard.js.map