lecodes-cli 0.18.2 → 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 (224) hide show
  1. package/dist/index.js +1866 -301
  2. package/package.json +14 -12
  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/core/Aspect.ts +0 -512
  86. package/runtime/sdk/core/InspectorUI.ts +0 -212
  87. package/runtime/sdk/core/color.ts +0 -66
  88. package/runtime/sdk/core/compWrite.ts +0 -42
  89. package/runtime/sdk/core/events.ts +0 -38
  90. package/runtime/sdk/core/fields.ts +0 -120
  91. package/runtime/sdk/core/registry.ts +0 -23
  92. package/runtime/sdk/core/signals.ts +0 -277
  93. package/runtime/sdk/core/time.ts +0 -81
  94. package/runtime/sdk/g2/Camera2D.ts +0 -40
  95. package/runtime/sdk/g2/CharacterController2D.ts +0 -276
  96. package/runtime/sdk/g2/Node2D.ts +0 -267
  97. package/runtime/sdk/g2/OneWay2D.ts +0 -66
  98. package/runtime/sdk/g2/Physics2D.ts +0 -346
  99. package/runtime/sdk/g2/Scene2D.ts +0 -209
  100. package/runtime/sdk/g2/Shape2D.ts +0 -259
  101. package/runtime/sdk/g2/Sprite.ts +0 -89
  102. package/runtime/sdk/g2/SpriteAnimation.ts +0 -171
  103. package/runtime/sdk/g2/SpriteSheet.ts +0 -166
  104. package/runtime/sdk/g2/Texture2D.ts +0 -47
  105. package/runtime/sdk/g2/Tilemap.ts +0 -41
  106. package/runtime/sdk/g2/Tileset.ts +0 -71
  107. package/runtime/sdk/g2/Trigger2D.ts +0 -77
  108. package/runtime/sdk/g2/autotile.ts +0 -433
  109. package/runtime/sdk/g2/cells.ts +0 -91
  110. package/runtime/sdk/g2/defineScene2d.ts +0 -381
  111. package/runtime/sdk/g2/groups2d.ts +0 -106
  112. package/runtime/sdk/g2/loop.ts +0 -50
  113. package/runtime/sdk/g2/scenarios2d.ts +0 -69
  114. package/runtime/sdk/g2/touch.ts +0 -83
  115. package/runtime/sdk/gl/Camera.ts +0 -160
  116. package/runtime/sdk/gl/CameraPlace.ts +0 -52
  117. package/runtime/sdk/gl/CharacterController.ts +0 -238
  118. package/runtime/sdk/gl/Gearbox.ts +0 -212
  119. package/runtime/sdk/gl/Geometry.ts +0 -279
  120. package/runtime/sdk/gl/IK.ts +0 -193
  121. package/runtime/sdk/gl/InstancedMesh.ts +0 -132
  122. package/runtime/sdk/gl/Light.ts +0 -99
  123. package/runtime/sdk/gl/Lightmap.ts +0 -179
  124. package/runtime/sdk/gl/Material.ts +0 -245
  125. package/runtime/sdk/gl/Mesh.ts +0 -83
  126. package/runtime/sdk/gl/Model.ts +0 -64
  127. package/runtime/sdk/gl/Node.ts +0 -350
  128. package/runtime/sdk/gl/Noise.ts +0 -30
  129. package/runtime/sdk/gl/Particles.ts +0 -676
  130. package/runtime/sdk/gl/Physics.ts +0 -222
  131. package/runtime/sdk/gl/Plane.ts +0 -53
  132. package/runtime/sdk/gl/Ray.ts +0 -16
  133. package/runtime/sdk/gl/Scene.ts +0 -479
  134. package/runtime/sdk/gl/Shape.ts +0 -377
  135. package/runtime/sdk/gl/Texture.ts +0 -46
  136. package/runtime/sdk/gl/Trigger.ts +0 -45
  137. package/runtime/sdk/gl/Vehicle.ts +0 -473
  138. package/runtime/sdk/gl/Wheel.ts +0 -240
  139. package/runtime/sdk/gl/animation/AnimationClip.ts +0 -204
  140. package/runtime/sdk/gl/animation/Animator.ts +0 -87
  141. package/runtime/sdk/gl/animation/Layer.ts +0 -29
  142. package/runtime/sdk/gl/animation/Loop.ts +0 -25
  143. package/runtime/sdk/gl/animation/Playback.ts +0 -43
  144. package/runtime/sdk/gl/animation/core.ts +0 -294
  145. package/runtime/sdk/gl/controls.ts +0 -95
  146. package/runtime/sdk/gl/physicsEvents.ts +0 -20
  147. package/runtime/sdk/gl/scenarios.ts +0 -291
  148. package/runtime/sdk/gl/state.ts +0 -6
  149. package/runtime/sdk/gl/touch.ts +0 -68
  150. package/runtime/sdk/inject.ts +0 -186
  151. package/runtime/sdk/math/Mathf.ts +0 -118
  152. package/runtime/sdk/math/mat4.ts +0 -278
  153. package/runtime/sdk/math/quat.ts +0 -232
  154. package/runtime/sdk/math/vec.ts +0 -255
  155. package/runtime/sdk/plugins/camera.ts +0 -81
  156. package/runtime/sdk/plugins/geolocation.ts +0 -123
  157. package/runtime/sdk/plugins/oauth.ts +0 -61
  158. package/runtime/sdk/plugins/permission.ts +0 -7
  159. package/runtime/sdk/plugins/push.ts +0 -132
  160. package/runtime/sdk/plugins/qr.ts +0 -73
  161. package/runtime/sdk/plugins/service.ts +0 -47
  162. package/runtime/sdk/runtime/app.ts +0 -101
  163. package/runtime/sdk/runtime/appEvents.ts +0 -54
  164. package/runtime/sdk/runtime/channel.ts +0 -61
  165. package/runtime/sdk/runtime/clipboard.ts +0 -20
  166. package/runtime/sdk/runtime/datetime.ts +0 -329
  167. package/runtime/sdk/runtime/device.ts +0 -293
  168. package/runtime/sdk/runtime/fetch.ts +0 -77
  169. package/runtime/sdk/runtime/files.ts +0 -23
  170. package/runtime/sdk/runtime/input.ts +0 -175
  171. package/runtime/sdk/runtime/media.ts +0 -111
  172. package/runtime/sdk/runtime/misc.ts +0 -16
  173. package/runtime/sdk/runtime/net.ts +0 -36
  174. package/runtime/sdk/runtime/rpc.ts +0 -218
  175. package/runtime/sdk/runtime/service.ts +0 -83
  176. package/runtime/sdk/runtime/share.ts +0 -9
  177. package/runtime/sdk/runtime/storage.ts +0 -13
  178. package/runtime/sdk/runtime/touch.ts +0 -76
  179. package/runtime/sdk/scene/defineScene.ts +0 -1227
  180. package/runtime/sdk/scene/editorPlugins.ts +0 -92
  181. package/runtime/sdk/scene/gizmos.ts +0 -148
  182. package/runtime/sdk/scene/grammar.ts +0 -120
  183. package/runtime/sdk/scene/material.ts +0 -188
  184. package/runtime/sdk/server/auth/appConfig.ts +0 -12
  185. package/runtime/sdk/server/auth/global.ts +0 -80
  186. package/runtime/sdk/server/auth/host.ts +0 -318
  187. package/runtime/sdk/server/auth/models.ts +0 -83
  188. package/runtime/sdk/server/auth/types.ts +0 -50
  189. package/runtime/sdk/server/channel.ts +0 -56
  190. package/runtime/sdk/server/context.ts +0 -36
  191. package/runtime/sdk/server/db/defineDb.ts +0 -237
  192. package/runtime/sdk/server/db/fields.ts +0 -132
  193. package/runtime/sdk/server/db/httpTransport.ts +0 -93
  194. package/runtime/sdk/server/db/index.ts +0 -7
  195. package/runtime/sdk/server/db/marci/query.ts +0 -412
  196. package/runtime/sdk/server/db/types.ts +0 -202
  197. package/runtime/sdk/server/errors.ts +0 -12
  198. package/runtime/sdk/server/host.ts +0 -74
  199. package/runtime/sdk/server/inject.ts +0 -13
  200. package/runtime/sdk/server/runtime.ts +0 -133
  201. package/runtime/sdk/server/validate.ts +0 -87
  202. package/runtime/sdk/ui/NativeView.ts +0 -142
  203. package/runtime/sdk/ui/UI.ts +0 -39
  204. package/runtime/sdk/ui/UIBottomSheet.ts +0 -139
  205. package/runtime/sdk/ui/UIButton.ts +0 -101
  206. package/runtime/sdk/ui/UIContainer.ts +0 -60
  207. package/runtime/sdk/ui/UIImage.ts +0 -83
  208. package/runtime/sdk/ui/UIInput.ts +0 -185
  209. package/runtime/sdk/ui/UIModal.ts +0 -139
  210. package/runtime/sdk/ui/UINode.ts +0 -826
  211. package/runtime/sdk/ui/UIPager.ts +0 -362
  212. package/runtime/sdk/ui/UIPopover.ts +0 -100
  213. package/runtime/sdk/ui/UIScreen.ts +0 -123
  214. package/runtime/sdk/ui/UIScrollable.ts +0 -87
  215. package/runtime/sdk/ui/UISpacer.ts +0 -14
  216. package/runtime/sdk/ui/UITabs.ts +0 -236
  217. package/runtime/sdk/ui/UIText.ts +0 -51
  218. package/runtime/sdk/ui/UIVideo.ts +0 -88
  219. package/runtime/sdk/ui/UIVirtualizedList.ts +0 -241
  220. package/runtime/sdk/ui/UIWidget.ts +0 -127
  221. package/runtime/sdk/ui/fonts.ts +0 -13
  222. package/runtime/sdk/ui/presentable.ts +0 -117
  223. package/runtime/sdk/ui/router.ts +0 -132
  224. 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)