Spaces:
Sleeping
Sleeping
| import { cn } from "@/lib/utils" | |
| type Point = { x: number; y: number } | |
| function toPath(points: Point[]) { | |
| if (!points.length) return "" | |
| return points | |
| .map((p, i) => `${i === 0 ? "M" : "L"} ${p.x.toFixed(2)} ${p.y.toFixed(2)}`) | |
| .join(" ") | |
| } | |
| export default function MiniLineChart(props: { values: number[]; className?: string }) { | |
| const w = 420 | |
| const h = 140 | |
| const padX = 10 | |
| const padY = 14 | |
| const max = Math.max(1, ...props.values) | |
| const min = Math.min(0, ...props.values) | |
| const span = Math.max(1, max - min) | |
| const points: Point[] = props.values.map((v, idx) => { | |
| const t = props.values.length <= 1 ? 0 : idx / (props.values.length - 1) | |
| const x = padX + t * (w - padX * 2) | |
| const y = padY + (1 - (v - min) / span) * (h - padY * 2) | |
| return { x, y } | |
| }) | |
| const areaPath = | |
| points.length > 1 | |
| ? `${toPath(points)} L ${points[points.length - 1].x} ${h - padY} L ${points[0].x} ${h - padY} Z` | |
| : "" | |
| return ( | |
| <svg viewBox={`0 0 ${w} ${h}`} className={cn("h-36 w-full", props.className)} role="img" aria-label="trend"> | |
| <defs> | |
| <linearGradient id="trendFill" x1="0" y1="0" x2="0" y2="1"> | |
| <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.25" /> | |
| <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" /> | |
| </linearGradient> | |
| <linearGradient id="trendStroke" x1="0" y1="0" x2="1" y2="0"> | |
| <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.5" /> | |
| <stop offset="60%" stopColor="var(--accent)" stopOpacity="1" /> | |
| <stop offset="100%" stopColor="var(--accent)" stopOpacity="0.6" /> | |
| </linearGradient> | |
| </defs> | |
| <path d={areaPath} fill="url(#trendFill)" /> | |
| <path d={toPath(points)} fill="none" stroke="url(#trendStroke)" strokeWidth="2.6" strokeLinejoin="round" strokeLinecap="round" /> | |
| {points.length ? ( | |
| <circle cx={points[points.length - 1].x} cy={points[points.length - 1].y} r="4.4" fill="var(--accent)" /> | |
| ) : null} | |
| </svg> | |
| ) | |
| } | |