@rafaelaugusto/jolt 0.1.0-beta.9 → 0.1.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (576) hide show
  1. package/README.md +167 -21
  2. package/dist/animate.d.ts +25 -4
  3. package/dist/animate.d.ts.map +1 -1
  4. package/dist/animate.js +67 -26
  5. package/dist/animate.js.map +1 -1
  6. package/dist/blur/index.d.ts +6 -0
  7. package/dist/blur/index.d.ts.map +1 -0
  8. package/dist/blur/index.js +196 -0
  9. package/dist/blur/index.js.map +1 -0
  10. package/dist/blur/native.d.ts +17 -0
  11. package/dist/blur/native.d.ts.map +1 -0
  12. package/dist/blur/native.js +44 -0
  13. package/dist/blur/native.js.map +1 -0
  14. package/dist/blur/types.d.ts +32 -0
  15. package/dist/blur/types.d.ts.map +1 -0
  16. package/dist/blur/types.js +2 -0
  17. package/dist/blur/types.js.map +1 -0
  18. package/dist/bottom-sheet/geometry.d.ts +18 -0
  19. package/dist/bottom-sheet/geometry.d.ts.map +1 -0
  20. package/dist/bottom-sheet/geometry.js +51 -0
  21. package/dist/bottom-sheet/geometry.js.map +1 -0
  22. package/dist/bottom-sheet/index.d.ts +56 -0
  23. package/dist/bottom-sheet/index.d.ts.map +1 -0
  24. package/dist/bottom-sheet/index.js +462 -0
  25. package/dist/bottom-sheet/index.js.map +1 -0
  26. package/dist/bottom-sheet/native.d.ts +11 -0
  27. package/dist/bottom-sheet/native.d.ts.map +1 -0
  28. package/dist/bottom-sheet/native.js +173 -0
  29. package/dist/bottom-sheet/native.js.map +1 -0
  30. package/dist/config.d.ts +9 -0
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/config.js +40 -1
  33. package/dist/config.js.map +1 -1
  34. package/dist/decay.d.ts +1 -0
  35. package/dist/decay.d.ts.map +1 -1
  36. package/dist/decay.js +7 -0
  37. package/dist/decay.js.map +1 -1
  38. package/dist/drag-physics.d.ts +6 -1
  39. package/dist/drag-physics.d.ts.map +1 -1
  40. package/dist/drag.d.ts +17 -3
  41. package/dist/drag.d.ts.map +1 -1
  42. package/dist/drag.js +34 -11
  43. package/dist/drag.js.map +1 -1
  44. package/dist/driver/android-gradient.d.ts +5 -0
  45. package/dist/driver/android-gradient.d.ts.map +1 -0
  46. package/dist/driver/android-gradient.js +99 -0
  47. package/dist/driver/android-gradient.js.map +1 -0
  48. package/dist/driver/android-particles.d.ts +6 -0
  49. package/dist/driver/android-particles.d.ts.map +1 -0
  50. package/dist/driver/android-particles.js +93 -0
  51. package/dist/driver/android-particles.js.map +1 -0
  52. package/dist/driver/android.d.ts.map +1 -1
  53. package/dist/driver/android.js +27 -1
  54. package/dist/driver/android.js.map +1 -1
  55. package/dist/driver/frame.d.ts +3 -0
  56. package/dist/driver/frame.d.ts.map +1 -0
  57. package/dist/driver/frame.js +7 -0
  58. package/dist/driver/frame.js.map +1 -0
  59. package/dist/driver/index.d.ts +4 -0
  60. package/dist/driver/index.d.ts.map +1 -1
  61. package/dist/driver/index.js.map +1 -1
  62. package/dist/driver/ios-gradient.d.ts +5 -0
  63. package/dist/driver/ios-gradient.d.ts.map +1 -0
  64. package/dist/driver/ios-gradient.js +131 -0
  65. package/dist/driver/ios-gradient.js.map +1 -0
  66. package/dist/driver/ios-scroll-delegate.d.ts +4 -0
  67. package/dist/driver/ios-scroll-delegate.d.ts.map +1 -0
  68. package/dist/driver/ios-scroll-delegate.js +26 -0
  69. package/dist/driver/ios-scroll-delegate.js.map +1 -0
  70. package/dist/driver/ios.d.ts.map +1 -1
  71. package/dist/driver/ios.js +9 -0
  72. package/dist/driver/ios.js.map +1 -1
  73. package/dist/easing.d.ts +3 -1
  74. package/dist/easing.d.ts.map +1 -1
  75. package/dist/easing.js +18 -1
  76. package/dist/easing.js.map +1 -1
  77. package/dist/engine.d.ts +31 -2
  78. package/dist/engine.d.ts.map +1 -1
  79. package/dist/engine.js +194 -42
  80. package/dist/engine.js.map +1 -1
  81. package/dist/gesture-native.d.ts +28 -0
  82. package/dist/gesture-native.d.ts.map +1 -0
  83. package/dist/gesture-native.js +61 -0
  84. package/dist/gesture-native.js.map +1 -0
  85. package/dist/gestures/index.d.ts +69 -0
  86. package/dist/gestures/index.d.ts.map +1 -0
  87. package/dist/gestures/index.js +262 -0
  88. package/dist/gestures/index.js.map +1 -0
  89. package/dist/glass/index.d.ts +55 -0
  90. package/dist/glass/index.d.ts.map +1 -0
  91. package/dist/glass/index.js +205 -0
  92. package/dist/glass/index.js.map +1 -0
  93. package/dist/gradient-binding.d.ts +38 -0
  94. package/dist/gradient-binding.d.ts.map +1 -0
  95. package/dist/gradient-binding.js +128 -0
  96. package/dist/gradient-binding.js.map +1 -0
  97. package/dist/gradient.d.ts +105 -0
  98. package/dist/gradient.d.ts.map +1 -0
  99. package/dist/gradient.js +514 -0
  100. package/dist/gradient.js.map +1 -0
  101. package/dist/gravity.d.ts +13 -0
  102. package/dist/gravity.d.ts.map +1 -0
  103. package/dist/gravity.js +84 -0
  104. package/dist/gravity.js.map +1 -0
  105. package/dist/haptics.d.ts.map +1 -1
  106. package/dist/haptics.js +101 -28
  107. package/dist/haptics.js.map +1 -1
  108. package/dist/image-effect.d.ts +1 -0
  109. package/dist/image-effect.d.ts.map +1 -1
  110. package/dist/image-effect.js +10 -2
  111. package/dist/image-effect.js.map +1 -1
  112. package/dist/index.d.ts +19 -7
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +10 -4
  115. package/dist/index.js.map +1 -1
  116. package/dist/inspector/index.d.ts +86 -0
  117. package/dist/inspector/index.d.ts.map +1 -0
  118. package/dist/inspector/index.js +419 -0
  119. package/dist/inspector/index.js.map +1 -0
  120. package/dist/inspector/plot.d.ts +4 -0
  121. package/dist/inspector/plot.d.ts.map +1 -0
  122. package/dist/inspector/plot.js +23 -0
  123. package/dist/inspector/plot.js.map +1 -0
  124. package/dist/inspector/probe.d.ts +19 -0
  125. package/dist/inspector/probe.d.ts.map +1 -0
  126. package/dist/inspector/probe.js +37 -0
  127. package/dist/inspector/probe.js.map +1 -0
  128. package/dist/inspector/tuning.d.ts +19 -0
  129. package/dist/inspector/tuning.d.ts.map +1 -0
  130. package/dist/inspector/tuning.js +37 -0
  131. package/dist/inspector/tuning.js.map +1 -0
  132. package/dist/interactive-navigation/index.d.ts +44 -0
  133. package/dist/interactive-navigation/index.d.ts.map +1 -0
  134. package/dist/interactive-navigation/index.js +350 -0
  135. package/dist/interactive-navigation/index.js.map +1 -0
  136. package/dist/keyboard.d.ts +24 -0
  137. package/dist/keyboard.d.ts.map +1 -1
  138. package/dist/keyboard.js +199 -6
  139. package/dist/keyboard.js.map +1 -1
  140. package/dist/live-spring-driver.d.ts +52 -0
  141. package/dist/live-spring-driver.d.ts.map +1 -0
  142. package/dist/live-spring-driver.js +104 -0
  143. package/dist/live-spring-driver.js.map +1 -0
  144. package/dist/mixer.d.ts +55 -0
  145. package/dist/mixer.d.ts.map +1 -0
  146. package/dist/mixer.js +286 -0
  147. package/dist/mixer.js.map +1 -0
  148. package/dist/motion-scope.d.ts +8 -2
  149. package/dist/motion-scope.d.ts.map +1 -1
  150. package/dist/motion-scope.js +24 -3
  151. package/dist/motion-scope.js.map +1 -1
  152. package/dist/motion-states.d.ts +19 -7
  153. package/dist/motion-states.d.ts.map +1 -1
  154. package/dist/motion-states.js +116 -26
  155. package/dist/motion-states.js.map +1 -1
  156. package/dist/motion-value.d.ts +227 -0
  157. package/dist/motion-value.d.ts.map +1 -0
  158. package/dist/motion-value.js +1074 -0
  159. package/dist/motion-value.js.map +1 -0
  160. package/dist/native/index.d.ts +10 -0
  161. package/dist/native/index.d.ts.map +1 -0
  162. package/dist/native/index.js +6 -0
  163. package/dist/native/index.js.map +1 -0
  164. package/dist/native-properties.d.ts +28 -0
  165. package/dist/native-properties.d.ts.map +1 -0
  166. package/dist/native-properties.js +154 -0
  167. package/dist/native-properties.js.map +1 -0
  168. package/dist/native-property-driver.d.ts +19 -0
  169. package/dist/native-property-driver.d.ts.map +1 -0
  170. package/dist/native-property-driver.js +69 -0
  171. package/dist/native-property-driver.js.map +1 -0
  172. package/dist/native-property.d.ts +37 -0
  173. package/dist/native-property.d.ts.map +1 -0
  174. package/dist/native-property.js +285 -0
  175. package/dist/native-property.js.map +1 -0
  176. package/dist/particles.d.ts +5 -2
  177. package/dist/particles.d.ts.map +1 -1
  178. package/dist/particles.js +16 -10
  179. package/dist/particles.js.map +1 -1
  180. package/dist/path.d.ts.map +1 -1
  181. package/dist/path.js +2 -2
  182. package/dist/path.js.map +1 -1
  183. package/dist/physics/index.d.ts +139 -0
  184. package/dist/physics/index.d.ts.map +1 -0
  185. package/dist/physics/index.js +316 -0
  186. package/dist/physics/index.js.map +1 -0
  187. package/dist/physics/native.d.ts +54 -0
  188. package/dist/physics/native.d.ts.map +1 -0
  189. package/dist/physics/native.js +64 -0
  190. package/dist/physics/native.js.map +1 -0
  191. package/dist/playback-group.d.ts.map +1 -1
  192. package/dist/playback-group.js +17 -1
  193. package/dist/playback-group.js.map +1 -1
  194. package/dist/playback.d.ts +15 -0
  195. package/dist/playback.d.ts.map +1 -1
  196. package/dist/playback.js +23 -0
  197. package/dist/playback.js.map +1 -1
  198. package/dist/predictive-back/index.d.ts +45 -0
  199. package/dist/predictive-back/index.d.ts.map +1 -0
  200. package/dist/predictive-back/index.js +220 -0
  201. package/dist/predictive-back/index.js.map +1 -0
  202. package/dist/predictive-back/presentation.d.ts +4 -0
  203. package/dist/predictive-back/presentation.d.ts.map +1 -0
  204. package/dist/predictive-back/presentation.js +3 -0
  205. package/dist/predictive-back/presentation.js.map +1 -0
  206. package/dist/press.d.ts.map +1 -1
  207. package/dist/press.js +11 -2
  208. package/dist/press.js.map +1 -1
  209. package/dist/reorder/handle.d.ts +6 -0
  210. package/dist/reorder/handle.d.ts.map +1 -0
  211. package/dist/reorder/handle.js +10 -0
  212. package/dist/reorder/handle.js.map +1 -0
  213. package/dist/reorder/index.d.ts +10 -0
  214. package/dist/reorder/index.d.ts.map +1 -0
  215. package/dist/reorder/index.js +233 -0
  216. package/dist/reorder/index.js.map +1 -0
  217. package/dist/reorder/list-view.d.ts +5 -0
  218. package/dist/reorder/list-view.d.ts.map +1 -0
  219. package/dist/reorder/list-view.js +238 -0
  220. package/dist/reorder/list-view.js.map +1 -0
  221. package/dist/reorder/model.d.ts +6 -0
  222. package/dist/reorder/model.d.ts.map +1 -0
  223. package/dist/reorder/model.js +30 -0
  224. package/dist/reorder/model.js.map +1 -0
  225. package/dist/reorder/surface.d.ts +6 -0
  226. package/dist/reorder/surface.d.ts.map +1 -0
  227. package/dist/reorder/surface.js +10 -0
  228. package/dist/reorder/surface.js.map +1 -0
  229. package/dist/reorder/types.d.ts +92 -0
  230. package/dist/reorder/types.d.ts.map +1 -0
  231. package/dist/reorder/types.js +2 -0
  232. package/dist/reorder/types.js.map +1 -0
  233. package/dist/sampling.d.ts +35 -0
  234. package/dist/sampling.d.ts.map +1 -0
  235. package/dist/sampling.js +123 -0
  236. package/dist/sampling.js.map +1 -0
  237. package/dist/scene-appearance.d.ts +14 -0
  238. package/dist/scene-appearance.d.ts.map +1 -0
  239. package/dist/scene-appearance.js +68 -0
  240. package/dist/scene-appearance.js.map +1 -0
  241. package/dist/scene-camera.d.ts +5 -0
  242. package/dist/scene-camera.d.ts.map +1 -0
  243. package/dist/scene-camera.js +23 -0
  244. package/dist/scene-camera.js.map +1 -0
  245. package/dist/scene-shader.d.ts +18 -0
  246. package/dist/scene-shader.d.ts.map +1 -0
  247. package/dist/scene-shader.js +76 -0
  248. package/dist/scene-shader.js.map +1 -0
  249. package/dist/scroll-header/geometry.d.ts +18 -0
  250. package/dist/scroll-header/geometry.d.ts.map +1 -0
  251. package/dist/scroll-header/geometry.js +46 -0
  252. package/dist/scroll-header/geometry.js.map +1 -0
  253. package/dist/scroll-header/index.d.ts +48 -0
  254. package/dist/scroll-header/index.d.ts.map +1 -0
  255. package/dist/scroll-header/index.js +399 -0
  256. package/dist/scroll-header/index.js.map +1 -0
  257. package/dist/scroll-header/native.d.ts +28 -0
  258. package/dist/scroll-header/native.d.ts.map +1 -0
  259. package/dist/scroll-header/native.js +43 -0
  260. package/dist/scroll-header/native.js.map +1 -0
  261. package/dist/sensors/index.d.ts +69 -0
  262. package/dist/sensors/index.d.ts.map +1 -0
  263. package/dist/sensors/index.js +149 -0
  264. package/dist/sensors/index.js.map +1 -0
  265. package/dist/sensors/native.d.ts +20 -0
  266. package/dist/sensors/native.d.ts.map +1 -0
  267. package/dist/sensors/native.js +48 -0
  268. package/dist/sensors/native.js.map +1 -0
  269. package/dist/sequence.d.ts +24 -0
  270. package/dist/sequence.d.ts.map +1 -1
  271. package/dist/sequence.js +181 -19
  272. package/dist/sequence.js.map +1 -1
  273. package/dist/shapes/android.d.ts +3 -0
  274. package/dist/shapes/android.d.ts.map +1 -0
  275. package/dist/shapes/android.js +51 -0
  276. package/dist/shapes/android.js.map +1 -0
  277. package/dist/shapes/index.d.ts +6 -0
  278. package/dist/shapes/index.d.ts.map +1 -0
  279. package/dist/shapes/index.js +238 -0
  280. package/dist/shapes/index.js.map +1 -0
  281. package/dist/shapes/ios.d.ts +3 -0
  282. package/dist/shapes/ios.d.ts.map +1 -0
  283. package/dist/shapes/ios.js +164 -0
  284. package/dist/shapes/ios.js.map +1 -0
  285. package/dist/shapes/native.d.ts +18 -0
  286. package/dist/shapes/native.d.ts.map +1 -0
  287. package/dist/shapes/native.js +10 -0
  288. package/dist/shapes/native.js.map +1 -0
  289. package/dist/shapes/path.d.ts +10 -0
  290. package/dist/shapes/path.d.ts.map +1 -0
  291. package/dist/shapes/path.js +106 -0
  292. package/dist/shapes/path.js.map +1 -0
  293. package/dist/shapes/types.d.ts +55 -0
  294. package/dist/shapes/types.d.ts.map +1 -0
  295. package/dist/shapes/types.js +11 -0
  296. package/dist/shapes/types.js.map +1 -0
  297. package/dist/shared-layout/index.d.ts +40 -0
  298. package/dist/shared-layout/index.d.ts.map +1 -0
  299. package/dist/shared-layout/index.js +267 -0
  300. package/dist/shared-layout/index.js.map +1 -0
  301. package/dist/shared-layout/native.d.ts +15 -0
  302. package/dist/shared-layout/native.d.ts.map +1 -0
  303. package/dist/shared-layout/native.js +79 -0
  304. package/dist/shared-layout/native.js.map +1 -0
  305. package/dist/shared-layout/timing.d.ts +9 -0
  306. package/dist/shared-layout/timing.d.ts.map +1 -0
  307. package/dist/shared-layout/timing.js +68 -0
  308. package/dist/shared-layout/timing.js.map +1 -0
  309. package/dist/shared-navigation/entry.d.ts +51 -0
  310. package/dist/shared-navigation/entry.d.ts.map +1 -0
  311. package/dist/shared-navigation/entry.js +619 -0
  312. package/dist/shared-navigation/entry.js.map +1 -0
  313. package/dist/shared-navigation/index.d.ts +58 -0
  314. package/dist/shared-navigation/index.d.ts.map +1 -0
  315. package/dist/shared-navigation/index.js +318 -0
  316. package/dist/shared-navigation/index.js.map +1 -0
  317. package/dist/shared-navigation/return-signal.d.ts +16 -0
  318. package/dist/shared-navigation/return-signal.d.ts.map +1 -0
  319. package/dist/shared-navigation/return-signal.js +35 -0
  320. package/dist/shared-navigation/return-signal.js.map +1 -0
  321. package/dist/shared-navigation/return-target.d.ts +32 -0
  322. package/dist/shared-navigation/return-target.d.ts.map +1 -0
  323. package/dist/shared-navigation/return-target.js +168 -0
  324. package/dist/shared-navigation/return-target.js.map +1 -0
  325. package/dist/shared-navigation/scope.d.ts +4 -0
  326. package/dist/shared-navigation/scope.d.ts.map +1 -0
  327. package/dist/shared-navigation/scope.js +2 -0
  328. package/dist/shared-navigation/scope.js.map +1 -0
  329. package/dist/shared-navigation/targets.d.ts +6 -0
  330. package/dist/shared-navigation/targets.d.ts.map +1 -0
  331. package/dist/shared-navigation/targets.js +36 -0
  332. package/dist/shared-navigation/targets.js.map +1 -0
  333. package/dist/size-layout.d.ts +19 -0
  334. package/dist/size-layout.d.ts.map +1 -0
  335. package/dist/size-layout.js +216 -0
  336. package/dist/size-layout.js.map +1 -0
  337. package/dist/size.d.ts +19 -0
  338. package/dist/size.d.ts.map +1 -0
  339. package/dist/size.js +251 -0
  340. package/dist/size.js.map +1 -0
  341. package/dist/spring.d.ts +2 -0
  342. package/dist/spring.d.ts.map +1 -1
  343. package/dist/spring.js +11 -0
  344. package/dist/spring.js.map +1 -1
  345. package/dist/svg-path.d.ts +18 -0
  346. package/dist/svg-path.d.ts.map +1 -1
  347. package/dist/svg-path.js +3 -2
  348. package/dist/svg-path.js.map +1 -1
  349. package/dist/testing/clock.d.ts +40 -0
  350. package/dist/testing/clock.d.ts.map +1 -0
  351. package/dist/testing/clock.js +116 -0
  352. package/dist/testing/clock.js.map +1 -0
  353. package/dist/testing/handoff-recorder.d.ts +8 -0
  354. package/dist/testing/handoff-recorder.d.ts.map +1 -0
  355. package/dist/testing/handoff-recorder.js +77 -0
  356. package/dist/testing/handoff-recorder.js.map +1 -0
  357. package/dist/testing/index.d.ts +5 -0
  358. package/dist/testing/index.d.ts.map +1 -0
  359. package/dist/testing/index.js +5 -0
  360. package/dist/testing/index.js.map +1 -0
  361. package/dist/testing/native.d.ts +46 -0
  362. package/dist/testing/native.d.ts.map +1 -0
  363. package/dist/testing/native.js +313 -0
  364. package/dist/testing/native.js.map +1 -0
  365. package/dist/testing/presentation.d.ts +11 -0
  366. package/dist/testing/presentation.d.ts.map +1 -0
  367. package/dist/testing/presentation.js +45 -0
  368. package/dist/testing/presentation.js.map +1 -0
  369. package/dist/testing/replay.d.ts +39 -0
  370. package/dist/testing/replay.d.ts.map +1 -0
  371. package/dist/testing/replay.js +99 -0
  372. package/dist/testing/replay.js.map +1 -0
  373. package/dist/testing/scroll-handoff-native.d.ts +10 -0
  374. package/dist/testing/scroll-handoff-native.d.ts.map +1 -0
  375. package/dist/testing/scroll-handoff-native.js +151 -0
  376. package/dist/testing/scroll-handoff-native.js.map +1 -0
  377. package/dist/testing/scroll-handoff.d.ts +25 -0
  378. package/dist/testing/scroll-handoff.d.ts.map +1 -0
  379. package/dist/testing/scroll-handoff.js +127 -0
  380. package/dist/testing/scroll-handoff.js.map +1 -0
  381. package/dist/testing/sensors.d.ts +13 -0
  382. package/dist/testing/sensors.d.ts.map +1 -0
  383. package/dist/testing/sensors.js +26 -0
  384. package/dist/testing/sensors.js.map +1 -0
  385. package/dist/testing/trace.d.ts +101 -0
  386. package/dist/testing/trace.d.ts.map +1 -0
  387. package/dist/testing/trace.js +263 -0
  388. package/dist/testing/trace.js.map +1 -0
  389. package/dist/timed-animation.d.ts +38 -0
  390. package/dist/timed-animation.d.ts.map +1 -0
  391. package/dist/timed-animation.js +177 -0
  392. package/dist/timed-animation.js.map +1 -0
  393. package/dist/track.d.ts +3 -0
  394. package/dist/track.d.ts.map +1 -1
  395. package/dist/track.js +281 -40
  396. package/dist/track.js.map +1 -1
  397. package/dist/transition.d.ts +54 -2
  398. package/dist/transition.d.ts.map +1 -1
  399. package/dist/transition.js +128 -8
  400. package/dist/transition.js.map +1 -1
  401. package/dist/types.d.ts +10 -1
  402. package/dist/types.d.ts.map +1 -1
  403. package/dist/value-observers.d.ts +22 -0
  404. package/dist/value-observers.d.ts.map +1 -0
  405. package/dist/value-observers.js +122 -0
  406. package/dist/value-observers.js.map +1 -0
  407. package/dist/value-track.d.ts +13 -0
  408. package/dist/value-track.d.ts.map +1 -0
  409. package/dist/value-track.js +59 -0
  410. package/dist/value-track.js.map +1 -0
  411. package/dist/vue/index.d.ts +33 -3
  412. package/dist/vue/index.d.ts.map +1 -1
  413. package/dist/vue/index.js +118 -3
  414. package/dist/vue/index.js.map +1 -1
  415. package/dist/zoomable.d.ts +1 -1
  416. package/dist/zoomable.d.ts.map +1 -1
  417. package/package.json +68 -3
  418. package/platforms/android/include.gradle +10 -0
  419. package/platforms/android/java/org/rafaelaugusto/jolt/BlurEffect.java +89 -0
  420. package/platforms/android/java/org/rafaelaugusto/jolt/CircleMath.java +158 -0
  421. package/platforms/android/java/org/rafaelaugusto/jolt/CircleWorld.java +221 -0
  422. package/platforms/android/java/org/rafaelaugusto/jolt/GestureSession.java +227 -0
  423. package/platforms/android/java/org/rafaelaugusto/jolt/GestureSurface.java +54 -0
  424. package/platforms/android/java/org/rafaelaugusto/jolt/GradientLayer.java +224 -0
  425. package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFrame.java +53 -0
  426. package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardFrameFollower.java +57 -0
  427. package/platforms/android/java/org/rafaelaugusto/jolt/KeyboardObserver.java +97 -0
  428. package/platforms/android/java/org/rafaelaugusto/jolt/LiveSpring.java +277 -0
  429. package/platforms/android/java/org/rafaelaugusto/jolt/MotionProbe.java +70 -0
  430. package/platforms/android/java/org/rafaelaugusto/jolt/ParticleEmitter.java +192 -0
  431. package/platforms/android/java/org/rafaelaugusto/jolt/ParticleSimulation.java +114 -0
  432. package/platforms/android/java/org/rafaelaugusto/jolt/PredictiveBackSession.java +212 -0
  433. package/platforms/android/java/org/rafaelaugusto/jolt/ReorderHandle.java +25 -0
  434. package/platforms/android/java/org/rafaelaugusto/jolt/ReorderSession.java +213 -0
  435. package/platforms/android/java/org/rafaelaugusto/jolt/ReorderSurface.java +27 -0
  436. package/platforms/android/java/org/rafaelaugusto/jolt/ScrollHeader.java +84 -0
  437. package/platforms/android/java/org/rafaelaugusto/jolt/SensorMath.java +28 -0
  438. package/platforms/android/java/org/rafaelaugusto/jolt/SensorSource.java +217 -0
  439. package/platforms/android/java/org/rafaelaugusto/jolt/ShapeLayer.java +120 -0
  440. package/platforms/android/java/org/rafaelaugusto/jolt/SharedLayoutFlight.java +287 -0
  441. package/platforms/android/java/org/rafaelaugusto/jolt/SharedNavigationScene.java +115 -0
  442. package/platforms/android/java/org/rafaelaugusto/jolt/SpringState.java +39 -0
  443. package/platforms/android/proguard-rules.pro +20 -0
  444. package/platforms/ios/build.xcconfig +1 -1
  445. package/platforms/ios/src/JoltBlur.h +14 -0
  446. package/platforms/ios/src/JoltBlur.m +86 -0
  447. package/platforms/ios/src/JoltCircleMath.h +191 -0
  448. package/platforms/ios/src/JoltCircleWorld.h +18 -0
  449. package/platforms/ios/src/JoltCircleWorld.m +218 -0
  450. package/platforms/ios/src/JoltGestureSession.h +23 -0
  451. package/platforms/ios/src/JoltGestureSession.m +251 -0
  452. package/platforms/ios/src/JoltInteractiveNavigation.h +23 -0
  453. package/platforms/ios/src/JoltInteractiveNavigation.m +255 -0
  454. package/platforms/ios/src/JoltLiveSpring.h +29 -0
  455. package/platforms/ios/src/JoltLiveSpring.m +243 -0
  456. package/platforms/ios/src/JoltMotionProbe.h +9 -0
  457. package/platforms/ios/src/JoltMotionProbe.m +72 -0
  458. package/platforms/ios/src/JoltReorderSession.h +15 -0
  459. package/platforms/ios/src/JoltReorderSession.m +205 -0
  460. package/platforms/ios/src/JoltScrollHeader.h +13 -0
  461. package/platforms/ios/src/JoltScrollHeader.m +101 -0
  462. package/platforms/ios/src/JoltSensorMath.h +39 -0
  463. package/platforms/ios/src/JoltSensorSource.h +13 -0
  464. package/platforms/ios/src/JoltSensorSource.m +201 -0
  465. package/platforms/ios/src/JoltSharedLayoutFlight.h +19 -0
  466. package/platforms/ios/src/JoltSharedLayoutFlight.m +250 -0
  467. package/platforms/ios/src/JoltSpringState.h +35 -0
  468. package/platforms/ios/src/module.modulemap +10 -0
  469. package/src/android-plugin.d.ts +464 -0
  470. package/src/animate.ts +129 -15
  471. package/src/blur/index.ts +195 -0
  472. package/src/blur/native.ts +70 -0
  473. package/src/blur/types.ts +32 -0
  474. package/src/bottom-sheet/geometry.ts +84 -0
  475. package/src/bottom-sheet/index.ts +536 -0
  476. package/src/bottom-sheet/native.ts +214 -0
  477. package/src/config.ts +39 -1
  478. package/src/decay.ts +9 -0
  479. package/src/drag.ts +67 -21
  480. package/src/driver/android-gradient.ts +116 -0
  481. package/src/driver/android-particles.ts +118 -0
  482. package/src/driver/android.ts +31 -1
  483. package/src/driver/frame.ts +10 -0
  484. package/src/driver/index.ts +4 -0
  485. package/src/driver/ios-gradient.ts +136 -0
  486. package/src/driver/ios-scroll-delegate.ts +23 -0
  487. package/src/driver/ios.ts +10 -0
  488. package/src/easing.ts +21 -1
  489. package/src/engine.ts +209 -60
  490. package/src/gesture-native.ts +139 -0
  491. package/src/gestures/index.ts +365 -0
  492. package/src/glass/index.ts +218 -0
  493. package/src/gradient-binding.ts +158 -0
  494. package/src/gradient.ts +663 -0
  495. package/src/gravity.ts +107 -0
  496. package/src/haptics.ts +106 -28
  497. package/src/image-effect.ts +10 -2
  498. package/src/index.ts +56 -7
  499. package/src/inspector/index.ts +523 -0
  500. package/src/inspector/plot.ts +27 -0
  501. package/src/inspector/probe.ts +50 -0
  502. package/src/inspector/tuning.ts +51 -0
  503. package/src/interactive-navigation/index.ts +427 -0
  504. package/src/ios-plugin.d.ts +280 -0
  505. package/src/keyboard.ts +231 -7
  506. package/src/live-spring-driver.ts +181 -0
  507. package/src/mixer.ts +312 -0
  508. package/src/motion-scope.ts +39 -6
  509. package/src/motion-states.ts +149 -42
  510. package/src/motion-value.ts +1289 -0
  511. package/src/native/index.ts +30 -0
  512. package/src/native-properties.ts +188 -0
  513. package/src/native-property-driver.ts +123 -0
  514. package/src/native-property.ts +366 -0
  515. package/src/particles.ts +18 -17
  516. package/src/path.ts +2 -1
  517. package/src/physics/index.ts +476 -0
  518. package/src/physics/native.ts +121 -0
  519. package/src/playback-group.ts +17 -1
  520. package/src/playback.ts +41 -0
  521. package/src/predictive-back/index.ts +280 -0
  522. package/src/predictive-back/presentation.ts +6 -0
  523. package/src/press.ts +10 -2
  524. package/src/reorder/handle.ts +9 -0
  525. package/src/reorder/index.ts +243 -0
  526. package/src/reorder/list-view.ts +262 -0
  527. package/src/reorder/model.ts +47 -0
  528. package/src/reorder/surface.ts +10 -0
  529. package/src/reorder/types.ts +87 -0
  530. package/src/sampling.ts +173 -0
  531. package/src/scene-appearance.ts +92 -0
  532. package/src/scene-camera.ts +30 -0
  533. package/src/scene-shader.ts +139 -0
  534. package/src/scroll-header/geometry.ts +88 -0
  535. package/src/scroll-header/index.ts +530 -0
  536. package/src/scroll-header/native.ts +89 -0
  537. package/src/sensors/index.ts +246 -0
  538. package/src/sensors/native.ts +72 -0
  539. package/src/sequence.ts +209 -20
  540. package/src/shapes/android.ts +63 -0
  541. package/src/shapes/index.ts +267 -0
  542. package/src/shapes/ios.ts +194 -0
  543. package/src/shapes/native.ts +27 -0
  544. package/src/shapes/path.ts +127 -0
  545. package/src/shapes/types.ts +63 -0
  546. package/src/shared-layout/index.ts +343 -0
  547. package/src/shared-layout/native.ts +138 -0
  548. package/src/shared-layout/timing.ts +87 -0
  549. package/src/shared-navigation/entry.ts +695 -0
  550. package/src/shared-navigation/index.ts +414 -0
  551. package/src/shared-navigation/return-signal.ts +41 -0
  552. package/src/shared-navigation/return-target.ts +197 -0
  553. package/src/shared-navigation/scope.ts +3 -0
  554. package/src/shared-navigation/targets.ts +38 -0
  555. package/src/size-layout.ts +237 -0
  556. package/src/size.ts +302 -0
  557. package/src/spring.ts +18 -0
  558. package/src/svg-path.ts +8 -3
  559. package/src/testing/clock.ts +128 -0
  560. package/src/testing/handoff-recorder.ts +98 -0
  561. package/src/testing/index.ts +4 -0
  562. package/src/testing/native.ts +386 -0
  563. package/src/testing/presentation.ts +46 -0
  564. package/src/testing/replay.ts +149 -0
  565. package/src/testing/scroll-handoff-native.ts +201 -0
  566. package/src/testing/scroll-handoff.ts +140 -0
  567. package/src/testing/sensors.ts +41 -0
  568. package/src/testing/trace.ts +340 -0
  569. package/src/timed-animation.ts +192 -0
  570. package/src/track.ts +334 -38
  571. package/src/transition.ts +197 -9
  572. package/src/types.ts +11 -1
  573. package/src/value-observers.ts +147 -0
  574. package/src/value-track.ts +71 -0
  575. package/src/vue/index.ts +147 -1
  576. package/src/zoomable.ts +1 -1
@@ -0,0 +1,149 @@
1
+ import {
2
+ parseTrace,
3
+ traceRandom,
4
+ type InteractionTrace,
5
+ type TraceInput,
6
+ type TraceState,
7
+ } from './trace.js'
8
+
9
+ export interface ReplayAdapter {
10
+ input(event: TraceInput): void | Promise<void>
11
+ read(id: string): TraceState
12
+ dispose(): void | Promise<void>
13
+ /** Owned subscriptions/handles remaining after dispose; must be zero. */
14
+ resources(): number
15
+ }
16
+ export interface ReplayObservation {
17
+ at: number
18
+ id: string
19
+ expected: TraceState
20
+ observed: TraceState
21
+ positionError: number
22
+ velocityError: number
23
+ passed: boolean
24
+ }
25
+ export interface ReplayReport {
26
+ passed: boolean
27
+ observations: ReplayObservation[]
28
+ errors: string[]
29
+ remainingResources: number
30
+ trace: InteractionTrace
31
+ /** A compact expected/observed SVG, useful as a failure artifact. */
32
+ plot: string
33
+ }
34
+ export interface ReplayOptions {
35
+ advanceTo(at: number): void | Promise<void>
36
+ /** Construct fresh state for each replay. Include the supplied seed in random effects. */
37
+ create(trace: InteractionTrace, random: () => number): ReplayAdapter
38
+ signal?: { readonly aborted: boolean }
39
+ }
40
+
41
+ /** Ordered replay at original timestamps. A 250 ms gap advances once, never fifteen fake frames. */
42
+ export async function replayInteraction(
43
+ value: InteractionTrace | string,
44
+ options: ReplayOptions,
45
+ ): Promise<ReplayReport> {
46
+ const trace = parseTrace(value)
47
+ const observations: ReplayObservation[] = [],
48
+ errors: string[] = []
49
+ let adapter: ReplayAdapter | undefined,
50
+ remainingResources = 0
51
+ try {
52
+ if (!trace.entries.some((entry) => 'expected' in entry))
53
+ throw new Error('A regression trace needs at least one checkpoint.')
54
+ adapter = options.create(trace, traceRandom(trace.seed))
55
+ let previous = -1
56
+ for (const entry of trace.entries) {
57
+ if (options.signal?.aborted) throw new Error('Replay cancelled.')
58
+ if (entry.at !== previous) {
59
+ await options.advanceTo(entry.at)
60
+ previous = entry.at
61
+ }
62
+ if ('input' in entry) await adapter.input(entry.input)
63
+ else {
64
+ const value = adapter.read(entry.id)
65
+ const observed = {
66
+ position: value.position,
67
+ velocity: value.velocity,
68
+ settled: value.settled,
69
+ }
70
+ const positionError = Math.abs(observed.position - entry.expected.position)
71
+ const velocityError = Math.abs(observed.velocity - entry.expected.velocity)
72
+ const passed =
73
+ typeof observed.position === 'number' &&
74
+ typeof observed.velocity === 'number' &&
75
+ typeof observed.settled === 'boolean' &&
76
+ Number.isFinite(positionError) &&
77
+ Number.isFinite(velocityError) &&
78
+ positionError <= entry.tolerance.position &&
79
+ velocityError <= entry.tolerance.velocity &&
80
+ observed.settled === entry.expected.settled
81
+ observations.push({
82
+ at: entry.at,
83
+ id: entry.id,
84
+ expected: entry.expected,
85
+ observed: { ...observed },
86
+ positionError,
87
+ velocityError,
88
+ passed,
89
+ })
90
+ if (!passed)
91
+ errors.push(
92
+ `${entry.id} at ${entry.at} ms: position error ${positionError}, velocity error ${velocityError}, settled ${observed.settled} (expected ${entry.expected.settled}).`,
93
+ )
94
+ }
95
+ }
96
+ } catch (error) {
97
+ errors.push(error instanceof Error ? error.message : 'Replay adapter failed.')
98
+ } finally {
99
+ if (adapter) {
100
+ try {
101
+ await adapter.dispose()
102
+ } catch {
103
+ errors.push('Replay adapter disposal failed.')
104
+ }
105
+ try {
106
+ remainingResources = adapter.resources()
107
+ if (!Number.isSafeInteger(remainingResources) || remainingResources !== 0)
108
+ errors.push('Replay left owned subscriptions or handles alive.')
109
+ } catch {
110
+ remainingResources = -1
111
+ errors.push('Replay resource audit failed.')
112
+ }
113
+ }
114
+ }
115
+ return {
116
+ passed: errors.length === 0,
117
+ observations,
118
+ errors,
119
+ remainingResources,
120
+ trace,
121
+ plot: replayPlot(observations),
122
+ }
123
+ }
124
+
125
+ /** IDs are validated by parseTrace; plotted values must be finite before entering SVG. */
126
+ export function replayPlot(samples: readonly ReplayObservation[]): string {
127
+ const finite = samples.filter((s) =>
128
+ [s.at, s.expected.position, s.observed.position].every(Number.isFinite),
129
+ )
130
+ const end = Math.max(1, ...finite.map((s) => s.at))
131
+ const min = Math.min(
132
+ 0,
133
+ ...finite.flatMap((s) => [s.expected.position, s.observed.position]),
134
+ )
135
+ const max = Math.max(
136
+ min + 1,
137
+ ...finite.flatMap((s) => [s.expected.position, s.observed.position]),
138
+ )
139
+ const point = (at: number, y: number) =>
140
+ `${(40 + (at / end) * 560).toFixed(2)},${(180 - ((y - min) / (max - min)) * 140).toFixed(2)}`
141
+ const ids = [...new Set(finite.map((s) => s.id))]
142
+ const lines = ids
143
+ .map((id) => {
144
+ const rows = finite.filter((s) => s.id === id)
145
+ return `<polyline fill="none" stroke="#176b5b" stroke-width="2" points="${rows.map((s) => point(s.at, s.expected.position)).join(' ')}"/><polyline fill="none" stroke="#b7355f" stroke-width="2" stroke-dasharray="4 3" points="${rows.map((s) => point(s.at, s.observed.position)).join(' ')}"/>`
146
+ })
147
+ .join('')
148
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="640" height="220" viewBox="0 0 640 220"><rect width="640" height="220" fill="#faf8f1"/><g font-family="sans-serif" font-size="12" fill="#202630"><text x="20" y="20">Presentation position (DIP): green expected / pink observed</text><text x="40" y="205">0 ms</text><text x="540" y="205">${end.toFixed(0)} ms</text><text x="8" y="45">${max.toFixed(0)}</text><text x="8" y="180">${min.toFixed(0)}</text></g><path d="M40 35 V180 H605" fill="none" stroke="#bfc5be"/>${lines}</svg>`
149
+ }
@@ -0,0 +1,201 @@
1
+ import { isIOS, ScrollView, Utils, type View } from '@nativescript/core'
2
+ import { GestureSurface } from '../gestures/index.js'
3
+ import {
4
+ liveSpringDriver,
5
+ nativeLiveNode,
6
+ type LiveNode,
7
+ type LiveBinding,
8
+ } from '../live-spring-driver.js'
9
+ import { retainScrollDelegate } from '../driver/ios-scroll-delegate.js'
10
+ import { nativeTracePosition } from './native.js'
11
+ import {
12
+ handoffIds,
13
+ handoffInput,
14
+ handoffMotions,
15
+ type HandoffIds,
16
+ } from './scroll-handoff.js'
17
+ import type { TraceMotion } from './trace.js'
18
+ import type { ReplayAdapter } from './replay.js'
19
+
20
+ /** Isolated native contact replay. Uses the production gesture session's consumption code.
21
+ * It holds the sheet at release; free spring settling and OS recognition are separate tests.
22
+ */
23
+ export function nativeScrollHandoffTraceGraph(
24
+ motions: readonly TraceMotion[],
25
+ surface: GestureSurface,
26
+ scroll: ScrollView,
27
+ ids: HandoffIds = handoffIds,
28
+ ): ReplayAdapter {
29
+ const config = handoffMotions(motions, ids)
30
+ let parent: View | undefined = scroll.parent as View | undefined
31
+ while (parent && parent !== surface) parent = parent.parent as View | undefined
32
+ if (
33
+ !(surface instanceof GestureSurface) ||
34
+ !(scroll instanceof ScrollView) ||
35
+ scroll.orientation !== 'vertical' ||
36
+ parent !== surface ||
37
+ !surface.isLoaded ||
38
+ !scroll.isLoaded
39
+ )
40
+ throw new TypeError(
41
+ 'Handoff replay requires a loaded GestureSurface and descendant vertical ScrollView.',
42
+ )
43
+ if (
44
+ isIOS
45
+ ? typeof JoltGestureSession === 'undefined' ||
46
+ !JoltGestureSession.supportsScrollReplay?.()
47
+ : typeof org === 'undefined' ||
48
+ !org.rafaelaugusto.jolt.GestureSession.supportsScrollReplay?.()
49
+ )
50
+ throw new Error('Rebuild the native app to use scroll handoff replay.')
51
+ if (Math.abs(scroll.scrollableHeight - config.scroll.max) > 1)
52
+ throw new RangeError('The loaded scroll range differs from the recorded geometry.')
53
+ if (
54
+ isIOS
55
+ ? JoltGestureSession.hasSession(surface.nativeViewProtected)
56
+ : (
57
+ surface.nativeViewProtected as org.rafaelaugusto.jolt.GestureSurface
58
+ ).hasSession()
59
+ )
60
+ throw new Error('Replay requires an unowned gesture surface.')
61
+ const count = () =>
62
+ isIOS ? JoltLiveSpring.nodeCount() : org.rafaelaugusto.jolt.LiveSpring.nodeCount()
63
+ const baseline = count(),
64
+ nodes: LiveNode[] = []
65
+ const surfaceInput = surface.isUserInteractionEnabled,
66
+ scrollInput = scroll.isUserInteractionEnabled
67
+ let claimedInput = false
68
+ let binding: LiveBinding | undefined,
69
+ releaseDelegate = () => {},
70
+ disposed = false,
71
+ ownsVelocity = false
72
+ let session:
73
+ | {
74
+ input(phase: number, delta: number, velocity: number): void
75
+ offset(value: number): void
76
+ dispose(): void
77
+ }
78
+ | undefined
79
+ const dispose = () => {
80
+ if (disposed) return
81
+ disposed = true
82
+ try {
83
+ session?.dispose()
84
+ } finally {
85
+ releaseDelegate()
86
+ binding?.cancel()
87
+ nodes.forEach((node) => node.dispose())
88
+ if (claimedInput) {
89
+ surface.isUserInteractionEnabled = surfaceInput
90
+ scroll.isUserInteractionEnabled = scrollInput
91
+ }
92
+ }
93
+ }
94
+ try {
95
+ const physics = {
96
+ stiffness: config.sheet.stiffness,
97
+ damping: config.sheet.damping,
98
+ mass: config.sheet.mass,
99
+ restDelta: 0.001,
100
+ restSpeed: 0.01,
101
+ }
102
+ for (const initial of [0, config.sheet.initial, 1, 0])
103
+ nodes.push(liveSpringDriver().create(initial, physics, false))
104
+ const options = JSON.stringify({
105
+ replay: true,
106
+ axis: 2,
107
+ threshold: 8,
108
+ failOffset: 12,
109
+ minX: 0,
110
+ maxX: 0,
111
+ minY: config.sheet.min,
112
+ maxY: config.sheet.max,
113
+ minScale: 1,
114
+ maxScale: 1,
115
+ pinch: false,
116
+ rotate: false,
117
+ tap: false,
118
+ doubleTap: false,
119
+ })
120
+ if (isIOS) {
121
+ const n = nodes.map(nativeLiveNode) as JoltLiveSpring[]
122
+ const native = JoltGestureSession.attachScrollXYScaleRotationOptionsOnState(
123
+ surface.nativeViewProtected,
124
+ scroll.nativeViewProtected,
125
+ n[0]!,
126
+ n[1]!,
127
+ n[2]!,
128
+ n[3]!,
129
+ options,
130
+ () => {},
131
+ )
132
+ session = {
133
+ input: (phase, delta, velocity) =>
134
+ native.replayScrollDeltaVelocity(phase, delta, velocity),
135
+ offset: (value) => native.replayScrollOffset(value),
136
+ dispose: () => native.dispose(),
137
+ }
138
+ releaseDelegate = retainScrollDelegate(scroll, () => native.refreshScrollDelegate())
139
+ } else {
140
+ const n = nodes.map(nativeLiveNode) as org.rafaelaugusto.jolt.LiveSpring[]
141
+ const native = new org.rafaelaugusto.jolt.GestureSession(
142
+ surface.nativeViewProtected,
143
+ scroll.nativeViewProtected,
144
+ n[0]!,
145
+ n[1]!,
146
+ n[2]!,
147
+ n[3]!,
148
+ options,
149
+ new org.rafaelaugusto.jolt.GestureSession.Listener({ onState() {} }),
150
+ )
151
+ session = {
152
+ input: (phase, delta, velocity) => native.replayScroll(phase, delta, velocity),
153
+ offset: (value) => native.replayScrollOffset(value),
154
+ dispose: () => native.dispose(),
155
+ }
156
+ }
157
+ // Claim input and bind only after native ownership validation succeeds.
158
+ claimedInput = true
159
+ surface.isUserInteractionEnabled = false
160
+ scroll.isUserInteractionEnabled = false
161
+ binding = nodes[1]!.bind(surface, 'y', [])
162
+ session.offset(config.scroll.initial)
163
+ } catch (error) {
164
+ dispose()
165
+ throw error
166
+ }
167
+ const input = handoffInput((phase, delta, velocity) => {
168
+ const before = nodes[1]!.position()
169
+ session!.input(phase, delta, velocity)
170
+ ownsVelocity = phase === 2 && nodes[1]!.position() !== before
171
+ })
172
+ return {
173
+ input(event) {
174
+ if (disposed) throw new Error('Handoff graph is disposed.')
175
+ if (event.type === 'gesture' && event.id === ids.sheet) input.gesture(event)
176
+ else if (event.type === 'scroll' && event.id === ids.scroll) {
177
+ if (event.offset < 0 || event.offset > config.scroll.max)
178
+ throw new RangeError('Scroll offset is outside the recorded bounds.')
179
+ session!.offset(event.offset)
180
+ } else if (event.type === 'lifecycle') input.lifecycle(event.state)
181
+ else throw new Error(`Handoff has no adapter for ${event.type}.`)
182
+ },
183
+ read(id) {
184
+ if (id !== ids.sheet && id !== ids.scroll)
185
+ throw new Error('Unknown handoff view ID.')
186
+ const offset = isIOS
187
+ ? (scroll.nativeViewProtected as UIScrollView).contentOffset.y +
188
+ (scroll.nativeViewProtected as UIScrollView).adjustedContentInset.top
189
+ : Utils.layout.toDeviceIndependentPixels(
190
+ (scroll.nativeViewProtected as android.view.View).getScrollY(),
191
+ )
192
+ return {
193
+ position: id === ids.sheet ? nativeTracePosition(surface, 'y') : offset,
194
+ velocity: id === ids.sheet && ownsVelocity ? nodes[1]!.velocity() : 0,
195
+ settled: !input.contact && !nodes[1]!.moving(),
196
+ }
197
+ },
198
+ dispose,
199
+ resources: () => (disposed ? Math.max(0, count() - baseline) : nodes.length + 2),
200
+ }
201
+ }
@@ -0,0 +1,140 @@
1
+ import type { ReplayAdapter } from './replay.js'
2
+ import { parseTrace, type TraceInput, type TraceMotion } from './trace.js'
3
+
4
+ export interface HandoffIds {
5
+ sheet: string
6
+ scroll: string
7
+ }
8
+ export const handoffIds: HandoffIds = { sheet: 'sheet', scroll: 'scroll' }
9
+
10
+ /** Both entries describe bounded y positions; no free-running spring is part of this adapter. */
11
+ export function handoffMotions(motions: readonly TraceMotion[], ids = handoffIds) {
12
+ // Reuse the trace schema rather than trusting a cast from a file or consumer.
13
+ const validated = parseTrace({
14
+ version: 1,
15
+ seed: 0,
16
+ settings: { timeScale: 1, reducedMotion: false },
17
+ metadata: {
18
+ platform: 'test',
19
+ os: 'test',
20
+ model: 'test',
21
+ refreshRate: 60,
22
+ density: 1,
23
+ width: 1,
24
+ height: 1,
25
+ },
26
+ motions,
27
+ entries: [],
28
+ }).motions
29
+ const sheet = validated.find((m) => m.id === ids.sheet),
30
+ scroll = validated.find((m) => m.id === ids.scroll)
31
+ if (
32
+ validated.length !== 2 ||
33
+ !sheet ||
34
+ !scroll ||
35
+ sheet === scroll ||
36
+ validated.some((m) => m.kind !== 'drag' || m.axis !== 'y' || m.snap.length) ||
37
+ scroll.min !== 0
38
+ )
39
+ throw new TypeError(
40
+ 'Handoff needs two distinct y drag motions, no snap, and scroll min 0.',
41
+ )
42
+ return { sheet, scroll }
43
+ }
44
+
45
+ /** Normalize cumulative contact positions once; membership changes rebase without a delta. */
46
+ export function handoffInput(
47
+ send: (phase: number, delta: number, velocity: number) => void,
48
+ ) {
49
+ let contact = false,
50
+ suspended = false,
51
+ previous = 0,
52
+ pointers = ''
53
+ return {
54
+ get contact() {
55
+ return contact
56
+ },
57
+ gesture(event: Extract<TraceInput, { type: 'gesture' }>) {
58
+ if (suspended) return
59
+ if (event.phase === 'begin') {
60
+ contact = true
61
+ previous = event.y
62
+ pointers = event.pointers.join(',')
63
+ send(1, 0, 0)
64
+ } else if (contact && event.phase === 'move') {
65
+ const next = event.pointers.join(',')
66
+ const changed = pointers !== next
67
+ const delta = changed ? 0 : event.y - previous
68
+ previous = event.y
69
+ pointers = next
70
+ send(2, delta, changed ? 0 : event.velocityY)
71
+ } else if (contact) {
72
+ contact = false
73
+ send(event.phase === 'cancel' ? 4 : 3, 0, 0)
74
+ }
75
+ },
76
+ lifecycle(state: string) {
77
+ if (state === 'suspend' || state === 'unload') {
78
+ suspended = true
79
+ contact = false
80
+ send(4, 0, 0)
81
+ } else suspended = false
82
+ },
83
+ }
84
+ }
85
+
86
+ /** Independent headless contract: scroll to its top before pulling the sheet down;
87
+ * expand the sheet before scrolling content up. Native replay exercises the production policy.
88
+ */
89
+ export function scrollHandoffTraceGraph(
90
+ motions: readonly TraceMotion[],
91
+ ids: HandoffIds = handoffIds,
92
+ ): ReplayAdapter {
93
+ const config = handoffMotions(motions, ids)
94
+ let y = config.sheet.initial,
95
+ offset = config.scroll.initial,
96
+ velocity = 0,
97
+ disposed = false
98
+ const input = handoffInput((phase, delta, speed) => {
99
+ if (phase !== 2) {
100
+ velocity = 0
101
+ return
102
+ }
103
+ const before = y
104
+ if (delta > 0) {
105
+ const content = Math.min(offset, delta)
106
+ offset -= content
107
+ y = Math.min(config.sheet.max, y + delta - content)
108
+ } else {
109
+ const panel = Math.min(y - config.sheet.min, -delta)
110
+ y -= panel
111
+ offset = Math.min(config.scroll.max, offset - delta - panel)
112
+ }
113
+ velocity = y === before ? 0 : speed
114
+ })
115
+ return {
116
+ input(event) {
117
+ if (disposed) throw new Error('Handoff graph is disposed.')
118
+ if (event.type === 'gesture' && event.id === ids.sheet) input.gesture(event)
119
+ else if (event.type === 'scroll' && event.id === ids.scroll) {
120
+ if (event.offset < 0 || event.offset > config.scroll.max)
121
+ throw new RangeError('Scroll offset is outside the recorded bounds.')
122
+ offset = event.offset
123
+ } else if (event.type === 'lifecycle') input.lifecycle(event.state)
124
+ else throw new Error(`Handoff has no adapter for ${event.type}.`)
125
+ },
126
+ read(id) {
127
+ if (id !== ids.sheet && id !== ids.scroll)
128
+ throw new Error('Unknown handoff view ID.')
129
+ return {
130
+ position: id === ids.sheet ? y : offset,
131
+ velocity: id === ids.sheet ? velocity : 0,
132
+ settled: !input.contact,
133
+ }
134
+ },
135
+ dispose() {
136
+ disposed = true
137
+ },
138
+ resources: () => (disposed ? 0 : 1),
139
+ }
140
+ }
@@ -0,0 +1,41 @@
1
+ import type { Sensor } from '../sensors/index.js'
2
+ import { sensorDriver } from '../sensors/native.js'
3
+ /** Explicit canonical test inputs. These are synthetic samples, never evidence from device hardware. */
4
+ export interface SensorSample {
5
+ /** Relative milliseconds from the start of playback. */
6
+ time: number
7
+ /** Device-coordinate quaternion xyzw for rotation; downward m/s² xyz for gravity. */
8
+ values: readonly number[]
9
+ /** Interface clockwise basis angle from device coordinates, in degrees. */
10
+ orientation?: 0 | 90 | 180 | 270
11
+ }
12
+ /** Play finite test inputs through the native sensor pipeline; hardware is detached during playback. */
13
+ export function replaySensor(source: Sensor, samples: readonly SensorSample[]): void {
14
+ if (!Array.isArray(samples) || samples.length < 2 || samples.length > 10000)
15
+ throw new RangeError('Use 2–10000 sensor samples.')
16
+ let previous = -1
17
+ for (const sample of samples) {
18
+ if (
19
+ !Number.isFinite(sample.time) ||
20
+ sample.time <= previous ||
21
+ sample.time > 60000 ||
22
+ sample.time < 0
23
+ )
24
+ throw new RangeError('Sensor times must increase within 0–60000 milliseconds.')
25
+ previous = sample.time
26
+ if (
27
+ !Array.isArray(sample.values) ||
28
+ sample.values.length !== (source.kind === 'rotation' ? 4 : 3) ||
29
+ sample.values.some((value: number) => !Number.isFinite(value))
30
+ )
31
+ throw new TypeError('Invalid canonical sensor sample.')
32
+ if (source.kind === 'rotation' && Math.hypot(...sample.values) < 1e-8)
33
+ throw new RangeError('A quaternion cannot be zero.')
34
+ if (
35
+ sample.orientation !== undefined &&
36
+ ![0, 90, 180, 270].includes(sample.orientation)
37
+ )
38
+ throw new RangeError('Invalid interface orientation.')
39
+ }
40
+ sensorDriver(source).replay(JSON.stringify(samples))
41
+ }