feat(steps): the order reading is the canvas, not a rail
The first cut drew the code's order as a nested document — a column of boxes, forks as rows of arm columns. Wrong picture: hard to read, and it threw away the thing that made the tree legible. The ask was the canvas back, with the timing fixed: the 200 comes after the token is signed, so it should branch out of it. So the order reading is now the SAME canvas, the same boxes, the same pills, hover and panel — only the graph changes. `ui/src/lib/program-model.ts` walks the server's block tree carrying a set of tails (the steps a next step would follow) and emits one edge per "and then": proshop's login draws the anchor, `User.findOne`, then the fork — `jwt.sign` under one arm with the `200` a row below it, the `401` under the other. A row down is one more thing that has already happened; an arm that answers, returns or throws has nothing leaving it; a helper, a loop, `later` and `together` ride on the line into what they hold. Rows are settled by relaxation, because a step reached twice can make the graph cyclic. A line means "and then" here and "leads to" in the tree, so the key says which. The fork conditions are drawn at rest rather than only for a selected box — `placeLabels` takes an `atRest` flag — because on this picture they are the content, and two ways to one step merge as one condition (`WHEN userExists OR NOT user`), not as two rendered labels stuck together. `StepsRail.svelte` and `RailBlock.svelte` are gone; `StepBox.svelte` stays as the box both readings draw. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
co-authored by
Claude Opus 5
parent
75686502e3
commit
209a07e881
@@ -757,18 +757,22 @@ function layPill(
|
||||
* pill: the pill for a hovered edge that is not the selected screen's is
|
||||
* placed separately by {@link hoverPill}.
|
||||
*/
|
||||
export function placeLabels(model: Picture, selected: string | null): PillLayout {
|
||||
export function placeLabels(model: Picture, selected: string | null, atRest = false): PillLayout {
|
||||
const pills = new Map<string, PillPlacement>();
|
||||
if (selected === null) return { pills, hidden: 0 };
|
||||
if (selected === null && !atRest) return { pills, hidden: 0 };
|
||||
const nodes = new Map(model.layout.nodes.map((n) => [n.id, n]));
|
||||
const lanes = laneCount(model.layerGap);
|
||||
const bounds = { width: model.layout.width, height: model.layout.height };
|
||||
const taken: Rect[] = model.layout.nodes.map((n) => ({ x: n.x, y: n.y, w: n.width, h: n.height }));
|
||||
|
||||
// At rest, only the selected screen's lines are labelled — a picture with a
|
||||
// label on every line is unreadable, and the reader has asked about one box.
|
||||
// A picture whose labels ARE its content says so (`atRest`): the Steps view
|
||||
// in the code's order, where the conditions on the lines are the flow.
|
||||
const candidates = model.layout.edges
|
||||
.filter((e) => e.source === selected || e.target === selected)
|
||||
.filter((e) => atRest || e.source === selected || e.target === selected)
|
||||
.map((edge) => {
|
||||
const end: 'source' | 'target' = edge.source === selected ? 'target' : 'source';
|
||||
const end: 'source' | 'target' = selected !== null && edge.target === selected ? 'source' : 'target';
|
||||
const far = nodes.get(end === 'source' ? edge.source : edge.target);
|
||||
const anchor = far ? portPoint(far, edge.id, end) : { x: 0, y: 0 };
|
||||
return { edge, end, anchor };
|
||||
|
||||
Reference in New Issue
Block a user