diff --git a/src/client/components/Timeline.tsx b/src/client/components/Timeline.tsx index 4ab5c5b..17e1345 100644 --- a/src/client/components/Timeline.tsx +++ b/src/client/components/Timeline.tsx @@ -1,4 +1,4 @@ -import { useLayoutEffect, useRef } from "react"; +import { Fragment, useLayoutEffect, useRef } from "react"; import { useGameMeta } from "../state/gameMeta.tsx"; import { DAY } from "../../shared/time.ts"; import type { RowEvent } from "./EventRow.tsx"; @@ -350,6 +350,8 @@ export function Timeline({
+ Not started yet +
+ ); +} + +/** + * The index of the first row that has not started, or -1 when none has. + * + * A single index rather than a per-row test, because the label marks a + * *boundary* and there is only one: every sort this board can be given puts + * live rows before upcoming ones — `endingSoonestFirst` on the merged board, + * and both list modes in the lanes, which say so explicitly. If that ever + * stopped holding, the honest repair is to fix the order rather than to scatter + * the label wherever the sequence flips. + * + * Exported so the guarantee is a test rather than a comment. + */ +export function splitAt( + rows: readonly { clock: { upcoming: boolean } }[], +): number { + return rows.findIndex((r) => r.clock.upcoming); +} + /** * One step of the scale control. * diff --git a/test/views.test.tsx b/test/views.test.tsx index 38e90ea..227f833 100644 --- a/test/views.test.tsx +++ b/test/views.test.tsx @@ -4,6 +4,7 @@ import { NextUp } from "../src/client/components/NextUp.tsx"; import { boardWindow, markerLabel, + splitAt, startMarkers, Timeline, } from "../src/client/components/Timeline.tsx"; @@ -305,14 +306,14 @@ describe("Timeline: events that have not started", () => { upcoming("Long Way Round", "wuwa", 30 * 24), ]; - const board = (showUpcoming: boolean, all = rows) => + const board = (showUpcoming: boolean, all = rows, group: "game" | "ending" = "ending") => render(