e30e75b5d4
Changesets / Create Version PR (push) Has been cancelled
Deploy Shadcn Registry / Deploy Production (push) Has been cancelled
Template Metrics / LOC + Bundle Size (push) Has been cancelled
Code Quality / Oxlint + Oxfmt (push) Has been cancelled
Code Quality / Template Sync (push) Has been cancelled
Code Quality / Build Changed Packages (push) Has been cancelled
Code Quality / Test Changed Packages (push) Has been cancelled
Deploy Expo Example / Deploy Production (push) Has been cancelled
Deploy Ink Example / Deploy Production (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-stream, 3.12) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Has been cancelled
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Has been cancelled
57 lines
1.3 KiB
TypeScript
57 lines
1.3 KiB
TypeScript
import { cn } from "@/lib/utils";
|
|
|
|
type Props = {
|
|
values: number[];
|
|
className?: string;
|
|
width?: number;
|
|
height?: number;
|
|
};
|
|
|
|
export function Sparkline({
|
|
values,
|
|
className,
|
|
width = 64,
|
|
height = 18,
|
|
}: Props) {
|
|
if (values.length < 2) return null;
|
|
|
|
const max = Math.max(...values);
|
|
const min = Math.min(...values);
|
|
const range = Math.max(1, max - min);
|
|
|
|
const stepX = width / (values.length - 1);
|
|
const points = values.map((v, i) => {
|
|
const x = i * stepX;
|
|
const y = height - ((v - min) / range) * (height - 2) - 1;
|
|
return [x, y] as const;
|
|
});
|
|
|
|
const linePath = points
|
|
.map(([x, y], i) => `${i === 0 ? "M" : "L"}${x.toFixed(2)} ${y.toFixed(2)}`)
|
|
.join(" ");
|
|
|
|
const areaPath = `${linePath} L${width.toFixed(2)} ${height} L0 ${height} Z`;
|
|
|
|
return (
|
|
<svg
|
|
width={width}
|
|
height={height}
|
|
viewBox={`0 0 ${width} ${height}`}
|
|
preserveAspectRatio="none"
|
|
className={cn("text-foreground/60", className)}
|
|
role="img"
|
|
>
|
|
<title>Weekly downloads trend</title>
|
|
<path d={areaPath} fill="currentColor" fillOpacity={0.08} />
|
|
<path
|
|
d={linePath}
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth={1.25}
|
|
strokeLinejoin="round"
|
|
strokeLinecap="round"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|