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
@@ -1,22 +1,33 @@
1
- // MapView — a vector map (maplibre-native on iOS/Android) as a Presentable. A typed wrapper over
2
- // the `NativeView("map")` capability (docs/map-plugin-plan.md): push it (`Router.push(map)`),
3
- // open it fullscreen (`map.open()`), or embed it among a screen's children where the host builds
4
- // the "native" layout node. The style is a URL, a bundled `asset()`, a read file or the style
5
- // object (see MapStyle). Data goes in as named layers (`map.markers(name)`, `map.line(name)`)
6
- // whose `set()` replaces their content; the camera is driven with `flyTo` / `fitPoints`; the user
7
- // puck is fed by the app (`setUserLocation`) — the plugin never touches the location hardware.
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/map/sdk/map.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // MapView — a vector map (maplibre-native on iOS / Android, maplibre-gl in the browser) as a view
4
+ // the app pushes (`Router.push(map)`), opens fullscreen (`map.open()`) or embeds among a screen's
5
+ // children. The style is a name, a URL, a bundled `asset()`, a read file or the style object (see
6
+ // MapStyle). Data goes in as named layers (`map.markers(name)`, `map.line(name)`) whose `set()`
7
+ // replaces their content; the camera is driven with `flyTo` / `fitPoints`; the user puck is fed by
8
+ // the app (`setUserLocation`) — the plugin never touches the location hardware.
8
9
  //
9
- // Host-OPTIONAL: it exists where the host registers a "map" view (the `map` plugin from
10
- // lecodes-plugins) — gate on `MapView.isSupported`. Everything here is sugar over ONE JSON channel
11
- // (`call` / `on`); the wire contract is the method/event table in docs/map-plugin-plan.md.
12
- //
13
- // Ordering: the native map exists only once presented and its style loaded — the plugin emits
14
- // `ready` then. Data and camera calls issued before that are queued and replayed in order, so an
15
- // app can build the map declaratively and push it later without a ready-dance of its own.
16
-
17
- import { NativeView, NativeViewElement } from "../ui/NativeView"
18
- import { _channelOn } from "../runtime/channel"
19
- import type { FetchResponse } from "../runtime/fetch"
10
+ // Hand-written over the generated wire because the public API is higher than the wire:
11
+ // - a style is resolved to a url or to text HERE, once, at creation;
12
+ // - marker items and coordinate lists become GeoJSON here;
13
+ // - the native map exists only once presented and its style loaded (`ready`): calls issued before
14
+ // that are queued and replayed in order, so an app builds the map declaratively and pushes it
15
+ // later without a ready-dance of its own;
16
+ // - what lives in the STYLE (layers, data, the padding, the user puck) is kept and re-applied
17
+ // after every style load.
18
+
19
+ import { ViewChannel, bufferText, type FetchResponse, type Json, type NativeView } from "../../../../plugin"
20
+ import { NAME, ensureLayer, fitPoints, flyTo, getCamera, jumpTo, setData, setPadding, setUserLocation } from "./map.gen"
21
+ import type {
22
+ LngLat, MapCamera, MapCameraMove, MapEvents, MapFitOptions, MapLayerKind, MapPadding, MapParams,
23
+ MapTap as WireTap, MapUserLocationOptions,
24
+ } from "../contract"
25
+
26
+ export type { LngLat, MapCamera }
27
+ export type CameraMove = MapCameraMove
28
+ export type FitOptions = MapFitOptions
29
+ export type MapPaddingValues = MapPadding
30
+ export type UserLocationOptions = MapUserLocationOptions
20
31
 
21
32
  /** The ready-made styles a map falls back on — [OpenFreeMap](https://openfreemap.org): OSM data,
22
33
  * no key, no registration, no request limits, commercial use allowed, and the whole stack is
@@ -56,34 +67,12 @@ const NAMED_STYLES: Record<string, string> = {
56
67
  // `string & {}` keeps the named suggestions in the editor while still accepting any URL.
57
68
  export type MapStyle = MapStyleName | (string & {}) | FetchResponse | object
58
69
 
59
- /** `[longitude, latitude]` — GeoJSON order, the same as the style, the tiles and your data. */
60
- export type LngLat = [number, number]
61
-
62
- export interface MapCamera {
63
- center: LngLat
64
- zoom: number
65
- /** Degrees clockwise from north. */
66
- bearing: number
67
- /** Degrees from the vertical. */
68
- pitch: number
69
- }
70
-
71
- export interface MapOptions {
70
+ export interface MapOptions extends Omit<MapParams, "style" | "styleJson"> {
72
71
  /** The MapLibre style: a ready-made name (`"liberty"` — the default, `"positron"`, …), a URL,
73
72
  * a style bundled with the app (`asset("./style.json")`), an already-read file
74
73
  * (`fetchLocal("style.json")`, `await fetch(url)`) or the style object itself — see
75
74
  * {@link MapStyle}. */
76
75
  style?: MapStyle
77
- center?: LngLat
78
- zoom?: number
79
- minZoom?: number
80
- maxZoom?: number
81
- bearing?: number
82
- pitch?: number
83
- /** Two-finger rotate gesture (default true). */
84
- rotate?: boolean
85
- /** Two-finger tilt gesture (default false — most city maps stay flat). */
86
- tilt?: boolean
87
76
  }
88
77
 
89
78
  /** A tap on the map itself — not on a feature of a managed layer. */
@@ -93,29 +82,6 @@ export interface MapTap {
93
82
  point: [number, number]
94
83
  }
95
84
 
96
- export interface CameraMove {
97
- zoom?: number
98
- bearing?: number
99
- pitch?: number
100
- /** Animation length, ms (flyTo only; default 600). */
101
- duration?: number
102
- }
103
-
104
- export interface MapPaddingValues {
105
- top?: number | string
106
- left?: number | string
107
- bottom?: number | string
108
- right?: number | string
109
- }
110
-
111
- export interface FitOptions {
112
- /** Px around the points, or per edge. Added to the view padding set by `setPadding`. */
113
- padding?: number | MapPaddingValues
114
- maxZoom?: number
115
- /** Default true. */
116
- animate?: boolean
117
- }
118
-
119
85
  /** One marker. `id` comes back in `onTap`; `icon` names an image of the style's sprite; `color` /
120
86
  * `title` feed the default layers; extra keys become feature properties. */
121
87
  export interface MarkerItem {
@@ -151,13 +117,6 @@ export interface LineLayerOptions {
151
117
  opacity?: number
152
118
  }
153
119
 
154
- export interface UserLocationOptions {
155
- /** Horizontal accuracy radius, meters — drawn as the halo around the dot. */
156
- accuracy?: number | null
157
- /** Degrees clockwise from north — drawn as the direction wedge; null hides it. */
158
- heading?: number | null
159
- }
160
-
161
120
  export interface MarkerLayer {
162
121
  readonly name: string
163
122
  /** Replace the layer's markers. */
@@ -208,15 +167,21 @@ export interface MapView extends NativeView {
208
167
  setUserLocation(lngLat: LngLat | null, options?: UserLocationOptions): this
209
168
  }
210
169
 
170
+ /** The wire's calls the wrapper sends without waiting for an answer, by name: what a queue entry
171
+ * replays. Every one takes the view first. */
172
+ const SEND = { ensureLayer, setData, flyTo, jumpTo, fitPoints, setPadding, setUserLocation }
173
+ type Send = typeof SEND
174
+ type SendArgs<M extends keyof Send> = Send[M] extends (view: any, ...args: infer A) => any ? A : never
175
+
211
176
  type Queued = { method: string, args: any[] }
212
- type LayerSpec = { kind: "markers" | "line", options: object }
177
+ type LayerSpec = { kind: MapLayerKind, options: object }
213
178
 
214
179
  /** Methods whose effect lives in the STYLE, not in the view: a style (re)load wipes them, so the
215
180
  * wrapper keeps their last value and re-applies it on every `ready` instead of replaying them
216
181
  * from the queue. Camera calls are not here — the camera survives a style reload. */
217
182
  const STATEFUL = ["ensureLayer", "setData", "setPadding", "setUserLocation"]
218
183
 
219
- class MapViewElement extends NativeViewElement {
184
+ class MapViewElement extends ViewChannel<MapEvents> {
220
185
  private _ready = false
221
186
  private _queue: Queued[] = []
222
187
  private readonly _layers = new Map<string, MapLayerHandle>()
@@ -224,18 +189,18 @@ class MapViewElement extends NativeViewElement {
224
189
  private readonly _specs = new Map<string, LayerSpec>()
225
190
  private readonly _data = new Map<string, object>()
226
191
  private _padding?: MapPaddingValues
227
- private _user?: any[]
192
+ private _user?: SendArgs<"setUserLocation">
228
193
  private readonly _readyCallbacks: (() => void)[] = []
229
194
  private readonly _tapCallbacks: ((tap: MapTap) => void)[] = []
230
195
  private readonly _moveCallbacks: ((camera: MapCamera) => void)[] = []
231
196
  private readonly _errorCallbacks: ((error: { message: string }) => void)[] = []
232
197
 
233
198
  constructor(options: MapOptions = {}) {
234
- super("map", _styleParams(options))
235
- _channelOn(this.nvl, "ready", () => this._onReady())
236
- _channelOn(this.nvl, "tap", (data: any) => this._onTap(data))
237
- _channelOn(this.nvl, "moveEnd", (data: any) => { for (const cb of [...this._moveCallbacks]) cb(data) })
238
- _channelOn(this.nvl, "error", (data: any) => this._onError(data))
199
+ super("MapView", NAME, _styleParams(options))
200
+ this.on("ready", () => this._onReady())
201
+ this.on("tap", tap => this._onTap(tap))
202
+ this.on("moveEnd", camera => { for (const cb of [...this._moveCallbacks]) cb(camera) })
203
+ this.on("error", error => this._onError(error))
239
204
  }
240
205
 
241
206
  onReady(callback: () => void): this { this._readyCallbacks.push(callback); return this }
@@ -251,7 +216,7 @@ class MapViewElement extends NativeViewElement {
251
216
  }
252
217
  setData(source: string, geojson: object): this {
253
218
  this._data.set(source, geojson)
254
- this._send("setData", [source, geojson])
219
+ this._send("setData", [source, geojson as Json])
255
220
  return this
256
221
  }
257
222
 
@@ -259,22 +224,23 @@ class MapViewElement extends NativeViewElement {
259
224
  jumpTo(center: LngLat, options: CameraMove = {}): this { this._send("jumpTo", [center, options]); return this }
260
225
  fitPoints(points: LngLat[], options: FitOptions = {}): this { this._send("fitPoints", [points, options]); return this }
261
226
  setPadding(padding: MapPaddingValues): this { this._padding = padding; this._send("setPadding", [padding]); return this }
262
- getCamera(): Promise<MapCamera> { return this.call("getCamera") }
227
+ getCamera(): Promise<MapCamera> { return getCamera(this) }
263
228
 
264
229
  setUserLocation(lngLat: LngLat | null, options: UserLocationOptions = {}): this {
265
230
  this._user = [lngLat, options]
266
- this._send("setUserLocation", [lngLat, options])
231
+ this._send("setUserLocation", this._user)
267
232
  return this
268
233
  }
269
234
 
270
235
  /** @internal queue until `ready`, then straight through. Rejections are logged, never thrown:
271
- * a fire-and-forget camera/data call has no caller to reject to. */
272
- _send(method: string, args: any[]): void {
236
+ * a fire-and-forget camera / data call has no caller to reject to. */
237
+ _send<M extends keyof Send>(method: M, args: SendArgs<M>): void {
273
238
  if (!this._ready) { this._queue.push({ method, args }); return }
274
- this.call(method, ...args).catch((e: Error) => console.error(`MapView.${method}: ${e.message}`))
239
+ const call: (view: this, ...args: any[]) => Promise<void> = SEND[method] ?? ((view, ...rest) => view._call(method, rest))
240
+ call(this, ...args).catch((e: Error) => console.error(`MapView.${method}: ${e.message}`))
275
241
  }
276
242
 
277
- private _layer(name: string, kind: "markers" | "line", options: object): MapLayerHandle {
243
+ private _layer(name: string, kind: MapLayerKind, options: object): MapLayerHandle {
278
244
  let layer = this._layers.get(name)
279
245
  if (!layer) {
280
246
  layer = new MapLayerHandle(this, name)
@@ -294,28 +260,28 @@ class MapViewElement extends NativeViewElement {
294
260
  const queue = this._queue
295
261
  this._queue = []
296
262
  for (const [name, spec] of this._specs) this._send("ensureLayer", [name, spec.kind, spec.options])
297
- for (const [source, geojson] of this._data) this._send("setData", [source, geojson])
263
+ for (const [source, geojson] of this._data) this._send("setData", [source, geojson as Json])
298
264
  if (this._padding) this._send("setPadding", [this._padding])
299
265
  if (this._user) this._send("setUserLocation", this._user)
300
- for (const q of queue) if (STATEFUL.indexOf(q.method) < 0) this._send(q.method, q.args)
266
+ for (const q of queue) if (STATEFUL.indexOf(q.method) < 0) this._send(q.method as keyof Send, q.args as any)
301
267
  for (const cb of [...this._readyCallbacks]) cb()
302
268
  }
303
269
 
304
- private _onError(data: any): void {
270
+ private _onError(error: { message: string }): void {
305
271
  // Unhandled is not unheard: a style the host couldn't load is exactly the failure that looks
306
272
  // like "the map is blank and nothing happened".
307
- if (this._errorCallbacks.length === 0) { console.error(`MapView: ${data?.message ?? "unknown error"}`); return }
308
- for (const cb of [...this._errorCallbacks]) cb(data)
273
+ if (this._errorCallbacks.length === 0) { console.error(`MapView: ${error?.message ?? "unknown error"}`); return }
274
+ for (const cb of [...this._errorCallbacks]) cb(error)
309
275
  }
310
276
 
311
- private _onTap(data: any): void {
312
- const feature = data?.feature
277
+ private _onTap(tap: WireTap): void {
278
+ const feature = tap?.feature
313
279
  const layer = feature ? this._layers.get(feature.source) : undefined
314
- if (layer) {
315
- layer._tap({ id: feature.id, lngLat: data.lngLat, properties: feature.properties ?? {} })
280
+ if (feature && layer) {
281
+ layer._tap({ id: feature.id as string | number, lngLat: tap.lngLat, properties: feature.properties ?? {} })
316
282
  return
317
283
  }
318
- for (const cb of [...this._tapCallbacks]) cb({ lngLat: data.lngLat, point: data.point })
284
+ for (const cb of [...this._tapCallbacks]) cb({ lngLat: tap.lngLat, point: tap.point })
319
285
  }
320
286
  }
321
287
 
@@ -348,15 +314,15 @@ class MapLayerHandle {
348
314
  }
349
315
  }
350
316
 
351
- /** @internal `MapOptions` → host params. A style URL stays a url the map fetches itself; every
317
+ /** @internal `MapOptions` → the wire's params. A style URL stays a url the map fetches itself; every
352
318
  * other form is read HERE and crosses as `styleJson` text — one string, once, at creation. A
353
319
  * bundled `asset()` is `"id:N"` in shell compiles (the host already holds the bytes) and a plain
354
320
  * url in server compiles, so the same call works on every host. */
355
- export const _styleParams = (options: MapOptions = {}): any => {
321
+ export const _styleParams = (options: MapOptions = {}): MapParams => {
356
322
  const { style = "liberty", ...rest } = options
357
323
  if (typeof style === "string") {
358
324
  if (!style.startsWith("id:")) return { ...rest, style: NAMED_STYLES[style] ?? style }
359
- const text = _creatorUtils.fetchToText(+style.slice(3))
325
+ const text = bufferText(+style.slice(3))
360
326
  if (!text) throw new Error("MapView: the style asset is empty or missing")
361
327
  return { ...rest, styleJson: text }
362
328
  }
@@ -380,9 +346,9 @@ export const _toGeoJson = (items: MarkerItem[] | LngLat[]): object => {
380
346
 
381
347
  /**
382
348
  * Create a map view. `MapView.isSupported` reports whether this host registered a "map" view —
383
- * check it before offering the feature (web, headless and shells without the plugin have none).
349
+ * check it before offering the feature.
384
350
  */
385
- // PURE IIFE so an app that never uses the map tree-shakes the whole plugin away (see NativeView).
351
+ // PURE IIFE so an app that never uses the map tree-shakes the whole plugin away.
386
352
  export const MapView: {
387
353
  (options?: MapOptions): MapView
388
354
  /** Whether this host registered a "map" view. */
@@ -390,7 +356,7 @@ export const MapView: {
390
356
  } = /*#__PURE__*/ (() => {
391
357
  const factory = (options: MapOptions = {}): MapView => new MapViewElement(options) as unknown as MapView
392
358
  Object.defineProperty(factory, "isSupported", {
393
- get: (): boolean => NativeView.isSupported("map"),
359
+ get: (): boolean => ViewChannel.supports(NAME),
394
360
  })
395
361
  return factory as any
396
362
  })()
@@ -0,0 +1,61 @@
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/push/contract.d.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // push — remote notifications (APNs on iOS, FCM on Android).
4
+ // The host owns the OS token, the permission prompt and the registration with the le.codes relay;
5
+ // the app sees the opaque project-scoped ADDRESS and the payloads, never the raw token.
6
+ //
7
+ // An OPEN SESSION is the delivery pipe of the events. Opening one is free (no prompt, no I/O).
8
+ // Identity: every call is attributed to the world that makes it (the project's uuid, held by the
9
+ // host); a world without one rejects "unavailable" BEFORE any permission path.
10
+
11
+ import type { Json, Service, i32 } from "../../../plugin"
12
+
13
+ /** A delivered notification, as the app sees it. */
14
+ export interface PushPayload {
15
+ title: string
16
+ body?: string
17
+ /** A deep link — it also rides the app's own link path (`app.launchUrl`, the "url" event). */
18
+ url?: string
19
+ /** The developer's own JSON object, ≤ 2 KB serialized. */
20
+ data?: { [key: string]: Json }
21
+ badge?: i32
22
+ }
23
+
24
+ export interface PushStatus {
25
+ /** The OS permission of the host app. "prompt" = not asked yet. */
26
+ permission: "granted" | "denied" | "prompt"
27
+ /** Whether this device holds a registration (an address) for this app. */
28
+ registered: boolean
29
+ }
30
+
31
+ export interface PushRegisterOptions {
32
+ /** The app's OWN user id. Client-asserted and unverified. The registration reflects the latest
33
+ * call: registering without it clears it. */
34
+ user?: string
35
+ }
36
+
37
+ export interface PushRegistration {
38
+ address: string
39
+ }
40
+
41
+ export interface PushParams {}
42
+
43
+ export interface PushEvents {
44
+ /** Arrived while this app was in the foreground (the host shows no banner). */
45
+ message: PushPayload
46
+ /** Tapped while the world was alive. */
47
+ tap: PushPayload
48
+ }
49
+
50
+ export interface Push extends Service<"push", PushParams, PushEvents> {
51
+ /** Permission + registration state. Never prompts. */
52
+ getStatus(): Promise<PushStatus>
53
+ /** Ask for the permission (the first time) and register this device. Idempotent.
54
+ * @rejects denied unavailable */
55
+ register(options?: PushRegisterOptions): Promise<PushRegistration>
56
+ /** Remove this device's registration.
57
+ * @rejects unavailable */
58
+ unregister(): Promise<void>
59
+ /** The notification that cold-started this world, or null. Stable across calls. */
60
+ getLaunch(): Promise<PushPayload | null>
61
+ }
@@ -0,0 +1,60 @@
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/push/sdk/push.gen.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // GENERATED by `lecodes plugin gen` from contract.d.ts — do not edit.
4
+ // push: the service "push", contract version 1.
5
+
6
+ import { ServiceChannel } from "../../../../plugin"
7
+ import type { PushEvents, PushParams, PushPayload, PushRegisterOptions, PushRegistration, PushStatus } from "../contract"
8
+
9
+ /** What the halves register under. */
10
+ export const NAME = "push"
11
+ /** The contract's version: the highest `@since` of its members. */
12
+ export const VERSION = 1
13
+
14
+ // ---- the wire, call by call ----------------------------------------------------------------------
15
+
16
+ /** Permission + registration state. Never prompts. */
17
+ export const getStatus = (service: ServiceChannel<PushEvents>): Promise<PushStatus> =>
18
+ service._call("getStatus", [])
19
+
20
+ /** Ask for the permission (the first time) and register this device. Idempotent.
21
+ * Rejects with "denied" / "unavailable". */
22
+ export const register = (service: ServiceChannel<PushEvents>, options?: PushRegisterOptions): Promise<PushRegistration> =>
23
+ service._call("register", [options])
24
+
25
+ /** Remove this device's registration.
26
+ * Rejects with "unavailable". */
27
+ export const unregister = (service: ServiceChannel<PushEvents>): Promise<void> =>
28
+ service._call("unregister", [])
29
+
30
+ /** The notification that cold-started this world, or null. Stable across calls. */
31
+ export const getLaunch = (service: ServiceChannel<PushEvents>): Promise<PushPayload | null> =>
32
+ service._call("getLaunch", []).then((w: any) => w ?? null)
33
+
34
+ // ---- what the host's half has --------------------------------------------------------------------
35
+
36
+ /** A method of the contract. */
37
+ export type Method = "getStatus" | "register" | "unregister" | "getLaunch"
38
+
39
+ /** Whether this host has the service "push" — and, given a method, a half new enough for it
40
+ * (a method added after the first version of the contract is tagged `@since`). */
41
+ export const supports = (method?: Method): boolean =>
42
+ ServiceChannel.supports(NAME) // every method is of version 1
43
+
44
+ // ---- the client -----------------------------------------------------------------------------------
45
+
46
+ /** The service "push" with the wire's methods as its own. */
47
+ export class PushBase extends ServiceChannel<PushEvents> {
48
+ constructor(params: PushParams = {}) { super("Push", NAME, params) }
49
+
50
+ /** Permission + registration state. Never prompts. */
51
+ getStatus(): Promise<PushStatus> { return getStatus(this) }
52
+ /** Ask for the permission (the first time) and register this device. Idempotent.
53
+ * Rejects with "denied" / "unavailable". */
54
+ register(options?: PushRegisterOptions): Promise<PushRegistration> { return register(this, options) }
55
+ /** Remove this device's registration.
56
+ * Rejects with "unavailable". */
57
+ unregister(): Promise<void> { return unregister(this) }
58
+ /** The notification that cold-started this world, or null. Stable across calls. */
59
+ getLaunch(): Promise<PushPayload | null> { return getLaunch(this) }
60
+ }
@@ -0,0 +1,105 @@
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/push/sdk/push.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // Push — remote notifications. The host owns the OS token, the permission prompt and the
4
+ // registration with the le.codes relay; the app only ever sees the opaque project-scoped ADDRESS
5
+ // (never the raw APNs / FCM token) plus payloads.
6
+ //
7
+ // Hand-written over the generated wire because the public API is a module singleton with
8
+ // `addEventListener`, and a listener must OPEN the session: events arrive on a live one only.
9
+ //
10
+ // The app is not running when a push arrives — display is host / OS work. The JS world sees
11
+ // exactly three delivery paths:
12
+ // - event "message": arrived while this app was foregrounded (the host suppresses the banner)
13
+ // - event "tap": tapped while the world was alive (warm)
14
+ // - getLaunch(): the notification that cold-started this world (stable pull, or null)
15
+ // A payload's `url` additionally rides the app-lifecycle deep-link path (`app.launchUrl` /
16
+ // the "url" event), so apps that already route links get notification routing for free.
17
+ //
18
+ // The OS permission prompt happens inside `register()`; `getStatus()` and `getLaunch()` never
19
+ // prompt. On a host without the service every method rejects at once, BEFORE any permission path.
20
+
21
+ import { NAME, PushBase } from "./push.gen"
22
+ import type { PushEvents, PushPayload, PushRegisterOptions, PushRegistration, PushStatus } from "../contract"
23
+
24
+ export type { PushPayload, PushRegisterOptions, PushStatus }
25
+
26
+ export type PushEvent = keyof PushEvents
27
+
28
+ /**
29
+ * Remote push notifications. `Push.isSupported` reports whether this host registered the
30
+ * service — check it before offering notification features.
31
+ */
32
+ // PURE IIFE so an app that never uses push tree-shakes the whole plugin away.
33
+ export const Push: {
34
+ /** Whether this host registered a "push" service. */
35
+ readonly isSupported: boolean
36
+ /** Permission + registration state. Never prompts. */
37
+ getStatus(): Promise<PushStatus>
38
+ /** Ask for permission (first time) and register this device → the opaque address your server
39
+ * targets. Idempotent — safe to call every launch; rejects "denied" / "unavailable". */
40
+ register(options?: PushRegisterOptions): Promise<PushRegistration>
41
+ /** Remove this device's registration (the address stops receiving). */
42
+ unregister(): Promise<void>
43
+ /** The notification that cold-started this app run, or null. Stable across calls. */
44
+ getLaunch(): Promise<PushPayload | null>
45
+ /** "message" = received while the app is open; "tap" = the user tapped one while it ran. */
46
+ addEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void
47
+ removeEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void
48
+ } = /*#__PURE__*/ (() => {
49
+ let client: PushBase | null = null
50
+ const service = (): PushBase => client ??= new PushBase()
51
+
52
+ const assertSupported = (): void => {
53
+ // Fail before the host is touched — a permission dialog for a feature that can't exist
54
+ // would be worse than the error.
55
+ if (!PushBase.supports(NAME)) {
56
+ throw new Error('Push isn\'t available on this host — it needs a registered "push" service.')
57
+ }
58
+ }
59
+
60
+ // `on` only records listeners; events need a live session to arrive on. Poke the host with the
61
+ // prompt-free getStatus once so a listener-only app (already registered on a previous run)
62
+ // still hears warm taps.
63
+ let pipeOpened = false
64
+ const ensurePipe = (): void => {
65
+ if (pipeOpened || !PushBase.supports(NAME)) return
66
+ pipeOpened = true
67
+ service().getStatus().catch(() => { pipeOpened = false })
68
+ }
69
+
70
+ const push = {
71
+ async getStatus(): Promise<PushStatus> {
72
+ assertSupported()
73
+ return await service().getStatus()
74
+ },
75
+
76
+ async register(options?: PushRegisterOptions): Promise<PushRegistration> {
77
+ assertSupported()
78
+ return await service().register(options ?? {})
79
+ },
80
+
81
+ async unregister(): Promise<void> {
82
+ assertSupported()
83
+ await service().unregister()
84
+ },
85
+
86
+ async getLaunch(): Promise<PushPayload | null> {
87
+ assertSupported()
88
+ return (await service().getLaunch()) ?? null
89
+ },
90
+
91
+ addEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void {
92
+ // Recording on an unsupported host is a silent no-op (the events just never fire),
93
+ // like app / device listeners — only the promise-returning methods reject loudly.
94
+ service().on(event, callback)
95
+ ensurePipe()
96
+ },
97
+ removeEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void {
98
+ service().off(event, callback)
99
+ },
100
+ }
101
+ Object.defineProperty(push, "isSupported", {
102
+ get: (): boolean => PushBase.supports(NAME),
103
+ })
104
+ return push as any
105
+ })()
@@ -0,0 +1,16 @@
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/qr-scanner/contract.d.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // qr-scanner — a camera view that decodes QR codes.
4
+ // A view with events only: the app opens / embeds it and listens.
5
+
6
+ import type { View } from "../../../plugin"
7
+
8
+ export interface QRScannerParams {}
9
+
10
+ export interface QRScannerEvents {
11
+ /** One per decoded camera frame: the payload, or null for a frame with no readable code (it
12
+ * repeats while the user aims). The same code may be reported more than once. */
13
+ scan: { data: string | null }
14
+ }
15
+
16
+ export interface QRScanner extends View<"qrScanner", QRScannerParams, QRScannerEvents> {}
@@ -0,0 +1,29 @@
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/qr-scanner/sdk/qr-scanner.gen.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // GENERATED by `lecodes plugin gen` from contract.d.ts — do not edit.
4
+ // qr-scanner: the view "qrScanner", contract version 1.
5
+
6
+ import { ViewChannel } from "../../../../plugin"
7
+ import type { QRScannerEvents, QRScannerParams } from "../contract"
8
+
9
+ /** What the halves register under. */
10
+ export const NAME = "qrScanner"
11
+ /** The contract's version: the highest `@since` of its members. */
12
+ export const VERSION = 1
13
+
14
+ // ---- what the host's half has --------------------------------------------------------------------
15
+
16
+ /** A method of the contract. */
17
+ export type Method = never
18
+
19
+ /** Whether this host has the view "qrScanner" — and, given a method, a half new enough for it
20
+ * (a method added after the first version of the contract is tagged `@since`). */
21
+ export const supports = (method?: Method): boolean =>
22
+ ViewChannel.supports(NAME) // every method is of version 1
23
+
24
+ // ---- the element ----------------------------------------------------------------------------------
25
+
26
+ /** The view "qrScanner" with the wire's methods as its own. */
27
+ export class QRScannerBase extends ViewChannel<QRScannerEvents> {
28
+ constructor(params: QRScannerParams = {}) { super("QRScanner", NAME, params) }
29
+ }
@@ -0,0 +1,52 @@
1
+ // GENERATED by scripts/vendor-plugins.ts from lecodes-plugins/plugins/qr-scanner/sdk/qr-scanner.ts — do not edit here.
2
+ // Change it in the plugin repo and run `bun run vendor:plugins`; `bun run check:plugins` fails when this copy is stale.
3
+ // QRScanner — the host's camera QR scanner as a view the app opens fullscreen
4
+ // (`await scanner.open()`), pushes (`Router.push(scanner)`) or embeds as a live preview.
5
+ //
6
+ // Hand-written over the generated wire for two things: `onScan` hands over the decoded string, not
7
+ // the event's payload, and the permission is asked BEFORE the view is presented.
8
+
9
+ import { prepareCamera, type NativeView, type PresentOptions } from "../../../../plugin"
10
+ import { NAME, QRScannerBase } from "./qr-scanner.gen"
11
+
12
+ export interface QRScanner extends NativeView {
13
+ /** Fires per decoded camera frame: the decoded string, or `null` for a frame with no readable
14
+ * code (expect those repeatedly while the user aims). The same code can be reported more than
15
+ * once — `close()` or debounce once you have what you need. */
16
+ onScan(callback: (data: string | null) => void): this
17
+ /** Request the camera permission, then present the scanner. The current destination (and its
18
+ * loading state) stays visible until the scanner is ready; rejects if the camera is denied,
19
+ * the host can't scan, or another navigation superseded this one. */
20
+ open(options?: PresentOptions): Promise<void>
21
+ }
22
+
23
+ class QRScannerElement extends QRScannerBase {
24
+ onScan(callback: (data: string | null) => void): this {
25
+ return this.on("scan", payload => callback(payload?.data ?? null))
26
+ }
27
+
28
+ /** @internal prepare-then-present (see Presentable._prepare). */
29
+ _prepare(): Promise<void> { return prepareCamera(this) }
30
+
31
+ override async open(options?: PresentOptions): Promise<void> {
32
+ await this._prepare()
33
+ super.open(options)
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Create a QR scanner view. `QRScanner.isSupported` reports whether this host can scan at all —
39
+ * check it before offering the feature.
40
+ */
41
+ // PURE IIFE so an app that never scans tree-shakes the whole plugin away.
42
+ export const QRScanner: {
43
+ (): QRScanner
44
+ /** Whether this host registered a "qrScanner" view. */
45
+ readonly isSupported: boolean
46
+ } = /*#__PURE__*/ (() => {
47
+ const factory = (): QRScanner => new QRScannerElement() as unknown as QRScanner
48
+ Object.defineProperty(factory, "isSupported", {
49
+ get: (): boolean => QRScannerBase.supports(NAME),
50
+ })
51
+ return factory as any
52
+ })()
@@ -1,7 +1,8 @@
1
- // Camera permission, host-gated: hosts expose it as `_creatorUtils.requestCamera`. Hosts without
2
- // that bridge resolve immediately — their view factory prompts on its own (e.g. getUserMedia on
1
+ // Camera permission, host-gated: hosts expose it as `_creatorDevice.requestCamera`. Hosts without
2
+ // that slot resolve immediately — their view factory prompts on its own (e.g. getUserMedia on
3
3
  // the web). Shared by ARScene.prepare, QRScanner and CameraView.
4
+
4
5
  export const _requestCameraPermission = (): Promise<void> =>
5
- typeof _creatorUtils.requestCamera === "function"
6
- ? new Promise<void>((res, rej) => _creatorUtils.requestCamera!(res, rej))
6
+ typeof _creatorDevice.requestCamera === "function"
7
+ ? new Promise<void>((res, rej) => _creatorDevice.requestCamera!(res, rej))
7
8
  : Promise.resolve()