lecodes-cli 0.10.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"global.d.ts":"// AUTO-GENERATED by build-types.ts. The import-free type surface for le.codes projects:\n// every SDK global declared ambiently, so user code uses Scene / Sprite / UIScreen / … \n// with no imports and full editor autocomplete.\n\nimport type * as SDK from \"./types/inject\"\n\ndeclare global {\n const ARScene: typeof SDK.ARScene\n const Aspect: typeof SDK.Aspect\n const AudioPlayer: typeof SDK.AudioPlayer\n const Bitmap: typeof SDK.Bitmap\n const Camera: typeof SDK.Camera\n const Camera2D: typeof SDK.Camera2D\n const CameraView: typeof SDK.CameraView\n const Canvas: typeof SDK.Canvas\n const CharacterController: typeof SDK.CharacterController\n const CharacterController2D: typeof SDK.CharacterController2D\n const ClickEvent: typeof SDK.ClickEvent\n const Color: typeof SDK.Color\n const DateValue: typeof SDK.DateValue\n const File: typeof SDK.File\n const FollowPath: typeof SDK.FollowPath\n const FormData: typeof SDK.FormData\n const Geolocation: typeof SDK.Geolocation\n const Geometry: typeof SDK.Geometry\n const Input: typeof SDK.Input\n const InspectorUI: typeof SDK.InspectorUI\n const Light: typeof SDK.Light\n const LongPressEvent: typeof SDK.LongPressEvent\n const LookAt: typeof SDK.LookAt\n const Mat4: typeof SDK.Mat4\n const Material: typeof SDK.Material\n const Mathf: typeof SDK.Mathf\n const Mesh: typeof SDK.Mesh\n const Model: typeof SDK.Model\n const ModelAnimation: typeof SDK.ModelAnimation\n const MoveTo: typeof SDK.MoveTo\n const NativeView: typeof SDK.NativeView\n const Node: typeof SDK.Node\n const Node2D: typeof SDK.Node2D\n const Noise: typeof SDK.Noise\n const Particles: typeof SDK.Particles\n const Physics: typeof SDK.Physics\n const Physics2D: typeof SDK.Physics2D\n const Plane: typeof SDK.Plane\n const PlayAnimation: typeof SDK.PlayAnimation\n const Presentable: typeof SDK.Presentable\n const QRScanner: typeof SDK.QRScanner\n const Quat: typeof SDK.Quat\n const Ray: typeof SDK.Ray\n const Router: typeof SDK.Router\n const Scene: typeof SDK.Scene\n const Scene2D: typeof SDK.Scene2D\n const SceneHandle: typeof SDK.SceneHandle\n const Service: typeof SDK.Service\n const Shape: typeof SDK.Shape\n const Shape2D: typeof SDK.Shape2D\n const Spin: typeof SDK.Spin\n const Sprite: typeof SDK.Sprite\n const SpriteAnimation: typeof SDK.SpriteAnimation\n const SvgSource: typeof SDK.SvgSource\n const Texture: typeof SDK.Texture\n const Texture2D: typeof SDK.Texture2D\n const Tilemap: typeof SDK.Tilemap\n const TouchStartEvent: typeof SDK.TouchStartEvent\n const Trigger: typeof SDK.Trigger\n const Trigger2D: typeof SDK.Trigger2D\n const UIBottomSheet: typeof SDK.UIBottomSheet\n const UIBox: typeof SDK.UIBox\n const UIButton: typeof SDK.UIButton\n const UIColumn: typeof SDK.UIColumn\n const UIImage: typeof SDK.UIImage\n const UIInput: typeof SDK.UIInput\n const UIModal: typeof SDK.UIModal\n const UIPager: typeof SDK.UIPager\n const UIPopover: typeof SDK.UIPopover\n const UIRow: typeof SDK.UIRow\n const UIScreen: typeof SDK.UIScreen\n const UIScrollable: typeof SDK.UIScrollable\n const UISpacer: typeof SDK.UISpacer\n const UIText: typeof SDK.UIText\n const UITextArea: typeof SDK.UITextArea\n const UIVideo: typeof SDK.UIVideo\n const UIVirtualizedList: typeof SDK.UIVirtualizedList\n const UIWidget: typeof SDK.UIWidget\n const VRScene: typeof SDK.VRScene\n const Vec2: typeof SDK.Vec2\n const Vec3: typeof SDK.Vec3\n const VideoPlayer: typeof SDK.VideoPlayer\n const WebSocket: typeof SDK.WebSocket\n const __editorPlugins: typeof SDK.__editorPlugins\n const __uiMap: typeof SDK.__uiMap\n const animate: typeof SDK.animate\n const animateMat4: typeof SDK.animateMat4\n const app: typeof SDK.app\n const clipboard: typeof SDK.clipboard\n const colorCurve: typeof SDK.colorCurve\n const computed: typeof SDK.computed\n const cubicBezier: typeof SDK.cubicBezier\n const curve: typeof SDK.curve\n const date: typeof SDK.date\n const defineScene: typeof SDK.defineScene\n const device: typeof SDK.device\n const easeIn: typeof SDK.easeIn\n const easeInOut: typeof SDK.easeInOut\n const easeOut: typeof SDK.easeOut\n const effect: typeof SDK.effect\n const fetch: typeof SDK.fetch\n const fetchLocal: typeof SDK.fetchLocal\n const localStorage: typeof SDK.localStorage\n const make: typeof SDK.make\n const openFilePicker: typeof SDK.openFilePicker\n const openURL: typeof SDK.openURL\n const pauseAnimation: typeof SDK.pauseAnimation\n const ref: typeof SDK.ref\n const registerEditorTool: typeof SDK.registerEditorTool\n const registerEditorWindow: typeof SDK.registerEditorWindow\n const registerFont: typeof SDK.registerFont\n const resumeAnimation: typeof SDK.resumeAnimation\n const share: typeof SDK.share\n const signal: typeof SDK.signal\n const stopAnimation: typeof SDK.stopAnimation\n const theme: typeof SDK.theme\n const toast: typeof SDK.toast\n const use: typeof SDK.use\n type ARScene<T extends ARMode = \"default\"> = SDK.ARScene<T>\n type AppState = SDK.AppState\n type Aspect<K extends string, P = Node> = SDK.Aspect<K, P>\n type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = SDK.AspectEntry<A>\n type AudioPlayer = SDK.AudioPlayer\n type Bitmap = SDK.Bitmap\n type Camera = SDK.Camera\n type Camera2D = SDK.Camera2D\n type CameraFacing = SDK.CameraFacing\n type CameraNodeDef = SDK.CameraNodeDef\n type CameraView = SDK.CameraView\n type Canvas = SDK.Canvas\n type CharacterController = SDK.CharacterController\n type CharacterController2D = SDK.CharacterController2D\n type ClickEvent<T = any> = SDK.ClickEvent<T>\n type Computed<T> = SDK.Computed<T>\n type DateInput = SDK.DateInput\n type DateValue = SDK.DateValue\n type EditorApi = SDK.EditorApi\n type EditorRayHit = SDK.EditorRayHit\n type EditorToolHooks = SDK.EditorToolHooks\n type EditorWindowFn = SDK.EditorWindowFn\n type FetchResponse = SDK.FetchResponse\n type FieldMeta<T = unknown> = SDK.FieldMeta<T>\n type File = SDK.File\n type FollowPath = SDK.FollowPath\n type FormData = SDK.FormData\n type GeoOptions = SDK.GeoOptions\n type GeoPosition = SDK.GeoPosition\n type GeoWatch = SDK.GeoWatch\n type Geometry = SDK.Geometry\n type HapticStyle = SDK.HapticStyle\n type InspectorUI = SDK.InspectorUI\n type Light = SDK.Light\n type LightDef = SDK.LightDef\n type LoadedScene<D extends SceneDef> = SDK.LoadedScene<D>\n type Locale = SDK.Locale\n type LongPressEvent<T = any> = SDK.LongPressEvent<T>\n type LookAt = SDK.LookAt\n type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = SDK.MakeEntry<A>\n type Mat4 = SDK.Mat4\n type Material = SDK.Material\n type MaterialDef = SDK.MaterialDef\n type Mesh = SDK.Mesh\n type MeshDef = SDK.MeshDef\n type Model = SDK.Model\n type ModelAnimation = SDK.ModelAnimation\n type MotionOptions = SDK.MotionOptions\n type MoveTo = SDK.MoveTo\n type NativeView = SDK.NativeView\n type Node = SDK.Node\n type Node2D = SDK.Node2D\n type Noise = SDK.Noise\n type Particles = SDK.Particles\n type Physics = SDK.Physics\n type Physics2D = SDK.Physics2D\n type Plane = SDK.Plane\n type PlayAnimation = SDK.PlayAnimation\n type PresentOptions = SDK.PresentOptions\n type Presentable = SDK.Presentable\n type QRScanner = SDK.QRScanner\n type Quat = SDK.Quat\n type Ray = SDK.Ray\n type Scene = SDK.Scene\n type Scene2D = SDK.Scene2D\n type SceneDef = SDK.SceneDef\n type SceneHandle<D extends SceneDef = SceneDef> = SDK.SceneHandle<D>\n type SceneNodeDef = SDK.SceneNodeDef\n type Service = SDK.Service\n type Shape = SDK.Shape\n type Shape2D = SDK.Shape2D\n type Signal<T> = SDK.Signal<T>\n type Spin = SDK.Spin\n type Sprite = SDK.Sprite\n type SpriteAnimation = SDK.SpriteAnimation\n type Texture = SDK.Texture\n type Texture2D = SDK.Texture2D\n type ThemeAccessors<T> = SDK.ThemeAccessors<T>\n type ThemeValues = SDK.ThemeValues\n type Tilemap = SDK.Tilemap\n type TouchStartEvent<T = any> = SDK.TouchStartEvent<T>\n type Transition = SDK.Transition\n type TransitionName = SDK.TransitionName\n type TransitionSpec = SDK.TransitionSpec\n type TransitionTransform = SDK.TransitionTransform\n type Trigger = SDK.Trigger\n type Trigger2D = SDK.Trigger2D\n type UIBottomSheet = SDK.UIBottomSheet\n type UIBottomSheetStyle = SDK.UIBottomSheetStyle\n type UIBox = SDK.UIBox\n type UIButton = SDK.UIButton\n type UIButtonStyle = SDK.UIButtonStyle\n type UIColumn = SDK.UIColumn\n type UIContainerStyle = SDK.UIContainerStyle\n type UIImage = SDK.UIImage\n type UIImageStyle = SDK.UIImageStyle\n type UIInput = SDK.UIInput\n type UIInputStyle = SDK.UIInputStyle\n type UIModal = SDK.UIModal\n type UIModalStyle = SDK.UIModalStyle\n type UINativeViewStyle = SDK.UINativeViewStyle\n type UINode = SDK.UINode\n type UINodeChild = SDK.UINodeChild\n type UIPager = SDK.UIPager\n type UIPagerStyle = SDK.UIPagerStyle\n type UIPopover = SDK.UIPopover\n type UIPopoverStyle = SDK.UIPopoverStyle\n type UIRow = SDK.UIRow\n type UIScreen = SDK.UIScreen\n type UIScreenStyle = SDK.UIScreenStyle\n type UIScrollable = SDK.UIScrollable\n type UIScrollableStyle = SDK.UIScrollableStyle\n type UISpacer = SDK.UISpacer\n type UISpacerStyle = SDK.UISpacerStyle\n type UIText = SDK.UIText\n type UITextArea = SDK.UITextArea\n type UITextStyle = SDK.UITextStyle\n type UIVideo = SDK.UIVideo\n type UIVideoStyle = SDK.UIVideoStyle\n type UIVirtualizedList<T = unknown> = SDK.UIVirtualizedList<T>\n type UIWidget = SDK.UIWidget\n type UIWidgetStyle = SDK.UIWidgetStyle\n type Unit = SDK.Unit\n type VRScene = SDK.VRScene\n type Vec2 = SDK.Vec2\n type Vec3 = SDK.Vec3\n type VideoPlayer = SDK.VideoPlayer\n type WebSocket = SDK.WebSocket\n type With<N, A extends Aspect<any, any>> = SDK.With<N, A>\n}\n\nexport {}\n","host.d.ts":"// JS-runtime globals provided by the host engine (web viewer / desktop / iOS), NOT by the SDK.\n// The SDK only declares them so its own source — and user code — type-check; they are never\n// bundled or injected. Mirrors packages/projects/src/global.d.ts. (Plus a couple of ambient,\n// type-only editor conveniences — e.g. `Style<T>` — which emit no runtime either.)\n\ndeclare global {\n // Timers + the per-frame loop. `setLoop(dt => …)` fires every frame; dt is SECONDS since the\n // previous frame. The host drives it (viewer RAF / desktop runTick).\n function setTimeout(handler: (...args: any[]) => void, timeout?: number): number\n function setInterval(handler: (...args: any[]) => void, timeout?: number): number\n function clearTimeout(id: number): void\n function clearInterval(id: number): void\n function setLoop(handler: (dt: number) => void): number\n function clearLoop(id: number): void\n\n // Math constants substituted at compile time by the bundler's esbuild `define`.\n var DEG2RAD: number\n var RAD2DEG: number\n\n // Compile-time boolean: `true` in scene-editor bundles, `false` (branch const-folded + DCE'd)\n // in shipped ones. Gate editor-only code with `if (EDITOR) { … }` — it costs zero bytes in\n // production. `*.editor.ts` files are the file-level form: compiled into editor bundles only.\n var EDITOR: boolean\n\n var console: {\n log(...data: any[]): void\n warn(...data: any[]): void\n info(...data: any[]): void\n error(...data: any[]): void\n }\n\n // Compile-time macro: `asset('./hero.png')` is desugared by the bundler into the module import\n // for that resource. Declared as a function purely so user code type-checks.\n function asset(path: string): string\n\n // Compile-time macro: installs a font and returns its family name — using a font IS declaring\n // it (docs/font-system-plan.md). A registry id (`font(\"manrope\")`) resolves against the font\n // registry; `{ weights, italic }` narrows/extends the face set (default: the family's standard\n // weights). A project path (`font(\"./fonts/Brand.ttf\")`) reads family/weight/italic from the\n // file itself. String-literal argument only. No awaiting — faces load with app boot and the\n // host holds first paint for them.\n function font(id: string, opts?: { weights?: number[], italic?: boolean }): string\n\n // Type-only editor convenience: the style object type of a UI element. `Style<UIButton>` (or\n // `Style<typeof myButton>`) resolves to the style you'd pass to `el.style(...)` — handy for typing\n // reusable style presets / helpers. Inferred from the element's callable `style` member, WITHOUT a\n // `Partial<>` wrapper: every style prop is already optional, and Partial over ClassStyles'\n // `$`-index signature adds `| undefined` to its values, making the preset unassignable back into\n // `.style(...)`. Round-trip is guarded by sdk/tests/ui-types.test.ts.\n type Style<T> = T extends { style: (s: infer S) => any } ? S : never\n}\n\nexport {}\n","types/animate/animate.d.ts":"type mat4 = Float32Array | number[];\ntype quat = Float32Array | number[];\ntype vec2 = Float32Array | number[];\ntype vec3 = Float32Array | number[];\nimport type { Easing } from \"./easings\";\ntype AnimateProps = number | string | vec2 | vec3 | quat;\nexport type AnimateOptions<T> = {\n from: T;\n to: T;\n duration: number;\n onUpdate(val: T): void;\n onComplete?(): void;\n easing?: Easing;\n};\nexport declare const animate: <T extends AnimateProps>(options: AnimateOptions<T>) => number;\nexport declare const stopAnimation: (id: number) => void;\nexport declare const pauseAnimation: (id: number) => void;\nexport declare const resumeAnimation: (id: number) => void;\nexport declare const animateMat4: (options: AnimateOptions<mat4>) => number;\nexport {};\n","types/animate/bezier.d.ts":"import type { Easing } from \"./easings\";\nexport declare function cubicBezier(mX1: number, mY1: number, mX2: number, mY2: number): Easing;\n","types/animate/easings.d.ts":"export type Easing = (v: number) => number;\nexport type EasingModifier = (easing: Easing) => Easing;\nexport declare function linear(p: number): number;\nexport declare function bounceOut(p: number): number;\nexport declare function bounceInOut(p: number): number;\nexport declare function reverseEasing(easing: Easing): Easing;\nexport declare function mirrorEasing(easing: Easing): Easing;\nexport declare function createExpoIn(power: number): Easing;\nexport declare function createBackIn(power: number): Easing;\nexport declare function createAnticipate(power: number): Easing;\nexport declare function bounceIn(p: number): number;\nexport declare function easeIn(p: number): number;\nexport declare function easeOut(p: number): number;\nexport declare function easeInOut(p: number): number;\nexport declare function circIn(p: number): number;\nexport declare function circOut(p: number): number;\nexport declare function circInOut(p: number): number;\nexport declare function backIn(p: number): number;\nexport declare function backOut(p: number): number;\nexport declare function backInOut(p: number): number;\nexport declare function anticipate(p: number): number;\n","types/canvas/Canvas.d.ts":"import { Texture2D } from \"../g2/Texture2D\";\nimport { File, type FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue } from \"../runtime/misc\";\ndeclare const ALIGN: {\n readonly left: 0;\n readonly center: 1;\n readonly right: 2;\n readonly start: 3;\n readonly end: 4;\n};\ndeclare const BASELINE: {\n readonly alphabetic: 0;\n readonly top: 1;\n readonly middle: 2;\n readonly bottom: 3;\n readonly hanging: 4;\n readonly ideographic: 5;\n};\ndeclare const JOIN: {\n readonly miter: 0;\n readonly round: 1;\n readonly bevel: 2;\n};\ndeclare const CAP: {\n readonly butt: 0;\n readonly round: 1;\n readonly square: 2;\n};\nexport type TextAlign = keyof typeof ALIGN;\nexport type TextBaseline = keyof typeof BASELINE;\nexport type LineJoin = keyof typeof JOIN;\nexport type LineCap = keyof typeof CAP;\nexport interface CanvasTextMetrics {\n width: number;\n ascent: number;\n descent: number;\n}\nexport declare class Canvas {\n /** Brand so `Sprite`/`UIImage`/`Material` can accept a Canvas anywhere a texture source is expected. */\n readonly __canvas: true;\n width: number;\n height: number;\n /** Device-pixel multiplier (draw at 2 for crisp retina text). Applied by the backend. */\n pixelRatio: number;\n private _cmd;\n private _refs;\n private _globalAlpha;\n private _fillStyle;\n private _strokeStyle;\n private _lineWidth;\n private _lineJoin;\n private _lineCap;\n private _font;\n private _textAlign;\n private _textBaseline;\n private _surfaceId;\n private _tex2d?;\n private _uiBound;\n constructor(width: number, height: number, opts?: {\n pixelRatio?: number;\n });\n private _ref;\n /** Discard the recorded drawing to start a new one (for dynamic canvases). */\n reset(): this;\n /** Change the surface size; takes effect on the next bake. */\n resize(width: number, height: number): this;\n save(): this;\n restore(): this;\n translate(x: number, y: number): this;\n scale(sx: number, sy: number): this;\n rotate(rad: number): this;\n get globalAlpha(): number;\n set globalAlpha(a: number);\n get fillStyle(): string;\n set fillStyle(color: string);\n get strokeStyle(): string;\n set strokeStyle(color: string);\n get lineWidth(): number;\n set lineWidth(w: number);\n get lineJoin(): LineJoin;\n set lineJoin(j: LineJoin);\n get lineCap(): LineCap;\n set lineCap(c: LineCap);\n get font(): string;\n set font(f: string);\n get textAlign(): TextAlign;\n set textAlign(a: TextAlign);\n get textBaseline(): TextBaseline;\n set textBaseline(b: TextBaseline);\n beginPath(): this;\n closePath(): this;\n moveTo(x: number, y: number): this;\n lineTo(x: number, y: number): this;\n quadraticCurveTo(cx: number, cy: number, x: number, y: number): this;\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this;\n arc(x: number, y: number, r: number, a0: number, a1: number, ccw?: boolean): this;\n rect(x: number, y: number, w: number, h: number): this;\n roundRect(x: number, y: number, w: number, h: number, r: number): this;\n fill(evenOdd?: boolean): this;\n stroke(): this;\n fillRect(x: number, y: number, w: number, h: number): this;\n strokeRect(x: number, y: number, w: number, h: number): this;\n clearRect(x: number, y: number, w: number, h: number): this;\n fillText(text: string, x: number, y: number, maxWidth?: number): this;\n strokeText(text: string, x: number, y: number, maxWidth?: number): this;\n /** Blit a `Bitmap` (a snapshot from `toBitmap()`) onto this canvas. All coordinates are LOGICAL —\n * including the source sub-rect in the 9-arg form (it's scaled by the bitmap's pixelRatio here).\n * Records a DRAW_IMAGE op, so the blit runs at bake time: keep the Bitmap alive until the next\n * `update()`/`toBitmap()`/`texture()`. Three browser-style forms:\n * drawImage(bmp, dx, dy) — whole bitmap at its natural size\n * drawImage(bmp, dx, dy, dw, dh) — whole bitmap, scaled into dw×dh\n * drawImage(bmp, sx, sy, sw, sh, dx, dy, dw, dh) — a sub-rect of the bitmap, scaled into dw×dh */\n drawImage(img: Bitmap, dx: number, dy: number): this;\n drawImage(img: Bitmap, dx: number, dy: number, dw: number, dh: number): this;\n drawImage(img: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): this;\n /** Decode an image source into a standalone `Bitmap` you can blit with `drawImage()` — either an\n * `SvgSource(...)` (rasterized) or a `FetchResponse` holding already-fetched image bytes (decoded).\n * This is async because turning SVG markup / encoded bytes into pixels needs a decode step (on the\n * web, `createImageBitmap` / an `<img>` load); `await` it ONCE, then `drawImage(bitmap, …)` is\n * synchronous and the Bitmap is reusable. The returned Bitmap owns a native surface at the image's\n * natural pixel size (`pixelRatio` 1) — `destroy()` it when done. Typical use:\n * const logo = await canvas.loadImage(SvgSource(svg)) // or: await fetch(url) → the response\n * canvas.drawImage(logo, 0, 0) // sync, blit as often as you like */\n loadImage(source: SvgSourceValue | FetchResponse): Promise<Bitmap>;\n /** Measure `text` in the current font on THIS platform. The one synchronous round-trip. */\n measureText(text: string): CanvasTextMetrics;\n /** Bake and return the 2D texture (created once, then cached). */\n texture(): Texture2D;\n /** Re-rasterize and re-upload to every texture this canvas produced (call after redrawing) — the\n * cached 2D and/or 3D texture, whichever engines this canvas was baked into. */\n update(): this;\n /** Copy the current pixels into a standalone, immutable `Bitmap` — independent of this canvas, so\n * later drawing/`reset()` never touches it. Draw it back with `drawImage()`, export it with\n * `toDataURL()`, or use it to \"flatten\" an ever-growing drawing so re-bakes stay O(1):\n * const snap = canvas.toBitmap()\n * canvas.reset(); canvas.drawImage(snap, 0, 0) // one op replaces the whole history\n * // …keep drawing on top; snap.destroy() once it's been drawn in. */\n toBitmap(): Bitmap;\n /** Encode the current pixels to an image `File` — 'image/png' (default) or 'image/jpeg'. The File\n * is a host buffer handle {id,name,size}: append it to a FormData to upload, load it as a texture\n * (`Texture2D.load(file)`), or hand it to a share/save sheet. */\n toFile(name?: string, type?: string): Promise<File>;\n destroy(): void;\n}\n/** Duck-type guard so consumers can accept a Canvas anywhere a texture source is expected. */\nexport declare const isCanvas: (v: unknown) => v is Canvas;\n/** An immutable RGBA8 snapshot of a canvas, produced by `Canvas.toBitmap()`. It owns its own baked\n * surface (a copy), so the source canvas can keep drawing or `reset()` without affecting it. Use it\n * to stamp/blit back (`canvas.drawImage(bitmap, …)`), to export (`bitmap.toDataURL()`), or as a\n * cheap \"layer\" you composite. Call `destroy()` when done — it holds a native surface. */\nexport declare class Bitmap {\n readonly __bitmap: true;\n /** Logical width, matching the Canvas it was captured from (pixelRatio is crispness, not size). */\n readonly width: number;\n readonly height: number;\n readonly pixelRatio: number;\n constructor(surfaceId: number, width: number, height: number, pixelRatio: number);\n /** Device-pixel dimensions of the stored bitmap (`width * pixelRatio`, rounded). */\n get pixelWidth(): number;\n get pixelHeight(): number;\n /** Encode to an image `File` — 'image/png' (default) or 'image/jpeg'. See `Canvas.toFile`. */\n toFile(name?: string, type?: string): Promise<File>;\n /** Free the native surface. The bitmap must not be drawn or encoded afterwards. */\n destroy(): void;\n}\n/** Duck-type guard for a Bitmap (see `isCanvas`). */\nexport declare const isBitmap: (v: unknown) => v is Bitmap;\nexport {};\n","types/core/Aspect.d.ts":"import { Emitter, type EventMap } from \"./events\";\nimport type { InspectorUI } from \"./InspectorUI\";\nimport type { Node } from \"../gl/Node\";\n/** The class object of an aspect — accepted even when its constructor is protected/abstract. */\nexport type AspectCtor<A extends Aspect<any, any>> = abstract new () => A;\n/** The accessor name carried in the aspect's generic. */\nexport type KeyOf<A> = A extends Aspect<infer K, any> ? K : never;\n/** The node kind an aspect targets. */\nexport type TargetOf<A> = A extends Aspect<any, infer P> ? P : never;\n/** `{ name: Aspect }` — the field an aspect contributes to its node. */\nexport type FieldOf<A extends Aspect<any, any>> = {\n [P in KeyOf<A>]: A;\n};\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\n/**\n * A variable typed as a node KNOWN to carry the given aspect(s). Union, not a tuple — reads as\n * English and mirrors the runtime guard `node.has(Health)`:\n * let boss: With<Sprite, Health | Physics>\n */\nexport type With<N, A extends Aspect<any, any>> = N & UnionToIntersection<A extends any ? FieldOf<A> : never>;\n/**\n * Base for anything that can carry aspects. Extends Emitter, so node kinds get events too. Provides\n * the four verbs; the named accessor (node.physics, node.health, …) is set as an own property at\n * attach time, keyed by the aspect class's runtime `aspect` name.\n */\nexport declare abstract class AspectHost<E extends EventMap = EventMap> extends Emitter<E> {\n /** Attach (and configure) an aspect, or reconfigure it if already present. Returns the node typed\n * as now-having that aspect (so no guard/`?.` is needed afterwards). Rejects a wrong target node. */\n aspect<Self extends TargetOf<A>, A extends Aspect<any, any>>(this: Self, ctor: AspectCtor<A>, opts?: Partial<A>): Self & FieldOf<A>;\n /** Safe access — undefined if the aspect isn't attached. */\n get<A extends Aspect<any, any>>(ctor: AspectCtor<A>): A | undefined;\n /** Existence check AND type guard: inside `if (node.has(Physics))`, `node.physics` is present. */\n has<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this is this & FieldOf<A>;\n /** Detach an aspect (runs its onDetach). Named `removeAspect` so it never collides with the\n * child-management `add`/`remove` semantics some node kinds expose. */\n removeAspect<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this;\n}\n/**\n * Base for everything you attach. `K` = accessor name (extracted by chisel for the runtime). `P` =\n * the target node kind: `this.node` is typed to it, AND attaching to a wrong node is a compile error.\n * Initialize in `onAttach` (the node is set by then) — not a constructor; aspects are created by the\n * engine via `node.aspect()`, never `new`.\n */\nexport declare abstract class Aspect<K extends string, P = Node> {\n /**\n * Opt this aspect class into EDITOR-RUN mode (generators): while a scene is edited, the scene\n * loader constructs the instance (refs resolved, `node`/`generated` set — never `onAttach`) and\n * calls `rebuild()` — again on inspector prop edits and when a `ref()`-referenced node moves.\n * `static editor = { rebuild: true }`.\n */\n static editor?: {\n rebuild?: boolean;\n };\n /**\n * Custom inspector card for this aspect in the scene editor (immediate-mode — see\n * core/InspectorUI.ts): re-runs on every edit/event and emits a widget list. Without it, the\n * editor shows the inferred fields; `ui.auto()` emits those same fields, so a custom inspector\n * usually starts with `ui.auto()` and appends status lines / buttons / dynamic dropdowns:\n *\n * static inspector(ui: InspectorUI, self: MyAspect) {\n * ui.auto()\n * if (ui.button('Randomize')) self.rebuild()\n * }\n */\n static inspector?: (ui: InspectorUI, aspect: any) => void;\n /** The node this aspect is attached to (set at attach time). */\n readonly node: P;\n /**\n * GENERATOR aspects (`static editor = { rebuild: true }`, attached through a scene file): a\n * scene-added container child for the aspect's generated output — `rebuild()` clears and refills\n * it. Provided by the scene loader before `onAttach`/`rebuild` run; nodes `add()`ed to it join\n * the scene's draw set automatically (membership is separate from parenting). Undefined for\n * aspects attached by hand outside scene files. See docs/3d/scene-files.md.\n */\n readonly generated: Node & {\n clear(): void;\n };\n onAttach?(): void;\n onDetach?(): void;\n /**\n * GENERATOR aspects: (re)build the derived output under `this.generated` — must be idempotent\n * (clear, then create). Call it from `onAttach()` for play mode; a class opting in with\n * `static editor = { rebuild: true }` ALSO runs it while a scene is being edited: once at load,\n * and again whenever an inspector prop changes or a `ref()`-referenced node moves.\n */\n rebuild?(): void;\n /**\n * Called every frame while attached (dt = seconds since the last frame). Render-synced: runs in the\n * LATE phase by default — after the physics step + transform sync, right before the frame draws — so\n * reads of `node.worldPosition` are the final drawn position (cameras/followers have no 1-frame lag).\n * Set `updateBeforePhysics = true` (an instance field) to run in the EARLY phase (before the step)\n * instead — for aspects that WRITE velocity/force/kinematic transforms and want the same frame's\n * step to consume them. Cameras/followers READ, so they stay in the default LATE phase.\n */\n update?(dt: number): void;\n /** Run update(dt) in the EARLY phase (before the physics step) rather than the default LATE phase.\n * An instance field (like `updateWhenVisible`) — set it as a class field: `updateBeforePhysics = true`.\n * Use only when you FEED the simulation (velocity/force/kinematic transform). Read once, at attach. */\n updateBeforePhysics: boolean;\n /** Tick order within a phase — ascending; default 0, ties keep attach order. Read once, at attach. */\n order: number;\n /** Opt-in: only run update(dt) while the node is on-screen. NOOP for now — visibility culling isn't\n * wired yet, so every updater ticks regardless; declared so aspects can opt in ahead of it. */\n updateWhenVisible: boolean;\n}\nexport {};\n","types/core/color.d.ts":"export type ColorInput = string | number | readonly [number, number, number] | readonly [number, number, number, number];\nexport declare const Color: {\n /** [r,g,b] in 0..1 — for the 2D engine's float color setters. */\n toRgb01(c: ColorInput): [number, number, number];\n /** [r,g,b,a] in 0..1. */\n toRgba01(c: ColorInput): [number, number, number, number];\n /** 0xRRGGBB packed int — for the 3D engine's color uniforms / skybox. */\n toPackedRgb(c: ColorInput): number;\n /** 0xRRGGBBAA packed int (unsigned). */\n toPackedRgba(c: ColorInput): number;\n /** '#rrggbb' (or '#rrggbbaa' when alpha < 1) — for the 3D material color uniforms. */\n toHexString(c: ColorInput): string;\n};\n","types/core/events.d.ts":"export type EventMap = Record<string, (...args: any[]) => void>;\nexport declare class Emitter<E extends EventMap> {\n private _listeners;\n addEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n removeEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n /** Fire all listeners on a channel. Protected: only the owning class emits. */\n protected dispatch<K extends keyof E>(channel: K, ...args: Parameters<E[K]>): void;\n protected hasListeners<K extends keyof E>(channel: K): boolean;\n /** Drop every listener on every channel (used when the owning object is disposed). */\n protected clearListeners(): void;\n}\n","types/core/fields.d.ts":"/** Editor widget kinds the inspector knows how to render. `\"node\"` = a scene-node reference\n * (`ref('name')` in the file, name dropdown + pick-in-viewport in the inspector) — declare it via\n * `static fields` on fields typed `Node | null`; a `Node | null` type annotation is also picked\n * up syntactically by the editor's source scan. `\"asset\"` = a project-asset path (the editor\n * fills the dropdown with the project's GLBs — `ui.asset()` in windows/tools/cards). */\nexport type FieldEditor = \"number\" | \"text\" | \"color\" | \"switch\" | \"select\" | \"vec2\" | \"vec3\" | \"vec4\" | \"node\" | \"asset\";\nexport type FieldMetaEntry = {\n /** Inspector label (default: the field name). */\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Allowed values — renders a dropdown (editor \"select\"). */\n options?: readonly (string | number)[];\n /** Override the editor inferred from the default value. */\n editor?: FieldEditor;\n /** Exclude the field from the inspector. */\n hidden?: boolean;\n};\n/** Declared on an aspect class as `static fields: FieldMeta<MyAspect> = { … }`. All optional. */\nexport type FieldMeta<T = unknown> = {\n [K in Extract<keyof T, string>]?: FieldMetaEntry;\n};\n/** One editable field: key + default value + resolved editor + merged metadata. */\nexport type FieldDescriptor = {\n key: string;\n label: string;\n /** The default value (from a freshly constructed instance; undefined if only declared in meta). */\n value: unknown;\n /** Resolved editor kind; undefined = no editor known (inspector shows it read-only). */\n editor: FieldEditor | undefined;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type AspectClassInfo = {\n /** The accessor name (`static aspect`, injected by chisel for user aspects). */\n name: string;\n className: string;\n fields: FieldDescriptor[];\n /** True for editor-run classes (`static editor` — generators). The editor routes their\n * structural changes through a re-run instead of a live patch. */\n editor?: boolean;\n /** True when the class declares a custom `static inspector(ui, aspect)` card. */\n inspector?: boolean;\n};\n/** Infer the editor widget from a default value's shape. */\nexport declare const inferFieldEditor: (value: unknown) => FieldEditor | undefined;\n/**\n * Enumerate the editable fields of a class: construct a default instance, take its own enumerable\n * non-underscore fields (minus the Aspect base plumbing), infer editors from the default values, and\n * merge the class's optional `static fields` metadata (which can also add keys that have no runtime\n * default, e.g. fields declared without an initializer).\n */\nexport declare const describeFields: (ctor: abstract new () => unknown) => FieldDescriptor[];\n/** Describe an aspect class for the inspector: accessor name + class name + editable fields. */\nexport declare const describeAspect: (ctor: abstract new () => unknown) => AspectClassInfo;\n","types/core/InspectorUI.d.ts":"import type { FieldEditor } from \"./fields\";\n/** One user interaction coming back from the editor panel: the widget's id (+ value for fields). */\nexport type InspectorEvent = {\n id: string;\n value?: unknown;\n};\nexport type InspectorFieldWidget = {\n kind: \"field\";\n id: string;\n /** The bound key — an aspect field (doc-bound) or an editor-state key. */\n key: string;\n label: string;\n editor: FieldEditor | undefined;\n value: unknown;\n /** True = persisted to the scene file by the editor; false = transient editor state. */\n doc: boolean;\n /** True = emitted by `ui.auto()` — the editor may overlay its syntactic hints (options/node). */\n auto?: boolean;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type InspectorWidget = InspectorFieldWidget | {\n kind: \"button\";\n id: string;\n label: string;\n} | {\n kind: \"toolButton\";\n id: string;\n label: string;\n tool: string;\n} | {\n kind: \"header\";\n id: string;\n label: string;\n} | {\n kind: \"info\" | \"warn\";\n id: string;\n text: string;\n};\ntype FieldOpts = {\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Default for EDITOR-STATE keys (doc keys default from the class field). */\n value?: unknown;\n};\n/**\n * The widget builder handed to `static inspector(ui, aspect)` (and to editor windows/tools later).\n * One instance lives per card and persists across runs — it carries the card's editor state.\n */\nexport declare class InspectorUI {\n /** Numeric field (min/max/step render as a slider-style scrub range). */\n number(key: string, opts?: FieldOpts): number;\n /** Alias of `number` — give it min/max/step and the editor renders a scrubable range. */\n slider(key: string, opts?: FieldOpts): number;\n text(key: string, opts?: FieldOpts): string;\n color(key: string, opts?: FieldOpts): string;\n switch(key: string, opts?: FieldOpts): boolean;\n /** Dropdown — `options` may be computed fresh every run (dynamic lists come free). */\n select(key: string, options: readonly (string | number)[], opts?: FieldOpts): string | number;\n vec2(key: string, opts?: FieldOpts): [number, number];\n vec3(key: string, opts?: FieldOpts): [number, number, number];\n vec4(key: string, opts?: FieldOpts): [number, number, number, number];\n /** Scene-node reference (`ref()` fields): name dropdown + pick-in-viewport. Returns the RAW doc\n * value (`{ $ref }` marker or null) — read the resolved live node off the aspect instance. */\n node(key: string, opts?: FieldOpts): unknown;\n /** Project-asset path (the editor renders a dropdown of the project's GLBs). \"\" = none picked. */\n asset(key: string, opts?: FieldOpts): string;\n /** True on the run that consumes this button's click — do the action right there. */\n button(label: string, opts?: {\n id?: string;\n }): boolean;\n /** A toggle that activates/deactivates the named viewport tool (`registerEditorTool`). The\n * editor owns the active-tool state — the click never round-trips into the scene world. */\n toolButton(label: string, tool: string): void;\n header(label: string): void;\n info(text: string): void;\n warn(text: string): void;\n /** Emit the inferred field widgets (all declared aspect fields, or just the named ones) — the\n * zero-ceremony baseline; append custom widgets around it. */\n auto(...keys: string[]): void;\n private _vec;\n private _field;\n}\nexport {};\n","types/core/registry.d.ts":"export declare class Registry<T> {\n private map;\n set(id: number, value: T): void;\n get(id: number): T | undefined;\n delete(id: number): void;\n has(id: number): boolean;\n}\n","types/core/signals.d.ts":"/** Runs every pending effect now instead of waiting for the microtask (test/host hook). */\nexport declare const flushEffects: () => void;\nexport interface Signal<T> {\n value: T;\n /** Read without subscribing the current effect/computed. */\n peek(): T;\n}\nexport interface Computed<T> {\n readonly value: T;\n /** Read without subscribing the current effect/computed (still recomputes if stale). */\n peek(): T;\n}\n/**\n * A reactive value. Reading `.value` inside an `effect`/`computed` (or a function-valued style\n * prop / `UIText` content) subscribes it; writing `.value` re-runs subscribers (batched — once\n * per microtask).\n */\nexport declare function signal<T>(initialValue: T): Signal<T>;\nexport declare function signal<T = undefined>(): Signal<T | undefined>;\n/** A lazily-cached derived value: recomputes on read after any of its dependencies changed. */\nexport declare function computed<T>(fn: () => T): Computed<T>;\n/**\n * Runs `fn` now and again whenever any signal/computed it read changes (batched per microtask).\n * Returns a dispose function; an undisposed effect lives for the rest of the app run.\n */\nexport declare function effect(fn: () => void): () => void;\n/** The shape UINode's Element exposes for binding ownership. */\nexport interface BindingHost {\n}\n","types/g2/Camera2D.d.ts":"import { Vec2, type Vec2Like } from \"../math/vec\";\nexport declare class Camera2D {\n private _x;\n private _y;\n private _zoom;\n private _rotation;\n private readonly sceneId;\n constructor(sceneId: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n get zoom(): number;\n set zoom(z: number);\n get rotation(): number;\n set rotation(deg: number);\n screenToWorld(screenX: number, screenY: number): Vec2;\n worldToScreen(worldX: number, worldY: number): Vec2;\n}\n","types/g2/CharacterController2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class CharacterController2D extends Aspect<\"controller\", Node2D> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Extra probe distance below the body's feet used for the grounded check (world units). */\n groundProbe: number;\n /** Distance from the node origin down to the feet. Defaults to half the sprite height. */\n footOffset?: number;\n private _moveX;\n private _jumpQueued;\n private _grounded;\n /** Horizontal intent in [-1, 1] (e.g. from input). Sticky — set 0 to stop. Applied next frame. */\n move(dir: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on something (updated each frame). */\n get grounded(): boolean;\n private get phys();\n onAttach(): void;\n update(_dt: number): void;\n private _spriteHalfHeight;\n}\n","types/g2/loop.d.ts":"export declare const onUpdate: (callback: (dt: number) => void) => void;\nexport declare const offUpdate: (callback: (dt: number) => void) => void;\nexport declare const ensureAnimEvents: () => void;\nexport declare const ensurePhysicsEvents: () => void;\n","types/g2/Node2D.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nexport { Vec2, type Vec2Like };\nexport type Node2DEvents = {\n /** A looping animation clip wrapped around (fires each loop). */\n loopReached: (clip: string) => void;\n /** A non-looping animation clip finished. */\n completed: (clip: string) => void;\n /** A physics contact / sensor overlap began / ended (the other node). */\n enter: (other: Node2D) => void;\n exit: (other: Node2D) => void;\n /** Pointer up over this node's Physics2D shape (a tap/click). */\n click: (ev: ClickEvent<Node2D | null>) => void;\n /** Pointer down on this node's Physics2D shape. Call ev.track(...) to capture the drag. */\n touchstart: (ev: TouchStartEvent<Node2D | null>) => void;\n};\n/** id → Node2D, so host callbacks (animation events) route back to the owning JS object. */\nexport declare const node2dRegistry: Registry<Node2D>;\nexport declare class Node2D extends AspectHost<Node2DEvents> {\n /** Native entity handle. */\n readonly id: number;\n protected _x: number;\n protected _y: number;\n protected _rotation: number;\n protected _sx: number;\n protected _sy: number;\n protected _layer: number;\n protected _z: number;\n protected _visible: boolean;\n private _parent;\n private _children;\n constructor(internalId?: number);\n private _pull;\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n /** Rotation in degrees (CCW). */\n get rotation(): number;\n set rotation(deg: number);\n get scale(): Vec2;\n set scale(v: Vec2Like | number);\n /** Draw layer (int). Higher layers render on top. */\n get layer(): number;\n set layer(v: number);\n /** Intra-layer depth for non-Y-sorted layers (higher z = on top). */\n get z(): number;\n set z(v: number);\n get visible(): boolean;\n set visible(v: boolean);\n get parent(): Node2D | null;\n set parent(p: Node2D | null);\n get children(): readonly Node2D[];\n /** Attach children to this node (each keeps its current world transform). Returns this. */\n add(...children: Node2D[]): this;\n /** Detach a direct child (reparents it to root, keeping its world transform). Returns this. */\n remove(child: Node2D): this;\n /**\n * Reparent this node. `keepWorld` (default true) recomputes the local transform so the on-screen\n * position/rotation/scale is unchanged; pass false to keep the local transform and move with the\n * new parent. Self/descendant parents are rejected natively (no cycles).\n */\n setParent(parent: Node2D | null, keepWorld?: boolean): this;\n /** World-space position (composes all ancestors). */\n get worldPosition(): Vec2;\n /** Convert a world-space point into this node's local space (and back). */\n worldToLocal(p: Vec2Like): Vec2;\n localToWorld(p: Vec2Like): Vec2;\n private _syncLocalFromNative;\n addEventListener<K extends keyof Node2DEvents>(channel: K, callback: Node2DEvents[K]): void;\n destroy(): void;\n}\n","types/g2/Physics2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { type Node2D } from \"./Node2D\";\nexport type MotionType = \"static\" | \"kinematic\" | \"dynamic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -980]. */\n gravity?: Vec2Like;\n /** Pixels per meter — tunes Box2D's internal tolerances; you still author in world units. Default 64. */\n pixelsPerMeter?: number;\n /** Solver sub-steps per fixed step. Default 4. */\n subSteps?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node2D | null;\n point: Vec2;\n normal: Vec2;\n fraction: number;\n}\nexport declare class Physics2D extends Aspect<\"physics\", Node2D> {\n static readonly aspect = \"physics\";\n /** Default \"dynamic\". */\n motion: MotionType;\n density: number;\n friction: number;\n restitution: number;\n /** Lock rotation (essential for platformer characters). */\n fixedRotation: boolean;\n /** Continuous collision for fast-moving bodies (projectiles). */\n bullet: boolean;\n private _gravityScale;\n private _h;\n /** Native physics body id. 0 until attached, or if the build has no physics support. Mirrors 3D `Physics.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Linear velocity in world units/second (fresh Vec2 on read). */\n get velocity(): Vec2;\n set velocity(v: Vec2Like);\n /** Angular velocity in degrees/second. */\n set angularVelocity(degPerSec: number);\n /** Per-body gravity multiplier: 1 = full world gravity, 0 = floats, <0 = repelled. Set at attach\n * time (as an option) or live. */\n get gravityScale(): number;\n set gravityScale(scale: number);\n set linearDamping(d: number);\n set enabled(v: boolean);\n /** Apply an instantaneous impulse (world units) and wake the body. */\n applyImpulse(v: Vec2Like): this;\n /** Apply a continuous force (world units) and wake the body. */\n applyForce(v: Vec2Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position (+ optional rotation degrees). */\n moveTo(p: Vec2Like, deg?: number): this;\n /** Create / reset the physics world. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_2D_PHYSICS). */\n static get supported(): boolean;\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Closest body hit by the segment from→to, or null. `node` resolves the hit entity. */\n static raycast(from: Vec2Like, to: Vec2Like): RayHit | null;\n /** Topmost body (solid or sensor) whose shape contains the world point, or null. */\n static overlapPoint(p: Vec2Like): Node2D | null;\n}\n","types/g2/Scene2D.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport { Camera2D } from \"./Camera2D\";\nimport { type Node2D } from \"./Node2D\";\nexport type Scene2DOptions = {\n /** Background color — '#10131a', 0x10131a, or [r,g,b]/[r,g,b,a] in 0..1. */\n background?: ColorInput;\n /** Texture sampling for the 2D renderer: `'nearest'` (default — crisp pixel art) or `'linear'`\n * (smooth — for hi-res / non-pixel-art assets). Applied when the scene is opened, so switching\n * scenes restores the active scene's choice. NOTE: this is a GLOBAL renderer setting (one sampler\n * for ALL textures, not per-texture), so the currently-open scene's filter wins. Omit to leave the\n * current setting (engine default is nearest). */\n filter?: 'nearest' | 'linear';\n};\n/** Returned by scene2d.layer(n); chain .ySort() to enable top-down depth sorting for that layer. */\ndeclare class LayerHandle {\n private readonly sceneId;\n private readonly layer;\n constructor(sceneId: number, layer: number);\n /** In this layer, lower-on-screen sprites overlap higher ones (top-down feet sorting). */\n ySort(enabled?: boolean): this;\n}\nexport declare class Scene2D implements Presentable {\n /** Native scene handle. */\n readonly id: number;\n readonly camera: Camera2D;\n private static _active;\n static get active(): Scene2D | null;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node2D | null>) => void>;\n /** Texture filter to (re)assert on open(); the sampler is global, so each scene reclaims it. */\n private readonly _filter?;\n constructor(options?: Scene2DOptions);\n set background(color: ColorInput);\n /** Address a draw layer to configure it, e.g. scene2d.layer(1).ySort(). */\n layer(n: number): LayerHandle;\n /** Topmost visible sprite whose world bounds contain the world point, or null. Body-free\n * hit-test for tap/click picking — pair with camera.screenToWorld(). */\n pick(worldPoint: Vec2Like): Node2D | null;\n /** Scene-level pointer events. The handler fires for every tap/press in the scene, with\n * `ev.target` = the hit Physics2D node (or null). On 'touchstart' you can ev.track(...) a drag. */\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node2D | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node2D | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n add(...nodes: Node2D[]): this;\n remove(...nodes: Node2D[]): this;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): this;\n close(): this;\n destroy(): void;\n}\nexport {};\n","types/g2/Shape2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Shape2D extends Aspect<\"shape\", Node2D> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hw, hh] (world units). */\n box?: Vec2Like;\n /** Circle radius. */\n circle?: number;\n /** Capsule between two local points, with a radius. */\n capsule?: {\n from: Vec2Like;\n to: Vec2Like;\n radius: number;\n };\n /** Thin segment (an edge — for static ground/walls/slopes) between two local points. */\n segment?: {\n from: Vec2Like;\n to: Vec2Like;\n };\n /** Convex polygon, up to 8 local points (a convex hull is computed). */\n polygon?: Vec2Like[];\n /** Local offset of the shape from the node origin. */\n offset?: Vec2Like;\n}\n","types/g2/Sprite.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\n/** Anything that can back a sprite: a texture, or a Canvas (baked to a texture on assign). */\nexport type TextureSource = Texture2D | Canvas;\nexport type SpriteOptions = {\n texture?: TextureSource;\n /** Pivot, [0,0] = top-left .. [1,1] = bottom-right. Use [0.5, 1] (feet) for Y-sorted depth. */\n anchor?: Vec2Like;\n /** World size; defaults to the texture's pixel dimensions. */\n size?: Vec2Like;\n /** Normalized UV sub-rect [u0,v0,u1,v1]. */\n frame?: [number, number, number, number];\n /** Tint multiplied with the texture. */\n color?: ColorInput;\n opacity?: number;\n layer?: number;\n position?: Vec2Like;\n};\nexport declare class Sprite extends Node2D {\n private _texture?;\n private _anchor;\n private _color;\n private _opacity;\n private _flipX;\n private _flipY;\n private _size;\n constructor(options?: SpriteOptions);\n get texture(): Texture2D | undefined;\n set texture(t: TextureSource | undefined);\n /** Current world size: explicit override if set, else the texture's pixel dimensions (a Canvas-backed\n * sprite defaults to the canvas's LOGICAL size, so pixelRatio is crispness only, not size). */\n get size(): Vec2;\n set size(v: Vec2Like);\n get anchor(): Vec2;\n set anchor(v: Vec2Like);\n /** Set the UV sub-rect (normalized). */\n set frame(uv: [number, number, number, number]);\n /** Set the sub-rect in texture pixels. */\n setFramePx(px: number, py: number, pw: number, ph: number): this;\n get color(): ColorInput;\n set color(c: ColorInput);\n get opacity(): number;\n set opacity(a: number);\n get flipX(): boolean;\n set flipX(v: boolean);\n get flipY(): boolean;\n set flipY(v: boolean);\n}\n","types/g2/SpriteAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Sprite } from \"./Sprite\";\n/** Per-clip frame list, or an object for per-clip fps/loop overrides. */\nexport type Clip = number[] | {\n frames: number[];\n fps?: number;\n loop?: boolean;\n};\nexport declare class SpriteAnimation extends Aspect<\"anim\", Sprite> {\n static readonly aspect = \"anim\";\n /** Grid cell size in texture pixels (defaults to the full texture). */\n size?: [number, number];\n /** Default fps for clips that don't override it. */\n fps: number;\n /** Default loop for clips that don't override it. */\n loop: boolean;\n /** Named clips; frame indices are row-major into the grid. Set via the attach opts. */\n clips: Record<string, Clip>;\n private _clipIds;\n private _clipNames;\n private _current;\n onAttach(): void;\n /** (Re)build native clips from `this.clips`. Called on attach; call again after changing clips. */\n define(): this;\n private _define;\n /** Play a clip by name. Re-playing the active clip is a no-op (keeps it running smoothly). */\n play(name: string): this;\n stop(): this;\n set speed(value: number);\n get current(): string | null;\n get frame(): number;\n}\n","types/g2/Texture2D.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture2D {\n /** Native texture handle. */\n readonly id: number;\n readonly width: number;\n readonly height: number;\n constructor(id: number, width: number, height: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n }): Texture2D;\n static load(source: string | FetchResponse | File): Promise<Texture2D>;\n destroy(): void;\n}\n","types/g2/Tilemap.d.ts":"import { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\nexport type TilemapOptions = {\n texture: Texture2D;\n /** Map grid size (in tiles). */\n cols: number;\n rows: number;\n /** On-screen cell size in world units — a single number (square) or [w, h]. */\n tile: number | [number, number];\n /** Atlas grid: how the texture is sliced into tiles, [atlasCols, atlasRows]. */\n atlas: [number, number];\n /** Row-major tile indices into the atlas (-1 = empty), length cols*rows. Row 0 is the top row. */\n data: number[] | Int32Array;\n};\nexport declare class Tilemap extends Node2D {\n readonly cols: number;\n readonly rows: number;\n constructor(options: TilemapOptions);\n setTile(x: number, y: number, index: number): this;\n}\n","types/g2/touch.d.ts":"/** Register the host pointer callback once, on the first click/touchstart listener (node or scene). */\nexport declare const ensurePointerEvents: () => void;\n","types/g2/Trigger2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Trigger2D extends Aspect<\"trigger\", Node2D> {\n static readonly aspect = \"trigger\";\n private _h;\n /** Native physics body id (0 if no physics support). Mirrors 3D `Trigger.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec2Like): this;\n}\n","types/gl/Camera.d.ts":"import { Vec3 } from \"../math/vec\";\nimport { Node } from \"./Node\";\nimport { Ray } from \"./Ray\";\nexport declare class Camera extends Node {\n private _sceneId;\n /** Live projection matrix (updated by the host when the viewport/fov changes). */\n readonly projectionMatrix: Float32Array<ArrayBuffer>;\n get fov(): number;\n get horizontalFov(): number;\n get displaySize(): [number, number];\n /** World-space ray direction through a screen pixel. */\n getViewDirection(screenX: number, screenY: number): Vec3;\n /** A pick ray from the camera through a screen pixel. */\n getRay(screenX: number, screenY: number): Ray;\n}\n","types/gl/CharacterController.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3 } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class CharacterController extends Aspect<\"controller\", Node> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Character-tuned gravity (world units/s²), separate from the world gravity — usually stronger for\n * snappier feel. Applied to the vertical velocity each frame. */\n gravity: number;\n /** Max ground slope (degrees) the character treats as walkable. Set before attach. */\n maxSlope: number;\n updateBeforePhysics: boolean;\n private _charId;\n private _mx;\n private _mz;\n private _jumpQueued;\n private _vy;\n onAttach(): void;\n onDetach(): void;\n /** Native character id (0 until attached / no physics support). */\n get id(): number;\n /** Horizontal move intent; each component in [-1, 1] (e.g. from input). Sticky — set 0 to stop. */\n move(x: number, z: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on walkable ground (OnGround). */\n get grounded(): boolean;\n /** Ground state: 0 on-ground, 1 on-steep-slope, 2 touching-but-unsupported, 3 in-air. */\n get groundState(): number;\n /** Current velocity (world units/s, fresh Vec3). */\n get velocity(): Vec3;\n /** Teleport to a world position (clears vertical velocity). */\n teleport(x: number, y: number, z: number): this;\n update(dt: number): void;\n}\n","types/gl/controls.d.ts":"import type { Node } from \"./Node\";\nimport type { Scene } from \"./Scene\";\nexport type ControlsOptions = {\n /** Smallest uniform scale the pinch gesture allows (default 0.08). */\n minScale?: number;\n /** Largest uniform scale the pinch gesture allows (default 2). */\n maxScale?: number;\n /** One-finger drag moves the target across the ground plane (default true). */\n pan?: boolean;\n /** Two-finger pinch scales the target (default true). */\n pinch?: boolean;\n /** Two-finger twist rotates the target around its Y axis (default true). */\n twist?: boolean;\n};\n/** Returned by `addControls` — call `remove()` to detach the gesture listeners. */\nexport type ControlsHandle = {\n remove(): void;\n};\nexport declare const attachControls: (scene: Scene, target: Node, options?: ControlsOptions) => ControlsHandle;\n","types/gl/Geometry.d.ts":"import { type Vec3Like } from \"../math/vec\";\nexport type MeshKind = \"triangles\" | \"vertices\" | \"edges\";\nexport declare class Geometry {\n vertices: Float32Array;\n normals: Float32Array;\n indices: Uint16Array;\n uv: Float32Array;\n constructor(vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array);\n translate(x: number, y: number, z: number): this;\n scale(x: number, y: number, z: number): this;\n scaleUV(x: number, y: number): this;\n set kind(kind: MeshKind);\n static box(): Geometry;\n static sphere(options?: SphereOptions): Geometry;\n static cylinder(options?: CylinderOptions): Geometry;\n static plane(options?: PlaneOptions): Geometry;\n}\nexport type SphereOptions = {\n radius?: number;\n widthSegments?: number;\n heightSegments?: number;\n};\nexport type CylinderOptions = {\n radius?: number;\n radiusTop?: number;\n radiusBottom?: number;\n edges?: number;\n smooth?: boolean;\n};\nexport type PlaneOptions = {\n normal?: Vec3Like;\n};\n","types/gl/Light.d.ts":"import { type ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Node } from \"./Node\";\nexport type SunOptions = {\n /** Light direction (points where the light travels). Defaults to a typical key-light angle. */\n direction?: Vec3Like;\n /** Luminous intensity. */\n intensity?: number;\n color?: ColorInput;\n /**\n * Shadow quality (default 1):\n * 0 - no shadows\n * 1 - standard (1024 shadow map, hard PCF edges)\n * 2 - high (2048 + stable, soft contact-hardening edges)\n * 3 - best (4096 + stable, PCSS soft shadows)\n * Higher values cost more GPU/memory.\n */\n shadowsQuality?: 0 | 1 | 2 | 3;\n};\nexport declare class Light extends Node {\n /** A directional sun light. */\n static sun(options?: SunOptions): Light;\n}\n","types/gl/Material.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type FetchResponse } from \"../runtime/fetch\";\nimport { Texture } from \"./Texture\";\nimport type { Canvas } from \"../canvas/Canvas\";\ntype UniformValue = string | Texture | number | boolean | number[] | Float32Array | null;\nexport type MaterialColorOptions = {\n color?: ColorInput;\n map?: Texture | Canvas | null;\n};\n/** `Material.particles` options — the default point-sprite material for particle systems. */\nexport type ParticlesMaterialOptions = {\n /** Sprite texture — a single image or an N×N flipbook sheet. Unset = soft round dot. */\n map?: Texture | null;\n /** Flipbook grid: the map is an N×N sheet of frames; drive the frame via `particles.frame`.\n * Default 1 (whole texture). */\n sheet?: number;\n /** Extra brightness multiplier for a glow look (0 = off). */\n emissive?: number;\n /** Compositing: `\"alpha\"` (default — smoke, dust) or `\"add\"` (fire, sparks, magic). */\n blend?: \"alpha\" | \"add\";\n /** Soft radial falloff toward the sprite edge. Defaults to true without a map, false with one. */\n soft?: boolean;\n};\n/** `Material.lit` options — PBR scalars on top of the color/map pair. */\nexport type LitMaterialOptions = MaterialColorOptions & {\n /** Perceptual roughness, 0 (mirror) … 1 (matte). Unset = the shader's default. */\n roughness?: number;\n /** Metallic factor, 0 (dielectric) … 1 (metal). Unset = the shader's default. */\n metallic?: number;\n};\nexport declare class Material {\n readonly shader: FetchResponse | \"unknown\";\n readonly uniforms: Record<string, UniformValue>;\n private _colorKey;\n private _useMapFlag;\n constructor(shader: FetchResponse | number);\n /** Set a uniform (chainable). */\n set(key: string, value: UniformValue): this;\n set color(c: ColorInput);\n set map(value: Texture | Canvas | null);\n /** PBR lit material. */\n static lit(options?: LitMaterialOptions): Material;\n /** Unlit (flat) material. */\n static unlit(options?: MaterialColorOptions): Material;\n /** Default particle material — camera-facing point sprites with tint/opacity/rotation/flipbook\n * driven by the particle curves. Uniforms all default to 0 on a fresh instance, so every look\n * knob is primed here; JS writes after construction override them. */\n static particles(options?: ParticlesMaterialOptions): Material;\n /** Material that samples a VideoPlayer's texture. */\n static video(map?: Texture): Material;\n /** Shadow-catcher material (transparent except where shadows fall). */\n static shadow(color?: ColorInput): Material;\n /** Load a custom compiled shader (.mat URL) as a material. */\n static load(url: string): Promise<Material>;\n}\nexport {};\n","types/gl/Mesh.d.ts":"import { type Vec3Like } from \"../math/vec\";\nimport { Geometry, type CylinderOptions, type PlaneOptions, type SphereOptions } from \"./Geometry\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\n/** Common transform/render options every primitive factory accepts. */\nexport type MeshOptions = {\n material?: Material;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n name?: string;\n castShadows?: boolean;\n receiveShadows?: boolean;\n};\nexport declare class Mesh extends Node {\n private _geometry?;\n private _materials;\n constructor(geometry?: Geometry, material?: Material);\n get geometry(): Geometry | undefined;\n get material(): Material;\n set material(m: Material);\n setMaterial(material: Material, index?: number): this;\n getMaterial(index?: number): Material | null;\n set culling(v: boolean);\n set castShadows(v: boolean);\n set receiveShadows(v: boolean);\n static box(options?: MeshOptions & {\n size?: Vec3Like | number;\n }): Mesh;\n static sphere(options?: MeshOptions & SphereOptions): Mesh;\n static cylinder(options?: MeshOptions & CylinderOptions): Mesh;\n static plane(options?: MeshOptions & PlaneOptions): Mesh;\n /** Wrap a custom Geometry. */\n static from(geometry: Geometry, options?: MeshOptions): Mesh;\n}\n","types/gl/Model.d.ts":"import { type FetchResponse } from \"../runtime/fetch\";\nimport { Node } from \"./Node\";\nimport { ModelAnimation } from \"./ModelAnimation\";\nexport declare class Model extends Node {\n /** GLB skeletal animation — always present on a Model. */\n readonly anim: ModelAnimation;\n constructor(internalId: number);\n /** Duplicate this model — a deep copy of the GLB (meshes, skeleton, animation clips), attached to\n * the same parent and scene and sharing this model's current transform. The clone has its own\n * independent animation state (reach it via clone.anim). Mirrors Model.load's culling default. */\n clone(): Model;\n /** Load a GLB model. Returns its root as a Model; play its baked clips via model.anim. */\n static load(source: string | FetchResponse, options?: {\n culling?: boolean;\n onProgress?: (p: {\n loaded: number;\n total?: number;\n }) => void;\n }): Promise<Model>;\n}\n","types/gl/ModelAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Model } from \"./Model\";\nexport declare class ModelAnimation extends Aspect<\"anim\", Model> {\n static readonly aspect = \"anim\";\n private _playing;\n private _clip;\n private _speed;\n private _loop;\n onAttach(): void;\n /** The clips baked into the glb. */\n get clips(): {\n name: string;\n duration: number;\n }[];\n get playing(): boolean;\n set playing(value: boolean);\n /** Play a clip by name or index. Chainable. */\n play(clip?: string | number, options?: {\n loop?: boolean;\n }): this;\n stop(): this;\n get loop(): boolean;\n set loop(v: boolean);\n get speed(): number;\n set speed(v: number);\n get time(): number;\n set time(v: number);\n}\n","types/gl/Node.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { Quat, type QuatLike } from \"../math/quat\";\nimport { Mat4, type Mat4Like } from \"../math/mat4\";\nimport type { Geometry } from \"./Geometry\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\n/** id → Node, so host callbacks (touch hits, animation events) route back to the owning object. */\nexport declare const nodeRegistry: Registry<Node>;\nexport type NodeEvents = {\n click: (ev: ClickEvent<Node | null>) => void;\n touchstart: (ev: TouchStartEvent<Node | null>) => void;\n /** A looping GLB animation clip wrapped around. */\n loopReached: (clip: number) => void;\n /** A non-looping GLB animation clip finished. */\n completed: (clip: number) => void;\n /** AR anchors only (`scene.root` / `scene.createAnchor()`): the anchor began tracking. */\n track: () => void;\n /** AR anchors only: the anchor lost tracking. */\n untrack: () => void;\n /** A physics contact/trigger overlap began (the other body's node). Needs a Shape + Physics/Trigger. */\n enter: (other: Node) => void;\n /** A physics contact/trigger overlap ended. */\n exit: (other: Node) => void;\n};\nexport declare class Node extends AspectHost<NodeEvents> {\n /** Native entity handle. */\n readonly id: number;\n /** AR anchors only — whether the anchor is currently being tracked. Kept in step with the\n * 'track' / 'untrack' events; `false` for any non-anchor node. */\n isTracked: boolean;\n private _matrix?;\n private _lastSync;\n private _worldMatrix?;\n private _scaleCache?;\n constructor(internalId?: number);\n /** Geometry, if this node is a Mesh (used by physics auto-shape). Overridden by Mesh. */\n get geometry(): Geometry | undefined;\n get name(): string;\n set name(value: string);\n get visible(): boolean;\n set visible(value: boolean);\n private _sync;\n get matrix(): Mat4;\n set matrix(m: Mat4Like);\n get worldMatrix(): Mat4;\n set worldMatrix(m: Mat4Like);\n get position(): Vec3;\n set position(v: Vec3Like);\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get z(): number;\n set z(v: number);\n get scale(): Vec3;\n set scale(v: Vec3Like | number);\n get quaternion(): Quat;\n set quaternion(v: QuatLike);\n get eulerAngles(): Vec3;\n set eulerAngles(v: Vec3Like);\n get forward(): Vec3;\n get worldPosition(): Vec3;\n get worldScale(): Vec3;\n get worldQuaternion(): Quat;\n get worldEulerAngles(): Vec3;\n get parent(): Node | null;\n get children(): Node[];\n get childCount(): number;\n getChild(index: number): Node | null;\n /** Parent the given nodes under this one. */\n add(...children: Node[]): this;\n setParent(parent: Node | null, worldPositionStays?: boolean): this;\n traverse(callback: (node: Node) => void): void;\n /** Orient the node so the given axis (default \"-z\", \"forward\") points at a world point. */\n lookAt(point: Vec3Like, mode?: \"z\" | \"-z\" | \"x\" | \"-x\" | \"y\" | \"-y\", ortho?: Vec3Like): this;\n addEventListener<K extends keyof NodeEvents>(channel: K, callback: NodeEvents[K]): void;\n destroy(): void;\n}\n","types/gl/Noise.d.ts":"export declare class Noise {\n private readonly _id;\n constructor();\n /** Sample 2D noise. */\n get(x: number, y: number): number;\n /** Sample 3D noise. */\n get3d(x: number, y: number, z: number): number;\n private _frequency;\n get frequency(): number;\n set frequency(v: number);\n private _octaves;\n get octaves(): number;\n set octaves(v: number);\n private _fractalLacunarity;\n get fractalLacunarity(): number;\n set fractalLacunarity(v: number);\n private _fractalGain;\n get fractalGain(): number;\n set fractalGain(v: number);\n}\n","types/gl/Particles.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type Vec3Like } from \"../math/vec\";\nimport { Material, type ParticlesMaterialOptions } from \"./Material\";\nimport { Node } from \"./Node\";\ntype Range<T> = T | {\n min: T;\n max: T;\n};\nexport declare class CurveBuilder {\n private _kind;\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<number>, mode: \"multiply\" | \"add\");\n /** Curve value at birth (t = 0). Must come before any other stop. */\n from(v: Range<number>): this;\n /** Curve value at `t` (0..1 of the particle's life). Stops must be added in ascending t order. */\n via(t: number, v: Range<number>): this;\n /** Curve value at death (t = 1). */\n to(v: Range<number>): this;\n /** The classic opacity envelope: rise over the first `fadeIn`, fall over the last `fadeOut`. */\n fade(fadeIn?: number, fadeOut?: number): this;\n /** The PARAM_CURVE record payload (sans slot): [kind, baseLo, baseHi, n, (t, lo, hi)×n]. */\n get _data(): Float32Array;\n}\nexport declare class ColorCurveBuilder {\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<ColorInput>);\n /** Curve color at birth (t = 0). Must come first. The curve multiplies the base color. */\n from(c: Range<ColorInput>): this;\n /** Curve color at `t` (0..1 of the particle's life), in ascending t order. */\n via(t: number, c: Range<ColorInput>): this;\n /** Curve color at death (t = 1). */\n to(c: Range<ColorInput>): this;\n /** The COLOR_CURVE record payload: [baseLo rgba, baseHi rgba, n, (t, lo rgba, hi rgba)×n]. */\n get _data(): Float32Array;\n}\n/** A value curve over each particle's lifetime. Default mode `multiply` (the curve scales the\n * base); `add` offsets it instead. */\nexport declare const curve: (base?: Range<number>, mode?: \"multiply\" | \"add\") => CurveBuilder;\n/** A color curve over each particle's lifetime — always multiplies the base color. */\nexport declare const colorCurve: (base?: Range<ColorInput>) => ColorCurveBuilder;\nexport type ParticleValue = Range<number> | CurveBuilder | {\n _data: Float32Array;\n};\nexport type ParticleColor = ColorInput | {\n min: ColorInput;\n max: ColorInput;\n} | ColorCurveBuilder | {\n _data: Float32Array;\n};\ntype VelocityValue = {\n speed?: Range<number>;\n /** Cone half-angle in radians — jitter the launch direction uniformly within it. */\n spread?: number;\n /** Asymmetric jitter: two angles (u, v — the x/y components) in radians. */\n randomizeAngle?: {\n min: Vec3Like;\n max: Vec3Like;\n };\n} & ({\n from: Vec3Like;\n} | {\n to: Vec3Like;\n} | {\n dir: Vec3Like;\n} | {});\ntype Shape = {\n type: \"point\";\n v: Vec3Like;\n} | {\n type: \"box\";\n min: Vec3Like;\n max: Vec3Like;\n} | {\n type: \"circle\";\n center: Vec3Like;\n radius: number;\n};\ntype Noise = {\n strength?: number;\n frequency?: number;\n speed?: number;\n};\nexport type ParticlesOptions = ParticlesMaterialOptions & {\n /** Custom draw material. Unset = the default point-sprite material, configured by the\n * `ParticlesMaterialOptions` sugar (map/sheet/emissive/blend/soft) — which is ignored\n * when an explicit material is passed. */\n material?: Material;\n /** Particle pool capacity (default 1000). */\n maxParticles?: number;\n /** Particles emitted per second. */\n rate?: number;\n shape?: Shape;\n startVelocity?: Vec3Like | VelocityValue;\n /** Downward acceleration, world units/s² — positive pulls particles DOWN (sugar for\n * `acceleration: [0, -g, 0]`). */\n gravity?: number;\n /** Constant acceleration vector (gravity, wind, …). Wins over `gravity` when both are set. */\n acceleration?: Vec3Like;\n drag?: number;\n lifetime?: Range<number>;\n color?: ParticleColor;\n /** World-unit diameter (alias of custom[0]). Default 1. */\n size?: ParticleValue;\n /** Radians (alias of custom[1]). */\n rotation?: ParticleValue;\n /** Per-particle opacity 0..1 (alias of custom[2]). Default 1. */\n opacity?: ParticleValue;\n /** Flipbook frame index (alias of custom[3]). With `sheet` set and no explicit frame, the\n * default is one full sheet cycle over each particle's lifetime from a random start frame. */\n frame?: ParticleValue;\n noise?: Noise | null;\n /** Fixed random seed for deterministic tests. */\n seed?: number;\n};\nexport declare class Particles extends Node {\n private _material;\n /** Custom curve-param slots (0..3); size/rotation/opacity/frame alias slots 0-3. */\n readonly custom: ParticleValue[];\n constructor(options?: ParticlesOptions);\n /** Emit `count` particles immediately (a burst). */\n spawn(count: number): this;\n private _send;\n set rate(val: number);\n set shape(shape: Shape);\n set startVelocity(val: Vec3Like | VelocityValue);\n /** Positive pulls particles down — sugar for `acceleration = [0, -g, 0]`. */\n set gravity(val: number);\n set acceleration(a: Vec3Like);\n set drag(val: number);\n set seed(val: number);\n set lifetime(val: Range<number>);\n set size(val: ParticleValue);\n set rotation(val: ParticleValue);\n set opacity(val: ParticleValue);\n set frame(val: ParticleValue);\n set color(value: ParticleColor);\n get material(): Material;\n set material(material: Material);\n set noise(noise: Noise | null);\n}\nexport {};\n","types/gl/Physics.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { type Node } from \"./Node\";\nexport type MotionType = \"static\" | \"dynamic\" | \"kinematic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -9.81, 0]. */\n gravity?: Vec3Like;\n /** Max simultaneous bodies (resizes the world; only before any body exists). Default 4096. */\n maxBodies?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node | null;\n point: Vec3;\n normal: Vec3;\n fraction: number;\n}\nexport declare class Physics extends Aspect<\"physics\", Node> {\n static readonly aspect = \"physics\";\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Default \"dynamic\". */\n motion: MotionType;\n /** Mass in kg for dynamic bodies (default 1). Ignored for static/kinematic. */\n mass: number;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n /** Native Jolt body id. 0 until attached, or if the build has no physics support. */\n get id(): number;\n /** Linear velocity in world units/second (fresh Vec3 on read). */\n get velocity(): Vec3;\n set velocity(v: Vec3Like);\n /** Apply an instantaneous impulse (kg·m/s) and wake the body. */\n applyImpulse(v: Vec3Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position. */\n moveTo(p: Vec3Like): this;\n /** Configure gravity / limits. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_GL_PHYSICS). */\n static get supported(): boolean;\n /** Closest pickable body hit by the ray from `origin` along `dir` (up to `maxDist`), or null. */\n static raycast(origin: Vec3Like, dir: Vec3Like, maxDist?: number): RayHit | null;\n}\n","types/gl/physicsEvents.d.ts":"export declare const ensurePhysicsEvents: () => void;\n","types/gl/Plane.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nimport type { Ray } from \"./Ray\";\nexport declare class Plane {\n /** Unit normal. */\n readonly normal: Vec3;\n /** Scalar offset: dot(normal, point). */\n readonly d: number;\n constructor(normal: Vec3Like, point: Vec3Like);\n static fromPoints(a: Vec3Like, b: Vec3Like, c: Vec3Like): Plane;\n static fromCoefficients(a: number, b: number, c: number, d: number): Plane;\n /** Ray-plane parameter t (≥0), or null on a miss (parallel / behind origin). */\n intersectRay(ray: Ray): number | null;\n /** Like intersectRay but allows hits behind the origin (line-plane). */\n intersectLine(ray: Ray): number | null;\n /** Signed distance from a point (positive on the normal's side). */\n signedDistance(point: Vec3Like): number;\n /** Project a point onto the plane. */\n projectPoint(point: Vec3Like): Vec3;\n}\n","types/gl/Ray.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nexport declare class Ray {\n readonly origin: Vec3;\n readonly dir: Vec3;\n constructor(origin: Vec3Like, dir: Vec3Like);\n /** The world-space point origin + t·dir. */\n getPoint(t: number): Vec3;\n}\n","types/gl/scenarios.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport type { InspectorUI } from \"../core/InspectorUI\";\nimport { Node } from \"./Node\";\nimport { Model } from \"./Model\";\ntype LoopMode = \"once\" | \"loop\" | \"pingpong\";\n/** Travel from the node's starting position to a target node in `duration` seconds. */\nexport declare class MoveTo extends Aspect<\"moveTo\"> {\n /** Where to travel — place an Empty node and pick it. */\n target: Node | null;\n /** Seconds for the full trip. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n /** once = stop at the target · loop = restart from the start point · pingpong = back and forth. */\n mode: LoopMode;\n /** Motion curve. */\n easing: \"smooth\" | \"linear\";\n static readonly aspect = \"moveTo\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<MoveTo>;\n private _t;\n private _start;\n update(dt: number): void;\n /** Editor-only path line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Travel through the children of a path node (add an Empty per waypoint) in `duration` seconds.\n * `loop` runs the circuit closed (last → first); `pingpong` goes back and forth along the open\n * path; `once` stops at the last waypoint. */\nexport declare class FollowPath extends Aspect<\"followPath\"> {\n /** A node whose CHILDREN are the waypoints, in file order. */\n path: Node | null;\n /** Seconds for one full pass of the path. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n mode: LoopMode;\n /** Turn to face the direction of travel. */\n orient: boolean;\n /** Which local axis leads when orienting. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n static readonly aspect = \"followPath\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<FollowPath>;\n private _t;\n private _points;\n update(dt: number): void;\n /** Editor-only waypoint polyline (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Continuous rotation about one of the node's local axes, degrees per second. */\nexport declare class Spin extends Aspect<\"spin\"> {\n /** Degrees per second. */\n speed: number;\n /** Local axis to spin around. */\n axis: \"x\" | \"y\" | \"z\";\n static readonly aspect = \"spin\";\n static fields: FieldMeta<Spin>;\n update(dt: number): void;\n}\n/** Keep the node facing a target node (a turret tracking, a signpost, a camera aimed at a hero).\n * Accessor `node.facing` — NOT `lookAt`, which would shadow the `Node.lookAt()` method. */\nexport declare class LookAt extends Aspect<\"facing\"> {\n /** The node to face. */\n target: Node | null;\n /** Which local axis points at the target. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n /** 0 = snap instantly; otherwise seconds of turn lag (bigger = slower, smoother). */\n smoothing: number;\n static readonly aspect = \"facing\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<LookAt>;\n update(dt: number): void;\n /** Editor-only sight line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Start a GLB animation clip when the scene runs. Attach to a `model:` node; the inspector card\n * lists the model's clips live and can preview them while editing. */\nexport declare class PlayAnimation extends Aspect<\"playAnimation\", Model> {\n /** Clip name; empty = the model's first clip. */\n clip: string;\n loop: boolean;\n /** Playback rate (1 = authored speed). */\n speed: number;\n static readonly aspect = \"playAnimation\";\n static fields: FieldMeta<PlayAnimation>;\n onAttach(): void;\n static inspector(ui: InspectorUI, a: PlayAnimation): void;\n}\nexport {};\n","types/gl/Scene.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport type { FetchResponse } from \"../runtime/fetch\";\nimport { Camera } from \"./Camera\";\nimport { type ControlsHandle, type ControlsOptions } from \"./controls\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\nexport type SceneOptions = {\n /** Image-based ambient lighting (default on). */\n ibl?: boolean;\n /** IBL intensity (default 20000). */\n environmentIntensity?: number;\n /** Bloom post-processing. */\n bloom?: boolean;\n bloomIntensity?: number;\n /** Skybox / clear color. */\n skybox?: ColorInput;\n /** Multisample anti-aliasing. */\n antialias?: boolean;\n};\nexport declare class Scene implements Presentable {\n readonly camera: Camera;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node | null>) => void>;\n private _material?;\n private static _active;\n static get active(): Scene | null;\n constructor(options?: SceneOptions);\n /** Scene occlusion material. */\n get occlusionMaterial(): Material;\n set skybox(color: ColorInput);\n setMaterialGlobalParameter(i: number, x: number, y: number, z: number, w: number): void;\n setAntialias(enabled: boolean, scale?: number): void;\n add(...nodes: Node[]): this;\n remove(...nodes: Node[]): this;\n createOverlay(options?: SceneOptions): Scene;\n warmRender(): Promise<void>;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): void | Promise<void>;\n close(): void;\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n}\nexport type ARMode = \"default\" | \"markers\" | \"arcore\" | \"detached\";\nexport declare class ARScene<T extends ARMode = \"default\"> extends Scene {\n readonly mode: T;\n useWarmRender: boolean;\n private _root?;\n constructor(options?: SceneOptions & {\n mode?: T;\n });\n /** Root anchor node (not available in marker mode). */\n get root(): Node;\n /** Create an anchor from a tracking source (e.g. an image target). */\n createAnchor(source: FetchResponse, physicalWidth?: number): Node;\n /**\n * Let the user place & manipulate a node with touch gestures — the staple AR object-placement\n * interaction: ONE finger drags it across the floor (relative to where the camera looks), TWO fingers\n * pinch to scale and twist to rotate. Returns a handle; call `.remove()` to detach. Tunable via\n * options (min/max scale, and toggles for `pan` / `pinch` / `twist`).\n */\n addControls(target: Node, options?: ControlsOptions): ControlsHandle;\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n/**\n * A 3D scene rendered in a VR headset (OpenXR — e.g. Meta Quest). The headset drives the camera:\n * every frame both eyes are rendered from the tracked head pose, so `scene.camera` position/lookAt\n * have no effect while the scene is open. The world origin is at floor level (stage space) —\n * author content with the ground at y = 0 and the user standing at the origin.\n *\n * `open()` rejects on hosts without a VR runtime (\"VR is not supported on this device\").\n */\nexport declare class VRScene extends Scene {\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n","types/gl/Shape.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Shape extends Aspect<\"shape\", Node> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hx, hy, hz] (world units). */\n box?: Vec3Like;\n /** Sphere radius. */\n sphere?: number;\n /** Cylinder aligned on Y: half-height + radius. */\n cylinder?: {\n halfHeight: number;\n radius: number;\n };\n /** Capsule aligned on Y: half-height of the cylinder section + radius. */\n capsule?: {\n halfHeight: number;\n radius: number;\n };\n /** Whether pointer rays can hit this shape (click / touchstart). Default true. */\n raycast: boolean;\n private _shapeId;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n private _createPickBody;\n private _build;\n}\n","types/gl/state.d.ts":"import type { Scene } from \"./Scene\";\nexport declare const glState: {\n activeScene: Scene | null;\n};\n","types/gl/Texture.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture {\n readonly width: number;\n readonly height: number;\n /** Horizontal wrap mode (U). */\n wrapS: number;\n /** Vertical wrap mode (V). */\n wrapT: number;\n constructor(width: number, height: number, id: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n _tex3dId: number;\n }): Texture;\n static load(source: string | FetchResponse | File): Promise<Texture>;\n}\n","types/gl/touch.d.ts":"export declare const registerTouchStartEvent: () => void;\nexport declare const registerTouchEndEvent: () => void;\n","types/gl/Trigger.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Trigger extends Aspect<\"trigger\", Node> {\n static readonly aspect = \"trigger\";\n private _bodyId;\n /** Native body id (0 if no physics support). */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec3Like): this;\n}\n","types/inject.d.ts":"export { Mathf } from \"./math/Mathf\";\nexport { Vec2, Vec3 } from \"./math/vec\";\nexport { Quat } from \"./math/quat\";\nexport { Mat4 } from \"./math/mat4\";\nexport { Color } from \"./core/color\";\nexport { Aspect, type With } from \"./core/Aspect\";\nexport { InspectorUI } from \"./core/InspectorUI\";\nexport { signal, computed, effect, type Signal, type Computed } from \"./core/signals\";\nexport { Canvas, Bitmap } from \"./canvas/Canvas\";\nexport { toast, openURL, SvgSource } from \"./runtime/misc\";\nexport { app, type AppState } from \"./runtime/app\";\nexport { clipboard } from \"./runtime/clipboard\";\nexport { date, type DateValue, type DateInput, type Unit, type Locale } from \"./runtime/datetime\";\nexport { fetch, fetchLocal, FormData, File, type FetchResponse } from \"./runtime/fetch\";\nexport { localStorage } from \"./runtime/storage\";\nexport { device, type HapticStyle, type MotionOptions } from \"./runtime/device\";\nexport { Input } from \"./runtime/input\";\nexport { WebSocket } from \"./runtime/net\";\nexport { AudioPlayer, VideoPlayer } from \"./runtime/media\";\nexport { openFilePicker } from \"./runtime/files\";\nexport { share } from \"./runtime/share\";\nexport { ClickEvent, TouchStartEvent, LongPressEvent } from \"./runtime/touch\";\nexport { Scene2D } from \"./g2/Scene2D\";\nexport { Node2D } from \"./g2/Node2D\";\nexport { Camera2D } from \"./g2/Camera2D\";\nexport { Sprite } from \"./g2/Sprite\";\nexport { SpriteAnimation } from \"./g2/SpriteAnimation\";\nexport { Shape2D } from \"./g2/Shape2D\";\nexport { Physics2D } from \"./g2/Physics2D\";\nexport { Trigger2D } from \"./g2/Trigger2D\";\nexport { CharacterController2D } from \"./g2/CharacterController2D\";\nexport { Tilemap } from \"./g2/Tilemap\";\nexport { Texture2D } from \"./g2/Texture2D\";\nexport { UIScreen, type UIScreenStyle, UIRow, UIColumn, UIBox, type UIContainerStyle, UIText, type UITextStyle, UIButton, type UIButtonStyle, UIImage, type UIImageStyle, UIVideo, type UIVideoStyle, UIInput, UITextArea, type UIInputStyle, UIScrollable, type UIScrollableStyle, UIPager, type UIPagerStyle, UIWidget, type UIWidgetStyle, UIModal, type UIModalStyle, UIBottomSheet, type UIBottomSheetStyle, UIPopover, type UIPopoverStyle, UISpacer, type UISpacerStyle, UIVirtualizedList, Router, NativeView, type UINativeViewStyle, registerFont, __uiMap, } from \"./ui/UI\";\nexport { Presentable } from \"./ui/UI\";\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from \"./ui/UI\";\nexport type { UINode, UINodeChild } from \"./ui/UINode\";\nexport { theme, type ThemeValues, type ThemeAccessors } from \"./ui/theme\";\nexport { animate, animateMat4, stopAnimation, pauseAnimation, resumeAnimation } from \"./animate/animate\";\nexport { cubicBezier } from \"./animate/bezier\";\nexport { easeIn, easeOut, easeInOut } from \"./animate/easings\";\nexport { QRScanner } from \"./plugins/qr\";\nexport { CameraView, type CameraFacing } from \"./plugins/camera\";\nexport { Geolocation, type GeoPosition, type GeoOptions, type GeoWatch } from \"./plugins/geolocation\";\nexport { Service } from \"./plugins/service\";\nexport { defineScene, use, ref, make, SceneHandle } from \"./scene/defineScene\";\nexport type { SceneDef, SceneNodeDef, MeshDef, LightDef, MaterialDef, CameraNodeDef, AspectEntry, MakeEntry, LoadedScene } from \"./scene/defineScene\";\nexport type { FieldMeta } from \"./core/fields\";\nexport { MoveTo, FollowPath, Spin, LookAt, PlayAnimation } from \"./gl/scenarios\";\nexport { registerEditorWindow, registerEditorTool, __editorPlugins } from \"./scene/editorPlugins\";\nexport type { EditorApi, EditorRayHit, EditorToolHooks, EditorWindowFn } from \"./scene/editorPlugins\";\nexport { Scene, ARScene, VRScene } from \"./gl/Scene\";\nexport { Node } from \"./gl/Node\";\nexport { Mesh } from \"./gl/Mesh\";\nexport { Model } from \"./gl/Model\";\nexport { Shape } from \"./gl/Shape\";\nexport { Physics } from \"./gl/Physics\";\nexport { Trigger } from \"./gl/Trigger\";\nexport { CharacterController } from \"./gl/CharacterController\";\nexport { ModelAnimation } from \"./gl/ModelAnimation\";\nexport { Light } from \"./gl/Light\";\nexport { Material } from \"./gl/Material\";\nexport { Geometry } from \"./gl/Geometry\";\nexport { Texture } from \"./gl/Texture\";\nexport { Camera } from \"./gl/Camera\";\nexport { Ray } from \"./gl/Ray\";\nexport { Plane } from \"./gl/Plane\";\nexport { Noise } from \"./gl/Noise\";\nexport { Particles, curve, colorCurve } from \"./gl/Particles\";\n","types/math/mat4.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nimport { Quat, type QuatLike, type EulerOrder } from \"./quat\";\nexport type Mat4Like = Mat4 | number[] | Float32Array | readonly number[];\nexport declare class Mat4 {\n /** The raw column-major elements (length 16). Public on purpose — read/write directly when you want\n * the metal: `mat.m[12] += vx * dt`. The fluent methods never mutate it (they return a new Mat4). */\n m: number[];\n constructor(src?: Mat4Like);\n set(values: ArrayLike<number>): this;\n copy(src: Mat4Like): this;\n /** `this · b` (apply `b` first in local space, then `this`). */\n mul(b: Mat4Like): Mat4;\n /** `b · this` — multiply on the other side (apply `this` first, then `b`). */\n premul(b: Mat4Like): Mat4;\n invert(): Mat4;\n transpose(): Mat4;\n determinant(): number;\n /** `this · translate(v)`. */\n translate(v: Vec3Like): Mat4;\n /** `this · scale(v)`. Accepts a vector or a uniform scalar. */\n scale(v: Vec3Like | number): Mat4;\n /** `this · rotate(axis, rad)`. */\n rotate(rad: number, axis: Vec3Like): Mat4;\n rotateX(rad: number): Mat4;\n rotateY(rad: number): Mat4;\n rotateZ(rad: number): Mat4;\n /** Transform a point (applies translation + perspective divide). */\n transformPoint(v: Vec3Like): Vec3;\n /** Transform a direction (rotation/scale only — no translation, no divide). */\n transformDirection(v: Vec3Like): Vec3;\n get position(): Vec3;\n get scaling(): Vec3;\n get rotation(): Quat;\n get eulerAngles(): Vec3;\n toEuler(order?: EulerOrder): Vec3;\n /** `{ position, rotation, scale }` in one shot. */\n decompose(): {\n position: Vec3;\n rotation: Quat;\n scale: Vec3;\n };\n /** Column basis vectors (the local X / Y / Z axes in world space). */\n get basisX(): Vec3;\n get basisY(): Vec3;\n get basisZ(): Vec3;\n clone(): Mat4;\n toArray(): number[];\n toFloat32Array(): Float32Array;\n equals(b: Mat4Like, eps?: number): boolean;\n static identity(): Mat4;\n static from(src: Mat4Like): Mat4;\n /** Translation · Rotation · Scale into one matrix. `scale` defaults to 1 and accepts a scalar. */\n static compose(position: Vec3Like, rotation: QuatLike, scale?: Vec3Like | number): Mat4;\n static fromQuat(q: QuatLike): Mat4;\n static fromTranslation(v: Vec3Like): Mat4;\n static fromScale(v: Vec3Like | number): Mat4;\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Mat4;\n /** A view matrix that looks from `eye` toward `center` with `up`. */\n static lookAt(eye: Vec3Like, center: Vec3Like, up?: Vec3Like): Mat4;\n /** A world matrix that places something at `eye` oriented to look at `target`. */\n static targetTo(eye: Vec3Like, target: Vec3Like, up?: Vec3Like): Mat4;\n /** Perspective projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). `fovy` is in RADIANS. */\n static perspective(fovy: number, aspect: number, near: number, far: number): Mat4;\n /** Orthographic projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). */\n static ortho(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4;\n}\n","types/math/Mathf.d.ts":"export type Damper<T extends number | number[]> = ((target: T, dt: number) => T) & {\n /** Snap the damper's internal current value (e.g. on teleport). */\n setValue(value: T): void;\n};\ndeclare function smoothDamp(initial: number, smoothTime: number, maxSpeed?: number): Damper<number>;\ndeclare function smoothDamp(initial: number[], smoothTime: number, maxSpeed?: number): Damper<number[]>;\nexport declare const Mathf: {\n PI: number;\n TAU: number;\n EPSILON: number;\n DEG2RAD: number;\n RAD2DEG: number;\n deg2rad: (deg: number) => number;\n rad2deg: (rad: number) => number;\n clamp: (v: number, min: number, max: number) => number;\n clamp01: (v: number) => number;\n lerp: (a: number, b: number, t: number) => number;\n inverseLerp: (a: number, b: number, v: number) => number;\n remap: (v: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;\n /** Move `a` toward `b` by at most `maxDelta`. */\n moveTowards: (a: number, b: number, maxDelta: number) => number;\n /** Frame-rate-independent exponential approach (good default: lambda 5..15). */\n damp: (a: number, b: number, lambda: number, dt: number) => number;\n sign: (x: number) => number;\n /** Loop a value into [0, length). */\n repeat: (t: number, length: number) => number;\n /** Ping-pong a value in [0, length]. */\n pingPong: (t: number, length: number) => number;\n random: (min?: number, max?: number) => number;\n randomInt: (min: number, max: number) => number;\n /**\n * Critically-damped follow (Unity SmoothDamp). Returns a stateful damper you call every frame:\n * const d = Mathf.smoothDamp([x, y], 0.15)\n * pos = d(targetPos, dt)\n * Works on a number or a numeric array (vec2 / vec3).\n */\n smoothDamp: typeof smoothDamp;\n};\nexport {};\n","types/math/quat.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nexport type QuatLike = Quat | readonly [number, number, number, number] | number[] | Float32Array;\nexport type EulerOrder = \"XYZ\" | \"YXZ\" | \"ZXY\" | \"ZYX\" | \"YZX\" | \"XZY\";\n/** Read the w / 4th component of any quaternion-like (wrapper `.w`, or array-like `[3]`). */\nexport declare const cw: (q: {\n w?: number;\n} | ArrayLike<number>) => number;\nexport declare class Quat {\n x: number;\n y: number;\n z: number;\n w: number;\n constructor(x?: number | QuatLike, y?: number, z?: number, w?: number);\n set(x: number, y: number, z: number, w: number): this;\n copy(q: QuatLike): this;\n /** Hamilton product `this ⊗ b` (apply `b` first, then `this`). */\n mul(b: QuatLike): Quat;\n normalize(): Quat;\n conjugate(): Quat;\n /** Inverse rotation. For a unit quaternion this equals `conjugate()`. */\n invert(): Quat;\n dot(b: QuatLike): number;\n /** Spherical interpolation toward `b` by `t ∈ [0, 1]`. */\n slerp(b: QuatLike, t: number): Quat;\n /** Angular distance (radians) between two unit quaternions. */\n angle(b: QuatLike): number;\n /** Rotate a vector by this quaternion → a new `Vec3`. */\n rotateVec3(v: Vec3Like): Vec3;\n /** Extract euler angles (DEGREES) in the given order. */\n toEuler(order?: EulerOrder): Vec3;\n equals(b: QuatLike, eps?: number): boolean;\n /** True if the two unit quaternions represent the same rotation (±q are equal). */\n sameRotation(b: QuatLike, eps?: number): boolean;\n clone(): Quat;\n toArray(): [number, number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(q: QuatLike): Quat;\n static get identity(): Quat;\n /** From euler angles in DEGREES (default order \"YXZ\"). Inverts `toEuler`. */\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Quat;\n /** From a rotation `axis` and an angle in RADIANS. The axis is normalized for you. */\n static fromAxisAngle(axis: Vec3Like, rad: number): Quat;\n /** The shortest rotation that takes direction `a` onto direction `b`. */\n static fromTo(a: Vec3Like, b: Vec3Like): Quat;\n /** A rotation whose forward (−Z) points along `forward`, with `up` as the reference up axis. */\n static lookRotation(forward: Vec3Like, up?: Vec3Like): Quat;\n}\n/** Quaternion from a column-major rotation matrix (≥3×3, indices 0,1,2,4,5,6,8,9,10). gl-matrix's\n * `getRotation` algorithm — the exact inverse of building a matrix from a quaternion. */\nexport declare const quatFromColMajor: (m: ArrayLike<number>) => Quat;\n/** Euler angles (DEGREES) from a column-major rotation matrix, standard three.js extraction.\n * Element naming follows the column-major layout: mRC = m[(C-1)*4 + (R-1)]. */\nexport declare const eulerFromColMajor: (m: ArrayLike<number>, order?: EulerOrder) => Vec3;\n","types/math/vec.d.ts":"export type Vec2Like = Vec2 | readonly [number, number] | number[] | Float32Array;\nexport type Vec3Like = Vec3 | readonly [number, number, number] | number[] | Float32Array;\n/** Read the x / first component of any vector-like (wrapper, tuple, or typed array). `?? ` is safe on\n * 0 and NaN — it only falls through on `undefined` (i.e. a non-wrapper that has no `.x`). */\nexport declare const cx: (v: {\n x?: number;\n} | ArrayLike<number>) => number;\nexport declare const cy: (v: {\n y?: number;\n} | ArrayLike<number>) => number;\nexport declare const cz: (v: {\n z?: number;\n} | ArrayLike<number>) => number;\nexport declare class Vec2 {\n x: number;\n y: number;\n constructor(x?: number | Vec2Like, y?: number);\n /** Mutate the components in place. Returns `this`. */\n set(x: number, y: number): this;\n /** Copy another vector's components into this one. Returns `this`. */\n copy(v: Vec2Like): this;\n add(v: Vec2Like): Vec2;\n sub(v: Vec2Like): Vec2;\n mul(v: Vec2Like): Vec2;\n div(v: Vec2Like): Vec2;\n scale(s: number): Vec2;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec2Like, s: number): Vec2;\n negate(): Vec2;\n dot(v: Vec2Like): number;\n /** 2D cross product → the scalar z of the 3D cross (signed parallelogram area). */\n cross(v: Vec2Like): number;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec2Like): number;\n distanceSqTo(v: Vec2Like): number;\n normalize(): Vec2;\n lerp(v: Vec2Like, t: number): Vec2;\n clamp(min: Vec2Like, max: Vec2Like): Vec2;\n min(v: Vec2Like): Vec2;\n max(v: Vec2Like): Vec2;\n /** Left-hand perpendicular: (-y, x), a 90° CCW turn. */\n perp(): Vec2;\n /** Rotate by `rad` (CCW) around `origin` (default 0). */\n rotate(rad: number, origin?: Vec2Like): Vec2;\n /** The vector's heading in radians: `atan2(y, x)`. */\n heading(): number;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec2Like): number;\n withX(x: number): Vec2;\n withY(y: number): Vec2;\n equals(v: Vec2Like, eps?: number): boolean;\n clone(): Vec2;\n toArray(): [number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec2Like): Vec2;\n static get zero(): Vec2;\n static get one(): Vec2;\n static get up(): Vec2;\n static get down(): Vec2;\n static get left(): Vec2;\n static get right(): Vec2;\n}\nexport declare class Vec3 {\n x: number;\n y: number;\n z: number;\n constructor(x?: number | Vec3Like, y?: number, z?: number);\n set(x: number, y: number, z: number): this;\n copy(v: Vec3Like): this;\n add(v: Vec3Like): Vec3;\n sub(v: Vec3Like): Vec3;\n mul(v: Vec3Like): Vec3;\n div(v: Vec3Like): Vec3;\n scale(s: number): Vec3;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec3Like, s: number): Vec3;\n negate(): Vec3;\n dot(v: Vec3Like): number;\n cross(v: Vec3Like): Vec3;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec3Like): number;\n distanceSqTo(v: Vec3Like): number;\n normalize(): Vec3;\n lerp(v: Vec3Like, t: number): Vec3;\n clamp(min: Vec3Like, max: Vec3Like): Vec3;\n min(v: Vec3Like): Vec3;\n max(v: Vec3Like): Vec3;\n /** Reflect this vector about a (unit) `normal`: `v - 2·(v·n)·n`. */\n reflect(normal: Vec3Like): Vec3;\n /** Vector projection of this onto `onto`. */\n project(onto: Vec3Like): Vec3;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec3Like): number;\n /** Rotate this point around the X axis through `origin` (default 0) by `rad`. */\n rotateX(rad: number, origin?: Vec3Like): Vec3;\n rotateY(rad: number, origin?: Vec3Like): Vec3;\n rotateZ(rad: number, origin?: Vec3Like): Vec3;\n /** Rotate this vector by a quaternion (x, y, z, w). Accepts a `Quat` or a raw `[x,y,z,w]`. */\n rotate(q: ArrayLike<number> | {\n x: number;\n y: number;\n z: number;\n w: number;\n }): Vec3;\n /** Transform this point by a column-major mat4 (a `Mat4`, its `.m`, or a raw length-16 array),\n * applying translation and the perspective divide. */\n transform(m: ArrayLike<number> | {\n m: ArrayLike<number>;\n }): Vec3;\n withX(x: number): Vec3;\n withY(y: number): Vec3;\n withZ(z: number): Vec3;\n equals(v: Vec3Like, eps?: number): boolean;\n clone(): Vec3;\n toArray(): [number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec3Like): Vec3;\n static get zero(): Vec3;\n static get one(): Vec3;\n static get up(): Vec3;\n static get down(): Vec3;\n static get left(): Vec3;\n static get right(): Vec3;\n /** Forward is −Z (the engine's cameras look down −Z; `node.forward` is −Z at identity). */\n static get forward(): Vec3;\n static get back(): Vec3;\n}\n","types/plugins/camera.d.ts":"import { File } from \"../runtime/fetch\";\nimport { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport type CameraFacing = \"front\" | \"back\";\nexport interface CameraView extends NativeView {\n /** Request camera permission, then present the preview. The current destination stays visible\n * until the camera is ready; rejects if permission is denied, the host has no camera, or\n * another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n /** Capture a still frame as an image `File` (host-encoded). */\n takePhoto(): Promise<File>;\n /** Switch between the front and back camera while the preview is live. */\n setFacingMode(facingMode: CameraFacing): Promise<void>;\n}\n/**\n * Create a camera view (default: the back camera). `CameraView.isSupported` reports whether this\n * host has a camera capability — check it before offering the feature.\n */\nexport declare const CameraView: {\n (options?: {\n facingMode?: CameraFacing;\n }): CameraView;\n /** Whether this host registered a \"camera\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/geolocation.d.ts":"export interface GeoPosition {\n latitude: number;\n longitude: number;\n /** Horizontal accuracy radius, meters. */\n accuracy: number;\n /** Meters above sea level, or null when the provider doesn't know. */\n altitude: number | null;\n /** Direction of travel in degrees clockwise from north, or null when stationary/unknown. */\n heading: number | null;\n /** Ground speed in m/s, or null when unknown. */\n speed: number | null;\n /** When this fix was taken, ms epoch. */\n timestamp: number;\n}\nexport interface GeoOptions {\n /** Prefer the precise (GPS) provider — slower first fix, more battery. Default false. */\n highAccuracy?: boolean;\n /** getCurrent only: reject with \"timeout\" if no fix arrives in this many ms. */\n timeout?: number;\n}\n/** A live `Geolocation.watch()` subscription — `stop()` it when the screen goes away. */\nexport interface GeoWatch {\n stop(): void;\n}\n/**\n * The device position. `Geolocation.isSupported` reports whether this host registered the\n * service — check it before offering location features.\n */\nexport declare const Geolocation: {\n /** Whether this host registered a \"geolocation\" service. */\n readonly isSupported: boolean;\n /** One position fix. Prompts for permission on first use; rejects on denial (\"denied\"), no\n * provider (\"unavailable\"), or `options.timeout` elapsing (\"timeout\"). */\n getCurrent(options?: GeoOptions): Promise<GeoPosition>;\n /** Continuous updates. Resolves once watching (permission granted + provider started) — so a\n * denial is a rejection, never a silently dead callback. One host watch serves every\n * subscriber; the options of the watch that starts it win. Always `stop()` when done. */\n watch(callback: (position: GeoPosition) => void, options?: GeoOptions): Promise<GeoWatch>;\n};\n","types/plugins/permission.d.ts":"export declare const _requestCameraPermission: () => Promise<void>;\n","types/plugins/qr.d.ts":"import { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport interface QRScanner extends NativeView {\n /** Fires per decoded camera frame: the decoded string, or `null` for a frame with no readable\n * code (expect those repeatedly while the user aims). The same code can be reported more than\n * once — `close()` or debounce once you have what you need. */\n onScan(callback: (data: string | null) => void): this;\n /** Request camera permission, then present the scanner. The current destination (and its\n * loading state) stays visible until the scanner is ready; rejects if the camera is denied,\n * the host can't scan, or another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n}\n/**\n * Create a QR scanner view. `QRScanner.isSupported` reports whether this host can scan at all —\n * check it before offering the feature.\n */\nexport declare const QRScanner: {\n (): QRScanner;\n /** Whether this host registered a \"qrScanner\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/service.d.ts":"export interface Service {\n /** Invoke a method on the service (`battery.call(\"level\")`). Arguments and the result are\n * JSON-serialized; rejects when the host has no such service or the method reports an\n * error. The host session opens lazily on the first call. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the service emits while a session is open\n * (`battery.on(\"change\", data => …)`). Payloads are JSON-decoded. */\n on(event: string, callback: (data?: any) => void): this;\n /** Remove a previously added listener. */\n off(event: string, callback: (data?: any) => void): this;\n /** Close the host session (stops whatever the service was doing). Listeners stay\n * registered — a later `call()` opens a fresh session that delivers to them again. */\n close(): void;\n}\n/**\n * A host-registered headless service — the UI-less sibling of `NativeView`. Use it for\n * services without a typed wrapper: native code registered in your app shell\n * (`engine.registerService(\"app.battery\") { … }`) or a third-party plugin's channel.\n * **Host-optional** — gate on `Service.isSupported` (the web editor registers none of them).\n *\n * ```ts\n * if (Service.isSupported(\"app.battery\")) {\n * const battery = Service(\"app.battery\")\n * battery.on(\"change\", data => { level.text = data.level + \"%\" })\n * const { level } = await battery.call(\"level\")\n * }\n * ```\n */\nexport declare const Service: {\n (name: string, params?: any): Service;\n /** Whether this host registered a service under `name`. */\n isSupported(name: string): boolean;\n};\n","types/runtime/app.d.ts":"export type AppState = \"active\" | \"background\";\ntype AppEventMap = {\n /** The app left the foreground (home button, tab hidden, another app on top). Delivered before\n * the host halts the frame loop — the last chance to persist state / pause work. */\n pause: () => void;\n /** The app returned to the foreground; frames are running again. */\n resume: () => void;\n /** A link arrived while the app was running (warm deep link). `app.launchUrl` is already\n * updated to the same value when this fires. */\n url: (url: string) => void;\n /** The on-screen keyboard changed. `height` mirrors `app.keyboardHeight` (the raw overlap, see\n * there); `duration` is the platform's keyboard animation duration in ms (0 where none) — pass\n * it to `animateTo` to move a composer in sync with the keyboard. */\n keyboard: (height: number, duration: number) => void;\n};\nexport declare const app: {\n /** Current lifecycle state. `\"background\"` while the app is not the foreground app / the tab is\n * hidden. `\"active\"` on hosts that don't track it. */\n readonly state: AppState;\n /** The URL the app was (most recently) opened with — the deep link — or `null` for a plain\n * launch. Warm links update it and fire the `\"url\"` event. */\n readonly launchUrl: string | null;\n /** On-screen keyboard height in logical px currently overlapping the app viewport, `0` when\n * hidden. This is the RAW overlap, independent of the focused input's `keyboardShrink` policy —\n * with the default shrink the layout already avoids the keyboard; the main consumer is overlay\n * mode (`keyboardShrink: false`), e.g. a chat composer's `pb`. `0` on hosts without an\n * on-screen keyboard. */\n readonly keyboardHeight: number;\n addEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n removeEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n};\nexport {};\n","types/runtime/appEvents.d.ts":"type AppEventCallback = (data?: string) => void;\nexport declare const appEventsOn: (event: string, cb: AppEventCallback) => void;\nexport declare const appEventsOff: (event: string, cb: AppEventCallback) => void;\ntype KeyboardCallback = (height: number, duration: number) => void;\nexport declare const keyboardEventsOn: (cb: KeyboardCallback) => void;\nexport declare const keyboardEventsOff: (cb: KeyboardCallback) => void;\nexport {};\n","types/runtime/channel.d.ts":"export {};\n","types/runtime/clipboard.d.ts":"export declare const clipboard: {\n /** Put `text` on the system clipboard. Silent no-op on hosts without clipboard access. */\n write(text: string): void;\n /** Read text from the system clipboard. Rejects when the platform has no clipboard access, the\n * user denied it, or there is nothing readable. */\n read(): Promise<string>;\n};\n","types/runtime/datetime.d.ts":"export type Locale = \"en\" | \"ru\";\nexport type DateInput = Date | number | string | DateValue;\nexport type Unit = \"ms\" | \"second\" | \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\" | \"year\";\n/**\n * An immutable moment in time — the value returned by [`date()`]. Wraps a single epoch-millisecond\n * scalar (`t`); every method returns a new `DateValue` or a plain scalar, never mutating. Construct\n * it with `date(...)`, not `new`.\n */\nexport declare class DateValue {\n /** Epoch milliseconds — the one canonical scalar. Prefer `valueOf()`; this is public so `date(a)`\n * can read it back cheaply and so tooling can treat it as the value's single component. */\n readonly t: number;\n constructor(ms: number);\n /**\n * Format against a `day.js`-style token pattern (default `\"D MMMM YYYY\"`). Locale defaults to the\n * current device language.\n *\n * Tokens: `YYYY`/`YY` year · `MMMM`/`MMM`/`MM`/`M` month · `DD`/`D` day · `dddd`/`ddd` weekday ·\n * `HH`/`H` 24-hour · `hh`/`h` 12-hour · `mm`/`m` minute · `ss`/`s` second · `A`/`a` AM/PM.\n *\n * ```ts\n * date().format() // \"10 July 2026\" / \"10 июля 2026\"\n * date(ts).format(\"DD.MM.YYYY HH:mm\") // \"10.07.2026 14:05\"\n * date(ts).format(\"MMMM YYYY\", \"ru\") // \"Июль 2026\" (nominative — no day token)\n * ```\n */\n format(pattern?: string, locale?: Locale): string;\n /**\n * Human relative time vs `now` (default: the current time) — \"5 minutes ago\", \"in 2 days\",\n * \"5 минут назад\", \"через 2 дня\". Reads as \"just now\" under ~45 seconds; handles Russian number\n * agreement (`1 минуту` / `2 минуты` / `5 минут`). Locale defaults to the device language.\n */\n timeAgo(locale?: Locale, now?: DateInput): string;\n /** Add `n` of a unit, returning a new value. Linear units (`ms`…`week`) are scalar ms math;\n * `month`/`year` are calendar-aware (clamp on short months, like day.js). */\n add(n: number, unit: Unit): DateValue;\n /** Subtract `n` of a unit. Equivalent to `add(-n, unit)`. */\n subtract(n: number, unit: Unit): DateValue;\n /** Snap down to the start of a unit (local time): start of day/hour/month/year, etc. */\n startOf(unit: Unit): DateValue;\n /** Snap up to the end of a unit (local time): the last millisecond of the day/hour/month/… */\n endOf(unit: Unit): DateValue;\n /** Epoch milliseconds. Enables `+date(x)`, `date(a) < date(b)`, `date(a) - date(b)` via coercion. */\n valueOf(): number;\n /** Whole seconds since the epoch (Unix time). */\n unix(): number;\n /** Signed difference to `other`, in whole `unit`s (default `ms`), truncated toward zero. */\n diff(other: DateInput, unit?: Unit): number;\n isBefore(other: DateInput): boolean;\n isAfter(other: DateInput): boolean;\n isSame(other: DateInput): boolean;\n year(): number;\n /** 0-based month (0 = January), matching `Date.getMonth`. */\n month(): number;\n /** Day of the month, 1–31. */\n day(): number;\n /** Day of the week, 0 (Sunday)–6 (Saturday), matching `Date.getDay`. */\n weekday(): number;\n hour(): number;\n minute(): number;\n second(): number;\n /** A native `Date` snapshot of this value. */\n toDate(): Date;\n}\n/**\n * Create a `DateValue` — a locale-aware, immutable moment, dayjs-style. Accepts a `Date`, a\n * millisecond timestamp (`Date.now()`), a parseable string, or another `DateValue`; with no argument\n * it's the current time. Chain arithmetic and finish with `format` / `timeAgo`, both of which\n * understand **English** and **Russian** and default to the current device language\n * ([`device.language`](../runtime/device.ts)).\n *\n * ```ts\n * date().format(\"dddd, D MMMM\") // \"Friday, 10 July\" / \"пятница, 10 июля\"\n * date(ts).timeAgo() // \"5 minutes ago\" / \"5 минут назад\"\n * date().add(3, \"day\").startOf(\"day\").format(\"D MMMM\")\n * date(a).diff(b, \"hour\") // signed whole hours\n * date(a).isBefore(b) // boolean\n * ```\n */\nexport declare const date: (value?: DateInput) => DateValue;\n","types/runtime/device.d.ts":"import { Quat } from \"../math/quat\";\nimport { Vec3 } from \"../math/vec\";\ntype ResizeCallback = (width: number, height: number) => void;\ntype DeviceEventMap = {\n resize: ResizeCallback;\n /** Connectivity came back (best-effort, navigator.onLine semantics). */\n online: () => void;\n /** Connectivity was lost. */\n offline: () => void;\n};\n/** Semantic haptic styles for `device.vibrate`. Impact styles (`light`/`medium`/`heavy`/`soft`/\n * `rigid`) are a physical \"tap\" of varying weight; notification styles (`success`/`warning`/`error`)\n * cue an outcome; `selection` is a light tick for a value change. Chosen to map 1:1 onto iOS\n * `UIFeedbackGenerator` and, on Android, `HapticFeedbackConstants` / `VibrationEffect` — so the same\n * call feels native everywhere, rather than a duration that only web/Android can honor. */\nexport type HapticStyle = \"light\" | \"medium\" | \"heavy\" | \"soft\" | \"rigid\" | \"success\" | \"warning\" | \"error\" | \"selection\";\n/** Options for `device.motion.start`. */\nexport interface MotionOptions {\n /** Sensor update interval in seconds (default 1/60). The sensor fuses at ≥ this rate in the\n * background; you poll the freshest sample each frame, so this is a floor, not a sync. */\n interval?: number;\n /** Frame the readables are delivered in. \"world\" (default): engine Y-up, screen-oriented — drops\n * straight into `camera.quaternion` / any node. \"device\": the raw sensor frame, no conversion. */\n frame?: \"world\" | \"device\";\n}\nexport declare const device: {\n readonly platform: \"web\" | \"android\" | \"ios\" | string;\n readonly language: string;\n /** Display device-pixel ratio (physical px per logical/CSS px): 1 on standard displays, 2–3 on\n * retina / iOS. Bake a Canvas at this ratio for crisp output without hardcoding, e.g.\n * `new Canvas(w, h, { pixelRatio: device.pixelRatio })`. NOTE: the web 2D/GL surface currently\n * renders at logical resolution, so on web this only helps UI canvases / is forward-looking for\n * 2D; on iOS (physical surface) it makes 2D canvases crisp. Falls back to 1 if the host omits it. */\n readonly pixelRatio: number;\n /** Current display width in logical px — the same value the \"resize\" event delivers, but readable at\n * any time (not only inside the listener). 0 until the host has reported a size. */\n readonly width: number;\n /** Current display height in logical px — the same value the \"resize\" event delivers, readable at any\n * time. 0 until the host has reported a size. */\n readonly height: number;\n /** Opt into the precise-touch system where the platform supports it. OFF by default. When on, fast\n * strokes are sampled at the touch digitizer's full rate (iOS coalesced touches, ≈120–240 Hz) instead\n * of once per display frame (~60 Hz), so a pointer-heavy app (drawing, handwriting, dragging) gets more\n * points and smoother lines. Leave it off for tap/button UIs. No-op on hosts without a coalesced-input\n * concept (web already coalesces pointermove; headless). */\n setPreciseTouch(enabled: boolean): void;\n /** Fire a one-shot haptic of the given semantic `style` (default `\"medium\"`) — a physical tap on\n * supported hardware (iOS Taptic Engine, Android vibrator). Chosen by meaning, not duration, so it\n * feels native on each platform; see {@link HapticStyle}. Host-gated: a silent no-op where there's\n * no haptic hardware (iPad, older iPhones, web, headless). */\n vibrate(style?: HapticStyle): void;\n /** Device-orientation sensor (gyro + accelerometer, fused) for tilt/steering and magic-window /\n * 360° panoramas. Poll `attitude` / `gravity` inside setLoop; they return the freshest fused\n * sample, so the sensor rate need not match your frame rate. Host-gated: a no-op with no sensor. */\n motion: {\n /** Whether this device has the motion sensors at all (no gyro → false; iPad/older, web, headless). */\n readonly available: boolean;\n /** Whether updates are currently running (start succeeded and stop hasn't been called). */\n readonly enabled: boolean;\n /** Begin sensor updates. Resolves to whether it actually started (false = no sensor / denied).\n * Async so a web host can await its permission prompt; native resolves immediately. */\n start(options?: MotionOptions): Promise<boolean>;\n /** Stop sensor updates and release the sensor (battery). */\n stop(): void;\n /** Capture the current heading as \"forward\" — a yaw-only recenter (pitch/roll stay gravity-\n * referenced, so the horizon stays level). No-op in the \"device\" frame. */\n recenter(): void;\n /** The device's current orientation as a `Quat`. In the \"world\" frame (default) it's engine Y-up\n * and screen-oriented, so `camera.quaternion = device.motion.attitude` is a complete magic-window\n * / panorama camera. `Quat.identity` until the first sample arrives / when not running. */\n readonly attitude: Quat;\n /** Gravity direction for tilt controls. In the \"world\" frame it's SCREEN space (x → right, y →\n * down, matching clientX/clientY), orientation-aware — a 2D game reads `gravity.x / gravity.y`.\n * `(0,0,0)` when not running. */\n readonly gravity: Vec3;\n };\n /** Current connectivity — best-effort navigator.onLine semantics: `false` only when the platform\n * is sure there's no network. `true` on hosts that don't track it. Change events: `\"online\"` /\n * `\"offline\"`. */\n readonly online: boolean;\n addEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n removeEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n};\nexport {};\n","types/runtime/fetch.d.ts":"export type FetchOptions = {\n body?: any;\n method?: string;\n headers?: Record<string, string>;\n useOnce?: boolean;\n onProgress?: (progress: {\n loaded: number;\n total?: number;\n }) => void;\n};\nexport interface FetchResponse {\n readonly status: number;\n json<T = any>(): T;\n text(): string;\n dispose(): void;\n}\nexport declare const fetch: (url: string, options?: FetchOptions) => Promise<FetchResponse>;\nexport declare const fetchLocal: (path: string) => FetchResponse;\n/** A handle to a picked / fetched file (see openFilePicker). */\nexport declare class File {\n readonly id: number;\n readonly name: string;\n readonly size: number;\n constructor(id: number, name: string, size: number);\n}\ntype FormDataValue = string | number | boolean | File | FetchResponse;\nexport declare class FormData {\n private _entries;\n append(name: string, value: FormDataValue, filename?: string): void;\n delete(name: string): void;\n}\nexport {};\n","types/runtime/files.d.ts":"import { File } from \"./fetch\";\ntype OpenFilePickerOptions = {\n accept?: string;\n};\nexport declare function openFilePicker(options?: OpenFilePickerOptions & {\n multiple?: false;\n}): Promise<File | null>;\nexport declare function openFilePicker(options: OpenFilePickerOptions & {\n multiple: true;\n}): Promise<File[]>;\nexport {};\n","types/runtime/input.d.ts":"export declare const Input: {\n /**\n * Is a key currently held? `code` is a KeyboardEvent.code-style string, e.g. 'ArrowRight',\n * 'KeyW', 'Space'. Poll this inside setLoop for frame-independent movement.\n */\n key(code: string): boolean;\n};\n","types/runtime/media.d.ts":"import { Emitter } from \"../core/events\";\nimport { Texture } from \"../gl/Texture\";\ntype MediaEvents = {\n /** Fired at each loop boundary while `loop` is true. */\n loopReached: () => void;\n /** Fired once when playback reaches the end while `loop` is false. */\n completed: () => void;\n};\ndeclare abstract class MediaPlayer extends Emitter<MediaEvents> {\n protected _id: number;\n protected _src: string;\n private _playing;\n private _loop;\n private _volume;\n private _disposed;\n private _assertAlive;\n play(): void;\n pause(): void;\n get playing(): boolean;\n set playing(value: boolean);\n get volume(): number;\n set volume(value: number);\n get loop(): boolean;\n set loop(value: boolean);\n /** Current playback position, in seconds. Settable to seek. */\n get time(): number;\n set time(value: number);\n /** Total media length in seconds (0 until metadata has loaded). */\n get duration(): number;\n /** True once {@link dispose} has been called; the player is unusable afterwards. */\n get disposed(): boolean;\n /**\n * Release the underlying host media resource (decoder, network, buffers) immediately and detach\n * all listeners. Idempotent. Any further use of the player throws.\n */\n dispose(): void;\n}\nexport declare class AudioPlayer extends MediaPlayer {\n constructor(src?: string);\n}\nexport declare class VideoPlayer extends MediaPlayer {\n constructor(src?: string);\n /** A 3D Texture that samples this video (e.g. for a Material.video()). */\n get texture(): Texture;\n}\nexport {};\n","types/runtime/misc.d.ts":"/** Show a transient toast notification. */\nexport declare const toast: (msg: string) => void;\n/** Open `url` in the system browser / external handler (fire-and-forget, like `share`). Silent\n * no-op on hosts without one (headless). */\nexport declare const openURL: (url: string) => void;\nexport type SvgSourceValue = {\n readonly svg: string;\n tintColor: string | null;\n};\n/** Wrap raw SVG XML so it can be used as an image source. */\nexport declare const SvgSource: (svg: string) => SvgSourceValue;\n","types/runtime/net.d.ts":"import { Emitter } from \"../core/events\";\ntype SocketEvents = {\n open: () => void;\n message: (data: any) => void;\n close: (code?: number) => void;\n error: () => void;\n};\nexport declare class WebSocket extends Emitter<SocketEvents> {\n private _id;\n constructor(url: string, headers?: Record<string, string>);\n send(message: string | ArrayBuffer): void;\n close(): void;\n private _onMessage;\n}\nexport {};\n","types/runtime/service.d.ts":"export {};\n","types/runtime/share.d.ts":"import type { File, FetchResponse } from \"./fetch\";\nexport declare function share(media: File | FetchResponse, text?: string): void;\n","types/runtime/storage.d.ts":"export declare const localStorage: {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n};\n","types/runtime/touch.d.ts":"export declare class ClickEvent<T = any> {\n readonly type = \"click\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n}\nexport interface TrackHandler {\n onMove?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onEnd?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onCancel?(): void;\n claim?: boolean | \"pan-x\" | \"pan-y\" | \"pan-down\" | \"pan-up\" | \"pan-left\" | \"pan-right\";\n}\nexport declare class TouchStartEvent<T = any> {\n readonly type = \"touchstart\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer (drag/pan gestures). */\n track(handler: TrackHandler): void;\n}\n/** Delivered to a `UIButton` `onLongPress` handler when a finger is held on the button past the\n * host's long-press threshold. Like `TouchStartEvent` it can `track(...)` the rest of the gesture —\n * so the common \"press-and-hold, then drag to move\" flow is one handler: start the drag from here. */\nexport declare class LongPressEvent<T = any> {\n readonly type = \"longpress\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer — drag the element after the hold. */\n track(handler: TrackHandler): void;\n}\n","types/scene/defineScene.d.ts":"import { Aspect, type AspectCtor, type With } from \"../core/Aspect\";\nimport type { ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Scene, type SceneOptions } from \"../gl/Scene\";\nimport { Node } from \"../gl/Node\";\nimport { Mesh } from \"../gl/Mesh\";\nimport { Model } from \"../gl/Model\";\nimport { Light, type SunOptions } from \"../gl/Light\";\nimport { Material, type LitMaterialOptions, type MaterialColorOptions } from \"../gl/Material\";\nimport type { CylinderOptions, PlaneOptions, SphereOptions } from \"../gl/Geometry\";\nexport type MeshDef = {\n kind: \"box\";\n size?: Vec3Like | number;\n} | ({\n kind: \"sphere\";\n} & SphereOptions) | ({\n kind: \"cylinder\";\n} & CylinderOptions) | ({\n kind: \"plane\";\n} & PlaneOptions);\nexport type LightDef = {\n kind: \"sun\";\n} & SunOptions;\nexport type MaterialDef = {\n lit: LitMaterialOptions;\n} | {\n unlit: MaterialColorOptions;\n} | {\n shadow: ColorInput;\n} | Material;\n/** One aspect to attach, created by `use(Ctor, props)`. */\nexport type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = {\n ctor: AspectCtor<A>;\n props?: Partial<A>;\n};\n/** Reference an aspect in a scene file: `aspects: [use(Physics, { motion: 'static' })]`. Props are\n * typechecked against the aspect's fields, exactly like `node.aspect(Ctor, props)`. */\nexport declare const use: <A extends Aspect<any, any>>(ctor: AspectCtor<A>, props?: Partial<A>) => AspectEntry<A>;\n/** A `make(fn, args)` source entry — see {@link make}. */\nexport type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = {\n fn: (args: A) => Node | Promise<Node>;\n args?: A;\n};\n/**\n * A code-created source in a scene file: `tower: { make: make(buildTower, { floors: 5 }), … }`.\n * The factory runs after every scene node exists (so `ref()` args resolve, forward references\n * included) and its returned subtree mounts under the def node — the def's transform stays\n * editor-owned, so moving the node never re-calls the factory. Args must be literal data (same\n * grammar as aspect props); in the editor they edit as fields, and an arg change re-CALLS the\n * factory live — the code is already in the bundle, so no compile happens. Keep factories pure\n * builders: same args → same subtree, no side effects outside the returned nodes.\n */\nexport declare const make: <A extends Record<string, unknown>>(fn: (args: A) => Node | Promise<Node>, args?: A) => MakeEntry<A>;\n/**\n * Reference another scene node by name in an aspect's props:\n * `use(Road, { from: ref('pointA'), to: ref('pointB') })`. Resolves to the live Node when aspects\n * attach — after EVERY node of the scene exists, so forward references work. An unknown name\n * resolves to `null` (type your aspect field `Node | null`). Scene files only — hand-written code\n * passes nodes directly: `node.aspect(Road, { from: nodes.pointA })`.\n */\nexport declare const ref: <T extends Node = Node>(name: string) => T;\n/** Transform overrides for one INTERNAL node of a GLB model or a prefab instance\n * (`overrides` on a model/prefab node, keyed by part path). */\nexport type ModelOverrideDef = {\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n};\n/** The `camera: {}` source block — reserved for projection settings (fov, …) later. */\nexport type CameraNodeDef = Record<string, never>;\nexport type SceneNodeDef = {\n mesh?: MeshDef;\n /** GLB url — `asset('./hero.glb')`. */\n model?: string;\n light?: LightDef;\n /** The scene camera as a NODE: in play mode `scene.camera` follows this node's world transform\n * every frame (so movement aspects on it are camera flythroughs); the editor shows a frustum\n * marker and refuses to delete the last camera node. The first camera node in file order wins;\n * cameras inside prefabs are ignored (like a prefab's `camera:` block). */\n camera?: CameraNodeDef;\n /** A code-built subtree — `make(factoryFn, { ...literal args })`. */\n make?: MakeEntry<any>;\n /** Another scene file used as a reusable composition — the imported handle:\n * `import streetlamp from './streetlamp.scene'` … `lamp: { prefab: streetlamp }`. Its nodes\n * instantiate under this node per instance (env/camera are the instancing file's business and\n * are ignored); `ref()`s inside the prefab resolve file-locally, per instance. */\n prefab?: SceneHandle<any>;\n /** Material for a `mesh` source. */\n material?: MaterialDef;\n /** Model/prefab sources: transform overrides for the INTERNAL nodes, keyed by part path\n * (see the part-path grammar above `modelPartRows`). Unresolved paths are ignored. */\n overrides?: Record<string, ModelOverrideDef>;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n /** Editor-only: the transform gizmo won't target this node (fields still edit). No runtime effect. */\n locked?: boolean;\n castShadows?: boolean;\n receiveShadows?: boolean;\n aspects?: readonly AspectEntry<any>[];\n children?: Record<string, SceneNodeDef>;\n};\nexport type SceneCameraDef = {\n position?: Vec3Like;\n /** Point the camera looks at. */\n target?: Vec3Like;\n};\nexport type SceneDef = {\n env?: SceneOptions;\n camera?: SceneCameraDef;\n nodes?: Record<string, SceneNodeDef>;\n};\ntype SourceNodeOf<N extends SceneNodeDef> = N extends {\n model: string;\n} ? Model : N extends {\n mesh: MeshDef;\n} ? Mesh : N extends {\n light: LightDef;\n} ? Light : Node;\ntype AspectsOf<N extends SceneNodeDef> = N extends {\n aspects: readonly AspectEntry<infer A>[];\n} ? A : never;\ntype NodeOf<N extends SceneNodeDef> = [\n AspectsOf<N>\n] extends [never] ? SourceNodeOf<N> : With<SourceNodeOf<N>, AspectsOf<N>>;\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\ntype ChildMapsOf<T extends Record<string, SceneNodeDef>> = {\n [K in keyof T]: T[K] extends {\n children: infer C extends Record<string, SceneNodeDef>;\n } ? NodesOf<C> : never;\n}[keyof T];\ntype NodesOf<T extends Record<string, SceneNodeDef>> = {\n [K in keyof T]: NodeOf<T[K]>;\n} & ([ChildMapsOf<T>] extends [never] ? unknown : UnionToIntersection<ChildMapsOf<T>>);\nexport type SceneNodes<D extends SceneDef> = D[\"nodes\"] extends Record<string, SceneNodeDef> ? NodesOf<D[\"nodes\"]> : Record<string, Node>;\nexport type LoadedScene<D extends SceneDef> = {\n scene: Scene;\n nodes: SceneNodes<D>;\n};\n/** One INTERNAL node of a loaded GLB (editor introspection). */\nexport type ModelPartRow = {\n path: string;\n name: string;\n depth: number;\n node: Node;\n};\n/** Flatten a model's (or prefab instance's) internal hierarchy to rows (depth-first, the root\n * excluded). `__generated` containers are derived output, not addressable parts — skipped. */\nexport declare const modelPartRows: (root: Node) => ModelPartRow[];\nexport declare class SceneHandle<D extends SceneDef = SceneDef> {\n readonly def: D;\n private _loading?;\n constructor(def: D);\n /** Instantiate the scene (idempotent — subsequent calls return the same instance). Does not open. */\n load(): Promise<LoadedScene<D>>;\n /** Load and make active. */\n open(): Promise<LoadedScene<D>>;\n}\n/**\n * Define a scene as data — the default export of a `.scene.ts` file. Returns a typed handle:\n * `const { scene, nodes } = await handle.open()` gives `nodes.<name>` typed by its source block\n * (Mesh / Model / Light / Node) with its `use(...)`d aspects attached.\n */\nexport declare const defineScene: <const D extends SceneDef>(def: D) => SceneHandle<D>;\nexport {};\n","types/scene/editorPlugins.d.ts":"import type { InspectorUI } from \"../core/InspectorUI\";\n/** A geometry hit under the viewport pointer, handed to tools. Physics builds raycast the scene's\n * meshes (precise); otherwise (and on misses) the hit falls back to the ground plane (y = 0). */\nexport type EditorRayHit = {\n point: [number, number, number];\n normal: [number, number, number];\n /** The scene-file node the hit belongs to — null for ground-plane fallback hits. */\n node: string | null;\n};\n/**\n * The editor scripting API handed to windows and tools. Doc-op methods write the scene DOCUMENT\n * through the editor's normal commit path (undo, file, live patching all included); they return\n * false / no-op when the document can't take the edit (duplicate name, unknown node).\n */\nexport type EditorApi = {\n /** The currently selected node name (or `model::part` key), null when nothing is selected. */\n readonly selection: string | null;\n select(name: string | null): void;\n /** The scene document's nodes (name + source kind: mesh / model / light / group). */\n nodes(): {\n name: string;\n kind: string;\n }[];\n /** First unused \"base\", \"base2\", \"base3\", … node name. */\n uniqueName(base: string): string;\n /** Add a node from plain def data (scene-file grammar; a string `model` value means an asset\n * path). One undo step unless grouped by `transact`. */\n addNode(name: string, def: Record<string, unknown>): boolean;\n /** Write one def prop (transforms apply live; anything else patches/re-runs the node). */\n setProp(name: string, key: string, value: unknown): boolean;\n removeNode(name: string): void;\n /** Duplicate a node; returns the copy's name (null when it can't). */\n duplicate(name: string): string | null;\n /** Raycast the scene under a viewport pixel (same hit rules as tool clicks). */\n raycast(screenX: number, screenY: number): EditorRayHit | null;\n /** Group every doc edit inside `fn` into ONE undo step. */\n transact(fn: () => void): void;\n};\nexport type EditorWindowFn = (ui: InspectorUI, editor: EditorApi) => void;\nexport type EditorToolHooks = {\n /** CSS cursor for the viewport while this tool is active (default \"crosshair\"). */\n cursor?: string;\n /** A short glyph (one character / emoji) for the tool's toolbar button — tools without one all\n * share the generic wand icon, so any editor with two or more tools should set it. */\n icon?: string;\n /** A viewport click while the tool is active — `hit` is the raycast result under the pointer.\n * Selection clicks and the transform gizmo are suspended while a tool is active. */\n onViewportClick?(hit: EditorRayHit, editor: EditorApi): void;\n};\n/** Register an editor panel — a collapsible overlay docked over the viewport (the inspector rail\n * stays selection-scoped). A window that emits `ui.toolButton` for a tool becomes that tool's\n * settings panel: activating the tool expands and highlights it. `render` re-runs immediate-mode\n * on every interaction — same protocol as `static inspector` cards. */\nexport declare const registerEditorWindow: (title: string, render: EditorWindowFn) => void;\n/** Register a viewport tool — a toolbar entry beside move/rotate/scale (activate it there or via\n * `ui.toolButton(label, name)`). While active, viewport clicks arrive as raycast hits. */\nexport declare const registerEditorTool: (name: string, hooks: EditorToolHooks) => void;\n","types/ui/fonts.d.ts":"type FontOptions = {\n weight?: number;\n style?: \"normal\" | \"italic\";\n};\nexport declare function registerFont(fontFamily: string, url: string, options?: FontOptions): Promise<void>;\nexport {};\n","types/ui/NativeView.d.ts":"import { type PresentOptions } from \"./presentable\";\nimport { type AnimateStyle, type BaseStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style } from \"./UINode\";\nexport type UINativeViewStyle = ElementStyle & DrawableStyle;\nexport interface NativeView {\n readonly type: \"native\";\n /** The registered view kind this instance resolves to (the `registerView` name). */\n readonly viewName: string;\n /** Creation params, passed to the host factory (JSON-serializable). */\n readonly params: any;\n style: Style<this, UINativeViewStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Show fullscreen as the current destination (see Presentable). */\n open(options?: PresentOptions): void;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Invoke a method on the native view (`map.call(\"setCenter\", [lng, lat])`). Args and the\n * result are JSON-serialized. Rejects if the host has no such view/method. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the native view emits (`map.on(\"markerTap\", cb)`). */\n on(event: string, callback: (data?: any) => void): this;\n off(event: string, callback: (data?: any) => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\n/**\n * Create an instance of a host-registered platform view. `NativeView.isSupported(name)` reports\n * whether this host registered a factory for it. Style via the chained `.style()`.\n */\nexport declare const NativeView: {\n (name: string, params?: object): NativeView;\n /** Whether this host registered a `registerView` factory under `name`. */\n isSupported(name: string): boolean;\n};\n","types/ui/presentable.d.ts":"/** Built-in transition catalog. `push`/`pop` are the stacked-navigation pair (slide + parallax +\n * dim + edge shadow); the rest are simple two-view moves. */\nexport type TransitionName = \"push\" | \"pop\" | \"slide-from-left\" | \"slide-from-right\" | \"slide-from-top\" | \"slide-from-bottom\" | \"zoom\" | \"zoom-in\" | \"zoom-out\" | \"fade\" | \"none\";\n/** Start/end pose of one side of a custom transition. `x`/`y` are logical px, or a percentage of\n * the destination's size (e.g. `\"100%\"` = one full width to the right). */\nexport type TransitionTransform = {\n x?: number | `${number}%`;\n y?: number | `${number}%`;\n scale?: number;\n opacity?: number;\n};\n/**\n * A custom transition: declarative poses for the incoming/outgoing destination, played natively.\n * Serializes onto each platform's existing transition machinery — there is no per-frame JS.\n * Fields omitted keep the identity pose. Interactive back-swipe stays system-native (push/pop\n * only); a spec applies to non-interactive transitions.\n */\nexport interface TransitionSpec {\n /** Duration in ms (default 300). */\n duration?: number;\n /** cubic-bezier control points (default ease-out). */\n easing?: [number, number, number, number];\n /** The entering destination animates FROM this pose to identity. */\n incoming?: {\n from?: TransitionTransform;\n };\n /** The leaving destination animates from identity TO this pose. */\n outgoing?: {\n to?: TransitionTransform;\n };\n /** Scrim alpha (0..1) painted over whichever destination is underneath. */\n dim?: number;\n /** Which side stacks on top during the animation (default \"incoming\"). On Android, transitions\n * involving a scene always animate the screen side on top — the scene view itself never moves. */\n onTop?: \"incoming\" | \"outgoing\";\n}\nexport type Transition = TransitionName | TransitionSpec;\nexport type PresentOptions = {\n /** Transition to play while this destination replaces the current one (default \"none\" for a\n * direct open(); the Router applies its own defaults — push/pop, and the theme's\n * `replaceTransition` for replace). */\n transition?: Transition;\n};\n/**\n * Anything that can be shown as the app's current destination: a `UIScreen`, a `Scene` /\n * `ARScene`, a `Scene2D`, a `NativeView`, or a `UIVideo`. One Presentable is visible at a time;\n * open it directly (`p.open()` — replaces the current destination, suspending an active Router\n * until `Router.restore()`) or navigate with `Router.push/replace/pop`.\n *\n * `onOpen`/`onClose` are the presentation lifecycle (fired when the destination becomes / stops\n * being the visible one — including router pushes covering it and pops revealing it).\n */\nexport interface Presentable {\n open(options?: PresentOptions): void | this | Promise<void>;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n}\n/** Runtime companion of the `Presentable` interface (declaration merging): the navigation\n * state that isn't tied to the Router. */\nexport declare const Presentable: Readonly<{\n /** The destination visible right now (a `UIScreen`, `Scene`, `Scene2D`, `NativeView` or\n * `UIVideo`), or `null` before the first open. Distinct from `Router.current` — that is the\n * top of the router stack, which stays meaningful while the router is suspended by a direct\n * `open()`; this is what is actually on screen. `UIWidget.show()` attaches to it. */\n readonly current: Presentable | null;\n}>;\n","types/ui/router.d.ts":"import { Presentable, type Transition } from \"./presentable\";\ntype RouterOptions = {\n showDefaultBackButton?: boolean;\n};\ntype NavigateOptions = {\n /** Transition to play. Defaults: `\"push\"` for push, `\"pop\"` for pop; replace follows the\n * theme's `replaceTransition` (`\"none\"` out of the box). */\n transition?: Transition;\n};\ntype Router = {\n get current(): Presentable;\n init(homePage: Presentable, opts?: RouterOptions): void;\n /** Push a destination onto the stack — a `UIScreen`, a `Scene`, a `Scene2D`, a `NativeView`,\n * or a `UIVideo`. The back gesture/button pops it. Destinations with async preparation\n * (`ARScene`: camera permission + warm render) return a Promise — the current page stays\n * visible until they're ready, and a rejection (permission denied / superseded) leaves the\n * stack untouched. */\n push(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n replace(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n pop(to?: number, opts?: NavigateOptions): void;\n hide(): void;\n restore(): void;\n addEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n removeEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n};\nexport declare const Router: Router;\nexport {};\n","types/ui/theme.d.ts":"import type { Transition } from \"./presentable\";\nexport type ThemeValues = Record<string, string | number | null>;\nexport type ThemeAccessors<T> = {\n readonly [K in keyof T]: K extends string ? `var(--${K})` : never;\n};\nexport declare const theme: (<T extends Record<string, string | number | Transition | null>>(values: T & { [K in Exclude<keyof T, \"replaceTransition\">]: string | number | null; }) => ThemeAccessors<Omit<T, \"replaceTransition\">>) & {\n /** The app accent color. Kit components will read it via `var(--primaryColor, <fallback>)`. */\n readonly primaryColor: \"var(--primaryColor)\";\n /** Secondary / inactive content color for kit components. */\n readonly mutedColor: \"var(--mutedColor)\";\n /** DEFAULT text color — text without an explicit `color` follows it (hosts source their\n * default from the theme; unset = the host default, white on dark screens). Set it once for\n * a light theme instead of `color: \"black\"` on every label. */\n readonly color: \"var(--color)\";\n /** DEFAULT text font — text without an explicit `fontFamily` follows it. */\n readonly fontFamily: \"var(--fontFamily)\";\n /** Raw comfort knobs (logical px). The bare `comfort-top` style TOKEN applies the safe-area\n * formula — these accessors read the knob value itself, for manual composition. */\n readonly \"comfort-top\": \"var(--comfort-top)\";\n readonly \"comfort-bottom\": \"var(--comfort-bottom)\";\n readonly \"comfort-left\": \"var(--comfort-left)\";\n readonly \"comfort-right\": \"var(--comfort-right)\";\n};\n","types/ui/UI.d.ts":"export { UIButton, type UIButtonStyle } from './UIButton';\nexport { UIScreen, type UIScreenStyle } from './UIScreen';\nexport { UISpacer, type UISpacerStyle } from './UISpacer';\nexport { UIText, type UITextStyle } from './UIText';\nexport { registerFont } from './fonts';\nexport { UIImage, type UIImageStyle } from './UIImage';\nexport { UIVideo, type UIVideoStyle } from './UIVideo';\nexport { UIInput, UITextArea, type UIInputStyle } from './UIInput';\nexport { UIWidget, type UIWidgetStyle } from './UIWidget';\nexport { UIModal, type UIModalStyle } from './UIModal';\nexport { UIBottomSheet, type UIBottomSheetStyle } from './UIBottomSheet';\nexport { UIPopover, type UIPopoverStyle, type UIPopoverAnchor } from './UIPopover';\nexport { UIRow, UIColumn, UIBox, type UIContainerStyle } from './UIContainer';\nexport { UIScrollable, type UIScrollableStyle } from './UIScrollable';\nexport { UIPager, type UIPagerStyle } from './UIPager';\nexport { UIVirtualizedList } from './UIVirtualizedList';\nexport { Router } from './router';\nexport { NativeView, type UINativeViewStyle } from './NativeView';\nexport { Presentable } from './presentable';\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from './presentable';\nexport { __uiMap } from './UINode';\n","types/ui/UIBottomSheet.d.ts":"import { ModalElement, type UIModalStyle } from \"./UIModal\";\nimport type { UIWidget } from \"./UIWidget\";\nimport type { ChildrenFn, UINodeChild } from \"./UINode\";\nexport type UIBottomSheetStyle = UIModalStyle;\n/**\n * A bottom sheet: a `UIWidget` pinned to the bottom edge. By default it is **content-sized** —\n * as tall as what's inside (capped at the screen), one position, drag down to dismiss (the\n * action-sheet shape). Call `detents()` for the multi-position map-app model instead: snap\n * positions the user drags between on native hosts. Ships as a widget node on the wire (no new\n * node type — docs/bottom-sheet-plan.md): hosts without sheet support show a static bottom panel.\n *\n * With detents, content lays out at the HIGHEST detent's size; lower detents show the top\n * slice. The scrim, `onOpen`/`onClose`, back-button and scrim-tap dismissal all come from the\n * modal machinery.\n *\n * ```ts\n * const actions = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [rows]) // content-sized\n *\n * const mapSheet = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [results])\n * .detents([0.3, 0.6, 1])\n * .onDetentChange(i => map.setPadding(...))\n * ```\n */\nexport interface UIBottomSheet extends UIWidget {\n /** Snap positions as fractions of screen height, ascending. Also sizes the sheet: its box is\n * the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet\n * is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */\n detents(list: number[]): this;\n /** Snap to a detent (animated). Clamped to the detents range; fires `onDetentChange`. */\n setDetent(index: number): void;\n /** Current detent index. */\n readonly detent: number;\n /** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */\n onDetentChange(callback: (index: number) => void): this;\n /** Mount and slide in to the current detent. No-op while already open. */\n show(): void;\n /** Slide out, fade the scrim, then unmount. No-op while closed. */\n hide(): void;\n /** True from `show()` until `hide()` starts. */\n readonly isOpen: boolean;\n /** Called when `show()` mounts the sheet. */\n onOpen(callback: () => void): this;\n /** Called when the sheet starts closing — scrim tap, back button, drag-dismiss, or `hide()`. */\n onClose(callback: () => void): this;\n /** `dismissible(false)`: scrim taps, the back button and dragging below the lowest detent no\n * longer close the sheet (a drag collapses to the lowest detent instead). Default `true`. */\n dismissible(enabled: boolean): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n}\nexport declare class BottomSheetElement extends ModalElement {\n _detents: number[];\n _detent: number;\n /** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the\n * settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.\n * `-1` = dragged below the lowest detent while dismissible. */\n readonly dtl: any[];\n readonly _detentListeners: ((index: number) => void)[];\n constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn);\n detents(list: number[]): this;\n get detent(): number;\n setDetent(index: number): void;\n onDetentChange(callback: (index: number) => void): this;\n show(): void;\n hide(): void;\n dismissible(enabled: boolean): this;\n}\nexport declare function UIBottomSheet(): UIBottomSheet;\nexport declare function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;\nexport declare function UIBottomSheet(style: UIBottomSheetStyle): UIBottomSheet;\nexport declare function UIBottomSheet(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn): UIBottomSheet;\n","types/ui/UIButton.d.ts":"import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType } from \"../runtime/touch\";\nimport { type ElementStyle, type ContainerStyle, type Classes, type Style, type DrawableStyle, type UINodeChild, type ChildrenFn, type OnLayoutCallback, type BoundingClientRect, type BaseStyle, type AnimateStyle, type Color } from \"./UINode\";\nexport type UIButtonStyle = ElementStyle & DrawableStyle & ContainerStyle & {\n rippleColor?: Color | \"default\";\n};\nexport interface UIButton {\n readonly type: \"button\";\n style: Style<this, UIButtonStyle & {\n onPressed?: UIButtonStyle & {\n duration?: number;\n };\n }>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n onClick(callback: (ev: ClickEventType<UIButton>) => void): this;\n onTouchStart(callback: (ev: TouchStartEventType<UIButton>) => void): this;\n /** Fired when a finger is held on the button past the long-press threshold. The event can\n * `ev.track(...)` the rest of the gesture (like `onTouchStart`), so a hold can flow straight into\n * dragging the element. A handled long-press suppresses the click that would follow the release. */\n onLongPress(callback: (ev: LongPressEventType<UIButton>) => void): this;\n isPressed(): boolean;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIButton(): UIButton;\nexport declare function UIButton(children: UINodeChild[] | ChildrenFn): UIButton;\nexport declare function UIButton(style: UIButtonStyle): UIButton;\nexport declare function UIButton(style: UIButtonStyle, children: UINodeChild[]): UIButton;\n","types/ui/UIContainer.d.ts":"import { type AnimateStyle, type ChildrenFn, type ContainerStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type UINodeChild } from \"./UINode\";\nexport type UIContainerStyle = ElementStyle & DrawableStyle & ContainerStyle;\nexport interface UIColumn {\n readonly type: \"column\";\n style: Style<this, UIContainerStyle>;\n animateTo: AnimateStyle<this, UIContainerStyle>;\n animateFrom: AnimateStyle<this, UIContainerStyle>;\n append(...nodes: UINodeChild[]): UIColumn;\n insert(index: number, ...nodes: UINodeChild[]): UIColumn;\n remove(...nodes: UINodeChild[]): UIColumn;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIColumn(): UIColumn;\nexport declare function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn;\nexport declare function UIColumn(style: UIContainerStyle): UIColumn;\nexport declare function UIColumn(style: UIContainerStyle, children: UINodeChild[]): UIColumn;\nexport interface UIRow {\n readonly type: \"row\";\n style: Style<this, UIContainerStyle>;\n animateTo: AnimateStyle<this, UIContainerStyle>;\n animateFrom: AnimateStyle<this, UIContainerStyle>;\n append(...nodes: UINodeChild[]): UIRow;\n insert(index: number, ...nodes: UINodeChild[]): UIRow;\n remove(...nodes: UINodeChild[]): UIRow;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIRow(): UIRow;\nexport declare function UIRow(children: UINodeChild[] | ChildrenFn): UIRow;\nexport declare function UIRow(style: UIContainerStyle): UIRow;\nexport declare function UIRow(style: UIContainerStyle, children: UINodeChild[]): UIRow;\nexport interface UIBox {\n readonly type: \"box\";\n style: Style<this, UIContainerStyle>;\n animateTo: AnimateStyle<this, UIContainerStyle>;\n animateFrom: AnimateStyle<this, UIContainerStyle>;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIBox(): UIBox;\nexport declare function UIBox(children: UINodeChild[] | ChildrenFn): UIBox;\nexport declare function UIBox(style: UIContainerStyle): UIBox;\nexport declare function UIBox(style: UIContainerStyle, children: UINodeChild[]): UIBox;\n","types/ui/UIImage.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue as SvgSource } from \"../runtime/misc\";\nimport type { File } from \"../runtime/fetch\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { type AnimateStyle, type Color, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style } from \"./UINode\";\nexport type UIImageStyle = ElementStyle & {\n borderRadius?: number;\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n tintColor?: Color;\n};\n/** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture — see\n * docs/canvas-contract.md (\"Pending\"). */\nexport type CanvasImageSource = {\n canvasSurface: number;\n};\n/** Accepted image sources. A Canvas is baked to a surface marker on assign. */\nexport type ImageSource = string | FetchResponse | File | SvgSource | Canvas;\n/** The stored/resolved image source (a Canvas is resolved to a surface marker). */\nexport type ResolvedImageSource = string | FetchResponse | File | SvgSource | CanvasImageSource;\nexport interface UIImage {\n readonly type: \"image\";\n get src(): ResolvedImageSource;\n set src(value: ImageSource);\n style: Style<this, UIImageStyle>;\n animateTo: AnimateStyle<this, UIImageStyle>;\n animateFrom: AnimateStyle<this, UIImageStyle>;\n setSourceRect(x: number, y: number, w: number, h: number): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UIImage(src: ImageSource): UIImage;\nexport declare function UIImage(style: UIImageStyle, src: ImageSource): UIImage;\n","types/ui/UIInput.d.ts":"import { type ElementStyle, type DrawableStyle, type Classes, type Style, type TextStyle, type Color, type OnLayoutCallback, type BoundingClientRect, type BaseStyle, type AnimateStyle } from \"./UINode\";\ntype InputStyle = {\n placeholder?: string;\n placeholderColor?: Color;\n /**\n * Keyboard hint, NOT a validator — `number` does not block pasted letters; validate in your own\n * onChange. The phone-pad value is `phone` (LeCodes has no `tel`).\n *\n * `date` / `time` are PICKER kinds, not keyboards: the host opens its native picker in the\n * keyboard slot (iOS wheels / browser calendar) and free typing is disabled. `value` is always\n * canonical — `YYYY-MM-DD` for `date`, `HH:MM` (24h) for `time` — while the field displays a\n * localized string; set/compare values in the canonical form only.\n */\n type?: \"text\" | \"password\" | \"search\" | \"phone\" | \"email\" | \"number\" | \"decimal\" | \"url\" | \"date\" | \"time\";\n /**\n * What the layout does while the keyboard is up (decided by the FOCUSED input). `true` (default):\n * the layout viewport shrinks to the area above the keyboard — one relayout. `false`: the keyboard\n * overlays the UI with NO layout recalculation — for chat composers that manage their own inset\n * (pair with `app.keyboardHeight` / the app `\"keyboard\"` event) and full-screen canvases where a\n * reflow is worse than overlap.\n */\n keyboardShrink?: boolean;\n /**\n * Whether a tap on a non-interactive area dismisses the keyboard while THIS input is focused\n * (like `keyboardShrink`, the policy of the focused input). `true` (default): tapping dead\n * space blurs — but a tap on a button or another input NEVER dismisses; the control acts and\n * focus stays. `false`: taps never dismiss — the chat-composer policy. `blur()`, the return\n * key (per `enterKey`), and the platform's own gestures (iOS drag-down over the keyboard)\n * still work in both modes. Scrolling never dismisses the keyboard on any setting.\n */\n keyboardDismiss?: boolean;\n /** Hard cap on the text length — enforced by the host while typing/pasting. */\n maxLength?: number;\n /** Auto-capitalization hint; omitted = platform default. */\n autocapitalize?: \"none\" | \"words\" | \"sentences\" | \"characters\";\n /** Enable/disable the platform autocorrection & suggestions; omitted = platform default. */\n autocorrect?: boolean;\n};\nexport type UIInputStyle = ElementStyle & DrawableStyle & TextStyle & InputStyle;\n/** UIInput-only (a UITextArea's Enter is a newline, period): the return-key label. */\ntype SubmitStyle = {\n /**\n * Return-key label. On submit the keyboard dismisses UNLESS `enterKey` is `\"next\"` — then the\n * app is expected to call `otherInput.focus()` from `onSubmit`, so the keyboard never blinks.\n */\n enterKey?: \"done\" | \"go\" | \"next\" | \"search\" | \"send\";\n};\nexport interface UIInput {\n readonly type: \"input\";\n value: string;\n style: Style<this, UIInputStyle & SubmitStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n }>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n onChange(callback: (value: string) => void): UIInput;\n onFocus(callback: () => void): UIInput;\n onBlur(callback: () => void): UIInput;\n /** The keyboard's return key was pressed. `value` is the current text. See `enterKey`. */\n onSubmit(callback: (value: string) => void): UIInput;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Focus the input (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this input held it). */\n blur(): void;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport interface UITextArea {\n readonly type: \"textarea\";\n value: string;\n style: Style<this, UIInputStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n }>;\n onChange(callback: (value: string) => void): UITextArea;\n onFocus(callback: () => void): UITextArea;\n onBlur(callback: () => void): UITextArea;\n /** Focus the text area (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this text area held it). */\n blur(): void;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UIInput(): UIInput;\nexport declare function UIInput(style: UIInputStyle): UIInput;\n/**\n * Multi-line text field. Enter is a newline (submit lives on UIInput / your own button).\n *\n * Auto-grow: with no explicit `height` the field measures its own content and grows line by\n * line — clamp the range with `minHeight` / `maxHeight` (past `maxHeight` the text scrolls\n * inside). A fixed `height` opts out and scrolls internally from the start. Chat composers are\n * the canonical use: a bare textarea in a padded pill, `maxHeight` at ~5 lines.\n */\nexport declare function UITextArea(): UITextArea;\nexport declare function UITextArea(style: UIInputStyle): UITextArea;\nexport {};\n","types/ui/UIModal.d.ts":"import { type UIWidget, type UIWidgetStyle, WidgetElement } from \"./UIWidget\";\nimport type { BaseStyle, ChildrenFn, Color, DrawableStyle, UINodeChild } from \"./UINode\";\nexport type UIModalStyle = UIWidgetStyle;\n/**\n * The modal's hidden pose: `show()` animates from it, `hide()` animates to it. `duration` (ms)\n * applies to both directions.\n */\nexport type UIModalTransition = DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n duration?: number;\n};\n/**\n * A dialog: a `UIWidget` with the modal boilerplate built in. Comes with a scrim\n * (`overlayColor: \"rgba(0, 0, 0, 0.5)\"` unless overridden), animates on `show()`/`hide()`\n * (a 200 ms fade by default — swap the pose via `transition()`; the exit plays with\n * `commit: false`, so the style is intact for the next show), and closes itself on a scrim tap\n * or the Android back button (disable via `dismissible(false)`). Everything else is a plain\n * widget — same styling, children, touch and `attachTo()` surface; create it **once** at module\n * scope and reuse it.\n */\nexport interface UIModal extends UIWidget {\n /** Mount as an overlay and play the entrance transition. No-op while already open. */\n show(): void;\n /** Play the exit transition, then unmount. No-op while closed or already closing. */\n hide(): void;\n /** True from `show()` until `hide()` starts (already false during the exit animation). */\n readonly isOpen: boolean;\n /**\n * Replace the show/hide animation. `hidden` is the off-screen pose — `show()` animates from\n * it, `hide()` animates to it. Default `{ opacity: 0, duration: 200 }` (a fade); the pose\n * replaces it wholesale, so a slide without a fade is just the slide. The scrim keeps its own\n * fade unless the pose sets `overlayColor` itself.\n *\n * ```ts\n * sheet.transition({ transform: \"translateY(480px)\", duration: 250 }) // bottom sheet\n * ```\n */\n transition(hidden: UIModalTransition): this;\n /** Called when `show()` mounts the modal. */\n onOpen(callback: () => void): this;\n /** Called when the modal starts closing — scrim tap, back button, or a `hide()` call. */\n onClose(callback: () => void): this;\n /** `dismissible(false)` keeps scrim taps and the back button from closing the modal\n * (forced-choice dialogs). Default `true`. */\n dismissible(enabled: boolean): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n}\nexport declare class ModalElement extends WidgetElement {\n _open: boolean;\n _dismissible: boolean;\n _transition: UIModalTransition;\n _closeTimer?: ReturnType<typeof setTimeout>;\n readonly _openListeners: (() => void)[];\n readonly _closeListeners: (() => void)[];\n constructor(style: UIModalStyle, children: UINodeChild[] | ChildrenFn);\n private _pose;\n private get _duration();\n transition(hidden: UIModalTransition): this;\n show(): void;\n hide(): void;\n get isOpen(): boolean;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n dismissible(enabled: boolean): this;\n}\nexport declare function UIModal(): UIModal;\nexport declare function UIModal(children: UINodeChild[] | ChildrenFn): UIModal;\nexport declare function UIModal(style: UIModalStyle): UIModal;\nexport declare function UIModal(style: UIModalStyle, children: UINodeChild[] | ChildrenFn): UIModal;\n","types/ui/UINode.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nexport interface UINode {\n readonly type: string;\n /** Author-given semantic name (a stable selector for tests + AI review feedback). */\n readonly name?: string;\n style: Style<this, any>;\n /** Style-class proxy — read/set/toggle/bind the `$`-classes declared in `.style()`. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport type UINodeChild = UINode | null | undefined | false;\nexport type Color = number | string | null;\nexport type BaseStyle = {\n opacity?: number | `${number}`;\n transform?: string | null;\n backgroundColor?: Color | null;\n bgColor?: Color | null;\n overflow?: \"visible\" | \"hidden\";\n boxSizing?: \"border-box\" | \"content-box\";\n /**\n * Author-given semantic name — a stable selector for tests and for marking elements in the AI\n * code-review feedback loop. NOT a style: it's extracted at construction (never sent to the layout\n * engine) and surfaced on the node + in the renderer's serialized output. Available on every element.\n */\n name?: string;\n};\nexport type DrawableStyle = {\n backgroundImage?: FetchResponse | File | string | null;\n bgGradient?: string;\n backgroundGradient?: string;\n bgImage?: FetchResponse | File | string | null;\n backgroundSize?: \"cover\" | \"contain\" | \"tile\";\n bgSize?: \"cover\" | \"contain\" | \"tile\";\n border?: string | number | null;\n borderWidth?: number;\n borderColor?: Color;\n borderLeft?: string | number | null;\n borderLeftWidth?: number;\n borderLeftColor?: Color;\n borderTop?: string | number | null;\n borderTopWidth?: number;\n borderTopColor?: Color;\n borderRight?: string | number | null;\n borderRightWidth?: number;\n borderRightColor?: Color;\n borderBottom?: string | number | null;\n borderBottomWidth?: number;\n borderBottomColor?: Color;\n borderRadius?: UIValue | string;\n borderTopLeftRadius?: UIValue;\n borderTopRightRadius?: UIValue;\n borderBottomLeftRadius?: UIValue;\n borderBottomRightRadius?: UIValue;\n pointerEvents?: \"all\" | \"none\";\n};\nexport type ContainerStyle = {\n flexDirection?: \"row\" | \"column\";\n justifyContent?: \"flex-start\" | \"center\" | \"flex-end\" | \"space-between\" | \"space-evenly\";\n alignItems?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n gap?: UIValue;\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n};\ntype UIValue = number | `${number}px` | `${number}vw` | `${number}vh` | `${number}vmin` | `${number}vmax` | `${number}em` | `calc(${string})` | `min(${string})` | `max(${string})` | `${string}%` | `clamp(${string})` | `var(--${string})`;\nexport type PaddingStyle = {\n paddingLeft?: UIValue | \"safe-left\" | \"comfort-left\";\n paddingTop?: UIValue | \"safe-top\" | \"comfort-top\";\n paddingRight?: UIValue | \"safe-right\" | \"comfort-right\";\n paddingBottom?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n padding?: UIValue | \"safe-all\" | \"comfort-all\";\n paddingHorizontal?: UIValue | \"comfort-x\";\n paddingVertical?: UIValue | \"comfort-y\";\n pl?: UIValue | \"safe-left\" | \"comfort-left\";\n pt?: UIValue | \"safe-top\" | \"comfort-top\";\n pr?: UIValue | \"safe-right\" | \"comfort-right\";\n pb?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n p?: UIValue | \"safe-all\" | \"comfort-all\";\n px?: UIValue | \"comfort-x\";\n py?: UIValue | \"comfort-y\";\n};\nexport type MarginStyle = {\n marginLeft?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n marginTop?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n marginRight?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n marginBottom?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n margin?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n marginHorizontal?: UIValue | \"auto\" | \"comfort-x\";\n marginVertical?: UIValue | \"auto\" | \"comfort-y\";\n ml?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n mt?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n mr?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n mb?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n m?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n mx?: UIValue | \"auto\" | \"comfort-x\";\n my?: UIValue | \"auto\" | \"comfort-y\";\n};\nexport type PositionStyle = {\n top?: UIValue | `${number}%` | 'safe-top' | 'comfort-top';\n left?: UIValue | `${number}%` | 'safe-left' | 'comfort-left';\n bottom?: UIValue | `${number}%` | 'safe-bottom' | 'comfort-bottom';\n right?: UIValue | `${number}%` | 'safe-right' | 'comfort-right';\n /** Shorthand for all four edges at one value. A longhand (`top`, `left`, …) overrides it. */\n inset?: UIValue | `${number}%` | \"auto\";\n width?: UIValue | `${number}%` | \"auto\";\n height?: UIValue | `${number}%` | \"auto\";\n maxWidth?: UIValue | `${number}%` | \"auto\";\n maxHeight?: UIValue | `${number}%` | \"auto\";\n minWidth?: UIValue | `${number}%` | \"auto\";\n minHeight?: UIValue | `${number}%` | \"auto\";\n};\nexport type ElementStyle = PaddingStyle & MarginStyle & BaseStyle & PositionStyle & {\n position?: \"absolute\" | \"static\" | \"relative\";\n aspectRatio?: number;\n flex?: number | string;\n flexGrow?: number;\n flexShrink?: number;\n flexBase?: UIValue | `${number}%` | \"auto\";\n alignSelf?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n display?: \"none\" | \"flex\";\n};\nexport type TextStyle = {\n textAlign?: \"start\" | \"center\" | \"end\" | \"left\" | \"right\";\n fontFamily?: string;\n fontSize?: UIValue;\n lineHeight?: UIValue | \"normal\";\n fontWeight?: number | `${number}` | \"normal\" | \"bold\";\n fontStyle?: \"normal\" | \"italic\";\n color?: Color;\n textDecoration?: \"underline\" | \"line-through\" | \"none\";\n letterSpacing?: UIValue;\n /** Cap the text at N lines; the box is measured to the clamped height. 0 / omitted = unbounded. */\n lineClamp?: number;\n /** How a clamped line ends. Only meaningful together with `lineClamp`. Default \"ellipsis\". */\n textOverflow?: \"ellipsis\" | \"clip\";\n};\nexport type Reactive<T> = {\n [K in keyof T]: NonNullable<T[K]> extends object ? T[K] : T[K] | (() => T[K]);\n};\nexport type ClassStyles<T> = {\n [key: `$${string}`]: T & {\n duration?: number;\n delay?: number;\n };\n};\n/** Value accepted by a `el.class` write: a boolean sets the class, a `() => boolean` binds it —\n * the class then tracks the signals the function reads (re-evaluated on change). Reads through\n * the proxy always return a plain boolean, never the bound function. */\nexport type ClassValue = boolean | (() => boolean);\n/** The `el.class` proxy — the runtime switch for `$`-class blocks declared in `.style()`\n * (see {@link ClassStyles}). One surface, mirroring `el.style`:\n *\n * ```ts\n * el.class.checked // read: is it active on THIS element? → boolean\n * el.class.checked = true // activate (false deactivates)\n * el.class.open = !el.class.open // toggle\n * el.class.done = () => todo.done.value // reactive binding (signals)\n * el.class({ checked: true, done: () => … }) // batch form — returns the element, chainable\n * ```\n *\n * Class names are accepted with or without the declaration-site `$` prefix. `R` is the concrete\n * node type, so the batch form chains like `.style()`.\n *\n * Typing note: property access is `any` because an index signature can't give reads (`boolean`)\n * and writes ({@link ClassValue}) different types — the batch form is the fully typed path;\n * single-key writes are runtime-coerced with `!!`. */\nexport type Classes<R> = ((classes: Record<string, ClassValue>) => R) & {\n [key: string]: any;\n};\nexport type OrientationStyles<T> = {\n onLandscape?: T;\n onPortrait?: T;\n /** @deprecated Misspelling of `onPortrait` (no second \"r\"). Kept so existing projects and published\n * bundles keep working — hosts still honour it — but new code should use `onPortrait`. */\n onPortait?: T;\n};\nexport type StyleFn<R, T extends object> = ((style: Reactive<T> & OrientationStyles<T> & ClassStyles<T>) => R);\nexport type Style<R, T extends object> = StyleFn<R, T> & T & OrientationStyles<T> & ClassStyles<T>;\nexport type AnimateStyle<R, T extends object> = ((style: T & {\n /** Tween length in **milliseconds** (default 225). */\n duration?: number;\n /** Wait before starting, in **milliseconds**. A looping animation delays once, not per cycle. */\n delay?: number;\n /** Escape hatch: target an internal style layer (the onPressed/orientation mechanism). Not part of the supported surface. */\n layer?: number;\n /** `false` = animate without writing the targets into the element's style (e.g. a fade-out right before `.hide()`). */\n commit?: boolean;\n /** Repeat the animation: `true` = forever, a number = that many cycles. A looping animation is an\n * effect, not a state change — it never commits, and the element ends back at its base style.\n * The loop stops when a later `animateTo`/`animateFrom` runs on the element or it leaves the screen. */\n loop?: boolean | number;\n /** `\"ping-pong\"` (default) animates there and back each cycle — no jump. `\"restart\"` snaps back and\n * replays forward — for full-turn spinners (`transform: \"rotate(360deg)\"`) and shimmers. Only meaningful with `loop`. */\n loopMode?: \"restart\" | \"ping-pong\";\n}) => R);\nexport type AppearStyle<R, T> = (arg: {\n from: T;\n duration?: number;\n delay?: number;\n}) => R;\nexport type DisappearStyle<R, T> = (arg: {\n to: T;\n duration?: number;\n delay?: number;\n}) => R;\nexport type OnLayoutCallback = (layout: {\n left: number;\n top: number;\n width: number;\n height: number;\n}) => void;\nexport type BoundingClientRect = {\n x: number;\n y: number;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n};\nexport declare class Element<T extends string> {\n readonly type: T;\n /** Author-given semantic name (LeCodes `name`) — see BaseStyle.name. Extracted from the options\n * object so it never reaches the layout engine; the renderer reads it off the node. */\n readonly name?: string;\n protected _style: any;\n protected _id: number;\n protected _styleProxy: any;\n protected _appear: any;\n protected _disappear: any;\n constructor(type: T, style: any);\n get style(): any;\n animateTo(style: any): this;\n animateFrom(style: any): this;\n protected _classProxy?: any;\n /** Style-class control — flips the `$`-class blocks declared in `.style()`. One proxy, same\n * contract as `el.style`:\n *\n * - `el.class.checked` — read: is the class active on THIS element? → `boolean`\n * - `el.class.checked = true` / `= false` — activate / deactivate\n * - `el.class.open = !el.class.open` — toggle\n * - `el.class.done = () => todo.done.value` — reactive: the class tracks the signals the\n * function reads; a later write to the same class (plain or function) replaces the binding\n * - `el.class({ checked: true, done: () => … })` — batch form, returns the element (chainable)\n *\n * Names are accepted with or without the leading `$`. A class set on an element CASCADES: it is\n * also active on every descendant (their same-name `$` blocks light up), until the subtree's\n * root — hosted screens/widgets don't inherit. Reads reflect only this element's own classes;\n * there is no opt-out below an active ancestor. `Object.keys(el.class)` lists the active names. */\n get class(): any;\n protected ll?: OnLayoutCallback[];\n onLayout(onLayout: OnLayoutCallback): this;\n /** Absolute rect in device space — the space `UIWidget` positions in and touch events report\n * `clientX`/`clientY` in — including scroll offsets, read live at call time (unlike `onLayout`,\n * whose coordinates are parent-relative and go stale when an ancestor scrolls). `null` before\n * the element is mounted and on hosts without the bridge read. Anchor popovers position-once\n * at open; don't poll per frame. */\n getBoundingClientRect(): BoundingClientRect | null;\n}\nexport type ChildrenFn = () => UINodeChild[];\n/**\n * Compiler-emitted memoized map for reactive children. The chisel `reactiveUi` pass rewrites\n * `list.map(fn)` inside a children binding to `__uiMap(list, fn, \"<file>:<offset>\")`, so unchanged\n * items keep their element identity across re-runs (the reconciler then leaves them mounted).\n * Cache: per (binding owner, call-site slot), keyed by item reference; duplicate items consume\n * cached nodes in order. Outside a children binding, for non-array inputs, or for non-element\n * results it behaves exactly like Array.prototype.map — a wrong rewrite can't change behavior.\n */\nexport declare function __uiMap(list: any, render: (item: any, index: number) => any, slot: string): any[];\nexport declare class ContainerElement<T extends string> extends Element<T> {\n children: any[];\n constructor(type: T, style: any, children: any[] | ChildrenFn);\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodesToDelete: UINode[]): this;\n setContent(children: UINodeChild[] | ChildrenFn): this;\n}\nexport {};\n","types/ui/UIPager.d.ts":"import { ContainerElement, type AnimateStyle, type BaseStyle, type ChildrenFn, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type UINodeChild } from \"./UINode\";\nimport type { UIScreen } from \"./UIScreen\";\n/** Styles a pager accepts — layout box + drawable (background, borders, …). Pages style\n * themselves; the pager only owns its own slot. */\nexport type UIPagerStyle = ElementStyle & DrawableStyle;\n/**\n * The screen-navigation element: sibling **tabs** that swipe natively side to side, each with its\n * own navigation **stack**. `push` opens a screen on top of the current tab (within the pager);\n * `pop` / the native edge back-swipe unwinds it. A one-tab pager is a plain navigation stack.\n *\n * ```ts\n * const pager = UIPager([ HomeScreen(), ProfileScreen() ]) // two tabs, side by side\n * Router.init(UIScreen([ pager.style({ flexGrow: 1 }), tabBar ]))\n *\n * // from anywhere inside a hosted screen — no reference threading:\n * UIPager.push(PostScreen(id))\n * ```\n *\n * To open something over *everything* (above bars, above the pager), use `Router.push` instead.\n */\nexport interface UIPager {\n readonly type: \"pager\";\n style: Style<this, UIPagerStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Replace the pager's tabs — one screen per tab, in order. Every tab becomes a fresh\n * one-screen stack (pushed screens are dropped) and the selection is clamped into range;\n * screens that were already tabs keep their state. Pass a function for reactive tabs. */\n setContent(tabs: UIScreen[] | (() => UIScreen[])): this;\n /** Switch to tab `index`. **Instant by default** — the tab-bar convention (tabs are parallel\n * modes, not neighbors); pass `animated: true` for the direction-aware slide of top-tab /\n * pager UIs. Out-of-range and same-index calls are no-ops. Tabs keep their stacks: selecting\n * away and back restores the tab exactly where it was, pushed screens included. */\n select(index: number, animated?: boolean): this;\n /** The selected tab index (0-based). */\n readonly index: number;\n /** Fires when the selected tab changes and has settled — a user swipe or `select()`. */\n onSelect(callback: (index: number) => void): this;\n /** Push `screen` on top of the **current tab** — slides in natively; the edge back-swipe (or\n * `pop()`) removes it. Other tabs are unaffected. */\n push(screen: UIScreen): this;\n /** Pop the current tab's top screen (no-op at the tab root — the root never pops). The\n * programmatic twin of the native edge back-swipe. */\n pop(): this;\n /** Unwind the current tab back to its root screen in one step. */\n popToRoot(): this;\n /** Swap the current tab's top screen for `screen` without growing the stack (at depth 1 this\n * swaps the tab's root). */\n replace(screen: UIScreen): this;\n /** The current tab's screens, root → top (read-only snapshot). */\n readonly stack: UIScreen[];\n /** The current tab's stack depth — 1 means only the root. While `depth > 1`, swiping between\n * tabs is disabled (the horizontal gesture belongs to the back-swipe). */\n readonly depth: number;\n /** Fires when the current tab's depth changes — push, pop, replace, or a back-swipe. */\n onChange(callback: (depth: number) => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class PagerElement extends ContainerElement<\"pager\"> {\n /** Per-tab stack lengths — partitions the flat tab-major `children`. Named `_*` so chisel\n * keeps it (the host reads it live). */\n _lens: number[];\n /** Selected tab. */\n _index: number;\n _openCount: number;\n private scl;\n private ncl;\n constructor(style: UIPagerStyle | null, tabs: UIScreen[]);\n /** Start offset of tab `i`'s segment in the flat `children`. */\n private _offset;\n get index(): number;\n get stack(): UIScreen[];\n get depth(): number;\n onSelect(callback: (index: number) => void): this;\n onChange(callback: (depth: number) => void): this;\n select(index: number, animated?: boolean): this;\n push(screen: UIScreen): this;\n pop(): this;\n popToRoot(): this;\n replace(screen: UIScreen): this;\n private _rebuild;\n setContent(children: UINodeChild[] | ChildrenFn): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodesToDelete: UIScreen[]): this;\n _reconcile(next: UINodeChild[]): void;\n _hostDidSelect(index: number): void;\n _hostDidPop(depth: number): void;\n private _emitSelect;\n private _emitChange;\n private _track;\n _activate(): void;\n _deactivate(): void;\n}\n/** Callable factory + ambient statics. The name `UIPager` is a value (this factory) and a type\n * (the instance interface above) — a standard value/type merge. */\ninterface UIPagerConstructor {\n /** One tab — a plain navigation stack rooted at `root` (push/pop, no tab swiping). */\n (root: UIScreen): UIPager;\n /** Sibling tabs, one per screen, in order — swipe (or `select`) between them. Tabs are fixed\n * at construction; each starts as its own one-screen stack. */\n (tabs: UIScreen[]): UIPager;\n /** Styled pager + content (a single root screen or an array of tab screens). */\n (style: UIPagerStyle, content: UIScreen | UIScreen[]): UIPager;\n /** The pager that owns the currently visible screen, or `null` when the visible screen isn't\n * hosted by one. With pagers nested inside pages, resolves to the **innermost** — so ambient\n * calls act on the pager the user is actually looking at. */\n readonly current: UIPager | null;\n /** `UIPager.current.push(screen)` — push onto the pager owning the visible screen, no\n * reference threading. No-op with a console warning when there is no current pager. */\n push(screen: UIScreen): void;\n /** `UIPager.current.pop()` — pop the visible pager's current tab (no-op at the tab root, or\n * with a warning when there is no current pager). */\n pop(): void;\n /** `UIPager.current.popToRoot()` — unwind the visible pager's current tab to its root. */\n popToRoot(): void;\n}\n/**\n * Create a pager — THE screen-navigation element: an array of screens becomes swipeable sibling\n * tabs, a single screen becomes a plain stack. Navigate within it via `pager.push/pop/replace`\n * (per-tab) and `pager.select(i)` (between tabs), or from any child screen via the ambient\n * `UIPager.push` / `UIPager.pop` / `UIPager.current`. Pages are full `UIScreen`s (own\n * `onOpen`/`onClose`); give the pager `flexGrow: 1` or a size so it doesn't\n * collapse. `Router` stays the way to open a destination ON TOP of the pager.\n */\nexport declare const UIPager: UIPagerConstructor;\nexport {};\n","types/ui/UIPopover.d.ts":"import { ModalElement, type UIModal, type UIModalStyle } from \"./UIModal\";\nimport type { BoundingClientRect, ChildrenFn, UINodeChild } from \"./UINode\";\nexport type UIPopoverStyle = UIModalStyle;\n/** What a popover can anchor to: any element (it reads `getBoundingClientRect()`), or a raw\n * `{x, y}` point — a long-press context menu anchors to the touch position. */\nexport type UIPopoverAnchor = {\n getBoundingClientRect(): BoundingClientRect | null;\n} | {\n x: number;\n y: number;\n};\n/**\n * An anchored menu: a `UIModal` whose scrim is transparent (invisible but still intercepting —\n * an outside tap dismisses, and nothing underneath can scroll while it's open) and whose\n * position comes from the anchor passed to `show(anchor)`: below the anchor's left edge,\n * flipped above when there's no room, clamped into the viewport. Position is computed once per\n * show — anchored popovers don't follow their anchor. Backs dropdowns, context menus, and\n * tooltips; create it **once** at module scope and reuse it.\n */\nexport interface UIPopover extends UIModal {\n /** Position next to `anchor` (an element or an `{x, y}` point), attach to\n * `Presentable.current` (unless an owner was set via `attachTo`), and play the entrance\n * transition. Without an anchor the popover shows wherever its own style puts it. */\n show(anchor?: UIPopoverAnchor): void;\n}\nexport declare class PopoverElement extends ModalElement {\n private _anchorRect?;\n private _placedLeft?;\n private _placedTop?;\n constructor(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn);\n show(anchor?: UIPopoverAnchor): void;\n private _place;\n}\nexport declare function UIPopover(): UIPopover;\nexport declare function UIPopover(children: UINodeChild[] | ChildrenFn): UIPopover;\nexport declare function UIPopover(style: UIPopoverStyle): UIPopover;\nexport declare function UIPopover(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn): UIPopover;\n","types/ui/UIScreen.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { type PresentOptions } from \"./presentable\";\nimport { ContainerElement, type AnimateStyle, type BaseStyle, type ContainerStyle, type DrawableStyle, type OnLayoutCallback, type BoundingClientRect, type PaddingStyle, type Classes, type Style, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIScreenStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle;\nexport interface UIScreen {\n readonly type: \"screen\";\n style: Style<this, UIScreenStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Show this screen as the current destination (replaces whatever is visible — a screen, a\n * scene, a native view — suspending an active Router until `Router.restore()`). */\n open(options?: PresentOptions): void;\n close(): void;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n readonly children: UINodeChild[];\n onBackPressed(callback: () => void): this;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n /**\n * Keep this screen's built native tree alive when a host detaches it: instead of being destroyed,\n * its views + layout + live state (scroll position, input text) are retained, so re-hosting the\n * SAME screen object restores it in place rather than rebuilding. `onClose`/`onOpen` still fire on\n * detach/re-attach. You own the lifetime — a kept tree is freed only by `dispose()` or when the\n * project unloads. (Native-only today; web rebuilds.)\n */\n keepAlive(enabled?: boolean): this;\n /** Free a `keepAlive()` screen's retained tree now. No-op unless it's currently detached-and-kept. */\n dispose(): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;\n}\nexport declare class ScreenElement extends ContainerElement<\"screen\"> {\n open(options?: PresentOptions): void;\n close(): void;\n protected ol: (() => void)[];\n onOpen(callback: () => void): this;\n protected cl: (() => void)[];\n onClose(callback: () => void): this;\n _keepAlive: boolean;\n keepAlive(enabled?: boolean): this;\n dispose(): this;\n readonly touchStartListeners: any[];\n _interactive: boolean;\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\nexport declare function UIScreen(): UIScreen;\nexport declare function UIScreen(children: UINodeChild[] | ChildrenFn): UIScreen;\nexport declare function UIScreen(style: UIScreenStyle): UIScreen;\nexport declare function UIScreen(style: UIScreenStyle, children: UINodeChild[]): UIScreen;\n","types/ui/UIScrollable.d.ts":"import type { UIContainerStyle } from \"./UIContainer\";\nimport { type Classes, type Style, type AnimateStyle, type UINodeChild, type ChildrenFn, type OnLayoutCallback, type BoundingClientRect, type Color } from \"./UINode\";\nexport type ScrollStyle = {\n showScrollbar?: boolean;\n overscrollMode?: \"none\" | \"absorb\" | \"default\";\n refreshControlColor?: Color;\n keyboardDismissMode?: \"interactive\" | \"scroll\" | \"none\";\n snap?: \"none\" | \"start\" | \"center\" | \"end\";\n};\nexport type UIScrollableStyle = UIContainerStyle & ScrollStyle & {\n scrollDirection?: \"horizontal\" | \"vertical\";\n};\nexport interface UIScrollable {\n readonly type: \"scrollable\";\n style: Style<this, UIScrollableStyle>;\n animateTo: AnimateStyle<this, UIScrollableStyle>;\n animateFrom: AnimateStyle<this, UIScrollableStyle>;\n append(...nodes: UINodeChild[]): UIScrollable;\n insert(index: number, ...nodes: UINodeChild[]): UIScrollable;\n remove(...nodes: UINodeChild[]): UIScrollable;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n onScroll(callback: (scrollPosition: number) => void): UIScrollable;\n onScrollRelease(callback: () => void): UIScrollable;\n onOverscroll(callback: (delta: number) => void): UIScrollable;\n /** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the\n * node mounts (hosts read it at creation). Vertical only; native hosts — no-op on web. */\n onRefresh(callback: () => void | Promise<void>): UIScrollable;\n readonly children: UINodeChild[];\n}\nexport declare function UIScrollable(): UIScrollable;\nexport declare function UIScrollable(children: UINodeChild[] | ChildrenFn): UIScrollable;\nexport declare function UIScrollable(style: UIScrollableStyle): UIScrollable;\nexport declare function UIScrollable(style: UIScrollableStyle, children: UINodeChild[]): UIScrollable;\n","types/ui/UISpacer.d.ts":"import { type ElementStyle, type Classes, type Style } from \"./UINode\";\nexport type UISpacerStyle = ElementStyle;\nexport interface UISpacer {\n readonly type: \"spacer\";\n style: Style<this, UISpacerStyle>;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UISpacer(): UISpacer;\nexport declare function UISpacer(style: UISpacerStyle): UISpacer;\n","types/ui/UIText.d.ts":"import { Element, type AnimateStyle, type BaseStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type TextStyle } from \"./UINode\";\nexport type UITextStyle = ElementStyle & TextStyle & DrawableStyle;\nexport interface UIText {\n readonly type: \"text\";\n text: string;\n style: Style<this, UITextStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle & TextStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle & TextStyle>;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class TextElement extends Element<\"text\"> {\n private _text;\n constructor(style: any, text: string | (() => string));\n get text(): string;\n set text(value: string);\n}\nexport declare function UIText(text: string | (() => string)): UIText;\nexport declare function UIText(style: UITextStyle, text: string | (() => string)): UIText;\n","types/ui/UIVideo.d.ts":"import type { VideoPlayer } from \"../runtime/media\";\nimport { type PresentOptions } from \"./presentable\";\nimport { type AnimateStyle, type BaseStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style } from \"./UINode\";\nexport type UIVideoStyle = ElementStyle & DrawableStyle & {\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n};\nexport interface UIVideo {\n readonly type: \"video\";\n player: VideoPlayer;\n style: Style<this, UIVideoStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Show fullscreen as the current destination. Promotion: if this video is mounted in a screen,\n * the SAME native player moves fullscreen — playback uninterrupted; a pop moves it back. */\n open(options?: PresentOptions): void;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UIVideo(player: VideoPlayer): UIVideo;\nexport declare function UIVideo(style: UIVideoStyle, player: VideoPlayer): UIVideo;\n","types/ui/UIVirtualizedList.d.ts":"import { Element, type Color, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type UINodeChild } from \"./UINode\";\nexport type UIVirtualizedListStyle = DrawableStyle & ElementStyle & {\n refreshControlColor?: Color;\n};\nexport interface VListConfig<T> {\n /** Стабильный уникальный ключ айтема */\n keyOf: (item: T) => string;\n /** Фабрика поддерева. Вызывается при входе айтема в окно; поддерево живёт до выхода из окна */\n render: (item: T) => UINodeChild;\n /**\n * Оценка высоты (px) до первого измерения. Число — или функция от айтема,\n * например для чата: msg => 40 + Math.ceil(msg.text.length / 35) * 20\n * Вычисляется один раз при добавлении айтема, в нативку уходит готовое число.\n */\n estimatedHeight: number | ((item: T) => number);\n /** px вокруг вьюпорта, которые держим смонтированными. Default: высота вьюпорта */\n overscan?: number;\n /** Чат-режим: первый layout проскроллен в конец, append при положении внизу автоскроллит */\n inverted?: boolean;\n}\nexport interface UIVirtualizedList<T = unknown> {\n readonly type: \"vlist\";\n style: Style<this, UIVirtualizedListStyle>;\n /** Полная замена данных. Нативка сама размонтирует исчезнувшие ключи через _syncWindow */\n setData(items: T[]): this;\n append(...items: T[]): this;\n /** Вставка в начало БЕЗ прыжка скролла (компенсация на стороне нативки) */\n prepend(...items: T[]): this;\n /** Обновить айтемы с теми же ключами: re-render, если смонтированы. Высота в кэше сохраняется до повторного измерения */\n update(...items: T[]): this;\n removeByKey(...keys: string[]): this;\n readonly itemCount: number;\n getItem(key: string): T | undefined;\n scrollTo(offset: number, animated?: boolean): void;\n scrollToKey(key: string, animated?: boolean): void;\n scrollToEnd(animated?: boolean): void;\n onScroll(callback: (scrollPosition: number) => void): this;\n /** Pull-to-refresh: спиннер держится, пока не разрешится промис. Навесить ДО маунта\n * (нативка читает при создании ноды). Только native-хосты; на вебе no-op. */\n onRefresh(callback: () => void | Promise<void>): this;\n /** Порог в px от нижнего края контента. Срабатывает один раз до ухода от края (защёлка в нативке) */\n onEndReached(thresholdPx: number, callback: () => void): this;\n /** Порог от верхнего края — подгрузка истории в чате */\n onStartReached(thresholdPx: number, callback: () => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class VListElement<T> extends Element<\"vlist\"> implements UIVirtualizedList<T> {\n _overscan: number;\n _inverted: boolean;\n _keys: string[];\n _estimates: number[];\n _endThreshold: number;\n _startThreshold: number;\n protected sl: ((scrollPosition: number) => void)[];\n protected erl: (() => void)[];\n protected strl: (() => void)[];\n private items;\n private mounted;\n private keyOf;\n private renderItem;\n private estimate;\n constructor(config: VListConfig<T>);\n private get isAttached();\n private register;\n setData(items: T[]): this;\n append(...items: T[]): this;\n prepend(...items: T[]): this;\n update(...items: T[]): this;\n removeByKey(...keys: string[]): this;\n get itemCount(): number;\n getItem(key: string): T | undefined;\n scrollTo(offset: number, animated?: boolean): void;\n scrollToKey(key: string, animated?: boolean): void;\n scrollToEnd(animated?: boolean): void;\n onScroll(callback: (scrollPosition: number) => void): this;\n _refreshCallback: any;\n onRefresh(callback: () => void | Promise<void>): this;\n onEndReached(thresholdPx: number, callback: () => void): this;\n onStartReached(thresholdPx: number, callback: () => void): this;\n /**\n * Единственный колбэк из нативки (через jsPtr, как у button).\n * Вызывается ТОЛЬКО когда окно пересекло границу — не на каждый кадр скролла.\n * Порядок: сначала unmount (нативка уже снесла поддеревья и обнулила _id,\n * здесь только чистим JS-ссылки), потом mount.\n */\n _syncWindow(unmountKeys: string[], mountKeys: string[]): void;\n}\nexport declare function UIVirtualizedList<T>(config: VListConfig<T>): UIVirtualizedList<T>;\n","types/ui/UIWidget.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { Presentable } from \"./presentable\";\nimport { ContainerElement, type AnimateStyle, type BaseStyle, type Color, type ContainerStyle, type DrawableStyle, type OnLayoutCallback, type BoundingClientRect, type PaddingStyle, type PositionStyle, type Classes, type Style, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIWidgetStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle & PositionStyle & {\n overlayColor?: Color | null;\n};\nexport interface UIWidget {\n readonly type: \"widget\";\n style: Style<this, UIWidgetStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n }>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n }>;\n /**\n * Attach this widget to a destination (a `Scene`, a `UIScreen`, …): the widget lives on that\n * page's layer — it shows/hides with the page and rides its transition, and a screen pushed\n * on top covers it (a scene HUD behaves like part of the scene). Sticky until `attachTo(null)`\n * (= back to a global overlay). Set it while the widget is hidden. The widget is always its own\n * overlay root mounted into the owner's page view — it never becomes a child of the owner, so it\n * stays topmost and its updates never trigger the owner's relayout. Works with a `UIScreen` that\n * is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe.\n */\n attachTo(owner: Presentable | null): this;\n /** Show the widget. By default it is a global overlay above every destination — it stays\n * visible across navigation until `hide()` (dialogs, mini-player, global loader). If the\n * widget was attached via `attachTo(owner)`, it mounts on that page's layer instead and is\n * only visible while the owner is presented. */\n show(): void;\n hide(): void;\n readonly isShow: boolean;\n append(...nodes: UINodeChild[]): UIWidget;\n insert(index: number, ...nodes: UINodeChild[]): UIWidget;\n remove(...nodes: UINodeChild[]): UIWidget;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n readonly children: UINodeChild[];\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n onTouchStart(callback: (ev: TouchStartEvent<UIWidget>) => void): this;\n onOverlayTap(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class WidgetElement extends ContainerElement<\"widget\"> {\n scrollable: false;\n _owner?: Presentable;\n constructor(type: \"widget\", style: UIWidgetStyle, children: UINodeChild[] | ChildrenFn);\n attachTo(owner: Presentable | null): this;\n show(): void;\n hide(): void;\n get isShow(): boolean;\n _interactive: boolean;\n readonly touchStartListeners: any[];\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n readonly otl: (() => void)[];\n onOverlayTap(callback: () => void): this;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\nexport declare function UIWidget(): UIWidget;\nexport declare function UIWidget(children: UINodeChild[] | ChildrenFn): UIWidget;\nexport declare function UIWidget(style: UIWidgetStyle): UIWidget;\nexport declare function UIWidget(style: UIWidgetStyle, children: UINodeChild[]): UIWidget;\n"}
1
+ {"global.d.ts":"// AUTO-GENERATED by build-types.ts. The import-free type surface for le.codes projects:\n// every SDK global declared ambiently, so user code uses Scene / Sprite / UIScreen / … \n// with no imports and full editor autocomplete.\n\nimport type * as SDK from \"./types/inject\"\n\ndeclare global {\n const ARScene: typeof SDK.ARScene\n const Aspect: typeof SDK.Aspect\n const AudioPlayer: typeof SDK.AudioPlayer\n const Bitmap: typeof SDK.Bitmap\n const Camera: typeof SDK.Camera\n const Camera2D: typeof SDK.Camera2D\n const CameraView: typeof SDK.CameraView\n const Canvas: typeof SDK.Canvas\n const CharacterController: typeof SDK.CharacterController\n const CharacterController2D: typeof SDK.CharacterController2D\n const ClickEvent: typeof SDK.ClickEvent\n const Color: typeof SDK.Color\n const DateValue: typeof SDK.DateValue\n const File: typeof SDK.File\n const FollowPath: typeof SDK.FollowPath\n const FormData: typeof SDK.FormData\n const Geolocation: typeof SDK.Geolocation\n const Geometry: typeof SDK.Geometry\n const Input: typeof SDK.Input\n const InspectorUI: typeof SDK.InspectorUI\n const Light: typeof SDK.Light\n const LongPressEvent: typeof SDK.LongPressEvent\n const LookAt: typeof SDK.LookAt\n const Mat4: typeof SDK.Mat4\n const Material: typeof SDK.Material\n const Mathf: typeof SDK.Mathf\n const Mesh: typeof SDK.Mesh\n const Model: typeof SDK.Model\n const ModelAnimation: typeof SDK.ModelAnimation\n const MoveTo: typeof SDK.MoveTo\n const NativeView: typeof SDK.NativeView\n const Node: typeof SDK.Node\n const Node2D: typeof SDK.Node2D\n const Noise: typeof SDK.Noise\n const Particles: typeof SDK.Particles\n const Physics: typeof SDK.Physics\n const Physics2D: typeof SDK.Physics2D\n const Plane: typeof SDK.Plane\n const PlayAnimation: typeof SDK.PlayAnimation\n const Presentable: typeof SDK.Presentable\n const QRScanner: typeof SDK.QRScanner\n const Quat: typeof SDK.Quat\n const Ray: typeof SDK.Ray\n const Router: typeof SDK.Router\n const Scene: typeof SDK.Scene\n const Scene2D: typeof SDK.Scene2D\n const SceneHandle: typeof SDK.SceneHandle\n const Service: typeof SDK.Service\n const Shape: typeof SDK.Shape\n const Shape2D: typeof SDK.Shape2D\n const Spin: typeof SDK.Spin\n const Sprite: typeof SDK.Sprite\n const SpriteAnimation: typeof SDK.SpriteAnimation\n const SvgSource: typeof SDK.SvgSource\n const Texture: typeof SDK.Texture\n const Texture2D: typeof SDK.Texture2D\n const Tilemap: typeof SDK.Tilemap\n const TouchStartEvent: typeof SDK.TouchStartEvent\n const Trail: typeof SDK.Trail\n const Trigger: typeof SDK.Trigger\n const Trigger2D: typeof SDK.Trigger2D\n const UIBottomSheet: typeof SDK.UIBottomSheet\n const UIBox: typeof SDK.UIBox\n const UIButton: typeof SDK.UIButton\n const UIColumn: typeof SDK.UIColumn\n const UIImage: typeof SDK.UIImage\n const UIInput: typeof SDK.UIInput\n const UIModal: typeof SDK.UIModal\n const UIPager: typeof SDK.UIPager\n const UIPopover: typeof SDK.UIPopover\n const UIRow: typeof SDK.UIRow\n const UIScreen: typeof SDK.UIScreen\n const UIScrollable: typeof SDK.UIScrollable\n const UISpacer: typeof SDK.UISpacer\n const UIText: typeof SDK.UIText\n const UITextArea: typeof SDK.UITextArea\n const UIVideo: typeof SDK.UIVideo\n const UIVirtualizedList: typeof SDK.UIVirtualizedList\n const UIWidget: typeof SDK.UIWidget\n const VRScene: typeof SDK.VRScene\n const Vec2: typeof SDK.Vec2\n const Vec3: typeof SDK.Vec3\n const VideoPlayer: typeof SDK.VideoPlayer\n const WebSocket: typeof SDK.WebSocket\n const __editorPlugins: typeof SDK.__editorPlugins\n const __uiMap: typeof SDK.__uiMap\n const animate: typeof SDK.animate\n const animateMat4: typeof SDK.animateMat4\n const app: typeof SDK.app\n const clipboard: typeof SDK.clipboard\n const colorCurve: typeof SDK.colorCurve\n const computed: typeof SDK.computed\n const cubicBezier: typeof SDK.cubicBezier\n const curve: typeof SDK.curve\n const date: typeof SDK.date\n const defineScene: typeof SDK.defineScene\n const device: typeof SDK.device\n const easeIn: typeof SDK.easeIn\n const easeInOut: typeof SDK.easeInOut\n const easeOut: typeof SDK.easeOut\n const effect: typeof SDK.effect\n const fetch: typeof SDK.fetch\n const fetchLocal: typeof SDK.fetchLocal\n const localStorage: typeof SDK.localStorage\n const make: typeof SDK.make\n const openFilePicker: typeof SDK.openFilePicker\n const openURL: typeof SDK.openURL\n const pauseAnimation: typeof SDK.pauseAnimation\n const ref: typeof SDK.ref\n const registerEditorTool: typeof SDK.registerEditorTool\n const registerEditorWindow: typeof SDK.registerEditorWindow\n const registerFont: typeof SDK.registerFont\n const resumeAnimation: typeof SDK.resumeAnimation\n const share: typeof SDK.share\n const signal: typeof SDK.signal\n const stopAnimation: typeof SDK.stopAnimation\n const theme: typeof SDK.theme\n const toast: typeof SDK.toast\n const use: typeof SDK.use\n type ARScene<T extends ARMode = \"default\"> = SDK.ARScene<T>\n type AppState = SDK.AppState\n type Aspect<K extends string, P = Node> = SDK.Aspect<K, P>\n type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = SDK.AspectEntry<A>\n type AudioPlayer = SDK.AudioPlayer\n type Bitmap = SDK.Bitmap\n type Camera = SDK.Camera\n type Camera2D = SDK.Camera2D\n type CameraFacing = SDK.CameraFacing\n type CameraNodeDef = SDK.CameraNodeDef\n type CameraView = SDK.CameraView\n type Canvas = SDK.Canvas\n type CharacterController = SDK.CharacterController\n type CharacterController2D = SDK.CharacterController2D\n type ClickEvent<T = any> = SDK.ClickEvent<T>\n type Computed<T> = SDK.Computed<T>\n type DateInput = SDK.DateInput\n type DateValue = SDK.DateValue\n type EditorApi = SDK.EditorApi\n type EditorRayHit = SDK.EditorRayHit\n type EditorToolHooks = SDK.EditorToolHooks\n type EditorWindowFn = SDK.EditorWindowFn\n type FetchResponse = SDK.FetchResponse\n type FieldMeta<T = unknown> = SDK.FieldMeta<T>\n type File = SDK.File\n type FollowPath = SDK.FollowPath\n type FormData = SDK.FormData\n type GeoOptions = SDK.GeoOptions\n type GeoPosition = SDK.GeoPosition\n type GeoWatch = SDK.GeoWatch\n type Geometry = SDK.Geometry\n type HapticStyle = SDK.HapticStyle\n type InspectorUI = SDK.InspectorUI\n type Light = SDK.Light\n type LightDef = SDK.LightDef\n type LoadedScene<D extends SceneDef> = SDK.LoadedScene<D>\n type Locale = SDK.Locale\n type LongPressEvent<T = any> = SDK.LongPressEvent<T>\n type LookAt = SDK.LookAt\n type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = SDK.MakeEntry<A>\n type Mat4 = SDK.Mat4\n type Material = SDK.Material\n type MaterialDef = SDK.MaterialDef\n type Mesh = SDK.Mesh\n type MeshDef = SDK.MeshDef\n type Model = SDK.Model\n type ModelAnimation = SDK.ModelAnimation\n type MotionOptions = SDK.MotionOptions\n type MoveTo = SDK.MoveTo\n type NativeView = SDK.NativeView\n type Node = SDK.Node\n type Node2D = SDK.Node2D\n type Noise = SDK.Noise\n type Particles = SDK.Particles\n type Physics = SDK.Physics\n type Physics2D = SDK.Physics2D\n type Plane = SDK.Plane\n type PlayAnimation = SDK.PlayAnimation\n type PresentOptions = SDK.PresentOptions\n type Presentable = SDK.Presentable\n type QRScanner = SDK.QRScanner\n type Quat = SDK.Quat\n type Ray = SDK.Ray\n type Scene = SDK.Scene\n type Scene2D = SDK.Scene2D\n type SceneDef = SDK.SceneDef\n type SceneHandle<D extends SceneDef = SceneDef> = SDK.SceneHandle<D>\n type SceneNodeDef = SDK.SceneNodeDef\n type Service = SDK.Service\n type Shape = SDK.Shape\n type Shape2D = SDK.Shape2D\n type Signal<T> = SDK.Signal<T>\n type Spin = SDK.Spin\n type Sprite = SDK.Sprite\n type SpriteAnimation = SDK.SpriteAnimation\n type Texture = SDK.Texture\n type Texture2D = SDK.Texture2D\n type ThemeAccessors<T> = SDK.ThemeAccessors<T>\n type ThemeValues = SDK.ThemeValues\n type Tilemap = SDK.Tilemap\n type TouchStartEvent<T = any> = SDK.TouchStartEvent<T>\n type Trail = SDK.Trail\n type Transition = SDK.Transition\n type TransitionName = SDK.TransitionName\n type TransitionSpec = SDK.TransitionSpec\n type TransitionTransform = SDK.TransitionTransform\n type Trigger = SDK.Trigger\n type Trigger2D = SDK.Trigger2D\n type UIBottomSheet = SDK.UIBottomSheet\n type UIBottomSheetStyle = SDK.UIBottomSheetStyle\n type UIBox = SDK.UIBox\n type UIButton = SDK.UIButton\n type UIButtonStyle = SDK.UIButtonStyle\n type UIColumn = SDK.UIColumn\n type UIContainerStyle = SDK.UIContainerStyle\n type UIImage = SDK.UIImage\n type UIImageStyle = SDK.UIImageStyle\n type UIInput = SDK.UIInput\n type UIInputStyle = SDK.UIInputStyle\n type UIModal = SDK.UIModal\n type UIModalStyle = SDK.UIModalStyle\n type UINativeViewStyle = SDK.UINativeViewStyle\n type UINode = SDK.UINode\n type UINodeChild = SDK.UINodeChild\n type UIPager = SDK.UIPager\n type UIPagerStyle = SDK.UIPagerStyle\n type UIPopover = SDK.UIPopover\n type UIPopoverStyle = SDK.UIPopoverStyle\n type UIRow = SDK.UIRow\n type UIScreen = SDK.UIScreen\n type UIScreenStyle = SDK.UIScreenStyle\n type UIScrollable = SDK.UIScrollable\n type UIScrollableStyle = SDK.UIScrollableStyle\n type UISpacer = SDK.UISpacer\n type UISpacerStyle = SDK.UISpacerStyle\n type UIText = SDK.UIText\n type UITextArea = SDK.UITextArea\n type UITextStyle = SDK.UITextStyle\n type UIVideo = SDK.UIVideo\n type UIVideoStyle = SDK.UIVideoStyle\n type UIVirtualizedList<T = unknown> = SDK.UIVirtualizedList<T>\n type UIWidget = SDK.UIWidget\n type UIWidgetStyle = SDK.UIWidgetStyle\n type Unit = SDK.Unit\n type VRScene = SDK.VRScene\n type Vec2 = SDK.Vec2\n type Vec3 = SDK.Vec3\n type VideoPlayer = SDK.VideoPlayer\n type WebSocket = SDK.WebSocket\n type With<N, A extends Aspect<any, any>> = SDK.With<N, A>\n}\n\nexport {}\n","host.d.ts":"// JS-runtime globals provided by the host engine (web viewer / desktop / iOS), NOT by the SDK.\n// The SDK only declares them so its own source — and user code — type-check; they are never\n// bundled or injected. Mirrors packages/projects/src/global.d.ts. (Plus a couple of ambient,\n// type-only editor conveniences — e.g. `Style<T>` — which emit no runtime either.)\n\ndeclare global {\n // Timers + the per-frame loop. `setLoop(dt => …)` fires every frame; dt is SECONDS since the\n // previous frame. The host drives it (viewer RAF / desktop runTick).\n function setTimeout(handler: (...args: any[]) => void, timeout?: number): number\n function setInterval(handler: (...args: any[]) => void, timeout?: number): number\n function clearTimeout(id: number): void\n function clearInterval(id: number): void\n function setLoop(handler: (dt: number) => void): number\n function clearLoop(id: number): void\n\n // Math constants substituted at compile time by the bundler's esbuild `define`.\n var DEG2RAD: number\n var RAD2DEG: number\n\n // Compile-time boolean: `true` in scene-editor bundles, `false` (branch const-folded + DCE'd)\n // in shipped ones. Gate editor-only code with `if (EDITOR) { … }` — it costs zero bytes in\n // production. `*.editor.ts` files are the file-level form: compiled into editor bundles only.\n var EDITOR: boolean\n\n var console: {\n log(...data: any[]): void\n warn(...data: any[]): void\n info(...data: any[]): void\n error(...data: any[]): void\n }\n\n // Compile-time macro: `asset('./hero.png')` is desugared by the bundler into the module import\n // for that resource. Declared as a function purely so user code type-checks.\n function asset(path: string): string\n\n // Compile-time macro: installs a font and returns its family name — using a font IS declaring\n // it (docs/font-system-plan.md). A registry id (`font(\"manrope\")`) resolves against the font\n // registry; `{ weights, italic }` narrows/extends the face set (default: the family's standard\n // weights). A project path (`font(\"./fonts/Brand.ttf\")`) reads family/weight/italic from the\n // file itself. String-literal argument only. No awaiting — faces load with app boot and the\n // host holds first paint for them.\n function font(id: string, opts?: { weights?: number[], italic?: boolean }): string\n\n // Type-only editor convenience: the style object type of a UI element. `Style<UIButton>` (or\n // `Style<typeof myButton>`) resolves to the style you'd pass to `el.style(...)` — handy for typing\n // reusable style presets / helpers. Inferred from the element's callable `style` member, WITHOUT a\n // `Partial<>` wrapper: every style prop is already optional, and Partial over ClassStyles'\n // `$`-index signature adds `| undefined` to its values, making the preset unassignable back into\n // `.style(...)`. Round-trip is guarded by sdk/tests/ui-types.test.ts.\n type Style<T> = T extends { style: (s: infer S) => any } ? S : never\n}\n\nexport {}\n","types/ui/NativeView.d.ts":"import { type PresentOptions } from \"./presentable\";\nimport { type AnimateStyle, type BaseStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style } from \"./UINode\";\nexport type UINativeViewStyle = ElementStyle & DrawableStyle;\nexport interface NativeView {\n readonly type: \"native\";\n /** The registered view kind this instance resolves to (the `registerView` name). */\n readonly viewName: string;\n /** Creation params, passed to the host factory (JSON-serializable). */\n readonly params: any;\n style: Style<this, UINativeViewStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Show fullscreen as the current destination (see Presentable). */\n open(options?: PresentOptions): void;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Invoke a method on the native view (`map.call(\"setCenter\", [lng, lat])`). Args and the\n * result are JSON-serialized. Rejects if the host has no such view/method. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the native view emits (`map.on(\"markerTap\", cb)`). */\n on(event: string, callback: (data?: any) => void): this;\n off(event: string, callback: (data?: any) => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\n/**\n * Create an instance of a host-registered platform view. `NativeView.isSupported(name)` reports\n * whether this host registered a factory for it. Style via the chained `.style()`.\n */\nexport declare const NativeView: {\n (name: string, params?: object): NativeView;\n /** Whether this host registered a `registerView` factory under `name`. */\n isSupported(name: string): boolean;\n};\n","types/ui/theme.d.ts":"import type { Transition } from \"./presentable\";\nexport type ThemeValues = Record<string, string | number | null>;\nexport type ThemeAccessors<T> = {\n readonly [K in keyof T]: K extends string ? `var(--${K})` : never;\n};\nexport declare const theme: (<T extends Record<string, string | number | Transition | null>>(values: T & { [K in Exclude<keyof T, \"replaceTransition\">]: string | number | null; }) => ThemeAccessors<Omit<T, \"replaceTransition\">>) & {\n /** The app accent color. Kit components will read it via `var(--primaryColor, <fallback>)`. */\n readonly primaryColor: \"var(--primaryColor)\";\n /** Secondary / inactive content color for kit components. */\n readonly mutedColor: \"var(--mutedColor)\";\n /** DEFAULT text color — text without an explicit `color` follows it (hosts source their\n * default from the theme; unset = the host default, white on dark screens). Set it once for\n * a light theme instead of `color: \"black\"` on every label. */\n readonly color: \"var(--color)\";\n /** DEFAULT text font — text without an explicit `fontFamily` follows it. */\n readonly fontFamily: \"var(--fontFamily)\";\n /** Raw comfort knobs (logical px). The bare `comfort-top` style TOKEN applies the safe-area\n * formula — these accessors read the knob value itself, for manual composition. */\n readonly \"comfort-top\": \"var(--comfort-top)\";\n readonly \"comfort-bottom\": \"var(--comfort-bottom)\";\n readonly \"comfort-left\": \"var(--comfort-left)\";\n readonly \"comfort-right\": \"var(--comfort-right)\";\n};\n","types/ui/UIBottomSheet.d.ts":"import { ModalElement, type UIModalStyle } from \"./UIModal\";\nimport type { UIWidget } from \"./UIWidget\";\nimport type { ChildrenFn, UINodeChild } from \"./UINode\";\nexport type UIBottomSheetStyle = UIModalStyle;\n/**\n * A bottom sheet: a `UIWidget` pinned to the bottom edge. By default it is **content-sized** —\n * as tall as what's inside (capped at the screen), one position, drag down to dismiss (the\n * action-sheet shape). Call `detents()` for the multi-position map-app model instead: snap\n * positions the user drags between on native hosts. Ships as a widget node on the wire (no new\n * node type — docs/bottom-sheet-plan.md): hosts without sheet support show a static bottom panel.\n *\n * With detents, content lays out at the HIGHEST detent's size; lower detents show the top\n * slice. The scrim, `onOpen`/`onClose`, back-button and scrim-tap dismissal all come from the\n * modal machinery.\n *\n * ```ts\n * const actions = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [rows]) // content-sized\n *\n * const mapSheet = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [results])\n * .detents([0.3, 0.6, 1])\n * .onDetentChange(i => map.setPadding(...))\n * ```\n */\nexport interface UIBottomSheet extends UIWidget {\n /** Snap positions as fractions of screen height, ascending. Also sizes the sheet: its box is\n * the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet\n * is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */\n detents(list: number[]): this;\n /** Snap to a detent (animated). Clamped to the detents range; fires `onDetentChange`. */\n setDetent(index: number): void;\n /** Current detent index. */\n readonly detent: number;\n /** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */\n onDetentChange(callback: (index: number) => void): this;\n /** Mount and slide in to the current detent. No-op while already open. */\n show(): void;\n /** Slide out, fade the scrim, then unmount. No-op while closed. */\n hide(): void;\n /** True from `show()` until `hide()` starts. */\n readonly isOpen: boolean;\n /** Called when `show()` mounts the sheet. */\n onOpen(callback: () => void): this;\n /** Called when the sheet starts closing — scrim tap, back button, drag-dismiss, or `hide()`. */\n onClose(callback: () => void): this;\n /** `dismissible(false)`: scrim taps, the back button and dragging below the lowest detent no\n * longer close the sheet (a drag collapses to the lowest detent instead). Default `true`. */\n dismissible(enabled: boolean): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n}\nexport declare class BottomSheetElement extends ModalElement {\n _detents: number[];\n _detent: number;\n /** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the\n * settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.\n * `-1` = dragged below the lowest detent while dismissible. */\n readonly dtl: any[];\n readonly _detentListeners: ((index: number) => void)[];\n constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn);\n detents(list: number[]): this;\n get detent(): number;\n setDetent(index: number): void;\n onDetentChange(callback: (index: number) => void): this;\n show(): void;\n hide(): void;\n dismissible(enabled: boolean): this;\n}\nexport declare function UIBottomSheet(): UIBottomSheet;\nexport declare function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;\nexport declare function UIBottomSheet(style: UIBottomSheetStyle): UIBottomSheet;\nexport declare function UIBottomSheet(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn): UIBottomSheet;\n","types/ui/UIModal.d.ts":"import { type UIWidget, type UIWidgetStyle, WidgetElement } from \"./UIWidget\";\nimport type { BaseStyle, ChildrenFn, Color, DrawableStyle, UINodeChild } from \"./UINode\";\nexport type UIModalStyle = UIWidgetStyle;\n/**\n * The modal's hidden pose: `show()` animates from it, `hide()` animates to it. `duration` (ms)\n * applies to both directions.\n */\nexport type UIModalTransition = DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n duration?: number;\n};\n/**\n * A dialog: a `UIWidget` with the modal boilerplate built in. Comes with a scrim\n * (`overlayColor: \"rgba(0, 0, 0, 0.5)\"` unless overridden), animates on `show()`/`hide()`\n * (a 200 ms fade by default — swap the pose via `transition()`; the exit plays with\n * `commit: false`, so the style is intact for the next show), and closes itself on a scrim tap\n * or the Android back button (disable via `dismissible(false)`). Everything else is a plain\n * widget — same styling, children, touch and `attachTo()` surface; create it **once** at module\n * scope and reuse it.\n */\nexport interface UIModal extends UIWidget {\n /** Mount as an overlay and play the entrance transition. No-op while already open. */\n show(): void;\n /** Play the exit transition, then unmount. No-op while closed or already closing. */\n hide(): void;\n /** True from `show()` until `hide()` starts (already false during the exit animation). */\n readonly isOpen: boolean;\n /**\n * Replace the show/hide animation. `hidden` is the off-screen pose — `show()` animates from\n * it, `hide()` animates to it. Default `{ opacity: 0, duration: 200 }` (a fade); the pose\n * replaces it wholesale, so a slide without a fade is just the slide. The scrim keeps its own\n * fade unless the pose sets `overlayColor` itself.\n *\n * ```ts\n * sheet.transition({ transform: \"translateY(480px)\", duration: 250 }) // bottom sheet\n * ```\n */\n transition(hidden: UIModalTransition): this;\n /** Called when `show()` mounts the modal. */\n onOpen(callback: () => void): this;\n /** Called when the modal starts closing — scrim tap, back button, or a `hide()` call. */\n onClose(callback: () => void): this;\n /** `dismissible(false)` keeps scrim taps and the back button from closing the modal\n * (forced-choice dialogs). Default `true`. */\n dismissible(enabled: boolean): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n}\nexport declare class ModalElement extends WidgetElement {\n _open: boolean;\n _dismissible: boolean;\n _transition: UIModalTransition;\n _closeTimer?: ReturnType<typeof setTimeout>;\n readonly _openListeners: (() => void)[];\n readonly _closeListeners: (() => void)[];\n constructor(style: UIModalStyle, children: UINodeChild[] | ChildrenFn);\n private _pose;\n private get _duration();\n transition(hidden: UIModalTransition): this;\n show(): void;\n hide(): void;\n get isOpen(): boolean;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n dismissible(enabled: boolean): this;\n}\nexport declare function UIModal(): UIModal;\nexport declare function UIModal(children: UINodeChild[] | ChildrenFn): UIModal;\nexport declare function UIModal(style: UIModalStyle): UIModal;\nexport declare function UIModal(style: UIModalStyle, children: UINodeChild[] | ChildrenFn): UIModal;\n","types/ui/UIButton.d.ts":"import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType } from \"../runtime/touch\";\nimport { type ElementStyle, type ContainerStyle, type Classes, type Style, type DrawableStyle, type UINodeChild, type ChildrenFn, type OnLayoutCallback, type BoundingClientRect, type BaseStyle, type AnimateStyle, type Color } from \"./UINode\";\nexport type UIButtonStyle = ElementStyle & DrawableStyle & ContainerStyle & {\n rippleColor?: Color | \"default\";\n};\nexport interface UIButton {\n readonly type: \"button\";\n style: Style<this, UIButtonStyle & {\n onPressed?: UIButtonStyle & {\n duration?: number;\n };\n }>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n onClick(callback: (ev: ClickEventType<UIButton>) => void): this;\n onTouchStart(callback: (ev: TouchStartEventType<UIButton>) => void): this;\n /** Fired when a finger is held on the button past the long-press threshold. The event can\n * `ev.track(...)` the rest of the gesture (like `onTouchStart`), so a hold can flow straight into\n * dragging the element. A handled long-press suppresses the click that would follow the release. */\n onLongPress(callback: (ev: LongPressEventType<UIButton>) => void): this;\n isPressed(): boolean;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIButton(): UIButton;\nexport declare function UIButton(children: UINodeChild[] | ChildrenFn): UIButton;\nexport declare function UIButton(style: UIButtonStyle): UIButton;\nexport declare function UIButton(style: UIButtonStyle, children: UINodeChild[]): UIButton;\n","types/ui/UIInput.d.ts":"import { type ElementStyle, type DrawableStyle, type Classes, type Style, type TextStyle, type Color, type OnLayoutCallback, type BoundingClientRect, type BaseStyle, type AnimateStyle } from \"./UINode\";\ntype InputStyle = {\n placeholder?: string;\n placeholderColor?: Color;\n /**\n * Keyboard hint, NOT a validator — `number` does not block pasted letters; validate in your own\n * onChange. The phone-pad value is `phone` (LeCodes has no `tel`).\n *\n * `date` / `time` are PICKER kinds, not keyboards: the host opens its native picker in the\n * keyboard slot (iOS wheels / browser calendar) and free typing is disabled. `value` is always\n * canonical — `YYYY-MM-DD` for `date`, `HH:MM` (24h) for `time` — while the field displays a\n * localized string; set/compare values in the canonical form only.\n */\n type?: \"text\" | \"password\" | \"search\" | \"phone\" | \"email\" | \"number\" | \"decimal\" | \"url\" | \"date\" | \"time\";\n /**\n * What the layout does while the keyboard is up (decided by the FOCUSED input). `true` (default):\n * the layout viewport shrinks to the area above the keyboard — one relayout. `false`: the keyboard\n * overlays the UI with NO layout recalculation — for chat composers that manage their own inset\n * (pair with `app.keyboardHeight` / the app `\"keyboard\"` event) and full-screen canvases where a\n * reflow is worse than overlap.\n */\n keyboardShrink?: boolean;\n /**\n * Whether a tap on a non-interactive area dismisses the keyboard while THIS input is focused\n * (like `keyboardShrink`, the policy of the focused input). `true` (default): tapping dead\n * space blurs — but a tap on a button or another input NEVER dismisses; the control acts and\n * focus stays. `false`: taps never dismiss — the chat-composer policy. `blur()`, the return\n * key (per `enterKey`), and the platform's own gestures (iOS drag-down over the keyboard)\n * still work in both modes. Scrolling never dismisses the keyboard on any setting.\n */\n keyboardDismiss?: boolean;\n /** Hard cap on the text length — enforced by the host while typing/pasting. */\n maxLength?: number;\n /** Auto-capitalization hint; omitted = platform default. */\n autocapitalize?: \"none\" | \"words\" | \"sentences\" | \"characters\";\n /** Enable/disable the platform autocorrection & suggestions; omitted = platform default. */\n autocorrect?: boolean;\n};\nexport type UIInputStyle = ElementStyle & DrawableStyle & TextStyle & InputStyle;\n/** UIInput-only (a UITextArea's Enter is a newline, period): the return-key label. */\ntype SubmitStyle = {\n /**\n * Return-key label. On submit the keyboard dismisses UNLESS `enterKey` is `\"next\"` — then the\n * app is expected to call `otherInput.focus()` from `onSubmit`, so the keyboard never blinks.\n */\n enterKey?: \"done\" | \"go\" | \"next\" | \"search\" | \"send\";\n};\nexport interface UIInput {\n readonly type: \"input\";\n /**\n * The field's text. Writable at any time — set it BEFORE the screen opens to pre-fill a form\n * (settings, edit-profile); the value is stashed on the node and applied when the host builds\n * it. Reads return the live text while the screen is open, and the last value you set while it\n * isn't. The user's typing is not preserved across close/open (use `keepAlive()` for that).\n */\n value: string;\n style: Style<this, UIInputStyle & SubmitStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n }>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n onChange(callback: (value: string) => void): UIInput;\n onFocus(callback: () => void): UIInput;\n onBlur(callback: () => void): UIInput;\n /** The keyboard's return key was pressed. `value` is the current text. See `enterKey`. */\n onSubmit(callback: (value: string) => void): UIInput;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Focus the input (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this input held it). */\n blur(): void;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport interface UITextArea {\n readonly type: \"textarea\";\n /** The field's text — same contract as {@link UIInput.value}: settable before mount to pre-fill. */\n value: string;\n style: Style<this, UIInputStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n }>;\n onChange(callback: (value: string) => void): UITextArea;\n onFocus(callback: () => void): UITextArea;\n onBlur(callback: () => void): UITextArea;\n /** Focus the text area (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this text area held it). */\n blur(): void;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UIInput(): UIInput;\nexport declare function UIInput(style: UIInputStyle): UIInput;\n/**\n * Multi-line text field. Enter is a newline (submit lives on UIInput / your own button).\n *\n * Auto-grow: with no explicit `height` the field measures its own content and grows line by\n * line — clamp the range with `minHeight` / `maxHeight` (past `maxHeight` the text scrolls\n * inside). A fixed `height` opts out and scrolls internally from the start. Chat composers are\n * the canonical use: a bare textarea in a padded pill, `maxHeight` at ~5 lines.\n */\nexport declare function UITextArea(): UITextArea;\nexport declare function UITextArea(style: UIInputStyle): UITextArea;\nexport {};\n","types/ui/UIText.d.ts":"import { Element, type AnimateStyle, type BaseStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type TextStyle } from \"./UINode\";\nexport type UITextStyle = ElementStyle & TextStyle & DrawableStyle;\nexport interface UIText {\n readonly type: \"text\";\n text: string;\n style: Style<this, UITextStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle & TextStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle & TextStyle>;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class TextElement extends Element<\"text\"> {\n private _text;\n constructor(style: any, text: string | (() => string));\n get text(): string;\n set text(value: string);\n}\nexport declare function UIText(text: string | (() => string)): UIText;\nexport declare function UIText(style: UITextStyle, text: string | (() => string)): UIText;\n","types/ui/UINode.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nexport interface UINode {\n readonly type: string;\n /** Author-given semantic name (a stable selector for tests + AI review feedback). */\n readonly name?: string;\n style: Style<this, any>;\n /** Style-class proxy — read/set/toggle/bind the `$`-classes declared in `.style()`. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport type UINodeChild = UINode | null | undefined | false;\nexport type Color = number | string | null;\nexport type BaseStyle = {\n opacity?: number | `${number}`;\n transform?: string | null;\n backgroundColor?: Color | null;\n bgColor?: Color | null;\n overflow?: \"visible\" | \"hidden\";\n boxSizing?: \"border-box\" | \"content-box\";\n /**\n * Author-given semantic name — a stable selector for tests and for marking elements in the AI\n * code-review feedback loop. NOT a style: it's extracted at construction (never sent to the layout\n * engine) and surfaced on the node + in the renderer's serialized output. Available on every element.\n */\n name?: string;\n};\nexport type DrawableStyle = {\n backgroundImage?: FetchResponse | File | string | null;\n bgGradient?: string;\n backgroundGradient?: string;\n bgImage?: FetchResponse | File | string | null;\n backgroundSize?: \"cover\" | \"contain\" | \"tile\";\n bgSize?: \"cover\" | \"contain\" | \"tile\";\n border?: string | number | null;\n borderWidth?: number;\n borderColor?: Color;\n borderLeft?: string | number | null;\n borderLeftWidth?: number;\n borderLeftColor?: Color;\n borderTop?: string | number | null;\n borderTopWidth?: number;\n borderTopColor?: Color;\n borderRight?: string | number | null;\n borderRightWidth?: number;\n borderRightColor?: Color;\n borderBottom?: string | number | null;\n borderBottomWidth?: number;\n borderBottomColor?: Color;\n borderRadius?: UIValue | string;\n borderTopLeftRadius?: UIValue;\n borderTopRightRadius?: UIValue;\n borderBottomLeftRadius?: UIValue;\n borderBottomRightRadius?: UIValue;\n pointerEvents?: \"all\" | \"none\";\n};\nexport type ContainerStyle = {\n flexDirection?: \"row\" | \"column\";\n justifyContent?: \"flex-start\" | \"center\" | \"flex-end\" | \"space-between\" | \"space-evenly\";\n alignItems?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n gap?: UIValue;\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n};\ntype UIValue = number | `${number}px` | `${number}vw` | `${number}vh` | `${number}vmin` | `${number}vmax` | `${number}em` | `calc(${string})` | `min(${string})` | `max(${string})` | `${string}%` | `clamp(${string})` | `var(--${string})`;\nexport type PaddingStyle = {\n paddingLeft?: UIValue | \"safe-left\" | \"comfort-left\";\n paddingTop?: UIValue | \"safe-top\" | \"comfort-top\";\n paddingRight?: UIValue | \"safe-right\" | \"comfort-right\";\n paddingBottom?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n padding?: UIValue | \"safe-all\" | \"comfort-all\";\n paddingHorizontal?: UIValue | \"comfort-x\";\n paddingVertical?: UIValue | \"comfort-y\";\n pl?: UIValue | \"safe-left\" | \"comfort-left\";\n pt?: UIValue | \"safe-top\" | \"comfort-top\";\n pr?: UIValue | \"safe-right\" | \"comfort-right\";\n pb?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n p?: UIValue | \"safe-all\" | \"comfort-all\";\n px?: UIValue | \"comfort-x\";\n py?: UIValue | \"comfort-y\";\n};\nexport type MarginStyle = {\n marginLeft?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n marginTop?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n marginRight?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n marginBottom?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n margin?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n marginHorizontal?: UIValue | \"auto\" | \"comfort-x\";\n marginVertical?: UIValue | \"auto\" | \"comfort-y\";\n ml?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n mt?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n mr?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n mb?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n m?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n mx?: UIValue | \"auto\" | \"comfort-x\";\n my?: UIValue | \"auto\" | \"comfort-y\";\n};\nexport type PositionStyle = {\n top?: UIValue | `${number}%` | 'safe-top' | 'comfort-top';\n left?: UIValue | `${number}%` | 'safe-left' | 'comfort-left';\n bottom?: UIValue | `${number}%` | 'safe-bottom' | 'comfort-bottom';\n right?: UIValue | `${number}%` | 'safe-right' | 'comfort-right';\n /** Shorthand for all four edges at one value. A longhand (`top`, `left`, …) overrides it. */\n inset?: UIValue | `${number}%` | \"auto\";\n width?: UIValue | `${number}%` | \"auto\";\n height?: UIValue | `${number}%` | \"auto\";\n maxWidth?: UIValue | `${number}%` | \"auto\";\n maxHeight?: UIValue | `${number}%` | \"auto\";\n minWidth?: UIValue | `${number}%` | \"auto\";\n minHeight?: UIValue | `${number}%` | \"auto\";\n};\nexport type ElementStyle = PaddingStyle & MarginStyle & BaseStyle & PositionStyle & {\n position?: \"absolute\" | \"static\" | \"relative\";\n aspectRatio?: number;\n flex?: number | string;\n flexGrow?: number;\n flexShrink?: number;\n flexBase?: UIValue | `${number}%` | \"auto\";\n alignSelf?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n display?: \"none\" | \"flex\";\n};\nexport type TextStyle = {\n textAlign?: \"start\" | \"center\" | \"end\" | \"left\" | \"right\";\n fontFamily?: string;\n fontSize?: UIValue;\n lineHeight?: UIValue | \"normal\";\n fontWeight?: number | `${number}` | \"normal\" | \"bold\";\n fontStyle?: \"normal\" | \"italic\";\n color?: Color;\n textDecoration?: \"underline\" | \"line-through\" | \"none\";\n letterSpacing?: UIValue;\n /** Cap the text at N lines; the box is measured to the clamped height. 0 / omitted = unbounded. */\n lineClamp?: number;\n /** How a clamped line ends. Only meaningful together with `lineClamp`. Default \"ellipsis\". */\n textOverflow?: \"ellipsis\" | \"clip\";\n};\nexport type Reactive<T> = {\n [K in keyof T]: NonNullable<T[K]> extends object ? T[K] : T[K] | (() => T[K]);\n};\nexport type ClassStyles<T> = {\n [key: `$${string}`]: T & {\n duration?: number;\n delay?: number;\n };\n};\n/** Value accepted by a `el.class` write: a boolean sets the class, a `() => boolean` binds it —\n * the class then tracks the signals the function reads (re-evaluated on change). Reads through\n * the proxy always return a plain boolean, never the bound function. */\nexport type ClassValue = boolean | (() => boolean);\n/** The `el.class` proxy — the runtime switch for `$`-class blocks declared in `.style()`\n * (see {@link ClassStyles}). One surface, mirroring `el.style`:\n *\n * ```ts\n * el.class.checked // read: is it active on THIS element? → boolean\n * el.class.checked = true // activate (false deactivates)\n * el.class.open = !el.class.open // toggle\n * el.class.done = () => todo.done.value // reactive binding (signals)\n * el.class({ checked: true, done: () => … }) // batch form — returns the element, chainable\n * ```\n *\n * Class names are accepted with or without the declaration-site `$` prefix. `R` is the concrete\n * node type, so the batch form chains like `.style()`.\n *\n * Typing note: property access is `any` because an index signature can't give reads (`boolean`)\n * and writes ({@link ClassValue}) different types — the batch form is the fully typed path;\n * single-key writes are runtime-coerced with `!!`. */\nexport type Classes<R> = ((classes: Record<string, ClassValue>) => R) & {\n [key: string]: any;\n};\nexport type OrientationStyles<T> = {\n onLandscape?: T;\n onPortrait?: T;\n /** @deprecated Misspelling of `onPortrait` (no second \"r\"). Kept so existing projects and published\n * bundles keep working — hosts still honour it — but new code should use `onPortrait`. */\n onPortait?: T;\n};\nexport type StyleFn<R, T extends object> = ((style: Reactive<T> & OrientationStyles<T> & ClassStyles<T>) => R);\nexport type Style<R, T extends object> = StyleFn<R, T> & T & OrientationStyles<T> & ClassStyles<T>;\nexport type AnimateStyle<R, T extends object> = ((style: T & {\n /** Tween length in **milliseconds** (default 225). */\n duration?: number;\n /** Wait before starting, in **milliseconds**. A looping animation delays once, not per cycle. */\n delay?: number;\n /** Escape hatch: target an internal style layer (the onPressed/orientation mechanism). Not part of the supported surface. */\n layer?: number;\n /** `false` = animate without writing the targets into the element's style (e.g. a fade-out right before `.hide()`). */\n commit?: boolean;\n /** Repeat the animation: `true` = forever, a number = that many cycles. A looping animation is an\n * effect, not a state change — it never commits, and the element ends back at its base style.\n * The loop stops when a later `animateTo`/`animateFrom` runs on the element or it leaves the screen. */\n loop?: boolean | number;\n /** `\"ping-pong\"` (default) animates there and back each cycle — no jump. `\"restart\"` snaps back and\n * replays forward — for full-turn spinners (`transform: \"rotate(360deg)\"`) and shimmers. Only meaningful with `loop`. */\n loopMode?: \"restart\" | \"ping-pong\";\n}) => R);\nexport type AppearStyle<R, T> = (arg: {\n from: T;\n duration?: number;\n delay?: number;\n}) => R;\nexport type DisappearStyle<R, T> = (arg: {\n to: T;\n duration?: number;\n delay?: number;\n}) => R;\nexport type OnLayoutCallback = (layout: {\n left: number;\n top: number;\n width: number;\n height: number;\n}) => void;\nexport type BoundingClientRect = {\n x: number;\n y: number;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n};\nexport declare class Element<T extends string> {\n readonly type: T;\n /** Author-given semantic name (LeCodes `name`) — see BaseStyle.name. Extracted from the options\n * object so it never reaches the layout engine; the renderer reads it off the node. */\n readonly name?: string;\n protected _style: any;\n protected _id: number;\n protected _styleProxy: any;\n protected _appear: any;\n protected _disappear: any;\n constructor(type: T, style: any);\n get style(): any;\n animateTo(style: any): this;\n animateFrom(style: any): this;\n protected _classProxy?: any;\n /** Style-class control — flips the `$`-class blocks declared in `.style()`. One proxy, same\n * contract as `el.style`:\n *\n * - `el.class.checked` — read: is the class active on THIS element? → `boolean`\n * - `el.class.checked = true` / `= false` — activate / deactivate\n * - `el.class.open = !el.class.open` — toggle\n * - `el.class.done = () => todo.done.value` — reactive: the class tracks the signals the\n * function reads; a later write to the same class (plain or function) replaces the binding\n * - `el.class({ checked: true, done: () => … })` — batch form, returns the element (chainable)\n *\n * Names are accepted with or without the leading `$`. A class set on an element CASCADES: it is\n * also active on every descendant (their same-name `$` blocks light up), until the subtree's\n * root — hosted screens/widgets don't inherit. Reads reflect only this element's own classes;\n * there is no opt-out below an active ancestor. `Object.keys(el.class)` lists the active names. */\n get class(): any;\n protected ll?: OnLayoutCallback[];\n onLayout(onLayout: OnLayoutCallback): this;\n /** Absolute rect in device space — the space `UIWidget` positions in and touch events report\n * `clientX`/`clientY` in — including scroll offsets, read live at call time (unlike `onLayout`,\n * whose coordinates are parent-relative and go stale when an ancestor scrolls). `null` before\n * the element is mounted and on hosts without the bridge read. Anchor popovers position-once\n * at open; don't poll per frame. */\n getBoundingClientRect(): BoundingClientRect | null;\n}\nexport type ChildrenFn = () => UINodeChild[];\n/**\n * Compiler-emitted memoized map for reactive children. The chisel `reactiveUi` pass rewrites\n * `list.map(fn)` inside a children binding to `__uiMap(list, fn, \"<file>:<offset>\")`, so unchanged\n * items keep their element identity across re-runs (the reconciler then leaves them mounted).\n * Cache: per (binding owner, call-site slot), keyed by item reference; duplicate items consume\n * cached nodes in order. Outside a children binding, for non-array inputs, or for non-element\n * results it behaves exactly like Array.prototype.map — a wrong rewrite can't change behavior.\n */\nexport declare function __uiMap(list: any, render: (item: any, index: number) => any, slot: string): any[];\nexport declare class ContainerElement<T extends string> extends Element<T> {\n children: any[];\n constructor(type: T, style: any, children: any[] | ChildrenFn);\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodesToDelete: UINode[]): this;\n setContent(children: UINodeChild[] | ChildrenFn): this;\n}\nexport {};\n","types/ui/presentable.d.ts":"/** Built-in transition catalog. `push`/`pop` are the stacked-navigation pair (slide + parallax +\n * dim + edge shadow); the rest are simple two-view moves. */\nexport type TransitionName = \"push\" | \"pop\" | \"slide-from-left\" | \"slide-from-right\" | \"slide-from-top\" | \"slide-from-bottom\" | \"zoom\" | \"zoom-in\" | \"zoom-out\" | \"fade\" | \"none\";\n/** Start/end pose of one side of a custom transition. `x`/`y` are logical px, or a percentage of\n * the destination's size (e.g. `\"100%\"` = one full width to the right). */\nexport type TransitionTransform = {\n x?: number | `${number}%`;\n y?: number | `${number}%`;\n scale?: number;\n opacity?: number;\n};\n/**\n * A custom transition: declarative poses for the incoming/outgoing destination, played natively.\n * Serializes onto each platform's existing transition machinery — there is no per-frame JS.\n * Fields omitted keep the identity pose. Interactive back-swipe stays system-native (push/pop\n * only); a spec applies to non-interactive transitions.\n */\nexport interface TransitionSpec {\n /** Duration in ms (default 300). */\n duration?: number;\n /** cubic-bezier control points (default ease-out). */\n easing?: [number, number, number, number];\n /** The entering destination animates FROM this pose to identity. */\n incoming?: {\n from?: TransitionTransform;\n };\n /** The leaving destination animates from identity TO this pose. */\n outgoing?: {\n to?: TransitionTransform;\n };\n /** Scrim alpha (0..1) painted over whichever destination is underneath. */\n dim?: number;\n /** Which side stacks on top during the animation (default \"incoming\"). On Android, transitions\n * involving a scene always animate the screen side on top — the scene view itself never moves. */\n onTop?: \"incoming\" | \"outgoing\";\n}\nexport type Transition = TransitionName | TransitionSpec;\nexport type PresentOptions = {\n /** Transition to play while this destination replaces the current one (default \"none\" for a\n * direct open(); the Router applies its own defaults — push/pop, and the theme's\n * `replaceTransition` for replace). */\n transition?: Transition;\n};\n/**\n * Anything that can be shown as the app's current destination: a `UIScreen`, a `Scene` /\n * `ARScene`, a `Scene2D`, a `NativeView`, or a `UIVideo`. One Presentable is visible at a time;\n * open it directly (`p.open()` — replaces the current destination, suspending an active Router\n * until `Router.restore()`) or navigate with `Router.push/replace/pop`.\n *\n * `onOpen`/`onClose` are the presentation lifecycle (fired when the destination becomes / stops\n * being the visible one — including router pushes covering it and pops revealing it).\n */\nexport interface Presentable {\n open(options?: PresentOptions): void | this | Promise<void>;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n}\n/** Runtime companion of the `Presentable` interface (declaration merging): the navigation\n * state that isn't tied to the Router. */\nexport declare const Presentable: Readonly<{\n /** The destination visible right now (a `UIScreen`, `Scene`, `Scene2D`, `NativeView` or\n * `UIVideo`), or `null` before the first open. Distinct from `Router.current` — that is the\n * top of the router stack, which stays meaningful while the router is suspended by a direct\n * `open()`; this is what is actually on screen. `UIWidget.show()` attaches to it. */\n readonly current: Presentable | null;\n}>;\n","types/ui/UI.d.ts":"export { UIButton, type UIButtonStyle } from './UIButton';\nexport { UIScreen, type UIScreenStyle } from './UIScreen';\nexport { UISpacer, type UISpacerStyle } from './UISpacer';\nexport { UIText, type UITextStyle } from './UIText';\nexport { registerFont } from './fonts';\nexport { UIImage, type UIImageStyle } from './UIImage';\nexport { UIVideo, type UIVideoStyle } from './UIVideo';\nexport { UIInput, UITextArea, type UIInputStyle } from './UIInput';\nexport { UIWidget, type UIWidgetStyle } from './UIWidget';\nexport { UIModal, type UIModalStyle } from './UIModal';\nexport { UIBottomSheet, type UIBottomSheetStyle } from './UIBottomSheet';\nexport { UIPopover, type UIPopoverStyle, type UIPopoverAnchor } from './UIPopover';\nexport { UIRow, UIColumn, UIBox, type UIContainerStyle } from './UIContainer';\nexport { UIScrollable, type UIScrollableStyle } from './UIScrollable';\nexport { UIPager, type UIPagerStyle } from './UIPager';\nexport { UIVirtualizedList } from './UIVirtualizedList';\nexport { Router } from './router';\nexport { NativeView, type UINativeViewStyle } from './NativeView';\nexport { Presentable } from './presentable';\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from './presentable';\nexport { __uiMap } from './UINode';\n","types/ui/UIScrollable.d.ts":"import type { UIContainerStyle } from \"./UIContainer\";\nimport { type Classes, type Style, type AnimateStyle, type UINodeChild, type ChildrenFn, type OnLayoutCallback, type BoundingClientRect, type Color } from \"./UINode\";\nexport type ScrollStyle = {\n showScrollbar?: boolean;\n overscrollMode?: \"none\" | \"absorb\" | \"default\";\n refreshControlColor?: Color;\n keyboardDismissMode?: \"interactive\" | \"scroll\" | \"none\";\n snap?: \"none\" | \"start\" | \"center\" | \"end\";\n};\nexport type UIScrollableStyle = UIContainerStyle & ScrollStyle & {\n scrollDirection?: \"horizontal\" | \"vertical\";\n};\nexport interface UIScrollable {\n readonly type: \"scrollable\";\n style: Style<this, UIScrollableStyle>;\n animateTo: AnimateStyle<this, UIScrollableStyle>;\n animateFrom: AnimateStyle<this, UIScrollableStyle>;\n append(...nodes: UINodeChild[]): UIScrollable;\n insert(index: number, ...nodes: UINodeChild[]): UIScrollable;\n remove(...nodes: UINodeChild[]): UIScrollable;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n onScroll(callback: (scrollPosition: number) => void): UIScrollable;\n onScrollRelease(callback: () => void): UIScrollable;\n onOverscroll(callback: (delta: number) => void): UIScrollable;\n /** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the\n * node mounts (hosts read it at creation). Vertical only; native hosts — no-op on web. */\n onRefresh(callback: () => void | Promise<void>): UIScrollable;\n readonly children: UINodeChild[];\n}\nexport declare function UIScrollable(): UIScrollable;\nexport declare function UIScrollable(children: UINodeChild[] | ChildrenFn): UIScrollable;\nexport declare function UIScrollable(style: UIScrollableStyle): UIScrollable;\nexport declare function UIScrollable(style: UIScrollableStyle, children: UINodeChild[]): UIScrollable;\n","types/ui/UIVideo.d.ts":"import type { VideoPlayer } from \"../runtime/media\";\nimport { type PresentOptions } from \"./presentable\";\nimport { type AnimateStyle, type BaseStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style } from \"./UINode\";\nexport type UIVideoStyle = ElementStyle & DrawableStyle & {\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n};\nexport interface UIVideo {\n readonly type: \"video\";\n player: VideoPlayer;\n style: Style<this, UIVideoStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Show fullscreen as the current destination. Promotion: if this video is mounted in a screen,\n * the SAME native player moves fullscreen — playback uninterrupted; a pop moves it back. */\n open(options?: PresentOptions): void;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UIVideo(player: VideoPlayer): UIVideo;\nexport declare function UIVideo(style: UIVideoStyle, player: VideoPlayer): UIVideo;\n","types/ui/UIWidget.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { Presentable } from \"./presentable\";\nimport { ContainerElement, type AnimateStyle, type BaseStyle, type Color, type ContainerStyle, type DrawableStyle, type OnLayoutCallback, type BoundingClientRect, type PaddingStyle, type PositionStyle, type Classes, type Style, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIWidgetStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle & PositionStyle & {\n overlayColor?: Color | null;\n};\nexport interface UIWidget {\n readonly type: \"widget\";\n style: Style<this, UIWidgetStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n }>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n }>;\n /**\n * Attach this widget to a destination (a `Scene`, a `UIScreen`, …): the widget lives on that\n * page's layer — it shows/hides with the page and rides its transition, and a screen pushed\n * on top covers it (a scene HUD behaves like part of the scene). Sticky until `attachTo(null)`\n * (= back to a global overlay). Set it while the widget is hidden. The widget is always its own\n * overlay root mounted into the owner's page view — it never becomes a child of the owner, so it\n * stays topmost and its updates never trigger the owner's relayout. Works with a `UIScreen` that\n * is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe.\n */\n attachTo(owner: Presentable | null): this;\n /** Show the widget. By default it is a global overlay above every destination — it stays\n * visible across navigation until `hide()` (dialogs, mini-player, global loader). If the\n * widget was attached via `attachTo(owner)`, it mounts on that page's layer instead and is\n * only visible while the owner is presented. */\n show(): void;\n hide(): void;\n readonly isShow: boolean;\n append(...nodes: UINodeChild[]): UIWidget;\n insert(index: number, ...nodes: UINodeChild[]): UIWidget;\n remove(...nodes: UINodeChild[]): UIWidget;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n readonly children: UINodeChild[];\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n onTouchStart(callback: (ev: TouchStartEvent<UIWidget>) => void): this;\n onOverlayTap(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class WidgetElement extends ContainerElement<\"widget\"> {\n scrollable: false;\n _owner?: Presentable;\n constructor(type: \"widget\", style: UIWidgetStyle, children: UINodeChild[] | ChildrenFn);\n attachTo(owner: Presentable | null): this;\n show(): void;\n hide(): void;\n get isShow(): boolean;\n _interactive: boolean;\n readonly touchStartListeners: any[];\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n readonly otl: (() => void)[];\n onOverlayTap(callback: () => void): this;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\nexport declare function UIWidget(): UIWidget;\nexport declare function UIWidget(children: UINodeChild[] | ChildrenFn): UIWidget;\nexport declare function UIWidget(style: UIWidgetStyle): UIWidget;\nexport declare function UIWidget(style: UIWidgetStyle, children: UINodeChild[]): UIWidget;\n","types/ui/router.d.ts":"import { Presentable, type Transition } from \"./presentable\";\ntype RouterOptions = {\n showDefaultBackButton?: boolean;\n};\ntype NavigateOptions = {\n /** Transition to play. Defaults: `\"push\"` for push, `\"pop\"` for pop; replace follows the\n * theme's `replaceTransition` (`\"none\"` out of the box). */\n transition?: Transition;\n};\ntype Router = {\n get current(): Presentable;\n init(homePage: Presentable, opts?: RouterOptions): void;\n /** Push a destination onto the stack — a `UIScreen`, a `Scene`, a `Scene2D`, a `NativeView`,\n * or a `UIVideo`. The back gesture/button pops it. Destinations with async preparation\n * (`ARScene`: camera permission + warm render) return a Promise — the current page stays\n * visible until they're ready, and a rejection (permission denied / superseded) leaves the\n * stack untouched. */\n push(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n replace(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n pop(to?: number, opts?: NavigateOptions): void;\n hide(): void;\n restore(): void;\n addEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n removeEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n};\nexport declare const Router: Router;\nexport {};\n","types/ui/UIPager.d.ts":"import { ContainerElement, type AnimateStyle, type BaseStyle, type ChildrenFn, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type UINodeChild } from \"./UINode\";\nimport type { UIScreen } from \"./UIScreen\";\n/** Styles a pager accepts — layout box + drawable (background, borders, …). Pages style\n * themselves; the pager only owns its own slot. */\nexport type UIPagerStyle = ElementStyle & DrawableStyle;\n/**\n * The screen-navigation element: sibling **tabs** that swipe natively side to side, each with its\n * own navigation **stack**. `push` opens a screen on top of the current tab (within the pager);\n * `pop` / the native edge back-swipe unwinds it. A one-tab pager is a plain navigation stack.\n *\n * ```ts\n * const pager = UIPager([ HomeScreen(), ProfileScreen() ]) // two tabs, side by side\n * Router.init(UIScreen([ pager.style({ flexGrow: 1 }), tabBar ]))\n *\n * // from anywhere inside a hosted screen — no reference threading:\n * UIPager.push(PostScreen(id))\n * ```\n *\n * To open something over *everything* (above bars, above the pager), use `Router.push` instead.\n */\nexport interface UIPager {\n readonly type: \"pager\";\n style: Style<this, UIPagerStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Replace the pager's tabs — one screen per tab, in order. Every tab becomes a fresh\n * one-screen stack (pushed screens are dropped) and the selection is clamped into range;\n * screens that were already tabs keep their state. Pass a function for reactive tabs. */\n setContent(tabs: UIScreen[] | (() => UIScreen[])): this;\n /** Switch to tab `index`. **Instant by default** — the tab-bar convention (tabs are parallel\n * modes, not neighbors); pass `animated: true` for the direction-aware slide of top-tab /\n * pager UIs. Out-of-range and same-index calls are no-ops. Tabs keep their stacks: selecting\n * away and back restores the tab exactly where it was, pushed screens included. */\n select(index: number, animated?: boolean): this;\n /** The selected tab index (0-based). */\n readonly index: number;\n /** Fires when the selected tab changes and has settled — a user swipe or `select()`. */\n onSelect(callback: (index: number) => void): this;\n /** Push `screen` on top of the **current tab** — slides in natively; the edge back-swipe (or\n * `pop()`) removes it. Other tabs are unaffected. */\n push(screen: UIScreen): this;\n /** Pop the current tab's top screen (no-op at the tab root — the root never pops). The\n * programmatic twin of the native edge back-swipe. */\n pop(): this;\n /** Unwind the current tab back to its root screen in one step. */\n popToRoot(): this;\n /** Swap the current tab's top screen for `screen` without growing the stack (at depth 1 this\n * swaps the tab's root). */\n replace(screen: UIScreen): this;\n /** The current tab's screens, root → top (read-only snapshot). */\n readonly stack: UIScreen[];\n /** The current tab's stack depth — 1 means only the root. While `depth > 1`, swiping between\n * tabs is disabled (the horizontal gesture belongs to the back-swipe). */\n readonly depth: number;\n /** Fires when the current tab's depth changes — push, pop, replace, or a back-swipe. */\n onChange(callback: (depth: number) => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class PagerElement extends ContainerElement<\"pager\"> {\n /** Per-tab stack lengths — partitions the flat tab-major `children`. Named `_*` so chisel\n * keeps it (the host reads it live). */\n _lens: number[];\n /** Selected tab. */\n _index: number;\n _openCount: number;\n private scl;\n private ncl;\n constructor(style: UIPagerStyle | null, tabs: UIScreen[]);\n /** Start offset of tab `i`'s segment in the flat `children`. */\n private _offset;\n get index(): number;\n get stack(): UIScreen[];\n get depth(): number;\n onSelect(callback: (index: number) => void): this;\n onChange(callback: (depth: number) => void): this;\n select(index: number, animated?: boolean): this;\n push(screen: UIScreen): this;\n pop(): this;\n popToRoot(): this;\n replace(screen: UIScreen): this;\n private _rebuild;\n setContent(children: UINodeChild[] | ChildrenFn): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodesToDelete: UIScreen[]): this;\n _reconcile(next: UINodeChild[]): void;\n _hostDidSelect(index: number): void;\n _hostDidPop(depth: number): void;\n private _emitSelect;\n private _emitChange;\n private _track;\n _activate(): void;\n _deactivate(): void;\n}\n/** Callable factory + ambient statics. The name `UIPager` is a value (this factory) and a type\n * (the instance interface above) — a standard value/type merge. */\ninterface UIPagerConstructor {\n /** One tab — a plain navigation stack rooted at `root` (push/pop, no tab swiping). */\n (root: UIScreen): UIPager;\n /** Sibling tabs, one per screen, in order — swipe (or `select`) between them. Tabs are fixed\n * at construction; each starts as its own one-screen stack. */\n (tabs: UIScreen[]): UIPager;\n /** Styled pager + content (a single root screen or an array of tab screens). */\n (style: UIPagerStyle, content: UIScreen | UIScreen[]): UIPager;\n /** The pager that owns the currently visible screen, or `null` when the visible screen isn't\n * hosted by one. With pagers nested inside pages, resolves to the **innermost** — so ambient\n * calls act on the pager the user is actually looking at. */\n readonly current: UIPager | null;\n /** `UIPager.current.push(screen)` — push onto the pager owning the visible screen, no\n * reference threading. No-op with a console warning when there is no current pager. */\n push(screen: UIScreen): void;\n /** `UIPager.current.pop()` — pop the visible pager's current tab (no-op at the tab root, or\n * with a warning when there is no current pager). */\n pop(): void;\n /** `UIPager.current.popToRoot()` — unwind the visible pager's current tab to its root. */\n popToRoot(): void;\n}\n/**\n * Create a pager — THE screen-navigation element: an array of screens becomes swipeable sibling\n * tabs, a single screen becomes a plain stack. Navigate within it via `pager.push/pop/replace`\n * (per-tab) and `pager.select(i)` (between tabs), or from any child screen via the ambient\n * `UIPager.push` / `UIPager.pop` / `UIPager.current`. Pages are full `UIScreen`s (own\n * `onOpen`/`onClose`); give the pager `flexGrow: 1` or a size so it doesn't\n * collapse. `Router` stays the way to open a destination ON TOP of the pager.\n */\nexport declare const UIPager: UIPagerConstructor;\nexport {};\n","types/ui/fonts.d.ts":"type FontOptions = {\n weight?: number;\n style?: \"normal\" | \"italic\";\n};\nexport declare function registerFont(fontFamily: string, url: string, options?: FontOptions): Promise<void>;\nexport {};\n","types/ui/UIContainer.d.ts":"import { type AnimateStyle, type ChildrenFn, type ContainerStyle, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type UINodeChild } from \"./UINode\";\nexport type UIContainerStyle = ElementStyle & DrawableStyle & ContainerStyle;\nexport interface UIColumn {\n readonly type: \"column\";\n style: Style<this, UIContainerStyle>;\n animateTo: AnimateStyle<this, UIContainerStyle>;\n animateFrom: AnimateStyle<this, UIContainerStyle>;\n append(...nodes: UINodeChild[]): UIColumn;\n insert(index: number, ...nodes: UINodeChild[]): UIColumn;\n remove(...nodes: UINodeChild[]): UIColumn;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIColumn(): UIColumn;\nexport declare function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn;\nexport declare function UIColumn(style: UIContainerStyle): UIColumn;\nexport declare function UIColumn(style: UIContainerStyle, children: UINodeChild[]): UIColumn;\nexport interface UIRow {\n readonly type: \"row\";\n style: Style<this, UIContainerStyle>;\n animateTo: AnimateStyle<this, UIContainerStyle>;\n animateFrom: AnimateStyle<this, UIContainerStyle>;\n append(...nodes: UINodeChild[]): UIRow;\n insert(index: number, ...nodes: UINodeChild[]): UIRow;\n remove(...nodes: UINodeChild[]): UIRow;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIRow(): UIRow;\nexport declare function UIRow(children: UINodeChild[] | ChildrenFn): UIRow;\nexport declare function UIRow(style: UIContainerStyle): UIRow;\nexport declare function UIRow(style: UIContainerStyle, children: UINodeChild[]): UIRow;\nexport interface UIBox {\n readonly type: \"box\";\n style: Style<this, UIContainerStyle>;\n animateTo: AnimateStyle<this, UIContainerStyle>;\n animateFrom: AnimateStyle<this, UIContainerStyle>;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n readonly children: UINodeChild[];\n}\nexport declare function UIBox(): UIBox;\nexport declare function UIBox(children: UINodeChild[] | ChildrenFn): UIBox;\nexport declare function UIBox(style: UIContainerStyle): UIBox;\nexport declare function UIBox(style: UIContainerStyle, children: UINodeChild[]): UIBox;\n","types/ui/UIVirtualizedList.d.ts":"import { Element, type Color, type DrawableStyle, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style, type UINodeChild } from \"./UINode\";\nexport type UIVirtualizedListStyle = DrawableStyle & ElementStyle & {\n refreshControlColor?: Color;\n};\nexport interface VListConfig<T> {\n /** Стабильный уникальный ключ айтема */\n keyOf: (item: T) => string;\n /** Фабрика поддерева. Вызывается при входе айтема в окно; поддерево живёт до выхода из окна */\n render: (item: T) => UINodeChild;\n /**\n * Оценка высоты (px) до первого измерения. Число — или функция от айтема,\n * например для чата: msg => 40 + Math.ceil(msg.text.length / 35) * 20\n * Вычисляется один раз при добавлении айтема, в нативку уходит готовое число.\n */\n estimatedHeight: number | ((item: T) => number);\n /** px вокруг вьюпорта, которые держим смонтированными. Default: высота вьюпорта */\n overscan?: number;\n /** Чат-режим: первый layout проскроллен в конец, append при положении внизу автоскроллит */\n inverted?: boolean;\n}\nexport interface UIVirtualizedList<T = unknown> {\n readonly type: \"vlist\";\n style: Style<this, UIVirtualizedListStyle>;\n /** Полная замена данных. Нативка сама размонтирует исчезнувшие ключи через _syncWindow */\n setData(items: T[]): this;\n append(...items: T[]): this;\n /** Вставка в начало БЕЗ прыжка скролла (компенсация на стороне нативки) */\n prepend(...items: T[]): this;\n /** Обновить айтемы с теми же ключами: re-render, если смонтированы. Высота в кэше сохраняется до повторного измерения */\n update(...items: T[]): this;\n removeByKey(...keys: string[]): this;\n readonly itemCount: number;\n getItem(key: string): T | undefined;\n scrollTo(offset: number, animated?: boolean): void;\n scrollToKey(key: string, animated?: boolean): void;\n scrollToEnd(animated?: boolean): void;\n onScroll(callback: (scrollPosition: number) => void): this;\n /** Pull-to-refresh: спиннер держится, пока не разрешится промис. Навесить ДО маунта\n * (нативка читает при создании ноды). Только native-хосты; на вебе no-op. */\n onRefresh(callback: () => void | Promise<void>): this;\n /** Порог в px от нижнего края контента. Срабатывает один раз до ухода от края (защёлка в нативке) */\n onEndReached(thresholdPx: number, callback: () => void): this;\n /** Порог от верхнего края — подгрузка истории в чате */\n onStartReached(thresholdPx: number, callback: () => void): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare class VListElement<T> extends Element<\"vlist\"> implements UIVirtualizedList<T> {\n _overscan: number;\n _inverted: boolean;\n _keys: string[];\n _estimates: number[];\n _endThreshold: number;\n _startThreshold: number;\n protected sl: ((scrollPosition: number) => void)[];\n protected erl: (() => void)[];\n protected strl: (() => void)[];\n private items;\n private mounted;\n private keyOf;\n private renderItem;\n private estimate;\n constructor(config: VListConfig<T>);\n private get isAttached();\n private register;\n setData(items: T[]): this;\n append(...items: T[]): this;\n prepend(...items: T[]): this;\n update(...items: T[]): this;\n removeByKey(...keys: string[]): this;\n get itemCount(): number;\n getItem(key: string): T | undefined;\n scrollTo(offset: number, animated?: boolean): void;\n scrollToKey(key: string, animated?: boolean): void;\n scrollToEnd(animated?: boolean): void;\n onScroll(callback: (scrollPosition: number) => void): this;\n _refreshCallback: any;\n onRefresh(callback: () => void | Promise<void>): this;\n onEndReached(thresholdPx: number, callback: () => void): this;\n onStartReached(thresholdPx: number, callback: () => void): this;\n /**\n * Единственный колбэк из нативки (через jsPtr, как у button).\n * Вызывается ТОЛЬКО когда окно пересекло границу — не на каждый кадр скролла.\n * Порядок: сначала unmount (нативка уже снесла поддеревья и обнулила _id,\n * здесь только чистим JS-ссылки), потом mount.\n */\n _syncWindow(unmountKeys: string[], mountKeys: string[]): void;\n}\nexport declare function UIVirtualizedList<T>(config: VListConfig<T>): UIVirtualizedList<T>;\n","types/ui/UIImage.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue as SvgSource } from \"../runtime/misc\";\nimport type { File } from \"../runtime/fetch\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { type AnimateStyle, type Color, type ElementStyle, type OnLayoutCallback, type BoundingClientRect, type Classes, type Style } from \"./UINode\";\nexport type UIImageStyle = ElementStyle & {\n borderRadius?: number;\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n tintColor?: Color;\n};\n/** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture — see\n * docs/canvas-contract.md (\"Pending\"). */\nexport type CanvasImageSource = {\n canvasSurface: number;\n};\n/** Accepted image sources. A Canvas is baked to a surface marker on assign. */\nexport type ImageSource = string | FetchResponse | File | SvgSource | Canvas;\n/** The stored/resolved image source (a Canvas is resolved to a surface marker). */\nexport type ResolvedImageSource = string | FetchResponse | File | SvgSource | CanvasImageSource;\nexport interface UIImage {\n readonly type: \"image\";\n get src(): ResolvedImageSource;\n set src(value: ImageSource);\n style: Style<this, UIImageStyle>;\n animateTo: AnimateStyle<this, UIImageStyle>;\n animateFrom: AnimateStyle<this, UIImageStyle>;\n setSourceRect(x: number, y: number, w: number, h: number): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UIImage(src: ImageSource): UIImage;\nexport declare function UIImage(style: UIImageStyle, src: ImageSource): UIImage;\n","types/ui/UIPopover.d.ts":"import { ModalElement, type UIModal, type UIModalStyle } from \"./UIModal\";\nimport type { BoundingClientRect, ChildrenFn, UINodeChild } from \"./UINode\";\nexport type UIPopoverStyle = UIModalStyle;\n/** What a popover can anchor to: any element (it reads `getBoundingClientRect()`), or a raw\n * `{x, y}` point — a long-press context menu anchors to the touch position. */\nexport type UIPopoverAnchor = {\n getBoundingClientRect(): BoundingClientRect | null;\n} | {\n x: number;\n y: number;\n};\n/**\n * An anchored menu: a `UIModal` whose scrim is transparent (invisible but still intercepting —\n * an outside tap dismisses, and nothing underneath can scroll while it's open) and whose\n * position comes from the anchor passed to `show(anchor)`: below the anchor's left edge,\n * flipped above when there's no room, clamped into the viewport. Position is computed once per\n * show — anchored popovers don't follow their anchor. Backs dropdowns, context menus, and\n * tooltips; create it **once** at module scope and reuse it.\n */\nexport interface UIPopover extends UIModal {\n /** Position next to `anchor` (an element or an `{x, y}` point), attach to\n * `Presentable.current` (unless an owner was set via `attachTo`), and play the entrance\n * transition. Without an anchor the popover shows wherever its own style puts it. */\n show(anchor?: UIPopoverAnchor): void;\n}\nexport declare class PopoverElement extends ModalElement {\n private _anchorRect?;\n private _placedLeft?;\n private _placedTop?;\n constructor(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn);\n show(anchor?: UIPopoverAnchor): void;\n private _place;\n}\nexport declare function UIPopover(): UIPopover;\nexport declare function UIPopover(children: UINodeChild[] | ChildrenFn): UIPopover;\nexport declare function UIPopover(style: UIPopoverStyle): UIPopover;\nexport declare function UIPopover(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn): UIPopover;\n","types/ui/UISpacer.d.ts":"import { type ElementStyle, type Classes, type Style } from \"./UINode\";\nexport type UISpacerStyle = ElementStyle;\nexport interface UISpacer {\n readonly type: \"spacer\";\n style: Style<this, UISpacerStyle>;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\nexport declare function UISpacer(): UISpacer;\nexport declare function UISpacer(style: UISpacerStyle): UISpacer;\n","types/ui/UIScreen.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { type PresentOptions } from \"./presentable\";\nimport { ContainerElement, type AnimateStyle, type BaseStyle, type ContainerStyle, type DrawableStyle, type OnLayoutCallback, type BoundingClientRect, type PaddingStyle, type Classes, type Style, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIScreenStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle;\nexport interface UIScreen {\n readonly type: \"screen\";\n style: Style<this, UIScreenStyle>;\n animateTo: AnimateStyle<this, DrawableStyle & BaseStyle>;\n animateFrom: AnimateStyle<this, DrawableStyle & BaseStyle>;\n /** Show this screen as the current destination (replaces whatever is visible — a screen, a\n * scene, a native view — suspending an active Router until `Router.restore()`). */\n open(options?: PresentOptions): void;\n close(): void;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodes: UINodeChild[]): this;\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n readonly children: UINodeChild[];\n onBackPressed(callback: () => void): this;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n /**\n * Keep this screen's built native tree alive when a host detaches it: instead of being destroyed,\n * its views + layout + live state (scroll position, input text) are retained, so re-hosting the\n * SAME screen object restores it in place rather than rebuilding. `onClose`/`onOpen` still fire on\n * detach/re-attach. You own the lifetime — a kept tree is freed only by `dispose()` or when the\n * project unloads. (Native-only today; web rebuilds.)\n */\n keepAlive(enabled?: boolean): this;\n /** Free a `keepAlive()` screen's retained tree now. No-op unless it's currently detached-and-kept. */\n dispose(): this;\n onLayout(onLayout: OnLayoutCallback): this;\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;\n}\nexport declare class ScreenElement extends ContainerElement<\"screen\"> {\n open(options?: PresentOptions): void;\n close(): void;\n protected ol: (() => void)[];\n onOpen(callback: () => void): this;\n protected cl: (() => void)[];\n onClose(callback: () => void): this;\n _keepAlive: boolean;\n keepAlive(enabled?: boolean): this;\n dispose(): this;\n readonly touchStartListeners: any[];\n _interactive: boolean;\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\nexport declare function UIScreen(): UIScreen;\nexport declare function UIScreen(children: UINodeChild[] | ChildrenFn): UIScreen;\nexport declare function UIScreen(style: UIScreenStyle): UIScreen;\nexport declare function UIScreen(style: UIScreenStyle, children: UINodeChild[]): UIScreen;\n","types/animate/animate.d.ts":"type mat4 = Float32Array | number[];\ntype quat = Float32Array | number[];\ntype vec2 = Float32Array | number[];\ntype vec3 = Float32Array | number[];\nimport type { Easing } from \"./easings\";\ntype AnimateProps = number | string | vec2 | vec3 | quat;\nexport type AnimateOptions<T> = {\n from: T;\n to: T;\n duration: number;\n onUpdate(val: T): void;\n onComplete?(): void;\n easing?: Easing;\n};\nexport declare const animate: <T extends AnimateProps>(options: AnimateOptions<T>) => number;\nexport declare const stopAnimation: (id: number) => void;\nexport declare const pauseAnimation: (id: number) => void;\nexport declare const resumeAnimation: (id: number) => void;\nexport declare const animateMat4: (options: AnimateOptions<mat4>) => number;\nexport {};\n","types/animate/bezier.d.ts":"import type { Easing } from \"./easings\";\nexport declare function cubicBezier(mX1: number, mY1: number, mX2: number, mY2: number): Easing;\n","types/animate/easings.d.ts":"export type Easing = (v: number) => number;\nexport type EasingModifier = (easing: Easing) => Easing;\nexport declare function linear(p: number): number;\nexport declare function bounceOut(p: number): number;\nexport declare function bounceInOut(p: number): number;\nexport declare function reverseEasing(easing: Easing): Easing;\nexport declare function mirrorEasing(easing: Easing): Easing;\nexport declare function createExpoIn(power: number): Easing;\nexport declare function createBackIn(power: number): Easing;\nexport declare function createAnticipate(power: number): Easing;\nexport declare function bounceIn(p: number): number;\nexport declare function easeIn(p: number): number;\nexport declare function easeOut(p: number): number;\nexport declare function easeInOut(p: number): number;\nexport declare function circIn(p: number): number;\nexport declare function circOut(p: number): number;\nexport declare function circInOut(p: number): number;\nexport declare function backIn(p: number): number;\nexport declare function backOut(p: number): number;\nexport declare function backInOut(p: number): number;\nexport declare function anticipate(p: number): number;\n","types/core/color.d.ts":"export type ColorInput = string | number | readonly [number, number, number] | readonly [number, number, number, number];\nexport declare const Color: {\n /** [r,g,b] in 0..1 — for the 2D engine's float color setters. */\n toRgb01(c: ColorInput): [number, number, number];\n /** [r,g,b,a] in 0..1. */\n toRgba01(c: ColorInput): [number, number, number, number];\n /** 0xRRGGBB packed int — for the 3D engine's color uniforms / skybox. */\n toPackedRgb(c: ColorInput): number;\n /** 0xRRGGBBAA packed int (unsigned). */\n toPackedRgba(c: ColorInput): number;\n /** '#rrggbb' (or '#rrggbbaa' when alpha < 1) — for the 3D material color uniforms. */\n toHexString(c: ColorInput): string;\n};\n","types/core/Aspect.d.ts":"import { Emitter, type EventMap } from \"./events\";\nimport type { InspectorUI } from \"./InspectorUI\";\nimport type { Node } from \"../gl/Node\";\n/** The class object of an aspect — accepted even when its constructor is protected/abstract. */\nexport type AspectCtor<A extends Aspect<any, any>> = abstract new () => A;\n/** The accessor name carried in the aspect's generic. */\nexport type KeyOf<A> = A extends Aspect<infer K, any> ? K : never;\n/** The node kind an aspect targets. */\nexport type TargetOf<A> = A extends Aspect<any, infer P> ? P : never;\n/** `{ name: Aspect }` — the field an aspect contributes to its node. */\nexport type FieldOf<A extends Aspect<any, any>> = {\n [P in KeyOf<A>]: A;\n};\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\n/**\n * A variable typed as a node KNOWN to carry the given aspect(s). Union, not a tuple — reads as\n * English and mirrors the runtime guard `node.has(Health)`:\n * let boss: With<Sprite, Health | Physics>\n */\nexport type With<N, A extends Aspect<any, any>> = N & UnionToIntersection<A extends any ? FieldOf<A> : never>;\n/**\n * Base for anything that can carry aspects. Extends Emitter, so node kinds get events too. Provides\n * the four verbs; the named accessor (node.physics, node.health, …) is set as an own property at\n * attach time, keyed by the aspect class's runtime `aspect` name.\n */\nexport declare abstract class AspectHost<E extends EventMap = EventMap> extends Emitter<E> {\n /** Attach (and configure) an aspect, or reconfigure it if already present. Returns the node typed\n * as now-having that aspect (so no guard/`?.` is needed afterwards). Rejects a wrong target node. */\n aspect<Self extends TargetOf<A>, A extends Aspect<any, any>>(this: Self, ctor: AspectCtor<A>, opts?: Partial<A>): Self & FieldOf<A>;\n /** Safe access — undefined if the aspect isn't attached. */\n get<A extends Aspect<any, any>>(ctor: AspectCtor<A>): A | undefined;\n /** Existence check AND type guard: inside `if (node.has(Physics))`, `node.physics` is present. */\n has<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this is this & FieldOf<A>;\n /** Detach an aspect (runs its onDetach). Named `removeAspect` so it never collides with the\n * child-management `add`/`remove` semantics some node kinds expose. */\n removeAspect<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this;\n}\n/**\n * Base for everything you attach. `K` = accessor name (extracted by chisel for the runtime). `P` =\n * the target node kind: `this.node` is typed to it, AND attaching to a wrong node is a compile error.\n * Initialize in `onAttach` (the node is set by then) — not a constructor; aspects are created by the\n * engine via `node.aspect()`, never `new`.\n */\nexport declare abstract class Aspect<K extends string, P = Node> {\n /**\n * Opt this aspect class into EDITOR-RUN mode (generators): while a scene is edited, the scene\n * loader constructs the instance (refs resolved, `node`/`generated` set — never `onAttach`) and\n * calls `rebuild()` — again on inspector prop edits and when a `ref()`-referenced node moves.\n * `static editor = { rebuild: true }`.\n */\n static editor?: {\n rebuild?: boolean;\n };\n /**\n * Custom inspector card for this aspect in the scene editor (immediate-mode — see\n * core/InspectorUI.ts): re-runs on every edit/event and emits a widget list. Without it, the\n * editor shows the inferred fields; `ui.auto()` emits those same fields, so a custom inspector\n * usually starts with `ui.auto()` and appends status lines / buttons / dynamic dropdowns:\n *\n * static inspector(ui: InspectorUI, self: MyAspect) {\n * ui.auto()\n * if (ui.button('Randomize')) self.rebuild()\n * }\n */\n static inspector?: (ui: InspectorUI, aspect: any) => void;\n /** The node this aspect is attached to (set at attach time). */\n readonly node: P;\n /**\n * GENERATOR aspects (`static editor = { rebuild: true }`, attached through a scene file): a\n * scene-added container child for the aspect's generated output — `rebuild()` clears and refills\n * it. Provided by the scene loader before `onAttach`/`rebuild` run; nodes `add()`ed to it join\n * the scene's draw set automatically (membership is separate from parenting). Undefined for\n * aspects attached by hand outside scene files. See docs/3d/scene-files.md.\n */\n readonly generated: Node & {\n clear(): void;\n };\n onAttach?(): void;\n onDetach?(): void;\n /**\n * GENERATOR aspects: (re)build the derived output under `this.generated` — must be idempotent\n * (clear, then create). Call it from `onAttach()` for play mode; a class opting in with\n * `static editor = { rebuild: true }` ALSO runs it while a scene is being edited: once at load,\n * and again whenever an inspector prop changes or a `ref()`-referenced node moves.\n */\n rebuild?(): void;\n /**\n * Called every frame while attached (dt = seconds since the last frame). Render-synced: runs in the\n * LATE phase by default — after the physics step + transform sync, right before the frame draws — so\n * reads of `node.worldPosition` are the final drawn position (cameras/followers have no 1-frame lag).\n * Set `updateBeforePhysics = true` (an instance field) to run in the EARLY phase (before the step)\n * instead — for aspects that WRITE velocity/force/kinematic transforms and want the same frame's\n * step to consume them. Cameras/followers READ, so they stay in the default LATE phase.\n */\n update?(dt: number): void;\n /** Run update(dt) in the EARLY phase (before the physics step) rather than the default LATE phase.\n * An instance field (like `updateWhenVisible`) — set it as a class field: `updateBeforePhysics = true`.\n * Use only when you FEED the simulation (velocity/force/kinematic transform). Read once, at attach. */\n updateBeforePhysics: boolean;\n /** Tick order within a phase — ascending; default 0, ties keep attach order. Read once, at attach. */\n order: number;\n /** Opt-in: only run update(dt) while the node is on-screen. NOOP for now — visibility culling isn't\n * wired yet, so every updater ticks regardless; declared so aspects can opt in ahead of it. */\n updateWhenVisible: boolean;\n}\nexport {};\n","types/core/registry.d.ts":"export declare class Registry<T> {\n private map;\n set(id: number, value: T): void;\n get(id: number): T | undefined;\n delete(id: number): void;\n has(id: number): boolean;\n}\n","types/core/events.d.ts":"export type EventMap = Record<string, (...args: any[]) => void>;\nexport declare class Emitter<E extends EventMap> {\n private _listeners;\n addEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n removeEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n /** Fire all listeners on a channel. Protected: only the owning class emits. */\n protected dispatch<K extends keyof E>(channel: K, ...args: Parameters<E[K]>): void;\n protected hasListeners<K extends keyof E>(channel: K): boolean;\n /** Drop every listener on every channel (used when the owning object is disposed). */\n protected clearListeners(): void;\n}\n","types/core/InspectorUI.d.ts":"import type { FieldEditor } from \"./fields\";\n/** One user interaction coming back from the editor panel: the widget's id (+ value for fields). */\nexport type InspectorEvent = {\n id: string;\n value?: unknown;\n};\nexport type InspectorFieldWidget = {\n kind: \"field\";\n id: string;\n /** The bound key — an aspect field (doc-bound) or an editor-state key. */\n key: string;\n label: string;\n editor: FieldEditor | undefined;\n value: unknown;\n /** True = persisted to the scene file by the editor; false = transient editor state. */\n doc: boolean;\n /** True = emitted by `ui.auto()` — the editor may overlay its syntactic hints (options/node). */\n auto?: boolean;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type InspectorWidget = InspectorFieldWidget | {\n kind: \"button\";\n id: string;\n label: string;\n} | {\n kind: \"toolButton\";\n id: string;\n label: string;\n tool: string;\n} | {\n kind: \"header\";\n id: string;\n label: string;\n} | {\n kind: \"info\" | \"warn\";\n id: string;\n text: string;\n};\ntype FieldOpts = {\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Default for EDITOR-STATE keys (doc keys default from the class field). */\n value?: unknown;\n};\n/**\n * The widget builder handed to `static inspector(ui, aspect)` (and to editor windows/tools later).\n * One instance lives per card and persists across runs — it carries the card's editor state.\n */\nexport declare class InspectorUI {\n /** Numeric field (min/max/step render as a slider-style scrub range). */\n number(key: string, opts?: FieldOpts): number;\n /** Alias of `number` — give it min/max/step and the editor renders a scrubable range. */\n slider(key: string, opts?: FieldOpts): number;\n text(key: string, opts?: FieldOpts): string;\n color(key: string, opts?: FieldOpts): string;\n switch(key: string, opts?: FieldOpts): boolean;\n /** Dropdown — `options` may be computed fresh every run (dynamic lists come free). */\n select(key: string, options: readonly (string | number)[], opts?: FieldOpts): string | number;\n vec2(key: string, opts?: FieldOpts): [number, number];\n vec3(key: string, opts?: FieldOpts): [number, number, number];\n vec4(key: string, opts?: FieldOpts): [number, number, number, number];\n /** Scene-node reference (`ref()` fields): name dropdown + pick-in-viewport. Returns the RAW doc\n * value (`{ $ref }` marker or null) — read the resolved live node off the aspect instance. */\n node(key: string, opts?: FieldOpts): unknown;\n /** Project-asset path (the editor renders a dropdown of the project's GLBs). \"\" = none picked. */\n asset(key: string, opts?: FieldOpts): string;\n /** True on the run that consumes this button's click — do the action right there. */\n button(label: string, opts?: {\n id?: string;\n }): boolean;\n /** A toggle that activates/deactivates the named viewport tool (`registerEditorTool`). The\n * editor owns the active-tool state — the click never round-trips into the scene world. */\n toolButton(label: string, tool: string): void;\n header(label: string): void;\n info(text: string): void;\n warn(text: string): void;\n /** Emit the inferred field widgets (all declared aspect fields, or just the named ones) — the\n * zero-ceremony baseline; append custom widgets around it. */\n auto(...keys: string[]): void;\n private _vec;\n private _field;\n}\nexport {};\n","types/core/fields.d.ts":"/** Editor widget kinds the inspector knows how to render. `\"node\"` = a scene-node reference\n * (`ref('name')` in the file, name dropdown + pick-in-viewport in the inspector) — declare it via\n * `static fields` on fields typed `Node | null`; a `Node | null` type annotation is also picked\n * up syntactically by the editor's source scan. `\"asset\"` = a project-asset path (the editor\n * fills the dropdown with the project's GLBs — `ui.asset()` in windows/tools/cards). */\nexport type FieldEditor = \"number\" | \"text\" | \"color\" | \"switch\" | \"select\" | \"vec2\" | \"vec3\" | \"vec4\" | \"node\" | \"asset\";\nexport type FieldMetaEntry = {\n /** Inspector label (default: the field name). */\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Allowed values — renders a dropdown (editor \"select\"). */\n options?: readonly (string | number)[];\n /** Override the editor inferred from the default value. */\n editor?: FieldEditor;\n /** Exclude the field from the inspector. */\n hidden?: boolean;\n};\n/** Declared on an aspect class as `static fields: FieldMeta<MyAspect> = { … }`. All optional. */\nexport type FieldMeta<T = unknown> = {\n [K in Extract<keyof T, string>]?: FieldMetaEntry;\n};\n/** One editable field: key + default value + resolved editor + merged metadata. */\nexport type FieldDescriptor = {\n key: string;\n label: string;\n /** The default value (from a freshly constructed instance; undefined if only declared in meta). */\n value: unknown;\n /** Resolved editor kind; undefined = no editor known (inspector shows it read-only). */\n editor: FieldEditor | undefined;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type AspectClassInfo = {\n /** The accessor name (`static aspect`, injected by chisel for user aspects). */\n name: string;\n className: string;\n fields: FieldDescriptor[];\n /** True for editor-run classes (`static editor` — generators). The editor routes their\n * structural changes through a re-run instead of a live patch. */\n editor?: boolean;\n /** True when the class declares a custom `static inspector(ui, aspect)` card. */\n inspector?: boolean;\n};\n/** Infer the editor widget from a default value's shape. */\nexport declare const inferFieldEditor: (value: unknown) => FieldEditor | undefined;\n/**\n * Enumerate the editable fields of a class: construct a default instance, take its own enumerable\n * non-underscore fields (minus the Aspect base plumbing), infer editors from the default values, and\n * merge the class's optional `static fields` metadata (which can also add keys that have no runtime\n * default, e.g. fields declared without an initializer).\n */\nexport declare const describeFields: (ctor: abstract new () => unknown) => FieldDescriptor[];\n/** Describe an aspect class for the inspector: accessor name + class name + editable fields. */\nexport declare const describeAspect: (ctor: abstract new () => unknown) => AspectClassInfo;\n","types/core/signals.d.ts":"/** Runs every pending effect now instead of waiting for the microtask (test/host hook). */\nexport declare const flushEffects: () => void;\nexport interface Signal<T> {\n value: T;\n /** Read without subscribing the current effect/computed. */\n peek(): T;\n}\nexport interface Computed<T> {\n readonly value: T;\n /** Read without subscribing the current effect/computed (still recomputes if stale). */\n peek(): T;\n}\n/**\n * A reactive value. Reading `.value` inside an `effect`/`computed` (or a function-valued style\n * prop / `UIText` content) subscribes it; writing `.value` re-runs subscribers (batched — once\n * per microtask).\n */\nexport declare function signal<T>(initialValue: T): Signal<T>;\nexport declare function signal<T = undefined>(): Signal<T | undefined>;\n/** A lazily-cached derived value: recomputes on read after any of its dependencies changed. */\nexport declare function computed<T>(fn: () => T): Computed<T>;\n/**\n * Runs `fn` now and again whenever any signal/computed it read changes (batched per microtask).\n * Returns a dispose function; an undisposed effect lives for the rest of the app run.\n */\nexport declare function effect(fn: () => void): () => void;\n/** The shape UINode's Element exposes for binding ownership. */\nexport interface BindingHost {\n}\n","types/plugins/camera.d.ts":"import { File } from \"../runtime/fetch\";\nimport { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport type CameraFacing = \"front\" | \"back\";\nexport interface CameraView extends NativeView {\n /** Request camera permission, then present the preview. The current destination stays visible\n * until the camera is ready; rejects if permission is denied, the host has no camera, or\n * another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n /** Capture a still frame as an image `File` (host-encoded). */\n takePhoto(): Promise<File>;\n /** Switch between the front and back camera while the preview is live. */\n setFacingMode(facingMode: CameraFacing): Promise<void>;\n}\n/**\n * Create a camera view (default: the back camera). `CameraView.isSupported` reports whether this\n * host has a camera capability — check it before offering the feature.\n */\nexport declare const CameraView: {\n (options?: {\n facingMode?: CameraFacing;\n }): CameraView;\n /** Whether this host registered a \"camera\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/geolocation.d.ts":"export interface GeoPosition {\n latitude: number;\n longitude: number;\n /** Horizontal accuracy radius, meters. */\n accuracy: number;\n /** Meters above sea level, or null when the provider doesn't know. */\n altitude: number | null;\n /** Direction of travel in degrees clockwise from north, or null when stationary/unknown. */\n heading: number | null;\n /** Ground speed in m/s, or null when unknown. */\n speed: number | null;\n /** When this fix was taken, ms epoch. */\n timestamp: number;\n}\nexport interface GeoOptions {\n /** Prefer the precise (GPS) provider — slower first fix, more battery. Default false. */\n highAccuracy?: boolean;\n /** getCurrent only: reject with \"timeout\" if no fix arrives in this many ms. */\n timeout?: number;\n}\n/** A live `Geolocation.watch()` subscription — `stop()` it when the screen goes away. */\nexport interface GeoWatch {\n stop(): void;\n}\n/**\n * The device position. `Geolocation.isSupported` reports whether this host registered the\n * service — check it before offering location features.\n */\nexport declare const Geolocation: {\n /** Whether this host registered a \"geolocation\" service. */\n readonly isSupported: boolean;\n /** One position fix. Prompts for permission on first use; rejects on denial (\"denied\"), no\n * provider (\"unavailable\"), or `options.timeout` elapsing (\"timeout\"). */\n getCurrent(options?: GeoOptions): Promise<GeoPosition>;\n /** Continuous updates. Resolves once watching (permission granted + provider started) — so a\n * denial is a rejection, never a silently dead callback. One host watch serves every\n * subscriber; the options of the watch that starts it win. Always `stop()` when done. */\n watch(callback: (position: GeoPosition) => void, options?: GeoOptions): Promise<GeoWatch>;\n};\n","types/plugins/permission.d.ts":"export declare const _requestCameraPermission: () => Promise<void>;\n","types/plugins/service.d.ts":"export interface Service {\n /** Invoke a method on the service (`battery.call(\"level\")`). Arguments and the result are\n * JSON-serialized; rejects when the host has no such service or the method reports an\n * error. The host session opens lazily on the first call. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the service emits while a session is open\n * (`battery.on(\"change\", data => …)`). Payloads are JSON-decoded. */\n on(event: string, callback: (data?: any) => void): this;\n /** Remove a previously added listener. */\n off(event: string, callback: (data?: any) => void): this;\n /** Close the host session (stops whatever the service was doing). Listeners stay\n * registered — a later `call()` opens a fresh session that delivers to them again. */\n close(): void;\n}\n/**\n * A host-registered headless service — the UI-less sibling of `NativeView`. Use it for\n * services without a typed wrapper: native code registered in your app shell\n * (`engine.registerService(\"app.battery\") { … }`) or a third-party plugin's channel.\n * **Host-optional** — gate on `Service.isSupported` (the web editor registers none of them).\n *\n * ```ts\n * if (Service.isSupported(\"app.battery\")) {\n * const battery = Service(\"app.battery\")\n * battery.on(\"change\", data => { level.text = data.level + \"%\" })\n * const { level } = await battery.call(\"level\")\n * }\n * ```\n */\nexport declare const Service: {\n (name: string, params?: any): Service;\n /** Whether this host registered a service under `name`. */\n isSupported(name: string): boolean;\n};\n","types/plugins/qr.d.ts":"import { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport interface QRScanner extends NativeView {\n /** Fires per decoded camera frame: the decoded string, or `null` for a frame with no readable\n * code (expect those repeatedly while the user aims). The same code can be reported more than\n * once — `close()` or debounce once you have what you need. */\n onScan(callback: (data: string | null) => void): this;\n /** Request camera permission, then present the scanner. The current destination (and its\n * loading state) stays visible until the scanner is ready; rejects if the camera is denied,\n * the host can't scan, or another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n}\n/**\n * Create a QR scanner view. `QRScanner.isSupported` reports whether this host can scan at all —\n * check it before offering the feature.\n */\nexport declare const QRScanner: {\n (): QRScanner;\n /** Whether this host registered a \"qrScanner\" view. */\n readonly isSupported: boolean;\n};\n","types/runtime/touch.d.ts":"export declare class ClickEvent<T = any> {\n readonly type = \"click\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n}\nexport interface TrackHandler {\n onMove?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onEnd?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onCancel?(): void;\n claim?: boolean | \"pan-x\" | \"pan-y\" | \"pan-down\" | \"pan-up\" | \"pan-left\" | \"pan-right\";\n}\nexport declare class TouchStartEvent<T = any> {\n readonly type = \"touchstart\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer (drag/pan gestures). */\n track(handler: TrackHandler): void;\n}\n/** Delivered to a `UIButton` `onLongPress` handler when a finger is held on the button past the\n * host's long-press threshold. Like `TouchStartEvent` it can `track(...)` the rest of the gesture —\n * so the common \"press-and-hold, then drag to move\" flow is one handler: start the drag from here. */\nexport declare class LongPressEvent<T = any> {\n readonly type = \"longpress\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer — drag the element after the hold. */\n track(handler: TrackHandler): void;\n}\n","types/runtime/share.d.ts":"import type { File, FetchResponse } from \"./fetch\";\nexport declare function share(media: File | FetchResponse, text?: string): void;\n","types/runtime/datetime.d.ts":"export type Locale = \"en\" | \"ru\";\nexport type DateInput = Date | number | string | DateValue;\nexport type Unit = \"ms\" | \"second\" | \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\" | \"year\";\n/**\n * An immutable moment in time — the value returned by [`date()`]. Wraps a single epoch-millisecond\n * scalar (`t`); every method returns a new `DateValue` or a plain scalar, never mutating. Construct\n * it with `date(...)`, not `new`.\n */\nexport declare class DateValue {\n /** Epoch milliseconds — the one canonical scalar. Prefer `valueOf()`; this is public so `date(a)`\n * can read it back cheaply and so tooling can treat it as the value's single component. */\n readonly t: number;\n constructor(ms: number);\n /**\n * Format against a `day.js`-style token pattern (default `\"D MMMM YYYY\"`). Locale defaults to the\n * current device language.\n *\n * Tokens: `YYYY`/`YY` year · `MMMM`/`MMM`/`MM`/`M` month · `DD`/`D` day · `dddd`/`ddd` weekday ·\n * `HH`/`H` 24-hour · `hh`/`h` 12-hour · `mm`/`m` minute · `ss`/`s` second · `A`/`a` AM/PM.\n *\n * ```ts\n * date().format() // \"10 July 2026\" / \"10 июля 2026\"\n * date(ts).format(\"DD.MM.YYYY HH:mm\") // \"10.07.2026 14:05\"\n * date(ts).format(\"MMMM YYYY\", \"ru\") // \"Июль 2026\" (nominative — no day token)\n * ```\n */\n format(pattern?: string, locale?: Locale): string;\n /**\n * Human relative time vs `now` (default: the current time) — \"5 minutes ago\", \"in 2 days\",\n * \"5 минут назад\", \"через 2 дня\". Reads as \"just now\" under ~45 seconds; handles Russian number\n * agreement (`1 минуту` / `2 минуты` / `5 минут`). Locale defaults to the device language.\n */\n timeAgo(locale?: Locale, now?: DateInput): string;\n /** Add `n` of a unit, returning a new value. Linear units (`ms`…`week`) are scalar ms math;\n * `month`/`year` are calendar-aware (clamp on short months, like day.js). */\n add(n: number, unit: Unit): DateValue;\n /** Subtract `n` of a unit. Equivalent to `add(-n, unit)`. */\n subtract(n: number, unit: Unit): DateValue;\n /** Snap down to the start of a unit (local time): start of day/hour/month/year, etc. */\n startOf(unit: Unit): DateValue;\n /** Snap up to the end of a unit (local time): the last millisecond of the day/hour/month/… */\n endOf(unit: Unit): DateValue;\n /** Epoch milliseconds. Enables `+date(x)`, `date(a) < date(b)`, `date(a) - date(b)` via coercion. */\n valueOf(): number;\n /** Whole seconds since the epoch (Unix time). */\n unix(): number;\n /** Signed difference to `other`, in whole `unit`s (default `ms`), truncated toward zero. */\n diff(other: DateInput, unit?: Unit): number;\n isBefore(other: DateInput): boolean;\n isAfter(other: DateInput): boolean;\n isSame(other: DateInput): boolean;\n year(): number;\n /** 0-based month (0 = January), matching `Date.getMonth`. */\n month(): number;\n /** Day of the month, 1–31. */\n day(): number;\n /** Day of the week, 0 (Sunday)–6 (Saturday), matching `Date.getDay`. */\n weekday(): number;\n hour(): number;\n minute(): number;\n second(): number;\n /** A native `Date` snapshot of this value. */\n toDate(): Date;\n}\n/**\n * Create a `DateValue` — a locale-aware, immutable moment, dayjs-style. Accepts a `Date`, a\n * millisecond timestamp (`Date.now()`), a parseable string, or another `DateValue`; with no argument\n * it's the current time. Chain arithmetic and finish with `format` / `timeAgo`, both of which\n * understand **English** and **Russian** and default to the current device language\n * ([`device.language`](../runtime/device.ts)).\n *\n * ```ts\n * date().format(\"dddd, D MMMM\") // \"Friday, 10 July\" / \"пятница, 10 июля\"\n * date(ts).timeAgo() // \"5 minutes ago\" / \"5 минут назад\"\n * date().add(3, \"day\").startOf(\"day\").format(\"D MMMM\")\n * date(a).diff(b, \"hour\") // signed whole hours\n * date(a).isBefore(b) // boolean\n * ```\n */\nexport declare const date: (value?: DateInput) => DateValue;\n","types/runtime/app.d.ts":"export type AppState = \"active\" | \"background\";\ntype AppEventMap = {\n /** The app left the foreground (home button, tab hidden, another app on top). Delivered before\n * the host halts the frame loop — the last chance to persist state / pause work. */\n pause: () => void;\n /** The app returned to the foreground; frames are running again. */\n resume: () => void;\n /** A link arrived while the app was running (warm deep link). `app.launchUrl` is already\n * updated to the same value when this fires. */\n url: (url: string) => void;\n /** The on-screen keyboard changed. `height` mirrors `app.keyboardHeight` (the raw overlap, see\n * there); `duration` is the platform's keyboard animation duration in ms (0 where none) — pass\n * it to `animateTo` to move a composer in sync with the keyboard. */\n keyboard: (height: number, duration: number) => void;\n};\nexport declare const app: {\n /** Current lifecycle state. `\"background\"` while the app is not the foreground app / the tab is\n * hidden. `\"active\"` on hosts that don't track it. */\n readonly state: AppState;\n /** The URL the app was (most recently) opened with — the deep link — or `null` for a plain\n * launch. Warm links update it and fire the `\"url\"` event. */\n readonly launchUrl: string | null;\n /** On-screen keyboard height in logical px currently overlapping the app viewport, `0` when\n * hidden. This is the RAW overlap, independent of the focused input's `keyboardShrink` policy —\n * with the default shrink the layout already avoids the keyboard; the main consumer is overlay\n * mode (`keyboardShrink: false`), e.g. a chat composer's `pb`. `0` on hosts without an\n * on-screen keyboard. */\n readonly keyboardHeight: number;\n addEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n removeEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n};\nexport {};\n","types/runtime/misc.d.ts":"/** Show a transient toast notification. */\nexport declare const toast: (msg: string) => void;\n/** Open `url` in the system browser / external handler (fire-and-forget, like `share`). Silent\n * no-op on hosts without one (headless). */\nexport declare const openURL: (url: string) => void;\nexport type SvgSourceValue = {\n readonly svg: string;\n tintColor: string | null;\n};\n/** Wrap raw SVG XML so it can be used as an image source. */\nexport declare const SvgSource: (svg: string) => SvgSourceValue;\n","types/runtime/input.d.ts":"export declare const Input: {\n /**\n * Is a key currently held? `code` is a KeyboardEvent.code-style string, e.g. 'ArrowRight',\n * 'KeyW', 'Space'. Poll this inside setLoop for frame-independent movement.\n */\n key(code: string): boolean;\n};\n","types/runtime/device.d.ts":"import { Quat } from \"../math/quat\";\nimport { Vec3 } from \"../math/vec\";\ntype ResizeCallback = (width: number, height: number) => void;\ntype DeviceEventMap = {\n resize: ResizeCallback;\n /** Connectivity came back (best-effort, navigator.onLine semantics). */\n online: () => void;\n /** Connectivity was lost. */\n offline: () => void;\n};\n/** Semantic haptic styles for `device.vibrate`. Impact styles (`light`/`medium`/`heavy`/`soft`/\n * `rigid`) are a physical \"tap\" of varying weight; notification styles (`success`/`warning`/`error`)\n * cue an outcome; `selection` is a light tick for a value change. Chosen to map 1:1 onto iOS\n * `UIFeedbackGenerator` and, on Android, `HapticFeedbackConstants` / `VibrationEffect` — so the same\n * call feels native everywhere, rather than a duration that only web/Android can honor. */\nexport type HapticStyle = \"light\" | \"medium\" | \"heavy\" | \"soft\" | \"rigid\" | \"success\" | \"warning\" | \"error\" | \"selection\";\n/** Options for `device.motion.start`. */\nexport interface MotionOptions {\n /** Sensor update interval in seconds (default 1/60). The sensor fuses at ≥ this rate in the\n * background; you poll the freshest sample each frame, so this is a floor, not a sync. */\n interval?: number;\n /** Frame the readables are delivered in. \"world\" (default): engine Y-up, screen-oriented — drops\n * straight into `camera.quaternion` / any node. \"device\": the raw sensor frame, no conversion. */\n frame?: \"world\" | \"device\";\n}\nexport declare const device: {\n readonly platform: \"web\" | \"android\" | \"ios\" | string;\n readonly language: string;\n /** Display device-pixel ratio (physical px per logical/CSS px): 1 on standard displays, 2–3 on\n * retina / iOS. Bake a Canvas at this ratio for crisp output without hardcoding, e.g.\n * `new Canvas(w, h, { pixelRatio: device.pixelRatio })`. NOTE: the web 2D/GL surface currently\n * renders at logical resolution, so on web this only helps UI canvases / is forward-looking for\n * 2D; on iOS (physical surface) it makes 2D canvases crisp. Falls back to 1 if the host omits it. */\n readonly pixelRatio: number;\n /** Current display width in logical px — the same value the \"resize\" event delivers, but readable at\n * any time (not only inside the listener). 0 until the host has reported a size. */\n readonly width: number;\n /** Current display height in logical px — the same value the \"resize\" event delivers, readable at any\n * time. 0 until the host has reported a size. */\n readonly height: number;\n /** Opt into the precise-touch system where the platform supports it. OFF by default. When on, fast\n * strokes are sampled at the touch digitizer's full rate (iOS coalesced touches, ≈120–240 Hz) instead\n * of once per display frame (~60 Hz), so a pointer-heavy app (drawing, handwriting, dragging) gets more\n * points and smoother lines. Leave it off for tap/button UIs. No-op on hosts without a coalesced-input\n * concept (web already coalesces pointermove; headless). */\n setPreciseTouch(enabled: boolean): void;\n /** Fire a one-shot haptic of the given semantic `style` (default `\"medium\"`) — a physical tap on\n * supported hardware (iOS Taptic Engine, Android vibrator). Chosen by meaning, not duration, so it\n * feels native on each platform; see {@link HapticStyle}. Host-gated: a silent no-op where there's\n * no haptic hardware (iPad, older iPhones, web, headless). */\n vibrate(style?: HapticStyle): void;\n /** Device-orientation sensor (gyro + accelerometer, fused) for tilt/steering and magic-window /\n * 360° panoramas. Poll `attitude` / `gravity` inside setLoop; they return the freshest fused\n * sample, so the sensor rate need not match your frame rate. Host-gated: a no-op with no sensor. */\n motion: {\n /** Whether this device has the motion sensors at all (no gyro → false; iPad/older, web, headless). */\n readonly available: boolean;\n /** Whether updates are currently running (start succeeded and stop hasn't been called). */\n readonly enabled: boolean;\n /** Begin sensor updates. Resolves to whether it actually started (false = no sensor / denied).\n * Async so a web host can await its permission prompt; native resolves immediately. */\n start(options?: MotionOptions): Promise<boolean>;\n /** Stop sensor updates and release the sensor (battery). */\n stop(): void;\n /** Capture the current heading as \"forward\" — a yaw-only recenter (pitch/roll stay gravity-\n * referenced, so the horizon stays level). No-op in the \"device\" frame. */\n recenter(): void;\n /** The device's current orientation as a `Quat`. In the \"world\" frame (default) it's engine Y-up\n * and screen-oriented, so `camera.quaternion = device.motion.attitude` is a complete magic-window\n * / panorama camera. `Quat.identity` until the first sample arrives / when not running. */\n readonly attitude: Quat;\n /** Gravity direction for tilt controls. In the \"world\" frame it's SCREEN space (x → right, y →\n * down, matching clientX/clientY), orientation-aware — a 2D game reads `gravity.x / gravity.y`.\n * `(0,0,0)` when not running. */\n readonly gravity: Vec3;\n };\n /** Current connectivity — best-effort navigator.onLine semantics: `false` only when the platform\n * is sure there's no network. `true` on hosts that don't track it. Change events: `\"online\"` /\n * `\"offline\"`. */\n readonly online: boolean;\n addEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n removeEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n};\nexport {};\n","types/runtime/service.d.ts":"export {};\n","types/runtime/appEvents.d.ts":"type AppEventCallback = (data?: string) => void;\nexport declare const appEventsOn: (event: string, cb: AppEventCallback) => void;\nexport declare const appEventsOff: (event: string, cb: AppEventCallback) => void;\ntype KeyboardCallback = (height: number, duration: number) => void;\nexport declare const keyboardEventsOn: (cb: KeyboardCallback) => void;\nexport declare const keyboardEventsOff: (cb: KeyboardCallback) => void;\nexport {};\n","types/runtime/channel.d.ts":"export {};\n","types/runtime/fetch.d.ts":"export type FetchOptions = {\n body?: any;\n method?: string;\n headers?: Record<string, string>;\n useOnce?: boolean;\n onProgress?: (progress: {\n loaded: number;\n total?: number;\n }) => void;\n};\nexport interface FetchResponse {\n readonly status: number;\n json<T = any>(): T;\n text(): string;\n dispose(): void;\n}\nexport declare const fetch: (url: string, options?: FetchOptions) => Promise<FetchResponse>;\nexport declare const fetchLocal: (path: string) => FetchResponse;\n/** A handle to a picked / fetched file (see openFilePicker). */\nexport declare class File {\n readonly name: string;\n readonly size: number;\n constructor(systemId: number, name: string, size: number);\n}\ntype FormDataValue = string | number | boolean | File | FetchResponse;\nexport declare class FormData {\n private _entries;\n append(name: string, value: FormDataValue, filename?: string): void;\n delete(name: string): void;\n}\nexport {};\n","types/runtime/clipboard.d.ts":"export declare const clipboard: {\n /** Put `text` on the system clipboard. Silent no-op on hosts without clipboard access. */\n write(text: string): void;\n /** Read text from the system clipboard. Rejects when the platform has no clipboard access, the\n * user denied it, or there is nothing readable. */\n read(): Promise<string>;\n};\n","types/runtime/files.d.ts":"import { File } from \"./fetch\";\ntype OpenFilePickerOptions = {\n accept?: string;\n};\nexport declare function openFilePicker(options?: OpenFilePickerOptions & {\n multiple?: false;\n}): Promise<File | null>;\nexport declare function openFilePicker(options: OpenFilePickerOptions & {\n multiple: true;\n}): Promise<File[]>;\nexport {};\n","types/runtime/media.d.ts":"import { Emitter } from \"../core/events\";\nimport { Texture } from \"../gl/Texture\";\ntype MediaEvents = {\n /** Fired at each loop boundary while `loop` is true. */\n loopReached: () => void;\n /** Fired once when playback reaches the end while `loop` is false. */\n completed: () => void;\n};\ndeclare abstract class MediaPlayer extends Emitter<MediaEvents> {\n protected _id: number;\n protected _src: string;\n private _playing;\n private _loop;\n private _volume;\n private _disposed;\n private _assertAlive;\n play(): void;\n pause(): void;\n get playing(): boolean;\n set playing(value: boolean);\n get volume(): number;\n set volume(value: number);\n get loop(): boolean;\n set loop(value: boolean);\n /** Current playback position, in seconds. Settable to seek. */\n get time(): number;\n set time(value: number);\n /** Total media length in seconds (0 until metadata has loaded). */\n get duration(): number;\n /** True once {@link dispose} has been called; the player is unusable afterwards. */\n get disposed(): boolean;\n /**\n * Release the underlying host media resource (decoder, network, buffers) immediately and detach\n * all listeners. Idempotent. Any further use of the player throws.\n */\n dispose(): void;\n}\nexport declare class AudioPlayer extends MediaPlayer {\n constructor(src?: string);\n}\nexport declare class VideoPlayer extends MediaPlayer {\n constructor(src?: string);\n /** A 3D Texture that samples this video (e.g. for a Material.video()). */\n get texture(): Texture;\n}\nexport {};\n","types/runtime/storage.d.ts":"export declare const localStorage: {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n};\n","types/runtime/net.d.ts":"import { Emitter } from \"../core/events\";\ntype SocketEvents = {\n open: () => void;\n message: (data: any) => void;\n close: (code?: number) => void;\n error: () => void;\n};\nexport declare class WebSocket extends Emitter<SocketEvents> {\n private _id;\n constructor(url: string, headers?: Record<string, string>);\n send(message: string | ArrayBuffer): void;\n close(): void;\n private _onMessage;\n}\nexport {};\n","types/math/Mathf.d.ts":"export type Damper<T extends number | number[]> = ((target: T, dt: number) => T) & {\n /** Snap the damper's internal current value (e.g. on teleport). */\n setValue(value: T): void;\n};\ndeclare function smoothDamp(initial: number, smoothTime: number, maxSpeed?: number): Damper<number>;\ndeclare function smoothDamp(initial: number[], smoothTime: number, maxSpeed?: number): Damper<number[]>;\nexport declare const Mathf: {\n PI: number;\n TAU: number;\n EPSILON: number;\n DEG2RAD: number;\n RAD2DEG: number;\n deg2rad: (deg: number) => number;\n rad2deg: (rad: number) => number;\n clamp: (v: number, min: number, max: number) => number;\n clamp01: (v: number) => number;\n lerp: (a: number, b: number, t: number) => number;\n inverseLerp: (a: number, b: number, v: number) => number;\n remap: (v: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;\n /** Move `a` toward `b` by at most `maxDelta`. */\n moveTowards: (a: number, b: number, maxDelta: number) => number;\n /** Frame-rate-independent exponential approach (good default: lambda 5..15). */\n damp: (a: number, b: number, lambda: number, dt: number) => number;\n sign: (x: number) => number;\n /** Loop a value into [0, length). */\n repeat: (t: number, length: number) => number;\n /** Ping-pong a value in [0, length]. */\n pingPong: (t: number, length: number) => number;\n random: (min?: number, max?: number) => number;\n randomInt: (min: number, max: number) => number;\n /**\n * Critically-damped follow (Unity SmoothDamp). Returns a stateful damper you call every frame:\n * const d = Mathf.smoothDamp([x, y], 0.15)\n * pos = d(targetPos, dt)\n * Works on a number or a numeric array (vec2 / vec3).\n */\n smoothDamp: typeof smoothDamp;\n};\nexport {};\n","types/math/vec.d.ts":"export type Vec2Like = Vec2 | readonly [number, number] | number[] | Float32Array;\nexport type Vec3Like = Vec3 | readonly [number, number, number] | number[] | Float32Array;\n/** Read the x / first component of any vector-like (wrapper, tuple, or typed array). `?? ` is safe on\n * 0 and NaN — it only falls through on `undefined` (i.e. a non-wrapper that has no `.x`). */\nexport declare const cx: (v: {\n x?: number;\n} | ArrayLike<number>) => number;\nexport declare const cy: (v: {\n y?: number;\n} | ArrayLike<number>) => number;\nexport declare const cz: (v: {\n z?: number;\n} | ArrayLike<number>) => number;\nexport declare class Vec2 {\n x: number;\n y: number;\n constructor(x?: number | Vec2Like, y?: number);\n /** Mutate the components in place. Returns `this`. */\n set(x: number, y: number): this;\n /** Copy another vector's components into this one. Returns `this`. */\n copy(v: Vec2Like): this;\n add(v: Vec2Like): Vec2;\n sub(v: Vec2Like): Vec2;\n mul(v: Vec2Like): Vec2;\n div(v: Vec2Like): Vec2;\n scale(s: number): Vec2;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec2Like, s: number): Vec2;\n negate(): Vec2;\n dot(v: Vec2Like): number;\n /** 2D cross product → the scalar z of the 3D cross (signed parallelogram area). */\n cross(v: Vec2Like): number;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec2Like): number;\n distanceSqTo(v: Vec2Like): number;\n normalize(): Vec2;\n lerp(v: Vec2Like, t: number): Vec2;\n clamp(min: Vec2Like, max: Vec2Like): Vec2;\n min(v: Vec2Like): Vec2;\n max(v: Vec2Like): Vec2;\n /** Left-hand perpendicular: (-y, x), a 90° CCW turn. */\n perp(): Vec2;\n /** Rotate by `rad` (CCW) around `origin` (default 0). */\n rotate(rad: number, origin?: Vec2Like): Vec2;\n /** The vector's heading in radians: `atan2(y, x)`. */\n heading(): number;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec2Like): number;\n withX(x: number): Vec2;\n withY(y: number): Vec2;\n equals(v: Vec2Like, eps?: number): boolean;\n clone(): Vec2;\n toArray(): [number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec2Like): Vec2;\n static get zero(): Vec2;\n static get one(): Vec2;\n static get up(): Vec2;\n static get down(): Vec2;\n static get left(): Vec2;\n static get right(): Vec2;\n}\nexport declare class Vec3 {\n x: number;\n y: number;\n z: number;\n constructor(x?: number | Vec3Like, y?: number, z?: number);\n set(x: number, y: number, z: number): this;\n copy(v: Vec3Like): this;\n add(v: Vec3Like): Vec3;\n sub(v: Vec3Like): Vec3;\n mul(v: Vec3Like): Vec3;\n div(v: Vec3Like): Vec3;\n scale(s: number): Vec3;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec3Like, s: number): Vec3;\n negate(): Vec3;\n dot(v: Vec3Like): number;\n cross(v: Vec3Like): Vec3;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec3Like): number;\n distanceSqTo(v: Vec3Like): number;\n normalize(): Vec3;\n lerp(v: Vec3Like, t: number): Vec3;\n clamp(min: Vec3Like, max: Vec3Like): Vec3;\n min(v: Vec3Like): Vec3;\n max(v: Vec3Like): Vec3;\n /** Reflect this vector about a (unit) `normal`: `v - 2·(v·n)·n`. */\n reflect(normal: Vec3Like): Vec3;\n /** Vector projection of this onto `onto`. */\n project(onto: Vec3Like): Vec3;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec3Like): number;\n /** Rotate this point around the X axis through `origin` (default 0) by `rad`. */\n rotateX(rad: number, origin?: Vec3Like): Vec3;\n rotateY(rad: number, origin?: Vec3Like): Vec3;\n rotateZ(rad: number, origin?: Vec3Like): Vec3;\n /** Rotate this vector by a quaternion (x, y, z, w). Accepts a `Quat` or a raw `[x,y,z,w]`. */\n rotate(q: ArrayLike<number> | {\n x: number;\n y: number;\n z: number;\n w: number;\n }): Vec3;\n /** Transform this point by a column-major mat4 (a `Mat4`, its `.m`, or a raw length-16 array),\n * applying translation and the perspective divide. */\n transform(m: ArrayLike<number> | {\n m: ArrayLike<number>;\n }): Vec3;\n withX(x: number): Vec3;\n withY(y: number): Vec3;\n withZ(z: number): Vec3;\n equals(v: Vec3Like, eps?: number): boolean;\n clone(): Vec3;\n toArray(): [number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec3Like): Vec3;\n static get zero(): Vec3;\n static get one(): Vec3;\n static get up(): Vec3;\n static get down(): Vec3;\n static get left(): Vec3;\n static get right(): Vec3;\n /** Forward is −Z (the engine's cameras look down −Z; `node.forward` is −Z at identity). */\n static get forward(): Vec3;\n static get back(): Vec3;\n}\n","types/math/mat4.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nimport { Quat, type QuatLike, type EulerOrder } from \"./quat\";\nexport type Mat4Like = Mat4 | number[] | Float32Array | readonly number[];\nexport declare class Mat4 {\n /** The raw column-major elements (length 16). Public on purpose — read/write directly when you want\n * the metal: `mat.m[12] += vx * dt`. The fluent methods never mutate it (they return a new Mat4). */\n m: number[];\n constructor(src?: Mat4Like);\n set(values: ArrayLike<number>): this;\n copy(src: Mat4Like): this;\n /** `this · b` (apply `b` first in local space, then `this`). */\n mul(b: Mat4Like): Mat4;\n /** `b · this` — multiply on the other side (apply `this` first, then `b`). */\n premul(b: Mat4Like): Mat4;\n invert(): Mat4;\n transpose(): Mat4;\n determinant(): number;\n /** `this · translate(v)`. */\n translate(v: Vec3Like): Mat4;\n /** `this · scale(v)`. Accepts a vector or a uniform scalar. */\n scale(v: Vec3Like | number): Mat4;\n /** `this · rotate(axis, rad)`. */\n rotate(rad: number, axis: Vec3Like): Mat4;\n rotateX(rad: number): Mat4;\n rotateY(rad: number): Mat4;\n rotateZ(rad: number): Mat4;\n /** Transform a point (applies translation + perspective divide). */\n transformPoint(v: Vec3Like): Vec3;\n /** Transform a direction (rotation/scale only — no translation, no divide). */\n transformDirection(v: Vec3Like): Vec3;\n get position(): Vec3;\n get scaling(): Vec3;\n get rotation(): Quat;\n get eulerAngles(): Vec3;\n toEuler(order?: EulerOrder): Vec3;\n /** `{ position, rotation, scale }` in one shot. */\n decompose(): {\n position: Vec3;\n rotation: Quat;\n scale: Vec3;\n };\n /** Column basis vectors (the local X / Y / Z axes in world space). */\n get basisX(): Vec3;\n get basisY(): Vec3;\n get basisZ(): Vec3;\n clone(): Mat4;\n toArray(): number[];\n toFloat32Array(): Float32Array;\n equals(b: Mat4Like, eps?: number): boolean;\n static identity(): Mat4;\n static from(src: Mat4Like): Mat4;\n /** Translation · Rotation · Scale into one matrix. `scale` defaults to 1 and accepts a scalar. */\n static compose(position: Vec3Like, rotation: QuatLike, scale?: Vec3Like | number): Mat4;\n static fromQuat(q: QuatLike): Mat4;\n static fromTranslation(v: Vec3Like): Mat4;\n static fromScale(v: Vec3Like | number): Mat4;\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Mat4;\n /** A view matrix that looks from `eye` toward `center` with `up`. */\n static lookAt(eye: Vec3Like, center: Vec3Like, up?: Vec3Like): Mat4;\n /** A world matrix that places something at `eye` oriented to look at `target`. */\n static targetTo(eye: Vec3Like, target: Vec3Like, up?: Vec3Like): Mat4;\n /** Perspective projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). `fovy` is in RADIANS. */\n static perspective(fovy: number, aspect: number, near: number, far: number): Mat4;\n /** Orthographic projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). */\n static ortho(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4;\n}\n","types/math/quat.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nexport type QuatLike = Quat | readonly [number, number, number, number] | number[] | Float32Array;\nexport type EulerOrder = \"XYZ\" | \"YXZ\" | \"ZXY\" | \"ZYX\" | \"YZX\" | \"XZY\";\n/** Read the w / 4th component of any quaternion-like (wrapper `.w`, or array-like `[3]`). */\nexport declare const cw: (q: {\n w?: number;\n} | ArrayLike<number>) => number;\nexport declare class Quat {\n x: number;\n y: number;\n z: number;\n w: number;\n constructor(x?: number | QuatLike, y?: number, z?: number, w?: number);\n set(x: number, y: number, z: number, w: number): this;\n copy(q: QuatLike): this;\n /** Hamilton product `this ⊗ b` (apply `b` first, then `this`). */\n mul(b: QuatLike): Quat;\n normalize(): Quat;\n conjugate(): Quat;\n /** Inverse rotation. For a unit quaternion this equals `conjugate()`. */\n invert(): Quat;\n dot(b: QuatLike): number;\n /** Spherical interpolation toward `b` by `t ∈ [0, 1]`. */\n slerp(b: QuatLike, t: number): Quat;\n /** Angular distance (radians) between two unit quaternions. */\n angle(b: QuatLike): number;\n /** Rotate a vector by this quaternion → a new `Vec3`. */\n rotateVec3(v: Vec3Like): Vec3;\n /** Extract euler angles (DEGREES) in the given order. */\n toEuler(order?: EulerOrder): Vec3;\n equals(b: QuatLike, eps?: number): boolean;\n /** True if the two unit quaternions represent the same rotation (±q are equal). */\n sameRotation(b: QuatLike, eps?: number): boolean;\n clone(): Quat;\n toArray(): [number, number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(q: QuatLike): Quat;\n static get identity(): Quat;\n /** From euler angles in DEGREES (default order \"YXZ\"). Inverts `toEuler`. */\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Quat;\n /** From a rotation `axis` and an angle in RADIANS. The axis is normalized for you. */\n static fromAxisAngle(axis: Vec3Like, rad: number): Quat;\n /** The shortest rotation that takes direction `a` onto direction `b`. */\n static fromTo(a: Vec3Like, b: Vec3Like): Quat;\n /** A rotation whose forward (−Z) points along `forward`, with `up` as the reference up axis. */\n static lookRotation(forward: Vec3Like, up?: Vec3Like): Quat;\n}\n/** Quaternion from a column-major rotation matrix (≥3×3, indices 0,1,2,4,5,6,8,9,10). gl-matrix's\n * `getRotation` algorithm — the exact inverse of building a matrix from a quaternion. */\nexport declare const quatFromColMajor: (m: ArrayLike<number>) => Quat;\n/** Euler angles (DEGREES) from a column-major rotation matrix, standard three.js extraction.\n * Element naming follows the column-major layout: mRC = m[(C-1)*4 + (R-1)]. */\nexport declare const eulerFromColMajor: (m: ArrayLike<number>, order?: EulerOrder) => Vec3;\n","types/canvas/Canvas.d.ts":"import { Texture2D } from \"../g2/Texture2D\";\nimport { File, type FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue } from \"../runtime/misc\";\ndeclare const ALIGN: {\n readonly left: 0;\n readonly center: 1;\n readonly right: 2;\n readonly start: 3;\n readonly end: 4;\n};\ndeclare const BASELINE: {\n readonly alphabetic: 0;\n readonly top: 1;\n readonly middle: 2;\n readonly bottom: 3;\n readonly hanging: 4;\n readonly ideographic: 5;\n};\ndeclare const JOIN: {\n readonly miter: 0;\n readonly round: 1;\n readonly bevel: 2;\n};\ndeclare const CAP: {\n readonly butt: 0;\n readonly round: 1;\n readonly square: 2;\n};\nexport type TextAlign = keyof typeof ALIGN;\nexport type TextBaseline = keyof typeof BASELINE;\nexport type LineJoin = keyof typeof JOIN;\nexport type LineCap = keyof typeof CAP;\nexport interface CanvasTextMetrics {\n width: number;\n ascent: number;\n descent: number;\n}\nexport declare class Canvas {\n /** Brand so `Sprite`/`UIImage`/`Material` can accept a Canvas anywhere a texture source is expected. */\n readonly __canvas: true;\n width: number;\n height: number;\n /** Device-pixel multiplier (draw at 2 for crisp retina text). Applied by the backend. */\n pixelRatio: number;\n private _cmd;\n private _refs;\n private _globalAlpha;\n private _fillStyle;\n private _strokeStyle;\n private _lineWidth;\n private _lineJoin;\n private _lineCap;\n private _font;\n private _textAlign;\n private _textBaseline;\n private _surfaceId;\n private _tex2d?;\n private _uiBound;\n constructor(width: number, height: number, opts?: {\n pixelRatio?: number;\n });\n private _ref;\n /** Discard the recorded drawing to start a new one (for dynamic canvases). */\n reset(): this;\n /** Change the surface size; takes effect on the next bake. */\n resize(width: number, height: number): this;\n save(): this;\n restore(): this;\n translate(x: number, y: number): this;\n scale(sx: number, sy: number): this;\n rotate(rad: number): this;\n get globalAlpha(): number;\n set globalAlpha(a: number);\n get fillStyle(): string;\n set fillStyle(color: string);\n get strokeStyle(): string;\n set strokeStyle(color: string);\n get lineWidth(): number;\n set lineWidth(w: number);\n get lineJoin(): LineJoin;\n set lineJoin(j: LineJoin);\n get lineCap(): LineCap;\n set lineCap(c: LineCap);\n get font(): string;\n set font(f: string);\n get textAlign(): TextAlign;\n set textAlign(a: TextAlign);\n get textBaseline(): TextBaseline;\n set textBaseline(b: TextBaseline);\n beginPath(): this;\n closePath(): this;\n moveTo(x: number, y: number): this;\n lineTo(x: number, y: number): this;\n quadraticCurveTo(cx: number, cy: number, x: number, y: number): this;\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this;\n arc(x: number, y: number, r: number, a0: number, a1: number, ccw?: boolean): this;\n rect(x: number, y: number, w: number, h: number): this;\n roundRect(x: number, y: number, w: number, h: number, r: number): this;\n fill(evenOdd?: boolean): this;\n stroke(): this;\n fillRect(x: number, y: number, w: number, h: number): this;\n strokeRect(x: number, y: number, w: number, h: number): this;\n clearRect(x: number, y: number, w: number, h: number): this;\n fillText(text: string, x: number, y: number, maxWidth?: number): this;\n strokeText(text: string, x: number, y: number, maxWidth?: number): this;\n /** Blit a `Bitmap` (a snapshot from `toBitmap()`) onto this canvas. All coordinates are LOGICAL —\n * including the source sub-rect in the 9-arg form (it's scaled by the bitmap's pixelRatio here).\n * Records a DRAW_IMAGE op, so the blit runs at bake time: keep the Bitmap alive until the next\n * `update()`/`toBitmap()`/`texture()`. Three browser-style forms:\n * drawImage(bmp, dx, dy) — whole bitmap at its natural size\n * drawImage(bmp, dx, dy, dw, dh) — whole bitmap, scaled into dw×dh\n * drawImage(bmp, sx, sy, sw, sh, dx, dy, dw, dh) — a sub-rect of the bitmap, scaled into dw×dh */\n drawImage(img: Bitmap, dx: number, dy: number): this;\n drawImage(img: Bitmap, dx: number, dy: number, dw: number, dh: number): this;\n drawImage(img: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): this;\n /** Decode an image source into a standalone `Bitmap` you can blit with `drawImage()` — either an\n * `SvgSource(...)` (rasterized) or a `FetchResponse` holding already-fetched image bytes (decoded).\n * This is async because turning SVG markup / encoded bytes into pixels needs a decode step (on the\n * web, `createImageBitmap` / an `<img>` load); `await` it ONCE, then `drawImage(bitmap, …)` is\n * synchronous and the Bitmap is reusable. The returned Bitmap owns a native surface at the image's\n * natural pixel size (`pixelRatio` 1) — `destroy()` it when done. Typical use:\n * const logo = await canvas.loadImage(SvgSource(svg)) // or: await fetch(url) → the response\n * canvas.drawImage(logo, 0, 0) // sync, blit as often as you like */\n loadImage(source: SvgSourceValue | FetchResponse): Promise<Bitmap>;\n /** Measure `text` in the current font on THIS platform. The one synchronous round-trip. */\n measureText(text: string): CanvasTextMetrics;\n /** Bake and return the 2D texture (created once, then cached). */\n texture(): Texture2D;\n /** Re-rasterize and re-upload to every texture this canvas produced (call after redrawing) — the\n * cached 2D and/or 3D texture, whichever engines this canvas was baked into. */\n update(): this;\n /** Copy the current pixels into a standalone, immutable `Bitmap` — independent of this canvas, so\n * later drawing/`reset()` never touches it. Draw it back with `drawImage()`, export it with\n * `toDataURL()`, or use it to \"flatten\" an ever-growing drawing so re-bakes stay O(1):\n * const snap = canvas.toBitmap()\n * canvas.reset(); canvas.drawImage(snap, 0, 0) // one op replaces the whole history\n * // …keep drawing on top; snap.destroy() once it's been drawn in. */\n toBitmap(): Bitmap;\n /** Encode the current pixels to an image `File` — 'image/png' (default) or 'image/jpeg'. The File\n * is an opaque host buffer handle (`name`/`size` only): append it to a FormData to upload, load it\n * as a texture (`Texture2D.load(file)`), or hand it to a share/save sheet. */\n toFile(name?: string, type?: string): Promise<File>;\n destroy(): void;\n}\n/** Duck-type guard so consumers can accept a Canvas anywhere a texture source is expected. */\nexport declare const isCanvas: (v: unknown) => v is Canvas;\n/** An immutable RGBA8 snapshot of a canvas, produced by `Canvas.toBitmap()`. It owns its own baked\n * surface (a copy), so the source canvas can keep drawing or `reset()` without affecting it. Use it\n * to stamp/blit back (`canvas.drawImage(bitmap, …)`), to export (`bitmap.toDataURL()`), or as a\n * cheap \"layer\" you composite. Call `destroy()` when done — it holds a native surface. */\nexport declare class Bitmap {\n readonly __bitmap: true;\n /** Logical width, matching the Canvas it was captured from (pixelRatio is crispness, not size). */\n readonly width: number;\n readonly height: number;\n readonly pixelRatio: number;\n constructor(surfaceId: number, width: number, height: number, pixelRatio: number);\n /** Device-pixel dimensions of the stored bitmap (`width * pixelRatio`, rounded). */\n get pixelWidth(): number;\n get pixelHeight(): number;\n /** Encode to an image `File` — 'image/png' (default) or 'image/jpeg'. See `Canvas.toFile`. */\n toFile(name?: string, type?: string): Promise<File>;\n /** Free the native surface. The bitmap must not be drawn or encoded afterwards. */\n destroy(): void;\n}\n/** Duck-type guard for a Bitmap (see `isCanvas`). */\nexport declare const isBitmap: (v: unknown) => v is Bitmap;\nexport {};\n","types/g2/loop.d.ts":"export declare const onUpdate: (callback: (dt: number) => void) => void;\nexport declare const offUpdate: (callback: (dt: number) => void) => void;\nexport declare const ensureAnimEvents: () => void;\nexport declare const ensurePhysicsEvents: () => void;\n","types/g2/touch.d.ts":"/** Register the host pointer callback once, on the first click/touchstart listener (node or scene). */\nexport declare const ensurePointerEvents: () => void;\n","types/g2/Texture2D.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture2D {\n /** Native texture handle. */\n readonly id: number;\n readonly width: number;\n readonly height: number;\n constructor(id: number, width: number, height: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n }): Texture2D;\n static load(source: string | FetchResponse | File): Promise<Texture2D>;\n destroy(): void;\n}\n","types/g2/Trigger2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Trigger2D extends Aspect<\"trigger\", Node2D> {\n static readonly aspect = \"trigger\";\n private _h;\n /** Native physics body id (0 if no physics support). Mirrors 3D `Trigger.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec2Like): this;\n}\n","types/g2/Camera2D.d.ts":"import { Vec2, type Vec2Like } from \"../math/vec\";\nexport declare class Camera2D {\n private _x;\n private _y;\n private _zoom;\n private _rotation;\n private readonly sceneId;\n constructor(sceneId: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n get zoom(): number;\n set zoom(z: number);\n get rotation(): number;\n set rotation(deg: number);\n screenToWorld(screenX: number, screenY: number): Vec2;\n worldToScreen(worldX: number, worldY: number): Vec2;\n}\n","types/g2/Shape2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Shape2D extends Aspect<\"shape\", Node2D> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hw, hh] (world units). */\n box?: Vec2Like;\n /** Circle radius. */\n circle?: number;\n /** Capsule between two local points, with a radius. */\n capsule?: {\n from: Vec2Like;\n to: Vec2Like;\n radius: number;\n };\n /** Thin segment (an edge — for static ground/walls/slopes) between two local points. */\n segment?: {\n from: Vec2Like;\n to: Vec2Like;\n };\n /** Convex polygon, up to 8 local points (a convex hull is computed). */\n polygon?: Vec2Like[];\n /** Local offset of the shape from the node origin. */\n offset?: Vec2Like;\n}\n","types/g2/Node2D.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nexport { Vec2, type Vec2Like };\nexport type Node2DEvents = {\n /** A looping animation clip wrapped around (fires each loop). */\n loopReached: (clip: string) => void;\n /** A non-looping animation clip finished. */\n completed: (clip: string) => void;\n /** A physics contact / sensor overlap began / ended (the other node). */\n enter: (other: Node2D) => void;\n exit: (other: Node2D) => void;\n /** Pointer up over this node's Physics2D shape (a tap/click). */\n click: (ev: ClickEvent<Node2D | null>) => void;\n /** Pointer down on this node's Physics2D shape. Call ev.track(...) to capture the drag. */\n touchstart: (ev: TouchStartEvent<Node2D | null>) => void;\n};\n/** id → Node2D, so host callbacks (animation events) route back to the owning JS object. */\nexport declare const node2dRegistry: Registry<Node2D>;\nexport declare class Node2D extends AspectHost<Node2DEvents> {\n /** Native entity handle. */\n readonly id: number;\n protected _x: number;\n protected _y: number;\n protected _rotation: number;\n protected _sx: number;\n protected _sy: number;\n protected _layer: number;\n protected _z: number;\n protected _visible: boolean;\n private _parent;\n private _children;\n constructor(internalId?: number);\n private _pull;\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n /** Rotation in degrees (CCW). */\n get rotation(): number;\n set rotation(deg: number);\n get scale(): Vec2;\n set scale(v: Vec2Like | number);\n /** Draw layer (int). Higher layers render on top. */\n get layer(): number;\n set layer(v: number);\n /** Intra-layer depth for non-Y-sorted layers (higher z = on top). */\n get z(): number;\n set z(v: number);\n get visible(): boolean;\n set visible(v: boolean);\n get parent(): Node2D | null;\n set parent(p: Node2D | null);\n get children(): readonly Node2D[];\n /** Attach children to this node (each keeps its current world transform). Returns this. */\n add(...children: Node2D[]): this;\n /** Detach a direct child (reparents it to root, keeping its world transform). Returns this. */\n remove(child: Node2D): this;\n /**\n * Reparent this node. `keepWorld` (default true) recomputes the local transform so the on-screen\n * position/rotation/scale is unchanged; pass false to keep the local transform and move with the\n * new parent. Self/descendant parents are rejected natively (no cycles).\n */\n setParent(parent: Node2D | null, keepWorld?: boolean): this;\n /** World-space position (composes all ancestors). */\n get worldPosition(): Vec2;\n /** Convert a world-space point into this node's local space (and back). */\n worldToLocal(p: Vec2Like): Vec2;\n localToWorld(p: Vec2Like): Vec2;\n private _syncLocalFromNative;\n addEventListener<K extends keyof Node2DEvents>(channel: K, callback: Node2DEvents[K]): void;\n destroy(): void;\n}\n","types/g2/SpriteAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Sprite } from \"./Sprite\";\n/** Per-clip frame list, or an object for per-clip fps/loop overrides. */\nexport type Clip = number[] | {\n frames: number[];\n fps?: number;\n loop?: boolean;\n};\nexport declare class SpriteAnimation extends Aspect<\"anim\", Sprite> {\n static readonly aspect = \"anim\";\n /** Grid cell size in texture pixels (defaults to the full texture). */\n size?: [number, number];\n /** Default fps for clips that don't override it. */\n fps: number;\n /** Default loop for clips that don't override it. */\n loop: boolean;\n /** Named clips; frame indices are row-major into the grid. Set via the attach opts. */\n clips: Record<string, Clip>;\n private _clipIds;\n private _clipNames;\n private _current;\n onAttach(): void;\n /** (Re)build native clips from `this.clips`. Called on attach; call again after changing clips. */\n define(): this;\n private _define;\n /** Play a clip by name. Re-playing the active clip is a no-op (keeps it running smoothly). */\n play(name: string): this;\n stop(): this;\n set speed(value: number);\n get current(): string | null;\n get frame(): number;\n}\n","types/g2/Tilemap.d.ts":"import { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\nexport type TilemapOptions = {\n texture: Texture2D;\n /** Map grid size (in tiles). */\n cols: number;\n rows: number;\n /** On-screen cell size in world units — a single number (square) or [w, h]. */\n tile: number | [number, number];\n /** Atlas grid: how the texture is sliced into tiles, [atlasCols, atlasRows]. */\n atlas: [number, number];\n /** Row-major tile indices into the atlas (-1 = empty), length cols*rows. Row 0 is the top row. */\n data: number[] | Int32Array;\n};\nexport declare class Tilemap extends Node2D {\n readonly cols: number;\n readonly rows: number;\n constructor(options: TilemapOptions);\n setTile(x: number, y: number, index: number): this;\n}\n","types/g2/Sprite.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\n/** Anything that can back a sprite: a texture, or a Canvas (baked to a texture on assign). */\nexport type TextureSource = Texture2D | Canvas;\nexport type SpriteOptions = {\n texture?: TextureSource;\n /** Pivot, [0,0] = top-left .. [1,1] = bottom-right. Use [0.5, 1] (feet) for Y-sorted depth. */\n anchor?: Vec2Like;\n /** World size; defaults to the texture's pixel dimensions. */\n size?: Vec2Like;\n /** Normalized UV sub-rect [u0,v0,u1,v1]. */\n frame?: [number, number, number, number];\n /** Tint multiplied with the texture. */\n color?: ColorInput;\n opacity?: number;\n layer?: number;\n position?: Vec2Like;\n};\nexport declare class Sprite extends Node2D {\n private _texture?;\n private _anchor;\n private _color;\n private _opacity;\n private _flipX;\n private _flipY;\n private _size;\n constructor(options?: SpriteOptions);\n get texture(): Texture2D | undefined;\n set texture(t: TextureSource | undefined);\n /** Current world size: explicit override if set, else the texture's pixel dimensions (a Canvas-backed\n * sprite defaults to the canvas's LOGICAL size, so pixelRatio is crispness only, not size). */\n get size(): Vec2;\n set size(v: Vec2Like);\n get anchor(): Vec2;\n set anchor(v: Vec2Like);\n /** Set the UV sub-rect (normalized). */\n set frame(uv: [number, number, number, number]);\n /** Set the sub-rect in texture pixels. */\n setFramePx(px: number, py: number, pw: number, ph: number): this;\n get color(): ColorInput;\n set color(c: ColorInput);\n get opacity(): number;\n set opacity(a: number);\n get flipX(): boolean;\n set flipX(v: boolean);\n get flipY(): boolean;\n set flipY(v: boolean);\n}\n","types/g2/Scene2D.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport { Camera2D } from \"./Camera2D\";\nimport { type Node2D } from \"./Node2D\";\nexport type Scene2DOptions = {\n /** Background color — '#10131a', 0x10131a, or [r,g,b]/[r,g,b,a] in 0..1. */\n background?: ColorInput;\n /** Texture sampling for the 2D renderer: `'nearest'` (default — crisp pixel art) or `'linear'`\n * (smooth — for hi-res / non-pixel-art assets). Applied when the scene is opened, so switching\n * scenes restores the active scene's choice. NOTE: this is a GLOBAL renderer setting (one sampler\n * for ALL textures, not per-texture), so the currently-open scene's filter wins. Omit to leave the\n * current setting (engine default is nearest). */\n filter?: 'nearest' | 'linear';\n};\n/** Returned by scene2d.layer(n); chain .ySort() to enable top-down depth sorting for that layer. */\ndeclare class LayerHandle {\n private readonly sceneId;\n private readonly layer;\n constructor(sceneId: number, layer: number);\n /** In this layer, lower-on-screen sprites overlap higher ones (top-down feet sorting). */\n ySort(enabled?: boolean): this;\n}\nexport declare class Scene2D implements Presentable {\n /** Native scene handle. */\n readonly id: number;\n readonly camera: Camera2D;\n private static _active;\n static get active(): Scene2D | null;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node2D | null>) => void>;\n /** Texture filter to (re)assert on open(); the sampler is global, so each scene reclaims it. */\n private readonly _filter?;\n constructor(options?: Scene2DOptions);\n set background(color: ColorInput);\n /** Address a draw layer to configure it, e.g. scene2d.layer(1).ySort(). */\n layer(n: number): LayerHandle;\n /** Topmost visible sprite whose world bounds contain the world point, or null. Body-free\n * hit-test for tap/click picking — pair with camera.screenToWorld(). */\n pick(worldPoint: Vec2Like): Node2D | null;\n /** Scene-level pointer events. The handler fires for every tap/press in the scene, with\n * `ev.target` = the hit Physics2D node (or null). On 'touchstart' you can ev.track(...) a drag. */\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node2D | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node2D | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n add(...nodes: Node2D[]): this;\n remove(...nodes: Node2D[]): this;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): this;\n close(): this;\n destroy(): void;\n}\nexport {};\n","types/g2/CharacterController2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class CharacterController2D extends Aspect<\"controller\", Node2D> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Extra probe distance below the body's feet used for the grounded check (world units). */\n groundProbe: number;\n /** Distance from the node origin down to the feet. Defaults to half the sprite height. */\n footOffset?: number;\n private _moveX;\n private _jumpQueued;\n private _grounded;\n /** Horizontal intent in [-1, 1] (e.g. from input). Sticky — set 0 to stop. Applied next frame. */\n move(dir: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on something (updated each frame). */\n get grounded(): boolean;\n private get phys();\n onAttach(): void;\n update(_dt: number): void;\n private _spriteHalfHeight;\n}\n","types/g2/Physics2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { type Node2D } from \"./Node2D\";\nexport type MotionType = \"static\" | \"kinematic\" | \"dynamic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -980]. */\n gravity?: Vec2Like;\n /** Pixels per meter — tunes Box2D's internal tolerances; you still author in world units. Default 64. */\n pixelsPerMeter?: number;\n /** Solver sub-steps per fixed step. Default 4. */\n subSteps?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node2D | null;\n point: Vec2;\n normal: Vec2;\n fraction: number;\n}\nexport declare class Physics2D extends Aspect<\"physics\", Node2D> {\n static readonly aspect = \"physics\";\n /** Default \"dynamic\". */\n motion: MotionType;\n density: number;\n friction: number;\n restitution: number;\n /** Lock rotation (essential for platformer characters). */\n fixedRotation: boolean;\n /** Continuous collision for fast-moving bodies (projectiles). */\n bullet: boolean;\n private _gravityScale;\n private _h;\n /** Native physics body id. 0 until attached, or if the build has no physics support. Mirrors 3D `Physics.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Linear velocity in world units/second (fresh Vec2 on read). */\n get velocity(): Vec2;\n set velocity(v: Vec2Like);\n /** Angular velocity in degrees/second. */\n set angularVelocity(degPerSec: number);\n /** Per-body gravity multiplier: 1 = full world gravity, 0 = floats, <0 = repelled. Set at attach\n * time (as an option) or live. */\n get gravityScale(): number;\n set gravityScale(scale: number);\n set linearDamping(d: number);\n set enabled(v: boolean);\n /** Apply an instantaneous impulse (world units) and wake the body. */\n applyImpulse(v: Vec2Like): this;\n /** Apply a continuous force (world units) and wake the body. */\n applyForce(v: Vec2Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position (+ optional rotation degrees). */\n moveTo(p: Vec2Like, deg?: number): this;\n /** Create / reset the physics world. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_2D_PHYSICS). */\n static get supported(): boolean;\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Closest body hit by the segment from→to, or null. `node` resolves the hit entity. */\n static raycast(from: Vec2Like, to: Vec2Like): RayHit | null;\n /** Topmost body (solid or sensor) whose shape contains the world point, or null. */\n static overlapPoint(p: Vec2Like): Node2D | null;\n}\n","types/gl/Model.d.ts":"import { type FetchResponse } from \"../runtime/fetch\";\nimport { Node } from \"./Node\";\nimport { ModelAnimation } from \"./ModelAnimation\";\nexport declare class Model extends Node {\n /** GLB skeletal animation — always present on a Model. */\n readonly anim: ModelAnimation;\n constructor(internalId: number);\n /** Duplicate this model — a deep copy of the GLB (meshes, skeleton, animation clips), attached to\n * the same parent and scene and sharing this model's current transform. The clone has its own\n * independent animation state (reach it via clone.anim). Mirrors Model.load's culling default. */\n clone(): Model;\n /** Load a GLB model. Returns its root as a Model; play its baked clips via model.anim. */\n static load(source: string | FetchResponse, options?: {\n culling?: boolean;\n onProgress?: (p: {\n loaded: number;\n total?: number;\n }) => void;\n }): Promise<Model>;\n}\n","types/gl/Shape.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Shape extends Aspect<\"shape\", Node> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hx, hy, hz] (world units). */\n box?: Vec3Like;\n /** Sphere radius. */\n sphere?: number;\n /** Cylinder aligned on Y: half-height + radius. */\n cylinder?: {\n halfHeight: number;\n radius: number;\n };\n /** Capsule aligned on Y: half-height of the cylinder section + radius. */\n capsule?: {\n halfHeight: number;\n radius: number;\n };\n /** Whether pointer rays can hit this shape (click / touchstart). Default true. */\n raycast: boolean;\n private _shapeId;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n private _createPickBody;\n private _build;\n}\n","types/gl/Geometry.d.ts":"import { type Vec3Like } from \"../math/vec\";\nexport type MeshKind = \"triangles\" | \"vertices\" | \"edges\";\nexport declare class Geometry {\n vertices: Float32Array;\n normals: Float32Array;\n indices: Uint16Array;\n uv: Float32Array;\n constructor(vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array);\n translate(x: number, y: number, z: number): this;\n scale(x: number, y: number, z: number): this;\n scaleUV(x: number, y: number): this;\n set kind(kind: MeshKind);\n static box(): Geometry;\n static sphere(options?: SphereOptions): Geometry;\n static cylinder(options?: CylinderOptions): Geometry;\n static plane(options?: PlaneOptions): Geometry;\n}\nexport type SphereOptions = {\n radius?: number;\n widthSegments?: number;\n heightSegments?: number;\n};\nexport type CylinderOptions = {\n radius?: number;\n radiusTop?: number;\n radiusBottom?: number;\n edges?: number;\n smooth?: boolean;\n};\nexport type PlaneOptions = {\n normal?: Vec3Like;\n};\n","types/gl/physicsEvents.d.ts":"export declare const ensurePhysicsEvents: () => void;\n","types/gl/touch.d.ts":"export declare const registerTouchStartEvent: () => void;\nexport declare const registerTouchEndEvent: () => void;\n","types/gl/controls.d.ts":"import type { Node } from \"./Node\";\nimport type { Scene } from \"./Scene\";\nexport type ControlsOptions = {\n /** Smallest uniform scale the pinch gesture allows (default 0.08). */\n minScale?: number;\n /** Largest uniform scale the pinch gesture allows (default 2). */\n maxScale?: number;\n /** One-finger drag moves the target across the ground plane (default true). */\n pan?: boolean;\n /** Two-finger pinch scales the target (default true). */\n pinch?: boolean;\n /** Two-finger twist rotates the target around its Y axis (default true). */\n twist?: boolean;\n};\n/** Returned by `addControls` — call `remove()` to detach the gesture listeners. */\nexport type ControlsHandle = {\n remove(): void;\n};\nexport declare const attachControls: (scene: Scene, target: Node, options?: ControlsOptions) => ControlsHandle;\n","types/gl/Plane.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nimport type { Ray } from \"./Ray\";\nexport declare class Plane {\n /** Unit normal. */\n readonly normal: Vec3;\n /** Scalar offset: dot(normal, point). */\n readonly d: number;\n constructor(normal: Vec3Like, point: Vec3Like);\n static fromPoints(a: Vec3Like, b: Vec3Like, c: Vec3Like): Plane;\n static fromCoefficients(a: number, b: number, c: number, d: number): Plane;\n /** Ray-plane parameter t (≥0), or null on a miss (parallel / behind origin). */\n intersectRay(ray: Ray): number | null;\n /** Like intersectRay but allows hits behind the origin (line-plane). */\n intersectLine(ray: Ray): number | null;\n /** Signed distance from a point (positive on the normal's side). */\n signedDistance(point: Vec3Like): number;\n /** Project a point onto the plane. */\n projectPoint(point: Vec3Like): Vec3;\n}\n","types/gl/state.d.ts":"import type { Scene } from \"./Scene\";\nexport declare const glState: {\n activeScene: Scene | null;\n};\n","types/gl/Camera.d.ts":"import { Vec3 } from \"../math/vec\";\nimport { Node } from \"./Node\";\nimport { Ray } from \"./Ray\";\nexport declare class Camera extends Node {\n private _sceneId;\n /** Live projection matrix (updated by the host when the viewport/fov changes). */\n readonly projectionMatrix: Float32Array<ArrayBuffer>;\n get fov(): number;\n get horizontalFov(): number;\n get displaySize(): [number, number];\n /** World-space ray direction through a screen pixel. */\n getViewDirection(screenX: number, screenY: number): Vec3;\n /** A pick ray from the camera through a screen pixel. */\n getRay(screenX: number, screenY: number): Ray;\n}\n","types/gl/Mesh.d.ts":"import { type Vec3Like } from \"../math/vec\";\nimport { Geometry, type CylinderOptions, type PlaneOptions, type SphereOptions } from \"./Geometry\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\n/** Common transform/render options every primitive factory accepts. */\nexport type MeshOptions = {\n material?: Material;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n name?: string;\n castShadows?: boolean;\n receiveShadows?: boolean;\n};\nexport declare class Mesh extends Node {\n private _geometry?;\n private _materials;\n constructor(geometry?: Geometry, material?: Material);\n get geometry(): Geometry | undefined;\n get material(): Material;\n set material(m: Material);\n setMaterial(material: Material, index?: number): this;\n getMaterial(index?: number): Material | null;\n set culling(v: boolean);\n set castShadows(v: boolean);\n set receiveShadows(v: boolean);\n static box(options?: MeshOptions & {\n size?: Vec3Like | number;\n }): Mesh;\n static sphere(options?: MeshOptions & SphereOptions): Mesh;\n static cylinder(options?: MeshOptions & CylinderOptions): Mesh;\n static plane(options?: MeshOptions & PlaneOptions): Mesh;\n /** Wrap a custom Geometry. */\n static from(geometry: Geometry, options?: MeshOptions): Mesh;\n}\n","types/gl/Noise.d.ts":"export declare class Noise {\n private readonly _id;\n constructor();\n /** Sample 2D noise. */\n get(x: number, y: number): number;\n /** Sample 3D noise. */\n get3d(x: number, y: number, z: number): number;\n private _frequency;\n get frequency(): number;\n set frequency(v: number);\n private _octaves;\n get octaves(): number;\n set octaves(v: number);\n private _fractalLacunarity;\n get fractalLacunarity(): number;\n set fractalLacunarity(v: number);\n private _fractalGain;\n get fractalGain(): number;\n set fractalGain(v: number);\n}\n","types/gl/Trigger.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Trigger extends Aspect<\"trigger\", Node> {\n static readonly aspect = \"trigger\";\n private _bodyId;\n /** Native body id (0 if no physics support). */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec3Like): this;\n}\n","types/gl/ModelAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Model } from \"./Model\";\nexport declare class ModelAnimation extends Aspect<\"anim\", Model> {\n static readonly aspect = \"anim\";\n private _playing;\n private _clip;\n private _speed;\n private _loop;\n onAttach(): void;\n /** The clips baked into the glb. */\n get clips(): {\n name: string;\n duration: number;\n }[];\n get playing(): boolean;\n set playing(value: boolean);\n /** Play a clip by name or index. Chainable. */\n play(clip?: string | number, options?: {\n loop?: boolean;\n }): this;\n stop(): this;\n get loop(): boolean;\n set loop(v: boolean);\n get speed(): number;\n set speed(v: number);\n get time(): number;\n set time(v: number);\n}\n","types/gl/CharacterController.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3 } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class CharacterController extends Aspect<\"controller\", Node> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Character-tuned gravity (world units/s²), separate from the world gravity — usually stronger for\n * snappier feel. Applied to the vertical velocity each frame. */\n gravity: number;\n /** Max ground slope (degrees) the character treats as walkable. Set before attach. */\n maxSlope: number;\n updateBeforePhysics: boolean;\n private _charId;\n private _mx;\n private _mz;\n private _jumpQueued;\n private _vy;\n onAttach(): void;\n onDetach(): void;\n /** Native character id (0 until attached / no physics support). */\n get id(): number;\n /** Horizontal move intent; each component in [-1, 1] (e.g. from input). Sticky — set 0 to stop. */\n move(x: number, z: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on walkable ground (OnGround). */\n get grounded(): boolean;\n /** Ground state: 0 on-ground, 1 on-steep-slope, 2 touching-but-unsupported, 3 in-air. */\n get groundState(): number;\n /** Current velocity (world units/s, fresh Vec3). */\n get velocity(): Vec3;\n /** Teleport to a world position (clears vertical velocity). */\n teleport(x: number, y: number, z: number): this;\n update(dt: number): void;\n}\n","types/gl/Scene.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport type { FetchResponse } from \"../runtime/fetch\";\nimport { Camera } from \"./Camera\";\nimport { type ControlsHandle, type ControlsOptions } from \"./controls\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\nexport type SceneOptions = {\n /** Image-based ambient lighting (default on). */\n ibl?: boolean;\n /** IBL intensity (default 20000). */\n environmentIntensity?: number;\n /** Bloom post-processing. */\n bloom?: boolean;\n bloomIntensity?: number;\n /** Skybox / clear color. */\n skybox?: ColorInput;\n /** Multisample anti-aliasing. */\n antialias?: boolean;\n};\nexport declare class Scene implements Presentable {\n readonly camera: Camera;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node | null>) => void>;\n private _material?;\n private static _active;\n static get active(): Scene | null;\n constructor(options?: SceneOptions);\n /** Scene occlusion material. */\n get occlusionMaterial(): Material;\n set skybox(color: ColorInput);\n setMaterialGlobalParameter(i: number, x: number, y: number, z: number, w: number): void;\n setAntialias(enabled: boolean, scale?: number): void;\n add(...nodes: Node[]): this;\n remove(...nodes: Node[]): this;\n createOverlay(options?: SceneOptions): Scene;\n warmRender(): Promise<void>;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): void | Promise<void>;\n close(): void;\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n}\nexport type ARMode = \"default\" | \"markers\" | \"arcore\" | \"detached\";\nexport declare class ARScene<T extends ARMode = \"default\"> extends Scene {\n readonly mode: T;\n useWarmRender: boolean;\n private _root?;\n constructor(options?: SceneOptions & {\n mode?: T;\n });\n /** Root anchor node (not available in marker mode). */\n get root(): Node;\n /** Create an anchor from a tracking source (e.g. an image target). */\n createAnchor(source: FetchResponse, physicalWidth?: number): Node;\n /**\n * Let the user place & manipulate a node with touch gestures — the staple AR object-placement\n * interaction: ONE finger drags it across the floor (relative to where the camera looks), TWO fingers\n * pinch to scale and twist to rotate. Returns a handle; call `.remove()` to detach. Tunable via\n * options (min/max scale, and toggles for `pan` / `pinch` / `twist`).\n */\n addControls(target: Node, options?: ControlsOptions): ControlsHandle;\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n/**\n * A 3D scene rendered in a VR headset (OpenXR — e.g. Meta Quest). The headset drives the camera:\n * every frame both eyes are rendered from the tracked head pose, so `scene.camera` position/lookAt\n * have no effect while the scene is open. The world origin is at floor level (stage space) —\n * author content with the ground at y = 0 and the user standing at the origin.\n *\n * `open()` rejects on hosts without a VR runtime (\"VR is not supported on this device\").\n */\nexport declare class VRScene extends Scene {\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n","types/gl/Light.d.ts":"import { type ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Node } from \"./Node\";\nexport type SunOptions = {\n /** Light direction (points where the light travels). Defaults to a typical key-light angle. */\n direction?: Vec3Like;\n /** Luminous intensity. */\n intensity?: number;\n color?: ColorInput;\n /**\n * Shadow quality (default 1):\n * 0 - no shadows\n * 1 - standard (1024 shadow map, hard PCF edges)\n * 2 - high (2048 + stable, soft contact-hardening edges)\n * 3 - best (4096 + stable, PCSS soft shadows)\n * Higher values cost more GPU/memory.\n */\n shadowsQuality?: 0 | 1 | 2 | 3;\n};\nexport declare class Light extends Node {\n /** A directional sun light. */\n static sun(options?: SunOptions): Light;\n}\n","types/gl/Particles.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type Vec3Like } from \"../math/vec\";\nimport { Material, type ParticlesMaterialOptions } from \"./Material\";\nimport { Node } from \"./Node\";\ntype Range<T> = T | {\n min: T;\n max: T;\n};\nexport declare class CurveBuilder {\n private _kind;\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<number>, mode: \"multiply\" | \"add\");\n /** Curve value at birth (t = 0). Must come before any other stop. */\n from(v: Range<number>): this;\n /** Curve value at `t` (0..1 of the particle's life). Stops must be added in ascending t order. */\n via(t: number, v: Range<number>): this;\n /** Curve value at death (t = 1). */\n to(v: Range<number>): this;\n /** The classic opacity envelope: rise over the first `fadeIn`, fall over the last `fadeOut`. */\n fade(fadeIn?: number, fadeOut?: number): this;\n /** The PARAM_CURVE record payload (sans slot): [kind, baseLo, baseHi, n, (t, lo, hi)×n]. */\n get _data(): Float32Array;\n}\nexport declare class ColorCurveBuilder {\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<ColorInput>);\n /** Curve color at birth (t = 0). Must come first. The curve multiplies the base color. */\n from(c: Range<ColorInput>): this;\n /** Curve color at `t` (0..1 of the particle's life), in ascending t order. */\n via(t: number, c: Range<ColorInput>): this;\n /** Curve color at death (t = 1). */\n to(c: Range<ColorInput>): this;\n /** The COLOR_CURVE record payload: [baseLo rgba, baseHi rgba, n, (t, lo rgba, hi rgba)×n]. */\n get _data(): Float32Array;\n}\n/** A value curve over each particle's lifetime. Default mode `multiply` (the curve scales the\n * base); `add` offsets it instead. */\nexport declare const curve: (base?: Range<number>, mode?: \"multiply\" | \"add\") => CurveBuilder;\n/** A color curve over each particle's lifetime — always multiplies the base color. */\nexport declare const colorCurve: (base?: Range<ColorInput>) => ColorCurveBuilder;\nexport type ParticleValue = Range<number> | CurveBuilder | {\n _data: Float32Array;\n};\nexport type ParticleColor = ColorInput | {\n min: ColorInput;\n max: ColorInput;\n} | ColorCurveBuilder | {\n _data: Float32Array;\n};\ntype VelocityValue = {\n speed?: Range<number>;\n /** Cone half-angle in radians — jitter the launch direction uniformly within it. */\n spread?: number;\n /** Asymmetric jitter: two angles (u, v — the x/y components) in radians. */\n randomizeAngle?: {\n min: Vec3Like;\n max: Vec3Like;\n };\n} & ({\n from: Vec3Like;\n} | {\n to: Vec3Like;\n} | {\n dir: Vec3Like;\n} | {});\ntype Shape = {\n type: \"point\";\n v: Vec3Like;\n} | {\n type: \"box\";\n min: Vec3Like;\n max: Vec3Like;\n} | {\n type: \"circle\";\n center: Vec3Like;\n radius: number;\n};\ntype Noise = {\n strength?: number;\n frequency?: number;\n speed?: number;\n};\nexport type ParticlesOptions = ParticlesMaterialOptions & {\n /** Custom draw material. Unset = the default point-sprite material, configured by the\n * `ParticlesMaterialOptions` sugar (map/sheet/emissive/blend/soft) — which is ignored\n * when an explicit material is passed. */\n material?: Material;\n /** Particle pool capacity (default 1000). */\n maxParticles?: number;\n /** Particles emitted per second. */\n rate?: number;\n /** Simulation space. `'local'` (default) — particles ride the node's transform; `'world'` —\n * each particle stays where it was born as the emitter moves on (trails: drift smoke, mud,\n * wake). Switching at runtime resets live particles. */\n space?: \"local\" | \"world\";\n /** Fraction (usually 0..1) of the emitter's own velocity added to each particle at spawn —\n * smoke \"thrown\" off a moving car. Takes effect with `space: 'world'`. */\n inheritVelocity?: number;\n /** Particles emitted per world unit the emitter MOVES, on top of `rate`, with spawn points\n * spread evenly along the path — trail density independent of speed, no per-frame clumps.\n * Meant for `space: 'world'`. */\n rateOverDistance?: number;\n shape?: Shape;\n startVelocity?: Vec3Like | VelocityValue;\n /** Downward acceleration, world units/s² — positive pulls particles DOWN (sugar for\n * `acceleration: [0, -g, 0]`). */\n gravity?: number;\n /** Constant acceleration vector (gravity, wind, …). Wins over `gravity` when both are set. */\n acceleration?: Vec3Like;\n drag?: number;\n lifetime?: Range<number>;\n color?: ParticleColor;\n /** World-unit diameter (alias of custom[0]). Default 1. */\n size?: ParticleValue;\n /** Radians (alias of custom[1]). */\n rotation?: ParticleValue;\n /** Per-particle opacity 0..1 (alias of custom[2]). Default 1. */\n opacity?: ParticleValue;\n /** Flipbook frame index (alias of custom[3]). With `sheet` set and no explicit frame, the\n * default is one full sheet cycle over each particle's lifetime, starting at `startFrame`. */\n frame?: ParticleValue;\n /** Where the default flipbook cycle begins: `'random'` (default — desynchronized loops like\n * fire/smoke) or a frame index (`0` plays the sheet in order — explosions, one-shot bursts).\n * Only shapes the default; an explicit `frame` wins. */\n startFrame?: number | \"random\";\n noise?: Noise | null;\n /** Fixed random seed for deterministic tests. */\n seed?: number;\n};\nexport declare class Particles extends Node {\n private _material;\n /** Custom curve-param slots (0..3); size/rotation/opacity/frame alias slots 0-3. */\n readonly custom: ParticleValue[];\n constructor(options?: ParticlesOptions);\n /** Emit `count` particles immediately (a burst). */\n spawn(count: number): this;\n private _send;\n set rate(val: number);\n /** `'world'` leaves particles behind where they were born (trails). Switching resets live ones. */\n set space(val: \"local\" | \"world\");\n set inheritVelocity(val: number);\n set rateOverDistance(val: number);\n set shape(shape: Shape);\n set startVelocity(val: Vec3Like | VelocityValue);\n /** Positive pulls particles down — sugar for `acceleration = [0, -g, 0]`. */\n set gravity(val: number);\n set acceleration(a: Vec3Like);\n set drag(val: number);\n set seed(val: number);\n set lifetime(val: Range<number>);\n set size(val: ParticleValue);\n set rotation(val: ParticleValue);\n set opacity(val: ParticleValue);\n set frame(val: ParticleValue);\n set color(value: ParticleColor);\n get material(): Material;\n set material(material: Material);\n set noise(noise: Noise | null);\n}\n/** `Trail` options. The look options (map/sheet/emissive/blend/soft) come from\n * `ParticlesMaterialOptions`, same as `Particles`. */\nexport type TrailOptions = Omit<ParticlesMaterialOptions, \"render\" | \"stretch\"> & {\n /** Seconds each trail point lives — the trail's length in time. Default 0.5. */\n time?: number;\n /** Strip width in world units; a curve tapers it over each point's life (head → tail).\n * Default 0.1. */\n width?: ParticleValue;\n /** Minimum emitter movement (world units) between recorded points. Default 0.05. */\n minDistance?: number;\n /** Point capacity (default 128). */\n maxPoints?: number;\n color?: ParticleColor;\n /** Opacity along the trail. Defaults to fading the tail out (`curve().to(0)`). */\n opacity?: ParticleValue;\n};\n/** A ribbon strip that follows this node through the world — sword swings, skid marks, missile\n * trails. Attach it to (or under) the moving node and just move; points are laid down per\n * `minDistance` of movement, live for `time` seconds, and the strip stays glued to the node at\n * its head. Width/opacity/color accept the same curves as `Particles`, evaluated over each\n * point's life — i.e. along the trail from head (fresh) to tail (dying). */\nexport declare class Trail extends Node {\n private _material;\n private _rateDistance;\n constructor(options?: TrailOptions);\n private _send;\n /** Trail length in seconds — how long each laid-down point lives. */\n set time(val: number);\n set width(val: ParticleValue);\n set opacity(val: ParticleValue);\n set color(value: ParticleColor);\n set minDistance(val: number);\n /** Pause/resume laying down points — existing ones still age out, so the trail fades naturally\n * after e.g. a sword swing ends. */\n set emitting(val: boolean);\n get material(): Material;\n}\nexport {};\n","types/gl/Ray.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nexport declare class Ray {\n readonly origin: Vec3;\n readonly dir: Vec3;\n constructor(origin: Vec3Like, dir: Vec3Like);\n /** The world-space point origin + t·dir. */\n getPoint(t: number): Vec3;\n}\n","types/gl/Physics.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { type Node } from \"./Node\";\nexport type MotionType = \"static\" | \"dynamic\" | \"kinematic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -9.81, 0]. */\n gravity?: Vec3Like;\n /** Max simultaneous bodies (resizes the world; only before any body exists). Default 4096. */\n maxBodies?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node | null;\n point: Vec3;\n normal: Vec3;\n fraction: number;\n}\nexport declare class Physics extends Aspect<\"physics\", Node> {\n static readonly aspect = \"physics\";\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Default \"dynamic\". */\n motion: MotionType;\n /** Mass in kg for dynamic bodies (default 1). Ignored for static/kinematic. */\n mass: number;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n /** Native Jolt body id. 0 until attached, or if the build has no physics support. */\n get id(): number;\n /** Linear velocity in world units/second (fresh Vec3 on read). */\n get velocity(): Vec3;\n set velocity(v: Vec3Like);\n /** Apply an instantaneous impulse (kg·m/s) and wake the body. */\n applyImpulse(v: Vec3Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position. */\n moveTo(p: Vec3Like): this;\n /** Configure gravity / limits. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_GL_PHYSICS). */\n static get supported(): boolean;\n /** Closest pickable body hit by the ray from `origin` along `dir` (up to `maxDist`), or null. */\n static raycast(origin: Vec3Like, dir: Vec3Like, maxDist?: number): RayHit | null;\n}\n","types/gl/Material.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type FetchResponse } from \"../runtime/fetch\";\nimport { Texture } from \"./Texture\";\nimport type { Canvas } from \"../canvas/Canvas\";\ntype UniformValue = string | Texture | number | boolean | number[] | Float32Array | null;\nexport type MaterialColorOptions = {\n color?: ColorInput;\n map?: Texture | Canvas | null;\n};\n/** `Material.particles` options — the default point-sprite material for particle systems. */\nexport type ParticlesMaterialOptions = {\n /** Sprite texture — a single image or a flipbook sheet of frames. Unset = soft round dot. */\n map?: Texture | null;\n /** Flipbook grid: `N` = an N×N sheet, `[cols, rows]` = a non-square one. Frames run\n * left-to-right, top-to-bottom; drive the index via `particles.frame`. Default 1. */\n sheet?: number | [number, number];\n /** Extra brightness multiplier for a glow look (0 = off). */\n emissive?: number;\n /** Compositing: `\"alpha\"` (default — smoke, dust) or `\"add\"` (fire, sparks, magic). */\n blend?: \"alpha\" | \"add\";\n /** Soft radial falloff toward the sprite edge. Defaults to true without a map, false with one. */\n soft?: boolean;\n /** How each particle is drawn: `'point'` (default — GPU point sprites, cheapest), `'quad'`\n * (real camera-facing quads — no driver size cap, geometric rotation), or `'stretch'`\n * (quads stretched along velocity — sparks, rain, speed streaks). `'ribbon'` is what `Trail`\n * uses internally. */\n render?: \"point\" | \"quad\" | \"stretch\" | \"ribbon\";\n /** (`render: 'stretch'`) extra sprite length in world units per unit of speed:\n * length = size + stretch·|velocity|. Default 0.05. */\n stretch?: number;\n};\n/** `Material.lit` options — PBR scalars on top of the color/map pair. */\nexport type LitMaterialOptions = MaterialColorOptions & {\n /** Perceptual roughness, 0 (mirror) … 1 (matte). Unset = the shader's default. */\n roughness?: number;\n /** Metallic factor, 0 (dielectric) … 1 (metal). Unset = the shader's default. */\n metallic?: number;\n};\nexport declare class Material {\n readonly shader: FetchResponse | \"unknown\";\n readonly uniforms: Record<string, UniformValue>;\n private _colorKey;\n private _useMapFlag;\n constructor(shader: FetchResponse | number);\n /** Set a uniform (chainable). */\n set(key: string, value: UniformValue): this;\n set color(c: ColorInput);\n set map(value: Texture | Canvas | null);\n /** PBR lit material. */\n static lit(options?: LitMaterialOptions): Material;\n /** Unlit (flat) material. */\n static unlit(options?: MaterialColorOptions): Material;\n /** Default particle material — camera-facing point sprites with tint/opacity/rotation/flipbook\n * driven by the particle curves. Uniforms all default to 0 on a fresh instance, so every look\n * knob is primed here; JS writes after construction override them. */\n static particles(options?: ParticlesMaterialOptions): Material;\n /** Material that samples a VideoPlayer's texture. */\n static video(map?: Texture): Material;\n /** Shadow-catcher material (transparent except where shadows fall). */\n static shadow(color?: ColorInput): Material;\n /** Load a custom compiled shader (.mat URL) as a material. */\n static load(url: string): Promise<Material>;\n}\nexport {};\n","types/gl/scenarios.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport type { InspectorUI } from \"../core/InspectorUI\";\nimport { Node } from \"./Node\";\nimport { Model } from \"./Model\";\ntype LoopMode = \"once\" | \"loop\" | \"pingpong\";\n/** Travel from the node's starting position to a target node in `duration` seconds. */\nexport declare class MoveTo extends Aspect<\"moveTo\"> {\n /** Where to travel — place an Empty node and pick it. */\n target: Node | null;\n /** Seconds for the full trip. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n /** once = stop at the target · loop = restart from the start point · pingpong = back and forth. */\n mode: LoopMode;\n /** Motion curve. */\n easing: \"smooth\" | \"linear\";\n static readonly aspect = \"moveTo\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<MoveTo>;\n private _t;\n private _start;\n update(dt: number): void;\n /** Editor-only path line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Travel through the children of a path node (add an Empty per waypoint) in `duration` seconds.\n * `loop` runs the circuit closed (last → first); `pingpong` goes back and forth along the open\n * path; `once` stops at the last waypoint. */\nexport declare class FollowPath extends Aspect<\"followPath\"> {\n /** A node whose CHILDREN are the waypoints, in file order. */\n path: Node | null;\n /** Seconds for one full pass of the path. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n mode: LoopMode;\n /** Turn to face the direction of travel. */\n orient: boolean;\n /** Which local axis leads when orienting. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n static readonly aspect = \"followPath\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<FollowPath>;\n private _t;\n private _points;\n update(dt: number): void;\n /** Editor-only waypoint polyline (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Continuous rotation about one of the node's local axes, degrees per second. */\nexport declare class Spin extends Aspect<\"spin\"> {\n /** Degrees per second. */\n speed: number;\n /** Local axis to spin around. */\n axis: \"x\" | \"y\" | \"z\";\n static readonly aspect = \"spin\";\n static fields: FieldMeta<Spin>;\n update(dt: number): void;\n}\n/** Keep the node facing a target node (a turret tracking, a signpost, a camera aimed at a hero).\n * Accessor `node.facing` — NOT `lookAt`, which would shadow the `Node.lookAt()` method. */\nexport declare class LookAt extends Aspect<\"facing\"> {\n /** The node to face. */\n target: Node | null;\n /** Which local axis points at the target. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n /** 0 = snap instantly; otherwise seconds of turn lag (bigger = slower, smoother). */\n smoothing: number;\n static readonly aspect = \"facing\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<LookAt>;\n update(dt: number): void;\n /** Editor-only sight line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Start a GLB animation clip when the scene runs. Attach to a `model:` node; the inspector card\n * lists the model's clips live and can preview them while editing. */\nexport declare class PlayAnimation extends Aspect<\"playAnimation\", Model> {\n /** Clip name; empty = the model's first clip. */\n clip: string;\n loop: boolean;\n /** Playback rate (1 = authored speed). */\n speed: number;\n static readonly aspect = \"playAnimation\";\n static fields: FieldMeta<PlayAnimation>;\n onAttach(): void;\n static inspector(ui: InspectorUI, a: PlayAnimation): void;\n}\nexport {};\n","types/gl/Node.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { Quat, type QuatLike } from \"../math/quat\";\nimport { Mat4, type Mat4Like } from \"../math/mat4\";\nimport type { Geometry } from \"./Geometry\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\n/** id → Node, so host callbacks (touch hits, animation events) route back to the owning object. */\nexport declare const nodeRegistry: Registry<Node>;\nexport type NodeEvents = {\n click: (ev: ClickEvent<Node | null>) => void;\n touchstart: (ev: TouchStartEvent<Node | null>) => void;\n /** A looping GLB animation clip wrapped around. */\n loopReached: (clip: number) => void;\n /** A non-looping GLB animation clip finished. */\n completed: (clip: number) => void;\n /** AR anchors only (`scene.root` / `scene.createAnchor()`): the anchor began tracking. */\n track: () => void;\n /** AR anchors only: the anchor lost tracking. */\n untrack: () => void;\n /** A physics contact/trigger overlap began (the other body's node). Needs a Shape + Physics/Trigger. */\n enter: (other: Node) => void;\n /** A physics contact/trigger overlap ended. */\n exit: (other: Node) => void;\n};\nexport declare class Node extends AspectHost<NodeEvents> {\n /** Native entity handle. */\n readonly id: number;\n /** AR anchors only — whether the anchor is currently being tracked. Kept in step with the\n * 'track' / 'untrack' events; `false` for any non-anchor node. */\n isTracked: boolean;\n private _matrix?;\n private _lastSync;\n private _worldMatrix?;\n private _scaleCache?;\n constructor(internalId?: number);\n /** Geometry, if this node is a Mesh (used by physics auto-shape). Overridden by Mesh. */\n get geometry(): Geometry | undefined;\n get name(): string;\n set name(value: string);\n get visible(): boolean;\n set visible(value: boolean);\n private _sync;\n get matrix(): Mat4;\n set matrix(m: Mat4Like);\n get worldMatrix(): Mat4;\n set worldMatrix(m: Mat4Like);\n get position(): Vec3;\n set position(v: Vec3Like);\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get z(): number;\n set z(v: number);\n get scale(): Vec3;\n set scale(v: Vec3Like | number);\n get quaternion(): Quat;\n set quaternion(v: QuatLike);\n get eulerAngles(): Vec3;\n set eulerAngles(v: Vec3Like);\n get forward(): Vec3;\n get worldPosition(): Vec3;\n get worldScale(): Vec3;\n get worldQuaternion(): Quat;\n get worldEulerAngles(): Vec3;\n get parent(): Node | null;\n get children(): Node[];\n get childCount(): number;\n getChild(index: number): Node | null;\n /** Parent the given nodes under this one. */\n add(...children: Node[]): this;\n setParent(parent: Node | null, worldPositionStays?: boolean): this;\n traverse(callback: (node: Node) => void): void;\n /** Orient the node so the given axis (default \"-z\", \"forward\") points at a world point. */\n lookAt(point: Vec3Like, mode?: \"z\" | \"-z\" | \"x\" | \"-x\" | \"y\" | \"-y\", ortho?: Vec3Like): this;\n addEventListener<K extends keyof NodeEvents>(channel: K, callback: NodeEvents[K]): void;\n destroy(): void;\n}\n","types/gl/Texture.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture {\n readonly width: number;\n readonly height: number;\n /** Horizontal wrap mode (U). */\n wrapS: number;\n /** Vertical wrap mode (V). */\n wrapT: number;\n constructor(width: number, height: number, id: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n _tex3dId: number;\n }): Texture;\n static load(source: string | FetchResponse | File): Promise<Texture>;\n}\n","types/inject.d.ts":"export { Mathf } from \"./math/Mathf\";\nexport { Vec2, Vec3 } from \"./math/vec\";\nexport { Quat } from \"./math/quat\";\nexport { Mat4 } from \"./math/mat4\";\nexport { Color } from \"./core/color\";\nexport { Aspect, type With } from \"./core/Aspect\";\nexport { InspectorUI } from \"./core/InspectorUI\";\nexport { signal, computed, effect, type Signal, type Computed } from \"./core/signals\";\nexport { Canvas, Bitmap } from \"./canvas/Canvas\";\nexport { toast, openURL, SvgSource } from \"./runtime/misc\";\nexport { app, type AppState } from \"./runtime/app\";\nexport { clipboard } from \"./runtime/clipboard\";\nexport { date, type DateValue, type DateInput, type Unit, type Locale } from \"./runtime/datetime\";\nexport { fetch, fetchLocal, FormData, File, type FetchResponse } from \"./runtime/fetch\";\nexport { localStorage } from \"./runtime/storage\";\nexport { device, type HapticStyle, type MotionOptions } from \"./runtime/device\";\nexport { Input } from \"./runtime/input\";\nexport { WebSocket } from \"./runtime/net\";\nexport { AudioPlayer, VideoPlayer } from \"./runtime/media\";\nexport { openFilePicker } from \"./runtime/files\";\nexport { share } from \"./runtime/share\";\nexport { ClickEvent, TouchStartEvent, LongPressEvent } from \"./runtime/touch\";\nexport { Scene2D } from \"./g2/Scene2D\";\nexport { Node2D } from \"./g2/Node2D\";\nexport { Camera2D } from \"./g2/Camera2D\";\nexport { Sprite } from \"./g2/Sprite\";\nexport { SpriteAnimation } from \"./g2/SpriteAnimation\";\nexport { Shape2D } from \"./g2/Shape2D\";\nexport { Physics2D } from \"./g2/Physics2D\";\nexport { Trigger2D } from \"./g2/Trigger2D\";\nexport { CharacterController2D } from \"./g2/CharacterController2D\";\nexport { Tilemap } from \"./g2/Tilemap\";\nexport { Texture2D } from \"./g2/Texture2D\";\nexport { UIScreen, type UIScreenStyle, UIRow, UIColumn, UIBox, type UIContainerStyle, UIText, type UITextStyle, UIButton, type UIButtonStyle, UIImage, type UIImageStyle, UIVideo, type UIVideoStyle, UIInput, UITextArea, type UIInputStyle, UIScrollable, type UIScrollableStyle, UIPager, type UIPagerStyle, UIWidget, type UIWidgetStyle, UIModal, type UIModalStyle, UIBottomSheet, type UIBottomSheetStyle, UIPopover, type UIPopoverStyle, UISpacer, type UISpacerStyle, UIVirtualizedList, Router, NativeView, type UINativeViewStyle, registerFont, __uiMap, } from \"./ui/UI\";\nexport { Presentable } from \"./ui/UI\";\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from \"./ui/UI\";\nexport type { UINode, UINodeChild } from \"./ui/UINode\";\nexport { theme, type ThemeValues, type ThemeAccessors } from \"./ui/theme\";\nexport { animate, animateMat4, stopAnimation, pauseAnimation, resumeAnimation } from \"./animate/animate\";\nexport { cubicBezier } from \"./animate/bezier\";\nexport { easeIn, easeOut, easeInOut } from \"./animate/easings\";\nexport { QRScanner } from \"./plugins/qr\";\nexport { CameraView, type CameraFacing } from \"./plugins/camera\";\nexport { Geolocation, type GeoPosition, type GeoOptions, type GeoWatch } from \"./plugins/geolocation\";\nexport { Service } from \"./plugins/service\";\nexport { defineScene, use, ref, make, SceneHandle } from \"./scene/defineScene\";\nexport type { SceneDef, SceneNodeDef, MeshDef, LightDef, MaterialDef, CameraNodeDef, AspectEntry, MakeEntry, LoadedScene } from \"./scene/defineScene\";\nexport type { FieldMeta } from \"./core/fields\";\nexport { MoveTo, FollowPath, Spin, LookAt, PlayAnimation } from \"./gl/scenarios\";\nexport { registerEditorWindow, registerEditorTool, __editorPlugins } from \"./scene/editorPlugins\";\nexport type { EditorApi, EditorRayHit, EditorToolHooks, EditorWindowFn } from \"./scene/editorPlugins\";\nexport { Scene, ARScene, VRScene } from \"./gl/Scene\";\nexport { Node } from \"./gl/Node\";\nexport { Mesh } from \"./gl/Mesh\";\nexport { Model } from \"./gl/Model\";\nexport { Shape } from \"./gl/Shape\";\nexport { Physics } from \"./gl/Physics\";\nexport { Trigger } from \"./gl/Trigger\";\nexport { CharacterController } from \"./gl/CharacterController\";\nexport { ModelAnimation } from \"./gl/ModelAnimation\";\nexport { Light } from \"./gl/Light\";\nexport { Material } from \"./gl/Material\";\nexport { Geometry } from \"./gl/Geometry\";\nexport { Texture } from \"./gl/Texture\";\nexport { Camera } from \"./gl/Camera\";\nexport { Ray } from \"./gl/Ray\";\nexport { Plane } from \"./gl/Plane\";\nexport { Noise } from \"./gl/Noise\";\nexport { Particles, Trail, curve, colorCurve } from \"./gl/Particles\";\n","types/scene/defineScene.d.ts":"import { Aspect, type AspectCtor, type With } from \"../core/Aspect\";\nimport type { ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Scene, type SceneOptions } from \"../gl/Scene\";\nimport { Node } from \"../gl/Node\";\nimport { Mesh } from \"../gl/Mesh\";\nimport { Model } from \"../gl/Model\";\nimport { Light, type SunOptions } from \"../gl/Light\";\nimport { Material, type LitMaterialOptions, type MaterialColorOptions } from \"../gl/Material\";\nimport type { CylinderOptions, PlaneOptions, SphereOptions } from \"../gl/Geometry\";\nexport type MeshDef = {\n kind: \"box\";\n size?: Vec3Like | number;\n} | ({\n kind: \"sphere\";\n} & SphereOptions) | ({\n kind: \"cylinder\";\n} & CylinderOptions) | ({\n kind: \"plane\";\n} & PlaneOptions);\nexport type LightDef = {\n kind: \"sun\";\n} & SunOptions;\nexport type MaterialDef = {\n lit: LitMaterialOptions;\n} | {\n unlit: MaterialColorOptions;\n} | {\n shadow: ColorInput;\n} | Material;\n/** One aspect to attach, created by `use(Ctor, props)`. */\nexport type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = {\n ctor: AspectCtor<A>;\n props?: Partial<A>;\n};\n/** Reference an aspect in a scene file: `aspects: [use(Physics, { motion: 'static' })]`. Props are\n * typechecked against the aspect's fields, exactly like `node.aspect(Ctor, props)`. */\nexport declare const use: <A extends Aspect<any, any>>(ctor: AspectCtor<A>, props?: Partial<A>) => AspectEntry<A>;\n/** A `make(fn, args)` source entry — see {@link make}. */\nexport type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = {\n fn: (args: A) => Node | Promise<Node>;\n args?: A;\n};\n/**\n * A code-created source in a scene file: `tower: { make: make(buildTower, { floors: 5 }), … }`.\n * The factory runs after every scene node exists (so `ref()` args resolve, forward references\n * included) and its returned subtree mounts under the def node — the def's transform stays\n * editor-owned, so moving the node never re-calls the factory. Args must be literal data (same\n * grammar as aspect props); in the editor they edit as fields, and an arg change re-CALLS the\n * factory live — the code is already in the bundle, so no compile happens. Keep factories pure\n * builders: same args → same subtree, no side effects outside the returned nodes.\n */\nexport declare const make: <A extends Record<string, unknown>>(fn: (args: A) => Node | Promise<Node>, args?: A) => MakeEntry<A>;\n/**\n * Reference another scene node by name in an aspect's props:\n * `use(Road, { from: ref('pointA'), to: ref('pointB') })`. Resolves to the live Node when aspects\n * attach — after EVERY node of the scene exists, so forward references work. An unknown name\n * resolves to `null` (type your aspect field `Node | null`). Scene files only — hand-written code\n * passes nodes directly: `node.aspect(Road, { from: nodes.pointA })`.\n */\nexport declare const ref: <T extends Node = Node>(name: string) => T;\n/** Transform overrides for one INTERNAL node of a GLB model or a prefab instance\n * (`overrides` on a model/prefab node, keyed by part path). */\nexport type ModelOverrideDef = {\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n};\n/** The `camera: {}` source block — reserved for projection settings (fov, …) later. */\nexport type CameraNodeDef = Record<string, never>;\nexport type SceneNodeDef = {\n mesh?: MeshDef;\n /** GLB url — `asset('./hero.glb')`. */\n model?: string;\n light?: LightDef;\n /** The scene camera as a NODE: in play mode `scene.camera` follows this node's world transform\n * every frame (so movement aspects on it are camera flythroughs); the editor shows a frustum\n * marker and refuses to delete the last camera node. The first camera node in file order wins;\n * cameras inside prefabs are ignored (like a prefab's `camera:` block). */\n camera?: CameraNodeDef;\n /** A code-built subtree — `make(factoryFn, { ...literal args })`. */\n make?: MakeEntry<any>;\n /** Another scene file used as a reusable composition — the imported handle:\n * `import streetlamp from './streetlamp.scene'` … `lamp: { prefab: streetlamp }`. Its nodes\n * instantiate under this node per instance (env/camera are the instancing file's business and\n * are ignored); `ref()`s inside the prefab resolve file-locally, per instance. */\n prefab?: SceneHandle<any>;\n /** Material for a `mesh` source. */\n material?: MaterialDef;\n /** Model/prefab sources: transform overrides for the INTERNAL nodes, keyed by part path\n * (see the part-path grammar above `modelPartRows`). Unresolved paths are ignored. */\n overrides?: Record<string, ModelOverrideDef>;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n /** Editor-only: the transform gizmo won't target this node (fields still edit). No runtime effect. */\n locked?: boolean;\n castShadows?: boolean;\n receiveShadows?: boolean;\n aspects?: readonly AspectEntry<any>[];\n children?: Record<string, SceneNodeDef>;\n};\nexport type SceneCameraDef = {\n position?: Vec3Like;\n /** Point the camera looks at. */\n target?: Vec3Like;\n};\nexport type SceneDef = {\n env?: SceneOptions;\n camera?: SceneCameraDef;\n nodes?: Record<string, SceneNodeDef>;\n};\ntype SourceNodeOf<N extends SceneNodeDef> = N extends {\n model: string;\n} ? Model : N extends {\n mesh: MeshDef;\n} ? Mesh : N extends {\n light: LightDef;\n} ? Light : Node;\ntype AspectsOf<N extends SceneNodeDef> = N extends {\n aspects: readonly AspectEntry<infer A>[];\n} ? A : never;\ntype NodeOf<N extends SceneNodeDef> = [\n AspectsOf<N>\n] extends [never] ? SourceNodeOf<N> : With<SourceNodeOf<N>, AspectsOf<N>>;\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\ntype ChildMapsOf<T extends Record<string, SceneNodeDef>> = {\n [K in keyof T]: T[K] extends {\n children: infer C extends Record<string, SceneNodeDef>;\n } ? NodesOf<C> : never;\n}[keyof T];\ntype NodesOf<T extends Record<string, SceneNodeDef>> = {\n [K in keyof T]: NodeOf<T[K]>;\n} & ([ChildMapsOf<T>] extends [never] ? unknown : UnionToIntersection<ChildMapsOf<T>>);\nexport type SceneNodes<D extends SceneDef> = D[\"nodes\"] extends Record<string, SceneNodeDef> ? NodesOf<D[\"nodes\"]> : Record<string, Node>;\nexport type LoadedScene<D extends SceneDef> = {\n scene: Scene;\n nodes: SceneNodes<D>;\n};\n/** One INTERNAL node of a loaded GLB (editor introspection). */\nexport type ModelPartRow = {\n path: string;\n name: string;\n depth: number;\n node: Node;\n};\n/** Flatten a model's (or prefab instance's) internal hierarchy to rows (depth-first, the root\n * excluded). `__generated` containers are derived output, not addressable parts — skipped. */\nexport declare const modelPartRows: (root: Node) => ModelPartRow[];\nexport declare class SceneHandle<D extends SceneDef = SceneDef> {\n readonly def: D;\n private _loading?;\n constructor(def: D);\n /** Instantiate the scene (idempotent — subsequent calls return the same instance). Does not open. */\n load(): Promise<LoadedScene<D>>;\n /** Load and make active. */\n open(): Promise<LoadedScene<D>>;\n}\n/**\n * Define a scene as data — the default export of a `.scene.ts` file. Returns a typed handle:\n * `const { scene, nodes } = await handle.open()` gives `nodes.<name>` typed by its source block\n * (Mesh / Model / Light / Node) with its `use(...)`d aspects attached.\n */\nexport declare const defineScene: <const D extends SceneDef>(def: D) => SceneHandle<D>;\nexport {};\n","types/scene/editorPlugins.d.ts":"import type { InspectorUI } from \"../core/InspectorUI\";\n/** A geometry hit under the viewport pointer, handed to tools. Physics builds raycast the scene's\n * meshes (precise); otherwise (and on misses) the hit falls back to the ground plane (y = 0). */\nexport type EditorRayHit = {\n point: [number, number, number];\n normal: [number, number, number];\n /** The scene-file node the hit belongs to — null for ground-plane fallback hits. */\n node: string | null;\n};\n/**\n * The editor scripting API handed to windows and tools. Doc-op methods write the scene DOCUMENT\n * through the editor's normal commit path (undo, file, live patching all included); they return\n * false / no-op when the document can't take the edit (duplicate name, unknown node).\n */\nexport type EditorApi = {\n /** The currently selected node name (or `model::part` key), null when nothing is selected. */\n readonly selection: string | null;\n select(name: string | null): void;\n /** The scene document's nodes (name + source kind: mesh / model / light / group). */\n nodes(): {\n name: string;\n kind: string;\n }[];\n /** First unused \"base\", \"base2\", \"base3\", … node name. */\n uniqueName(base: string): string;\n /** Add a node from plain def data (scene-file grammar; a string `model` value means an asset\n * path). One undo step unless grouped by `transact`. */\n addNode(name: string, def: Record<string, unknown>): boolean;\n /** Write one def prop (transforms apply live; anything else patches/re-runs the node). */\n setProp(name: string, key: string, value: unknown): boolean;\n removeNode(name: string): void;\n /** Duplicate a node; returns the copy's name (null when it can't). */\n duplicate(name: string): string | null;\n /** Raycast the scene under a viewport pixel (same hit rules as tool clicks). */\n raycast(screenX: number, screenY: number): EditorRayHit | null;\n /** Group every doc edit inside `fn` into ONE undo step. */\n transact(fn: () => void): void;\n};\nexport type EditorWindowFn = (ui: InspectorUI, editor: EditorApi) => void;\nexport type EditorToolHooks = {\n /** CSS cursor for the viewport while this tool is active (default \"crosshair\"). */\n cursor?: string;\n /** A short glyph (one character / emoji) for the tool's toolbar button — tools without one all\n * share the generic wand icon, so any editor with two or more tools should set it. */\n icon?: string;\n /** A viewport click while the tool is active — `hit` is the raycast result under the pointer.\n * Selection clicks and the transform gizmo are suspended while a tool is active. */\n onViewportClick?(hit: EditorRayHit, editor: EditorApi): void;\n};\n/** Register an editor panel — a collapsible overlay docked over the viewport (the inspector rail\n * stays selection-scoped). A window that emits `ui.toolButton` for a tool becomes that tool's\n * settings panel: activating the tool expands and highlights it. `render` re-runs immediate-mode\n * on every interaction — same protocol as `static inspector` cards. */\nexport declare const registerEditorWindow: (title: string, render: EditorWindowFn) => void;\n/** Register a viewport tool — a toolbar entry beside move/rotate/scale (activate it there or via\n * `ui.toolButton(label, name)`). While active, viewport clicks arrive as raycast hits. */\nexport declare const registerEditorTool: (name: string, hooks: EditorToolHooks) => void;\n"}