diff --git a/frontend/src/components/git/ForgejoHeatmap.tsx b/frontend/src/components/git/ForgejoHeatmap.tsx index e1cc537..f389a62 100644 --- a/frontend/src/components/git/ForgejoHeatmap.tsx +++ b/frontend/src/components/git/ForgejoHeatmap.tsx @@ -129,16 +129,24 @@ function fmtCommitTitle(date: string, count: number): string { } // Catmull-Rom → cubic bezier smooth path -function smoothPath(pts: { x: number; y: number }[]): string { +function smoothPath( + pts: { x: number; y: number }[], + yMin?: number, + yMax?: number, +): string { if (pts.length < 2) return ""; const t = 1 / 6; + const cy = (y: number) => + yMin !== undefined && yMax !== undefined + ? Math.max(yMin, Math.min(yMax, y)) + : y; let d = `M${pts[0].x.toFixed(1)},${pts[0].y.toFixed(1)}`; for (let i = 0; i < pts.length - 1; i++) { const p0 = pts[Math.max(0, i - 1)], p1 = pts[i], p2 = pts[i + 1], p3 = pts[Math.min(pts.length - 1, i + 2)]; - d += ` C${(p1.x + t * (p2.x - p0.x)).toFixed(1)},${(p1.y + t * (p2.y - p0.y)).toFixed(1)} ${(p2.x - t * (p3.x - p1.x)).toFixed(1)},${(p2.y - t * (p3.y - p1.y)).toFixed(1)} ${p2.x.toFixed(1)},${p2.y.toFixed(1)}`; + d += ` C${(p1.x + t * (p2.x - p0.x)).toFixed(1)},${cy(p1.y + t * (p2.y - p0.y)).toFixed(1)} ${(p2.x - t * (p3.x - p1.x)).toFixed(1)},${cy(p2.y - t * (p3.y - p1.y)).toFixed(1)} ${p2.x.toFixed(1)},${p2.y.toFixed(1)}`; } return d; } @@ -274,7 +282,7 @@ function LineChart({ }; }); - const linePath = smoothPath(pts); + const linePath = smoothPath(pts, LP_T, LP_T + LCH); const last = pts[pts.length - 1], first = pts[0]; const baseline = LP_T + LCH;