diff --git a/frontend/src/components/Dashboard/ui/core/controls.check.ts b/frontend/src/components/Dashboard/ui/core/controls.check.ts new file mode 100644 index 0000000..0668b06 --- /dev/null +++ b/frontend/src/components/Dashboard/ui/core/controls.check.ts @@ -0,0 +1,60 @@ +/** + * The tick-label thinning, checked. + * + * ponytail: a script rather than a suite, matching `color.check.ts` — pure + * arithmetic needs no browser: + * + * cd frontend && bun run src/components/Dashboard/ui/core/controls.check.ts + */ +import assert from "node:assert/strict" +import { fitMarks } from "./controls" + +const marks = (...labels: string[]) => labels.map((label) => ({ label })) +const labels = (kept: { label: string }[]) => kept.map((m) => m.label) + +const five = marks("20", "20.5", "21", "21.5", "22") + +// Unmeasured, so nothing is thinned yet. +assert.deepEqual(fitMarks(five, 0), five) + +// Two labels are the ends themselves and can never crowd. +assert.deepEqual(fitMarks(marks("0", "1"), 1), marks("0", "1")) + +// The default four columns keeps all five. +assert.deepEqual(labels(fitMarks(five, 261)), [ + "20", + "20.5", + "21", + "21.5", + "22", +]) + +// Three columns thins to the whole numbers, ends included. +assert.deepEqual(labels(fitMarks(five, 177)), ["20", "21", "22"]) + +// Across every width: the ends survive, and the stride divides the intervals +// so the last label lands on the end rather than short of it. Four intervals +// may thin by 1, 2 or 4 — never 3. +for (let width = 1; width <= 600; width++) { + const kept = labels(fitMarks(five, width)) + assert.equal(kept[0], "20", `first lost at ${width}px`) + assert.equal(kept[kept.length - 1], "22", `last lost at ${width}px`) + assert.ok( + [2, 3, 5].includes(kept.length), + `${kept.length} labels at ${width}px`, + ) +} + +// Six marks reach the divisor guard that five cannot: at this width the +// narrowest stride that fits is 3, which does not divide five intervals and +// would drop the last label. It must fall through to 5 and keep both ends. +const six = marks("0", "1", "2", "3", "4", "5") +assert.deepEqual(labels(fitMarks(six, 60)), ["0", "5"]) + +// Wider labels thin sooner than narrow ones at the same width. +assert.ok( + fitMarks(marks("1000.5", "1001", "1001.5"), 120).length <= + fitMarks(marks("1", "2", "3"), 120).length, +) + +console.log("fitMarks: ok")