UNPKG

aura-glass

Version:

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

340 lines (337 loc) 12.7 kB
'use client'; import { jsx, jsxs } from 'react/jsx-runtime'; import { cn } from '../../../../lib/utilsComprehensive.js'; import { forwardRef } from 'react'; import { GlassCore } from '../../../../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 { GlassBadge } from '../../../data-display/GlassBadge.js'; import { VStack, HStack } from '../../../layout/GlassStack.js'; /** * ChartWidget component * Displays various chart types with glassmorphism styling */ const ChartWidget = /*#__PURE__*/forwardRef(({ data, type = "bar", variant = "default", size = "md", colorScheme = "default", showLegend = true, showGrid = true, interactive = true, loading = false, actions, renderChart, className, ...props }, ref) => { const sizeClasses = { sm: { height: "h-32", padding: "glass-p-3", title: "glass-text-sm", subtitle: "glass-text-xs" }, md: { height: "h-48", padding: "glass-p-4", title: "glass-text-base", subtitle: "glass-text-sm" }, lg: { height: "h-64", padding: "glass-p-6", title: "glass-text-lg", subtitle: "glass-text-base" } }; const colorSchemes = { default: ["var(--glass-color-primary)", "#8B5CF6", "var(--glass-color-success)", "var(--glass-color-warning)", "var(--glass-color-danger)"], primary: ["var(--glass-color-primary)", "var(--glass-color-primary-light)", "#93C5FD", "#DBEAFE", "#EBF8FF"], success: ["var(--glass-color-success)", "var(--glass-color-success-light)", "#6EE7B7", "#A7F3D0", "#D1FAE5"], warning: ["var(--glass-color-warning)", "var(--glass-color-warning-light)", "#FCD34D", "#FDE68A", "#FEF3C7"], destructive: ["var(--glass-color-danger)", "var(--glass-color-danger-light)", "#FCA5A5", "#FECACA", "#FEE2E2"], rainbow: ["var(--glass-color-primary)", "#8B5CF6", "var(--glass-color-success)", "var(--glass-color-warning)", "var(--glass-color-danger)", "#EC4899", "#06B6D4"] }; const config = sizeClasses?.[size] || sizeClasses.md; const colors = colorSchemes?.[colorScheme] || colorSchemes.default; // Simple bar chart renderer const renderBarChart = () => { if (!data?.dataPoints || data.dataPoints.length === 0) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full glass-text-secondary", children: "No data available" }); } const maxValue = Math.max(...data.dataPoints.map(d => d.value)); return jsx("div", { "data-glass-component": true, className: "glass-flex glass-items-end glass-justify-between glass-gap-2 glass-h-full", children: data?.dataPoints.map((point, index) => { const height = point.value / maxValue * 100; const color = point.color || colors[index % (colors?.length || 0)]; return jsxs(MotionFramer, { preset: "slideUp", delay: index * 100, className: "glass-flex-1 glass-flex glass-flex-col glass-items-center glass-gap-2", children: [jsx("div", { className: 'glass-w-full glass-radius-t transition-all duration-300 hover:opacity-80 cursor-pointer', style: { height: `${height}%`, backgroundColor: color, minHeight: "4px" }, title: `${point.label}: ${point.value}` }), jsx("div", { className: 'glass-text-xs glass-text-secondary text-center truncate glass-w-full', children: point.label })] }, point.label); }) }); }; // Simple line chart renderer const renderLineChart = () => { if (!data?.dataPoints || data.dataPoints.length === 0) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full glass-text-secondary", children: "No data available" }); } const maxValue = Math.max(...data.dataPoints.map(d => d.value)); const points = data?.dataPoints.map((point, index) => { const x = index / ((data.dataPoints?.length || 0) - 1) * 100; const y = 100 - point.value / maxValue * 100; return `${x},${y}`; }).join(" "); return jsxs("div", { className: 'relative glass-h-full glass-w-full', children: [jsxs("svg", { className: "glass-w-full glass-h-full", viewBox: "0 0 100 100", preserveAspectRatio: "none", children: [showGrid && jsx("g", { children: Array.from({ length: 5 }, (_, i) => jsx("line", { x1: "0", y1: i * 25, x2: "100", y2: i * 25, stroke: "rgba(255,255,255,0.18)", strokeWidth: "0.5" }, i)) }), jsx("polyline", { points: points, fill: "none", stroke: colors?.[0] || "var(--glass-color-primary)", strokeWidth: "2", className: 'drop-shadow-sm' }), data?.dataPoints.map((point, index) => { const x = index / ((data.dataPoints?.length || 0) - 1) * 100; const y = 100 - point.value / maxValue * 100; return jsx("circle", { cx: x, cy: y, r: "2", fill: colors?.[0] || "var(--glass-color-primary)", className: 'hover:r-3 transition-all cursor-pointer' }, index); })] }), jsx("div", { className: 'absolute bottom-0 left-0 right-0 glass-flex glass-justify-between', children: data?.dataPoints.map((point, index) => jsx("div", { className: 'glass-text-xs text-primary/80', children: point.label }, index)) })] }); }; // Simple pie chart renderer const renderPieChart = () => { if (!data?.dataPoints || data.dataPoints.length === 0) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full glass-text-secondary", children: "No data available" }); } const total = data.dataPoints.reduce((sum, d) => sum + d.value, 0); let cumulative = 0; return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full", children: jsx("div", { className: 'relative', children: jsx("svg", { width: "120", height: "120", viewBox: "0 0 120 120", children: data?.dataPoints.map((point, index) => { const percentage = point.value / total; const angle = percentage * 360; const startAngle = cumulative; cumulative += angle; const color = point.color || colors[index % (colors?.length || 0)]; // Calculate path for pie slice const centerX = 60; const centerY = 60; const radius = 50; const startAngleRad = startAngle * Math.PI / 180; const endAngleRad = (startAngle + angle) * Math.PI / 180; const x1 = centerX + radius * Math.cos(startAngleRad); const y1 = centerY + radius * Math.sin(startAngleRad); const x2 = centerX + radius * Math.cos(endAngleRad); const y2 = centerY + radius * Math.sin(endAngleRad); const largeArcFlag = angle > 180 ? 1 : 0; const pathData = [`M ${centerX} ${centerY}`, `L ${x1} ${y1}`, `A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`, "Z"].join(" "); return jsx("path", { d: pathData, fill: color, className: 'hover:opacity-80 transition-opacity cursor-pointer' }, index); }) }) }) }); }; // Sparkline renderer const renderSparkline = () => { if (!data?.dataPoints || data.dataPoints.length === 0) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full glass-text-secondary glass-text-xs", children: "No data" }); } const maxValue = Math.max(...data.dataPoints.map(d => d.value)); const points = data?.dataPoints.map((point, index) => { const x = index / ((data.dataPoints?.length || 0) - 1) * 100; const y = 100 - point.value / maxValue * 100; return `${x},${y}`; }).join(" "); return jsx("svg", { className: 'glass-w-full h-8', viewBox: "0 0 100 100", preserveAspectRatio: "none", children: jsx("polyline", { points: points, fill: "none", stroke: colors?.[0] || "var(--glass-color-primary)", strokeWidth: "3", className: 'drop-shadow-sm' }) }); }; const renderChartContent = () => { if (loading) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full", children: jsx("div", { className: 'w-6 h-6 glass-border-2 glass-border-primary glass-border-t-transparent glass-radius-full animate-spin' }) }); } if (!data) { return jsx("div", { className: "glass-flex glass-items-center glass-justify-center glass-h-full glass-text-secondary", children: "No chart data provided" }); } if (renderChart) { return renderChart ? renderChart(data, { type, colorScheme, colors, showGrid, interactive }) : jsx("div", { children: "Chart not available" }); } switch (type) { case "line": case "area": return renderLineChart ? renderLineChart() : jsx("div", { children: "Line chart not available" }); case "pie": case "donut": return renderPieChart ? renderPieChart() : jsx("div", { children: "Pie chart not available" }); case "sparkline": return renderSparkline(); default: return renderBarChart ? renderBarChart() : jsx("div", { children: "Bar chart not available" }); } }; const renderLegend = () => { if (!showLegend || type === "sparkline" || !data?.dataPoints || data.dataPoints.length === 0) return null; return jsx("div", { className: "glass-flex glass-flex-wrap glass-gap-2", children: data.dataPoints.map((point, index) => { const color = point.color || colors[index % (colors?.length || 0)]; return jsxs("div", { className: "glass-flex glass-items-center glass-gap-1", children: [jsx("div", { className: 'w-3 h-3 glass-radius-sm', style: { backgroundColor: color } }), jsx("span", { className: "glass-text-xs glass-text-secondary", children: point.label })] }, index); }) }); }; return jsx(GlassCore, { ref: ref, className: cn("w-full h-full glass-radius-lg", config.padding, className), ...props, children: jsxs(VStack, { space: "md", className: "glass-h-full", children: [jsxs(HStack, { space: "sm", align: "center", justify: "between", children: [jsxs(VStack, { space: "xs", children: [jsx("h3", { className: cn("font-medium text-foreground", config.title), children: data?.title || "Chart" }), data?.subtitle && jsx("p", { className: cn("glass-text-secondary", config.subtitle), children: data?.subtitle })] }), actions && jsx("div", { className: "glass-flex-shrink-0", children: actions })] }), data?.summary && variant !== "minimal" && jsxs(HStack, { space: "sm", align: "center", children: [data?.summary.total && jsx("div", { className: 'glass-text-lg font-bold text-primary', children: data?.summary.total.toLocaleString() }), data?.summary.change && jsxs(GlassBadge, { variant: data?.summary.trend === "up" ? "success" : data?.summary.trend === "down" ? "error" : "outline", size: "xs", children: [data?.summary.change > 0 ? "+" : "", data?.summary.change, "%"] })] }), jsx("div", { className: cn("flex-1", config.height, type === "sparkline" && "h-auto"), children: renderChartContent() }), renderLegend()] }) }); }); ChartWidget.displayName = "ChartWidget"; export { ChartWidget }; //# sourceMappingURL=ChartWidget.js.map