lecodes-sdk 1.1.0 → 2.0.0

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.
Files changed (257) hide show
  1. package/README.md +5 -2
  2. package/dist/editor.d.ts +12 -0
  3. package/dist/global.d.ts +4 -8
  4. package/dist/host.d.ts +2 -3
  5. package/dist/types/animate/tween/Animation.d.ts +0 -3
  6. package/dist/types/animate/tween/animateValue.d.ts +4 -2
  7. package/dist/types/animate/tween/easing.d.ts +8 -0
  8. package/dist/types/animate/tween/spec.d.ts +15 -7
  9. package/dist/types/audio/audio.d.ts +2 -1
  10. package/dist/types/canvas/Canvas.d.ts +40 -108
  11. package/dist/types/canvas/gen/cssColor.d.ts +17 -0
  12. package/dist/types/canvas/gen/recorder.d.ts +118 -0
  13. package/dist/types/canvas/gen/spec.d.ts +144 -0
  14. package/dist/types/core/color.d.ts +3 -1
  15. package/dist/types/core/pins.d.ts +18 -0
  16. package/dist/types/g2/Node2D.d.ts +5 -8
  17. package/dist/types/g2/Scene2D.d.ts +6 -2
  18. package/dist/types/gl/Foliage.d.ts +30 -7
  19. package/dist/types/gl/Light.d.ts +11 -0
  20. package/dist/types/gl/Lightmap.d.ts +13 -2
  21. package/dist/types/gl/Material.d.ts +17 -3
  22. package/dist/types/gl/Model.d.ts +6 -2
  23. package/dist/types/gl/Node.d.ts +3 -6
  24. package/dist/types/gl/Particles.d.ts +15 -0
  25. package/dist/types/gl/Scene.d.ts +41 -13
  26. package/dist/types/gl/Texture.d.ts +1 -1
  27. package/dist/types/gl/animation/Locomotion.d.ts +59 -3
  28. package/dist/types/gl/terrain/Terrain.d.ts +8 -0
  29. package/dist/types/inject.d.ts +11 -11
  30. package/dist/types/inject.editor.d.ts +1 -0
  31. package/dist/types/net/core.d.ts +7 -0
  32. package/dist/types/plugin.d.ts +76 -0
  33. package/dist/types/plugins/gen/camera/sdk/camera.d.ts +24 -0
  34. package/dist/types/plugins/gen/camera/sdk/camera.gen.d.ts +25 -0
  35. package/dist/types/plugins/{geolocation.d.ts → gen/geolocation/sdk/geolocation.d.ts} +2 -20
  36. package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +31 -0
  37. package/dist/types/plugins/{map.d.ts → gen/map/sdk/map.d.ts} +9 -50
  38. package/dist/types/plugins/gen/map/sdk/map.gen.d.ts +53 -0
  39. package/dist/types/plugins/gen/push/sdk/push.d.ts +23 -0
  40. package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +35 -0
  41. package/dist/types/plugins/{qr.d.ts → gen/qr-scanner/sdk/qr-scanner.d.ts} +2 -3
  42. package/dist/types/plugins/gen/qr-scanner/sdk/qr-scanner.gen.d.ts +15 -0
  43. package/dist/types/runtime/app.d.ts +9 -2
  44. package/dist/types/runtime/fetch.d.ts +2 -0
  45. package/dist/types/runtime/input.d.ts +8 -1
  46. package/dist/types/runtime/media.d.ts +6 -10
  47. package/dist/types/runtime/misc.d.ts +4 -1
  48. package/dist/types/runtime/net.d.ts +3 -2
  49. package/dist/types/runtime/touch.d.ts +32 -0
  50. package/dist/types/scene/defineScene.d.ts +43 -2
  51. package/dist/types/scene/editor.d.ts +52 -0
  52. package/dist/types/scene/gizmos.d.ts +7 -4
  53. package/dist/types/ui/NativeView.d.ts +6 -4
  54. package/dist/types/ui/UI.d.ts +1 -1
  55. package/dist/types/ui/UIBottomSheet.d.ts +6 -12
  56. package/dist/types/ui/UIButton.d.ts +12 -14
  57. package/dist/types/ui/UIContainer.d.ts +0 -6
  58. package/dist/types/ui/UIImage.d.ts +1 -4
  59. package/dist/types/ui/UIInput.d.ts +8 -24
  60. package/dist/types/ui/UIModal.d.ts +0 -2
  61. package/dist/types/ui/UINode.d.ts +70 -56
  62. package/dist/types/ui/UIPager.d.ts +28 -27
  63. package/dist/types/ui/UIPopover.d.ts +0 -2
  64. package/dist/types/ui/UIScreen.d.ts +12 -17
  65. package/dist/types/ui/UIScrollable.d.ts +1 -4
  66. package/dist/types/ui/UIText.d.ts +0 -2
  67. package/dist/types/ui/UIVideo.d.ts +3 -5
  68. package/dist/types/ui/UIVirtualizedList.d.ts +14 -16
  69. package/dist/types/ui/UIWidget.d.ts +10 -9
  70. package/dist/types/ui/colorKeys.gen.d.ts +9 -0
  71. package/dist/types/ui/presentable.d.ts +46 -32
  72. package/dist/types/ui/router.d.ts +18 -7
  73. package/dist/types/ui/styleColor.d.ts +1 -0
  74. package/dist/types/ui/transitions.d.ts +18 -0
  75. package/dist/types/ui/tree.d.ts +75 -0
  76. package/dist/types/version.d.ts +10 -0
  77. package/dist/types.json +1 -1
  78. package/package.json +12 -3
  79. package/prompts/2d.md +2 -6
  80. package/prompts/3d.md +1 -5
  81. package/prompts/README.md +142 -142
  82. package/prompts/canvas.md +9 -8
  83. package/prompts/compose.ts +1 -1
  84. package/prompts/core.md +3 -3
  85. package/prompts/design.md +1 -1
  86. package/prompts/dist/2d-game.md +77 -54
  87. package/prompts/dist/3d-app.md +75 -52
  88. package/prompts/dist/ar-app.md +74 -51
  89. package/prompts/dist/design.md +30 -8
  90. package/prompts/dist/ui-app.md +73 -46
  91. package/prompts/ui-design.md +2 -3
  92. package/prompts/ui.md +45 -37
  93. package/src/animate/tween/Animation.ts +262 -378
  94. package/src/animate/tween/animateValue.ts +103 -100
  95. package/src/animate/tween/easing.ts +10 -3
  96. package/src/animate/tween/spec.ts +505 -479
  97. package/src/audio/Sound.ts +3 -3
  98. package/src/audio/audio.ts +162 -161
  99. package/src/bridges/2d.d.ts +317 -0
  100. package/src/bridges/app.d.ts +91 -0
  101. package/src/bridges/audio.d.ts +97 -0
  102. package/src/bridges/canvas.d.ts +79 -0
  103. package/src/bridges/device.d.ts +72 -0
  104. package/src/bridges/fetch.d.ts +80 -0
  105. package/src/bridges/files.d.ts +70 -0
  106. package/src/bridges/gl.d.ts +1133 -0
  107. package/src/bridges/input.d.ts +72 -0
  108. package/src/bridges/media.d.ts +55 -0
  109. package/src/bridges/nav.d.ts +71 -0
  110. package/src/bridges/net.d.ts +52 -0
  111. package/src/bridges/service.d.ts +52 -0
  112. package/src/bridges/socket.d.ts +31 -0
  113. package/src/bridges/storage.d.ts +33 -0
  114. package/src/bridges/tree.d.ts +301 -0
  115. package/src/bridges/types.d.ts +49 -0
  116. package/src/canvas/Canvas.ts +114 -159
  117. package/src/canvas/gen/cssColor.ts +224 -0
  118. package/src/canvas/gen/recorder.ts +212 -0
  119. package/src/canvas/gen/spec.ts +201 -0
  120. package/src/chisel.ts +193 -0
  121. package/src/compile/assetMacro.ts +1 -1
  122. package/src/compile/bundler.ts +11 -2
  123. package/src/compile/compileProject.ts +43 -4
  124. package/src/compile/fontMacro.ts +3 -4
  125. package/src/compile/header.ts +26 -5
  126. package/src/compile/index.ts +3 -1
  127. package/src/compile/liteMaterial.ts +1 -1
  128. package/src/compile/sceneEditor.ts +11 -26
  129. package/src/core/color.ts +73 -30
  130. package/src/core/pins.ts +51 -0
  131. package/src/core/signals.ts +8 -1
  132. package/src/g2/CharacterController2D.ts +3 -3
  133. package/src/g2/Node2D.ts +57 -39
  134. package/src/g2/Physics2D.ts +2 -2
  135. package/src/g2/Scene2D.ts +35 -23
  136. package/src/g2/Texture2D.ts +1 -1
  137. package/src/g2/loop.ts +4 -4
  138. package/src/gl/Foliage.ts +72 -17
  139. package/src/gl/Geometry.ts +1 -2
  140. package/src/gl/Light.ts +13 -0
  141. package/src/gl/Lightmap.ts +45 -29
  142. package/src/gl/Material.ts +95 -51
  143. package/src/gl/Model.ts +172 -167
  144. package/src/gl/Node.ts +91 -24
  145. package/src/gl/Particles.ts +20 -1
  146. package/src/gl/Scene.ts +100 -44
  147. package/src/gl/Texture.ts +8 -7
  148. package/src/gl/animation/AnimationClip.ts +1 -1
  149. package/src/gl/animation/Locomotion.ts +77 -8
  150. package/src/gl/nav/NavMesh.ts +3 -4
  151. package/src/gl/physics/Physics.ts +2 -2
  152. package/src/gl/physics/physicsEvents.ts +3 -3
  153. package/src/gl/terrain/Terrain.ts +33 -5
  154. package/src/gl/touch.ts +14 -15
  155. package/src/host.d.ts +2 -3
  156. package/src/inject.editor.ts +7 -0
  157. package/src/inject.ts +233 -236
  158. package/src/net/core.ts +6 -5
  159. package/src/net/index.ts +1 -1
  160. package/src/net/replication.ts +1 -1
  161. package/src/plugin.ts +191 -0
  162. package/src/plugins/gen/camera/contract.d.ts +27 -0
  163. package/src/plugins/gen/camera/sdk/camera.gen.ts +46 -0
  164. package/src/plugins/gen/camera/sdk/camera.ts +57 -0
  165. package/src/plugins/gen/geolocation/contract.d.ts +50 -0
  166. package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +54 -0
  167. package/src/plugins/{geolocation.ts → gen/geolocation/sdk/geolocation.ts} +22 -43
  168. package/src/plugins/gen/map/contract.d.ts +144 -0
  169. package/src/plugins/gen/map/sdk/map.gen.ts +88 -0
  170. package/src/plugins/{map.ts → gen/map/sdk/map.ts} +68 -102
  171. package/src/plugins/gen/push/contract.d.ts +61 -0
  172. package/src/plugins/gen/push/sdk/push.gen.ts +60 -0
  173. package/src/plugins/gen/push/sdk/push.ts +105 -0
  174. package/src/plugins/gen/qr-scanner/contract.d.ts +16 -0
  175. package/src/plugins/gen/qr-scanner/sdk/qr-scanner.gen.ts +29 -0
  176. package/src/plugins/gen/qr-scanner/sdk/qr-scanner.ts +52 -0
  177. package/src/plugins/permission.ts +5 -4
  178. package/src/runtime/app.ts +20 -9
  179. package/src/runtime/appEvents.ts +5 -4
  180. package/src/runtime/channel.ts +18 -15
  181. package/src/runtime/clipboard.ts +4 -3
  182. package/src/runtime/datetime.ts +2 -1
  183. package/src/runtime/device.ts +17 -15
  184. package/src/runtime/fetch.ts +30 -20
  185. package/src/runtime/files.ts +16 -15
  186. package/src/runtime/input.ts +21 -8
  187. package/src/runtime/media.ts +50 -46
  188. package/src/runtime/misc.ts +7 -3
  189. package/src/runtime/net.ts +8 -7
  190. package/src/runtime/rpc.ts +1 -3
  191. package/src/runtime/service.ts +19 -14
  192. package/src/runtime/share.ts +4 -3
  193. package/src/runtime/storage.ts +6 -4
  194. package/src/runtime/touch.ts +32 -0
  195. package/src/scene/defineScene.ts +61 -365
  196. package/src/scene/editor.ts +408 -0
  197. package/src/scene/editorPlugins.ts +3 -3
  198. package/src/scene/gizmos.ts +154 -148
  199. package/src/server/db/marci/query.ts +1 -1
  200. package/src/server/host.ts +1 -1
  201. package/src/server/runtime.ts +1 -1
  202. package/src/ui/NativeView.ts +72 -25
  203. package/src/ui/UI.ts +3 -3
  204. package/src/ui/UIBottomSheet.ts +16 -17
  205. package/src/ui/UIButton.ts +54 -16
  206. package/src/ui/UIContainer.ts +0 -6
  207. package/src/ui/UIImage.ts +34 -30
  208. package/src/ui/UIInput.ts +29 -37
  209. package/src/ui/UIModal.ts +1 -3
  210. package/src/ui/UINode.ts +347 -297
  211. package/src/ui/UIPager.ts +93 -78
  212. package/src/ui/UIPopover.ts +0 -2
  213. package/src/ui/UIScreen.ts +41 -36
  214. package/src/ui/UIScrollable.ts +19 -13
  215. package/src/ui/UISpacer.ts +1 -1
  216. package/src/ui/UITabs.ts +8 -6
  217. package/src/ui/UIText.ts +7 -17
  218. package/src/ui/UIVideo.ts +30 -27
  219. package/src/ui/UIVirtualizedList.ts +58 -59
  220. package/src/ui/UIWidget.ts +38 -18
  221. package/src/ui/colorKeys.gen.ts +37 -0
  222. package/src/ui/fonts.ts +2 -2
  223. package/src/ui/presentable.ts +59 -42
  224. package/src/ui/router.ts +52 -35
  225. package/src/ui/styleColor.ts +56 -0
  226. package/src/ui/theme.ts +7 -6
  227. package/src/ui/transitions.ts +249 -0
  228. package/src/ui/tree.ts +346 -0
  229. package/src/version.ts +24 -0
  230. package/tests/helpers/engineWorld.ts +11 -0
  231. package/tests/helpers/fakeTree.ts +353 -0
  232. package/tests/helpers/hostStubs.ts +31 -0
  233. package/tests/helpers/index.ts +14 -0
  234. package/tests/helpers/memoryMarci.ts +124 -0
  235. package/tests/helpers/phases.ts +23 -0
  236. package/tests/helpers/preload.ts +18 -0
  237. package/tests/helpers/stubApp.ts +2 -0
  238. package/tests/helpers/stubDevice.ts +2 -0
  239. package/tests/helpers/stubFetch.ts +2 -0
  240. package/tests/helpers/stubInput.ts +2 -0
  241. package/dist/inject.js +0 -4730
  242. package/dist/types/core/registry.d.ts +0 -7
  243. package/dist/types/plugins/camera.d.ts +0 -25
  244. package/dist/types/plugins/push.d.ts +0 -46
  245. package/src/bridges.d.ts +0 -1760
  246. package/src/compile/__tests__/assetIconMacro.test.ts +0 -219
  247. package/src/compile/__tests__/assetMacro.test.ts +0 -100
  248. package/src/compile/__tests__/assetName.test.ts +0 -55
  249. package/src/compile/__tests__/compile.test.ts +0 -310
  250. package/src/compile/__tests__/detectEntry.test.ts +0 -151
  251. package/src/compile/__tests__/fontMacro.test.ts +0 -199
  252. package/src/compile/__tests__/serverSplit.test.ts +0 -27
  253. package/src/core/__tests__/stateMachine.test.ts +0 -132
  254. package/src/core/registry.ts +0 -23
  255. package/src/plugins/camera.ts +0 -81
  256. package/src/plugins/push.ts +0 -132
  257. package/src/plugins/qr.ts +0 -73
@@ -17,6 +17,10 @@ type AppEventMap = {
17
17
  keyboard: (height: number, duration: number) => void;
18
18
  };
19
19
  export declare const app: {
20
+ /** The SDK this app was compiled with (semver, e.g. `"2.0.0"`). Its major is the bundle ↔ runtime
21
+ * contract: a host runs only bundles of its own major, and the launchers send it as `?sdk=` when
22
+ * they fetch a published bundle — the platform keeps one bundle per major. */
23
+ sdkVersion: string;
20
24
  /** Current lifecycle state. `"background"` while the app is not the foreground app / the tab is
21
25
  * hidden. `"active"` on hosts that don't track it. */
22
26
  readonly state: AppState;
@@ -47,12 +51,12 @@ export declare const app: {
47
51
  quit(): void;
48
52
  /** Global back-press fallback (Android back button/gesture — iOS has no system back). Fires
49
53
  * only when nothing else consumed the press: no open widget/modal claimed it, the current
50
- * screen has no `onBackPressed`, every pager is at its tab root and the router is at its
54
+ * screen has no `onBack`, every pager is at its tab root and the router is at its
51
55
  * stack root. The place for app-wide policy — e.g. double-press-to-quit:
52
56
  *
53
57
  * ```ts
54
58
  * let armedAt = 0
55
- * app.onBackPressed(() => {
59
+ * app.onBack(() => {
56
60
  * if (Date.now() - armedAt < 2000) { app.quit(); return }
57
61
  * armedAt = Date.now()
58
62
  * toast("Press back again to exit")
@@ -60,6 +64,9 @@ export declare const app: {
60
64
  * ```
61
65
  *
62
66
  * Replaces the previous handler; pass `null` to remove. */
67
+ onBack(callback: (() => void) | null): void;
68
+ /** @deprecated Renamed `onBack` (2026-09-26). An alias for the projects compiled before the
69
+ * rename; removed with the release that recompiles them. */
63
70
  onBackPressed(callback: (() => void) | null): void;
64
71
  addEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;
65
72
  removeEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;
@@ -12,6 +12,8 @@ export interface FetchResponse {
12
12
  readonly status: number;
13
13
  json<T = any>(): T;
14
14
  text(): string;
15
+ /** @deprecated A no-op: the body is freed with the response's handle (owned handles). Apps written
16
+ * against the pre-owned SDK still call it after `text()` / `json()`; remove the call. */
15
17
  dispose(): void;
16
18
  }
17
19
  export declare const fetch: (url: string, options?: FetchOptions) => Promise<FetchResponse>;
@@ -1,4 +1,4 @@
1
- /** Continuous channel ids — the `_creatorUtils.inputRead` contract (bridges.d.ts). */
1
+ /** Continuous channel ids — the `_creatorInput.read` contract (sdk/src/bridges/input.d.ts). */
2
2
  export declare const InputChannel: {
3
3
  readonly MouseX: 0;
4
4
  readonly MouseY: 1;
@@ -82,6 +82,13 @@ export interface GamepadState {
82
82
  axis(name: GamepadAxisName, deadzone?: number): number;
83
83
  /** Held? Same as `Input.key(code, index)`. */
84
84
  button(code: string): boolean;
85
+ /** Rumble: `strong` = the heavy low-frequency motor, `weak` = the light high-frequency one, both
86
+ * 0..1, for `durationMs` (default 200, hosts cap at 5000). A new call replaces the running
87
+ * effect. The host stops the motors by itself — after the duration, on focus loss and when the
88
+ * project is swapped — so there is nothing to clean up. False when the pad or host has no motors. */
89
+ rumble(strong: number, weak?: number, durationMs?: number): boolean;
90
+ /** Stop the running rumble now. */
91
+ stopRumble(): void;
85
92
  }
86
93
  export declare const Input: {
87
94
  /**
@@ -7,15 +7,14 @@ type MediaEvents = {
7
7
  completed: () => void;
8
8
  };
9
9
  declare abstract class MediaPlayer extends Emitter<MediaEvents> {
10
- protected _id: number;
11
10
  protected _src: string;
12
11
  private _playing;
13
12
  private _loop;
14
13
  private _volume;
15
- private _disposed;
16
- private _assertAlive;
17
14
  play(): void;
18
15
  pause(): void;
16
+ /** Pause and rewind to the start. */
17
+ stop(): void;
19
18
  get playing(): boolean;
20
19
  set playing(value: boolean);
21
20
  get volume(): number;
@@ -27,12 +26,9 @@ declare abstract class MediaPlayer extends Emitter<MediaEvents> {
27
26
  set time(value: number);
28
27
  /** Total media length in seconds (0 until metadata has loaded). */
29
28
  get duration(): number;
30
- /** True once {@link dispose} has been called; the player is unusable afterwards. */
31
- get disposed(): boolean;
32
- /**
33
- * Release the underlying host media resource (decoder, network, buffers) immediately and detach
34
- * all listeners. Idempotent. Any further use of the player throws.
35
- */
29
+ /** @deprecated There is nothing to dispose — a player the app stops referencing is released by
30
+ * the runtime (a playing one at its end). Kept as `stop()` so old code still silences the player;
31
+ * call `stop()` / `pause()` instead. */
36
32
  dispose(): void;
37
33
  }
38
34
  export declare class AudioPlayer extends MediaPlayer {
@@ -40,7 +36,7 @@ export declare class AudioPlayer extends MediaPlayer {
40
36
  }
41
37
  export declare class VideoPlayer extends MediaPlayer {
42
38
  constructor(src?: string);
43
- /** A 3D Texture that samples this video (e.g. for a Material.video()). */
39
+ /** A 3D Texture that samples this video (e.g. for a Material.video()). Owned by the player. */
44
40
  get texture(): Texture;
45
41
  }
46
42
  export {};
@@ -1,3 +1,4 @@
1
+ import type { ColorInput } from "../core/color";
1
2
  /** Show a transient toast notification. */
2
3
  export declare const toast: (msg: string) => void;
3
4
  /** Open `url` in the system browser / external handler (fire-and-forget, like `share`). Silent
@@ -5,7 +6,9 @@ export declare const toast: (msg: string) => void;
5
6
  export declare const openURL: (url: string) => void;
6
7
  export type SvgSourceValue = {
7
8
  readonly svg: string;
8
- tintColor: string | null;
9
+ /** The source-level tint (a mask recolor under the `tintColor` style, which wins): any color, or
10
+ * a theme `var(--…)`. */
11
+ tintColor: ColorInput | null;
9
12
  };
10
13
  /** Wrap raw SVG XML so it can be used as an image source. */
11
14
  export declare const SvgSource: (svg: string) => SvgSourceValue;
@@ -7,8 +7,9 @@ type SocketEvents = {
7
7
  };
8
8
  export declare class WebSocket extends Emitter<SocketEvents> {
9
9
  private _id;
10
- constructor(url: string, headers?: Record<string, string>);
11
- send(message: string | ArrayBuffer): void;
10
+ constructor(url: string);
11
+ /** Send a text frame. */
12
+ send(message: string): void;
12
13
  close(): void;
13
14
  private _onMessage;
14
15
  }
@@ -54,3 +54,35 @@ export declare class LongPressEvent<T = any> {
54
54
  /** Capture subsequent moves/end for this pointer — drag the element after the hold. */
55
55
  track(handler: TrackHandler): void;
56
56
  }
57
+ /** What a hover `track()` takes: the cursor's moves inside the element (only delivered when
58
+ * `onMove` is present — otherwise the host never crosses into JS for them), `onEnd` when it
59
+ * leaves (with the last position), `onCancel` when the element went away underneath it. No
60
+ * `claim`: a hover competes with nothing. */
61
+ export interface HoverTrackHandler {
62
+ onMove?(pos: {
63
+ clientX: number;
64
+ clientY: number;
65
+ deltaX: number;
66
+ deltaY: number;
67
+ }): void;
68
+ onEnd?(pos: {
69
+ clientX: number;
70
+ clientY: number;
71
+ deltaX: number;
72
+ deltaY: number;
73
+ }): void;
74
+ onCancel?(): void;
75
+ }
76
+ /** Delivered to a `UIButton` `onMouseEnter` handler when a mouse cursor (no button) enters the
77
+ * button. There is no separate leave event: `ev.track({ onEnd })` follows this hover to its end,
78
+ * `onMove` follows the cursor inside — the visual state itself is the reserved `$hovered` class.
79
+ * Touch never produces one. */
80
+ export declare class MouseEnterEvent<T = any> {
81
+ readonly type = "mouseenter";
82
+ readonly clientX: number;
83
+ readonly clientY: number;
84
+ target: T;
85
+ constructor(clientX: number, clientY: number);
86
+ /** Follow this hover: moves inside the element, its end (the cursor left), its cancel. */
87
+ track(handler: HoverTrackHandler): void;
88
+ }
@@ -1,4 +1,3 @@
1
- import { type With } from "../core/Aspect";
2
1
  import { use, ref, make, type AspectEntry, type MakeEntry as SharedMakeEntry } from "./grammar";
3
2
  import type { Vec3Like } from "../math/vec";
4
3
  import { Scene, type SceneOptions } from "../gl/Scene";
@@ -11,6 +10,7 @@ import { type TerrainLayer, type TerrainRegion, type TerrainOptions } from "../g
11
10
  import { Light, type SunOptions } from "../gl/Light";
12
11
  import { type MaterialDef } from "./material";
13
12
  import type { CapsuleOptions, CylinderOptions, PlaneOptions, SphereOptions } from "../gl/Geometry";
13
+ import { GizmoBuffer } from "./gizmos";
14
14
  export type MeshDef = {
15
15
  kind: "box";
16
16
  size?: Vec3Like | number;
@@ -152,7 +152,7 @@ export type SceneCameraDef = CameraProjectionDef & {
152
152
  /** Point the camera looks at. */
153
153
  target?: Vec3Like;
154
154
  };
155
- /** `env.lightmap` — the level's baked lighting (packages/creator-bake): the files `lecodes lightmap bake`
155
+ /** `env.lightmap` — the level's baked lighting (engines/bake): the files `lecodes lightmap bake`
156
156
  * writes. Absent = real-time only. */
157
157
  export type SceneLightmapDef = {
158
158
  /** `asset('./assets/lightmap/level.bake')` */
@@ -274,6 +274,8 @@ export type ModelPartRow = {
274
274
  * not parts, skipped. Filtering BEFORE segment math keeps `name[i]` indices stable no matter
275
275
  * what defs are parented in. */
276
276
  export declare const modelPartRows: (root: Node) => ModelPartRow[];
277
+ /** Where a def node attaches: its `mount` part when it resolves, else the parent itself. */
278
+ export declare const attachHost: (parent: Node, def: SceneNodeDef, path: string) => Node;
277
279
  /** The static verdict for one node def (the editor's "Baked lighting" switch shows the same rule).
278
280
  * Children of a mover are movers too — buildNodes carries that down, this is the node's own verdict. */
279
281
  export declare const isLightmapStatic: (def: SceneNodeDef) => boolean;
@@ -283,6 +285,45 @@ export declare const applyEditorPose: (node: Node, pose: {
283
285
  clip?: string;
284
286
  time?: number;
285
287
  } | undefined) => void;
288
+ /** Edit mode: otherwise-invisible nodes (empties, `camera:` nodes) get an ANCHORED gizmo marker —
289
+ * an axis cross / a frustum in the node's local frame (scene/gizmos.ts) — so they show and pick
290
+ * in the viewport. Never scene content: nothing renders in Filament, nothing outlines, and the
291
+ * engine follows the node live, so the buffer is filled once and lives on the node
292
+ * (`_editorMarker`) — `sceneEditor.gizmos()` reads it off the handle's own def nodes, so a removed
293
+ * node's marker goes with its record and prefab / instance internals (not selectable) draw none. */
294
+ export declare const addEditorMarker: (node: Node, def: SceneNodeDef) => void;
295
+ /** fov / near / far from a camera block onto the live camera. The build path leaves an empty block
296
+ * alone (a host may run with its own configured fov); `reset` — the editor's live patch — fills
297
+ * omitted keys with the defaults instead, so clearing a field in the inspector takes effect. */
298
+ export declare const applyCameraProjection: (scene: Scene, def: CameraProjectionDef, reset?: boolean) => void;
299
+ export declare const foreignRuns: Map<Node, EditorRun[]>;
300
+ /** One live editor-run aspect instance (edit mode only). */
301
+ export type EditorRun = {
302
+ /** Absolute path of the host def node (re-keyed on rename/reparent). */
303
+ hostPath: string;
304
+ node: Node;
305
+ /** Index within the def's `aspects` array — the doc's aspect index addresses it. */
306
+ index: number;
307
+ inst: {
308
+ rebuild?(): void | Promise<void>;
309
+ };
310
+ /** Async rebuild() supersession counter (see safeRebuild). */
311
+ generation: number;
312
+ /** Mutable props snapshot — `sceneEditor.setProp` updates it and re-derives `deps`. Holds the
313
+ * DOC-LITERAL `$ref` strings (never resolved paths): the inspector's doc-sync compares these
314
+ * against the file's props, so rewriting them would re-fire on every render. */
315
+ props: Record<string, unknown>;
316
+ /** ABSOLUTE paths the ref() props resolved to — a change to any of them (or anything inside
317
+ * their subtrees) re-runs rebuild(). Re-derived after every structural change. */
318
+ deps: Set<string>;
319
+ /** Editor lines drawn by the last rebuild() (`Gizmos.*` calls — see scene/gizmos.ts). */
320
+ gizmos: GizmoBuffer;
321
+ };
322
+ /** Re-assign every ref-carrying prop from the CURRENT nodes map — a live patch replaces node
323
+ * instances, so a generator's resolved fields would otherwise point at destroyed nodes. */
324
+ export declare const assignRefProps: (run: EditorRun, nodes: Record<string, Node>) => void;
325
+ /** EditorRun.index for a node's make() run (aspect runs use their array index, always >= 0). */
326
+ export declare const MAKE_INDEX = -1;
286
327
  export declare class SceneHandle<D extends SceneDef = SceneDef> {
287
328
  readonly def: D;
288
329
  private _loading?;
@@ -0,0 +1,52 @@
1
+ import { type AspectClassInfo } from "../core/fields";
2
+ import { InspectorUI, type InspectorEvent, type InspectorWidget } from "../core/InspectorUI";
3
+ import type { Material } from "../gl/Material";
4
+ import type { Node } from "../gl/Node";
5
+ import { type ModelPartRow, type SceneHandle, type SceneNodeDef } from "./defineScene";
6
+ import { GizmoBuffer, type GizmoBatch } from "./gizmos";
7
+ type Handle = SceneHandle<any>;
8
+ export declare const sceneEditor: {
9
+ patchNode: (handle: Handle, path: string, def: SceneNodeDef | null) => Promise<Node | null>;
10
+ renameNode: (handle: Handle, path: string, newName: string) => string | null;
11
+ reparentNode: (handle: Handle, path: string, newParentPath: string | null) => string | null;
12
+ nodeChanged: (handle: Handle, path: string) => void;
13
+ modelParts: (handle: Handle, path: string) => Promise<ModelPartRow[]>;
14
+ describeAspects: (handle: Handle) => AspectClassInfo[];
15
+ setProp: (handle: Handle, hostPath: string, index: number, key: string, value: unknown) => boolean;
16
+ setMakeArg: (handle: Handle, hostPath: string, key: string, value: unknown) => boolean;
17
+ gizmos: (handle: Handle) => {
18
+ version: number;
19
+ batches: GizmoBatch[];
20
+ };
21
+ inspectorRender: (handle: Handle, hostPath: string, index: number, props: Record<string, unknown>, event?: InspectorEvent) => InspectorWidget[] | null;
22
+ /** The preview pose of a model node (`editor: { clip, time }`) — idempotent; no clip = the rest pose. */
23
+ applyPose: (node: Node, pose: {
24
+ clip?: string;
25
+ time?: number;
26
+ } | undefined) => void;
27
+ isLocked: (node: Node) => boolean;
28
+ setLocked: (node: Node, locked: boolean) => void;
29
+ /** Assign a material def to one slot of a node (a material asset handle, an inline def, a shader). */
30
+ assignMaterial: (node: Node, slot: number, def: import("./material").MaterialDef) => Promise<Material>;
31
+ /** One parameter into a live material: a value, or a texture URL that loads in. */
32
+ setMaterialParam: (material: Material, name: string, value: import("./material").MaterialParamValue | null) => Promise<void>;
33
+ isBuiltinMaterial: (material: Material) => boolean;
34
+ forgetMaterial: (node: Node, slot: number) => void;
35
+ GizmoBuffer: typeof GizmoBuffer;
36
+ withGizmoScope: <T>(buffer: GizmoBuffer, fn: () => T) => T;
37
+ runCard: (ui: InspectorUI, render: (ui: InspectorUI) => void, event?: InspectorEvent) => InspectorWidget[];
38
+ /** The registry `registerEditorWindow` / `registerEditorTool` fill (`*.editor.ts` files). */
39
+ plugins: {
40
+ windows: {
41
+ title: string;
42
+ render: import("./editorPlugins").EditorWindowFn;
43
+ }[];
44
+ tools: {
45
+ name: string;
46
+ hooks: import("./editorPlugins").EditorToolHooks;
47
+ }[];
48
+ };
49
+ };
50
+ /** The contract of an editor's in-world half with the SDK — the type of the `__sceneEditor` global. */
51
+ export type SceneEditorApi = typeof sceneEditor;
52
+ export {};
@@ -1,3 +1,4 @@
1
+ import { type ColorInput } from "../core/color";
1
2
  import { type Mat4Like } from "../math/mat4";
2
3
  import type { Vec3Like } from "../math/vec";
3
4
  /** The anchor of a gizmo call: any object with an engine entity id (a `Node`). */
@@ -5,8 +6,9 @@ export type GizmoAnchor = {
5
6
  readonly id: number;
6
7
  };
7
8
  export type GizmoStyle = {
8
- /** CSS hex color (`#rgb` / `#rrggbb`); default a neutral light gray. */
9
- color?: string;
9
+ /** Any color (a CSS color string, `0xRRGGBB`, `[r, g, b(, a)]`; its alpha multiplies `alpha`);
10
+ * default a neutral light gray. */
11
+ color?: ColorInput;
10
12
  /** 0..1, default 1. */
11
13
  alpha?: number;
12
14
  /** Anchor: points are in this node's LOCAL frame (scale ignored); the lines follow the node
@@ -14,8 +16,9 @@ export type GizmoStyle = {
14
16
  * selected. Omit for world-space lines (not pickable). */
15
17
  node?: GizmoAnchor | null;
16
18
  };
17
- /** One color batch of LINES (flat `[x,y,z, x,y,z]` per segment) — what a host hands the engine.
18
- * With `entityId` the segments are in that entity's local frame (see GizmoStyle.node). */
19
+ /** One color batch of LINES (flat `[x,y,z, x,y,z]` per segment) — what a host hands the engine
20
+ * (`color` a CSS color string, '#rrggbbaa' from here). With `entityId` the segments are in that
21
+ * entity's local frame (see GizmoStyle.node). */
19
22
  export type GizmoBatch = {
20
23
  color: string;
21
24
  alpha: number;
@@ -1,4 +1,4 @@
1
- import { type PresentOptions } from "./presentable";
1
+ import { type DismissOptions, type PresentOptions } from "./presentable";
2
2
  import { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from "./UINode";
3
3
  export type UINativeViewStyle = ElementStyle & DrawableStyle;
4
4
  /** An instance of a host-registered platform view (map, QR scanner, camera preview, …) —
@@ -13,15 +13,15 @@ export interface NativeView extends UIElementBase<UINativeViewStyle, DrawableSty
13
13
  /** Show fullscreen as the current destination (see Presentable). */
14
14
  open(options?: PresentOptions): void;
15
15
  /** Dismiss if this is the visible destination. */
16
- close(): void;
16
+ close(options?: DismissOptions): void;
17
17
  /** Became the visible destination. */
18
18
  onOpen(callback: () => void): this;
19
19
  /** Stopped being the visible destination. */
20
20
  onClose(callback: () => void): this;
21
21
  /** Hardware/system back while current. */
22
- onBackPressed(callback: () => void): this;
22
+ onBack(callback: () => void): this;
23
23
  /** Invoke a method on the native view (`map.call("setCenter", [lng, lat])`). Args and the
24
- * result are JSON-serialized. Rejects if the host has no such view/method. */
24
+ * result are plain data (and Uint8Array). Rejects if the host has no such view/method. */
25
25
  call(method: string, ...args: any[]): Promise<any>;
26
26
  /** Subscribe to an event the native view emits (`map.on("markerTap", cb)`). */
27
27
  on(event: string, callback: (data?: any) => void): this;
@@ -35,4 +35,6 @@ export declare const NativeView: {
35
35
  (name: string, params?: object): NativeView;
36
36
  /** Whether this host registered a `registerView` factory under `name`. */
37
37
  isSupported(name: string): boolean;
38
+ /** The contract version of the host's view `name`: 0 when it has none, 1 for one written by hand. */
39
+ version(name: string): number;
38
40
  };
@@ -18,7 +18,7 @@ export { UIVirtualizedList } from './UIVirtualizedList';
18
18
  export { Router } from './router';
19
19
  export { NativeView, type UINativeViewStyle } from './NativeView';
20
20
  export { Presentable } from './presentable';
21
- export type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from './presentable';
21
+ export type { DismissOptions, PresentOptions, Transition, TransitionName, TransitionPose, TransitionSpec } from './presentable';
22
22
  export { __uiMap } from './UINode';
23
23
  export { __UIColumn, __UIRow, __UIBox } from './UIContainer';
24
24
  export { __UIButton } from './UIButton';
@@ -14,11 +14,11 @@ export type UIBottomSheetStyle = UIModalStyle;
14
14
  * modal machinery.
15
15
  *
16
16
  * ```ts
17
- * const actions = UIBottomSheet({ bgColor: "#1c1c1e", borderRadius: 16 }, [rows]) // content-sized
17
+ * const actions = UIBottomSheet(rows).style({ bgColor: "#1c1c1e", borderRadius: 16 }) // content-sized
18
18
  *
19
- * const mapSheet = UIBottomSheet({ bgColor: "#1c1c1e", borderRadius: 16 }, [results])
19
+ * const mapSheet = UIBottomSheet(results).style({ bgColor: "#1c1c1e", borderRadius: 16 })
20
20
  * .detents([0.3, 0.6, 1])
21
- * .onDetentChange(i => map.setPadding(...))
21
+ * .onDetent(i => map.setPadding(...))
22
22
  * ```
23
23
  */
24
24
  export interface UIBottomSheet extends UIWidget {
@@ -26,12 +26,12 @@ export interface UIBottomSheet extends UIWidget {
26
26
  * the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet
27
27
  * is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */
28
28
  detents(list: number[]): this;
29
- /** Snap to a detent (animated). Clamped to the detents range; fires `onDetentChange`. */
29
+ /** Snap to a detent (animated). Clamped to the detents range; fires `onDetent`. */
30
30
  setDetent(index: number): void;
31
31
  /** Current detent index. */
32
32
  readonly detent: number;
33
33
  /** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */
34
- onDetentChange(callback: (index: number) => void): this;
34
+ onDetent(callback: (index: number) => void): this;
35
35
  /** Mount and slide in to the current detent. No-op while already open. */
36
36
  show(): void;
37
37
  /** Slide out, fade the scrim, then unmount. No-op while closed. */
@@ -49,16 +49,12 @@ export interface UIBottomSheet extends UIWidget {
49
49
  export declare class BottomSheetElement extends ModalElement {
50
50
  _detents: number[];
51
51
  _detent: number;
52
- /** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the
53
- * settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.
54
- * `-1` = dragged below the lowest detent while dismissible. */
55
- readonly dtl: any[];
56
52
  readonly _detentListeners: ((index: number) => void)[];
57
53
  constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn);
58
54
  detents(list: number[]): this;
59
55
  get detent(): number;
60
56
  setDetent(index: number): void;
61
- onDetentChange(callback: (index: number) => void): this;
57
+ onDetent(callback: (index: number) => void): this;
62
58
  show(): void;
63
59
  hide(): void;
64
60
  dismissible(enabled: boolean): this;
@@ -67,5 +63,3 @@ export declare class BottomSheetElement extends ModalElement {
67
63
  * `.detents([...])` for snap positions. Same argument forms as `UIColumn`. */
68
64
  export declare function UIBottomSheet(...children: UIChildArg[]): UIBottomSheet;
69
65
  export declare function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;
70
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
71
- export declare function UIBottomSheet(style: UIBottomSheetStyle, children?: UINodeChild[] | ChildrenFn): UIBottomSheet;
@@ -1,17 +1,11 @@
1
- import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType } from "../runtime/touch";
2
- import { type ElementStyle, type ContainerStyle, type DrawableStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type BaseStyle, type Color, type LayerEasing } from "./UINode";
1
+ import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType, MouseEnterEvent as MouseEnterEventType } from "../runtime/touch";
2
+ import { type ElementStyle, type ContainerStyle, type DrawableStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type BaseStyle, type Color } from "./UINode";
3
3
  export type UIButtonStyle = ElementStyle & DrawableStyle & ContainerStyle & {
4
4
  rippleColor?: Color | "default";
5
5
  };
6
- /** A tappable container — row + centered children by default. Press feedback via the `onPressed`
7
- * style block, the `$pressed` class, or `rippleColor`. */
8
- export interface UIButton extends UIContainerBase<UIButtonStyle & {
9
- onPressed?: UIButtonStyle & {
10
- duration?: number;
11
- delay?: number;
12
- easing?: LayerEasing;
13
- };
14
- }, DrawableStyle & BaseStyle> {
6
+ /** A tappable container — row + centered children by default. Press feedback via the `$pressed`
7
+ * class block or `rippleColor`. */
8
+ export interface UIButton extends UIContainerBase<UIButtonStyle, DrawableStyle & BaseStyle> {
15
9
  readonly type: "button";
16
10
  /** Fired on a completed tap/click. */
17
11
  onClick(callback: (ev: ClickEventType<UIButton>) => void): this;
@@ -21,12 +15,16 @@ export interface UIButton extends UIContainerBase<UIButtonStyle & {
21
15
  * `ev.track(...)` the rest of the gesture (like `onTouchStart`), so a hold can flow straight into
22
16
  * dragging the element. A handled long-press suppresses the click that would follow the release. */
23
17
  onLongPress(callback: (ev: LongPressEventType<UIButton>) => void): this;
18
+ /** Fired when a mouse cursor (no button) enters the button — desktop / web; touch never fires it.
19
+ * There is no leave event: `ev.track({ onMove, onEnd, onCancel })` follows the hover to its
20
+ * end. The visual state is the reserved `$hovered` class (cascades like `$pressed`). */
21
+ onMouseEnter(callback: (ev: MouseEnterEventType<UIButton>) => void): this;
24
22
  /** Is a finger currently down on the button? */
25
- isPressed(): boolean;
23
+ readonly isPressed: boolean;
24
+ /** Is a mouse cursor currently over the button (the topmost interactive node under it)? */
25
+ readonly isHovered: boolean;
26
26
  }
27
27
  /** Create a button (row + centered by default — the icon+label shape). Same argument forms as
28
28
  * `UIColumn`; attach behavior with `.onClick(...)`. */
29
29
  export declare function UIButton(...children: UIChildArg[]): UIButton;
30
30
  export declare function UIButton(children: UINodeChild[] | ChildrenFn): UIButton;
31
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
32
- export declare function UIButton(style: UIButtonStyle, children?: UINodeChild[] | ChildrenFn): UIButton;
@@ -10,8 +10,6 @@ export declare const __UIBox: (children: UINodeChild[] | ChildrenFn) => UIBox;
10
10
  * entries are skipped; a lone function makes the children reactive. */
11
11
  export declare function UIColumn(...children: UIChildArg[]): UIColumn;
12
12
  export declare function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn;
13
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
14
- export declare function UIColumn(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIColumn;
15
13
  /** A horizontal flex container — children flow left to right. */
16
14
  export interface UIRow extends UIContainerBase<UIContainerStyle> {
17
15
  readonly type: "row";
@@ -19,8 +17,6 @@ export interface UIRow extends UIContainerBase<UIContainerStyle> {
19
17
  /** Create a horizontal flex container (same argument forms as `UIColumn`). */
20
18
  export declare function UIRow(...children: UIChildArg[]): UIRow;
21
19
  export declare function UIRow(children: UINodeChild[] | ChildrenFn): UIRow;
22
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
23
- export declare function UIRow(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIRow;
24
20
  /** A centering container — `justifyContent`/`alignItems` default to center. */
25
21
  export interface UIBox extends UIContainerBase<UIContainerStyle> {
26
22
  readonly type: "box";
@@ -29,5 +25,3 @@ export interface UIBox extends UIContainerBase<UIContainerStyle> {
29
25
  * avatars, empty states). Same argument forms as `UIColumn`. */
30
26
  export declare function UIBox(...children: UIChildArg[]): UIBox;
31
27
  export declare function UIBox(children: UINodeChild[] | ChildrenFn): UIBox;
32
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
33
- export declare function UIBox(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIBox;
@@ -9,8 +9,7 @@ export type UIImageStyle = ElementStyle & {
9
9
  objectFit?: "cover" | "contain" | "fill";
10
10
  tintColor?: Color;
11
11
  };
12
- /** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture — see
13
- * docs/canvas-contract.md ("Pending"). */
12
+ /** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture. */
14
13
  export type CanvasImageSource = {
15
14
  canvasSurface: number;
16
15
  };
@@ -41,5 +40,3 @@ export interface UIImage extends UIElementBase<UIImageStyle> {
41
40
  }
42
41
  /** Create an image element from a source (see {@link ImageSource}). */
43
42
  export declare function UIImage(src: ImageSource): UIImage;
44
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
45
- export declare function UIImage(style: UIImageStyle, src: ImageSource): UIImage;
@@ -1,4 +1,4 @@
1
- import { type ElementStyle, type DrawableStyle, type TextStyle, type Color, type BaseStyle, type UIElementBase, type LayerEasing } from "./UINode";
1
+ import { type ElementStyle, type DrawableStyle, type TextStyle, type Color, type BaseStyle, type UIElementBase } from "./UINode";
2
2
  type InputStyle = {
3
3
  placeholder?: string;
4
4
  placeholderColor?: Color;
@@ -47,20 +47,10 @@ type SubmitStyle = {
47
47
  };
48
48
  /** A single-line text input. Keyboard/picker kind via the `type` style, return-key behavior via
49
49
  * `enterKey` + `onSubmit`; keyboard policy on `keyboardShrink`/`keyboardDismiss`. */
50
- export interface UIInput extends UIElementBase<UIInputStyle & SubmitStyle & {
51
- onFocused?: UIInputStyle & {
52
- duration?: number;
53
- delay?: number;
54
- easing?: LayerEasing;
55
- };
56
- }, DrawableStyle & BaseStyle> {
50
+ export interface UIInput extends UIElementBase<UIInputStyle & SubmitStyle, DrawableStyle & BaseStyle> {
57
51
  readonly type: "input";
58
- /**
59
- * The field's text. Writable at any time — set it BEFORE the screen opens to pre-fill a form
60
- * (settings, edit-profile); the value is stashed on the node and applied when the host builds
61
- * it. Reads return the live text while the screen is open, and the last value you set while it
62
- * isn't. The user's typing is not preserved across close/open (use `keepAlive()` for that).
63
- */
52
+ /** The field's text. Writable at any time; reads return the live text (the host owns the field
53
+ * while the user types — IME composition, paste, the maxLength clamp, date/time canonicalization). */
64
54
  value: string;
65
55
  /** The text changed — fires on every user edit. */
66
56
  onChange(callback: (value: string) => void): UIInput;
@@ -70,21 +60,15 @@ export interface UIInput extends UIElementBase<UIInputStyle & SubmitStyle & {
70
60
  onBlur(callback: () => void): UIInput;
71
61
  /** The keyboard's return key was pressed. `value` is the current text. See `enterKey`. */
72
62
  onSubmit(callback: (value: string) => void): UIInput;
73
- /** Focus the input (opens the keyboard). No-op before mount. */
63
+ /** Focus the input (opens the keyboard). */
74
64
  focus(): void;
75
65
  /** Release focus (dismisses the keyboard when this input held it). */
76
66
  blur(): void;
77
67
  }
78
68
  /** A multi-line text field — see the {@link UITextArea} factory for the auto-grow contract. */
79
- export interface UITextArea extends UIElementBase<UIInputStyle & {
80
- onFocused?: UIInputStyle & {
81
- duration?: number;
82
- delay?: number;
83
- easing?: LayerEasing;
84
- };
85
- }, DrawableStyle & BaseStyle> {
69
+ export interface UITextArea extends UIElementBase<UIInputStyle, DrawableStyle & BaseStyle> {
86
70
  readonly type: "textarea";
87
- /** The field's text — same contract as {@link UIInput.value}: settable before mount to pre-fill. */
71
+ /** The field's text — same contract as {@link UIInput.value}. */
88
72
  value: string;
89
73
  /** The text changed — fires on every user edit. */
90
74
  onChange(callback: (value: string) => void): UITextArea;
@@ -92,7 +76,7 @@ export interface UITextArea extends UIElementBase<UIInputStyle & {
92
76
  onFocus(callback: () => void): UITextArea;
93
77
  /** Lost focus. */
94
78
  onBlur(callback: () => void): UITextArea;
95
- /** Focus the text area (opens the keyboard). No-op before mount. */
79
+ /** Focus the text area (opens the keyboard). */
96
80
  focus(): void;
97
81
  /** Release focus (dismisses the keyboard when this text area held it). */
98
82
  blur(): void;
@@ -66,5 +66,3 @@ export declare class ModalElement extends WidgetElement {
66
66
  * `show()`/`hide()`. Same argument forms as `UIColumn`. */
67
67
  export declare function UIModal(...children: UIChildArg[]): UIModal;
68
68
  export declare function UIModal(children: UINodeChild[] | ChildrenFn): UIModal;
69
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
70
- export declare function UIModal(style: UIModalStyle, children?: UINodeChild[] | ChildrenFn): UIModal;