import type { ChannelFlow } from "yt-dlp-transcript-common/views/pipeline/channelFlow"; import { GapFoot, GapHead, GapRail } from "./FlowGap"; import { StationFoot, StationHead, StationRail } from "./FlowStation"; // THE CHANNEL LINE. // // A transit diagram, not a row of cards. Stations are stages; the gap between // two stations carries the shortfall. The one structural trick is the LAYOUT // CONTRACT: every cell emits exactly three children — // // row 1 the station numeral (gaps contribute nothing) // row 2 the rail: a dot for a station, a track for a gap // row 3 the coverage note / the shortfall + its sidings // // — and the parent is a 3-row column-flow grid on md+. That is what keeps every // dot on one horizontal rule no matter how tall the labels above them run, with // no absolute positioning and no measured heights. // // On a narrow screen the same DOM stacks vertically in reading order, which is // the natural form for a transit diagram in a column: label, count, dot, // coverage, then the track and the shortfall leading into the next station. export function ChannelLine({ flow, slug, }: { flow: ChannelFlow; slug: string; }) { const cells: ( | { kind: "station"; index: number } | { kind: "gap"; index: number } )[] = []; flow.stations.forEach((_, i) => { cells.push({ kind: "station", index: i }); if (i < flow.gaps.length) cells.push({ kind: "gap", index: i }); }); // Stations size to their content; gaps take the slack, so the line stretches // to the card and the negative space is genuinely negative space. const gridTemplateColumns = cells .map((c) => (c.kind === "station" ? "max-content" : "minmax(3rem,1fr)")) .join(" "); return (
{cells.map((cell) => { if (cell.kind === "station") { const station = flow.stations[cell.index]; return [ , , , ]; } const gap = flow.gaps[cell.index]; return [ , , 0} />, ]; })}
); }