/** * The nested paint, flattened into addressable nodes. * * A renderer wants two things the nested tree cannot give it: a name for every * node it can hold onto, and a way to reach one node without walking to it. An * id from the STRUCTURAL PATH gives both — and because the path uses the * component's `key` wherever it wrote one, the id of a row survives a repaint * that inserts a row above it. Downstream that id becomes the React key, so * state inside the rendered kit (an open menu, a focused input, a scroll * position) survives the repaint too. An id built from a running counter would * not: every row below the insert would be renamed and remounted. * * The format reads as the walk that produced it — `root.0.Card:tr_129.1`. * * The VM's handler ids are minted against the SAME path (plus the prop name), * so a node's id and the ids of its handlers agree by construction. * * THE ONE CAVEAT, and the reason a key is worth writing: a position is a * position. A keyless sibling that appears — the `{error && }` above a * list — renumbers every keyless sibling after it, so those ids change and the * kit remounts them. React has the same property, which is why keys exist; * anything conditional or repeated wants one. */ import { type FlatNode, type FlatTree, type NestedNode } from "./types.js"; /** * Flatten one paint. Total and pure: every node in, every node out, ids * deterministic for an unchanged position. * * A text child becomes a node of its own — component {@link SCREEN_TEXT_NODE}, * its text in `props.text` — so `children` is unambiguously a list of ids and a * renderer never has to guess whether `"root"` is an id or the word. * * Two siblings written with the SAME key would claim one id (React warns about * exactly this); the second and later take a `~2` suffix rather than * overwriting the first, so a duplicate key costs stability, never a node. * * `source` is whoever asked for the paint saying what this SCREEN is, stamped on * every node it emits — the VM emits elements, not provenance, so there is no * finer truth to be had here. The gauntlet is the only hand that sets it, and it * sets it off the DIALECT the screen was type-checked in * (server/checking/screen-typings.ts), which is what actually holds the class * boundary; a screen has no way to name its own. */ export declare function flattenTree(root: NestedNode, source?: FlatNode["source"]): FlatTree; //# sourceMappingURL=flatten.d.ts.map