@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
package/src/transition.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { resolveEasing, type Easing, type EasingFunction } from './easing.js'
1
+ import { linear, resolveEasing, type Easing, type EasingFunction } from './easing.js'
2
2
  import type { Property } from './properties.js'
3
3
  import { isDecorationProperty } from './decoration.js'
4
4
  import { isColorProperty } from './color.js'
5
5
  import { springPhysics, type SpringPhysics } from './spring.js'
6
6
  import type { DragCurve } from './drag-physics.js'
7
+ import { DEFAULT_ACCELERATION, DEFAULT_RESTITUTION } from './gravity.js'
7
8
 
8
9
  export interface Timing {
9
10
  /** Milliseconds to wait before starting. The first keyframe is applied right away. */
@@ -12,8 +13,15 @@ export interface Timing {
12
13
  repeat?: number
13
14
  /** `reverse` plays every other repeat backwards. */
14
15
  repeatType?: 'loop' | 'reverse'
16
+ /**
17
+ * Milliseconds to hold the end value before each repeat. The first play doesn't wait.
18
+ * `[min, max]` draws a new pause for each repeat.
19
+ */
20
+ repeatDelay?: number | RepeatDelayRange
15
21
  }
16
22
 
23
+ export type RepeatDelayRange = readonly [min: number, max: number]
24
+
17
25
  export interface Tween extends Timing {
18
26
  type?: 'tween'
19
27
  /** Milliseconds. */
@@ -22,6 +30,11 @@ export interface Tween extends Timing {
22
30
  ease?: Easing | readonly Easing[]
23
31
  /** Where each keyframe sits, from 0 to 1. Evenly spaced by default. */
24
32
  times?: readonly number[]
33
+ /**
34
+ * Run one `ease` over the whole track instead of each segment, with straight lines
35
+ * between keyframes, like React Native's `interpolate`.
36
+ */
37
+ easeTrack?: boolean
25
38
  }
26
39
 
27
40
  export interface Spring extends Timing {
@@ -37,7 +50,19 @@ export interface Spring extends Timing {
37
50
  velocity?: number
38
51
  }
39
52
 
40
- export type Transition = Tween | Spring
53
+ export interface Gravity extends Timing {
54
+ type: 'gravity'
55
+ /** Positive acceleration toward the final value, in units per second squared. Default 1800. */
56
+ acceleration?: number
57
+ /** Fraction of impact speed retained by each bounce, from 0 (no bounce) to less than 1. Default 0.55. */
58
+ restitution?: number
59
+ /** Signed units per second. Defaults to the velocity of the animation it interrupts. */
60
+ velocity?: number
61
+ /** Duration is determined by the physical parameters. */
62
+ duration?: never
63
+ }
64
+
65
+ export type Transition = Tween | Spring | Gravity
41
66
 
42
67
  export type SpringName = 'smooth' | 'snappy' | 'bouncy'
43
68
 
@@ -47,13 +72,51 @@ export const springs: Record<SpringName, Spring> = {
47
72
  bouncy: { type: 'spring', duration: 550, bounce: 0.4 },
48
73
  }
49
74
 
75
+ export interface OrigamiSpring {
76
+ /** React Native's default is 7. */
77
+ friction?: number
78
+ /** React Native's default is 40. */
79
+ tension?: number
80
+ }
81
+
82
+ /**
83
+ * The spring React Native's `Animated.spring` plays for `friction` and `tension`,
84
+ * converted with the same Origami formulas.
85
+ *
86
+ * ```ts
87
+ * animate(card, { x: 100 }, origamiSpring({ friction: 7, tension: 40 }))
88
+ * ```
89
+ */
90
+ export function origamiSpring({
91
+ friction = 7,
92
+ tension = 40,
93
+ }: OrigamiSpring = {}): Spring {
94
+ if (!Number.isFinite(friction) || !Number.isFinite(tension))
95
+ throw new RangeError('Origami friction and tension must be finite.')
96
+ const stiffness = (tension - 30) * 3.62 + 194
97
+ const damping = (friction - 8) * 3 + 25
98
+ if (stiffness <= 0 || damping < 0)
99
+ throw new RangeError(
100
+ `Origami tension ${tension} and friction ${friction} give no spring (stiffness ${stiffness}, damping ${damping}).`,
101
+ )
102
+ return { type: 'spring', stiffness, damping, mass: 1 }
103
+ }
104
+
50
105
  export type Curve =
51
106
  | DragCurve
107
+ | {
108
+ type: 'gravity'
109
+ acceleration: number
110
+ restitution: number
111
+ velocity: number | undefined
112
+ }
52
113
  | {
53
114
  type: 'tween'
54
115
  duration: number
55
116
  ease: readonly EasingFunction[]
56
117
  times: readonly number[] | undefined
118
+ /** One easing over the whole track; `ease` is then linear per segment. */
119
+ track?: EasingFunction
57
120
  }
58
121
  | { type: 'spring'; physics: SpringPhysics; velocity: number | undefined }
59
122
  | {
@@ -68,11 +131,23 @@ export interface ResolvedTransition {
68
131
  delay: number
69
132
  repeat: number
70
133
  reverse: boolean
134
+ repeatDelay?: number | RepeatDelayRange
135
+ /** Draws the pauses of a `repeatDelay` range; tracks of one animation share it. */
136
+ seed?: number
71
137
  }
72
138
 
73
139
  const springKeys = ['stiffness', 'damping', 'mass', 'bounce', 'velocity'] as const
74
- const curveKeys = ['type', 'duration', 'ease', 'times', ...springKeys] as const
75
- const timingKeys = ['delay', 'repeat', 'repeatType'] as const
140
+ const curveKeys = [
141
+ 'type',
142
+ 'duration',
143
+ 'ease',
144
+ 'times',
145
+ 'easeTrack',
146
+ 'acceleration',
147
+ 'restitution',
148
+ ...springKeys,
149
+ ] as const
150
+ const timingKeys = ['delay', 'repeat', 'repeatType', 'repeatDelay'] as const
76
151
 
77
152
  export const DEFAULT_DURATION = 300
78
153
 
@@ -90,11 +165,59 @@ export function timingOf(transition: Transition): Timing {
90
165
  return timing
91
166
  }
92
167
 
93
- /** Timing merges key by key, the curve is taken whole from whichever side has one. */
168
+ const isSpring = (transition: Transition) =>
169
+ transition.type === 'spring' ||
170
+ springKeys.some((key) => (transition as Spring)[key] !== undefined)
171
+
172
+ /** Curve keys a merged transition took from the main one rather than from its override. */
173
+ const inherited = new WeakMap<Transition, ReadonlySet<string>>()
174
+
175
+ /**
176
+ * Timing merges key by key. Over a tween, a curve that stays a tween merges key by key too;
177
+ * otherwise the curve is taken whole from whichever side has one.
178
+ */
94
179
  export function mergeTransitions(base: Transition, override: Transition): Transition {
95
- return hasCurve(override)
96
- ? { ...timingOf(base), ...override }
97
- : { ...base, ...timingOf(override) }
180
+ if (!hasCurve(override)) {
181
+ const merged = { ...base, ...timingOf(override) }
182
+ const taken = inherited.get(base)
183
+ if (taken) inherited.set(merged, taken)
184
+ return merged
185
+ }
186
+ if (
187
+ !hasCurve(base) ||
188
+ base.type === 'gravity' ||
189
+ override.type === 'gravity' ||
190
+ isSpring(base) ||
191
+ isSpring(override)
192
+ )
193
+ return { ...timingOf(base), ...override }
194
+ const merged = { ...base, ...override } as Transition
195
+ const own = override as Record<string, unknown>
196
+ inherited.set(
197
+ merged,
198
+ new Set(
199
+ curveKeys.filter(
200
+ (key) =>
201
+ (base as Record<string, unknown>)[key] !== undefined && own[key] === undefined,
202
+ ),
203
+ ),
204
+ )
205
+ return merged
206
+ }
207
+
208
+ /** Drops inherited `times` and per-segment easings that don't fit this property's keyframes. */
209
+ export function fitTransition(transition: Transition, keyframes: number): Transition {
210
+ const taken = inherited.get(transition)
211
+ if (!taken) return transition
212
+ const tween = { ...transition } as Tween
213
+ const segments = (ease: Tween['ease']) =>
214
+ ease !== undefined && isEasingList(ease) ? ease.length : undefined
215
+ if (taken.has('times') && tween.times && tween.times.length !== keyframes)
216
+ delete tween.times
217
+ if (taken.has('ease') && (segments(tween.ease) ?? keyframes - 1) !== keyframes - 1)
218
+ delete tween.ease
219
+ if (taken.has('easeTrack') && segments(tween.ease) !== undefined) delete tween.easeTrack
220
+ return tween
98
221
  }
99
222
 
100
223
  export function resolveTransition(
@@ -119,9 +242,63 @@ export function resolveTransition(
119
242
  if (delay < 0 || Number.isNaN(delay)) throw new RangeError(`Invalid delay: ${delay}.`)
120
243
  if (repeat < 0 || Number.isNaN(repeat))
121
244
  throw new RangeError(`Invalid repeat: ${repeat}.`)
122
- const timing = { delay, repeat, reverse: transition.repeatType === 'reverse' }
245
+ const repeatDelay = transition.repeatDelay ?? 0
246
+ const [shortest, longest] =
247
+ typeof repeatDelay === 'number' ? [repeatDelay, repeatDelay] : repeatDelay
248
+ if (
249
+ (typeof repeatDelay !== 'number' &&
250
+ (!Array.isArray(repeatDelay) || repeatDelay.length !== 2)) ||
251
+ !Number.isFinite(shortest) ||
252
+ !Number.isFinite(longest) ||
253
+ shortest! < 0 ||
254
+ shortest! > longest!
255
+ )
256
+ throw new RangeError(`Invalid repeat delay: ${JSON.stringify(repeatDelay)}.`)
257
+ const timing = {
258
+ delay,
259
+ repeat,
260
+ reverse: transition.repeatType === 'reverse',
261
+ ...(longest! > 0 && repeat > 0 && { repeatDelay }),
262
+ ...(longest! > shortest! && repeat > 0 && { seed: Math.random() }),
263
+ }
264
+
265
+ if (type === 'gravity') {
266
+ if (property !== 'x' && property !== 'y')
267
+ throw new TypeError('Gravity applies to x, y or a numeric motion value.')
268
+ if (keyframes !== 2)
269
+ throw new TypeError('Gravity needs a start and one fixed landing position.')
270
+ const gravity = transition as Gravity
271
+ const acceleration = gravity.acceleration ?? DEFAULT_ACCELERATION
272
+ const restitution = gravity.restitution ?? DEFAULT_RESTITUTION
273
+ if (!Number.isFinite(acceleration) || acceleration <= 0)
274
+ throw new RangeError('Gravity acceleration must be finite and positive.')
275
+ if (!Number.isFinite(restitution) || restitution < 0 || restitution >= 1)
276
+ throw new RangeError('Gravity restitution must be at least 0 and less than 1.')
277
+ if (gravity.velocity !== undefined && !Number.isFinite(gravity.velocity))
278
+ throw new RangeError('Gravity velocity must be finite.')
279
+ for (const key of [
280
+ 'duration',
281
+ 'ease',
282
+ 'times',
283
+ 'easeTrack',
284
+ 'stiffness',
285
+ 'damping',
286
+ 'mass',
287
+ 'bounce',
288
+ ])
289
+ if ((transition as unknown as Record<string, unknown>)[key] !== undefined)
290
+ throw new TypeError(
291
+ `Gravity does not accept "${key}"; timing comes from its physics.`,
292
+ )
293
+ return {
294
+ ...timing,
295
+ curve: { type, acceleration, restitution, velocity: gravity.velocity },
296
+ }
297
+ }
123
298
 
124
299
  if (type === 'spring') {
300
+ if ((transition as Tween).easeTrack)
301
+ throw new TypeError('easeTrack applies to tweens, not springs.')
125
302
  if (keyframes > 2) {
126
303
  throw new Error(
127
304
  `A spring goes from one value to another, but "${property}" has ${keyframes} keyframes. Use a tween for keyframes.`,
@@ -147,6 +324,10 @@ export function resolveTransition(
147
324
 
148
325
  const segments = keyframes - 1
149
326
  const ease = tween.ease ?? 'easeOut'
327
+ if (tween.easeTrack && isEasingList(ease))
328
+ throw new TypeError(
329
+ 'easeTrack runs one easing over the whole track; pass a single ease.',
330
+ )
150
331
  const eases = isEasingList(ease) ? ease : Array.from({ length: segments }, () => ease)
151
332
  if (eases.length !== segments) {
152
333
  throw new Error(
@@ -168,6 +349,13 @@ export function resolveTransition(
168
349
  }
169
350
  }
170
351
 
352
+ if (tween.easeTrack) {
353
+ const track = resolveEasing(ease as Easing)
354
+ return {
355
+ ...timing,
356
+ curve: { type, duration, ease: eases.map(() => linear), times, track },
357
+ }
358
+ }
171
359
  return {
172
360
  ...timing,
173
361
  curve: { type, duration, ease: eases.map(resolveEasing), times },
package/src/types.ts CHANGED
@@ -48,6 +48,11 @@ export interface Keyframes {
48
48
  /** Properties that can be timed or stopped independently. A path owns x/y and optionally rotate. */
49
49
  export type KeyframeProperty = Exclude<keyof Keyframes, 'path' | 'orient'>
50
50
 
51
+ /** One value per property, as `set()` applies them. */
52
+ export type Values = {
53
+ [K in KeyframeProperty]?: Exclude<Keyframes[K], readonly unknown[]>
54
+ }
55
+
51
56
  /** A view, or anything that holds one: a NativeScript-Vue element, an Angular `ElementRef`. */
52
57
  export type Target =
53
58
  View | { readonly nativeView: View } | { readonly nativeElement: View }
@@ -79,6 +84,11 @@ export type AnimateOptions = Transition & {
79
84
  relative?: boolean
80
85
  /** With several targets, delays each one by this much more than the previous. */
81
86
  stagger?: number | Stagger
82
- /** iOS impact feedback at arrival, or at explicit points in a finite animation. */
87
+ /** Native haptic feedback at arrival, or at explicit points in a finite animation. */
83
88
  haptic?: Haptic
89
+ /**
90
+ * Plays on a named layer, on top of the property's other animations instead of replacing
91
+ * them. Translations and rotations add; scale and opacity multiply.
92
+ */
93
+ layer?: string
84
94
  }
@@ -0,0 +1,147 @@
1
+ import { Application, Color, Trace } from '@nativescript/core'
2
+ import { getDriver } from './driver/index.js'
3
+
4
+ export interface SubscribeOptions {
5
+ /** Deliver the current value synchronously when subscribing. Defaults to true. */
6
+ immediate?: boolean
7
+ }
8
+
9
+ /** `time` is milliseconds on the native animation clock, shared by a notification batch. */
10
+ export type ValueListener<T> = (value: T, time: number) => void
11
+
12
+ interface Observer {
13
+ read(value: number): number
14
+ color: boolean
15
+ listener: ValueListener<number | Color>
16
+ previous: number
17
+ }
18
+
19
+ // Only sources that need a frame live here. Idle subscriptions retain no global root reference.
20
+ const pending = new Set<ValueObservers>()
21
+ let cancelFrame: (() => void) | undefined
22
+ let listening = false
23
+ let suspended = false
24
+
25
+ function suspend() {
26
+ suspended = true
27
+ cancelFrame?.()
28
+ cancelFrame = undefined
29
+ }
30
+
31
+ function resume() {
32
+ suspended = false
33
+ schedule()
34
+ }
35
+
36
+ function schedule() {
37
+ if (!pending.size) {
38
+ cancelFrame?.()
39
+ cancelFrame = undefined
40
+ if (listening && !suspended) {
41
+ Application.off(Application.suspendEvent, suspend)
42
+ Application.off(Application.resumeEvent, resume)
43
+ listening = false
44
+ }
45
+ return
46
+ }
47
+ if (!listening) {
48
+ Application.on(Application.suspendEvent, suspend)
49
+ Application.on(Application.resumeEvent, resume)
50
+ listening = true
51
+ }
52
+ if (cancelFrame || suspended) return
53
+ cancelFrame = getDriver().frame(() => {
54
+ cancelFrame = undefined
55
+ const time = getDriver().now()
56
+ const sources = [...pending]
57
+ pending.clear()
58
+ // Capture every source before calling any listener: reentrant writes belong to the next batch.
59
+ const deliveries = sources.map((source) => source.snapshot(time))
60
+ for (const source of sources) if (source.active) pending.add(source)
61
+ for (const deliver of deliveries) deliver()
62
+ schedule()
63
+ })
64
+ }
65
+
66
+ function deliver(observer: Observer, value: number, time: number) {
67
+ try {
68
+ observer.listener(observer.color ? new Color(value) : value, time)
69
+ } catch (error) {
70
+ // A consumer failure must not interrupt other consumers or strand the shared frame source.
71
+ Trace.write(
72
+ `Jolt motion value subscriber failed: ${error instanceof Error ? error.stack : String(error)}`,
73
+ Trace.categories.Error,
74
+ Trace.messageType.error,
75
+ )
76
+ }
77
+ }
78
+
79
+ /** Root-owned subscriptions; mappings are evaluated only for consumers that opted in. */
80
+ export class ValueObservers {
81
+ private readonly observers = new Set<Observer>()
82
+ private running = false
83
+
84
+ constructor(
85
+ private readonly read: (time: number) => number,
86
+ private readonly isRunning?: () => boolean,
87
+ ) {}
88
+
89
+ get size() {
90
+ return this.observers.size
91
+ }
92
+
93
+ get active() {
94
+ return (this.isRunning?.() ?? this.running) && this.observers.size > 0
95
+ }
96
+
97
+ subscribe(
98
+ read: (value: number) => number,
99
+ color: boolean,
100
+ listener: ValueListener<number | Color>,
101
+ options: SubscribeOptions = {},
102
+ ): () => void {
103
+ if (typeof listener !== 'function')
104
+ throw new TypeError('subscribe() needs a listener function.')
105
+ const time = getDriver().now()
106
+ const observer = { read, color, listener, previous: read(this.read(time)) }
107
+ this.observers.add(observer)
108
+ if (options.immediate !== false) deliver(observer, observer.previous, time)
109
+ if (this.active) this.changed(true)
110
+ return () => {
111
+ this.observers.delete(observer)
112
+ if (!this.observers.size) {
113
+ pending.delete(this)
114
+ schedule()
115
+ }
116
+ }
117
+ }
118
+
119
+ changed(running: boolean) {
120
+ this.running = running
121
+ if (this.observers.size) {
122
+ pending.add(this)
123
+ schedule()
124
+ }
125
+ }
126
+
127
+ clear() {
128
+ this.observers.clear()
129
+ pending.delete(this)
130
+ this.running = false
131
+ schedule()
132
+ }
133
+
134
+ snapshot(time: number): () => void {
135
+ const value = this.read(time)
136
+ const deliveries = [...this.observers].flatMap((observer) => {
137
+ const next = observer.read(value)
138
+ if (Object.is(next, observer.previous)) return []
139
+ observer.previous = next
140
+ return [{ observer, next }]
141
+ })
142
+ return () => {
143
+ for (const { observer, next } of deliveries)
144
+ if (this.observers.has(observer)) deliver(observer, next, time)
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,71 @@
1
+ import { instantTrack, type Track } from './track.js'
2
+
3
+ export interface ValuePart {
4
+ readonly track: Track
5
+ readonly elapsed: number
6
+ readonly base: number
7
+ readonly span: number
8
+ }
9
+
10
+ /** Compile scalar addition before any binding's mapping. The snapshot is independent of later edits. */
11
+ export function valueTrack(parts: readonly ValuePart[], rest: number) {
12
+ const value = (time: number) =>
13
+ parts.reduce(
14
+ (sum, part) =>
15
+ sum + part.base + part.span * part.track.valueAt(part.elapsed + time),
16
+ rest,
17
+ )
18
+ let finite = 0
19
+ const periods: number[] = []
20
+ for (const { track, elapsed } of parts) {
21
+ if (Number.isFinite(track.end)) finite = Math.max(finite, track.end - elapsed)
22
+ else if (elapsed < track.delay) finite = Math.max(finite, track.delay - elapsed)
23
+ else periods.push(Math.max(1, track.duration * (track.reverse ? 2 : 1)))
24
+ }
25
+ if (finite <= 0 && !periods.length)
26
+ return { track: instantTrack('x', value(0)), windowed: false }
27
+ const loop = finite <= 0 && periods.length ? commonPeriod(periods) : undefined
28
+ // Bound finite compositions too: a minutes-long base must not undersample a short pulse.
29
+ const duration = finite > 0 ? Math.min(finite, 4000) : (loop ?? 4000)
30
+ const steps = Math.max(1, Math.min(6000, Math.ceil((duration * 60) / 1000)))
31
+ const times = Array.from({ length: steps + 1 }, (_, i) => i / steps)
32
+ const values = times.map((time) => value(time * duration))
33
+ const endless = loop !== undefined
34
+ const at = (time: number) =>
35
+ value(
36
+ endless
37
+ ? ((time % duration) + duration) % duration
38
+ : Math.min(duration, Math.max(0, time)),
39
+ )
40
+ const track: Track = {
41
+ property: 'x',
42
+ delay: 0,
43
+ duration,
44
+ repeat: endless ? Infinity : 0,
45
+ reverse: false,
46
+ times,
47
+ values,
48
+ to: endless ? values[0]! : values[steps]!,
49
+ end: endless ? Infinity : duration,
50
+ arrival: endless ? Infinity : duration,
51
+ valueAt: at,
52
+ velocityAt: (time) => (at(time + 0.5) - at(time - 0.5)) * 1000,
53
+ }
54
+ return {
55
+ track,
56
+ windowed:
57
+ finite > duration ||
58
+ (!endless && parts.some(({ track }) => !Number.isFinite(track.end))),
59
+ }
60
+ }
61
+
62
+ function commonPeriod(periods: readonly number[]) {
63
+ const gcd = (a: number, b: number): number => (b ? gcd(b, a % b) : a)
64
+ let total = 1
65
+ for (const period of periods) {
66
+ if (!Number.isInteger(period)) return undefined
67
+ total = (total / gcd(total, period)) * period
68
+ if (total > 30000) return undefined
69
+ }
70
+ return total
71
+ }