import { n as DisplayList, s as FontSpec } from "./displayList.js"; import { J as TextMeasurer, R as BindablePropTarget, V as Node, X as WrappedTextMetrics, o as Group } from "./nodes.js"; import { BoundTimeline, CompiledTimeline, Playhead, Timeline } from "@glissade/core"; //#region src/scene.d.ts interface Scene { readonly root: Group; readonly nodes: ReadonlyMap; readonly size: { w: number; h: number; }; /** Per-scene playhead; players and evaluate() write it. */ readonly playhead: Playhead; resolveTarget(target: string): BindablePropTarget | undefined; /** * Inject the active backend's TextMeasurer (§3.2) so line breaking always * measures with the rasterizer that will draw. Defaults to an estimator. */ setTextMeasurer(measurer: TextMeasurer): void; readonly textMeasurer: TextMeasurer; /** * Measure how `text` wraps to `width` with `font`, using THIS scene's measurer * — `{ width, lines, height, ascent, descent }`. Size a container (bubble/card) * to wrapped text WITHOUT a Text node (the node-free analogue of * `Text.measuredSize`/`lineBoxes`). `lineHeight` is a multiple of `font.size`, * default 1.25. */ measureWrappedText(text: string, font: FontSpec, width: number, lineHeight?: number): WrappedTextMetrics; } declare class DuplicateNodeIdError extends Error { constructor(id: string); } declare class ReservedNodeIdError extends Error { constructor(id: string); } interface SceneInit { size: { w: number; h: number; }; children: Node[]; } /** * The scene-module convention: what `gs render`, the golden harness, and the * studio load. createScene is a factory — every consumer gets a fresh graph. */ interface SceneModule { createScene(): Scene; timeline: Timeline; } declare function createScene(init: SceneInit): Scene; interface BindingCacheEntry { compiled: CompiledTimeline; bound: BoundTimeline; } /** Options for {@link bindScene}. */ interface BindSceneOptions { /** * 0.59 mode gate (threaded to {@link BindOptions.onUnbound}): `'throw'` * (default, loud) vs `'warn'` (prod embeds — downgrade an unresolved target to * a dev-warning and skip the track). `mount({ production: true })` passes * `'warn'` here on its first (memo-warming) bind, so the whole render loop runs * in the chosen mode. Byte-neutral for every valid scene (see BindOptions). */ onUnbound?: 'throw' | 'warn'; } declare function bindScene(scene: Scene, doc: Timeline, opts?: BindSceneOptions): BindingCacheEntry; /** * The non-negotiable contract (§2.5): same (scene, timeline, t) → identical * DisplayList, in any call order. Never awaits; asset readiness is the * caller's precondition. */ declare function evaluate(scene: Scene, doc: Timeline, t: number): DisplayList; /** * Controlled / imperative drive (0.19): `evaluate(scene)` with NO timeline — * the host owns the clock. It evaluates against an EMPTY timeline at the * scene's current playhead value (`peek()`, 0 by default), so values set * imperatively via `node.set(...)` between frames survive into the DisplayList * (no track clobbers them). See docs/controlled-drive.md for the loop and the * `.set()`-vs-timeline precedence contract. * * PRECEDENCE: a timeline track ALWAYS overrides `.set()` on the prop it * targets while that track is live — pass the timeline through the 3-arg form * for animated props; reserve this overload for host-owned props. */ declare function evaluate(scene: Scene): DisplayList; //#endregion export { SceneInit as a, createScene as c, Scene as i, evaluate as l, DuplicateNodeIdError as n, SceneModule as o, ReservedNodeIdError as r, bindScene as s, BindSceneOptions as t };