Documentation
    Preparing search index...

    Class Toggle

    §73's toggle (switch) — a control whose activation applies immediately.

    State-identical to Checkbox; see this module's header for why both ship. Give it accessibility: { role: "switch", label: … } (§75).

    Hierarchy (View Summary)

    Index

    Cross-axis placement. Default "start".

    anchor: Vector2

    Where in the parent's content box this widget attaches, normalized: (0, 0) is the top-left corner, (1, 1) the bottom-right (§74 anchor). Absolute layout only.

    clip: boolean

    Whether this node's own drawn shape clips its subtree (§67; R-23, 2026-08-21). Default false.

    panel.clip = true;          // children are masked to the panel's shape
    panel.add(content); // …including everything below them

    The mask is the node's own geometry, drawn with colour writes off, so a §50 Shape clips to its path, a rectangle clips to a rectangle, and a Sprite clips to its quad — §67's "path masks" and "UI overflow clipping" with no second authoring surface and nothing new to build a region out of. @fourjs/render's clip.ts states the tier and what it deliberately leaves to a later packet (alpha masks, 3D clipping planes, true scissor rectangles).

    The clip gates this node's descendants and not this node, which is the exact mirror of layers above (§46 gates the node and not its subtree). That is what a UI panel needs — it paints its own background and border and then contains its children — and it is why the two fields sit next to each other with opposite scopes rather than sharing a spelling.

    Nested clips intersect: a clipped subtree that contains another clip draws only where both shapes cover. Eight clips can be live in one frame, because a stencil bit plane is spent on each and every stencil buffer WebGL 2 can allocate is eight bits deep; the ninth is dropped with a §67 diagnostic, and its subtree spills rather than vanishing (see ClipPlaneAllocator).

    Two conditions make this field inert, both warned about in a development build and both failing toward drawing rather than toward an empty screen: a node with no geometry to draw (a plain Group) has no shape to mask with, and a renderer whose drawing buffer carries no stencil buffer (new WebglRenderer({ stencil: true }), R-7) has nothing to write a mask into.

    A plain field, like visible and layers and for the same reason: the render list reads it once per node per frame and there is no value it can hold that §85 would refuse.

    direction: LayoutDirection

    Main axis for stack and flex. Default "row".

    enabled: boolean

    Whether this node participates in simulation and updates (§6). Default true.

    focusable: boolean

    Whether a pointer press on this widget takes the focus. false by default: a panel is not a focus target, a button is (see Button).

    gap: number

    Space between adjacent children, in layout units. Default 0.

    grow: number

    Share of a flex container's leftover main-axis space this widget claims (§74 flex). 0 — the default — never grows. Ignored by absolute and stack layout.

    height: number | null

    Requested height in layout units, or null for the intrinsic height.

    hitTestMode: HitTestMode | null

    Which §71 hit-test strategy answers for this node, or null — the default — for §71's own default rule: "the engine should select the cheapest valid method" (A-11; the field ships with the analytic tier per the adopted RFC 0005 Q3, 2026-08-29).

    mesh.hitTestMode = "geometry";   // exact ray/triangle, never just the box
    decal.hitTestMode = "pixel"; // a hit must land on a present texel
    hull.hitTestMode = "bounds"; // the box alone, whatever data is attached
    boid.hitTestMode = "gpu"; // the id-buffer pass answers, not the ray

    The node carries only the choice; the data each strategy needs rides the Pickable candidate (@fourjs/input may not import @fourjs/geometry or a render type, plan §3.1 — the recorded reason picking takes a structural candidate list). Under null, pick() runs the bounding-volume test and refines it by whatever the candidate carries — triangles, an alpha mask, or nothing — which is the cheapest method that is valid for that candidate, and is byte-for-byte the pre-field behaviour. An explicit mode selects exactly one strategy and requires its data (§85: a candidate that asked for precision and silently fell back would pick where the author said not to); "gpu" excludes the node from the ray tier altogether, because RFC 0005's id-buffer pass is that strategy's implementation and one pointer event must not resolve the node twice.

    The mode gates this node only, not its subtree — the layers scope, not the clip scope: every descendant is its own picking candidate with its own mode, exactly as it is its own layer member.

    §71's "custom" value is deliberately absent from the union: no custom-callback strategy exists yet, and a selector value with nothing behind it would be a silent no-op. It joins HitTestMode with that strategy.

    A plain field, like visible, layers and clip, and for their reason: pick() reads it once per candidate per pick, and the union is the check — there is no assignable value §85 would refuse (a §79 document's value is filtered on read instead, restoring null for anything unrecognized).

    id: string

    Stable identity (§6). Engine-assigned at construction from a monotonic counter, formatted node-<n>; ids are unique within a process and ascending in construction order.

    readonly, as §6 requires. §79 additionally requires that a deserialized node keep the id it was saved with ("the engine assigns ids only to newly created objects"): pass NodeOptions.id to restore one, which also reserves it against the counter (2026-08-06, A-17 — the note that used to stand here deferred this to the serialization packet, which shipped without it).

    justify: LayoutJustify

    Main-axis distribution of leftover space. Default "start".

    layers: number

    Which §46 layers this node belongs to, as a bit mask (R-38, 2026-08-08).

    Defaults to DEFAULT_LAYER_MASK — the layer named "default", and nothing else — so a scene that never mentions layers is seen by every camera and every viewport, whose own masks default to ALL_LAYERS.

    node.layers = layerMask("ui");            // one layer
    node.layers = layerMask("ui", "debug"); // two
    applyLayers(panel, layerMask("ui")); // this node *and* its subtree

    The mask gates this node only, not its subtree: a child on another layer is unaffected by what its parent is on, which is the opposite of visible/enabled and is a recorded decision — see layers.ts for the reasoning and for the subtree spelling.

    A plain field, like visible and tags, rather than a validated accessor: the render list reads it once per node per frame, and §85's checks are made where a mask is built (layerMask) and where one is accepted from an author (assertLayerMask), not on every read of a hot field.

    Not to be confused with Renderable.renderLayer (§49), which is §66's sort ordinal rather than a membership mask.

    layoutType: LayoutType

    Which of §74's modes places this panel's children. Default "absolute".

    margin: Insets

    Space outside this widget's box, reserved by its parent's layout (§74).

    Honoured by stack and flex layout. Absolute layout ignores margins: an absolutely positioned child is placed by its anchor, pivot, and offset, and folding a fifth and sixth number into that arithmetic makes the result unpredictable rather than expressive (decision, WP-11.3).

    maxHeight: number

    Upper bound on UIWidget.measuredHeight. Default Infinity.

    maxWidth: number

    Upper bound on UIWidget.measuredWidth (§74 maximum size). Default Infinity.

    metadata: Record<string, unknown>

    Free-form user data (§6). Its own object per node.

    minHeight: number

    Lower bound on UIWidget.measuredHeight. Default 0.

    minWidth: number

    Lower bound on UIWidget.measuredWidth (§74 minimum size). Default 0.

    name: string

    Human-readable name (§6); not unique and not an identity. Empty by default.

    offset: Vector2

    Displacement applied after anchoring, in layout units, +x right and +y down. Absolute layout only.

    opacity: number

    Opacity in [0, 1] (§6). Default 1. Not clamped here.

    padding: Insets

    Space inside this widget's box, between its edges and its content (§74). Never replaced — write into it.

    pivot: Vector2

    Which point of this widget lands on the anchor, normalized the same way: (0, 0) is its own top-left, (0.5, 0.5) its centre. Absolute layout only.

    tags: Set<string>

    Free-form tags, queried by Scene.findByTag (§46). Empty by default.

    transform: Transform

    Local transform (§7). Never replaced — write into it.

    transformAuthority: TransformAuthority

    Which system owns this node's transform (§42). Default "manual".

    §42 spells this as a plain assignable field — node.transformAuthority = "physics" — and that is exactly what it is: read it, write it, one value at a time. Every value of TransformAuthority assigns, "blended" included: it was guarded by a FourError("NOT_IMPLEMENTED") between WP-2.3 and WP-7.3, because nothing implemented §19's physics-animation pipeline and a node claiming it would have been owned by a system that did not exist. PhysicsWorld now runs that pipeline (@fourjs/physics, plan P7-4), so the guard is gone and the value means what §42 says it means.

    A "blended" node is driven by §19's pipeline, which needs two more things this field cannot check for — a RigidBody registered with a PhysicsWorld and a PoseTarget on the node. The first step that tries to blend a node with no target throws FourError naming it; see PhysicsWorld.step. Assigning the authority is never itself an error, exactly as "kinematic" on a node no controller drives is not.

    Enforcement lives in the writing systems (see warnAuthorityConflict), not here: Node records ownership, systems honour it.

    visible: boolean

    Whether this node renders (§6). Default true.

    width: number | null

    Requested width in layout units, or null for the intrinsic width (§74's "intrinsic text/image size" — see UIWidget.measureIntrinsic).

    Requested, not resolved: UIWidget.measuredWidth is the answer, after clamping and after a "stretch" or growing parent has had its say.

    • get accessibility(): WidgetAccessibility | null

      §75's accessibility record, or null. Assigning replaces the record and notifies an installed DOM mirror. Mutating fields in place does not — assign a new object, write UIWidget.label / UIWidget.role, or call mirror.sync(widget).

      Returns WidgetAccessibility | null

    • set accessibility(value: WidgetAccessibility | null): void

      Parameters

      Returns void

    • get accessibilityVersion(): number

      Generation of this widget's accessibility surface. Incremented by every setter that a mirror cares about (disabled, checked, value, label / role / accessibility). An installer that would rather poll than subscribe compares this against the last value it projected.

      Returns number

    • get checked(): boolean

      Whether this control is checked (§75). Never null for a checkable one.

      Returns boolean

    • set checked(value: boolean): void

      Sets the checkedness, emitting uistatechange when it actually changed.

      Programmatic and unconditional: unlike an activation it is refused by nothing, because setting the state of a disabled control is how an application restores one, and refusing it would silently desynchronize the widget from the model it mirrors.

      Parameters

      • value: boolean

      Returns void

    • get children(): readonly Node[]

      Children in insertion order (§6).

      The live array is returned as a readonly view rather than a copy, so reading children allocates nothing on hot paths. It is a view, not a snapshot: it reflects later mutations, and casting the readonly away to mutate it corrupts the parent pointers this class maintains.

      Returns readonly Node[]

    • get components(): IterableIterator<Component>

      The components attached to this node, in attach order (§6a, 2026-08-06 A-15).

      A live iterator over the registry's own map, so reading it allocates nothing and reflects the node's current state; do not attach or detach while iterating (the underlying Map would be mutated mid-walk). Copy it first — [...node.components] — for a snapshot.

      Enumeration exists for §79. Without it a serializer cannot walk what a node has; it can only probe for what it knows about, and a component whose type has no registered serializer is then dropped from the document with nobody able to notice — a save that silently loses state, which is the one failure mode that design could not warn about. @fourjs/serialization walks this getter and refuses an unserializable component by name.

      ComponentHost (§6a, @fourjs/core) does not declare it: the host contract is what a component sees of its owner, and a component enumerating its siblings is not something §6a sanctions.

      Returns IterableIterator<Component>

    • get contentHeight(): number

      Height available inside the padding — never negative.

      Returns number

    • get contentWidth(): number

      Width available inside the padding — never negative.

      Returns number

    • get disabled(): boolean

      §75's disabled state. Disabling clears hover, press, and focus (blurring emits blur), and refuses every later interaction until it is cleared.

      Returns boolean

    • set disabled(value: boolean): void

      Parameters

      • value: boolean

      Returns void

    • get disposed(): boolean

      Whether UIWidget.dispose has run.

      Returns boolean

    • get focused(): boolean

      This widget holds its scene root's focus (§75).

      Returns boolean

    • get hitArea(): Pickable

      This widget as a picking candidate (§71), with bounds (0, −height, 0) … (width, 0, 0) in its own local space.

      The box is flat: UI is a plane, and pick intersects a zero-depth box exactly as long as the ray is not parallel to it. Two coplanar widgets that overlap therefore tie on distance and resolve by candidate order — see collectPickables.

      Returns Pickable

    • get hovered(): boolean

      A pointer is over this widget's hit area.

      Returns boolean

    • get interactive(): boolean

      Whether pointer events change this widget's state. true by default; turning it off clears hover and press and drops the widget from collectPickables.

      Returns boolean

    • set interactive(value: boolean): void

      Parameters

      • value: boolean

      Returns void

    • get label(): string | undefined

      Accessible name (§75). Writes accessibility.label, creating the record when there is not one yet. Empty-string is stored as authored; undefined removes the field.

      Returns string | undefined

    • set label(value: string | undefined): void

      Parameters

      • value: string | undefined

      Returns void

    • get layoutLeft(): number

      Distance from the parent's origin to this widget's left edge, as the last arrange pass placed it. 0 for a root, which nothing lays out.

      Returns number

    • get layoutTop(): number

      Distance down from the parent's origin to this widget's top edge.

      Returns number

    • get measuredHeight(): number

      Height resolved by the last measure pass.

      Returns number

    • get measuredWidth(): number

      Width resolved by the last measure pass, in layout units.

      Returns number

    • get parent(): Node | null

      This node's parent, or null when it is a root (§6).

      Assignment is supported and is defined in terms of the hierarchy methods: node.parent = other is other.add(node) (including its cycle check and its detach-from-the-old-parent step) and node.parent = null is oldParent.remove(node). It is never a bare field write, because a bare write could not keep the two children arrays consistent.

      Returns Node | null

    • set parent(value: Node | null): void

      Parameters

      Returns void

    • get position(): Vector3

      Alias for this.transform.position — the same live Vector3, never a copy, so node.position.set(1, 2, 3) and node.transform.position.set(1, 2, 3) are one and the same write and both run the transform's change hook (plan D3: the version bumps, dependent caches invalidate).

      The spec writes this spelling throughout — Four.animate(node.position) (§15), camera.position.set(0, 2, 6) and label.position.set(0, 1.2, 0) (§97) — while Transform is where the value actually lives (§7). This getter makes both spellings work, resolving the WP-3.1 ergonomics flag (TODO: Node.position/rotation/scale aliases onto transform.*).

      Getter only, deliberately: Transform.position is a readonly property holding a mutable vector — replacing the instance would silently drop the change hook — and the alias mirrors exactly that contract. Assignment (node.position = v) is not the API; write into the vector with .set(...) / .copy(...).

      Transform authority (§42) is unmoved by the spelling: a write through this alias is a write to the node's transform, and a system that is not the node's Node.transformAuthority must not make it either way.

      Returns Vector3

    • get pressed(): boolean

      A pointer is pressed on this widget.

      Returns boolean

    • get role(): string | undefined

      Semantic role (§75). Writes accessibility.role with the same create-or- mutate rule as UIWidget.label.

      Returns string | undefined

    • set role(value: string | undefined): void

      Parameters

      • value: string | undefined

      Returns void

    • get rotation(): Quaternion

      Alias for this.transform.rotation — the same live Quaternion, never a copy. Radians semantics per §7a; getter only, for the reasons documented on Node.position (mutate via quaternion methods, never by assignment). Writes through it bump the transform version exactly as transform.rotation writes do, and §42 authority applies unchanged.

      Returns Quaternion

    • get scale(): Vector3

      Alias for this.transform.scale — the same live Vector3, never a copy. Getter only, for the reasons documented on Node.position (mutate via .set(...) / .copy(...), never by assignment). Writes through it bump the transform version exactly as transform.scale writes do, and §42 authority applies unchanged.

      Returns Vector3

    • get skin(): WidgetSkin | null

      The application-supplied visuals of this widget, or null. See WidgetSkin and this module's header.

      Returns WidgetSkin | null

    • set skin(value: WidgetSkin | null): void

      Parameters

      Returns void

    • Emits uiactivate and returns whether it fired.

      Refused — returning false, emitting nothing — when the button is disposed, UIWidget.disabled, or enabled = false. interactive is deliberately not checked: it governs whether pointers reach the widget, and neither a keyboard nor a programmatic activation is a pointer (the click listener checks it before calling in).

      Public, and it stayed public: the keyboard layer this module's header describes calls it with "keyboard", and an application drives it with the default "programmatic" — one path, one event, three sources.

      Parameters

      Returns boolean

    • Attaches nodes as children, in argument order, appending each to the end of Node.children. Returns this.

      Rules:

      • Cycles (§85). Adding a node to itself, or to any of its own descendants, throws FourError("INVALID_SCENE_GRAPH"). Nothing is attached for that argument.
      • Reparenting. A node that already has a parent is detached from it first, which fires removed on the node before added fires.
      • Re-adding. Adding a node that is already a child of this node is a no-op: it keeps its current index and fires no event. (Decision — the alternative, move-to-end, would make add silently reorder siblings and emit a spurious removed/added pair; callers that want a new index can remove then add.)
      • Partial application. Arguments are validated and attached one at a time, so a throw on the third argument leaves the first two attached. The graph is always left consistent; it is not rolled back.

      Parameters

      Returns this

    • Attaches component to this node (§6a), replacing any component of the same type (with a development warning) and running onAttach with this node as the host. Returns the component.

      Type Parameters

      Parameters

      • component: T

      Returns T

    • Places this widget at (left, top) in its parent's frame and arranges its own children. Engine-internal: a parent's arrange pass calls it.

      The transform write is (left, −top, z) — see the module header on coordinates — and is refused with a §42 warning when this widget's transformAuthority is not UI_LAYOUT_AUTHORITY. Everything else still happens: the refusal is about who owns the position, not about whether the widget has a size.

      Parameters

      • left: number
      • top: number

      Returns void

    • Places every enabled widget child, then lets each arrange its own.

      Returns void

    • Runs immediately before this control becomes checked, whatever caused it — a click, a key, or an assignment. A no-op here.

      RadioButton overrides it to clear its group, which is why it runs before the flip: the peers are already off when this control's uistatechange goes out, so a listener never sees two checked radios.

      Returns void

    • Drops the focus if this widget holds it. Emits blur. Otherwise a no-op.

      Returns void

    • Records the current flags so UIWidget.publishState can diff them.

      protected rather than private since 2026-08-07 (A-12): a control that owns a state flag the base does not — a Toggle's checkedness — brackets its own mutation with these two and inherits the whole publication path (no-change suppression, both snapshots, the skin notification, the event) instead of re-implementing it. There is exactly one buffer per widget, so the two calls must be adjacent: capture, mutate, publish.

      Returns void

    • Releases this widget's own listeners, focus, and skin (§83). Idempotent.

      It does not remove the widget from its parent, dispose its children, or touch whatever a skin built — those are owned by whoever created them.

      Returns void

    • Delivers event to the listeners registered for type in registration order. Re-entrant emission of type is deferred (rule 4).

      Type Parameters

      Parameters

      Returns void

    • Gives this widget the focus of its scene root (§75), blurring whichever widget held it.

      A no-op for a widget that is not UIWidget.focusable, is disabled, is enabled = false, is disposed, or already holds the focus. Emits blur on the previous holder and then focus on this one, each carrying the other as UIFocusEvent.related.

      Returns void

    • Writes the world-space unit vector this node faces — its −Z axis — into out and returns it (§7b's out-parameter convention; nothing allocates).

      −Z is the engine's one forward direction, for every node rather than for cameras alone: a camera looks down it (Camera.viewMatrix, Matrix4.setPerspective), a directional or spot light shines along it (§68), and Node.lookAt aims it. The inverse of lookAt, and the cheapest way to ask where something ended up pointing.

      World transforms are resolved on demand (resolveWorldTransform(this)), exactly as Camera.updateViewMatrix resolves — O(depth), version-cached, so the render path's prior resolve pass makes this a few comparisons. The basis column is normalized, so ancestor scale does not stretch the direction.

      A degenerate node — zero scale somewhere up the chain — yields the zero vector rather than NaN (Vector3.normalize's documented zero-length behaviour): like a degenerate camera (§47), it poisons nothing downstream and raises no error on a per-frame path.

      Parameters

      Returns Vector3

    • Lays this subtree out: one bottom-up measure pass, then one top-down arrange pass. The entry point — call it on the root of a UI tree after changing anything, and never per widget.

      A root's own position is untouched (nothing lays out a root); its size, its hit area, and every descendant are resolved.

      Returns void

    • Number of live registrations for type (diagnostics, §83).

      Type Parameters

      Parameters

      • type: K

      Returns number

    • Number of live listener registrations across every event type (§83).

      Used by teardown diagnostics — a detached node that still holds listeners pins its subtree until those listeners are removed.

      Returns number

    • Turns this node so that its −Z axis points at target, with its +Y axis as close to up as the aim allows (§44/§47's orientation helper — "aiming a camera or a light" without hand-composing quaternions). Returns this.

      camera.position.set(0, 2, 6);
      camera.lookAt(new Vector3(0, 0.5, 0)); // §7a's world +Y is the default up
      sun.lookAt(target, new Vector3(0, 0, 1)); // a light is aimed the same way

      Always, whatever this node is parented to (decision, R-36). A world-space target is the contract that makes the call mean the same thing when a node is later reparented onto a moving rig — the case §44's follow rigs and spring arms exist for — and it is the only one under which "point the camera at the player" is a single call. The local rotation is derived from it: this node's world position comes from its resolved world matrix, the world rotation is built from the aim, and the parent's world rotation is divided out

      localRotation = conjugate(parentWorldRotation) · worldRotation
      

      so a node under a rotated, translated, or uniformly scaled parent aims correctly. A parent with non-uniform scale has no exact rotation to divide out; Matrix4.decompose's closest-rotation reading is used, with the shear it cannot represent left in — the same documented limitation every decomposition in the engine carries. A parent with a zero scale component decomposes to the identity, so the aim lands in world terms.

      The node's own scale and pivot are irrelevant to the result: only the rotation is written, through transform.rotation.copy(...), so the version bumps exactly once (plan D3) and dependent caches invalidate exactly as they do for any other transform write.

      This is an ordinary application transform write: it always lands, the same as node.rotation.setFromAxisAngle(...). A DEV build warns once if Node.transformAuthority is not "manual" (warnApplicationTransformWrite); production is silent. The write is never refused. A rig that wants to aim a node every frame under a non-manual authority has the same obligation as any other writer: claim the authority, or wrap with runOwnedTransformWrite.

      FourError("INVALID_SCENE_GRAPH") is thrown, and nothing is written, when

      • target coincides with this node's world position (or either is non-finite): there is no direction to face; and
      • up is zero, parallel to the aim, or non-finite: the aim leaves the roll about it completely undetermined — the top-down lookAt from directly above with the default +Y up is exactly this case, and wants an explicit up such as world −Z.

      Refusing rather than substituting is §85's "detect singular transforms" applied at the point of authoring, reported under the same code Node.add uses for §85's scene-graph rule so one catch covers both. Silently picking a fallback up — the usual engine behaviour — would rewrite the orientation the caller asked for and hide the mistake behind a plausible-looking roll; leaving the node unturned would be indistinguishable from a frozen rig. A rig that can reach a degenerate configuration (an orbit at zero radius, a follow target that catches its camera) must guard the call, exactly as it must guard a division by its own radius.

      Allocates nothing: the aim, the world rotation, and the parent's rotation live in module scratch.

      Parameters

      Returns this

    • Resolves UIWidget.measuredWidth and UIWidget.measuredHeight, after resolving every enabled widget child. Engine-internal: layout() calls it.

      The requested size wins when given; otherwise the intrinsic size does. Both are clamped into [min, max], and never below zero.

      Returns void

    • The size this panel needs to hold its children, plus its padding — §74's intrinsic sizing, used whenever width/height is null.

      Parameters

      Returns void

    • Bumps UIWidget.accessibilityVersion and notifies every installed DOM mirror. protected so a subclass that owns a field the base does not (a future expanded) can push the same way checked does.

      Returns void

    • Tells the skin that something it draws changed which is neither this widget's box nor one of its §75 states (2026-08-07, A-12) — see WidgetSkin.onContentChange.

      protected because it is the control's own business when its content changed: Slider, ProgressIndicator, and ImageWidget call it, and no caller outside a widget can know better than the widget does. It emits no event: a value change has its own (uivaluechange), and an image's source has no observer but the skin.

      Returns void

    • Emits uistatechange when anything actually changed since UIWidget.captureState, notifying the skin first so a listener sees the widget already looking the way it will look.

      Returns void

    • Detaches nodes from this node, in argument order. Returns this.

      Removing a node that is not a child of this node is a no-op — no throw, no event (decision: removal is idempotent, so teardown paths can call it without first testing parentage).

      Parameters

      Returns this

    • Removes every listener, or every listener of one type. Used by teardown paths that must not leave detached nodes retaining listeners (§83).

      Type Parameters

      Parameters

      • Optionaltype: K

      Returns void

    • Detaches component, running its onDetach; returns false when it is not the component currently attached for its type. Detaching does not dispose (§6a).

      Parameters

      Returns boolean

    • Applies a §74 layout record. Omitted fields keep their current value, so panel.setLayout({ gap: 4 }) changes only the gap. Returns this.

      Parameters

      Returns this

    • Overrides the measured size, clamped into [min, max]. Engine-internal: a flex parent calls it to grow a child, and a "stretch" parent to fill the cross axis. Applications set UIWidget.width instead.

      Parameters

      • width: number
      • height: number

      Returns void

    • Calls visitor on this node, then on every descendant, depth-first in insertion order (§6).

      Children are read live by index rather than from a snapshot, so the walk allocates nothing; the price is that structurally mutating the hierarchy from inside visitor is not supported (removing the current node's successor skips it). Collect first, mutate after.

      Recursive, so depth is bounded by the JS stack — scene graphs thousands of levels deep are out of scope.

      Parameters

      • visitor: (node: Node) => void

      Returns void

    • Flips the checkedness — the activation behaviour of an independent checkable control (§72 click, §75 Enter/Space, or activate()).

      Returns void