lecodes-sdk 1.2.0 → 2.0.1

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 (260) 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 +8 -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/Scene.d.ts +41 -13
  25. package/dist/types/gl/Texture.d.ts +1 -1
  26. package/dist/types/gl/animation/Locomotion.d.ts +8 -1
  27. package/dist/types/inject.d.ts +11 -11
  28. package/dist/types/inject.editor.d.ts +1 -0
  29. package/dist/types/net/core.d.ts +7 -0
  30. package/dist/types/plugin.d.ts +76 -0
  31. package/dist/types/plugins/gen/camera/sdk/camera.d.ts +24 -0
  32. package/dist/types/plugins/gen/camera/sdk/camera.gen.d.ts +25 -0
  33. package/dist/types/plugins/{geolocation.d.ts → gen/geolocation/sdk/geolocation.d.ts} +2 -20
  34. package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +31 -0
  35. package/dist/types/plugins/{map.d.ts → gen/map/sdk/map.d.ts} +9 -50
  36. package/dist/types/plugins/gen/map/sdk/map.gen.d.ts +53 -0
  37. package/dist/types/plugins/gen/push/sdk/push.d.ts +23 -0
  38. package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +35 -0
  39. package/dist/types/plugins/{qr.d.ts → gen/qr-scanner/sdk/qr-scanner.d.ts} +2 -3
  40. package/dist/types/plugins/gen/qr-scanner/sdk/qr-scanner.gen.d.ts +15 -0
  41. package/dist/types/runtime/app.d.ts +9 -2
  42. package/dist/types/runtime/fetch.d.ts +2 -0
  43. package/dist/types/runtime/input.d.ts +1 -1
  44. package/dist/types/runtime/media.d.ts +6 -10
  45. package/dist/types/runtime/misc.d.ts +4 -1
  46. package/dist/types/runtime/net.d.ts +3 -2
  47. package/dist/types/runtime/touch.d.ts +32 -0
  48. package/dist/types/scene/defineScene.d.ts +43 -2
  49. package/dist/types/scene/editor.d.ts +52 -0
  50. package/dist/types/scene/gizmos.d.ts +7 -4
  51. package/dist/types/ui/NativeView.d.ts +6 -4
  52. package/dist/types/ui/UI.d.ts +1 -1
  53. package/dist/types/ui/UIBottomSheet.d.ts +6 -12
  54. package/dist/types/ui/UIButton.d.ts +12 -14
  55. package/dist/types/ui/UIContainer.d.ts +0 -6
  56. package/dist/types/ui/UIImage.d.ts +1 -4
  57. package/dist/types/ui/UIInput.d.ts +8 -24
  58. package/dist/types/ui/UIModal.d.ts +0 -2
  59. package/dist/types/ui/UINode.d.ts +70 -56
  60. package/dist/types/ui/UIPager.d.ts +28 -27
  61. package/dist/types/ui/UIPopover.d.ts +0 -2
  62. package/dist/types/ui/UIScreen.d.ts +12 -17
  63. package/dist/types/ui/UIScrollable.d.ts +1 -4
  64. package/dist/types/ui/UIText.d.ts +0 -2
  65. package/dist/types/ui/UIVideo.d.ts +3 -5
  66. package/dist/types/ui/UIVirtualizedList.d.ts +14 -16
  67. package/dist/types/ui/UIWidget.d.ts +10 -9
  68. package/dist/types/ui/colorKeys.gen.d.ts +9 -0
  69. package/dist/types/ui/presentable.d.ts +46 -32
  70. package/dist/types/ui/router.d.ts +18 -7
  71. package/dist/types/ui/styleColor.d.ts +1 -0
  72. package/dist/types/ui/transitions.d.ts +18 -0
  73. package/dist/types/ui/tree.d.ts +75 -0
  74. package/dist/types/version.d.ts +10 -0
  75. package/dist/types.json +1 -1
  76. package/package.json +12 -3
  77. package/prompts/2d.md +2 -6
  78. package/prompts/3d.md +1 -5
  79. package/prompts/README.md +1 -1
  80. package/prompts/canvas.md +9 -8
  81. package/prompts/compose.ts +1 -1
  82. package/prompts/core.md +3 -3
  83. package/prompts/design.md +1 -1
  84. package/prompts/dist/2d-game.md +473 -239
  85. package/prompts/dist/3d-app.md +553 -205
  86. package/prompts/dist/ar-app.md +435 -202
  87. package/prompts/dist/design.md +113 -95
  88. package/prompts/dist/ui-app.md +386 -170
  89. package/prompts/ui-design.md +2 -3
  90. package/prompts/ui.md +45 -37
  91. package/src/animate/tween/Animation.ts +34 -150
  92. package/src/animate/tween/Timeline.ts +175 -175
  93. package/src/animate/tween/animateValue.ts +6 -3
  94. package/src/animate/tween/easing.ts +10 -3
  95. package/src/animate/tween/spec.ts +41 -15
  96. package/src/audio/Sound.ts +3 -3
  97. package/src/audio/audio.ts +2 -1
  98. package/src/bridges/2d.d.ts +317 -0
  99. package/src/bridges/app.d.ts +91 -0
  100. package/src/bridges/audio.d.ts +97 -0
  101. package/src/bridges/canvas.d.ts +79 -0
  102. package/src/bridges/device.d.ts +72 -0
  103. package/src/bridges/fetch.d.ts +80 -0
  104. package/src/bridges/files.d.ts +70 -0
  105. package/src/bridges/gl.d.ts +1133 -0
  106. package/src/bridges/input.d.ts +72 -0
  107. package/src/bridges/media.d.ts +55 -0
  108. package/src/bridges/nav.d.ts +71 -0
  109. package/src/bridges/net.d.ts +52 -0
  110. package/src/bridges/service.d.ts +52 -0
  111. package/src/bridges/socket.d.ts +31 -0
  112. package/src/bridges/storage.d.ts +33 -0
  113. package/src/bridges/tree.d.ts +301 -0
  114. package/src/bridges/types.d.ts +49 -0
  115. package/src/canvas/Canvas.ts +114 -159
  116. package/src/canvas/gen/cssColor.ts +224 -0
  117. package/src/canvas/gen/recorder.ts +212 -0
  118. package/src/canvas/gen/spec.ts +201 -0
  119. package/src/chisel.ts +193 -0
  120. package/src/compile/assetMacro.ts +1 -1
  121. package/src/compile/bundler.ts +11 -2
  122. package/src/compile/compileProject.ts +43 -4
  123. package/src/compile/fontMacro.ts +3 -4
  124. package/src/compile/header.ts +26 -5
  125. package/src/compile/index.ts +3 -1
  126. package/src/compile/liteMaterial.ts +1 -1
  127. package/src/compile/sceneEditor.ts +11 -26
  128. package/src/core/color.ts +73 -30
  129. package/src/core/pins.ts +51 -0
  130. package/src/core/signals.ts +8 -1
  131. package/src/g2/CharacterController2D.ts +3 -3
  132. package/src/g2/Node2D.ts +57 -39
  133. package/src/g2/Physics2D.ts +2 -2
  134. package/src/g2/Scene2D.ts +35 -23
  135. package/src/g2/Texture2D.ts +1 -1
  136. package/src/g2/loop.ts +4 -4
  137. package/src/gl/CameraPlace.ts +52 -52
  138. package/src/gl/Foliage.ts +72 -17
  139. package/src/gl/Geometry.ts +1 -2
  140. package/src/gl/Light.ts +10 -0
  141. package/src/gl/Lightmap.ts +45 -29
  142. package/src/gl/Material.ts +95 -51
  143. package/src/gl/Mesh.ts +120 -120
  144. package/src/gl/Model.ts +21 -16
  145. package/src/gl/Node.ts +91 -24
  146. package/src/gl/Particles.ts +1 -1
  147. package/src/gl/Scene.ts +100 -44
  148. package/src/gl/Texture.ts +8 -7
  149. package/src/gl/animation/AnimationClip.ts +1 -1
  150. package/src/gl/animation/DynamicBone.ts +482 -482
  151. package/src/gl/animation/Locomotion.ts +8 -3
  152. package/src/gl/nav/NavMesh.ts +3 -4
  153. package/src/gl/physics/Physics.ts +2 -2
  154. package/src/gl/physics/physicsEvents.ts +3 -3
  155. package/src/gl/scenarios.ts +291 -291
  156. package/src/gl/terrain/Terrain.ts +4 -5
  157. package/src/gl/touch.ts +14 -15
  158. package/src/host.d.ts +2 -3
  159. package/src/inject.editor.ts +7 -0
  160. package/src/inject.ts +13 -16
  161. package/src/net/core.ts +6 -5
  162. package/src/net/index.ts +1 -1
  163. package/src/net/replication.ts +1 -1
  164. package/src/plugin.ts +191 -0
  165. package/src/plugins/gen/camera/contract.d.ts +27 -0
  166. package/src/plugins/gen/camera/sdk/camera.gen.ts +46 -0
  167. package/src/plugins/gen/camera/sdk/camera.ts +57 -0
  168. package/src/plugins/gen/geolocation/contract.d.ts +50 -0
  169. package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +54 -0
  170. package/src/plugins/{geolocation.ts → gen/geolocation/sdk/geolocation.ts} +22 -43
  171. package/src/plugins/gen/map/contract.d.ts +144 -0
  172. package/src/plugins/gen/map/sdk/map.gen.ts +88 -0
  173. package/src/plugins/{map.ts → gen/map/sdk/map.ts} +68 -102
  174. package/src/plugins/gen/push/contract.d.ts +61 -0
  175. package/src/plugins/gen/push/sdk/push.gen.ts +60 -0
  176. package/src/plugins/gen/push/sdk/push.ts +105 -0
  177. package/src/plugins/gen/qr-scanner/contract.d.ts +16 -0
  178. package/src/plugins/gen/qr-scanner/sdk/qr-scanner.gen.ts +29 -0
  179. package/src/plugins/gen/qr-scanner/sdk/qr-scanner.ts +52 -0
  180. package/src/plugins/permission.ts +5 -4
  181. package/src/runtime/app.ts +20 -9
  182. package/src/runtime/appEvents.ts +5 -4
  183. package/src/runtime/channel.ts +18 -15
  184. package/src/runtime/clipboard.ts +4 -3
  185. package/src/runtime/datetime.ts +2 -1
  186. package/src/runtime/device.ts +17 -15
  187. package/src/runtime/fetch.ts +30 -20
  188. package/src/runtime/files.ts +16 -15
  189. package/src/runtime/input.ts +12 -10
  190. package/src/runtime/media.ts +50 -46
  191. package/src/runtime/misc.ts +7 -3
  192. package/src/runtime/net.ts +8 -7
  193. package/src/runtime/rpc.ts +1 -3
  194. package/src/runtime/service.ts +19 -14
  195. package/src/runtime/share.ts +4 -3
  196. package/src/runtime/storage.ts +6 -4
  197. package/src/runtime/touch.ts +32 -0
  198. package/src/scene/defineScene.ts +61 -365
  199. package/src/scene/editor.ts +408 -0
  200. package/src/scene/editorPlugins.ts +3 -3
  201. package/src/scene/gizmos.ts +15 -9
  202. package/src/server/db/marci/query.ts +1 -1
  203. package/src/server/host.ts +1 -1
  204. package/src/server/runtime.ts +1 -1
  205. package/src/ui/NativeView.ts +72 -25
  206. package/src/ui/UI.ts +3 -3
  207. package/src/ui/UIBottomSheet.ts +16 -17
  208. package/src/ui/UIButton.ts +54 -16
  209. package/src/ui/UIContainer.ts +0 -6
  210. package/src/ui/UIImage.ts +34 -30
  211. package/src/ui/UIInput.ts +29 -37
  212. package/src/ui/UIModal.ts +1 -3
  213. package/src/ui/UINode.ts +347 -297
  214. package/src/ui/UIPager.ts +93 -78
  215. package/src/ui/UIPopover.ts +0 -2
  216. package/src/ui/UIScreen.ts +41 -36
  217. package/src/ui/UIScrollable.ts +19 -13
  218. package/src/ui/UISpacer.ts +1 -1
  219. package/src/ui/UITabs.ts +8 -6
  220. package/src/ui/UIText.ts +7 -17
  221. package/src/ui/UIVideo.ts +30 -27
  222. package/src/ui/UIVirtualizedList.ts +58 -59
  223. package/src/ui/UIWidget.ts +38 -18
  224. package/src/ui/colorKeys.gen.ts +37 -0
  225. package/src/ui/fonts.ts +2 -2
  226. package/src/ui/presentable.ts +59 -42
  227. package/src/ui/router.ts +52 -35
  228. package/src/ui/styleColor.ts +56 -0
  229. package/src/ui/theme.ts +7 -6
  230. package/src/ui/transitions.ts +249 -0
  231. package/src/ui/tree.ts +346 -0
  232. package/src/version.ts +24 -0
  233. package/tests/helpers/engineWorld.ts +11 -0
  234. package/tests/helpers/fakeTree.ts +353 -0
  235. package/tests/helpers/hostStubs.ts +31 -0
  236. package/tests/helpers/index.ts +14 -0
  237. package/tests/helpers/memoryMarci.ts +124 -0
  238. package/tests/helpers/phases.ts +23 -0
  239. package/tests/helpers/preload.ts +18 -0
  240. package/tests/helpers/stubApp.ts +2 -0
  241. package/tests/helpers/stubDevice.ts +2 -0
  242. package/tests/helpers/stubFetch.ts +2 -0
  243. package/tests/helpers/stubInput.ts +2 -0
  244. package/dist/inject.js +0 -4629
  245. package/dist/types/core/registry.d.ts +0 -7
  246. package/dist/types/plugins/camera.d.ts +0 -25
  247. package/dist/types/plugins/push.d.ts +0 -46
  248. package/src/bridges.d.ts +0 -1769
  249. package/src/compile/__tests__/assetIconMacro.test.ts +0 -219
  250. package/src/compile/__tests__/assetMacro.test.ts +0 -100
  251. package/src/compile/__tests__/assetName.test.ts +0 -55
  252. package/src/compile/__tests__/compile.test.ts +0 -310
  253. package/src/compile/__tests__/detectEntry.test.ts +0 -151
  254. package/src/compile/__tests__/fontMacro.test.ts +0 -199
  255. package/src/compile/__tests__/serverSplit.test.ts +0 -27
  256. package/src/core/__tests__/stateMachine.test.ts +0 -132
  257. package/src/core/registry.ts +0 -23
  258. package/src/plugins/camera.ts +0 -81
  259. package/src/plugins/push.ts +0 -132
  260. package/src/plugins/qr.ts +0 -73
@@ -0,0 +1,301 @@
1
+ // The UI tree bridge (`_creatorTree`): the runtime OWNS the UI tree — every node exists in
2
+ // runtime/native's presentation from `create()` on (engines/ui Yoga + the screens / destinations /
3
+ // widgets / pager / vlist model), and the SDK's element objects are HANDLES over it (docs/hosts-
4
+ // unification-plan.md, phase 9). Nothing here reads a JS object: every argument is a node id or a
5
+ // scalar, every event comes back through the one emitter with the node id. Part of the host
6
+ // contract: every runtime implements this global (runtime/native in C++, the wasm build of the same
7
+ // code for the simulator hosts). Types are the PRECISE ones the native side reads (./types.d.ts).
8
+ import type { f32, f64, i32, i64, nodeid, u16, u32, u8 } from "./types"
9
+
10
+ declare global {
11
+ /** A node id: the runtime's node pointer as a JS number (< 2^53). Stable for the node's life. */
12
+ type TreeNodeId = number
13
+
14
+ /** An OWNED handle (docs/plans/hosts-unification-plan.md, phase 10): what a `create…` call returns —
15
+ * the resource's id on an object whose collection tells the runtime "the app dropped this" (a
16
+ * class object with a finalizer on QuickJS / JSC, a FinalizationRegistry token in wasm). The
17
+ * SDK wrapper keeps it as `_h` and uses `_h.id` on the wire; there is no other reference. */
18
+ interface Handle { readonly id: number }
19
+
20
+ var _creatorTree: {
21
+ // ---- nodes --------------------------------------------------------------------------------
22
+ // Create a node of `type` ("screen", "column", "text", "input", "pager", "vlist", "native", …) as
23
+ // a detached layout root; the host's view exists from here on (HostUI.nodeFactory). The node
24
+ // belongs to the JS handle until it gets a parent or is presented.
25
+ create(type: string): Handle
26
+ // Free a DETACHED subtree now (`node.destroy()`): yoga, the host views, the owner slots. A node
27
+ // that still has a parent or is presented is left alone (an error is logged). The handles of
28
+ // the freed descendants come back through `freed`.
29
+ destroy(id: TreeNodeId): void
30
+ // Attach `child` (a root) under `parent` at `index` (clamped); `remove` makes it a root again
31
+ // without freeing it. A pager parent takes PAGES (independent layout roots), a vlist parent takes
32
+ // nothing (items go through vlistMount).
33
+ insert(parent: TreeNodeId, child: TreeNodeId, index: i32): void
34
+ remove(parent: TreeNodeId, child: TreeNodeId): void
35
+ // The parent's id, 0 for a root; the children's ids (a pager's pages in tab-major order).
36
+ parent(id: TreeNodeId): TreeNodeId
37
+ children(id: TreeNodeId): TreeNodeId[]
38
+
39
+ // ---- content ------------------------------------------------------------------------------
40
+ // A content property as text: "text", "src" (a url; "id:<bufferId>" for a host buffer,
41
+ // "svg:<source>", "canvas:<surfaceId>", "scene2d:<sceneId>" — the SDK spells the prefixes),
42
+ // "value", "focus" ("1" / "0"), "sourceRect" ("x y w h"), "viewName", "viewParams" (JSON),
43
+ // "name". null clears. The runtime dirties a measured leaf's layout for text / src / value and
44
+ // forwards to the host. "srcTintColor" (a CSS color or var(), the source's own tint) is the
45
+ // exception: the runtime stores it as the node's tintColor on the core's SOURCE layer (under
46
+ // every style tint; a src write drops it) and never forwards it.
47
+ setString(id: TreeNodeId, key: string, value: string | null): void
48
+ // A small integer content property: "playerId" (a media player), "viewId" (a NativeView).
49
+ setInt(id: TreeNodeId, key: string, value: i32): void
50
+ // Which listeners / traits the node has (TREE_FLAG_* of the SDK's tree.ts, mirrored in
51
+ // runtime/native/src/presentation/tree-events.h): the host reads the mask for hit-testing
52
+ // and event routing; the runtime for the back chain and the interaction classes' scope (an
53
+ // INTERACTIVE node starts its own $hovered / $pressed / $focused). Replaces the whole mask.
54
+ setFlags(id: TreeNodeId, mask: u32): void
55
+ // An input's live text (the host's; "" for anything else).
56
+ getTextValue(id: TreeNodeId): string
57
+
58
+ // ---- style --------------------------------------------------------------------------------
59
+ setStyle(id: TreeNodeId, key: string, value: string | f64 | null): void
60
+ // A style bag: plain values, `{ _h }` owned handles (backgroundImage), nested state blocks
61
+ // (`$class` keys — `$pressed`, `$landscape`, `$checked`, …) under their own layer.
62
+ mergeStyle(id: TreeNodeId, style: object): void
63
+ // Toggle a user style class (`name` WITHOUT the `$`); cascades to descendants — engines/ui's
64
+ // setNodeClass owns the cascade, hosts add nothing. The reserved names (hovered pressed focused
65
+ // landscape portrait) are refused: the system toggles those.
66
+ setClass(id: TreeNodeId, name: string, enabled: boolean): void
67
+ // Theme variables: MERGES `values` (null removes a key, numbers are px lengths, a color is a
68
+ // string) and re-resolves live styles. Env names (safe-*, vw/vh/…) are reserved.
69
+ setTheme(values: Record<string, string | f64 | null>): void
70
+
71
+ // ---- presentation -------------------------------------------------------------------------
72
+ // A transition (sdk/src/ui/transitions.ts): a tween blob whose targets are ROLES — `roles[i]` is
73
+ // the role of the blob's target i (0 the incoming screen, 1 the outgoing one, 2 / 3 the same two
74
+ // playing ALONE: next to a scene / a native view / a video, which never move, or to nothing).
75
+ // `flags`: 1 = the incoming side is above the outgoing one. Registered once per world; the id
76
+ // (> 0) is what the calls below carry — 0 = no transition, -1 = the caller names none (a pop
77
+ // plays what the entry it pops remembers; a replace keeps the way back of the entry it replaces).
78
+ defineTransition(data: Float32Array, strings: string[], roles: i32[], flags: i32): i32
79
+ // Present a destination directly (suspends an active router until routerRestore). `kind` is
80
+ // TREE_DEST_* (0 screen: `id` = the screen node; 1 scene3d / 2 scene2d: `id` = the sceneId;
81
+ // 3 native: `id` = the NativeView's viewId, `viewName` + `paramsJson` its factory call; 4 video:
82
+ // `id` = the video node).
83
+ open(kind: u8, id: f64, viewName: string, paramsJson: string, transition: i32): void
84
+ // Dismiss the destination (kind, id) with no successor — only when it is the one on screen: a
85
+ // destination something else already replaced (a router init / push, another open) is left
86
+ // alone, so a late `scene.close()` never takes down the page that replaced the scene.
87
+ close(kind: u8, id: f64, transition: i32): void
88
+ // The router over destinations (the same (kind, id, viewName, paramsJson) tuple). The runtime
89
+ // reports every stack change through the `routerChange` event with the new top's (kind, id).
90
+ // `back` = the way back the new entry remembers: what a pop that names no transition, the edge
91
+ // swipe and the system's back play.
92
+ routerOpen(kind: u8, id: f64, viewName: string, paramsJson: string, showBackButton: boolean): void
93
+ routerPush(kind: u8, id: f64, viewName: string, paramsJson: string, transition: i32, back: i32): void
94
+ routerReplace(kind: u8, id: f64, viewName: string, paramsJson: string, transition: i32, back: i32): void
95
+ routerPop(index: i32, transition: i32): void
96
+ routerHide(transition: i32): void
97
+ routerRestore(transition: i32): void
98
+ // Does the host registerView(name)? / the contract version its half was generated from (0 = no
99
+ // such view; on a host that does not say, 1 for a view it has) / the NativeView method channel:
100
+ // `args` is the array of the call's arguments, the callbacks settle exactly once through the
101
+ // dispatch bridge. A value that cannot cross (runtime/native/src/values/js.h) throws here,
102
+ // before the host sees the call.
103
+ isViewSupported(name: string): boolean
104
+ viewVersion(name: string): i32
105
+ viewCall(viewId: i32, method: string, args: value, onComplete: (result?: value) => void, onReject: (message: string) => void): void
106
+ // Show a widget root; `ownerKind` / `ownerId` bind it to a destination (widget.attachTo: it
107
+ // mounts inside that page and rides its transition) — TREE_DEST_NONE = a global overlay.
108
+ showWidget(id: TreeNodeId, ownerKind: u8, ownerId: f64): void
109
+ hideWidget(id: TreeNodeId): void
110
+
111
+ // ---- pager (a "pager" node's children are its pages; TAB-MAJOR order, `lens` = per-tab stack
112
+ // lengths, `index` = the selected tab). A change of the current tab's stack plays a
113
+ // transition like the router's — the same ids, the pager being the stage; `back` = the way
114
+ // back the new entry remembers (what a pop that names none, the back button and the edge
115
+ // swipe's fallback play) ----------------------------------------------------------------
116
+ pagerSetContent(id: TreeNodeId, pages: TreeNodeId[], lens: i32[], index: i32): void
117
+ pagerSelect(id: TreeNodeId, index: i32, animated: boolean): void
118
+ pagerPush(id: TreeNodeId, page: TreeNodeId, transition: i32, back: i32): void
119
+ pagerPop(id: TreeNodeId, transition: i32): void
120
+ pagerPopToRoot(id: TreeNodeId, transition: i32): void
121
+ pagerReplace(id: TreeNodeId, page: TreeNodeId, transition: i32, back: i32): void
122
+
123
+ // ---- virtualized list (the window math lives in engines/ui vlist.cpp) ----------------------
124
+ // Right after create("vlist"): the list's config (overscan px, -1 = a viewport; chat mode;
125
+ // the onStart / onEnd thresholds).
126
+ vlistInit(id: TreeNodeId, overscan: f32, inverted: boolean, startThreshold: f32, endThreshold: f32): void
127
+ vlistSetKeys(id: TreeNodeId, keys: string[], estimates: f32[]): void
128
+ vlistInsertKeys(id: TreeNodeId, index: i32, keys: string[], estimates: f32[]): void
129
+ vlistRemoveKeys(id: TreeNodeId, keys: string[]): void
130
+ vlistInvalidate(id: TreeNodeId, key: string): void
131
+ // From inside a `vlistSync` event, per mount key: the item subtree (a root) becomes the mounted
132
+ // item — the runtime measures it and anchors the window.
133
+ vlistMount(id: TreeNodeId, key: string, item: TreeNodeId): void
134
+ vlistScrollTo(id: TreeNodeId, offset: f32, animated: boolean): void
135
+ vlistScrollToKey(id: TreeNodeId, key: string, animated: boolean): void
136
+ vlistScrollToEnd(id: TreeNodeId, animated: boolean): void
137
+
138
+ // ---- misc ---------------------------------------------------------------------------------
139
+ // Load a font face (weight 100–900, style 0 normal / 2 italic); the callbacks settle once.
140
+ registerFont(fontFamily: string, url: string, weight: i32, style: i32, onComplete: () => void, onReject: () => void): void
141
+ // Preferred container format for CDN-served faces: "woff2" on browser hosts, absent (= "ttf")
142
+ // on native / headless — read by the font() macro's generated registration code.
143
+ fontFormat?: "woff2" | "ttf"
144
+ toast(message: string, durationMs: i32): void
145
+ // Is the button node pressed right now (the UIButton.isPressed getter)?
146
+ isButtonPressed(id: TreeNodeId): boolean
147
+ // Is the node the one under the mouse cursor (the runtime's hover state, presentation/hover.cpp)?
148
+ isHovered(id: TreeNodeId): boolean
149
+ // [left, top, width, height] in logical px, scroll included, read live; null when not laid out
150
+ // or on a host without the read (VR panel).
151
+ getBoundingClientRect(id: TreeNodeId): [number, number, number, number] | null
152
+ // The display size [width, height] in logical px (0×0 until the host's first onResize).
153
+ getDisplaySize(): [number, number]
154
+ // ---- debug: the tree of truth as JSON ------------------------------------------------------
155
+ // Every live root (the presented screen, the shown widgets, a pager's pages); per node the id,
156
+ // type, name, flags, laid-out box and the paint record (present / dirty / own + every field).
157
+ // Runtime-side text, identical on every host — the same JSON `lecodes test`'s `dump` writes.
158
+ debugDump(): string
159
+ // One node's paint record as JSON ("null" for a dead id).
160
+ debugPaint(id: TreeNodeId): string
161
+ // Canvas.update(): every image node showing this baked surface re-reads its pixels in place —
162
+ // a HOST-provided method (registerCallback) where the host can; the SDK re-assigns `src` otherwise.
163
+ refreshCanvasSurface?(surfaceId: i32): void
164
+
165
+ // ---- keyframe animation core (creator-tween; docs/timeline-plan.md) ------------------------
166
+ // One evaluator for UI style props, 3D node transforms / lights / cameras and 2D sprites: the
167
+ // SDK hands over a flat blob (sdk/src/animate/tween/spec.ts) and gets an id. `targets` are the
168
+ // track targets: a node id for the UI domain, an entity / scene id for the 3D and 2D domains.
169
+ // Created = paused at t = 0. Ops: 0 play, 1 pause, 2 resume, 3 cancel, 4 finish. Events come
170
+ // back through the `tween` event (kind 0 call, 1 finish, 2 a VALUE track's frame).
171
+ // Owned (owned.h): the animation is natively owned while it PLAYS; dropped otherwise → cancelled.
172
+ tweenCreate(data: Float32Array, strings: string[], targets: f64[]): Handle | null
173
+ tweenControl(id: u32, op: i32): void
174
+ tweenSeek(id: u32, ms: f32): void
175
+ tweenSetRate(id: u32, rate: f32): void
176
+ tweenGetTime(id: u32): f64
177
+ tweenGetElapsed(id: u32): f64
178
+ // The tween core's own callback (kind 0 = call, 1 = finish, 2 = a VALUE track's frame followed
179
+ // by its lanes as plain numbers) — separate from the emitter because of the variable arity.
180
+ registerTweenEvent(callback: (id: number, kind: number, index: number, ...lanes: number[]) => void): void
181
+
182
+ // ---- events -------------------------------------------------------------------------------
183
+ // ONE function per world receives everything the runtime says (TREE_EVENT_* of tree.ts /
184
+ // tree-events.h): `fn(id, kind, a, b, c, d)` with `id` the node (0 for world-level events: scene
185
+ // touches, resize, router changes, back). The return value matters for touchStart / longPress
186
+ // (the track claim mask: 0 = untracked, else TREE_TRACK_* bits) and back (true = handled).
187
+ // Delivered on the JS thread; `vlistSync` arrives synchronously (the SDK re-enters vlistMount
188
+ // from it).
189
+ setEmitter(fn: (id: TreeNodeId, kind: i32, a?: any, b?: any, c?: any, d?: any) => any): void
190
+ }
191
+ }
192
+
193
+ /** The UI RENDERER's side of the contract — the table runtime/native's presentation core calls
194
+ * (`HostUI` of creator-pkg/host.gen.h; a host fills it BEFORE initJS(), `?` = optional slot). The
195
+ * runtime owns the tree (engines/ui Yoga, the screens / destinations / widgets / pager / vlist
196
+ * model); the host owns one view per node, keyed by the node id (the same pointer engines/ui's
197
+ * style handlers deliver) and paints it. Nothing of JavaScript reaches the host:
198
+ * listeners are a flag mask, events go back through the runtime's entry points with the node id.
199
+ * One implementation per platform: renderers/tgfx (desktop, Quest), the Kotlin views (Android),
200
+ * UIKit (Apple), the null renderer of lecodes-server.
201
+ * @host ui HostUI */
202
+ export interface HostUI {
203
+ /** Create the host view for a node of `type` ("column", "text", "image", "input", "screen", …).
204
+ * Called at the node's creation, before any parent exists (`parent` is 0 then); `index` is the
205
+ * position it will take under `parent` when both are known at once. */
206
+ nodeFactory(id: nodeid, type: string, parent: nodeid, index: i32): void
207
+ /** A content property as text ("text", "src", "value", "focus", "placeholder", "sourceRect",
208
+ * "viewName", "viewParams", "name", …); null clears. Never "srcTintColor": a source's tint
209
+ * arrives in the paint record's tintColor. */
210
+ setPropertyString(id: nodeid, prop: string, value: string | null): void
211
+ /** A small integer content property ("playerId", "viewId"). */
212
+ setPropertyInt(id: nodeid, prop: string, value: i32): void
213
+ /** The node's listener / trait mask (TREE_FLAG_* of tree-events.h): interactive (a touch target),
214
+ * click, longPress, layout, scroll, overscroll, scrollRelease, refresh, change, focus, blur,
215
+ * submit, overlayTap, detent, keepAlive, back. */
216
+ setFlags(id: nodeid, mask: u32): void
217
+ /** Mount `child` under `parent` at `index` (the runtime already laid it out). */
218
+ insertNode(parent: nodeid, child: nodeid, index: u16): void
219
+ removeNode(parent: nodeid, child: nodeid): void
220
+ /** The node is freed: drop the host's view and its map entry. */
221
+ releaseNode(id: nodeid): void
222
+ /** Make a destination the visible one (TREE_DEST_* = creator-pkg.h VIEW_DEST_*): screen — `node` =
223
+ * the screen root (`id` 0); scene3d / scene2d — `id` = sceneId, the engine is already active, the
224
+ * host mounts / reveals its scene view; native — `id` = viewId, `viewName` + `paramsJson` describe
225
+ * the registerView factory call; video — `node` = the video node. `above`: the view goes over
226
+ * what is shown, else under it (a scene / native view / video is always the bottom: a screen
227
+ * next to one is above it). What WAS shown stays mounted until its `dropView`: the runtime moves
228
+ * both through their own `transform` / `opacity` / `dim` meanwhile (a transition is tween tracks
229
+ * on the roots — the host plays none of its own) and drops the one that left when it lands; with
230
+ * no transition the drop follows at once. */
231
+ openView(kind: u8, node: nodeid, id: i32, viewName: string, paramsJson: string, above: boolean): void
232
+ /** The destination that left the screen is unmounted (the same (kind, node, id) its openView had). */
233
+ dropView(kind: u8, node: nodeid, id: i32): void
234
+ /** Nothing is the current destination (the one that was stays mounted until its `dropView`). */
235
+ closeView(): void
236
+ /** Did the host registerView(name)? */
237
+ isViewSupported?(name: string): boolean
238
+ /** The contract version the half registered as `name` was generated from; 1 for a half written
239
+ * by hand, 0 when there is none. Backs `supports("<method>")` of a generated wrapper. */
240
+ viewVersion?(name: string): i32
241
+ /** NativeView channel: invoke `method` on the live instance `viewId`; `args` is the array of the
242
+ * call's arguments, valid for the call. Settle exactly one of the two callbacks through the
243
+ * dispatch bridge — `onComplete` with the result as ONE value, or with none. */
244
+ viewCall?(viewId: i32, method: string, args: value, onComplete: (result?: value) => void, onReject: (message: string) => void): void
245
+ /** Show a widget root: `ownerKind` = TREE_DEST_* (0xFF = a global overlay), `ownerId` = the sceneId /
246
+ * viewId of a scene / native owner (0 for a screen), `ownerNode` = the owner screen's root (a
247
+ * screen destination or a pager page) — 0 otherwise. */
248
+ widgetOpen(node: nodeid, ownerKind: u8, ownerId: i32, ownerNode: nodeid): void
249
+ widgetClose(node: nodeid): void
250
+ /** Load a font face for `fontFamily` (weight 100–900, style 0 normal / 2 italic) from `url`; settle
251
+ * one of the callbacks through the dispatch bridge. */
252
+ registerFont(url: string, fontFamily: string, weight: i32, style: i32, onComplete: () => void, onReject: (err: string) => void): void
253
+ showToast(message: string, duration: i32): void
254
+ /** Is the button node currently pressed (the UIButton.isPressed getter)? */
255
+ getButtonPressed(node: nodeid): boolean
256
+ /** The current text of an input node (malloc'd; the runtime frees it). */
257
+ getTextValue(node: nodeid): string
258
+ /** {left, top, width, height} of a laid-out node in LOGICAL px, every ancestor's scroll included,
259
+ * read live; null when not mounted / laid out yet. Optional: the JS method answers null without
260
+ * it. @out 4 */
261
+ getBoundingRect?(node: nodeid): Float32Array | null
262
+ /** A node's touchStart / longPress listener took the gesture (`ev.track`): keep feeding this
263
+ * pointer's moves (`claim` = a PanDirection bitmask, `hasMove` = it wants onMove). */
264
+ touchHandler?(pointerId: i32, hasMove: boolean, claim: u8, node: nodeid): void
265
+ /** A long press was HANDLED: swallow the click that would follow the release. */
266
+ longPressHandler?(pointerId: i32, node: nodeid): void
267
+ /** Virtualized list: apply a scroll position (physical px). `animated` false = anchoring (idempotent,
268
+ * after the content height update), true = a user scroll command. */
269
+ vlistScroll(node: nodeid, scrollY: f32, animated: boolean): void
270
+ /** UIPager: a change the runtime already made — "select" (the selected tab; `animated` = scroll
271
+ * to it) or "content" (the pages changed wholesale: remount from the pager* pulls, every tab
272
+ * showing its stack's top). A change of a tab's STACK is not a command: see pagerShowPage. */
273
+ pagerCommand?(node: nodeid, cmd: string, animated: boolean): void
274
+ /** UIPager: `page` is the top of the current tab's stack from now on, laid out at the pager's box
275
+ * — show it in the tab's cell, above the page shown there or under it, and KEEP that one shown
276
+ * (the twin of openView: the runtime moves both through their own `transform` / `opacity` /
277
+ * `dim` and drops the one that left when the transition lands — at once when none plays). */
278
+ pagerShowPage?(node: nodeid, page: nodeid, above: boolean): void
279
+ /** UIPager: `page` left the top of its tab and its transition has landed — hide it. It may stay
280
+ * a child (covered by a push, a keepAlive page); a page that is released goes through
281
+ * removeNode right after. */
282
+ pagerDropPage?(node: nodeid, page: nodeid): void
283
+ /** A pager page root (`page`) was mounted under the pager or released (an attachTo widget names the
284
+ * page node as its owner). */
285
+ pagerPageMounted?(page: nodeid, mounted: boolean): void
286
+ /** Optional: the host may PLAY a UI tween track itself — a platform animation interpolating on its
287
+ * own clock (Core Animation on iOS) instead of one style write per runtime frame. `samples` holds
288
+ * the track evaluated at even points of its length, easing included, `lanes` floats each: 1 for a
289
+ * number prop, 4 (rgba 0..1) for a color, 9 for `transform` (the 3x3 in the paint record's layout).
290
+ * The first sample shows after `delayMs`, the samples span `durationMs`, the last one holds;
291
+ * `iterations` -1 = forever, `pingPong` = every other iteration backwards; `rate` = playback speed.
292
+ * Return true to own the channel's presentation until `tweenRelease` — the runtime keeps its clock,
293
+ * its events and the resting value, and writes nothing to the prop meanwhile. false = the runtime
294
+ * writes per frame as usual (a prop the host has no layer property for, a fixed-clock run). */
295
+ tweenClaim?(node: nodeid, prop: string, lanes: i32, samples: Float32Array, durationMs: f32, delayMs: f32, iterations: i32, pingPong: boolean, rate: f32): boolean
296
+ /** The claimed channel is the runtime's again (`reason`: 0 the end was reached, 1 a control —
297
+ * paused / seeked / re-played / cancelled, 2 dropped — a newer animation took the channel or the
298
+ * node left the tree). The prop's model was just written with the value to show: apply the pending
299
+ * paint of the node, then stop the host's playback — nothing may flash. */
300
+ tweenRelease?(node: nodeid, prop: string, reason: u8): void
301
+ }
@@ -0,0 +1,49 @@
1
+ // The precise scalar types of the host contract (sdk/src/bridges/*.d.ts). Every alias is `number`
2
+ // for the SDK and TypeScript; the name says what the NATIVE side reads out of the JS value, i.e. what
3
+ // the generated bridge handlers (runtime/native/src/gen, runtime/web/src/gen) convert to. Derived
4
+ // 2026-09-23 from runtime/native's hand-written handlers (u32()/f32()/JS_ToInt32/…), so a declaration
5
+ // here is what QuickJS actually reads today — and what a JavaScriptCore backend must read tomorrow.
6
+
7
+ /** Unsigned 32-bit: entity / node / texture / clip / body handles, counts, masks, packed RGBA colors. */
8
+ export type u32 = number
9
+ /** Signed 32-bit: indices that can be -1, durations, offsets, small enums. */
10
+ export type i32 = number
11
+ /** Unsigned 8-bit: small enums and flags read through u8(). */
12
+ export type u8 = number
13
+ /** Single precision: positions, angles, scales, weights — the engines' own float ABI. */
14
+ export type f32 = number
15
+ /** Double precision: read through JS_ToFloat64 (time stamps, intensities, a few legacy params). */
16
+ export type f64 = number
17
+ /** A host buffer id (a `systemId` from fetch / fetchLocal / a canvas bake): the native side turns it
18
+ * into a malloc'd byte copy before the call, so the engine sees bytes, not the id. */
19
+ export type bytes = number
20
+ /** Unsigned 16-bit: a child index in the UI tree (host table slots). */
21
+ export type u16 = number
22
+ /** Signed 64-bit: a yoga node id, a retained JS value handed to the host as an opaque long. */
23
+ export type i64 = number
24
+
25
+ // The host-table (`export interface Host<Name>`) types the runtime hands a host and JS never sees —
26
+ // scripts/lib/gen-host.ts maps them to C, Kotlin and Swift.
27
+ /** An opaque HOST pointer (a renderer's node object, a GL context): `void*` in C, a Long in Kotlin,
28
+ * a raw pointer in Swift. The runtime stores and passes it back; it never dereferences it. */
29
+ export type ptr = number
30
+ /** A UI node id — the runtime's node pointer (engines/ui): `const void*` in C, a Long in Kotlin, an
31
+ * Int in Swift, a number in JS. The one identity of a node across the SDK, the runtime and the host. */
32
+ export type nodeid = number
33
+ /** A numeric HOST handle (a GL context): `void*` in C, a Long in Kotlin, a raw pointer in Swift —
34
+ * `ptr` is a host OBJECT (a node), this is a number a host packs itself. */
35
+ export type handle = number
36
+ /** A retained JS value the runtime hands the host as an opaque handle (a node's JS element for the
37
+ * jsCallListeners* entry points): `js_ptr` in C, a Long in Kotlin. Released by the runtime. */
38
+ export type jsptr = number
39
+ /** DATA on its way to a host — what a plugin channel carries (a call's arguments, its result, an
40
+ * event's payload): null, a boolean, a number, a string, a Uint8Array, arrays and objects of them.
41
+ * The runtime reads it ONCE into a LeValue (runtime/native/src/values/js.h says what cannot
42
+ * cross) and the host gets its platform's own values: `const LeValue*` in C; in Kotlin and Swift the
43
+ * objects the platform's JSON reader makes (org.json / Foundation), plus bytes as ByteArray / Data.
44
+ * A TS host — JavaScript like the app — gets the value itself. */
45
+ export type value = unknown
46
+ /** An OUT parameter: the runtime passes a buffer the host FILLS (`float*` / `int32_t*`); how many
47
+ * values, the slot's doc says. */
48
+ export type f32out = Float32Array
49
+ export type i32out = Int32Array