Files
stats/apps/public/components/simple-chart.tsx
2024-11-13 21:15:46 +01:00

71 lines
1.7 KiB
TypeScript

import { useMemo } from 'react';
interface SimpleChartProps {
width?: number;
height?: number;
points?: number[];
strokeWidth?: number;
strokeColor?: string;
className?: string;
}
export function SimpleChart({
width = 300,
height = 100,
points = [0, 10, 5, 8, 12, 4, 7],
strokeWidth = 2,
strokeColor = '#2563eb',
className,
}: SimpleChartProps) {
// Skip if no points
if (!points.length) return null;
// Calculate scaling factors
const maxValue = Math.max(...points);
const xStep = width / (points.length - 1);
const yScale = height / maxValue;
// Generate path commands
const pathCommands = points
.map((point, index) => {
const x = index * xStep;
const y = height - point * yScale;
return `${index === 0 ? 'M' : 'L'} ${x},${y}`;
})
.join(' ');
// Create area path by adding bottom corners
const areaPath = `${pathCommands} L ${width},${height} L 0,${height} Z`;
// Generate unique gradient ID
const gradientId = `gradient-${strokeColor
.replace('#', '')
.replaceAll('(', '')
.replaceAll(')', '')}`;
return (
<svg
viewBox={`0 0 ${width} ${height}`}
className={`w-full ${className ?? ''}`}
>
<defs>
<linearGradient id={gradientId} x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stopColor={strokeColor} stopOpacity="0.3" />
<stop offset="100%" stopColor={strokeColor} stopOpacity="0" />
</linearGradient>
</defs>
{/* Area fill */}
<path d={areaPath} fill={`url(#${gradientId})`} />
{/* Stroke line */}
<path
d={pathCommands}
fill="none"
stroke={strokeColor}
strokeWidth={strokeWidth}
/>
</svg>
);
}