Files
wireguard-ui/src/pages/admin/(partials)/sparkline.tsx
T
2026-09-13 06:53:33 +01:00

63 lines
1.6 KiB
TypeScript

import { twMerge } from "tailwind-merge";
type Props = {
data: number[];
width?: number;
height?: number;
className?: string;
};
export default function Sparkline({
data,
width = 120,
height = 44,
className,
}: Props) {
const min = Math.min(...data);
const max = Math.max(...data);
const range = max - min || 1;
const stepX = width / (data.length - 1);
const pad = 3;
const points: [number, number][] = data.map((value, index) => [
index * stepX,
height - pad - ((value - min) / range) * (height - pad * 2),
]);
const linePath = points
.map(
([x, y], index) =>
`${index == 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`,
)
.join(" ");
const areaPath = `${linePath} L${width},${height} L0,${height} Z`;
const last = points[points.length - 1]!;
return (
<svg
width={width}
height={height}
viewBox={`0 0 ${width} ${height}`}
className={twMerge("overflow-visible", className)}
aria-hidden="true"
>
<path d={areaPath} fill="currentColor" opacity="0.08" />
<path
d={linePath}
fill="none"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<circle
cx={last[0]}
cy={last[1]}
r="2.5"
fill="currentColor"
/>
</svg>
);
}