aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
340 lines (337 loc) • 12.7 kB
JavaScript
'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