@webspatial/core-sdk 1.6.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +10 -0
  3. package/dist/JSBCommand.d.ts +398 -0
  4. package/dist/JSBCommand.js +668 -0
  5. package/dist/JSBCommand.js.map +1 -0
  6. package/dist/Spatial.d.ts +63 -0
  7. package/dist/Spatial.js +60 -0
  8. package/dist/Spatial.js.map +1 -0
  9. package/dist/SpatialObject.d.ts +19 -0
  10. package/dist/SpatialObject.js +44 -0
  11. package/dist/SpatialObject.js.map +1 -0
  12. package/dist/SpatialScene.d.ts +51 -0
  13. package/dist/SpatialScene.js +74 -0
  14. package/dist/SpatialScene.js.map +1 -0
  15. package/dist/SpatialSession.d.ts +143 -0
  16. package/dist/SpatialSession.js +173 -0
  17. package/dist/SpatialSession.js.map +1 -0
  18. package/dist/SpatialWebEvent.d.ts +8 -0
  19. package/dist/SpatialWebEvent.js +18 -0
  20. package/dist/SpatialWebEvent.js.map +1 -0
  21. package/dist/SpatialWebEventCreator.d.ts +11 -0
  22. package/dist/SpatialWebEventCreator.js +11 -0
  23. package/dist/SpatialWebEventCreator.js.map +1 -0
  24. package/dist/Spatialized2DElement.d.ts +42 -0
  25. package/dist/Spatialized2DElement.js +47 -0
  26. package/dist/Spatialized2DElement.js.map +1 -0
  27. package/dist/SpatializedDynamic3DElement.d.ts +7 -0
  28. package/dist/SpatializedDynamic3DElement.js +43 -0
  29. package/dist/SpatializedDynamic3DElement.js.map +1 -0
  30. package/dist/SpatializedElement.d.ts +7 -0
  31. package/dist/SpatializedElement.js +206 -0
  32. package/dist/SpatializedElement.js.map +1 -0
  33. package/dist/SpatializedElementCreator.d.ts +15 -0
  34. package/dist/SpatializedElementCreator.js +47 -0
  35. package/dist/SpatializedElementCreator.js.map +1 -0
  36. package/dist/SpatializedStatic3DElement.d.ts +195 -0
  37. package/dist/SpatializedStatic3DElement.js +327 -0
  38. package/dist/SpatializedStatic3DElement.js.map +1 -0
  39. package/dist/WebMsgCommand.d.ts +7 -0
  40. package/dist/WebMsgCommand.js +23 -0
  41. package/dist/WebMsgCommand.js.map +1 -0
  42. package/dist/index.d.ts +35 -1101
  43. package/dist/index.js +21 -3393
  44. package/dist/index.js.map +1 -1
  45. package/dist/install-polyfills.d.ts +2 -0
  46. package/dist/install-polyfills.js +13 -0
  47. package/dist/install-polyfills.js.map +1 -0
  48. package/dist/isSSREnv.d.ts +3 -0
  49. package/dist/isSSREnv.js +6 -0
  50. package/dist/isSSREnv.js.map +1 -0
  51. package/dist/motion/AnimationObject.d.ts +7 -0
  52. package/dist/motion/AnimationObject.js +140 -0
  53. package/dist/motion/AnimationObject.js.map +1 -0
  54. package/dist/motion/compute/index.d.ts +10 -0
  55. package/dist/motion/compute/index.js +19 -0
  56. package/dist/motion/compute/index.js.map +1 -0
  57. package/dist/motion/compute/motionPropertyValues.d.ts +19 -0
  58. package/dist/motion/compute/motionPropertyValues.js +50 -0
  59. package/dist/motion/compute/motionPropertyValues.js.map +1 -0
  60. package/dist/motion/compute/normalize.d.ts +31 -0
  61. package/dist/motion/compute/normalize.js +201 -0
  62. package/dist/motion/compute/normalize.js.map +1 -0
  63. package/dist/motion/compute/validate.d.ts +22 -0
  64. package/dist/motion/compute/validate.js +103 -0
  65. package/dist/motion/compute/validate.js.map +1 -0
  66. package/dist/motion/index.d.ts +8 -0
  67. package/dist/motion/index.js +6 -0
  68. package/dist/motion/index.js.map +1 -0
  69. package/dist/motion/native/serializeMotionTimeline.d.ts +12 -0
  70. package/dist/motion/native/serializeMotionTimeline.js +21 -0
  71. package/dist/motion/native/serializeMotionTimeline.js.map +1 -0
  72. package/dist/physicalMetrics-W5uZ5xKb.d.ts +48 -0
  73. package/dist/physicalMetrics.d.ts +1 -0
  74. package/dist/physicalMetrics.js +58 -0
  75. package/dist/physicalMetrics.js.map +1 -0
  76. package/dist/platform-adapter/CommandResultUtils.d.ts +12 -0
  77. package/dist/platform-adapter/CommandResultUtils.js +21 -0
  78. package/dist/platform-adapter/CommandResultUtils.js.map +1 -0
  79. package/dist/platform-adapter/createPlatformSync.d.ts +16 -0
  80. package/dist/platform-adapter/createPlatformSync.js +30 -0
  81. package/dist/platform-adapter/createPlatformSync.js.map +1 -0
  82. package/dist/platform-adapter/index.d.ts +12 -0
  83. package/dist/platform-adapter/index.js +10 -0
  84. package/dist/platform-adapter/index.js.map +1 -0
  85. package/dist/platform-adapter/interface.d.ts +7 -0
  86. package/dist/platform-adapter/interface.js +1 -0
  87. package/dist/platform-adapter/interface.js.map +1 -0
  88. package/dist/platform-adapter/pico-os/PicoOSPlatform.d.ts +25 -0
  89. package/dist/platform-adapter/pico-os/PicoOSPlatform.js +168 -0
  90. package/dist/platform-adapter/pico-os/PicoOSPlatform.js.map +1 -0
  91. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.d.ts +66 -0
  92. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js +372 -0
  93. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js.map +1 -0
  94. package/dist/platform-adapter/spatialRequestMetadata.d.ts +6 -0
  95. package/dist/platform-adapter/spatialRequestMetadata.js +39 -0
  96. package/dist/platform-adapter/spatialRequestMetadata.js.map +1 -0
  97. package/dist/platform-adapter/spatialSceneQuery.d.ts +12 -0
  98. package/dist/platform-adapter/spatialSceneQuery.js +12 -0
  99. package/dist/platform-adapter/spatialSceneQuery.js.map +1 -0
  100. package/dist/platform-adapter/vision-os/VisionOSPlatform.d.ts +19 -0
  101. package/dist/platform-adapter/vision-os/VisionOSPlatform.js +77 -0
  102. package/dist/platform-adapter/vision-os/VisionOSPlatform.js.map +1 -0
  103. package/dist/platform-runtime.d.ts +12 -0
  104. package/dist/platform-runtime.js +14 -0
  105. package/dist/platform-runtime.js.map +1 -0
  106. package/dist/reality/Attachment.d.ts +19 -0
  107. package/dist/reality/Attachment.js +39 -0
  108. package/dist/reality/Attachment.js.map +1 -0
  109. package/dist/reality/component/ModelComponent.d.ts +14 -0
  110. package/dist/reality/component/ModelComponent.js +11 -0
  111. package/dist/reality/component/ModelComponent.js.map +1 -0
  112. package/dist/reality/component/SpatialComponent.d.ts +8 -0
  113. package/dist/reality/component/SpatialComponent.js +19 -0
  114. package/dist/reality/component/SpatialComponent.js.map +1 -0
  115. package/dist/reality/component/index.d.ts +8 -0
  116. package/dist/reality/component/index.js +3 -0
  117. package/dist/reality/component/index.js.map +1 -0
  118. package/dist/reality/entity/SpatialEntity.d.ts +7 -0
  119. package/dist/reality/entity/SpatialEntity.js +291 -0
  120. package/dist/reality/entity/SpatialEntity.js.map +1 -0
  121. package/dist/reality/entity/SpatialModelEntity.d.ts +17 -0
  122. package/dist/reality/entity/SpatialModelEntity.js +17 -0
  123. package/dist/reality/entity/SpatialModelEntity.js.map +1 -0
  124. package/dist/reality/entity/index.d.ts +8 -0
  125. package/dist/reality/entity/index.js +3 -0
  126. package/dist/reality/entity/index.js.map +1 -0
  127. package/dist/reality/geometry/SpatialBoxGeometry.d.ts +16 -0
  128. package/dist/reality/geometry/SpatialBoxGeometry.js +13 -0
  129. package/dist/reality/geometry/SpatialBoxGeometry.js.map +1 -0
  130. package/dist/reality/geometry/SpatialConeGeometry.d.ts +16 -0
  131. package/dist/reality/geometry/SpatialConeGeometry.js +13 -0
  132. package/dist/reality/geometry/SpatialConeGeometry.js.map +1 -0
  133. package/dist/reality/geometry/SpatialCylinderGeometry.d.ts +16 -0
  134. package/dist/reality/geometry/SpatialCylinderGeometry.js +13 -0
  135. package/dist/reality/geometry/SpatialCylinderGeometry.js.map +1 -0
  136. package/dist/reality/geometry/SpatialGeometry.d.ts +7 -0
  137. package/dist/reality/geometry/SpatialGeometry.js +13 -0
  138. package/dist/reality/geometry/SpatialGeometry.js.map +1 -0
  139. package/dist/reality/geometry/SpatialPlaneGeometry.d.ts +16 -0
  140. package/dist/reality/geometry/SpatialPlaneGeometry.js +13 -0
  141. package/dist/reality/geometry/SpatialPlaneGeometry.js.map +1 -0
  142. package/dist/reality/geometry/SpatialSphereGeometry.d.ts +16 -0
  143. package/dist/reality/geometry/SpatialSphereGeometry.js +13 -0
  144. package/dist/reality/geometry/SpatialSphereGeometry.js.map +1 -0
  145. package/dist/reality/geometry/index.d.ts +12 -0
  146. package/dist/reality/geometry/index.js +7 -0
  147. package/dist/reality/geometry/index.js.map +1 -0
  148. package/dist/reality/index.d.ts +18 -0
  149. package/dist/reality/index.js +7 -0
  150. package/dist/reality/index.js.map +1 -0
  151. package/dist/reality/material/SpatialMaterial.d.ts +7 -0
  152. package/dist/reality/material/SpatialMaterial.js +13 -0
  153. package/dist/reality/material/SpatialMaterial.js.map +1 -0
  154. package/dist/reality/material/SpatialUnlitMaterial.d.ts +16 -0
  155. package/dist/reality/material/SpatialUnlitMaterial.js +16 -0
  156. package/dist/reality/material/SpatialUnlitMaterial.js.map +1 -0
  157. package/dist/reality/material/index.d.ts +8 -0
  158. package/dist/reality/material/index.js +3 -0
  159. package/dist/reality/material/index.js.map +1 -0
  160. package/dist/reality/realityCreator.d.ts +22 -0
  161. package/dist/reality/realityCreator.js +89 -0
  162. package/dist/reality/realityCreator.js.map +1 -0
  163. package/dist/reality/resource/SpatialModelAsset.d.ts +15 -0
  164. package/dist/reality/resource/SpatialModelAsset.js +12 -0
  165. package/dist/reality/resource/SpatialModelAsset.js.map +1 -0
  166. package/dist/reality/resource/SpatialTextureResource.d.ts +16 -0
  167. package/dist/reality/resource/SpatialTextureResource.js +16 -0
  168. package/dist/reality/resource/SpatialTextureResource.js.map +1 -0
  169. package/dist/reality/resource/index.d.ts +9 -0
  170. package/dist/reality/resource/index.js +3 -0
  171. package/dist/reality/resource/index.js.map +1 -0
  172. package/dist/runtime/WebSpatialRuntimeError.d.ts +10 -0
  173. package/dist/runtime/WebSpatialRuntimeError.js +14 -0
  174. package/dist/runtime/WebSpatialRuntimeError.js.map +1 -0
  175. package/dist/runtime/capability-data.d.ts +12 -0
  176. package/dist/runtime/capability-data.js +134 -0
  177. package/dist/runtime/capability-data.js.map +1 -0
  178. package/dist/runtime/index.d.ts +8 -0
  179. package/dist/runtime/index.js +27 -0
  180. package/dist/runtime/index.js.map +1 -0
  181. package/dist/runtime/jsbAdapterPlatform.d.ts +9 -0
  182. package/dist/runtime/jsbAdapterPlatform.js +38 -0
  183. package/dist/runtime/jsbAdapterPlatform.js.map +1 -0
  184. package/dist/runtime/keys.d.ts +34 -0
  185. package/dist/runtime/keys.js +122 -0
  186. package/dist/runtime/keys.js.map +1 -0
  187. package/dist/runtime/semver.d.ts +8 -0
  188. package/dist/runtime/semver.js +32 -0
  189. package/dist/runtime/semver.js.map +1 -0
  190. package/dist/runtime/supports.d.ts +22 -0
  191. package/dist/runtime/supports.js +78 -0
  192. package/dist/runtime/supports.js.map +1 -0
  193. package/dist/runtime/types.d.ts +12 -0
  194. package/dist/runtime/types.js +1 -0
  195. package/dist/runtime/types.js.map +1 -0
  196. package/dist/runtime/userAgent.d.ts +20 -0
  197. package/dist/runtime/userAgent.js +41 -0
  198. package/dist/runtime/userAgent.js.map +1 -0
  199. package/dist/scene-polyfill.d.ts +18 -0
  200. package/dist/scene-polyfill.js +480 -0
  201. package/dist/scene-polyfill.js.map +1 -0
  202. package/dist/spatial-host.d.ts +13 -0
  203. package/dist/spatial-host.js +18 -0
  204. package/dist/spatial-host.js.map +1 -0
  205. package/dist/spatial-window-polyfill.d.ts +3 -0
  206. package/dist/spatial-window-polyfill.js +155 -0
  207. package/dist/spatial-window-polyfill.js.map +1 -0
  208. package/dist/spatializedElementMotion-_0XWPQCE.d.ts +1009 -0
  209. package/dist/types/animation.d.ts +7 -0
  210. package/dist/types/animation.js +1 -0
  211. package/dist/types/animation.js.map +1 -0
  212. package/dist/types/global.d.ts +38 -0
  213. package/dist/types/global.js +1 -0
  214. package/dist/types/global.js.map +1 -0
  215. package/dist/types/internal.d.ts +7 -0
  216. package/dist/types/internal.js +12 -0
  217. package/dist/types/internal.js.map +1 -0
  218. package/dist/types/motion/index.d.ts +7 -0
  219. package/dist/types/motion/index.js +3 -0
  220. package/dist/types/motion/index.js.map +1 -0
  221. package/dist/types/motion/spatializedElementMotion.d.ts +7 -0
  222. package/dist/types/motion/spatializedElementMotion.js +1 -0
  223. package/dist/types/motion/spatializedElementMotion.js.map +1 -0
  224. package/dist/types/motion/spatializedMotion.d.ts +7 -0
  225. package/dist/types/motion/spatializedMotion.js +16 -0
  226. package/dist/types/motion/spatializedMotion.js.map +1 -0
  227. package/dist/types/motion/spatializedPlayback.d.ts +11 -0
  228. package/dist/types/motion/spatializedPlayback.js +1 -0
  229. package/dist/types/motion/spatializedPlayback.js.map +1 -0
  230. package/dist/types/motion/spatializedVisual.d.ts +35 -0
  231. package/dist/types/motion/spatializedVisual.js +1 -0
  232. package/dist/types/motion/spatializedVisual.js.map +1 -0
  233. package/dist/types/types.d.ts +7 -0
  234. package/dist/types/types.js +117 -0
  235. package/dist/types/types.js.map +1 -0
  236. package/dist/utils.d.ts +44 -0
  237. package/dist/utils.js +86 -0
  238. package/dist/utils.js.map +1 -0
  239. package/package.json +20 -4
  240. package/src/JSBCommand.ts +148 -91
  241. package/src/Spatial.ts +0 -21
  242. package/src/SpatialObject.ts +10 -0
  243. package/src/SpatialScene.ts +1 -5
  244. package/src/SpatialSession.ts +17 -3
  245. package/src/Spatialized2DElement.ts +5 -0
  246. package/src/SpatializedDynamic3DElement.ts +5 -1
  247. package/src/SpatializedElement.ts +29 -0
  248. package/src/SpatializedElementCreator.ts +6 -4
  249. package/src/SpatializedStatic3DElement.test.ts +99 -0
  250. package/src/SpatializedStatic3DElement.ts +141 -4
  251. package/src/WebMsgCommand.ts +50 -0
  252. package/src/coverage-boost.test.ts +258 -316
  253. package/src/index.ts +28 -12
  254. package/src/install-polyfills.ts +38 -0
  255. package/src/jsbcommand.coverage.test.ts +42 -48
  256. package/src/motion/AnimationObject.test.ts +421 -0
  257. package/src/motion/AnimationObject.ts +208 -0
  258. package/src/motion/compute/index.ts +10 -0
  259. package/src/motion/compute/motionPropertyValues.test.ts +55 -0
  260. package/src/motion/compute/motionPropertyValues.ts +70 -0
  261. package/src/motion/compute/normalize.test.ts +99 -0
  262. package/src/motion/compute/normalize.ts +289 -0
  263. package/src/motion/compute/validate.test.ts +229 -0
  264. package/src/motion/compute/validate.ts +156 -0
  265. package/src/motion/index.ts +2 -0
  266. package/src/motion/native/serializeMotionTimeline.test.ts +61 -0
  267. package/src/motion/native/serializeMotionTimeline.ts +27 -0
  268. package/src/platform-adapter/CommandResultUtils.ts +2 -2
  269. package/src/platform-adapter/createPlatformSync.ts +36 -0
  270. package/src/platform-adapter/index.ts +5 -51
  271. package/src/platform-adapter/interface.ts +35 -23
  272. package/src/platform-adapter/pico-os/PicoOSPlatform.ts +156 -59
  273. package/src/platform-adapter/puppeteer/PuppeteerPlatform.ts +37 -11
  274. package/src/platform-adapter/spatialRequestMetadata.test.ts +175 -0
  275. package/src/platform-adapter/spatialRequestMetadata.ts +48 -0
  276. package/src/platform-adapter/spatialSceneQuery.ts +17 -0
  277. package/src/platform-adapter/vision-os/VisionOSPlatform.ts +60 -24
  278. package/src/platform-runtime.ts +13 -0
  279. package/src/reality/Attachment.ts +2 -2
  280. package/src/reality/entity/SpatialEntity.ts +127 -2
  281. package/src/reality/realityCreator.ts +15 -1
  282. package/src/reality/resource/SpatialTextureResource.ts +16 -0
  283. package/src/reality/resource/index.ts +1 -0
  284. package/src/runtime/WebSpatialRuntimeError.ts +16 -0
  285. package/src/runtime/capability-data.ts +213 -0
  286. package/src/runtime/contract-review.test.ts +44 -0
  287. package/src/runtime/index.ts +17 -0
  288. package/src/runtime/jsbAdapterPlatform.test.ts +36 -0
  289. package/src/runtime/jsbAdapterPlatform.ts +51 -0
  290. package/src/runtime/keys.ts +140 -0
  291. package/src/runtime/semver.ts +33 -0
  292. package/src/runtime/supports.test.ts +346 -0
  293. package/src/runtime/supports.ts +112 -0
  294. package/src/runtime/types.ts +11 -0
  295. package/src/runtime/useAnimation.capability.test.ts +275 -0
  296. package/src/runtime/userAgent.ts +64 -0
  297. package/src/scene-polyfill.manifest.test.ts +312 -9
  298. package/src/scene-polyfill.request-metadata.test.ts +39 -0
  299. package/src/scene-polyfill.test.ts +33 -94
  300. package/src/scene-polyfill.ts +125 -92
  301. package/src/spatial-host.ts +25 -0
  302. package/src/spatial-window-polyfill.ts +18 -2
  303. package/src/transform-roundtrip.test.ts +90 -0
  304. package/src/types/animation.ts +224 -0
  305. package/src/types/{global.d.ts → global.ts} +10 -12
  306. package/src/types/motion/index.ts +10 -0
  307. package/src/types/motion/spatializedElementMotion.ts +49 -0
  308. package/src/types/motion/spatializedMotion.ts +147 -0
  309. package/src/types/motion/spatializedPlayback.ts +17 -0
  310. package/src/types/motion/spatializedVisual.ts +24 -0
  311. package/src/types/types.ts +12 -0
  312. package/src/utils.ts +54 -0
  313. package/tsup.config.ts +61 -36
  314. package/vitest.config.ts +5 -1
  315. package/dist/iife/index.d.ts +0 -1101
  316. package/dist/iife/index.global.js +0 -75
  317. package/dist/iife/index.global.js.map +0 -1
  318. package/src/platform-adapter/android/AndroidPlatform.ts +0 -133
  319. package/src/platform-adapter/ssr/SSRPlatform.ts +0 -43
  320. /package/src/{ssr-polyfill.ts → isSSREnv.ts} +0 -0
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Versioned capability rows transcribed from the product matrix (`capability-matrix.template.md`).
3
+ * visionOS **WSAppShell/1.5.0** & **1.6.0** & **1.7.0** & **1.8.0**; picoOS **PicoWebApp/0.1.1** & **0.1.2** & **0.2.2** & **0.3.1** & **0.4.90** — see matrix in OpenSpec / product docs.
4
+ *
5
+ * **picoOS** rows use dedicated builders (alpha2.0 / alpha2.1 subtokens); visionOS rows are separate.
6
+ */
7
+ import { SUB_TOKENS_BY_NAME, TOP_LEVEL_KEYS } from './keys'
8
+
9
+ export type CapabilityVersionRow = {
10
+ /** Semver string from `WSAppShell` / `PicoWebApp` (see `review.md` §4). */
11
+ version: string
12
+ /** Top-level keys and `name:subToken` compound keys. */
13
+ flags: Record<string, boolean>
14
+ }
15
+
16
+ function baseTrueFlags(): Record<string, boolean> {
17
+ const flags: Record<string, boolean> = {}
18
+ for (const k of TOP_LEVEL_KEYS) {
19
+ flags[k] = true
20
+ }
21
+ for (const [name, toks] of Object.entries(SUB_TOKENS_BY_NAME)) {
22
+ for (const t of toks) {
23
+ flags[`${name}:${t}`] = true
24
+ }
25
+ }
26
+ return flags
27
+ }
28
+
29
+ /**
30
+ * visionOS **WSAppShell/1.5.0**.
31
+ * Model: only `ready`, `currentSrc`, `entityTransform` among tracked sub-tokens are Y; SpatialRotateEvent:constrainedToAxis Y.
32
+ */
33
+ function matrixVision_1_5_0_Flags(): Record<string, boolean> {
34
+ const flags = baseTrueFlags()
35
+ const modelNo = [
36
+ 'autoplay',
37
+ 'loop',
38
+ 'stagemode',
39
+ 'poster',
40
+ 'loading',
41
+ 'source',
42
+ 'paused',
43
+ 'duration',
44
+ 'playbackRate',
45
+ 'play',
46
+ 'pause',
47
+ 'currentTime',
48
+ ] as const
49
+ for (const t of modelNo) {
50
+ flags[`Model:${t}`] = false
51
+ }
52
+ flags['SpatialRotateEvent:constrainedToAxis'] = true
53
+ // Container useAnimation is not supported until WSAppShell/1.8.0.
54
+ flags['useAnimation'] = false
55
+ // Placement-shaped attachment protocol lands in picoOS PicoWebApp/0.4.90
56
+ // (OTA0); no visionOS shell decodes it yet.
57
+ flags['AttachmentEntity:placement'] = false
58
+ return flags
59
+ }
60
+
61
+ /**
62
+ * visionOS **WSAppShell/1.6.0** — WebSpatial April / playback expansion (see product matrix).
63
+ * Model: `stagemode`, `poster`, `loading`, `currentTime` remain N; rest of tracked Model sub-tokens Y.
64
+ */
65
+ function matrixVision_1_6_0_Flags(): Record<string, boolean> {
66
+ const flags = baseTrueFlags()
67
+ for (const t of ['stagemode', 'poster', 'loading', 'currentTime'] as const) {
68
+ flags[`Model:${t}`] = false
69
+ }
70
+ flags['SpatialRotateEvent:constrainedToAxis'] = true
71
+ // Container useAnimation is not supported until WSAppShell/1.8.0.
72
+ flags['useAnimation'] = false
73
+ // Placement-shaped attachment protocol lands in picoOS PicoWebApp/0.4.90
74
+ // (OTA0); no visionOS shell decodes it yet.
75
+ flags['AttachmentEntity:placement'] = false
76
+ return flags
77
+ }
78
+
79
+ /**
80
+ * visionOS **WSAppShell/1.7.0** — entity transform animation support.
81
+ * Container `useAnimation` remains unavailable in this row.
82
+ */
83
+ function matrixVision_1_7_0_Flags(): Record<string, boolean> {
84
+ const flags = matrixVision_1_6_0_Flags()
85
+ flags['Model:currentTime'] = true
86
+ flags['Model:loading'] = true
87
+ flags['Model:poster'] = true
88
+ return flags
89
+ }
90
+
91
+ /**
92
+ * visionOS **WSAppShell/1.8.0**.
93
+ */
94
+ function matrixVision_1_8_0_Flags(): Record<string, boolean> {
95
+ const flags = matrixVision_1_7_0_Flags()
96
+ flags['useAnimation'] = true
97
+ return flags
98
+ }
99
+
100
+ /**
101
+ * picoOS **PicoWebApp/0.1.1** — alpha2.0 baseline (product matrix).
102
+ * WindowScene / VolumeScene / Material subtokens Y; Model sub-tokens per matrix; **`xrInnerDepth` / `xrOuterDepth` N**.
103
+ */
104
+ function matrixPico_0_1_1_Flags(): Record<string, boolean> {
105
+ const flags = matrixVision_1_5_0_Flags()
106
+ flags.xrInnerDepth = false
107
+ flags.xrOuterDepth = false
108
+ return flags
109
+ }
110
+
111
+ /**
112
+ * picoOS **PicoWebApp/0.1.2** — beta2.0 playback expansion (product matrix).
113
+ * **`xrInnerDepth` / `xrOuterDepth` N** (same as 0.1.1).
114
+ */
115
+ function matrixPico_0_1_2_Flags(): Record<string, boolean> {
116
+ const flags = matrixVision_1_6_0_Flags()
117
+ flags.xrInnerDepth = false
118
+ flags.xrOuterDepth = false
119
+ flags['Model:currentTime'] = true
120
+ flags['Model:poster'] = true
121
+ return flags
122
+ }
123
+
124
+ /**
125
+ * picoOS **PicoWebApp/0.2.2** — entity transform animation support.
126
+ * Container `useAnimation` remains unavailable in this row.
127
+ */
128
+ function matrixPico_0_2_2_Flags(): Record<string, boolean> {
129
+ const flags = matrixPico_0_1_2_Flags()
130
+ return flags
131
+ }
132
+
133
+ /**
134
+ * picoOS **PicoWebApp/0.3.1** — beta2.1
135
+ */
136
+ function matrixPico_0_3_1_Flags(): Record<string, boolean> {
137
+ const flags = matrixPico_0_2_2_Flags()
138
+ flags['Model:loading'] = true
139
+ return flags
140
+ }
141
+
142
+ /**
143
+ * picoOS **PicoWebApp/0.4.90** — OTA0 container animation support.
144
+ */
145
+ function matrixPico_0_4_90_Flags(): Record<string, boolean> {
146
+ const flags = matrixPico_0_3_1_Flags()
147
+ flags['useAnimation'] = true
148
+ flags['AttachmentEntity:placement'] = true
149
+ return flags
150
+ }
151
+
152
+ function visionOsRow_1_5_0(): CapabilityVersionRow {
153
+ return { version: '1.5.0', flags: matrixVision_1_5_0_Flags() }
154
+ }
155
+
156
+ function visionOsRow_1_6_0(): CapabilityVersionRow {
157
+ return { version: '1.6.0', flags: matrixVision_1_6_0_Flags() }
158
+ }
159
+
160
+ function visionOsRow_1_7_0(): CapabilityVersionRow {
161
+ return { version: '1.7.0', flags: matrixVision_1_7_0_Flags() }
162
+ }
163
+
164
+ /**
165
+ * Build the capability row for visionOS **WSAppShell/1.8.0**.
166
+ */
167
+ function visionOsRow_1_8_0(): CapabilityVersionRow {
168
+ return { version: '1.8.0', flags: matrixVision_1_8_0_Flags() }
169
+ }
170
+
171
+ function picoOsRow_0_1_1(): CapabilityVersionRow {
172
+ return { version: '0.1.1', flags: matrixPico_0_1_1_Flags() }
173
+ }
174
+
175
+ // Pico OS 6.0 Beta 2.0
176
+ function picoOsRow_0_1_2(): CapabilityVersionRow {
177
+ return { version: '0.1.2', flags: matrixPico_0_1_2_Flags() }
178
+ }
179
+
180
+ function picoOsRow_0_2_2(): CapabilityVersionRow {
181
+ return { version: '0.2.2', flags: matrixPico_0_2_2_Flags() }
182
+ }
183
+
184
+ // Pico OS 6.0 Beta 2.1
185
+ function picoOsRow_0_3_1(): CapabilityVersionRow {
186
+ return { version: '0.3.1', flags: matrixPico_0_3_1_Flags() }
187
+ }
188
+
189
+ /**
190
+ * Build the capability row for picoOS **PicoWebApp/0.4.90** OTA0.
191
+ */
192
+ function picoOsRow_0_4_90(): CapabilityVersionRow {
193
+ return { version: '0.4.90', flags: matrixPico_0_4_90_Flags() }
194
+ }
195
+
196
+ export const CAPABILITY_TABLE: {
197
+ visionos: CapabilityVersionRow[]
198
+ picoos: CapabilityVersionRow[]
199
+ } = {
200
+ visionos: [
201
+ visionOsRow_1_5_0(),
202
+ visionOsRow_1_6_0(),
203
+ visionOsRow_1_7_0(),
204
+ visionOsRow_1_8_0(),
205
+ ],
206
+ picoos: [
207
+ picoOsRow_0_1_1(),
208
+ picoOsRow_0_1_2(),
209
+ picoOsRow_0_2_2(),
210
+ picoOsRow_0_3_1(),
211
+ picoOsRow_0_4_90(),
212
+ ],
213
+ }
@@ -0,0 +1,44 @@
1
+ import { describe, expect, test, vi, beforeEach } from 'vitest'
2
+ import { ELEMENT_DOM_DEPTH_KEYS, WINDOW_DOM_DEPTH_KEYS } from './keys'
3
+
4
+ describe('OpenSpec review.md §3.5.1 — Window DOM depth (xrInnerDepth / xrOuterDepth)', () => {
5
+ beforeEach(() => {
6
+ vi.resetModules()
7
+ })
8
+
9
+ test('plain browser UA: unsupported keys absent from window surface', async () => {
10
+ vi.stubGlobal('navigator', {
11
+ userAgent:
12
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
13
+ } as Navigator)
14
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
15
+ resetRuntimeCacheForTests()
16
+
17
+ for (const key of WINDOW_DOM_DEPTH_KEYS) {
18
+ expect(supports(key)).toBe(false)
19
+ expect(key in window).toBe(false)
20
+ expect(Object.prototype.hasOwnProperty.call(window, key)).toBe(false)
21
+ }
22
+ })
23
+ })
24
+
25
+ describe('OpenSpec review.md §3.5.2 — Element depth keys must not use Window surface', () => {
26
+ beforeEach(() => {
27
+ vi.resetModules()
28
+ })
29
+
30
+ test('plain browser: xrClientDepth / xrOffsetBack are not on window (live on spatialized ref)', async () => {
31
+ vi.stubGlobal('navigator', {
32
+ userAgent:
33
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
34
+ } as Navigator)
35
+ const { supports, resetRuntimeCacheForTests } = await import('./supports')
36
+ resetRuntimeCacheForTests()
37
+
38
+ for (const key of ELEMENT_DOM_DEPTH_KEYS) {
39
+ expect(supports(key)).toBe(false)
40
+ expect(key in window).toBe(false)
41
+ expect(Object.prototype.hasOwnProperty.call(window, key)).toBe(false)
42
+ }
43
+ })
44
+ })
@@ -0,0 +1,17 @@
1
+ export type { WebSpatialRuntimeSnapshot, WebSpatialRuntimeType } from './types'
2
+ export { WebSpatialRuntimeError } from './WebSpatialRuntimeError'
3
+ export {
4
+ supports,
5
+ getRuntime,
6
+ resetRuntimeCacheForTests,
7
+ VISIONOS_DEBUG_SHELL_VERSION_PLACEHOLDER,
8
+ } from './supports'
9
+ export { compareSemver, parseSemverOrNull } from './semver'
10
+ export { computeRuntimeFromUserAgent, parseShellToken } from './userAgent'
11
+ export {
12
+ resolveJsbAdapterPlatform,
13
+ type JsbAdapterPlatformKind,
14
+ } from './jsbAdapterPlatform'
15
+ export type { CapabilityVersionRow } from './capability-data'
16
+ export { CAPABILITY_TABLE } from './capability-data'
17
+ export type { CapabilityKey } from './keys'
@@ -0,0 +1,36 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { resolveJsbAdapterPlatform } from './jsbAdapterPlatform'
3
+
4
+ describe('resolveJsbAdapterPlatform', () => {
5
+ test('Puppeteer UA maps to puppeteer', () => {
6
+ expect(
7
+ resolveJsbAdapterPlatform(
8
+ 'Mozilla/5.0 Puppeteer Chrome/120 WSAppShell/1.5.0 WebSpatial/1.5.0',
9
+ ),
10
+ ).toBe('puppeteer')
11
+ })
12
+
13
+ test('PicoWebApp with WebSpatial > 0.0.1 maps to picoos', () => {
14
+ expect(
15
+ resolveJsbAdapterPlatform(
16
+ 'Mozilla/5.0 PicoWebApp/0.1.1 WebSpatial/1.5.0',
17
+ ),
18
+ ).toBe('picoos')
19
+ })
20
+
21
+ test('Linux without Pico pico branch maps to visionos', () => {
22
+ expect(
23
+ resolveJsbAdapterPlatform(
24
+ 'Mozilla/5.0 (X11; Linux x86_64) WSAppShell/1.5.0 WebSpatial/1.5.0',
25
+ ),
26
+ ).toBe('visionos')
27
+ })
28
+
29
+ test('Mac visionOS-class UA maps to visionos', () => {
30
+ expect(
31
+ resolveJsbAdapterPlatform(
32
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) WSAppShell/1.5.0 WebSpatial/1.5.0',
33
+ ),
34
+ ).toBe('visionos')
35
+ })
36
+ })
@@ -0,0 +1,51 @@
1
+ import { computeRuntimeFromUserAgent } from './userAgent'
2
+
3
+ function getWebSpatialVersion(ua: string): number[] | null {
4
+ const match = ua.match(/WebSpatial\/(\d+)\.(\d+)\.(\d+)/)
5
+ if (!match) {
6
+ return null
7
+ }
8
+ return [Number(match[1]), Number(match[2]), Number(match[3])]
9
+ }
10
+
11
+ function isVersionGreater(a: number[] | null, b: number[]): boolean {
12
+ if (!a) {
13
+ return false
14
+ }
15
+ for (let index = 0; index < 3; index += 1) {
16
+ const diff = a[index] - b[index]
17
+ if (diff > 0) {
18
+ return true
19
+ }
20
+ if (diff < 0) {
21
+ return false
22
+ }
23
+ }
24
+ return false
25
+ }
26
+
27
+ /**
28
+ * Which native JSB / protocol adapter to load in the browser.
29
+ * Derived from {@link computeRuntimeFromUserAgent} plus legacy fallbacks
30
+ * (Pico WebSpatial semver gate; otherwise default visionOS shell).
31
+ */
32
+ export type JsbAdapterPlatformKind = 'puppeteer' | 'picoos' | 'visionos'
33
+
34
+ export function resolveJsbAdapterPlatform(
35
+ userAgent: string,
36
+ ): JsbAdapterPlatformKind {
37
+ const rt = computeRuntimeFromUserAgent(userAgent)
38
+ if (rt.type === 'puppeteer') {
39
+ return 'puppeteer'
40
+ }
41
+
42
+ const webSpatialVersion = getWebSpatialVersion(userAgent)
43
+ if (
44
+ userAgent.includes('PicoWebApp') &&
45
+ isVersionGreater(webSpatialVersion, [0, 0, 1])
46
+ ) {
47
+ return 'picoos'
48
+ }
49
+
50
+ return 'visionos'
51
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Canonical `supports(name)` key registry (OpenSpec `review.md` §3).
3
+ * Aliases are normalized before lookup (see `normalizeCapabilityName`).
4
+ *
5
+ * @internal SDK contract data — not part of the public `@webspatial/react-sdk`
6
+ * surface. Import via `@webspatial/core-sdk/runtime/keys` only for SDK demos,
7
+ * contract tests, and capability-matrix tooling.
8
+ */
9
+
10
+ export const COMPONENT_KEYS = [
11
+ 'Model',
12
+ 'Reality',
13
+ 'Entity',
14
+ 'BoxEntity',
15
+ 'SphereEntity',
16
+ 'ConeEntity',
17
+ 'CylinderEntity',
18
+ 'PlaneEntity',
19
+ 'SceneGraph',
20
+ 'ModelAsset',
21
+ 'ModelEntity',
22
+ 'UnlitMaterial',
23
+ 'Material',
24
+ 'AttachmentAsset',
25
+ 'AttachmentEntity',
26
+ ] as const
27
+
28
+ export const CSS_KEYS = [
29
+ '-xr-background-material',
30
+ '-xr-back',
31
+ '-xr-depth',
32
+ '-xr-transform',
33
+ ] as const
34
+
35
+ export const GESTURE_KEYS = [
36
+ 'SpatialTapEvent',
37
+ 'SpatialDragStartEvent',
38
+ 'SpatialDragEvent',
39
+ 'SpatialDragEndEvent',
40
+ 'SpatialRotateEvent',
41
+ 'SpatialRotateEndEvent',
42
+ 'SpatialMagnifyEvent',
43
+ 'SpatialMagnifyEndEvent',
44
+ ] as const
45
+
46
+ export const ANIMATION_KEYS = ['useAnimation'] as const
47
+
48
+ export const JS_SCENE_KEYS = [
49
+ 'useMetrics',
50
+ 'convertCoordinate',
51
+ 'initScene',
52
+ 'WindowScene',
53
+ 'VolumeScene',
54
+ ] as const
55
+
56
+ /**
57
+ * Spatialized container `ref` readbacks (`HTMLElement` / React `useDomProxy` Proxy).
58
+ * See `global.d.ts` (`HTMLElement`) and `useDomProxy.ts` (`has` / `get` traps).
59
+ */
60
+ export const ELEMENT_DOM_DEPTH_KEYS = ['xrClientDepth', 'xrOffsetBack'] as const
61
+
62
+ /**
63
+ * Scene / global readbacks on `Window` (`global.d.ts` → `Window`).
64
+ */
65
+ export const WINDOW_DOM_DEPTH_KEYS = ['xrInnerDepth', 'xrOuterDepth'] as const
66
+
67
+ export const DOM_DEPTH_KEYS = [
68
+ ...ELEMENT_DOM_DEPTH_KEYS,
69
+ ...WINDOW_DOM_DEPTH_KEYS,
70
+ ] as const
71
+
72
+ /** Top-level names accepted by `supports(name)` (canonical keys after alias normalization). */
73
+ export const TOP_LEVEL_KEYS = [
74
+ ...COMPONENT_KEYS,
75
+ ...CSS_KEYS,
76
+ ...GESTURE_KEYS,
77
+ ...ANIMATION_KEYS,
78
+ ...JS_SCENE_KEYS,
79
+ ...DOM_DEPTH_KEYS,
80
+ ] as const
81
+
82
+ /** Union of documented capability keys; unknown strings may still be passed to `supports` (returns `false`). */
83
+ export type CapabilityKey = (typeof TOP_LEVEL_KEYS)[number]
84
+
85
+ const ALIAS_TO_CANONICAL: Record<string, string> = {
86
+ Box: 'BoxEntity',
87
+ Sphere: 'SphereEntity',
88
+ Cone: 'ConeEntity',
89
+ Cylinder: 'CylinderEntity',
90
+ Plane: 'PlaneEntity',
91
+ World: 'SceneGraph',
92
+ }
93
+
94
+ export function normalizeCapabilityName(name: string): string {
95
+ return ALIAS_TO_CANONICAL[name] ?? name
96
+ }
97
+
98
+ /** Known sub-tokens per canonical top-level `name` (AND semantics). */
99
+ export const SUB_TOKENS_BY_NAME: Readonly<Record<string, readonly string[]>> = {
100
+ Material: ['unlit'],
101
+ WindowScene: ['defaultSize', 'resizability'],
102
+ VolumeScene: [
103
+ 'defaultSize',
104
+ 'resizability',
105
+ 'worldScaling',
106
+ 'worldAlignment',
107
+ 'baseplateVisibility',
108
+ ],
109
+ SpatialRotateEvent: ['constrainedToAxis'],
110
+ // Placement-shaped attachment JSB protocol (placementId + Vec3 transform +
111
+ // meter width/height). Runtimes without it take the legacy payload
112
+ // (parentEntityId + tuple position + point size).
113
+ AttachmentEntity: ['placement'],
114
+ Model: [
115
+ 'autoplay',
116
+ 'loop',
117
+ 'stagemode',
118
+ 'poster',
119
+ 'loading',
120
+ 'source',
121
+ 'ready',
122
+ 'currentSrc',
123
+ 'entityTransform',
124
+ 'paused',
125
+ 'duration',
126
+ 'playbackRate',
127
+ 'play',
128
+ 'pause',
129
+ 'currentTime',
130
+ ],
131
+ }
132
+
133
+ export function isKnownTopLevel(name: string): boolean {
134
+ return (TOP_LEVEL_KEYS as readonly string[]).includes(name)
135
+ }
136
+
137
+ export function isKnownSubToken(name: string, token: string): boolean {
138
+ const allowed = SUB_TOKENS_BY_NAME[name]
139
+ return allowed !== undefined && allowed.includes(token)
140
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Minimal semver compare for capability table rows (`major.minor.patch`).
3
+ * Returns negative if a < b, zero if equal, positive if a > b.
4
+ */
5
+ export function compareSemver(a: string, b: string): number {
6
+ const pa = parseSemverParts(a)
7
+ const pb = parseSemverParts(b)
8
+ if (!pa || !pb) {
9
+ return String(a).localeCompare(String(b))
10
+ }
11
+ const len = Math.max(pa.length, pb.length)
12
+ for (let i = 0; i < len; i++) {
13
+ const da = pa[i] ?? 0
14
+ const db = pb[i] ?? 0
15
+ if (da !== db) return da - db
16
+ }
17
+ return 0
18
+ }
19
+
20
+ function parseSemverParts(v: string): number[] | null {
21
+ const m = /^(\d+)(?:\.(\d+)(?:\.(\d+))?)?/.exec(v.trim())
22
+ if (!m) return null
23
+ const major = Number(m[1])
24
+ const minor = m[2] !== undefined ? Number(m[2]) : 0
25
+ const patch = m[3] !== undefined ? Number(m[3]) : 0
26
+ if ([major, minor, patch].some(n => Number.isNaN(n))) return null
27
+ return [major, minor, patch]
28
+ }
29
+
30
+ export function parseSemverOrNull(v: string): string | null {
31
+ const m = /^(\d+(?:\.\d+){0,2})/.exec(v.trim())
32
+ return m ? m[1] : null
33
+ }