@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
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ // SPEC-UNIVERSAL-SUBSET §3 — the loud-fail capability resolver (REQ-SUBSET-014). A capability present in
3
+ // an animate/initial/exit target or a gesture prop, on a host that does not declare it, raises a typed
4
+ // UnsupportedCapabilityError naming the capability, the active host, and the host(s) that DO support it.
5
+ // It never silently no-ops, drops, or degrades — this is REQ-API-005's fail-closed invariant applied to
6
+ // subset membership, and the primitive SPEC-COMPONENT's validateTarget builds on. Host-agnostic: it reads
7
+ // the frozen registry and a pure host-capability descriptor; it touches no real react-native host.
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.UnsupportedCapabilityError = void 0;
10
+ exports.hostCapabilities = hostCapabilities;
11
+ exports.resolveCapabilityVerdict = resolveCapabilityVerdict;
12
+ exports.resolveCapability = resolveCapability;
13
+ exports.resolveTargetCapabilities = resolveTargetCapabilities;
14
+ const registry_1 = require("./registry.cjs");
15
+ class UnsupportedCapabilityError extends Error {
16
+ capability;
17
+ hostId;
18
+ reason;
19
+ // The host ids that DO support the capability (empty for an unknown key). Named in the message so a
20
+ // developer sees where the capability is valid.
21
+ supportedOn;
22
+ constructor(capability, hostId, reason, supportedOn, message) {
23
+ super(message);
24
+ this.name = 'UnsupportedCapabilityError';
25
+ this.capability = capability;
26
+ this.hostId = hostId;
27
+ this.reason = reason;
28
+ this.supportedOn = supportedOn;
29
+ }
30
+ }
31
+ exports.UnsupportedCapabilityError = UnsupportedCapabilityError;
32
+ // The host archetypes that support each universality class. Provisional taxonomy for the deterministic
33
+ // interior (native = touch-first, web = pointer/keyboard): pointer-gated capability lives on the web
34
+ // host, web-only on the web host, universal + native-extension on both. The exact per-host / per-input
35
+ // gating granularity is a §8 open decision (flagged), refined at the device milestone.
36
+ function supportedHostsFor(universality) {
37
+ switch (universality) {
38
+ case 'universal':
39
+ case 'native-extension':
40
+ return ['native', 'web'];
41
+ case 'web-only':
42
+ case 'pointer-gated':
43
+ return ['web'];
44
+ }
45
+ }
46
+ // Build a host from the universalities its input model supports: it declares every registry key whose
47
+ // universality is in `supported`. Keeps host declarations derived from the single source of truth.
48
+ function hostCapabilities(id, supported) {
49
+ const supportedSet = new Set(supported);
50
+ const declares = new Set();
51
+ for (const entry of registry_1.UNIVERSAL_SUBSET.entries) {
52
+ if (!supportedSet.has(entry.universality))
53
+ continue;
54
+ for (const key of entry.keys)
55
+ declares.add(key);
56
+ }
57
+ return { id, declares };
58
+ }
59
+ function resolveCapabilityVerdict(host, key) {
60
+ const entry = registry_1.UNIVERSAL_SUBSET.get(key);
61
+ if (entry === undefined) {
62
+ return {
63
+ entry: null,
64
+ unsupported: new UnsupportedCapabilityError(key, host.id, 'unknown', [], `Unknown capability '${key}': not in the universal-subset registry ` +
65
+ `(host '${host.id}').`),
66
+ };
67
+ }
68
+ if (!host.declares.has(key)) {
69
+ const supportedOn = supportedHostsFor(entry.universality);
70
+ return {
71
+ entry: null,
72
+ unsupported: new UnsupportedCapabilityError(key, host.id, 'off-host', supportedOn, `Capability '${key}' is not supported on host '${host.id}' — ` +
73
+ `it is ${entry.universality}; supported on: ${supportedOn.join(', ')}.`),
74
+ };
75
+ }
76
+ return { entry, unsupported: null };
77
+ }
78
+ // Resolve a single capability key against a host. Returns the registry entry when the host declares it;
79
+ // throws UnsupportedCapabilityError otherwise. The unknown-key check comes FIRST so the registry stays
80
+ // authoritative even if a malformed host over-declares.
81
+ function resolveCapability(host, key) {
82
+ const verdict = resolveCapabilityVerdict(host, key);
83
+ if (verdict.unsupported !== null)
84
+ throw verdict.unsupported;
85
+ return verdict.entry;
86
+ }
87
+ // Gate every key of a target object against a host's declared capability set. Fails closed on the FIRST
88
+ // unsupported key (the throw aborts iteration) and returns a fresh key→entry map only when ALL keys
89
+ // resolve — it never partially resolves (REQ-SUBSET-014 / REQ-API-013 fail-closed). Named
90
+ // `resolveTargetCapabilities` (not `resolveTarget`) so SPEC-COMPONENT can own the public
91
+ // `resolveTarget(base, target)` value-merge; this is the SUBSET capability gate, a distinct function.
92
+ function resolveTargetCapabilities(host, target) {
93
+ const resolved = new Map();
94
+ for (const key of Object.keys(target)) {
95
+ resolved.set(key, resolveCapability(host, key));
96
+ }
97
+ return resolved;
98
+ }
@@ -0,0 +1,24 @@
1
+ import { type CapabilityEntry, type Universality } from "./registry.cjs";
2
+ export interface HostCapabilities {
3
+ readonly id: string;
4
+ readonly declares: ReadonlySet<string>;
5
+ }
6
+ export type UnsupportedReason = 'unknown' | 'off-host';
7
+ export declare class UnsupportedCapabilityError extends Error {
8
+ readonly capability: string;
9
+ readonly hostId: string;
10
+ readonly reason: UnsupportedReason;
11
+ readonly supportedOn: readonly string[];
12
+ constructor(capability: string, hostId: string, reason: UnsupportedReason, supportedOn: readonly string[], message: string);
13
+ }
14
+ export declare function hostCapabilities(id: string, supported: readonly Universality[]): HostCapabilities;
15
+ export type CapabilityVerdict = {
16
+ readonly entry: CapabilityEntry;
17
+ readonly unsupported: null;
18
+ } | {
19
+ readonly entry: null;
20
+ readonly unsupported: UnsupportedCapabilityError;
21
+ };
22
+ export declare function resolveCapabilityVerdict(host: HostCapabilities, key: string): CapabilityVerdict;
23
+ export declare function resolveCapability(host: HostCapabilities, key: string): CapabilityEntry;
24
+ export declare function resolveTargetCapabilities(host: HostCapabilities, target: Readonly<Record<string, unknown>>): ReadonlyMap<string, CapabilityEntry>;
@@ -0,0 +1,24 @@
1
+ import { type CapabilityEntry, type Universality } from "./registry.js";
2
+ export interface HostCapabilities {
3
+ readonly id: string;
4
+ readonly declares: ReadonlySet<string>;
5
+ }
6
+ export type UnsupportedReason = 'unknown' | 'off-host';
7
+ export declare class UnsupportedCapabilityError extends Error {
8
+ readonly capability: string;
9
+ readonly hostId: string;
10
+ readonly reason: UnsupportedReason;
11
+ readonly supportedOn: readonly string[];
12
+ constructor(capability: string, hostId: string, reason: UnsupportedReason, supportedOn: readonly string[], message: string);
13
+ }
14
+ export declare function hostCapabilities(id: string, supported: readonly Universality[]): HostCapabilities;
15
+ export type CapabilityVerdict = {
16
+ readonly entry: CapabilityEntry;
17
+ readonly unsupported: null;
18
+ } | {
19
+ readonly entry: null;
20
+ readonly unsupported: UnsupportedCapabilityError;
21
+ };
22
+ export declare function resolveCapabilityVerdict(host: HostCapabilities, key: string): CapabilityVerdict;
23
+ export declare function resolveCapability(host: HostCapabilities, key: string): CapabilityEntry;
24
+ export declare function resolveTargetCapabilities(host: HostCapabilities, target: Readonly<Record<string, unknown>>): ReadonlyMap<string, CapabilityEntry>;
@@ -0,0 +1,90 @@
1
+ // SPEC-UNIVERSAL-SUBSET §3 — the loud-fail capability resolver (REQ-SUBSET-014). A capability present in
2
+ // an animate/initial/exit target or a gesture prop, on a host that does not declare it, raises a typed
3
+ // UnsupportedCapabilityError naming the capability, the active host, and the host(s) that DO support it.
4
+ // It never silently no-ops, drops, or degrades — this is REQ-API-005's fail-closed invariant applied to
5
+ // subset membership, and the primitive SPEC-COMPONENT's validateTarget builds on. Host-agnostic: it reads
6
+ // the frozen registry and a pure host-capability descriptor; it touches no real react-native host.
7
+ import { UNIVERSAL_SUBSET } from "./registry.js";
8
+ export class UnsupportedCapabilityError extends Error {
9
+ capability;
10
+ hostId;
11
+ reason;
12
+ // The host ids that DO support the capability (empty for an unknown key). Named in the message so a
13
+ // developer sees where the capability is valid.
14
+ supportedOn;
15
+ constructor(capability, hostId, reason, supportedOn, message) {
16
+ super(message);
17
+ this.name = 'UnsupportedCapabilityError';
18
+ this.capability = capability;
19
+ this.hostId = hostId;
20
+ this.reason = reason;
21
+ this.supportedOn = supportedOn;
22
+ }
23
+ }
24
+ // The host archetypes that support each universality class. Provisional taxonomy for the deterministic
25
+ // interior (native = touch-first, web = pointer/keyboard): pointer-gated capability lives on the web
26
+ // host, web-only on the web host, universal + native-extension on both. The exact per-host / per-input
27
+ // gating granularity is a §8 open decision (flagged), refined at the device milestone.
28
+ function supportedHostsFor(universality) {
29
+ switch (universality) {
30
+ case 'universal':
31
+ case 'native-extension':
32
+ return ['native', 'web'];
33
+ case 'web-only':
34
+ case 'pointer-gated':
35
+ return ['web'];
36
+ }
37
+ }
38
+ // Build a host from the universalities its input model supports: it declares every registry key whose
39
+ // universality is in `supported`. Keeps host declarations derived from the single source of truth.
40
+ export function hostCapabilities(id, supported) {
41
+ const supportedSet = new Set(supported);
42
+ const declares = new Set();
43
+ for (const entry of UNIVERSAL_SUBSET.entries) {
44
+ if (!supportedSet.has(entry.universality))
45
+ continue;
46
+ for (const key of entry.keys)
47
+ declares.add(key);
48
+ }
49
+ return { id, declares };
50
+ }
51
+ export function resolveCapabilityVerdict(host, key) {
52
+ const entry = UNIVERSAL_SUBSET.get(key);
53
+ if (entry === undefined) {
54
+ return {
55
+ entry: null,
56
+ unsupported: new UnsupportedCapabilityError(key, host.id, 'unknown', [], `Unknown capability '${key}': not in the universal-subset registry ` +
57
+ `(host '${host.id}').`),
58
+ };
59
+ }
60
+ if (!host.declares.has(key)) {
61
+ const supportedOn = supportedHostsFor(entry.universality);
62
+ return {
63
+ entry: null,
64
+ unsupported: new UnsupportedCapabilityError(key, host.id, 'off-host', supportedOn, `Capability '${key}' is not supported on host '${host.id}' — ` +
65
+ `it is ${entry.universality}; supported on: ${supportedOn.join(', ')}.`),
66
+ };
67
+ }
68
+ return { entry, unsupported: null };
69
+ }
70
+ // Resolve a single capability key against a host. Returns the registry entry when the host declares it;
71
+ // throws UnsupportedCapabilityError otherwise. The unknown-key check comes FIRST so the registry stays
72
+ // authoritative even if a malformed host over-declares.
73
+ export function resolveCapability(host, key) {
74
+ const verdict = resolveCapabilityVerdict(host, key);
75
+ if (verdict.unsupported !== null)
76
+ throw verdict.unsupported;
77
+ return verdict.entry;
78
+ }
79
+ // Gate every key of a target object against a host's declared capability set. Fails closed on the FIRST
80
+ // unsupported key (the throw aborts iteration) and returns a fresh key→entry map only when ALL keys
81
+ // resolve — it never partially resolves (REQ-SUBSET-014 / REQ-API-013 fail-closed). Named
82
+ // `resolveTargetCapabilities` (not `resolveTarget`) so SPEC-COMPONENT can own the public
83
+ // `resolveTarget(base, target)` value-merge; this is the SUBSET capability gate, a distinct function.
84
+ export function resolveTargetCapabilities(host, target) {
85
+ const resolved = new Map();
86
+ for (const key of Object.keys(target)) {
87
+ resolved.set(key, resolveCapability(host, key));
88
+ }
89
+ return resolved;
90
+ }
@@ -0,0 +1,206 @@
1
+ "use strict";
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
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.NAMED_EASING_KEYS = void 0;
16
+ exports.resolveEasing = resolveEasing;
17
+ exports.isEasingList = isEasingList;
18
+ exports.timingGenerator = timingGenerator;
19
+ // Runtime-readable named set (validate / keyframeTiming / shippedSurface share this authority).
20
+ exports.NAMED_EASING_KEYS = [
21
+ 'linear',
22
+ 'easeIn',
23
+ 'easeOut',
24
+ 'easeInOut',
25
+ 'circIn',
26
+ 'circOut',
27
+ 'circInOut',
28
+ 'backIn',
29
+ 'backOut',
30
+ 'backInOut',
31
+ 'anticipate',
32
+ ];
33
+ const DEFAULT_DURATION_MS = 300; // REQ-TIMING-002 (0.3s)
34
+ const DEFAULT_EASE = [0.25, 0.1, 0.35, 1]; // REQ-TIMING-002
35
+ const VELOCITY_SAMPLE_MS = 5;
36
+ // Named cubic-bezier control points (motion-utils/easing/ease + back). Data only — no function values.
37
+ const EASE_IN = [0.42, 0, 1, 1];
38
+ const EASE_OUT = [0, 0, 0.58, 1];
39
+ const EASE_IN_OUT = [0.42, 0, 0.58, 1];
40
+ // motion-utils/easing/back.ts: backOut = cubicBezier(0.33, 1.53, 0.69, 0.99)
41
+ const BACK_OUT = [0.33, 1.53, 0.69, 0.99];
42
+ const clamp01 = (v) => Math.max(0, Math.min(1, v));
43
+ const mix = (from, to, p) => from + (to - from) * p;
44
+ const SUBDIVISION_PRECISION = 1e-7;
45
+ const SUBDIVISION_MAX_ITERATIONS = 12;
46
+ // x(t)/y(t) of the bezier given a single control-point pair (exact port of motion-utils calcBezier).
47
+ const calcBezier = (t, a1, a2) => ((1 - 3 * a2 + 3 * a1) * t + (3 * a2 - 6 * a1)) * t * t + 3 * a1 * t;
48
+ /** Pure cubic-bezier sample — no nested function allocation at module init (hytd3r). */
49
+ function evaluateCubic(x1, y1, x2, y2, t) {
50
+ if (t === 0 || t === 1)
51
+ return t;
52
+ // Linear gradient is the identity; also avoids a degenerate subdivision.
53
+ if (x1 === y1 && x2 === y2)
54
+ return t;
55
+ let lower = 0;
56
+ let upper = 1;
57
+ let currentT = 0;
58
+ let currentX = 0;
59
+ let i = 0;
60
+ do {
61
+ currentT = lower + (upper - lower) / 2;
62
+ currentX = calcBezier(currentT, x1, x2) - t;
63
+ if (currentX > 0)
64
+ upper = currentT;
65
+ else
66
+ lower = currentT;
67
+ } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);
68
+ return calcBezier(currentT, y1, y2);
69
+ }
70
+ // motion-utils/easing/circ.ts — pure forms of reverse/mirror so no function-valued table.
71
+ function evaluateCircIn(p) {
72
+ return 1 - Math.sin(Math.acos(clamp01(p)));
73
+ }
74
+ function evaluateCircOut(p) {
75
+ // reverse(circIn): 1 - circIn(1 - p)
76
+ return 1 - evaluateCircIn(1 - p);
77
+ }
78
+ function evaluateCircInOut(p) {
79
+ // mirror(circIn)
80
+ return p <= 0.5 ? evaluateCircIn(2 * p) / 2 : (2 - evaluateCircIn(2 * (1 - p))) / 2;
81
+ }
82
+ function evaluateBackOut(p) {
83
+ return evaluateCubic(BACK_OUT[0], BACK_OUT[1], BACK_OUT[2], BACK_OUT[3], p);
84
+ }
85
+ function evaluateBackIn(p) {
86
+ // reverse(backOut)
87
+ return 1 - evaluateBackOut(1 - p);
88
+ }
89
+ function evaluateBackInOut(p) {
90
+ // mirror(backIn)
91
+ return p <= 0.5 ? evaluateBackIn(2 * p) / 2 : (2 - evaluateBackIn(2 * (1 - p))) / 2;
92
+ }
93
+ // motion-utils/easing/anticipate.ts
94
+ function evaluateAnticipate(p) {
95
+ if (p >= 1)
96
+ return 1;
97
+ const doubled = p * 2;
98
+ return doubled < 1 ? 0.5 * evaluateBackIn(doubled) : 0.5 * (2 - Math.pow(2, -10 * (doubled - 1)));
99
+ }
100
+ const NAMED_EASING_SET = new Set(exports.NAMED_EASING_KEYS);
101
+ function isNamedEasing(value) {
102
+ return NAMED_EASING_SET.has(value);
103
+ }
104
+ /** Pure named-easing sample — captures no function values (hytd3r Remote Function law). */
105
+ function evaluateNamedEasing(name, p) {
106
+ switch (name) {
107
+ case 'linear':
108
+ return p;
109
+ case 'easeIn':
110
+ return evaluateCubic(EASE_IN[0], EASE_IN[1], EASE_IN[2], EASE_IN[3], p);
111
+ case 'easeOut':
112
+ return evaluateCubic(EASE_OUT[0], EASE_OUT[1], EASE_OUT[2], EASE_OUT[3], p);
113
+ case 'easeInOut':
114
+ return evaluateCubic(EASE_IN_OUT[0], EASE_IN_OUT[1], EASE_IN_OUT[2], EASE_IN_OUT[3], p);
115
+ case 'circIn':
116
+ return evaluateCircIn(p);
117
+ case 'circOut':
118
+ return evaluateCircOut(p);
119
+ case 'circInOut':
120
+ return evaluateCircInOut(p);
121
+ case 'backIn':
122
+ return evaluateBackIn(p);
123
+ case 'backOut':
124
+ return evaluateBackOut(p);
125
+ case 'backInOut':
126
+ return evaluateBackInOut(p);
127
+ case 'anticipate':
128
+ return evaluateAnticipate(p);
129
+ default: {
130
+ // Exhaustiveness + runtime cast guard (9a4arp): never sample NaN for an unknown name.
131
+ const _exhaustive = name;
132
+ throw new Error(`unknown named easing '${String(_exhaustive)}'`);
133
+ }
134
+ }
135
+ }
136
+ // alloc-ok: lifecycle-edge — easing resolution at factory time. Exported for the multi-keyframe
137
+ // generator (keyframes.ts, REQ-API-033), which resolves ONE easing per segment through this same
138
+ // exact BezierEasing / Motion-named port — never a second easing vocabulary.
139
+ // Closures capture only primitives (name string or four numbers) so worklet serialization never
140
+ // embeds a JS-thread Remote Function (hytd3r).
141
+ // Fail-closed (9a4arp): unknown named strings throw before any sample can emit NaN. The public
142
+ // validateTransition boundary also refuses them; this is the generator-seam backstop for direct
143
+ // timingGenerator / resolveEasing callers.
144
+ function resolveEasing(ease) {
145
+ if (typeof ease === 'string') {
146
+ if (!isNamedEasing(ease)) {
147
+ throw new Error(`unknown named easing '${ease}' — expected one of ${exports.NAMED_EASING_KEYS.join(', ')} ` +
148
+ '(REQ-TIMING-001 / REQ-API-033)');
149
+ }
150
+ const name = ease;
151
+ // Named returned closures (frame-path manifest anonymous-sampler repair): the qualified
152
+ // symbols are resolveEasing.namedEvaluator / resolveEasing.cubicEvaluator.
153
+ return function namedEvaluator(p) {
154
+ return evaluateNamedEasing(name, p);
155
+ };
156
+ }
157
+ const x1 = ease[0];
158
+ const y1 = ease[1];
159
+ const x2 = ease[2];
160
+ const y2 = ease[3];
161
+ return function cubicEvaluator(p) {
162
+ return evaluateCubic(x1, y1, x2, y2, p);
163
+ };
164
+ }
165
+ // Disambiguate a PER-SEGMENT easing list (`['easeIn', 'easeOut']`, `[[…],[…]]`) from a SINGLE
166
+ // cubic-bezier easing (`[0.25, 0.1, 0.35, 1]`) — both are arrays. A per-segment list's elements are
167
+ // themselves easings (a named string or a nested bezier array); a single CubicBezier's elements are
168
+ // plain numbers. Mirrors motion-dom's `isEasingArray`. Without this, a single-bezier `ease` on a
169
+ // keyframe array would be mis-read element-by-element as per-segment (REQ-API-033).
170
+ function isEasingList(ease) {
171
+ return Array.isArray(ease) && typeof ease[0] !== 'number';
172
+ }
173
+ /**
174
+ * Build a tween `GeneratorFactory` (REQ-API-004). `seed.from` is the origin; the seed's incoming
175
+ * velocity is intentionally ignored (REQ-TIMING-001). The tween finishes deterministically at
176
+ * `t ≥ duration`.
177
+ */
178
+ // alloc-ok: lifecycle-edge — the factory resolves duration/ease once per animate command;
179
+ // per-frame work is sample() below, which mutates the reused record and allocates nothing.
180
+ function timingGenerator(target, config) {
181
+ const duration = config?.duration ?? DEFAULT_DURATION_MS;
182
+ const ease = resolveEasing(config?.ease ?? DEFAULT_EASE);
183
+ // alloc-ok: lifecycle-edge — generator construction at command time; the one reused sample
184
+ // record is built here, never per frame.
185
+ return (seed) => {
186
+ const origin = seed.from;
187
+ const value = (t) => mix(origin, target, ease(clamp01(t / duration)));
188
+ // One sample record per generator, mutated and returned every call — motion's own generators
189
+ // return their reused `state` the same way. Per-frame sampling must not allocate
190
+ // (REQ-DRIVER-015); callers read the scalars immediately and never retain the record.
191
+ const out = { value: origin, velocity: 0, done: false };
192
+ return {
193
+ sample(elapsedMs) {
194
+ const current = value(elapsedMs);
195
+ const prevT = Math.max(elapsedMs - VELOCITY_SAMPLE_MS, 0);
196
+ const dt = elapsedMs - prevT;
197
+ const velocity = dt ? ((current - value(prevT)) / dt) * 1000 : 0; // px/s (REQ-TIMING-001)
198
+ const done = elapsedMs >= duration;
199
+ out.value = done ? target : current;
200
+ out.velocity = velocity;
201
+ out.done = done;
202
+ return out;
203
+ },
204
+ };
205
+ };
206
+ }
@@ -0,0 +1,17 @@
1
+ import type { GeneratorFactory } from "./types.cjs";
2
+ export type CubicBezier = readonly [number, number, number, number];
3
+ export type NamedEasing = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'circIn' | 'circOut' | 'circInOut' | 'backIn' | 'backOut' | 'backInOut' | 'anticipate';
4
+ export type Easing = CubicBezier | NamedEasing;
5
+ export declare const NAMED_EASING_KEYS: readonly ["linear", "easeIn", "easeOut", "easeInOut", "circIn", "circOut", "circInOut", "backIn", "backOut", "backInOut", "anticipate"];
6
+ export interface TimingConfig {
7
+ duration?: number;
8
+ ease?: Easing;
9
+ }
10
+ export declare function resolveEasing(ease: Easing): (p: number) => number;
11
+ export declare function isEasingList(ease: Easing | readonly Easing[]): ease is readonly Easing[];
12
+ /**
13
+ * Build a tween `GeneratorFactory` (REQ-API-004). `seed.from` is the origin; the seed's incoming
14
+ * velocity is intentionally ignored (REQ-TIMING-001). The tween finishes deterministically at
15
+ * `t ≥ duration`.
16
+ */
17
+ export declare function timingGenerator(target: number, config?: TimingConfig): GeneratorFactory;
@@ -0,0 +1,17 @@
1
+ import type { GeneratorFactory } from "./types.js";
2
+ export type CubicBezier = readonly [number, number, number, number];
3
+ export type NamedEasing = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut' | 'circIn' | 'circOut' | 'circInOut' | 'backIn' | 'backOut' | 'backInOut' | 'anticipate';
4
+ export type Easing = CubicBezier | NamedEasing;
5
+ export declare const NAMED_EASING_KEYS: readonly ["linear", "easeIn", "easeOut", "easeInOut", "circIn", "circOut", "circInOut", "backIn", "backOut", "backInOut", "anticipate"];
6
+ export interface TimingConfig {
7
+ duration?: number;
8
+ ease?: Easing;
9
+ }
10
+ export declare function resolveEasing(ease: Easing): (p: number) => number;
11
+ export declare function isEasingList(ease: Easing | readonly Easing[]): ease is readonly Easing[];
12
+ /**
13
+ * Build a tween `GeneratorFactory` (REQ-API-004). `seed.from` is the origin; the seed's incoming
14
+ * velocity is intentionally ignored (REQ-TIMING-001). The tween finishes deterministically at
15
+ * `t ≥ duration`.
16
+ */
17
+ export declare function timingGenerator(target: number, config?: TimingConfig): GeneratorFactory;