@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,208 @@
1
+ import {
2
+ ControlSpatializedElementAnimationJSBCommand,
3
+ CreateSpatializedElementAnimationJSBCommand,
4
+ } from '../JSBCommand'
5
+ import { SpatialObject } from '../SpatialObject'
6
+ import { SpatialWebEvent } from '../SpatialWebEvent'
7
+ import type {
8
+ ControlSpatializedElementAnimationCommand,
9
+ SpatialAnimationStateChangedDetail,
10
+ SpatialAnimationStateChangedMsg,
11
+ } from '../types/motion/spatializedElementMotion'
12
+ import type { SpatializedPlaybackError } from '../types/motion/spatializedPlayback'
13
+ import type { SpatializedVisualValues } from '../types/motion/spatializedVisual'
14
+ import type {
15
+ SpatializedMotionTimeline,
16
+ SpatializedPlaybackApi,
17
+ SpatializedMotionPlayState,
18
+ } from '../types/motion/spatializedMotion'
19
+
20
+ export interface AnimationObjectCreateOptions {
21
+ elementId: string
22
+ timeline: SpatializedMotionTimeline
23
+ }
24
+
25
+ export interface AnimationObjectCallbacks {
26
+ onStart?: () => void
27
+ onComplete?: (values: SpatializedVisualValues) => void
28
+ onStop?: (values: SpatializedVisualValues) => void
29
+ onReset?: (values: SpatializedVisualValues) => void
30
+ onError?: (error: SpatializedPlaybackError) => void
31
+ onValuesChange?: (values: SpatializedVisualValues) => void
32
+ onStateChange?: () => void
33
+ }
34
+
35
+ export class AnimationObject
36
+ extends SpatialObject
37
+ implements SpatializedPlaybackApi
38
+ {
39
+ readonly elementId: string
40
+ readonly timeline: SpatializedMotionTimeline
41
+
42
+ private callbacks: AnimationObjectCallbacks = {}
43
+ private _playState: SpatializedMotionPlayState = 'idle'
44
+ private _finished = false
45
+ private started = false
46
+
47
+ constructor(id: string, options: AnimationObjectCreateOptions) {
48
+ super(id)
49
+ this.elementId = options.elementId
50
+ this.timeline = options.timeline
51
+
52
+ SpatialWebEvent.addEventReceiver(id, data => this.onReceiveEvent(data))
53
+ }
54
+
55
+ static async create(options: AnimationObjectCreateOptions) {
56
+ const ret = await new CreateSpatializedElementAnimationJSBCommand({
57
+ elementId: options.elementId,
58
+ timeline: options.timeline,
59
+ }).execute()
60
+ if (!ret.success) {
61
+ throw new Error(
62
+ ret.errorMessage ?? 'CreateSpatializedElementAnimation command failed',
63
+ )
64
+ }
65
+
66
+ const data = ret.data as { id?: string } | undefined
67
+ const id = data?.id
68
+ if (!id) {
69
+ throw new Error('CreateSpatializedElementAnimation did not return an id')
70
+ }
71
+
72
+ return new AnimationObject(id, options)
73
+ }
74
+
75
+ setCallbacks(callbacks: AnimationObjectCallbacks): void {
76
+ this.callbacks = callbacks
77
+ }
78
+
79
+ get playState() {
80
+ return this._playState
81
+ }
82
+
83
+ get isAnimating() {
84
+ return this._playState === 'running' || this._playState === 'queued'
85
+ }
86
+
87
+ get isPaused() {
88
+ return this._playState === 'paused'
89
+ }
90
+
91
+ get finished() {
92
+ return this._finished
93
+ }
94
+
95
+ play(): Promise<void> {
96
+ return this.control('play')
97
+ }
98
+
99
+ pause(): Promise<void> {
100
+ return this.control('pause')
101
+ }
102
+
103
+ stop(): Promise<void> {
104
+ return this.control('stop')
105
+ }
106
+
107
+ reset(): Promise<void> {
108
+ return this.control('reset')
109
+ }
110
+
111
+ finish(): Promise<void> {
112
+ return this.control('finish')
113
+ }
114
+
115
+ protected override onDestroy(): void {
116
+ SpatialWebEvent.removeEventReceiver(this.id)
117
+ }
118
+
119
+ private async control(
120
+ type: ControlSpatializedElementAnimationCommand['type'],
121
+ ): Promise<void> {
122
+ if (this.isDestroyed) return
123
+
124
+ const ret = await new ControlSpatializedElementAnimationJSBCommand({
125
+ animationId: this.id,
126
+ type,
127
+ }).execute()
128
+
129
+ if (!ret.success) {
130
+ throw new Error(
131
+ ret.errorMessage ??
132
+ `ControlSpatializedElementAnimation(${type}) command failed`,
133
+ )
134
+ }
135
+ }
136
+
137
+ onReceiveEvent(data: SpatialAnimationStateChangedMsg | { detail?: unknown }) {
138
+ const detail = data?.detail ?? data
139
+ if (!this.isSpatialAnimationStateChangedDetail(detail)) return
140
+ if (detail.animationId !== this.id) return
141
+
142
+ this._playState = detail.playState
143
+ this._finished = detail.finished
144
+
145
+ if (detail.values) {
146
+ this.callbacks.onValuesChange?.(detail.values)
147
+ }
148
+ if (detail.action !== 'start') {
149
+ this.callbacks.onStateChange?.()
150
+ }
151
+
152
+ if (detail.error) {
153
+ this.started = false
154
+ // Native currently emits asynchronous errors only when play cannot acquire the ownership mask.
155
+ this.callbacks.onError?.({
156
+ command: 'play',
157
+ code: detail.error.code,
158
+ reason: detail.error.message,
159
+ })
160
+ return
161
+ }
162
+
163
+ if (detail.action === 'start') {
164
+ if (!this.started) {
165
+ this.started = true
166
+ this.callbacks.onStart?.()
167
+ }
168
+ return
169
+ }
170
+
171
+ if (detail.action === 'complete' || detail.action === 'finish') {
172
+ this.started = false
173
+ this.callbacks.onComplete?.(detail.values ?? {})
174
+ return
175
+ }
176
+
177
+ if (detail.action === 'stop') {
178
+ this.started = false
179
+ this.callbacks.onStop?.(detail.values ?? {})
180
+ return
181
+ }
182
+
183
+ if (detail.action === 'reset') {
184
+ this.started = false
185
+ this.callbacks.onReset?.(detail.values ?? {})
186
+ return
187
+ }
188
+
189
+ if (detail.action === 'destroy') {
190
+ this.started = false
191
+ this.isDestroyed = true
192
+ this.onDestroy()
193
+ }
194
+ }
195
+
196
+ private isSpatialAnimationStateChangedDetail(
197
+ detail: unknown,
198
+ ): detail is SpatialAnimationStateChangedDetail {
199
+ if (!detail || typeof detail !== 'object') return false
200
+ const candidate = detail as Partial<SpatialAnimationStateChangedDetail>
201
+ return (
202
+ typeof candidate.animationId === 'string' &&
203
+ typeof candidate.action === 'string' &&
204
+ typeof candidate.playState === 'string' &&
205
+ typeof candidate.finished === 'boolean'
206
+ )
207
+ }
208
+ }
@@ -0,0 +1,10 @@
1
+ export { setMotionPropertyValue } from './motionPropertyValues'
2
+ export {
3
+ validateNormalizedMotionConfig,
4
+ validateSpatializedMotionConfig,
5
+ } from './validate'
6
+ export {
7
+ desugarTimelineConfig,
8
+ normalizeMotionConfig,
9
+ segmentConfigToMotionConfig,
10
+ } from './normalize'
@@ -0,0 +1,55 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import type { SpatializedMotionProperty } from '../../types/motion/spatializedMotion'
3
+ import { setMotionPropertyValue } from './motionPropertyValues'
4
+
5
+ describe('setMotionPropertyValue', () => {
6
+ test('writes opacity', () => {
7
+ const values = {}
8
+
9
+ setMotionPropertyValue(values, 'opacity', 0.5)
10
+
11
+ expect(values).toEqual({ opacity: 0.5 })
12
+ })
13
+
14
+ test.each([
15
+ ['transform.translate.x', { transform: { translate: { x: 1 } } }],
16
+ ['transform.translate.y', { transform: { translate: { y: 2 } } }],
17
+ ['transform.translate.z', { transform: { translate: { z: 3 } } }],
18
+ ['transform.rotate.x', { transform: { rotate: { x: 4 } } }],
19
+ ['transform.rotate.y', { transform: { rotate: { y: 5 } } }],
20
+ ['transform.rotate.z', { transform: { rotate: { z: 6 } } }],
21
+ ['transform.scale.x', { transform: { scale: { x: 7 } } }],
22
+ ['transform.scale.y', { transform: { scale: { y: 8 } } }],
23
+ ['transform.scale.z', { transform: { scale: { z: 9 } } }],
24
+ ] as const)('writes %s', (motionProperty, expected) => {
25
+ const values = {}
26
+ const sampledValue = Object.values(
27
+ Object.values(expected.transform ?? {})[0] ?? {},
28
+ )[0] as number
29
+
30
+ setMotionPropertyValue(
31
+ values,
32
+ motionProperty as SpatializedMotionProperty,
33
+ sampledValue,
34
+ )
35
+
36
+ expect(values).toEqual(expected)
37
+ })
38
+
39
+ test('preserves existing transform groups while writing another property', () => {
40
+ const values = {
41
+ transform: {
42
+ translate: { x: 10 },
43
+ },
44
+ }
45
+
46
+ setMotionPropertyValue(values, 'transform.rotate.y', 20)
47
+
48
+ expect(values).toEqual({
49
+ transform: {
50
+ translate: { x: 10 },
51
+ rotate: { y: 20 },
52
+ },
53
+ })
54
+ })
55
+ })
@@ -0,0 +1,70 @@
1
+ import type { SpatializedVisualValues } from '../../types/motion/spatializedVisual'
2
+ import type { SpatializedMotionProperty } from '../../types/motion/spatializedMotion'
3
+
4
+ function getTranslate(
5
+ visualValues: SpatializedVisualValues,
6
+ ): NonNullable<NonNullable<SpatializedVisualValues['transform']>['translate']> {
7
+ const transform = (visualValues.transform ??= {})
8
+ return (transform.translate ??= {})
9
+ }
10
+
11
+ function getRotate(
12
+ visualValues: SpatializedVisualValues,
13
+ ): NonNullable<NonNullable<SpatializedVisualValues['transform']>['rotate']> {
14
+ const transform = (visualValues.transform ??= {})
15
+ return (transform.rotate ??= {})
16
+ }
17
+
18
+ function getScale(
19
+ visualValues: SpatializedVisualValues,
20
+ ): NonNullable<NonNullable<SpatializedVisualValues['transform']>['scale']> {
21
+ const transform = (visualValues.transform ??= {})
22
+ return (transform.scale ??= {})
23
+ }
24
+
25
+ /**
26
+ * Writes a sampled numeric track value into the corresponding
27
+ * SpatializedVisualValues field.
28
+ *
29
+ * @param visualValues Visual value object being populated for the sampled time.
30
+ * @param motionProperty Motion property path for the sampled track.
31
+ * @param sampledValue Numeric value sampled from the track at the current time.
32
+ */
33
+ export function setMotionPropertyValue(
34
+ visualValues: SpatializedVisualValues,
35
+ motionProperty: SpatializedMotionProperty,
36
+ sampledValue: number,
37
+ ): void {
38
+ switch (motionProperty) {
39
+ case 'opacity':
40
+ visualValues.opacity = sampledValue
41
+ return
42
+ case 'transform.translate.x':
43
+ getTranslate(visualValues).x = sampledValue
44
+ return
45
+ case 'transform.translate.y':
46
+ getTranslate(visualValues).y = sampledValue
47
+ return
48
+ case 'transform.translate.z':
49
+ getTranslate(visualValues).z = sampledValue
50
+ return
51
+ case 'transform.rotate.x':
52
+ getRotate(visualValues).x = sampledValue
53
+ return
54
+ case 'transform.rotate.y':
55
+ getRotate(visualValues).y = sampledValue
56
+ return
57
+ case 'transform.rotate.z':
58
+ getRotate(visualValues).z = sampledValue
59
+ return
60
+ case 'transform.scale.x':
61
+ getScale(visualValues).x = sampledValue
62
+ return
63
+ case 'transform.scale.y':
64
+ getScale(visualValues).y = sampledValue
65
+ return
66
+ case 'transform.scale.z':
67
+ getScale(visualValues).z = sampledValue
68
+ return
69
+ }
70
+ }
@@ -0,0 +1,99 @@
1
+ import { describe, expect, test, vi } from 'vitest'
2
+ import { normalizeMotionConfig } from './normalize'
3
+
4
+ describe('normalizeMotionConfig', () => {
5
+ test('normalizes mixed timeline entries into numeric tracks', () => {
6
+ expect(
7
+ normalizeMotionConfig({
8
+ duration: 2,
9
+ timeline: {
10
+ from: { opacity: 0, transform: { translate: { x: 0 } } },
11
+ '50%': { opacity: 0.5 },
12
+ to: { opacity: 1, transform: { translate: { x: 10 } } },
13
+ },
14
+ }),
15
+ ).toMatchObject({
16
+ duration: 2,
17
+ tracks: [
18
+ {
19
+ property: 'opacity',
20
+ keyframes: [
21
+ { at: 0, value: 0 },
22
+ { at: 1, value: 0.5 },
23
+ { at: 2, value: 1 },
24
+ ],
25
+ },
26
+ {
27
+ property: 'transform.translate.x',
28
+ keyframes: [
29
+ { at: 0, value: 0 },
30
+ { at: 2, value: 10 },
31
+ ],
32
+ },
33
+ ],
34
+ })
35
+ })
36
+
37
+ test('uses only timeline values when top-level boundaries are present', () => {
38
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
39
+ expect(
40
+ normalizeMotionConfig({
41
+ from: { opacity: 0.25 },
42
+ to: { opacity: 0.75 },
43
+ timeline: {
44
+ from: { opacity: 0 },
45
+ to: { opacity: 1 },
46
+ },
47
+ }),
48
+ ).toMatchObject({
49
+ duration: 0.3,
50
+ tracks: [
51
+ {
52
+ property: 'opacity',
53
+ keyframes: [
54
+ { at: 0, value: 0 },
55
+ { at: 0.3, value: 1 },
56
+ ],
57
+ },
58
+ ],
59
+ })
60
+ expect(warnSpy).toHaveBeenCalledWith(
61
+ expect.stringContaining('top-level from/to are ignored'),
62
+ )
63
+ warnSpy.mockRestore()
64
+ })
65
+
66
+ test('preserves sparse property keyframe ranges', () => {
67
+ expect(
68
+ normalizeMotionConfig({
69
+ duration: 2,
70
+ timeline: {
71
+ '0%': { transform: { rotate: { z: -20 } } },
72
+ '50%': {
73
+ opacity: 0,
74
+ transform: { rotate: { z: 80 } },
75
+ },
76
+ '100%': { opacity: 1 },
77
+ },
78
+ }),
79
+ ).toMatchObject({
80
+ duration: 2,
81
+ tracks: [
82
+ {
83
+ property: 'transform.rotate.z',
84
+ keyframes: [
85
+ { at: 0, value: -20 },
86
+ { at: 1, value: 80 },
87
+ ],
88
+ },
89
+ {
90
+ property: 'opacity',
91
+ keyframes: [
92
+ { at: 1, value: 0 },
93
+ { at: 2, value: 1 },
94
+ ],
95
+ },
96
+ ],
97
+ })
98
+ })
99
+ })