@rootnative/inertia 0.0.0-alpha.7 → 0.0.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 (42) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-ALRHDFZE.mjs → chunk-2DHKV2XY.mjs} +1 -1
  4. package/dist/chunk-34Q4UM6V.js +8 -0
  5. package/dist/{chunk-CWLFUYIY.mjs → chunk-HFDZAHWP.mjs} +1 -1
  6. package/dist/{chunk-7UDYEFBU.js → chunk-IWLU3VDE.js} +361 -288
  7. package/dist/chunk-KYJROYCG.js +8 -0
  8. package/dist/{chunk-DWCLIBYO.mjs → chunk-LYMLQ6WQ.mjs} +362 -289
  9. package/dist/{chunk-TDSO63CJ.js → chunk-NKA6XR77.js} +2 -2
  10. package/dist/{chunk-6SMPIOIC.mjs → chunk-TUMNV4P7.mjs} +1 -1
  11. package/dist/{chunk-2HYD2ZBK.js → chunk-TUYHTHVV.js} +2 -2
  12. package/dist/{chunk-NXDJZD6A.mjs → chunk-V6BTXHZK.mjs} +1 -1
  13. package/dist/chunk-X5J5M3K3.js +8 -0
  14. package/dist/{chunk-JVBXPF2G.mjs → chunk-ZN3PNGHQ.mjs} +1 -1
  15. package/dist/index.d.mts +229 -43
  16. package/dist/index.d.ts +229 -43
  17. package/dist/index.js +199 -23
  18. package/dist/index.mjs +191 -18
  19. package/dist/motion/Image.js +3 -3
  20. package/dist/motion/Image.mjs +2 -2
  21. package/dist/motion/Pressable.js +3 -3
  22. package/dist/motion/Pressable.mjs +2 -2
  23. package/dist/motion/ScrollView.js +3 -3
  24. package/dist/motion/ScrollView.mjs +2 -2
  25. package/dist/motion/Text.js +3 -3
  26. package/dist/motion/Text.mjs +2 -2
  27. package/dist/motion/View.js +3 -3
  28. package/dist/motion/View.mjs +2 -2
  29. package/llms.txt +6 -1
  30. package/package.json +1 -1
  31. package/src/index.ts +10 -0
  32. package/src/motion/createMotionComponent.tsx +624 -501
  33. package/src/values/index.ts +13 -0
  34. package/src/values/useAnimation.ts +15 -1
  35. package/src/values/useAnimator.ts +72 -0
  36. package/src/values/useColorCascade.ts +107 -0
  37. package/src/values/useInterpolatedStyle.ts +319 -0
  38. package/src/values/useMotionValue.ts +20 -2
  39. package/src/values/useSpring.ts +12 -0
  40. package/dist/chunk-3UTJJ4A3.js +0 -8
  41. package/dist/chunk-4QGXK6TF.js +0 -8
  42. package/dist/chunk-Z7HIOFKQ.js +0 -8
package/dist/index.mjs CHANGED
@@ -1,21 +1,21 @@
1
1
  export { useGesture } from './chunk-RGNX6UZN.mjs';
2
- import { MotionView } from './chunk-6SMPIOIC.mjs';
3
- export { MotionView } from './chunk-6SMPIOIC.mjs';
4
- import { MotionText } from './chunk-JVBXPF2G.mjs';
5
- export { MotionText } from './chunk-JVBXPF2G.mjs';
6
- import { MotionImage } from './chunk-ALRHDFZE.mjs';
7
- export { MotionImage } from './chunk-ALRHDFZE.mjs';
8
- import { MotionPressable } from './chunk-NXDJZD6A.mjs';
9
- export { MotionPressable } from './chunk-NXDJZD6A.mjs';
10
- import { MotionScrollView } from './chunk-CWLFUYIY.mjs';
11
- export { MotionScrollView } from './chunk-CWLFUYIY.mjs';
12
- export { Presence, createMotionComponent, usePresence } from './chunk-DWCLIBYO.mjs';
2
+ import { MotionView } from './chunk-TUMNV4P7.mjs';
3
+ export { MotionView } from './chunk-TUMNV4P7.mjs';
4
+ import { MotionText } from './chunk-ZN3PNGHQ.mjs';
5
+ export { MotionText } from './chunk-ZN3PNGHQ.mjs';
6
+ import { MotionImage } from './chunk-2DHKV2XY.mjs';
7
+ export { MotionImage } from './chunk-2DHKV2XY.mjs';
8
+ import { MotionPressable } from './chunk-V6BTXHZK.mjs';
9
+ export { MotionPressable } from './chunk-V6BTXHZK.mjs';
10
+ import { MotionScrollView } from './chunk-HFDZAHWP.mjs';
11
+ export { MotionScrollView } from './chunk-HFDZAHWP.mjs';
12
+ export { Presence, createMotionComponent, usePresence } from './chunk-LYMLQ6WQ.mjs';
13
13
  import { useShouldReduceMotion, resolveNamedTransition, useNamedTransitions, lookupNamedTransition } from './chunk-R63GIUNU.mjs';
14
14
  export { MotionConfig, resolveNamedTransition, useMotionConfig, useNamedTransitions, useShouldReduceMotion } from './chunk-R63GIUNU.mjs';
15
15
  import { stableSig, resolveTransition, springToReanimated, warnNonWorkletOnce } from './chunk-CY7Y64C3.mjs';
16
16
  export { buildReleaseAnimation, cubicBezier, ensureWorkletEasing, resolveAnimatableValue, resolveTransition } from './chunk-CY7Y64C3.mjs';
17
- import { useEffect, useMemo, useRef } from 'react';
18
- import { useSharedValue, withSpring, useAnimatedReaction, useAnimatedStyle, interpolateColor, useDerivedValue, Extrapolation, useAnimatedScrollHandler, interpolate } from 'react-native-reanimated';
17
+ import { useEffect, useCallback, useMemo, useRef } from 'react';
18
+ import { useSharedValue, cancelAnimation, withSpring, useAnimatedReaction, useAnimatedStyle, interpolateColor, interpolate, useDerivedValue, Extrapolation, useAnimatedScrollHandler } from 'react-native-reanimated';
19
19
  import { isWorkletFunction } from 'react-native-worklets';
20
20
 
21
21
  // src/motion/index.ts
@@ -35,8 +35,26 @@ function useAnimation(target, transition) {
35
35
  const cfg = shouldReduceMotion ? { type: "no-animation" } : resolved ?? { type: "spring" };
36
36
  output.value = resolveTransition(cfg, target);
37
37
  }, [target, cfgSig, shouldReduceMotion]);
38
+ useEffect(
39
+ () => () => cancelAnimation(output),
40
+ // `output` is identity-stable per hook instance (Reanimated guarantee).
41
+ // eslint-disable-next-line react-hooks/exhaustive-deps
42
+ []
43
+ );
38
44
  return output;
39
45
  }
46
+ function useAnimator() {
47
+ const registry = useNamedTransitions();
48
+ const shouldReduceMotion = useShouldReduceMotion();
49
+ return useCallback(
50
+ (value, to, transition) => {
51
+ const resolved = resolveNamedTransition(transition, registry);
52
+ const cfg = shouldReduceMotion ? { type: "no-animation" } : resolved ?? { type: "spring" };
53
+ value.value = resolveTransition(cfg, to);
54
+ },
55
+ [registry, shouldReduceMotion]
56
+ );
57
+ }
40
58
  function useSpring(target, config) {
41
59
  const spring = resolveSpringInput(config, useNamedTransitions());
42
60
  const reanimConfig = useMemo(
@@ -75,6 +93,12 @@ function useSpring(target, config) {
75
93
  },
76
94
  [isSharedTarget, reanimConfig]
77
95
  );
96
+ useEffect(
97
+ () => () => cancelAnimation(output),
98
+ // `output` is identity-stable per hook instance (Reanimated guarantee).
99
+ // eslint-disable-next-line react-hooks/exhaustive-deps
100
+ []
101
+ );
78
102
  return output;
79
103
  }
80
104
  function resolveSpringInput(config, registry) {
@@ -96,6 +120,24 @@ function isSharedValue(v) {
96
120
  function useBooleanSpring(active, springConfig) {
97
121
  return useSpring(active ? 1 : 0, springConfig);
98
122
  }
123
+ function useColorCascade(rest, layers, options) {
124
+ const key = options?.key ?? "backgroundColor";
125
+ const sig = `${key}|${rest}|${layers.length}|${layers.map((l) => l.color).join(",")}`;
126
+ const colors = useMemo(() => layers.map((l) => l.color), [sig]);
127
+ const progressValues = useMemo(() => layers.map((l) => l.progress), [sig]);
128
+ return useAnimatedStyle(() => {
129
+ "worklet";
130
+ let acc = rest;
131
+ for (let i = 0; i < colors.length; i++) {
132
+ acc = interpolateColor(
133
+ progressValues[i].value,
134
+ [0, 1],
135
+ [acc, colors[i]]
136
+ );
137
+ }
138
+ return { [key]: acc };
139
+ });
140
+ }
99
141
  function useColorTransition(progress, range, options) {
100
142
  const key = options?.key ?? "backgroundColor";
101
143
  const from = range[0];
@@ -105,8 +147,139 @@ function useColorTransition(progress, range, options) {
105
147
  return { [key]: interpolateColor(progress.value, [0, 1], [from, to]) };
106
148
  });
107
149
  }
150
+ var TRANSFORM_KEYS = /* @__PURE__ */ new Set([
151
+ "translateX",
152
+ "translateY",
153
+ "scale",
154
+ "scaleX",
155
+ "scaleY",
156
+ "rotate",
157
+ "rotateX",
158
+ "rotateY"
159
+ ]);
160
+ var ROTATION_KEYS = /* @__PURE__ */ new Set(["rotate", "rotateX", "rotateY"]);
161
+ var COLOR_KEYS = /* @__PURE__ */ new Set([
162
+ "backgroundColor",
163
+ "color",
164
+ "borderColor",
165
+ "borderTopColor",
166
+ "borderRightColor",
167
+ "borderBottomColor",
168
+ "borderLeftColor",
169
+ "tintColor",
170
+ "shadowColor"
171
+ ]);
172
+ function evenlySpaced(count) {
173
+ if (count <= 1) return [0];
174
+ const out = [];
175
+ for (let i = 0; i < count; i++) out.push(i / (count - 1));
176
+ return out;
177
+ }
178
+ function mapExtrapolation(mode) {
179
+ if (mode === "identity") return Extrapolation.IDENTITY;
180
+ if (mode === "extend") return Extrapolation.EXTEND;
181
+ return Extrapolation.CLAMP;
182
+ }
183
+ function buildSignature(map, options) {
184
+ let sig = "";
185
+ for (const key of Object.keys(map)) {
186
+ const output = map[key];
187
+ sig += `${key}:${JSON.stringify(output)}|`;
188
+ }
189
+ sig += `#ir:${JSON.stringify(options?.inputRange)}|ex:${options?.extrapolate ?? ""}`;
190
+ return sig;
191
+ }
192
+ function buildEntries(map, options) {
193
+ const explicitInput = options?.inputRange;
194
+ const entries = [];
195
+ for (const key of Object.keys(map)) {
196
+ const output = map[key];
197
+ if (output === void 0 || output.length === 0) continue;
198
+ const input = explicitInput ? explicitInput : output.length === 2 ? [0, 1] : evenlySpaced(output.length);
199
+ if (__DEV__ && explicitInput && explicitInput.length !== output.length) {
200
+ console.warn(
201
+ `[inertia] useInterpolatedStyle: inputRange has ${explicitInput.length} stops but the "${String(
202
+ key
203
+ )}" output has ${output.length}. They must match \u2014 interpolation results are undefined otherwise.`
204
+ );
205
+ }
206
+ const isColor = COLOR_KEYS.has(key) && typeof output[0] === "string";
207
+ if (isColor) {
208
+ entries.push({
209
+ kind: "color",
210
+ key,
211
+ input,
212
+ output
213
+ });
214
+ } else if (ROTATION_KEYS.has(key)) {
215
+ entries.push({
216
+ kind: "rotation",
217
+ key,
218
+ input,
219
+ output
220
+ });
221
+ } else if (TRANSFORM_KEYS.has(key)) {
222
+ entries.push({
223
+ kind: "transform-numeric",
224
+ key,
225
+ input,
226
+ output
227
+ });
228
+ } else {
229
+ entries.push({
230
+ kind: "numeric",
231
+ key,
232
+ input,
233
+ output
234
+ });
235
+ }
236
+ }
237
+ return entries;
238
+ }
239
+ function useInterpolatedStyle(progress, map, options) {
240
+ const extrapolate = mapExtrapolation(options?.extrapolate);
241
+ const sig = buildSignature(map, options);
242
+ const entries = useMemo(() => buildEntries(map, options), [sig]);
243
+ return useAnimatedStyle(() => {
244
+ "worklet";
245
+ const out = {};
246
+ const transform = [];
247
+ for (const e of entries) {
248
+ if (e.kind === "color") {
249
+ out[e.key] = interpolateColor(progress.value, e.input, e.output);
250
+ } else if (e.kind === "numeric") {
251
+ out[e.key] = interpolate(progress.value, e.input, e.output, {
252
+ extrapolateLeft: extrapolate,
253
+ extrapolateRight: extrapolate
254
+ });
255
+ } else if (e.kind === "transform-numeric") {
256
+ transform.push({
257
+ [e.key]: interpolate(progress.value, e.input, e.output, {
258
+ extrapolateLeft: extrapolate,
259
+ extrapolateRight: extrapolate
260
+ })
261
+ });
262
+ } else {
263
+ const deg = interpolate(progress.value, e.input, e.output, {
264
+ extrapolateLeft: extrapolate,
265
+ extrapolateRight: extrapolate
266
+ });
267
+ transform.push({ [e.key]: `${deg}deg` });
268
+ }
269
+ }
270
+ if (transform.length > 0) out.transform = transform;
271
+ return out;
272
+ });
273
+ }
108
274
  function useMotionValue(initial) {
109
- return useSharedValue(initial);
275
+ const sv = useSharedValue(initial);
276
+ useEffect(
277
+ () => () => cancelAnimation(sv),
278
+ // `sv` is identity-stable per hook instance (Reanimated guarantee).
279
+ // eslint-disable-next-line react-hooks/exhaustive-deps
280
+ []
281
+ );
282
+ return sv;
110
283
  }
111
284
  function useTransform(arg1, inputRange, outputRange, options) {
112
285
  let producer;
@@ -129,8 +302,8 @@ function useTransform(arg1, inputRange, outputRange, options) {
129
302
  const input = inputRange;
130
303
  const output = outputRange;
131
304
  const isColor = output.length > 0 && typeof output[0] === "string";
132
- const extrapolateLeft = mapExtrapolation(options?.extrapolateLeft);
133
- const extrapolateRight = mapExtrapolation(options?.extrapolateRight);
305
+ const extrapolateLeft = mapExtrapolation2(options?.extrapolateLeft);
306
+ const extrapolateRight = mapExtrapolation2(options?.extrapolateRight);
134
307
  producer = isColor ? () => {
135
308
  "worklet";
136
309
  return interpolateColor(
@@ -150,7 +323,7 @@ function useTransform(arg1, inputRange, outputRange, options) {
150
323
  }
151
324
  return useDerivedValue(producer);
152
325
  }
153
- function mapExtrapolation(mode) {
326
+ function mapExtrapolation2(mode) {
154
327
  if (mode === "identity") return Extrapolation.IDENTITY;
155
328
  if (mode === "extend") return Extrapolation.EXTEND;
156
329
  return Extrapolation.CLAMP;
@@ -401,4 +574,4 @@ function useVariants(variants, initial) {
401
574
  }, []);
402
575
  }
403
576
 
404
- export { Motion, useAnimation, useBooleanSpring, useColorTransition, useMotionValue, useScroll, useShadow, useSpring, useTransform, useVariants };
577
+ export { Motion, useAnimation, useAnimator, useBooleanSpring, useColorCascade, useColorTransition, useInterpolatedStyle, useMotionValue, useScroll, useShadow, useSpring, useTransform, useVariants };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk3UTJJ4A3_js = require('../chunk-3UTJJ4A3.js');
4
- require('../chunk-7UDYEFBU.js');
3
+ var chunk34Q4UM6V_js = require('../chunk-34Q4UM6V.js');
4
+ require('../chunk-IWLU3VDE.js');
5
5
  require('../chunk-7AOERN53.js');
6
6
  require('../chunk-PTRF47DA.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionImage", {
11
11
  enumerable: true,
12
- get: function () { return chunk3UTJJ4A3_js.MotionImage; }
12
+ get: function () { return chunk34Q4UM6V_js.MotionImage; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionImage } from '../chunk-ALRHDFZE.mjs';
2
- import '../chunk-DWCLIBYO.mjs';
1
+ export { MotionImage } from '../chunk-2DHKV2XY.mjs';
2
+ import '../chunk-LYMLQ6WQ.mjs';
3
3
  import '../chunk-R63GIUNU.mjs';
4
4
  import '../chunk-CY7Y64C3.mjs';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkTDSO63CJ_js = require('../chunk-TDSO63CJ.js');
4
- require('../chunk-7UDYEFBU.js');
3
+ var chunkNKA6XR77_js = require('../chunk-NKA6XR77.js');
4
+ require('../chunk-IWLU3VDE.js');
5
5
  require('../chunk-7AOERN53.js');
6
6
  require('../chunk-PTRF47DA.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionPressable", {
11
11
  enumerable: true,
12
- get: function () { return chunkTDSO63CJ_js.MotionPressable; }
12
+ get: function () { return chunkNKA6XR77_js.MotionPressable; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionPressable } from '../chunk-NXDJZD6A.mjs';
2
- import '../chunk-DWCLIBYO.mjs';
1
+ export { MotionPressable } from '../chunk-V6BTXHZK.mjs';
2
+ import '../chunk-LYMLQ6WQ.mjs';
3
3
  import '../chunk-R63GIUNU.mjs';
4
4
  import '../chunk-CY7Y64C3.mjs';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk2HYD2ZBK_js = require('../chunk-2HYD2ZBK.js');
4
- require('../chunk-7UDYEFBU.js');
3
+ var chunkTUYHTHVV_js = require('../chunk-TUYHTHVV.js');
4
+ require('../chunk-IWLU3VDE.js');
5
5
  require('../chunk-7AOERN53.js');
6
6
  require('../chunk-PTRF47DA.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionScrollView", {
11
11
  enumerable: true,
12
- get: function () { return chunk2HYD2ZBK_js.MotionScrollView; }
12
+ get: function () { return chunkTUYHTHVV_js.MotionScrollView; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionScrollView } from '../chunk-CWLFUYIY.mjs';
2
- import '../chunk-DWCLIBYO.mjs';
1
+ export { MotionScrollView } from '../chunk-HFDZAHWP.mjs';
2
+ import '../chunk-LYMLQ6WQ.mjs';
3
3
  import '../chunk-R63GIUNU.mjs';
4
4
  import '../chunk-CY7Y64C3.mjs';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkZ7HIOFKQ_js = require('../chunk-Z7HIOFKQ.js');
4
- require('../chunk-7UDYEFBU.js');
3
+ var chunkX5J5M3K3_js = require('../chunk-X5J5M3K3.js');
4
+ require('../chunk-IWLU3VDE.js');
5
5
  require('../chunk-7AOERN53.js');
6
6
  require('../chunk-PTRF47DA.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionText", {
11
11
  enumerable: true,
12
- get: function () { return chunkZ7HIOFKQ_js.MotionText; }
12
+ get: function () { return chunkX5J5M3K3_js.MotionText; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionText } from '../chunk-JVBXPF2G.mjs';
2
- import '../chunk-DWCLIBYO.mjs';
1
+ export { MotionText } from '../chunk-ZN3PNGHQ.mjs';
2
+ import '../chunk-LYMLQ6WQ.mjs';
3
3
  import '../chunk-R63GIUNU.mjs';
4
4
  import '../chunk-CY7Y64C3.mjs';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk4QGXK6TF_js = require('../chunk-4QGXK6TF.js');
4
- require('../chunk-7UDYEFBU.js');
3
+ var chunkKYJROYCG_js = require('../chunk-KYJROYCG.js');
4
+ require('../chunk-IWLU3VDE.js');
5
5
  require('../chunk-7AOERN53.js');
6
6
  require('../chunk-PTRF47DA.js');
7
7
 
@@ -9,5 +9,5 @@ require('../chunk-PTRF47DA.js');
9
9
 
10
10
  Object.defineProperty(exports, "MotionView", {
11
11
  enumerable: true,
12
- get: function () { return chunk4QGXK6TF_js.MotionView; }
12
+ get: function () { return chunkKYJROYCG_js.MotionView; }
13
13
  });
@@ -1,4 +1,4 @@
1
- export { MotionView } from '../chunk-6SMPIOIC.mjs';
2
- import '../chunk-DWCLIBYO.mjs';
1
+ export { MotionView } from '../chunk-TUMNV4P7.mjs';
2
+ import '../chunk-LYMLQ6WQ.mjs';
3
3
  import '../chunk-R63GIUNU.mjs';
4
4
  import '../chunk-CY7Y64C3.mjs';
package/llms.txt CHANGED
@@ -26,6 +26,8 @@ import {
26
26
  useTransform,
27
27
  useShadow,
28
28
  useColorTransition,
29
+ useColorCascade,
30
+ useInterpolatedStyle,
29
31
  useScroll,
30
32
  } from '@rootnative/inertia'
31
33
  // Opt-in MD3 / iOS state-layer overlay helper:
@@ -50,11 +52,14 @@ import { MotionScrollView } from '@rootnative/inertia/scroll-view'
50
52
  - `useVariants(variants, initial?)` — returns `{ current, transitionTo }` controller for the `controller` prop.
51
53
  - `useMotionValue(initial)` — thin pass-through over `useSharedValue<T>`. Returns a `SharedValue<T>` directly so it interops with every Reanimated API without unwrapping.
52
54
  - `useAnimation(target, transition?)` — drive a `SharedValue<number>` toward `target` with any `TransitionConfig` (spring / timing / decay / no-animation, plus `repeat`) or a registered `TransitionName`. The general-purpose value-layer hook for boolean-state progress, indeterminate loops, and anywhere the same value needs to feed multiple `useAnimatedStyle` blocks.
55
+ - `useAnimator()` — the **imperative** counterpart to `useAnimation`. Returns an identity-stable `(value: SharedValue<number>, to: number, transition?: TransitionConfig | TransitionName) => void` setter to call from event handlers (hover-in, focus, press) rather than from an effect. Resolves registered `TransitionName`s through the nearest `<MotionConfig transitions>` and gates on `<MotionConfig reducedMotion>` (`'no-animation'` downgrade) — the two things a hand-rolled `resolveTransition` write in an event handler silently gets wrong. Default transition is the library spring. Not a new animation API — the hooks-layer equivalent of `useMotionValue` + `resolveTransition`, minus the footguns.
53
56
  - `useSpring(target, config?)` — spring-only shorthand. Animates a `SharedValue<number>` toward `target` with react-spring vocab (or a spring-typed registered `TransitionName`; non-spring names warn and fall back to the default spring). `target` may be a plain number (effect-driven) or a `SharedValue<number>` (UI-thread reaction); the latter is the gesture-smoothing path.
54
57
  - `useBooleanSpring(active, config?)` — sugar over `useSpring` for the recurring "spring 0↔1 progress from a boolean" shape (checkbox checks, accordion expansions, drawer open/closed). Identical mechanics to `useSpring(active ? 1 : 0, config)` — the named form so the call site reads as the boolean it represents.
55
58
  - `useTransform(value, inputRange, outputRange, options?)` / `useTransform(transformer)` — interpolate a numeric shared value onto a number or color range, or derive any value from any number of shared values via a worklet. Non-worklet transformers are auto-wrapped.
56
59
  - `useShadow({ from, to, progress })` — pure value-layer interpolator between two `ShadowConfig`s (`shadowOpacity` / `shadowRadius` / `shadowOffset` / `elevation` / `shadowColor`, plus `boxShadow` as a CSS string or `BoxShadowLayer[]` — the shadow surface on web and RN 0.76+ new-arch; multi-layer, CSS-transition padding semantics, malformed strings throw at setup) driven by a `SharedValue<number>` (0→1). Returns an animated style fragment to spread onto `style`; only emits keys present on either side, absent sides default to natural zero. The hook does not animate on its own — drive `progress` with a spring, a scroll-derived `useTransform`, or any other shared value source.
57
60
  - `useColorTransition(progress, [from, to], options?)` — pure value-layer interpolator for a single color channel, driven by a `SharedValue<number>` (0→1). Returns an animated style fragment with one color key (default `backgroundColor`; configurable via `options.key` to `color` / `borderColor` / `tintColor` / `shadowColor` / per-side border colors). For raw `SharedValue<string>` output, use `useTransform(progress, [0, 1], [from, to])` instead.
61
+ - `useColorCascade(rest, layers, options?)` — pure value-layer interpolator compositing a **priority-ordered** stack of color layers over a base `rest` color; each `layers` entry is `{ progress: SharedValue<number>, color: string }`, later entries win as their progress rises (equivalent to the nested `focus(error(hover(rest)))` `interpolateColor` chain). `options.key` reuses `ColorStyleKey` (default `backgroundColor`). Returns a spreadable animated style fragment; memoized on a colors+key signature. Color-only by design — cascade a numeric key separately via `useInterpolatedStyle` + `useTransform` max. `useColorTransition` stays the single-layer fast path.
62
+ - `useInterpolatedStyle(progress, map, options?)` — pure value-layer interpolator mapping one `SharedValue<number>` onto **N** style props at once, returned as a spreadable animated style fragment (the multi-key, style-fragment counterpart to `useTransform`'s output-range form). Numeric keys (`opacity` / `height` / `fontSize` / …) route through `interpolate`; transform keys (`translateX` / `scale` / `rotate` / …) lift into a `transform` array in map key-order (`rotate*` emit `'<n>deg'`); color keys (`backgroundColor` / `borderColor` / …) route through `interpolateColor` (a multi-stop `useColorTransition`). Stop types are compile-checked. `options.inputRange` (default `[0,1]` / evenly-spaced) and `options.extrapolate` (default `'clamp'`) apply to every key. Memoized on an order-preserving signature. For function-valued or multi-source composition, drop to `useTransform`'s worklet form or a hand-rolled `useAnimatedStyle`.
58
63
  - `useScroll()` — returns `{ scrollX, scrollY, onScroll }` for use with `Motion.ScrollView`. Scroll events fire on the UI thread.
59
64
  - `createMotionComponent<C>(C)` — wrap any component with the same Motion prop surface, inferring style from `C`.
60
65
  - `buildReleaseAnimation(transition, toValue)` — worklet-safe single-step animation builder (spring / timing / decay / no-animation). For assigning Inertia-resolved animations to shared values from inside a gesture worklet. Used internally by `@rootnative/inertia-gestures`'s `useDrag({ onRelease })`.
@@ -133,7 +138,7 @@ Numeric: `opacity`, `translateX`, `translateY`, `scale`, `scaleX`, `scaleY`, `ro
133
138
 
134
139
  Color: `backgroundColor`, `borderColor`, `color`, `tintColor` (Image only), `shadowColor`. Hex, `rgb()` / `rgba()`, `hsl()` / `hsla()`, and named colors all work; the target string is forwarded straight through `withSpring` / `withTiming` and Reanimated handles RGBA interpolation natively.
135
140
 
136
- Nested object: `shadowOffset: { width, height }`. The only nested-object style on the surface — internally decomposes into two synthetic axis SVs that the worklet recomposes into a single `shadowOffset` prop. v0.1 supports the **single-value form only** (`{ width: 0, height: 4 }`); sequences / array keyframes / per-axis transition splits are out of scope, drop to `useMotionValue` for those.
141
+ Nested object: `shadowOffset: { width, height }`. The only nested-object style on the surface — internally decomposes into two synthetic axis SVs that the worklet recomposes into a single `shadowOffset` prop. `0.0.1` supports the **single-value form only** (`{ width: 0, height: 4 }`); sequences / array keyframes / per-axis transition splits are out of scope, drop to `useMotionValue` for those.
137
142
 
138
143
  Auto-layout transitions ship via the `layout` prop (`true` / `TransitionConfig`) on every `Motion.*` primitive — see Layout. Shared element transitions ship via the `layoutId` prop: pair the same id on a source and target `Motion.*` and Inertia FLIPs between them on mount (parent-relative coords, rect-only animation, 1s TTL).
139
144
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootnative/inertia",
3
- "version": "0.0.0-alpha.7",
3
+ "version": "0.0.2",
4
4
  "description": "Declarative animation primitives for React Native, built on react-native-reanimated.",
5
5
  "license": "MIT",
6
6
  "author": "RootNative",
package/src/index.ts CHANGED
@@ -41,9 +41,12 @@ export {
41
41
  } from './transitions'
42
42
  export {
43
43
  useAnimation,
44
+ useAnimator,
44
45
  useBooleanSpring,
46
+ useColorCascade,
45
47
  useColorTransition,
46
48
  useGesture,
49
+ useInterpolatedStyle,
47
50
  useMotionValue,
48
51
  useScroll,
49
52
  useShadow,
@@ -57,13 +60,20 @@ export {
57
60
  // Runtime render-layer interop lives in `@rootnative/inertia/reanimated`.
58
61
  export type { SharedValue } from 'react-native-reanimated'
59
62
  export type {
63
+ Animator,
60
64
  BoxShadowLayer,
65
+ ColorCascadeLayer,
61
66
  ColorStyleKey,
62
67
  ExtrapolationMode,
68
+ InterpolatedStyleMap,
69
+ NumericStyleKey,
63
70
  ShadowConfig,
71
+ TransformKey,
72
+ UseColorCascadeOptions,
64
73
  UseColorTransitionOptions,
65
74
  UseGestureHandlers,
66
75
  UseGestureResult,
76
+ UseInterpolatedStyleOptions,
67
77
  UseScrollResult,
68
78
  UseShadowOptions,
69
79
  UseTransformOptions,