import { For } from "solid-js"; import type { Edge, GraphRow } from "../lib/bindings"; /** * Geometry, in pixels. These match the custom properties in `app.css`; the SVG * needs real numbers to build paths from, and CSS needs them to size the row. */ const LANE_WIDTH = 14; const ROW_HEIGHT = 28; const DOT_RADIUS = 4; /** The centre of a column. */ function centreOf(column: number): number { return column * LANE_WIDTH + LANE_WIDTH / 2; } /** * One line segment as a path. * * Control points sit at the vertical midpoint of the segment, which gives a * smooth S-curve when the line changes column and collapses to a straight * vertical line when it does not — so one formula covers every case. */ function segment(edge: Edge, commitColumn: number): string { const middle = ROW_HEIGHT / 2; let from: [number, number]; let to: [number, number]; switch (edge.kind) { case "through": { from = [centreOf(edge.fromColumn), 0]; to = [centreOf(edge.toColumn), ROW_HEIGHT]; break; } case "toCommit": { from = [centreOf(edge.fromColumn), 0]; to = [centreOf(commitColumn), middle]; break; } case "fromCommit": { from = [centreOf(commitColumn), middle]; to = [centreOf(edge.toColumn), ROW_HEIGHT]; break; } } const bend = (from[1] + to[1]) / 2; return `M ${from[0]} ${from[1]} C ${from[0]} ${bend} ${to[0]} ${bend} ${to[0]} ${to[1]}`; } /** * The lanes and dot for one row. * * Decoration over content that already reads correctly without it, so it is * hidden from assistive technology entirely. Colours come from the `--lane` * custom property, which means the whole graph re-themes in CSS with no * re-render. */ export default function GraphLanes(props: { row: GraphRow }) { const width = () => Math.max(props.row.width, props.row.column + 1) * LANE_WIDTH; return ( ); }