lecodes-cli 0.19.0 → 0.19.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.
Files changed (254) hide show
  1. package/dist/index.js +730 -235
  2. package/package.json +14 -13
  3. package/runtime/scene-harness.json +1 -1
  4. package/runtime/sdk-types.json +1 -1
  5. package/src/api.ts +302 -0
  6. package/src/browserAuth.ts +87 -0
  7. package/src/cmgenTool.ts +104 -0
  8. package/src/commands/app.ts +891 -0
  9. package/src/commands/appAndroid.ts +603 -0
  10. package/src/commands/appDesktop.ts +326 -0
  11. package/src/commands/appDesktopMac.ts +470 -0
  12. package/src/commands/appIcon.ts +187 -0
  13. package/src/commands/appShared.ts +448 -0
  14. package/src/commands/appTemplates.ts +883 -0
  15. package/src/commands/appTemplatesAndroid.ts +599 -0
  16. package/src/commands/appTemplatesGradlew.ts +9 -0
  17. package/src/commands/assets.ts +28 -0
  18. package/src/commands/clone.ts +60 -0
  19. package/src/commands/compile.ts +253 -0
  20. package/src/commands/create.ts +59 -0
  21. package/src/commands/design.ts +863 -0
  22. package/src/commands/designTemplates.ts +11 -0
  23. package/src/commands/desktop.ts +122 -0
  24. package/src/commands/dev.ts +214 -0
  25. package/src/commands/diff.ts +59 -0
  26. package/src/commands/init.ts +191 -0
  27. package/src/commands/install.ts +198 -0
  28. package/src/commands/lightmap.ts +290 -0
  29. package/src/commands/link.ts +147 -0
  30. package/src/commands/login.ts +24 -0
  31. package/src/commands/navmesh.ts +225 -0
  32. package/src/commands/pn.ts +305 -0
  33. package/src/commands/projectTemplates.ts +129 -0
  34. package/src/commands/pull.ts +109 -0
  35. package/src/commands/push.ts +173 -0
  36. package/src/commands/render.ts +414 -0
  37. package/src/commands/scene.ts +148 -0
  38. package/src/commands/shaders.ts +157 -0
  39. package/src/commands/status.ts +29 -0
  40. package/src/commands/test.ts +370 -0
  41. package/src/commands/thumbs.ts +178 -0
  42. package/src/commands/types.ts +87 -0
  43. package/src/commands/update.ts +190 -0
  44. package/src/compile/assetIcons.ts +214 -0
  45. package/src/compile/collect.ts +46 -0
  46. package/src/compile/collectLocal.ts +37 -0
  47. package/src/compile/designCompile.ts +104 -0
  48. package/src/compile/fonts.ts +156 -0
  49. package/src/compile/headlessBundle.ts +129 -0
  50. package/src/compile/nativeStack.ts +21 -0
  51. package/src/compile/projectCompile.ts +109 -0
  52. package/src/compile/sceneCompile.ts +113 -0
  53. package/src/compile/screenEntry.ts +127 -0
  54. package/src/compile/shaders.ts +245 -0
  55. package/src/config.ts +42 -0
  56. package/src/designMeta.ts +35 -0
  57. package/src/desktopRenderer.ts +532 -0
  58. package/src/desktopScript.ts +276 -0
  59. package/src/dev/clientTemplates.ts +160 -0
  60. package/src/dev/devServer.ts +292 -0
  61. package/src/dev/wsServer.ts +144 -0
  62. package/src/distRoot.ts +20 -0
  63. package/src/ignore.ts +163 -0
  64. package/src/index.ts +491 -0
  65. package/src/lecodes-3d-editor.d.ts +41 -0
  66. package/src/lecodes-assets.d.ts +7 -0
  67. package/src/lecodes-design.d.ts +191 -0
  68. package/src/lecodes-renderer.d.ts +131 -0
  69. package/src/localFiles.ts +144 -0
  70. package/src/manifest.ts +46 -0
  71. package/src/matcTool.ts +137 -0
  72. package/src/peers.ts +40 -0
  73. package/src/project.ts +61 -0
  74. package/src/projectEnv.ts +94 -0
  75. package/src/qrcode-terminal.d.ts +9 -0
  76. package/src/releases.ts +125 -0
  77. package/src/serverDiff.ts +78 -0
  78. package/src/textDiff.ts +103 -0
  79. package/src/types.ts +0 -0
  80. package/src/util.ts +146 -0
  81. package/runtime/sdk/animate/animate.ts +0 -238
  82. package/runtime/sdk/animate/bezier.ts +0 -138
  83. package/runtime/sdk/animate/easings.ts +0 -126
  84. package/runtime/sdk/canvas/Canvas.ts +0 -305
  85. package/runtime/sdk/compile/aspectMacro.ts +0 -86
  86. package/runtime/sdk/compile/assetIconMacro.ts +0 -384
  87. package/runtime/sdk/compile/assetMacro.ts +0 -146
  88. package/runtime/sdk/compile/assetName.ts +0 -50
  89. package/runtime/sdk/compile/bundler.ts +0 -287
  90. package/runtime/sdk/compile/compileProject.ts +0 -129
  91. package/runtime/sdk/compile/detectEntry.ts +0 -128
  92. package/runtime/sdk/compile/fontMacro.ts +0 -459
  93. package/runtime/sdk/compile/fontRegistry.ts +0 -78
  94. package/runtime/sdk/compile/header.ts +0 -67
  95. package/runtime/sdk/compile/index.ts +0 -100
  96. package/runtime/sdk/compile/libraryImports.ts +0 -52
  97. package/runtime/sdk/compile/liteMaterial.ts +0 -247
  98. package/runtime/sdk/compile/sceneEditor.ts +0 -88
  99. package/runtime/sdk/compile/serverSplit.ts +0 -233
  100. package/runtime/sdk/compile/serverTypes.ts +0 -227
  101. package/runtime/sdk/compile/sfnt.ts +0 -98
  102. package/runtime/sdk/compile/shaderSchema.ts +0 -202
  103. package/runtime/sdk/compile/shaderTargets.ts +0 -81
  104. package/runtime/sdk/compile/sourcemap.ts +0 -25
  105. package/runtime/sdk/core/Aspect.ts +0 -568
  106. package/runtime/sdk/core/InspectorUI.ts +0 -212
  107. package/runtime/sdk/core/StateMachine.ts +0 -308
  108. package/runtime/sdk/core/color.ts +0 -66
  109. package/runtime/sdk/core/compWrite.ts +0 -42
  110. package/runtime/sdk/core/events.ts +0 -38
  111. package/runtime/sdk/core/fields.ts +0 -120
  112. package/runtime/sdk/core/registry.ts +0 -23
  113. package/runtime/sdk/core/signals.ts +0 -277
  114. package/runtime/sdk/core/time.ts +0 -84
  115. package/runtime/sdk/g2/Camera2D.ts +0 -40
  116. package/runtime/sdk/g2/CharacterController2D.ts +0 -276
  117. package/runtime/sdk/g2/Node2D.ts +0 -267
  118. package/runtime/sdk/g2/OneWay2D.ts +0 -66
  119. package/runtime/sdk/g2/Physics2D.ts +0 -346
  120. package/runtime/sdk/g2/Scene2D.ts +0 -209
  121. package/runtime/sdk/g2/Shape2D.ts +0 -259
  122. package/runtime/sdk/g2/Sprite.ts +0 -89
  123. package/runtime/sdk/g2/SpriteAnimation.ts +0 -171
  124. package/runtime/sdk/g2/SpriteSheet.ts +0 -166
  125. package/runtime/sdk/g2/Texture2D.ts +0 -47
  126. package/runtime/sdk/g2/Tilemap.ts +0 -41
  127. package/runtime/sdk/g2/Tileset.ts +0 -71
  128. package/runtime/sdk/g2/Trigger2D.ts +0 -77
  129. package/runtime/sdk/g2/autotile.ts +0 -433
  130. package/runtime/sdk/g2/cells.ts +0 -91
  131. package/runtime/sdk/g2/defineScene2d.ts +0 -381
  132. package/runtime/sdk/g2/groups2d.ts +0 -106
  133. package/runtime/sdk/g2/loop.ts +0 -50
  134. package/runtime/sdk/g2/scenarios2d.ts +0 -69
  135. package/runtime/sdk/g2/touch.ts +0 -83
  136. package/runtime/sdk/gl/Camera.ts +0 -160
  137. package/runtime/sdk/gl/CameraPlace.ts +0 -52
  138. package/runtime/sdk/gl/CharacterController.ts +0 -238
  139. package/runtime/sdk/gl/Gearbox.ts +0 -212
  140. package/runtime/sdk/gl/Geometry.ts +0 -279
  141. package/runtime/sdk/gl/IK.ts +0 -193
  142. package/runtime/sdk/gl/InstancedMesh.ts +0 -132
  143. package/runtime/sdk/gl/Light.ts +0 -107
  144. package/runtime/sdk/gl/Lightmap.ts +0 -256
  145. package/runtime/sdk/gl/Material.ts +0 -260
  146. package/runtime/sdk/gl/Mesh.ts +0 -83
  147. package/runtime/sdk/gl/Model.ts +0 -124
  148. package/runtime/sdk/gl/NavAgent.ts +0 -337
  149. package/runtime/sdk/gl/NavMesh.ts +0 -397
  150. package/runtime/sdk/gl/Node.ts +0 -350
  151. package/runtime/sdk/gl/Noise.ts +0 -30
  152. package/runtime/sdk/gl/Particles.ts +0 -676
  153. package/runtime/sdk/gl/Physics.ts +0 -222
  154. package/runtime/sdk/gl/Plane.ts +0 -53
  155. package/runtime/sdk/gl/Ragdoll.ts +0 -270
  156. package/runtime/sdk/gl/Ray.ts +0 -16
  157. package/runtime/sdk/gl/Scene.ts +0 -486
  158. package/runtime/sdk/gl/Shape.ts +0 -409
  159. package/runtime/sdk/gl/Terrain.ts +0 -1092
  160. package/runtime/sdk/gl/Texture.ts +0 -63
  161. package/runtime/sdk/gl/Trigger.ts +0 -45
  162. package/runtime/sdk/gl/Vehicle.ts +0 -473
  163. package/runtime/sdk/gl/Wheel.ts +0 -240
  164. package/runtime/sdk/gl/animation/AnimationClip.ts +0 -204
  165. package/runtime/sdk/gl/animation/Animator.ts +0 -120
  166. package/runtime/sdk/gl/animation/Layer.ts +0 -31
  167. package/runtime/sdk/gl/animation/Loop.ts +0 -30
  168. package/runtime/sdk/gl/animation/Playback.ts +0 -44
  169. package/runtime/sdk/gl/animation/core.ts +0 -336
  170. package/runtime/sdk/gl/controls.ts +0 -95
  171. package/runtime/sdk/gl/physicsEvents.ts +0 -20
  172. package/runtime/sdk/gl/scenarios.ts +0 -291
  173. package/runtime/sdk/gl/state.ts +0 -6
  174. package/runtime/sdk/gl/terrainMesh.ts +0 -219
  175. package/runtime/sdk/gl/touch.ts +0 -68
  176. package/runtime/sdk/inject.ts +0 -197
  177. package/runtime/sdk/math/Mathf.ts +0 -118
  178. package/runtime/sdk/math/mat4.ts +0 -278
  179. package/runtime/sdk/math/quat.ts +0 -232
  180. package/runtime/sdk/math/vec.ts +0 -255
  181. package/runtime/sdk/net/codec.ts +0 -119
  182. package/runtime/sdk/net/core.ts +0 -384
  183. package/runtime/sdk/net/index.ts +0 -181
  184. package/runtime/sdk/net/replication.ts +0 -622
  185. package/runtime/sdk/plugins/camera.ts +0 -81
  186. package/runtime/sdk/plugins/geolocation.ts +0 -123
  187. package/runtime/sdk/plugins/oauth.ts +0 -61
  188. package/runtime/sdk/plugins/permission.ts +0 -7
  189. package/runtime/sdk/plugins/push.ts +0 -132
  190. package/runtime/sdk/plugins/qr.ts +0 -73
  191. package/runtime/sdk/plugins/service.ts +0 -47
  192. package/runtime/sdk/runtime/app.ts +0 -101
  193. package/runtime/sdk/runtime/appEvents.ts +0 -54
  194. package/runtime/sdk/runtime/channel.ts +0 -61
  195. package/runtime/sdk/runtime/clipboard.ts +0 -20
  196. package/runtime/sdk/runtime/datetime.ts +0 -329
  197. package/runtime/sdk/runtime/device.ts +0 -293
  198. package/runtime/sdk/runtime/fetch.ts +0 -77
  199. package/runtime/sdk/runtime/files.ts +0 -23
  200. package/runtime/sdk/runtime/input.ts +0 -175
  201. package/runtime/sdk/runtime/media.ts +0 -111
  202. package/runtime/sdk/runtime/misc.ts +0 -16
  203. package/runtime/sdk/runtime/net.ts +0 -36
  204. package/runtime/sdk/runtime/rpc.ts +0 -218
  205. package/runtime/sdk/runtime/service.ts +0 -83
  206. package/runtime/sdk/runtime/share.ts +0 -9
  207. package/runtime/sdk/runtime/storage.ts +0 -13
  208. package/runtime/sdk/runtime/touch.ts +0 -76
  209. package/runtime/sdk/scene/defineScene.ts +0 -1353
  210. package/runtime/sdk/scene/editorPlugins.ts +0 -110
  211. package/runtime/sdk/scene/gizmos.ts +0 -148
  212. package/runtime/sdk/scene/grammar.ts +0 -120
  213. package/runtime/sdk/scene/material.ts +0 -188
  214. package/runtime/sdk/server/auth/appConfig.ts +0 -12
  215. package/runtime/sdk/server/auth/global.ts +0 -80
  216. package/runtime/sdk/server/auth/host.ts +0 -318
  217. package/runtime/sdk/server/auth/models.ts +0 -83
  218. package/runtime/sdk/server/auth/types.ts +0 -50
  219. package/runtime/sdk/server/channel.ts +0 -56
  220. package/runtime/sdk/server/context.ts +0 -36
  221. package/runtime/sdk/server/db/defineDb.ts +0 -237
  222. package/runtime/sdk/server/db/fields.ts +0 -132
  223. package/runtime/sdk/server/db/httpTransport.ts +0 -93
  224. package/runtime/sdk/server/db/index.ts +0 -7
  225. package/runtime/sdk/server/db/marci/query.ts +0 -412
  226. package/runtime/sdk/server/db/types.ts +0 -202
  227. package/runtime/sdk/server/errors.ts +0 -12
  228. package/runtime/sdk/server/host.ts +0 -74
  229. package/runtime/sdk/server/inject.ts +0 -13
  230. package/runtime/sdk/server/runtime.ts +0 -133
  231. package/runtime/sdk/server/validate.ts +0 -87
  232. package/runtime/sdk/ui/NativeView.ts +0 -142
  233. package/runtime/sdk/ui/UI.ts +0 -39
  234. package/runtime/sdk/ui/UIBottomSheet.ts +0 -139
  235. package/runtime/sdk/ui/UIButton.ts +0 -101
  236. package/runtime/sdk/ui/UIContainer.ts +0 -60
  237. package/runtime/sdk/ui/UIImage.ts +0 -83
  238. package/runtime/sdk/ui/UIInput.ts +0 -185
  239. package/runtime/sdk/ui/UIModal.ts +0 -139
  240. package/runtime/sdk/ui/UINode.ts +0 -830
  241. package/runtime/sdk/ui/UIPager.ts +0 -362
  242. package/runtime/sdk/ui/UIPopover.ts +0 -100
  243. package/runtime/sdk/ui/UIScreen.ts +0 -123
  244. package/runtime/sdk/ui/UIScrollable.ts +0 -87
  245. package/runtime/sdk/ui/UISpacer.ts +0 -14
  246. package/runtime/sdk/ui/UITabs.ts +0 -236
  247. package/runtime/sdk/ui/UIText.ts +0 -51
  248. package/runtime/sdk/ui/UIVideo.ts +0 -88
  249. package/runtime/sdk/ui/UIVirtualizedList.ts +0 -241
  250. package/runtime/sdk/ui/UIWidget.ts +0 -127
  251. package/runtime/sdk/ui/fonts.ts +0 -13
  252. package/runtime/sdk/ui/presentable.ts +0 -117
  253. package/runtime/sdk/ui/router.ts +0 -132
  254. package/runtime/sdk/ui/theme.ts +0 -84
@@ -1,127 +0,0 @@
1
- import { TouchStartEvent } from "../runtime/touch"
2
- import { _descOf, _navSupported, Presentable } from "./presentable"
3
- import { ContainerElement, buildUI, type BaseStyle, type Color, type ContainerStyle, type DrawableStyle, type PaddingStyle, type PositionStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from "./UINode"
4
-
5
-
6
- export type UIWidgetStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle & PositionStyle & {
7
- /** A layer behind the widget that intercepts clicks — `"transparent"` still intercepts, `null`
8
- * removes the layer. A tap on it fires `onOverlayTap`. */
9
- overlayColor?: Color | null
10
- }
11
-
12
-
13
- /** A floating overlay — absolutely positioned in device coordinates, mounted above the page as
14
- * its own layout root (never a child of what's underneath). The base of dialogs, toasts,
15
- * mini-players and scene HUDs; `UIModal`/`UIPopover`/`UIBottomSheet` build on it. */
16
- export interface UIWidget extends UIContainerBase<UIWidgetStyle, DrawableStyle & BaseStyle & { overlayColor?: Color | null }> {
17
- readonly type: "widget",
18
-
19
- /**
20
- * Attach this widget to a destination (a `Scene`, a `UIScreen`, …): the widget lives on that
21
- * page's layer — it shows/hides with the page and rides its transition, and a screen pushed
22
- * on top covers it (a scene HUD behaves like part of the scene). Sticky until `attachTo(null)`
23
- * (= back to a global overlay). Set it while the widget is hidden. The widget is always its own
24
- * overlay root mounted into the owner's page view — it never becomes a child of the owner, so it
25
- * stays topmost and its updates never trigger the owner's relayout. Works with a `UIScreen` that
26
- * is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe. (Web shows
27
- * and hides it with the owner but does not yet ride the transition.)
28
- */
29
- attachTo(owner: Presentable | null): this,
30
-
31
- /** Show the widget. By default it is a global overlay above every destination — it stays
32
- * visible across navigation until `hide()` (dialogs, mini-player, global loader). If the
33
- * widget was attached via `attachTo(owner)`, it mounts on that page's layer instead and is
34
- * only visible while the owner is presented. */
35
- show(): void,
36
- /** Unmount the widget. */
37
- hide(): void,
38
-
39
- /** Mounted right now (`show()` ran, `hide()` hasn't). */
40
- readonly isShow: boolean,
41
-
42
- /** Touch began on the widget; `ev.track(...)` takes over the rest of the gesture. */
43
- onTouchStart(callback: (ev: TouchStartEvent<UIWidget>) => void): this,
44
- /** Tap on the overlay layer (requires an `overlayColor`). */
45
- onOverlayTap(callback: () => void): this,
46
- /** Hardware/system back while the widget is shown. */
47
- onBackPressed(callback: () => void): this
48
- }
49
-
50
-
51
- export class WidgetElement extends ContainerElement<"widget"> {
52
- scrollable = false as const
53
- _owner?: Presentable
54
- constructor(type: "widget", style: UIWidgetStyle, children: UINodeChild[] | ChildrenFn) {
55
- // Widgets are absolutely positioned in device coordinates — in the constructor (not the
56
- // factory) so subclasses like ModalElement inherit it.
57
- super(type, { position: "absolute", ...style }, children)
58
- }
59
- attachTo(owner: Presentable | null): this {
60
- this._owner = owner ?? undefined
61
- return this
62
- }
63
- show(): void {
64
- // A widget is always its OWN overlay root (a separate Yoga tree mounted above the owner's
65
- // content) — never a child of the owner, so it stays topmost, its updates never relayout the
66
- // owner, and it doesn't pollute the owner's children. `attachTo(owner)` just tells the host
67
- // which page view to mount that root into; ownerless widgets are global overlays.
68
- if (this._owner && _navSupported()) {
69
- _creatorUI.showWidget(this, _descOf(this._owner))
70
- } else {
71
- // Unattached (or legacy host): global overlay above navigation.
72
- _creatorUI.showWidget(this)
73
- }
74
- }
75
- hide(): void {
76
- _creatorUI.hideWidget(this)
77
- }
78
- get isShow(): boolean {
79
- return this._id !== 0
80
- }
81
-
82
- _interactive = false
83
- readonly touchStartListeners: any[] = []
84
- onTouchStart (callback: any): this {
85
- this._interactive = true
86
- this.touchStartListeners.push(callback)
87
- return this
88
- }
89
- _emitTouchStart(pointerId: number, clientX: number, clientY: number): any {
90
- const touchEvent = new TouchStartEvent(clientX, clientY, pointerId)
91
- touchEvent.target = this
92
- for (let callback of this.touchStartListeners) {
93
- callback(touchEvent)
94
- if ((touchEvent as any)._trackHandler) {
95
- return (touchEvent as any)._trackHandler
96
- }
97
- }
98
- return null
99
- }
100
- readonly otl: (() => void)[] = []
101
- onOverlayTap(callback: () => void): this {
102
- this.otl.push(callback)
103
- return this
104
- }
105
-
106
- _backButtonCallback?: () => void
107
- onBackPressed(callback: any): this {
108
- this._backButtonCallback = callback
109
- return this
110
- }
111
- }
112
-
113
-
114
- const makeWidget = (style: any, children: any) => new WidgetElement("widget", style, children)
115
-
116
- /** @internal Compiler fast path (chisel `flatten_ui` raw lowering) — see UIContainer. */
117
- export const __UIWidget = (children: UINodeChild[] | ChildrenFn): UIWidget => makeWidget({}, children)
118
-
119
- /** Create a widget (same argument forms as `UIColumn`). Position it with absolute-style props
120
- * (`top`/`left`/`bottom`/`right`), then `show()`/`hide()`. */
121
- export function UIWidget(...children: UIChildArg[]): UIWidget;
122
- export function UIWidget(children: UINodeChild[] | ChildrenFn): UIWidget;
123
- /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */
124
- export function UIWidget(style: UIWidgetStyle, children?: UINodeChild[] | ChildrenFn): UIWidget;
125
- export function UIWidget(...args: any[]): UIWidget {
126
- return buildUI(args, null, makeWidget)
127
- }
@@ -1,13 +0,0 @@
1
- type FontOptions = {
2
- weight?: number,
3
- style?: "normal" | "italic"
4
- }
5
-
6
- /** Register a font face from a URL at runtime under `fontFamily`; resolves once it's ready to
7
- * use in styles. For registry/project fonts prefer the compile-time `font()` macro — this is the
8
- * dynamic escape hatch. */
9
- export async function registerFont (fontFamily: string, url: string, options: FontOptions = {}): Promise<void> {
10
- return new Promise<void>((res, rej) => {
11
- _creatorUI.registerFont(fontFamily, url, options, res, rej)
12
- })
13
- }
@@ -1,117 +0,0 @@
1
- // The Presentable contract — the one navigation model (docs/navigation-presentable-plan.md).
2
- // Anything that can occupy the app's main slot implements it: UIScreen, Scene (+ARScene),
3
- // Scene2D, NativeView, UIVideo. Exactly one Presentable is visible at a time — a screen no
4
- // longer overlays a scene, it replaces it (with a transition); UI over a scene goes through
5
- // `UIWidget.attachTo(scene)`.
6
- //
7
- // This module is dependency-free on purpose: gl/ and g2/ import it, so it must not pull any UI
8
- // element code into engine-only bundles.
9
-
10
- /** Built-in transition catalog. `push`/`pop` are the stacked-navigation pair (slide + parallax +
11
- * dim + edge shadow); the rest are simple two-view moves. */
12
- export type TransitionName =
13
- | "push" | "pop"
14
- | "slide-from-left" | "slide-from-right" | "slide-from-top" | "slide-from-bottom"
15
- | "zoom" | "zoom-in" | "zoom-out" | "fade" | "none"
16
-
17
- /** Start/end pose of one side of a custom transition. `x`/`y` are logical px, or a percentage of
18
- * the destination's size (e.g. `"100%"` = one full width to the right). */
19
- export type TransitionTransform = {
20
- x?: number | `${number}%`
21
- y?: number | `${number}%`
22
- scale?: number
23
- opacity?: number
24
- }
25
-
26
- /**
27
- * A custom transition: declarative poses for the incoming/outgoing destination, played natively.
28
- * Serializes onto each platform's existing transition machinery — there is no per-frame JS.
29
- * Fields omitted keep the identity pose. Interactive back-swipe stays system-native (push/pop
30
- * only); a spec applies to non-interactive transitions.
31
- */
32
- export interface TransitionSpec {
33
- /** Duration in ms (default 300). */
34
- duration?: number
35
- /** cubic-bezier control points (default ease-out). */
36
- easing?: [number, number, number, number]
37
- /** The entering destination animates FROM this pose to identity. */
38
- incoming?: { from?: TransitionTransform }
39
- /** The leaving destination animates from identity TO this pose. */
40
- outgoing?: { to?: TransitionTransform }
41
- /** Scrim alpha (0..1) painted over whichever destination is underneath. */
42
- dim?: number
43
- /** Which side stacks on top during the animation (default "incoming"). On Android, transitions
44
- * involving a scene always animate the screen side on top — the scene view itself never moves. */
45
- onTop?: "incoming" | "outgoing"
46
- }
47
-
48
- export type Transition = TransitionName | TransitionSpec
49
-
50
- export type PresentOptions = {
51
- /** Transition to play while this destination replaces the current one (default "none" for a
52
- * direct open(); the Router applies its own defaults — push/pop, and the theme's
53
- * `replaceTransition` for replace). */
54
- transition?: Transition
55
- }
56
-
57
- /**
58
- * Anything that can be shown as the app's current destination: a `UIScreen`, a `Scene` /
59
- * `ARScene`, a `Scene2D`, a `NativeView`, or a `UIVideo`. One Presentable is visible at a time;
60
- * open it directly (`p.open()` — replaces the current destination, suspending an active Router
61
- * until `Router.restore()`) or navigate with `Router.push/replace/pop`.
62
- *
63
- * `onOpen`/`onClose` are the presentation lifecycle (fired when the destination becomes / stops
64
- * being the visible one — including router pushes covering it and pops revealing it).
65
- */
66
- export interface Presentable {
67
- // Return type covers the implementers: UIScreen → void, Scene2D → this, ARScene → Promise.
68
- open(options?: PresentOptions): void | this | Promise<void>
69
- close(): void
70
- onOpen(callback: () => void): this
71
- onClose(callback: () => void): this
72
- onBackPressed(callback: () => void): this
73
- /** @internal Async work that must finish BEFORE this destination replaces the current one
74
- * (camera permission, warm render, session launch — ARScene). The previous destination —
75
- * typically a loading screen — stays visible while it runs; `open()` and `Router.push/replace`
76
- * await it and skip the swap entirely if it rejects (permission denied, or superseded by
77
- * another navigation that happened while preparing). */
78
- _prepare?(): Promise<void>
79
- }
80
-
81
- // The destination visible right now. Set optimistically by every successful open()/router
82
- // navigation, cleared by close(), and corrected by router onChange (hosts hand the wire desc
83
- // back on every stack change, including back gestures — `_p` resolves it to the SDK instance).
84
- let current: Presentable | null = null
85
- /** @internal Call whenever the visible destination changes. */
86
- export const _setCurrent = (p: Presentable | null): void => { current = p }
87
-
88
- /** Runtime companion of the `Presentable` interface (declaration merging): the navigation
89
- * state that isn't tied to the Router. */
90
- export const Presentable = /*#__PURE__*/ Object.freeze({
91
- /** The destination visible right now (a `UIScreen`, `Scene`, `Scene2D`, `NativeView` or
92
- * `UIVideo`), or `null` before the first open. Distinct from `Router.current` — that is the
93
- * top of the router stack, which stays meaningful while the router is suspended by a direct
94
- * `open()`; this is what is actually on screen. `UIWidget.show()` attaches to it. */
95
- get current(): Presentable | null { return current },
96
- })
97
-
98
- // Monotonic navigation epoch: every destination change (open/close/router nav) bumps it. Async
99
- // preparers capture the epoch before their awaits and reject as "superseded" if it moved — so a
100
- // slow AR prepare can't steal the screen from a navigation the user made in the meantime.
101
- let navEpoch = 0
102
- /** @internal */
103
- export const _navEpoch = (): number => navEpoch
104
- /** @internal Call on every action that changes the visible destination. */
105
- export const _bumpNavEpoch = (): void => { navEpoch++ }
106
-
107
- /** @internal Does this host implement the Presentable navigation surface? The SDK falls back to
108
- * the legacy openScreen/openScene bridges when it doesn't (screens keep working; scene/native
109
- * destinations in the Router then throw). */
110
- export const _navSupported = (): boolean =>
111
- typeof _creatorUI !== "undefined" && typeof _creatorUI.openView === "function"
112
-
113
- /** @internal The wire descriptor for a Presentable. Screens (and anything without `_viewDesc`)
114
- * travel as themselves; scenes/native views/video provide a stable descriptor object carrying
115
- * `_p` (the SDK instance) so hosts can hand it back through router onChange / lifecycle. */
116
- export const _descOf = (p: Presentable): object =>
117
- typeof (p as any)._viewDesc === "function" ? (p as any)._viewDesc() : (p as object)
@@ -1,132 +0,0 @@
1
- import { _bumpNavEpoch, _descOf, _navSupported, _setCurrent, Presentable, type Transition } from "./presentable"
2
- import { _navDefaults } from "./theme"
3
-
4
- type RouterOptions = {
5
- showDefaultBackButton?: boolean
6
- }
7
-
8
- type NavigateOptions = {
9
- /** Transition to play. Defaults: `"push"` for push, `"pop"` for pop; replace follows the
10
- * theme's `replaceTransition` (`"none"` out of the box). */
11
- transition?: Transition
12
- }
13
-
14
- /** Stack navigation over `Presentable` destinations. `init` once with the home page, then
15
- * `push`/`replace`/`pop`; the back gesture/button pops natively. A direct `page.open()` suspends
16
- * the router until `restore()`. */
17
- type Router = {
18
- /** The top of the router stack (not necessarily what's on screen — see `Presentable.current`). */
19
- get current(): Presentable
20
- /** Mount the router with `homePage` as the stack root — the app's navigation entry point. */
21
- init(homePage: Presentable, opts?: RouterOptions): void
22
- /** Push a destination onto the stack — a `UIScreen`, a `Scene`, a `Scene2D`, a `NativeView`,
23
- * or a `UIVideo`. The back gesture/button pops it. Destinations with async preparation
24
- * (`ARScene`: camera permission + warm render) return a Promise — the current page stays
25
- * visible until they're ready, and a rejection (permission denied / superseded) leaves the
26
- * stack untouched. */
27
- push(page: Presentable, opts?: NavigateOptions): void | Promise<void>
28
- /** Swap the top of the stack for `page` — no back entry to the replaced one. */
29
- replace(page: Presentable, opts?: NavigateOptions): void | Promise<void>
30
- /** Pop the top destination (the programmatic twin of the back gesture); `to` unwinds to a
31
- * stack index in one step. */
32
- pop(to?: number, opts?: NavigateOptions): void
33
- /** Blank the router's page, keeping the stack — `restore()` brings it back. A destination
34
- * opened directly stays visible. */
35
- hide(): void
36
- /** Re-present the stack top after `hide()` or a direct `open()` suspended the router. */
37
- restore(): void
38
-
39
- /** `"change"` fires on every stack change — pushes, pops, and native back gestures — with the
40
- * new top destination. */
41
- addEventListener(channel: "change", callback: (page: Presentable) => void): void
42
- removeEventListener(channel: "change", callback: (page: Presentable) => void): void
43
- }
44
-
45
- let currentPage: Presentable | null = null
46
- let onChange = (page: any) => {
47
- // Hosts hand back the wire object: the screen itself, or a descriptor carrying `_p`.
48
- currentPage = page && page._p ? page._p : page
49
- // The router's page is the visible destination (hosts fire this on every stack change,
50
- // including back gestures) — keep Presentable.current in sync.
51
- _setCurrent(currentPage)
52
- for (let callback of (Router as any)._changeListeners) {
53
- callback(currentPage)
54
- }
55
- }
56
-
57
- // Non-screen destinations have no legacy bridge to fall back to — surface that clearly instead
58
- // of letting an old host try to build a screen out of a scene descriptor.
59
- const wireDesc = (page: Presentable): object => {
60
- const desc = _descOf(page)
61
- if (desc !== page && !_navSupported()) {
62
- throw new Error("This host does not support scene/native-view navigation (requires _creatorUI.openView)")
63
- }
64
- return desc
65
- }
66
-
67
- export const Router: Router = /*#__PURE__*/ Object.freeze({
68
-
69
- init(homePage: Presentable, opts: RouterOptions = {}): void {
70
- _bumpNavEpoch()
71
- _creatorUI.routerOpen(wireDesc(homePage), onChange, opts.showDefaultBackButton ?? false)
72
- currentPage = homePage
73
- _setCurrent(homePage)
74
- },
75
- push(page: Presentable, opts?: NavigateOptions): void | Promise<void> {
76
- const desc = wireDesc(page) // throws early on unsupported hosts, before any async work
77
- const go = () => {
78
- _bumpNavEpoch()
79
- // Legacy hosts ignore the extra transition argument.
80
- _creatorUI.routerPush(desc, opts?.transition ?? "push")
81
- _setCurrent(page) // optimistic — host onChange confirms (async on native hosts)
82
- }
83
- // A preparing destination (ARScene) keeps the current page visible until it's ready; a
84
- // rejection (camera denied / superseded) propagates to the caller and nothing is pushed.
85
- const prep = page._prepare?.()
86
- return prep ? prep.then(go) : go()
87
- },
88
- replace(page: Presentable, opts?: NavigateOptions): void | Promise<void> {
89
- const desc = wireDesc(page)
90
- const go = () => {
91
- _bumpNavEpoch()
92
- _creatorUI.routerReplace(desc, opts?.transition ?? _navDefaults.replace)
93
- _setCurrent(page) // optimistic — host onChange confirms (async on native hosts)
94
- }
95
- const prep = page._prepare?.()
96
- return prep ? prep.then(go) : go()
97
- },
98
- pop(to?: number, opts?: NavigateOptions): void {
99
- _bumpNavEpoch()
100
- _creatorUI.routerPop(to ?? -1, opts?.transition ?? "pop")
101
- },
102
- hide() {
103
- _bumpNavEpoch()
104
- _creatorUI.routerHide()
105
- // hide() only blanks the router's own page — a directly-opened destination stays visible.
106
- if (Presentable.current === currentPage) _setCurrent(null)
107
- },
108
- restore() {
109
- _bumpNavEpoch()
110
- _creatorUI.routerRestore()
111
- _setCurrent(currentPage) // the stack top is visible again
112
- },
113
-
114
- get current(): Presentable {
115
- return currentPage!
116
- },
117
-
118
- _changeListeners: [] as any[],
119
- addEventListener(channel: "change", callback: (page: Presentable) => void): void {
120
- if (channel === "change") {
121
- this._changeListeners.push(callback)
122
- }
123
- },
124
- removeEventListener(channel: "change", callback: (page: Presentable) => void): void {
125
- if (channel === "change") {
126
- let index = this._changeListeners.indexOf(callback)
127
- if (index >= 0) {
128
- this._changeListeners.splice(index, 1)
129
- }
130
- }
131
- }
132
- })
@@ -1,84 +0,0 @@
1
- // theme() — app theme variables (docs/ui-theme-plan.md). One global var table lives in the UI
2
- // core; `var(--key)` references resolve at style-apply time, so re-calling theme() re-styles the
3
- // LIVE UI. Bare style tokens (`pt: "comfort-top"`) are keywords that may expand to formulas
4
- // (max(safe-top, knob)); `var(--comfort-top)` always reads the raw table value.
5
-
6
- import type { Transition } from "./presentable"
7
-
8
- export type ThemeValues = Record<string, string | number | null>
9
-
10
- /** @internal Navigation defaults the theme owns; the router reads them at call time.
11
- * (SDK-side state, deliberately NOT in the host var table — `var(--replaceTransition)`
12
- * is not a style value.) */
13
- export const _navDefaults: { replace: Transition } = { replace: "none" }
14
-
15
- // (Unconstrained: it also maps inputs whose `replaceTransition` key was carved out.)
16
- export type ThemeAccessors<T> = {
17
- readonly [K in keyof T]: K extends string ? `var(--${K})` : never
18
- }
19
-
20
- const RESERVED = ["safe-top", "safe-bottom", "safe-left", "safe-right", "vw", "vh", "vmin", "vmax"]
21
-
22
- /**
23
- * Merge app theme variables into the live table and get typed `var(--key)` accessors back:
24
- *
25
- * ```ts
26
- * export const T = theme({ primaryColor: "#0A84FF", cardBg: "#1C1C1E" })
27
- * card.style({ bgColor: T.cardBg }) // T.cardBg === "var(--cardBg)"
28
- * ```
29
- *
30
- * Strings pass through (colors, fonts, expressions like `"max(safe-top, 24px)"`); numbers are
31
- * lengths (px); `null` removes a key (comfort knobs reset to their defaults). Env names
32
- * (`safe-*`, `vw`/`vh`/…) are host-owned — skipped with a warning. One special key:
33
- * `replaceTransition` — the app-wide default transition for `Router.replace` (consumed SDK-side,
34
- * never sent to the host table).
35
- */
36
- const setTheme = <T extends Record<string, string | number | Transition | null>>(
37
- // Only `replaceTransition` may carry a Transition — every other key is a style value.
38
- values: T & { [K in Exclude<keyof T, "replaceTransition">]: string | number | null }
39
- ): ThemeAccessors<Omit<T, "replaceTransition">> => {
40
- const accessors: Record<string, string> = {}
41
- let send = values as ThemeValues
42
- const strip = (key: string) => {
43
- if (send === values) send = { ...values } as ThemeValues
44
- delete send[key]
45
- }
46
- for (const key of Object.keys(values)) {
47
- if (key === "replaceTransition") {
48
- _navDefaults.replace = (values[key] ?? "none") as Transition
49
- strip(key) // SDK-consumed, no accessor: it isn't a style var
50
- continue
51
- }
52
- if (RESERVED.includes(key)) {
53
- console.warn(`theme(): "${key}" is an environment value (host-owned) — ignored`)
54
- strip(key)
55
- continue
56
- }
57
- accessors[key] = `var(--${key})`
58
- }
59
- // Optional during rollout: hosts without the method simply don't theme (values still type).
60
- if (Object.keys(send).length > 0) _creatorUI.setTheme?.(send)
61
- return accessors as ThemeAccessors<Omit<T, "replaceTransition">>
62
- }
63
-
64
- /** App theme: callable to merge variables (`theme({...})` — re-calling re-styles the live UI, so
65
- * dark mode is just a second call), with the system vars as static properties
66
- * (`theme.primaryColor`, `theme["comfort-top"]`, …). */
67
- export const theme = Object.assign(setTheme, {
68
- /** The app accent color. Kit components will read it via `var(--primaryColor, <fallback>)`. */
69
- primaryColor: "var(--primaryColor)",
70
- /** Secondary / inactive content color for kit components. */
71
- mutedColor: "var(--mutedColor)",
72
- /** DEFAULT text color — text without an explicit `color` follows it (hosts source their
73
- * default from the theme; unset = the host default, white on dark screens). Set it once for
74
- * a light theme instead of `color: "black"` on every label. */
75
- color: "var(--color)",
76
- /** DEFAULT text font — text without an explicit `fontFamily` follows it. */
77
- fontFamily: "var(--fontFamily)",
78
- /** Raw comfort knobs (logical px). The bare `comfort-top` style TOKEN applies the safe-area
79
- * formula — these accessors read the knob value itself, for manual composition. */
80
- "comfort-top": "var(--comfort-top)",
81
- "comfort-bottom": "var(--comfort-bottom)",
82
- "comfort-left": "var(--comfort-left)",
83
- "comfort-right": "var(--comfort-right)",
84
- } as const)