@unrulysystems/native-motion-core 0.1.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (326) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +21 -0
  3. package/README.md +48 -0
  4. package/dist/clock.cjs +71 -0
  5. package/dist/clock.d.cts +23 -0
  6. package/dist/clock.d.ts +23 -0
  7. package/dist/clock.js +66 -0
  8. package/dist/collect-reads.cjs +68 -0
  9. package/dist/collect-reads.d.cts +23 -0
  10. package/dist/collect-reads.d.ts +23 -0
  11. package/dist/collect-reads.js +62 -0
  12. package/dist/component/boundedArray.cjs +74 -0
  13. package/dist/component/boundedArray.d.cts +25 -0
  14. package/dist/component/boundedArray.d.ts +25 -0
  15. package/dist/component/boundedArray.js +68 -0
  16. package/dist/component/index.cjs +57 -0
  17. package/dist/component/index.d.cts +12 -0
  18. package/dist/component/index.d.ts +12 -0
  19. package/dist/component/index.js +22 -0
  20. package/dist/component/orchestration.cjs +129 -0
  21. package/dist/component/orchestration.d.cts +66 -0
  22. package/dist/component/orchestration.d.ts +66 -0
  23. package/dist/component/orchestration.js +124 -0
  24. package/dist/component/resolve.cjs +104 -0
  25. package/dist/component/resolve.d.cts +11 -0
  26. package/dist/component/resolve.d.ts +11 -0
  27. package/dist/component/resolve.js +97 -0
  28. package/dist/component/transition.cjs +352 -0
  29. package/dist/component/transition.d.cts +33 -0
  30. package/dist/component/transition.d.ts +33 -0
  31. package/dist/component/transition.js +339 -0
  32. package/dist/component/types.cjs +114 -0
  33. package/dist/component/types.d.cts +60 -0
  34. package/dist/component/types.d.ts +60 -0
  35. package/dist/component/types.js +111 -0
  36. package/dist/component/validate.cjs +1015 -0
  37. package/dist/component/validate.d.cts +37 -0
  38. package/dist/component/validate.d.ts +37 -0
  39. package/dist/component/validate.js +1002 -0
  40. package/dist/component/variants.cjs +333 -0
  41. package/dist/component/variants.d.cts +106 -0
  42. package/dist/component/variants.d.ts +106 -0
  43. package/dist/component/variants.js +321 -0
  44. package/dist/config/constants.cjs +41 -0
  45. package/dist/config/constants.d.cts +29 -0
  46. package/dist/config/constants.d.ts +29 -0
  47. package/dist/config/constants.js +38 -0
  48. package/dist/delay.cjs +72 -0
  49. package/dist/delay.d.cts +26 -0
  50. package/dist/delay.d.ts +26 -0
  51. package/dist/delay.js +70 -0
  52. package/dist/derived.cjs +143 -0
  53. package/dist/derived.d.cts +41 -0
  54. package/dist/derived.d.ts +41 -0
  55. package/dist/derived.js +139 -0
  56. package/dist/driver/index.cjs +22 -0
  57. package/dist/driver/index.d.cts +7 -0
  58. package/dist/driver/index.d.ts +7 -0
  59. package/dist/driver/index.js +14 -0
  60. package/dist/driver/keyframeTiming.cjs +130 -0
  61. package/dist/driver/keyframeTiming.d.cts +18 -0
  62. package/dist/driver/keyframeTiming.d.ts +18 -0
  63. package/dist/driver/keyframeTiming.js +124 -0
  64. package/dist/driver/keyframeTimingConfig.cjs +24 -0
  65. package/dist/driver/keyframeTimingConfig.d.cts +5 -0
  66. package/dist/driver/keyframeTimingConfig.d.ts +5 -0
  67. package/dist/driver/keyframeTimingConfig.js +22 -0
  68. package/dist/driver/prepare.cjs +459 -0
  69. package/dist/driver/prepare.d.cts +4 -0
  70. package/dist/driver/prepare.d.ts +4 -0
  71. package/dist/driver/prepare.js +454 -0
  72. package/dist/driver/reference.cjs +762 -0
  73. package/dist/driver/reference.d.cts +53 -0
  74. package/dist/driver/reference.d.ts +53 -0
  75. package/dist/driver/reference.js +757 -0
  76. package/dist/driver/step.cjs +55 -0
  77. package/dist/driver/step.d.cts +9 -0
  78. package/dist/driver/step.d.ts +9 -0
  79. package/dist/driver/step.js +52 -0
  80. package/dist/driver/tiers.cjs +40 -0
  81. package/dist/driver/tiers.d.cts +2 -0
  82. package/dist/driver/tiers.d.ts +2 -0
  83. package/dist/driver/tiers.js +37 -0
  84. package/dist/driver/types.cjs +9 -0
  85. package/dist/driver/types.d.cts +68 -0
  86. package/dist/driver/types.d.ts +68 -0
  87. package/dist/driver/types.js +8 -0
  88. package/dist/external-animation-ledger.cjs +1250 -0
  89. package/dist/external-animation-ledger.d.cts +416 -0
  90. package/dist/external-animation-ledger.d.ts +416 -0
  91. package/dist/external-animation-ledger.js +1243 -0
  92. package/dist/gesture/directionLock.cjs +25 -0
  93. package/dist/gesture/directionLock.d.cts +8 -0
  94. package/dist/gesture/directionLock.d.ts +8 -0
  95. package/dist/gesture/directionLock.js +21 -0
  96. package/dist/gesture/dragConfig.cjs +634 -0
  97. package/dist/gesture/dragConfig.d.cts +298 -0
  98. package/dist/gesture/dragConfig.d.ts +298 -0
  99. package/dist/gesture/dragConfig.js +624 -0
  100. package/dist/gesture/elastic.cjs +44 -0
  101. package/dist/gesture/elastic.d.cts +4 -0
  102. package/dist/gesture/elastic.d.ts +4 -0
  103. package/dist/gesture/elastic.js +39 -0
  104. package/dist/gesture/handoffSession.cjs +161 -0
  105. package/dist/gesture/handoffSession.d.cts +35 -0
  106. package/dist/gesture/handoffSession.d.ts +35 -0
  107. package/dist/gesture/handoffSession.js +158 -0
  108. package/dist/gesture/index.cjs +37 -0
  109. package/dist/gesture/index.d.cts +12 -0
  110. package/dist/gesture/index.d.ts +12 -0
  111. package/dist/gesture/index.js +11 -0
  112. package/dist/gesture/projection.cjs +95 -0
  113. package/dist/gesture/projection.d.cts +7 -0
  114. package/dist/gesture/projection.d.ts +7 -0
  115. package/dist/gesture/projection.js +87 -0
  116. package/dist/gesture/session.cjs +162 -0
  117. package/dist/gesture/session.d.cts +29 -0
  118. package/dist/gesture/session.d.ts +29 -0
  119. package/dist/gesture/session.js +158 -0
  120. package/dist/gesture/types.cjs +5 -0
  121. package/dist/gesture/types.d.cts +13 -0
  122. package/dist/gesture/types.d.ts +13 -0
  123. package/dist/gesture/types.js +4 -0
  124. package/dist/gesture/viewportConstraints.cjs +38 -0
  125. package/dist/gesture/viewportConstraints.d.cts +6 -0
  126. package/dist/gesture/viewportConstraints.d.ts +6 -0
  127. package/dist/gesture/viewportConstraints.js +34 -0
  128. package/dist/graph.cjs +226 -0
  129. package/dist/graph.d.cts +2 -0
  130. package/dist/graph.d.ts +2 -0
  131. package/dist/graph.js +223 -0
  132. package/dist/index.cjs +140 -0
  133. package/dist/index.d.cts +33 -0
  134. package/dist/index.d.ts +33 -0
  135. package/dist/index.js +70 -0
  136. package/dist/inertia.cjs +214 -0
  137. package/dist/inertia.d.cts +53 -0
  138. package/dist/inertia.d.ts +53 -0
  139. package/dist/inertia.js +212 -0
  140. package/dist/instant.cjs +66 -0
  141. package/dist/instant.d.cts +16 -0
  142. package/dist/instant.d.ts +16 -0
  143. package/dist/instant.js +63 -0
  144. package/dist/internal-driver.cjs +81 -0
  145. package/dist/internal-driver.d.cts +19 -0
  146. package/dist/internal-driver.d.ts +19 -0
  147. package/dist/internal-driver.js +35 -0
  148. package/dist/keyframes.cjs +191 -0
  149. package/dist/keyframes.d.cts +13 -0
  150. package/dist/keyframes.d.ts +13 -0
  151. package/dist/keyframes.js +188 -0
  152. package/dist/layout/commitDetector.cjs +67 -0
  153. package/dist/layout/commitDetector.d.cts +21 -0
  154. package/dist/layout/commitDetector.d.ts +21 -0
  155. package/dist/layout/commitDetector.js +64 -0
  156. package/dist/layout/compose.cjs +67 -0
  157. package/dist/layout/compose.d.cts +30 -0
  158. package/dist/layout/compose.d.ts +30 -0
  159. package/dist/layout/compose.js +65 -0
  160. package/dist/layout/constants.cjs +13 -0
  161. package/dist/layout/constants.d.cts +6 -0
  162. package/dist/layout/constants.d.ts +6 -0
  163. package/dist/layout/constants.js +10 -0
  164. package/dist/layout/identity.cjs +700 -0
  165. package/dist/layout/identity.d.cts +67 -0
  166. package/dist/layout/identity.d.ts +67 -0
  167. package/dist/layout/identity.js +698 -0
  168. package/dist/layout/index.cjs +36 -0
  169. package/dist/layout/index.d.cts +18 -0
  170. package/dist/layout/index.d.ts +18 -0
  171. package/dist/layout/index.js +13 -0
  172. package/dist/layout/measure.cjs +81 -0
  173. package/dist/layout/measure.d.cts +43 -0
  174. package/dist/layout/measure.d.ts +43 -0
  175. package/dist/layout/measure.js +78 -0
  176. package/dist/layout/projection.cjs +99 -0
  177. package/dist/layout/projection.d.cts +23 -0
  178. package/dist/layout/projection.d.ts +23 -0
  179. package/dist/layout/projection.js +97 -0
  180. package/dist/layout/scroll.cjs +27 -0
  181. package/dist/layout/scroll.d.cts +13 -0
  182. package/dist/layout/scroll.d.ts +13 -0
  183. package/dist/layout/scroll.js +24 -0
  184. package/dist/layout/session.cjs +207 -0
  185. package/dist/layout/session.d.cts +73 -0
  186. package/dist/layout/session.d.ts +73 -0
  187. package/dist/layout/session.js +205 -0
  188. package/dist/layout/tree.cjs +826 -0
  189. package/dist/layout/tree.d.cts +70 -0
  190. package/dist/layout/tree.d.ts +70 -0
  191. package/dist/layout/tree.js +823 -0
  192. package/dist/layout/types.cjs +36 -0
  193. package/dist/layout/types.d.cts +31 -0
  194. package/dist/layout/types.d.ts +31 -0
  195. package/dist/layout/types.js +35 -0
  196. package/dist/motion-arc.cjs +184 -0
  197. package/dist/motion-arc.d.cts +78 -0
  198. package/dist/motion-arc.d.ts +78 -0
  199. package/dist/motion-arc.js +183 -0
  200. package/dist/motion-mix.cjs +205 -0
  201. package/dist/motion-mix.d.cts +3 -0
  202. package/dist/motion-mix.d.ts +3 -0
  203. package/dist/motion-mix.js +202 -0
  204. package/dist/motion-value-driver-port.cjs +636 -0
  205. package/dist/motion-value-driver-port.d.cts +406 -0
  206. package/dist/motion-value-driver-port.d.ts +406 -0
  207. package/dist/motion-value-driver-port.js +627 -0
  208. package/dist/motion-value.cjs +189 -0
  209. package/dist/motion-value.d.cts +51 -0
  210. package/dist/motion-value.d.ts +51 -0
  211. package/dist/motion-value.js +185 -0
  212. package/dist/presence/controller.cjs +657 -0
  213. package/dist/presence/controller.d.cts +6 -0
  214. package/dist/presence/controller.d.ts +6 -0
  215. package/dist/presence/controller.js +652 -0
  216. package/dist/presence/index.cjs +19 -0
  217. package/dist/presence/index.d.cts +4 -0
  218. package/dist/presence/index.d.ts +4 -0
  219. package/dist/presence/index.js +12 -0
  220. package/dist/presence/machine.cjs +50 -0
  221. package/dist/presence/machine.d.cts +10 -0
  222. package/dist/presence/machine.d.ts +10 -0
  223. package/dist/presence/machine.js +46 -0
  224. package/dist/presence/types.cjs +6 -0
  225. package/dist/presence/types.d.cts +32 -0
  226. package/dist/presence/types.d.ts +32 -0
  227. package/dist/presence/types.js +5 -0
  228. package/dist/repeat.cjs +311 -0
  229. package/dist/repeat.d.cts +174 -0
  230. package/dist/repeat.d.ts +174 -0
  231. package/dist/repeat.js +300 -0
  232. package/dist/spring.cjs +128 -0
  233. package/dist/spring.d.cts +18 -0
  234. package/dist/spring.d.ts +18 -0
  235. package/dist/spring.js +125 -0
  236. package/dist/subscriptions.cjs +74 -0
  237. package/dist/subscriptions.d.cts +19 -0
  238. package/dist/subscriptions.d.ts +19 -0
  239. package/dist/subscriptions.js +69 -0
  240. package/dist/subset/index.cjs +23 -0
  241. package/dist/subset/index.d.cts +6 -0
  242. package/dist/subset/index.d.ts +6 -0
  243. package/dist/subset/index.js +13 -0
  244. package/dist/subset/normalize.cjs +90 -0
  245. package/dist/subset/normalize.d.cts +10 -0
  246. package/dist/subset/normalize.d.ts +10 -0
  247. package/dist/subset/normalize.js +85 -0
  248. package/dist/subset/registry.cjs +259 -0
  249. package/dist/subset/registry.d.cts +25 -0
  250. package/dist/subset/registry.d.ts +25 -0
  251. package/dist/subset/registry.js +256 -0
  252. package/dist/subset/resolve.cjs +98 -0
  253. package/dist/subset/resolve.d.cts +24 -0
  254. package/dist/subset/resolve.d.ts +24 -0
  255. package/dist/subset/resolve.js +90 -0
  256. package/dist/timing.cjs +206 -0
  257. package/dist/timing.d.cts +17 -0
  258. package/dist/timing.d.ts +17 -0
  259. package/dist/timing.js +201 -0
  260. package/dist/transformTemplate.cjs +219 -0
  261. package/dist/transformTemplate.d.cts +29 -0
  262. package/dist/transformTemplate.d.ts +29 -0
  263. package/dist/transformTemplate.js +215 -0
  264. package/dist/transition.cjs +231 -0
  265. package/dist/transition.d.cts +89 -0
  266. package/dist/transition.d.ts +89 -0
  267. package/dist/transition.js +223 -0
  268. package/dist/types.cjs +4 -0
  269. package/dist/types.d.cts +175 -0
  270. package/dist/types.d.ts +175 -0
  271. package/dist/types.js +3 -0
  272. package/dist/value-types/color.cjs +220 -0
  273. package/dist/value-types/color.d.cts +19 -0
  274. package/dist/value-types/color.d.ts +19 -0
  275. package/dist/value-types/color.js +218 -0
  276. package/dist/value-types/complex.cjs +160 -0
  277. package/dist/value-types/complex.d.cts +19 -0
  278. package/dist/value-types/complex.d.ts +19 -0
  279. package/dist/value-types/complex.js +155 -0
  280. package/dist/value-types/constants.cjs +15 -0
  281. package/dist/value-types/constants.d.cts +6 -0
  282. package/dist/value-types/constants.d.ts +6 -0
  283. package/dist/value-types/constants.js +12 -0
  284. package/dist/value-types/discrete.cjs +62 -0
  285. package/dist/value-types/discrete.d.cts +4 -0
  286. package/dist/value-types/discrete.d.ts +4 -0
  287. package/dist/value-types/discrete.js +56 -0
  288. package/dist/value-types/index.cjs +59 -0
  289. package/dist/value-types/index.d.cts +14 -0
  290. package/dist/value-types/index.d.ts +14 -0
  291. package/dist/value-types/index.js +24 -0
  292. package/dist/value-types/measure-resolve.cjs +325 -0
  293. package/dist/value-types/measure-resolve.d.cts +91 -0
  294. package/dist/value-types/measure-resolve.d.ts +91 -0
  295. package/dist/value-types/measure-resolve.js +313 -0
  296. package/dist/value-types/mix.cjs +90 -0
  297. package/dist/value-types/mix.d.cts +27 -0
  298. package/dist/value-types/mix.d.ts +27 -0
  299. package/dist/value-types/mix.js +85 -0
  300. package/dist/value-types/named-colors.cjs +61 -0
  301. package/dist/value-types/named-colors.d.cts +2 -0
  302. package/dist/value-types/named-colors.d.ts +2 -0
  303. package/dist/value-types/named-colors.js +58 -0
  304. package/dist/value-types/numeric.cjs +86 -0
  305. package/dist/value-types/numeric.d.cts +16 -0
  306. package/dist/value-types/numeric.d.ts +16 -0
  307. package/dist/value-types/numeric.js +79 -0
  308. package/dist/worklet-layout/config/constants.js +39 -0
  309. package/dist/worklet-layout/layout/constants.js +11 -0
  310. package/dist/worklet-layout/layout/identity.js +699 -0
  311. package/dist/worklet-layout/layout/projection.js +98 -0
  312. package/dist/worklet-layout/layout/session.js +206 -0
  313. package/dist/worklet-layout/layout/tree.js +824 -0
  314. package/dist/worklet-layout/layout/types.js +36 -0
  315. package/dist/worklet-layout/spring.js +125 -0
  316. package/dist/worklet-layout/timing.js +201 -0
  317. package/dist/worklet-layout/transition.js +223 -0
  318. package/dist/worklet-layout.cjs +47 -0
  319. package/dist/worklet-layout.d.cts +15 -0
  320. package/dist/worklet-layout.d.ts +15 -0
  321. package/dist/worklet-layout.js +28 -0
  322. package/dist/wrap.cjs +7 -0
  323. package/dist/wrap.d.cts +1 -0
  324. package/dist/wrap.d.ts +1 -0
  325. package/dist/wrap.js +4 -0
  326. package/package.json +45 -0
package/dist/timing.js ADDED
@@ -0,0 +1,201 @@
1
+ 'worklet';
2
+ // @frame-path — executes inside the UI-runtime frame step; allocation-gated (REQ-DRIVER-021).
3
+ // Duration+ease timing (tween) generator (SPEC-SPRING REQ-TIMING-001/002). value = mix(origin, target,
4
+ // ease(clamp(0,1,t/duration))); velocity is a 5ms finite difference of that curve; done at t ≥ duration;
5
+ // incoming velocity is ignored. Host-agnostic (REQ-CORE-003): the cubic-bezier evaluator is an exact
6
+ // port of motion-utils' Gaëtan Renaudeau BezierEasing (binary subdivision), NOT imported. Numerics are
7
+ // pinned to motion@12.42.2 and proven by golden parity in timing.test.ts.
8
+ //
9
+ // Worklet safety (hytd3r / Remote Function crash class): NEVER store named-easing evaluators as
10
+ // module-init function values. reverseEasing/mirrorEasing wrappers and cubicBezier returns built at
11
+ // load time lacked __workletHash and crashed when UI-runtime call sites invoked them. All named and
12
+ // cubic evaluation is pure math over number tables; resolveEasing returns thin closures that capture
13
+ // only serializable primitives (name string or control points).
14
+ // Runtime-readable named set (validate / keyframeTiming / shippedSurface share this authority).
15
+ export const NAMED_EASING_KEYS = [
16
+ 'linear',
17
+ 'easeIn',
18
+ 'easeOut',
19
+ 'easeInOut',
20
+ 'circIn',
21
+ 'circOut',
22
+ 'circInOut',
23
+ 'backIn',
24
+ 'backOut',
25
+ 'backInOut',
26
+ 'anticipate',
27
+ ];
28
+ const DEFAULT_DURATION_MS = 300; // REQ-TIMING-002 (0.3s)
29
+ const DEFAULT_EASE = [0.25, 0.1, 0.35, 1]; // REQ-TIMING-002
30
+ const VELOCITY_SAMPLE_MS = 5;
31
+ // Named cubic-bezier control points (motion-utils/easing/ease + back). Data only — no function values.
32
+ const EASE_IN = [0.42, 0, 1, 1];
33
+ const EASE_OUT = [0, 0, 0.58, 1];
34
+ const EASE_IN_OUT = [0.42, 0, 0.58, 1];
35
+ // motion-utils/easing/back.ts: backOut = cubicBezier(0.33, 1.53, 0.69, 0.99)
36
+ const BACK_OUT = [0.33, 1.53, 0.69, 0.99];
37
+ const clamp01 = (v) => Math.max(0, Math.min(1, v));
38
+ const mix = (from, to, p) => from + (to - from) * p;
39
+ const SUBDIVISION_PRECISION = 1e-7;
40
+ const SUBDIVISION_MAX_ITERATIONS = 12;
41
+ // x(t)/y(t) of the bezier given a single control-point pair (exact port of motion-utils calcBezier).
42
+ const calcBezier = (t, a1, a2) => ((1 - 3 * a2 + 3 * a1) * t + (3 * a2 - 6 * a1)) * t * t + 3 * a1 * t;
43
+ /** Pure cubic-bezier sample — no nested function allocation at module init (hytd3r). */
44
+ function evaluateCubic(x1, y1, x2, y2, t) {
45
+ if (t === 0 || t === 1)
46
+ return t;
47
+ // Linear gradient is the identity; also avoids a degenerate subdivision.
48
+ if (x1 === y1 && x2 === y2)
49
+ return t;
50
+ let lower = 0;
51
+ let upper = 1;
52
+ let currentT = 0;
53
+ let currentX = 0;
54
+ let i = 0;
55
+ do {
56
+ currentT = lower + (upper - lower) / 2;
57
+ currentX = calcBezier(currentT, x1, x2) - t;
58
+ if (currentX > 0)
59
+ upper = currentT;
60
+ else
61
+ lower = currentT;
62
+ } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
63
+ return calcBezier(currentT, y1, y2);
64
+ }
65
+ // motion-utils/easing/circ.ts — pure forms of reverse/mirror so no function-valued table.
66
+ function evaluateCircIn(p) {
67
+ return 1 - Math.sin(Math.acos(clamp01(p)));
68
+ }
69
+ function evaluateCircOut(p) {
70
+ // reverse(circIn): 1 - circIn(1 - p)
71
+ return 1 - evaluateCircIn(1 - p);
72
+ }
73
+ function evaluateCircInOut(p) {
74
+ // mirror(circIn)
75
+ return p <= 0.5 ? evaluateCircIn(2 * p) / 2 : (2 - evaluateCircIn(2 * (1 - p))) / 2;
76
+ }
77
+ function evaluateBackOut(p) {
78
+ return evaluateCubic(BACK_OUT[0], BACK_OUT[1], BACK_OUT[2], BACK_OUT[3], p);
79
+ }
80
+ function evaluateBackIn(p) {
81
+ // reverse(backOut)
82
+ return 1 - evaluateBackOut(1 - p);
83
+ }
84
+ function evaluateBackInOut(p) {
85
+ // mirror(backIn)
86
+ return p <= 0.5 ? evaluateBackIn(2 * p) / 2 : (2 - evaluateBackIn(2 * (1 - p))) / 2;
87
+ }
88
+ // motion-utils/easing/anticipate.ts
89
+ function evaluateAnticipate(p) {
90
+ if (p >= 1)
91
+ return 1;
92
+ const doubled = p * 2;
93
+ return doubled < 1 ? 0.5 * evaluateBackIn(doubled) : 0.5 * (2 - Math.pow(2, -10 * (doubled - 1)));
94
+ }
95
+ const NAMED_EASING_SET = new Set(NAMED_EASING_KEYS);
96
+ function isNamedEasing(value) {
97
+ return NAMED_EASING_SET.has(value);
98
+ }
99
+ /** Pure named-easing sample — captures no function values (hytd3r Remote Function law). */
100
+ function evaluateNamedEasing(name, p) {
101
+ switch (name) {
102
+ case 'linear':
103
+ return p;
104
+ case 'easeIn':
105
+ return evaluateCubic(EASE_IN[0], EASE_IN[1], EASE_IN[2], EASE_IN[3], p);
106
+ case 'easeOut':
107
+ return evaluateCubic(EASE_OUT[0], EASE_OUT[1], EASE_OUT[2], EASE_OUT[3], p);
108
+ case 'easeInOut':
109
+ return evaluateCubic(EASE_IN_OUT[0], EASE_IN_OUT[1], EASE_IN_OUT[2], EASE_IN_OUT[3], p);
110
+ case 'circIn':
111
+ return evaluateCircIn(p);
112
+ case 'circOut':
113
+ return evaluateCircOut(p);
114
+ case 'circInOut':
115
+ return evaluateCircInOut(p);
116
+ case 'backIn':
117
+ return evaluateBackIn(p);
118
+ case 'backOut':
119
+ return evaluateBackOut(p);
120
+ case 'backInOut':
121
+ return evaluateBackInOut(p);
122
+ case 'anticipate':
123
+ return evaluateAnticipate(p);
124
+ default: {
125
+ // Exhaustiveness + runtime cast guard (9a4arp): never sample NaN for an unknown name.
126
+ const _exhaustive = name;
127
+ throw new Error(`unknown named easing '${String(_exhaustive)}'`);
128
+ }
129
+ }
130
+ }
131
+ // alloc-ok: lifecycle-edge — easing resolution at factory time. Exported for the multi-keyframe
132
+ // generator (keyframes.ts, REQ-API-033), which resolves ONE easing per segment through this same
133
+ // exact BezierEasing / Motion-named port — never a second easing vocabulary.
134
+ // Closures capture only primitives (name string or four numbers) so worklet serialization never
135
+ // embeds a JS-thread Remote Function (hytd3r).
136
+ // Fail-closed (9a4arp): unknown named strings throw before any sample can emit NaN. The public
137
+ // validateTransition boundary also refuses them; this is the generator-seam backstop for direct
138
+ // timingGenerator / resolveEasing callers.
139
+ export function resolveEasing(ease) {
140
+ if (typeof ease === 'string') {
141
+ if (!isNamedEasing(ease)) {
142
+ throw new Error(`unknown named easing '${ease}' — expected one of ${NAMED_EASING_KEYS.join(', ')} ` +
143
+ '(REQ-TIMING-001 / REQ-API-033)');
144
+ }
145
+ const name = ease;
146
+ // Named returned closures (frame-path manifest anonymous-sampler repair): the qualified
147
+ // symbols are resolveEasing.namedEvaluator / resolveEasing.cubicEvaluator.
148
+ return function namedEvaluator(p) {
149
+ return evaluateNamedEasing(name, p);
150
+ };
151
+ }
152
+ const x1 = ease[0];
153
+ const y1 = ease[1];
154
+ const x2 = ease[2];
155
+ const y2 = ease[3];
156
+ return function cubicEvaluator(p) {
157
+ return evaluateCubic(x1, y1, x2, y2, p);
158
+ };
159
+ }
160
+ // Disambiguate a PER-SEGMENT easing list (`['easeIn', 'easeOut']`, `[[…],[…]]`) from a SINGLE
161
+ // cubic-bezier easing (`[0.25, 0.1, 0.35, 1]`) — both are arrays. A per-segment list's elements are
162
+ // themselves easings (a named string or a nested bezier array); a single CubicBezier's elements are
163
+ // plain numbers. Mirrors motion-dom's `isEasingArray`. Without this, a single-bezier `ease` on a
164
+ // keyframe array would be mis-read element-by-element as per-segment (REQ-API-033).
165
+ export function isEasingList(ease) {
166
+ return Array.isArray(ease) && typeof ease[0] !== 'number';
167
+ }
168
+ /**
169
+ * Build a tween `GeneratorFactory` (REQ-API-004). `seed.from` is the origin; the seed's incoming
170
+ * velocity is intentionally ignored (REQ-TIMING-001). The tween finishes deterministically at
171
+ * `t ≥ duration`.
172
+ */
173
+ // alloc-ok: lifecycle-edge — the factory resolves duration/ease once per animate command;
174
+ // per-frame work is sample() below, which mutates the reused record and allocates nothing.
175
+ export function timingGenerator(target, config) {
176
+ const duration = config?.duration ?? DEFAULT_DURATION_MS;
177
+ const ease = resolveEasing(config?.ease ?? DEFAULT_EASE);
178
+ // alloc-ok: lifecycle-edge — generator construction at command time; the one reused sample
179
+ // record is built here, never per frame.
180
+ return (seed) => {
181
+ const origin = seed.from;
182
+ const value = (t) => mix(origin, target, ease(clamp01(t / duration)));
183
+ // One sample record per generator, mutated and returned every call — motion's own generators
184
+ // return their reused `state` the same way. Per-frame sampling must not allocate
185
+ // (REQ-DRIVER-015); callers read the scalars immediately and never retain the record.
186
+ const out = { value: origin, velocity: 0, done: false };
187
+ return {
188
+ sample(elapsedMs) {
189
+ const current = value(elapsedMs);
190
+ const prevT = Math.max(elapsedMs - VELOCITY_SAMPLE_MS, 0);
191
+ const dt = elapsedMs - prevT;
192
+ const velocity = dt ? ((current - value(prevT)) / dt) * 1000 : 0; // px/s (REQ-TIMING-001)
193
+ const done = elapsedMs >= duration;
194
+ out.value = done ? target : current;
195
+ out.velocity = velocity;
196
+ out.done = done;
197
+ return out;
198
+ },
199
+ };
200
+ };
201
+ }
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ // @frame-path — executes inside the UI-runtime frame step; allocation-gated (REQ-DRIVER-021).
3
+ // Bounded transform-template support (T17 packet, specs/T17-TRANSFORM-TEMPLATE-BUILD-PACKET.md):
4
+ // the canonical generated-string builder (pin `motion-dom buildTransform` format and value
5
+ // typing) and the bounded parser that turns a template's RETURN string into the RN transform
6
+ // array. Grammar is exactly the canonical builder's function set; anything off-grammar fails
7
+ // loud naming the offending token — never a silent partial parse (the R13 law). Host-agnostic
8
+ // (REQ-CORE-003): no host imports.
9
+ //
10
+ // alloc-ok: frame — template composition is string-valued by pin design (motion-dom
11
+ // buildTransform allocates the composed string per frame); the parser allocates only the small
12
+ // output entry list, proportional to the entry count.
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.buildTransformString = buildTransformString;
15
+ exports.buildTransformTemplateArgs = buildTransformTemplateArgs;
16
+ exports.parseTransformTemplateOutput = parseTransformTemplateOutput;
17
+ // Canonical key order (pin `transformPropOrder` restricted to the shipped transform keys — the
18
+ // same list composeTransform commits, so template and non-template composition agree).
19
+ const TEMPLATE_KEY_ORDER = [
20
+ 'perspective',
21
+ 'x',
22
+ 'y',
23
+ 'scale',
24
+ 'scaleX',
25
+ 'scaleY',
26
+ 'rotate',
27
+ 'rotateX',
28
+ 'rotateY',
29
+ 'skewX',
30
+ 'skewY',
31
+ ];
32
+ // Function name in the generated string per key (pin: translateAlias x→translateX, y→translateY).
33
+ const KEY_FUNCTION = {
34
+ perspective: 'perspective',
35
+ x: 'translateX',
36
+ y: 'translateY',
37
+ scale: 'scale',
38
+ scaleX: 'scaleX',
39
+ scaleY: 'scaleY',
40
+ rotate: 'rotate',
41
+ rotateX: 'rotateX',
42
+ rotateY: 'rotateY',
43
+ skewX: 'skewX',
44
+ skewY: 'skewY',
45
+ };
46
+ // Plain-object lookups, never Sets: worklet captures stay in the most conservative shareable
47
+ // shape — records of primitives (the composeTransform.ts law) — so serialization can never be
48
+ // the failure mode on the UI runtime.
49
+ const DEGREE_KEYS = Object.freeze({
50
+ rotate: 1,
51
+ rotateX: 1,
52
+ rotateY: 1,
53
+ skewX: 1,
54
+ skewY: 1,
55
+ });
56
+ const LENGTH_KEYS = Object.freeze({ perspective: 1, x: 1, y: 1 });
57
+ // Pin build-transform's default law: `value === (key.startsWith("scale") ? 1 : 0)`.
58
+ const SCALE_KEYS = Object.freeze({ scale: 1, scaleX: 1, scaleY: 1 });
59
+ // The values-map key name per canonical key (pin latestValues naming: transformPerspective).
60
+ const VALUES_MAP_KEY = {
61
+ perspective: 'transformPerspective',
62
+ x: 'x',
63
+ y: 'y',
64
+ scale: 'scale',
65
+ scaleX: 'scaleX',
66
+ scaleY: 'scaleY',
67
+ rotate: 'rotate',
68
+ rotateX: 'rotateX',
69
+ rotateY: 'rotateY',
70
+ skewX: 'skewX',
71
+ skewY: 'skewY',
72
+ };
73
+ function typedValueFor(key, value) {
74
+ const unit = DEGREE_KEYS[key] === 1 ? 'deg' : LENGTH_KEYS[key] === 1 ? 'px' : '';
75
+ return `${value}${unit}`;
76
+ }
77
+ function assertFiniteTemplateValue(key, value) {
78
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
79
+ throw new Error(`transformTemplate values: key '${key}' must be a finite number, got ${String(value)} (T17).`);
80
+ }
81
+ }
82
+ /**
83
+ * The canonical generated string (pin `buildTransform`): `${fn}(${valueWithUnit})` joined by
84
+ * spaces in canonical order. A non-finite value fails loud naming the key.
85
+ */
86
+ function buildTransformString(values) {
87
+ let out = '';
88
+ for (const key of TEMPLATE_KEY_ORDER) {
89
+ const value = values[key];
90
+ if (value === undefined)
91
+ continue;
92
+ assertFiniteTemplateValue(key, value);
93
+ out += `${out === '' ? '' : ' '}${KEY_FUNCTION[key]}(${typedValueFor(key, value)})`;
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * The pin's template call args (motion-dom build-transform, verbatim loop): the values map
99
+ * carries every PRESENT key typed (defaults INCLUDED — `!valueIsDefault || transformTemplate`);
100
+ * the generated string carries only NON-DEFAULT values in canonical order, so an all-default
101
+ * transform hands the template '' (pin `transformIsDefault ? "" : transformString`).
102
+ */
103
+ function buildTransformTemplateArgs(values) {
104
+ const typed = {};
105
+ let generated = '';
106
+ for (const key of TEMPLATE_KEY_ORDER) {
107
+ const value = values[key];
108
+ if (value === undefined)
109
+ continue;
110
+ assertFiniteTemplateValue(key, value);
111
+ const typedValue = typedValueFor(key, value);
112
+ typed[VALUES_MAP_KEY[key]] = typedValue;
113
+ const isDefault = SCALE_KEYS[key] === 1 ? value === 1 : value === 0;
114
+ if (!isDefault) {
115
+ generated += `${generated === '' ? '' : ' '}${KEY_FUNCTION[key]}(${typedValue})`;
116
+ }
117
+ }
118
+ return { values: typed, generated };
119
+ }
120
+ // Per-function unit law: translate* take px|%; scale* are unitless; rotate*/skew* take
121
+ // deg|unitless; perspective takes px|unitless. Anything else is a named refusal.
122
+ const FUNCTION_UNITS = {
123
+ perspective: ['px', ''],
124
+ translate: ['px', '%'],
125
+ translateX: ['px', '%'],
126
+ translateY: ['px', '%'],
127
+ scale: [''],
128
+ scaleX: [''],
129
+ scaleY: [''],
130
+ rotate: ['deg', ''],
131
+ rotateX: ['deg', ''],
132
+ rotateY: ['deg', ''],
133
+ skewX: ['deg', ''],
134
+ skewY: ['deg', ''],
135
+ };
136
+ const ENTRY_NAME = {
137
+ perspective: 'perspective',
138
+ translateX: 'translateX',
139
+ translateY: 'translateY',
140
+ scale: 'scale',
141
+ scaleX: 'scaleX',
142
+ scaleY: 'scaleY',
143
+ rotate: 'rotate',
144
+ rotateX: 'rotateX',
145
+ rotateY: 'rotateY',
146
+ skewX: 'skewX',
147
+ skewY: 'skewY',
148
+ };
149
+ const VALUE_RE = /^(-?(?:\d+(?:\.\d+)?|\.\d+))(px|%|deg)?$/;
150
+ function fail(templateOutput, reason) {
151
+ throw new Error(`transformTemplate output '${templateOutput}': ${reason} (T17 bounded grammar).`);
152
+ }
153
+ function parseValue(templateOutput, fn, raw) {
154
+ const m = VALUE_RE.exec(raw.trim());
155
+ if (m === null) {
156
+ fail(templateOutput, `unparseable value '${raw}' for ${fn}`);
157
+ }
158
+ const [, numeral, rawUnit] = m;
159
+ const unit = (rawUnit ?? '');
160
+ const allowed = FUNCTION_UNITS[fn];
161
+ if (!allowed.includes(unit)) {
162
+ fail(templateOutput, `unit '${unit || '(none)'}' is not valid for ${fn}`);
163
+ }
164
+ // Percent translate entries ride RN's percent-string form. Angle entries commit as RN degree
165
+ // STRINGS — the shipped composeTransform output shape (RN types the rotate/skew family
166
+ // string-typed; a bare number is not a valid entry). A unitless angle is degrees by the pin's
167
+ // getValueAsType law. Everything else commits numeric.
168
+ if (unit === '%')
169
+ return `${numeral}%`;
170
+ if (allowed.includes('deg'))
171
+ return `${numeral}deg`;
172
+ return Number(numeral);
173
+ }
174
+ /**
175
+ * Parse a template's RETURN string into the ordered RN transform array. The grammar is the
176
+ * canonical builder's function set with px/%/deg/unitless values; `translate` takes 1-2 args
177
+ * (comma or space separated). Anything else throws naming the offending token.
178
+ */
179
+ function parseTransformTemplateOutput(templateOutput) {
180
+ const out = [];
181
+ let rest = templateOutput.trim();
182
+ while (rest.length > 0) {
183
+ const open = rest.indexOf('(');
184
+ const fn = open === -1 ? rest.trim() : rest.slice(0, open).trim();
185
+ if (open === -1 || fn === '' || /\s/.test(fn)) {
186
+ fail(templateOutput, `malformed token '${fn}' — expected fn(args)`);
187
+ }
188
+ if (!(fn in FUNCTION_UNITS) && fn !== 'translate') {
189
+ fail(templateOutput, `transform function '${fn}' is outside the bounded grammar`);
190
+ }
191
+ const close = rest.indexOf(')', open);
192
+ if (close === -1) {
193
+ fail(templateOutput, `unbalanced parens near '${fn}('`);
194
+ }
195
+ const argsRaw = rest.slice(open + 1, close);
196
+ const args = argsRaw.includes(',')
197
+ ? argsRaw.split(',').map((a) => a.trim())
198
+ : argsRaw.trim() === ''
199
+ ? []
200
+ : argsRaw.trim().split(/\s+/);
201
+ if (fn === 'translate') {
202
+ if (args.length === 0 || args.length > 2) {
203
+ fail(templateOutput, `translate takes 1 or 2 args, got ${args.length}`);
204
+ }
205
+ out.push({ translateX: parseValue(templateOutput, 'translate', args[0]) });
206
+ if (args.length === 2) {
207
+ out.push({ translateY: parseValue(templateOutput, 'translate', args[1]) });
208
+ }
209
+ }
210
+ else {
211
+ if (args.length !== 1) {
212
+ fail(templateOutput, `${fn} takes exactly 1 arg, got ${args.length}`);
213
+ }
214
+ out.push({ [ENTRY_NAME[fn]]: parseValue(templateOutput, fn, args[0]) });
215
+ }
216
+ rest = rest.slice(close + 1).trim();
217
+ }
218
+ return out;
219
+ }
@@ -0,0 +1,29 @@
1
+ export type TransformTemplateValues = Partial<Record<(typeof TEMPLATE_KEY_ORDER)[number], number>>;
2
+ export type TransformPropertyKey = 'transformPerspective' | 'x' | 'y' | 'scale' | 'scaleX' | 'scaleY' | 'rotate' | 'rotateX' | 'rotateY' | 'skewX' | 'skewY';
3
+ export type TransformProperties = Partial<Record<TransformPropertyKey, string>>;
4
+ export type TransformTemplate = (transform: TransformProperties, generatedTransform: string) => string;
5
+ declare const TEMPLATE_KEY_ORDER: readonly ["perspective", "x", "y", "scale", "scaleX", "scaleY", "rotate", "rotateX", "rotateY", "skewX", "skewY"];
6
+ /**
7
+ * The canonical generated string (pin `buildTransform`): `${fn}(${valueWithUnit})` joined by
8
+ * spaces in canonical order. A non-finite value fails loud naming the key.
9
+ */
10
+ export declare function buildTransformString(values: TransformTemplateValues): string;
11
+ export type TransformTemplateArgs = {
12
+ readonly values: TransformProperties;
13
+ readonly generated: string;
14
+ };
15
+ /**
16
+ * The pin's template call args (motion-dom build-transform, verbatim loop): the values map
17
+ * carries every PRESENT key typed (defaults INCLUDED — `!valueIsDefault || transformTemplate`);
18
+ * the generated string carries only NON-DEFAULT values in canonical order, so an all-default
19
+ * transform hands the template '' (pin `transformIsDefault ? "" : transformString`).
20
+ */
21
+ export declare function buildTransformTemplateArgs(values: TransformTemplateValues): TransformTemplateArgs;
22
+ export type TransformEntry = Readonly<Record<string, number | string>>;
23
+ /**
24
+ * Parse a template's RETURN string into the ordered RN transform array. The grammar is the
25
+ * canonical builder's function set with px/%/deg/unitless values; `translate` takes 1-2 args
26
+ * (comma or space separated). Anything else throws naming the offending token.
27
+ */
28
+ export declare function parseTransformTemplateOutput(templateOutput: string): TransformEntry[];
29
+ export {};
@@ -0,0 +1,29 @@
1
+ export type TransformTemplateValues = Partial<Record<(typeof TEMPLATE_KEY_ORDER)[number], number>>;
2
+ export type TransformPropertyKey = 'transformPerspective' | 'x' | 'y' | 'scale' | 'scaleX' | 'scaleY' | 'rotate' | 'rotateX' | 'rotateY' | 'skewX' | 'skewY';
3
+ export type TransformProperties = Partial<Record<TransformPropertyKey, string>>;
4
+ export type TransformTemplate = (transform: TransformProperties, generatedTransform: string) => string;
5
+ declare const TEMPLATE_KEY_ORDER: readonly ["perspective", "x", "y", "scale", "scaleX", "scaleY", "rotate", "rotateX", "rotateY", "skewX", "skewY"];
6
+ /**
7
+ * The canonical generated string (pin `buildTransform`): `${fn}(${valueWithUnit})` joined by
8
+ * spaces in canonical order. A non-finite value fails loud naming the key.
9
+ */
10
+ export declare function buildTransformString(values: TransformTemplateValues): string;
11
+ export type TransformTemplateArgs = {
12
+ readonly values: TransformProperties;
13
+ readonly generated: string;
14
+ };
15
+ /**
16
+ * The pin's template call args (motion-dom build-transform, verbatim loop): the values map
17
+ * carries every PRESENT key typed (defaults INCLUDED — `!valueIsDefault || transformTemplate`);
18
+ * the generated string carries only NON-DEFAULT values in canonical order, so an all-default
19
+ * transform hands the template '' (pin `transformIsDefault ? "" : transformString`).
20
+ */
21
+ export declare function buildTransformTemplateArgs(values: TransformTemplateValues): TransformTemplateArgs;
22
+ export type TransformEntry = Readonly<Record<string, number | string>>;
23
+ /**
24
+ * Parse a template's RETURN string into the ordered RN transform array. The grammar is the
25
+ * canonical builder's function set with px/%/deg/unitless values; `translate` takes 1-2 args
26
+ * (comma or space separated). Anything else throws naming the offending token.
27
+ */
28
+ export declare function parseTransformTemplateOutput(templateOutput: string): TransformEntry[];
29
+ export {};