feat(frontend): wire Vite app to FastAPI parser with NDJSON streaming + Upload page

This commit is contained in:
Tyler
2026-06-19 17:31:59 -06:00
parent 999889ecb3
commit 3d3bdfb07c
44 changed files with 7811 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
interface SparklineProps {
values: number[];
className?: string;
}
/**
* Minimal SVG sparkline. Normalises to its own range, draws a stroked line
* with a soft fill, and marks the last point. Stretch-friendly via
* preserveAspectRatio="none" + non-scaling-stroke.
*/
export function Sparkline({ values, className }: SparklineProps) {
if (!values || values.length < 2) return null;
const w = 100;
const h = 28;
const min = Math.min(...values);
const max = Math.max(...values);
const range = max - min || 1;
const pts = values.map((v, i) => {
const x = (i / (values.length - 1)) * w;
const y = h - ((v - min) / range) * (h - 4) - 2;
return [x, y] as const;
});
const line = pts
.map((p, i) => `${i === 0 ? "M" : "L"}${p[0].toFixed(2)} ${p[1].toFixed(2)}`)
.join(" ");
const area = `${line} L ${w} ${h} L 0 ${h} Z`;
const last = pts[pts.length - 1]!;
return (
<svg
className={className}
viewBox={`0 0 ${w} ${h}`}
preserveAspectRatio="none"
width="100%"
height="36"
aria-hidden="true"
>
<path d={area} fill="hsl(var(--accent) / 0.13)" />
<path
d={line}
fill="none"
stroke="hsl(var(--accent))"
strokeWidth="1.4"
strokeLinecap="round"
strokeLinejoin="round"
vectorEffect="non-scaling-stroke"
/>
<circle
cx={last[0]}
cy={last[1]}
r="2"
fill="hsl(var(--accent))"
vectorEffect="non-scaling-stroke"
/>
</svg>
);
}