ref
References another node so later marks can reuse its position or bounding box — the basis for overlays, connectors, and arrows.
See also How to name and scope for when to use strings vs. tokens vs. paths.
Signature
ref(
nodeOrSelection:
| string // layer-local lookup
| Token // global lookup; chainable as ref(token).foo[i].bar
| (Token | string | number)[] // path (array form)
| GoFishNode // direct node
| { __ref: GoFishNode }
);Forms
String — layer-local
ref("x") walks up the parent chain to the nearest Layer and picks the direct child named .name("x"). Strings do not cross component boundaries.
Layer([
rect({ w: 80, h: 40 }).name("bg"),
ref("bg"), // resolves to the rect above
]);Token — globally addressable
A Token (from createName) is a unique JS value. .name(token) registers the node in a global token context; ref(token) retrieves it.
const targetName = createName("target");
Layer([
rect({ w: 80, h: 40 }).name(targetName),
// ...somewhere in a sibling subtree:
ref(targetName),
]);Path — step through scopes + positional children
A path starts at a Token and descends one step per segment. Tag strings resolve against the current node's scope map (populated by createName-tagged children inside a scope root). Numbers pick the positional child at that index.
Two equivalent spellings:
// Chained (proxy) — preferred for static paths
ref(globalFrameName).variables[2].value;
// Array — useful when segments are dynamic
ref([globalFrameName, "variables", 2, "value"]);The chained form is a Proxy that wraps the underlying GoFishRef; instanceof GoFishRef still holds, so it can go anywhere a ref is expected.
For variadic dynamic segments (e.g. spreading a [row, col] tuple into the path), use .path(...):
const cell = addrPos.get(addr)!; // [row, col]
ref(heapName).path(...cell).elmTuples[0];
// equivalent to:
ref([heapName, ...cell, "elmTuples", 0]);Reserved names. Children registered with one of GoFishRef's own property names (name, type, parent, dims, layout, place, color, …), the escape-hatch method path, or JS-language names (then, toString, constructor, __proto__, …) are not reachable via dotted access. Use ref(token).path("name") or the array form for those.
Direct node
Pass a GoFishNode (or a .__ref wrapper) to reference it without name resolution.
const bar = rect({ h: "value" });
Layer([bar, ref(bar)]);Parameters
| Parameter | Type | Description |
|---|---|---|
nodeOrSelection | string | Token | (Token | string | number)[] | GoFishNode | { __ref: GoFishNode } | What to reference. See forms above — string (local), Token (global), path, or the node. |
Notes
- Refs participate in layout: the referenced node's placement determines the ref's bounding box, and
Arrow,connect, etc. use that to draw geometry between nodes. - Cross-subtree refs resolve correctly: the ref traverses to the least common ancestor and accumulates coordinate transforms along the way, so you can ref a node inside one component from inside another.
- Errors name the scope: if a path segment misses, the error lists the tags or indices available at that level.
