Skip to content

App

Defined in: src/core/app.ts:62

Owns a running ztui application: the Driver, the screen stack, focus, input dispatch, theming, and the frame scheduler. Construct one, render() your tree onto activeScreen, then call run.

new App(driver?, options?): App

Defined in: src/core/app.ts:164

Driver

Backend to render through. Defaults to BunDriver (the terminal); pass WebDriver for the browser canvas or MockDriver for tests.

boolean

Drive the mouse-pointer shape from widget cursor styles (default true); see App.pointerShapes.

App

DOMNode.constructor

children: DOMNode[] = []

Defined in: src/dom/dom.ts:16

Child nodes in document order.

DOMNode.children


classes: Set<string>

Defined in: src/dom/dom.ts:10

Advisory class names (no CSS cascade today).

DOMNode.classes


driver: Driver

Defined in: src/core/app.ts:66

The backend this app renders through.


readonly hotkeys: HotkeyRegistry

Defined in: src/core/app.ts:114

Global hotkey registry: named, grouped, context-scoped shortcuts. Priority (modified) keys dispatch before the focused widget; bare keys after the focus chain declined them — see the key handler in run.


id: string = ""

Defined in: src/dom/dom.ts:8

Optional stable identifier (from the id prop).

DOMNode.id


readonly input: AppInput

Defined in: src/core/app.ts:100


parent: DOMNode | null = null

Defined in: src/dom/dom.ts:14

Parent node, or null when detached / at the root.

DOMNode.parent


screenStack: Screen[] = []

Defined in: src/core/app.ts:68

Screen stack; the top is the activeScreen.


tagName: string = ""

Defined in: src/dom/dom.ts:12

Host element tag, lowercased (e.g. “ztui-button”).

DOMNode.tagName


static instance: App | null = null

Defined in: src/core/app.ts:64

The most recently constructed App (convenience singleton; prefer widget.app).

get activeScreen(): Screen

Defined in: src/core/app.ts:179

The screen on top of the stack — where render mounts the tree.

Screen


get buffer(): ScreenBuffer

Defined in: src/core/app.ts:187

The most recently rendered frame buffer (read-only view). Exposed for inspection/testing — callers must not mutate it.

ScreenBuffer


get framePipelineRunCount(): number

Defined in: src/core/app.ts:465

Total render-pipeline runs so far (full or paint-only), regardless of whether they emitted. Tests diff this across an action to assert a frame ran — or, for a no-op, that none did.

number


get hoveredWidget(): Widget | null

Defined in: src/core/app.ts:430

The widget currently under the pointer, or null. Read by the style pass (for :hover) and the inspector; the live state is owned by AppInput.

Widget | null


get pointerShapes(): boolean

Defined in: src/core/app.ts:145

Whether the app drives the mouse-pointer shape (OSC 22) from the hovered widget’s cursor. On by default; set false to leave the pointer alone (e.g. to cut passive-hover tracking on capable terminals). Turning it off at runtime immediately resets the pointer to the terminal default. Has no effect on terminals that don’t advertise TerminalCapabilities.pointerShapes.

boolean

set pointerShapes(enabled): void

Defined in: src/core/app.ts:148

boolean

void

appendChild(child): void

Defined in: src/dom/dom.ts:23

Append child, detaching it from any previous parent.

DOMNode

void

DOMNode.appendChild


copyActiveSelection(): string | null

Defined in: src/core/app.ts:412

Copy the active read-only selection (the true content value across every widget it spans, in document order — see ReadonlySelectionManager). Writes the clipboard and returns the text, or null when the selection is empty.

string | null


describe(): string

Defined in: src/dom/dom.ts:59

Human/LLM-readable identity for logs and diagnostics, e.g. button#submit.primary @ (2,1 10x1). Includes the laid-out region when one is present (widgets), and the text preview for text nodes.

string

DOMNode.describe


getLastFrame(): FrameSummary | null

Defined in: src/core/app.ts:456

The FrameSummary of the most recent render-pipeline run, or null before the first. For deterministic frame-scheduling tests — inspect it after flushing a frame to assert how the frame was scoped and whether it emitted.

FrameSummary | null


getMouseDiagnostics(): Record<string, number>

Defined in: src/core/app.ts:422

Record<string, number>


getRenderReasonStats(): Record<string, number>

Defined in: src/core/app.ts:418

Record<string, number>


insertBefore(child, before): void

Defined in: src/dom/dom.ts:41

Insert child before the before sibling (appends if before isn’t found).

DOMNode

DOMNode

void

DOMNode.insertBefore


loadStyles(tcssContent): void

Defined in: src/core/app.ts:212

Load a TCSS stylesheet string (selectors + :hover/:focus rules) into the resolver.

string

void


matchesSelector(selector): boolean

Defined in: src/dom/dom.ts:109

Match a compound selector against this node — tags, IDs, and classes (e.g. tag#id.a.b).

string

boolean

DOMNode.matchesSelector


popScreen(): void

Defined in: src/core/app.ts:203

Pop the top screen, returning to the one beneath (never empties the stack).

void


pushScreen(screen): void

Defined in: src/core/app.ts:192

Push a screen onto the stack and make it active (e.g. a full-screen view).

Screen

void


queueRender(reason?): void

Defined in: src/core/app.ts:329

Schedule a full re-render — restyle + measure + layout + paint — on the next microtask (coalesced). This is the safe default: call it after any state change that might affect sizes or structure.

string = "unknown"

void


queueRepaint(region?, reason?): void

Defined in: src/core/app.ts:358

Schedule a paint-only re-render: restyle + paint, reusing the previous frame’s layout (regions/sizes). For high-frequency animations that change appearance but never geometry — the blinking caret above all — so an idle focused editor doesn’t relayout the whole tree ~17×/second. If anything calls queueRender in the same frame, the full path runs instead, so a repaint can never mask a real layout change.

{ bottom: number; y: number; } | null

string = "unknown"

void


queueRepaintWidget(widget, reason?): void

Defined in: src/core/app.ts:389

Repaint a single widget whose content changed, scoping the frame to its region — but only after a fresh layout confirms nothing moved. Unlike queueRepaint (caller asserts geometry is stable, e.g. the caret), this is safe for a change that might resize: the frame re-measures and re-lays out (cheap), and if any region shifted it transparently falls back to a full frame. When the layout is unchanged it re-renders only this widget’s subtree instead of the whole tree — the subtree-damage win.

Multiple widgets dirtied in one tick union their regions; a concurrent queueRender or an open overlay/selection escalates to full.

Widget

string = "unknown"

void


refresh(reason?): void

Defined in: src/core/app.ts:343

Force the next frame to re-emit every cell, even ones whose buffer content is unchanged. Needed after a global that affects serialization but not the cell data the per-cell diff compares — toggling colorMode (NO_COLOR) or the terminal’s colour depth — where a normal queueRender would find no changed cells and emit nothing.

string = "refresh"

void


removeChild(child): void

Defined in: src/dom/dom.ts:32

Remove child if it’s a child of this node.

DOMNode

void

DOMNode.removeChild


run(options?): void

Defined in: src/core/app.ts:219

Start the event loop: bind the driver, probe capabilities, and render frames.

number

void


stop(): void

Defined in: src/core/app.ts:295

Stop the loop and restore the backend; releases timers, the inspector, and the singleton.

void


walk(callback): void

Defined in: src/dom/dom.ts:83

Depth-first visit of this node and its descendants, in z-index (paint) order — mirrors what’s actually drawn on top, for callers like toAccessibleText(). z-index is a paint-only concept, so callers that need tab/focus order (nothing to do with stacking) should use walkDocumentOrder instead — otherwise a widget with a nonzero z-index purely for painting (e.g. an overlapping decorative sibling) jumps to a different position in the Tab sequence than where it structurally sits.

(node) => void

void

DOMNode.walk


walkDocumentOrder(callback): void

Defined in: src/dom/dom.ts:101

Depth-first visit of this node and its descendants in plain document order, ignoring z-index. Use for tab/focus order (e.g. Screen.getFocusableWidgets) — see walk’s doc comment for why z-index order is wrong there.

(node) => void

void

DOMNode.walkDocumentOrder