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:158

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:173

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

Screen


get buffer(): ScreenBuffer

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

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:431

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:396

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:139

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:142

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:378

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:422

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:388

Record<string, number>


getRenderReasonStats(): Record<string, number>

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

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:206

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

string

void


matchesSelector(selector): boolean

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

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:197

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

void


pushScreen(screen): void

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

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:301

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:330

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:355

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:315

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:213

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

number

void


stop(): void

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

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

void


walk(callback): void

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

Depth-first visit of this node and its descendants, in z-index order.

(node) => void

void

DOMNode.walk