@rootnative/inertia 0.0.0-alpha.0 → 0.0.0-alpha.1
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.
- package/CHANGELOG.md +10 -0
- package/README.md +2 -0
- package/dist/gestureLayer/index.d.mts +6 -5
- package/dist/gestureLayer/index.d.ts +6 -5
- package/dist/gestureLayer/index.js +89 -27
- package/dist/gestureLayer/index.js.map +1 -1
- package/dist/gestureLayer/index.mjs +89 -27
- package/dist/gestureLayer/index.mjs.map +1 -1
- package/dist/index.d.mts +127 -16
- package/dist/index.d.ts +127 -16
- package/dist/index.js +177 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +175 -61
- package/dist/index.mjs.map +1 -1
- package/dist/motion/Image.d.mts +1 -1
- package/dist/motion/Image.d.ts +1 -1
- package/dist/motion/Image.js +90 -48
- package/dist/motion/Image.js.map +1 -1
- package/dist/motion/Image.mjs +90 -48
- package/dist/motion/Image.mjs.map +1 -1
- package/dist/motion/Pressable.d.mts +1 -1
- package/dist/motion/Pressable.d.ts +1 -1
- package/dist/motion/Pressable.js +90 -48
- package/dist/motion/Pressable.js.map +1 -1
- package/dist/motion/Pressable.mjs +90 -48
- package/dist/motion/Pressable.mjs.map +1 -1
- package/dist/motion/ScrollView.d.mts +1 -1
- package/dist/motion/ScrollView.d.ts +1 -1
- package/dist/motion/ScrollView.js +90 -48
- package/dist/motion/ScrollView.js.map +1 -1
- package/dist/motion/ScrollView.mjs +90 -48
- package/dist/motion/ScrollView.mjs.map +1 -1
- package/dist/motion/Text.d.mts +1 -1
- package/dist/motion/Text.d.ts +1 -1
- package/dist/motion/Text.js +90 -48
- package/dist/motion/Text.js.map +1 -1
- package/dist/motion/Text.mjs +90 -48
- package/dist/motion/Text.mjs.map +1 -1
- package/dist/motion/View.d.mts +1 -1
- package/dist/motion/View.d.ts +1 -1
- package/dist/motion/View.js +90 -48
- package/dist/motion/View.js.map +1 -1
- package/dist/motion/View.mjs +90 -48
- package/dist/motion/View.mjs.map +1 -1
- package/dist/touch/index.d.mts +1 -1
- package/dist/touch/index.d.ts +1 -1
- package/dist/{types-cU43dEmH.d.mts → types-BzEgiUdJ.d.mts} +58 -9
- package/dist/{types-cU43dEmH.d.ts → types-BzEgiUdJ.d.ts} +58 -9
- package/dist/{useGesture-BnY65PlQ.d.ts → useGesture-BRLgiNOC.d.ts} +6 -4
- package/dist/{useGesture-DxtXdz-K.d.mts → useGesture-C0GBS7d2.d.mts} +6 -4
- package/llms.txt +8 -4
- package/package.json +1 -1
- package/src/__type-tests__/motion-value.test-d.ts +39 -0
- package/src/config/MotionConfig.tsx +55 -9
- package/src/config/MotionConfigContext.ts +21 -1
- package/src/config/index.ts +7 -1
- package/src/config/namedTransitions.ts +80 -0
- package/src/gestureLayer/useGestureLayer.ts +32 -8
- package/src/index.ts +20 -2
- package/src/motion/createMotionComponent.tsx +36 -6
- package/src/transitions/cubicBezier.ts +126 -0
- package/src/transitions/index.ts +1 -0
- package/src/types.ts +63 -8
- package/src/values/useAnimation.ts +12 -6
- package/src/values/useBooleanSpring.ts +5 -3
- package/src/values/useGesture.ts +25 -7
- package/src/values/useMotionValue.ts +11 -0
- package/src/values/useScroll.ts +8 -1
- package/src/values/useSpring.ts +46 -9
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ All notable changes to `@rootnative/inertia` are documented here. The format fol
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Named transition registry** — `<MotionConfig transitions={{ name: TransitionConfig }}>` registers named transitions for the subtree; the name is accepted everywhere a `TransitionConfig` is: the `transition` prop (top-level, per-property, per gesture layer), the `layout` prop, and `useAnimation` / `useSpring` / `useBooleanSpring` / `useGesture` / `useGestureLayer`. Names resolve at the nearest provider; nested providers merge with child-overrides-per-name; unknown names warn in dev and fall back to the default spring. No presets ship — names are consumer vocabulary. New exports: `useNamedTransitions()`, `resolveNamedTransition()`, and the `TransitionName` / `TransitionInput` / `NamedTransitions` / `RegisteredTransitions` types (`RegisteredTransitions` is the augmentation point for compile-time-typed names).
|
|
10
|
+
|
|
11
|
+
- **`cubicBezier()` easing helper** — builds a `timing.easing` value from cubic-bezier control points as four numbers, as a W3C CSS `cubic-bezier(x1, y1, x2, y2)` string, or as a CSS keyword (`'linear'` / `'ease'` / `'ease-in'` / `'ease-out'` / `'ease-in-out'`). Makes CSS-format design-token easings directly consumable (pair with the named-transition registry). Invalid input throws: `x1` / `x2` must be finite and within `[0, 1]`; `step-*` keywords and the CSS `linear(...)` function are unsupported. The `EasingFunction` / `EasingFunctionFactory` / `EasingInput` types are now exported from the root barrel.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- **Nested `<MotionConfig>` now inherits `reducedMotion`** from its ancestor when the prop is omitted (previously an inner provider silently reset the subtree to the `'user'` default). A transitions-only inner provider no longer clobbers an outer `reducedMotion="never"` / `"always"`.
|
|
16
|
+
|
|
7
17
|
## [0.0.0-alpha.0]
|
|
8
18
|
|
|
9
19
|
Initial alpha publish. The full v0.1 surface is in place; APIs are still subject to change before `0.1.0`.
|
package/README.md
CHANGED
|
@@ -126,6 +126,8 @@ Full docs, every primitive's example screen, and an `llms-full.txt` reference li
|
|
|
126
126
|
- [llms.txt](https://rootnative.github.io/inertia/llms.txt) — concise overview
|
|
127
127
|
- [llms-full.txt](https://rootnative.github.io/inertia/llms-full.txt) — full API reference
|
|
128
128
|
|
|
129
|
+
AI agents: this package ships its own copy of the reference — read `node_modules/@rootnative/inertia/llms.txt` for the full API, no network needed.
|
|
130
|
+
|
|
129
131
|
## License
|
|
130
132
|
|
|
131
133
|
[MIT](./LICENSE) © RootNative
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnimatedStyle } from 'react-native-reanimated';
|
|
2
|
-
import { U as UseGestureHandlers } from '../useGesture-
|
|
3
|
-
import { T as
|
|
2
|
+
import { U as UseGestureHandlers } from '../useGesture-C0GBS7d2.mjs';
|
|
3
|
+
import { T as TransitionInput, n as GestureLayerTransitions } from '../types-BzEgiUdJ.mjs';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'react-native';
|
|
6
6
|
|
|
@@ -49,10 +49,11 @@ interface UseGestureLayerOptions {
|
|
|
49
49
|
/**
|
|
50
50
|
* Transition forwarded to the underlying `useGesture` hook. Either a single
|
|
51
51
|
* `TransitionConfig` for every gesture layer, or a `GestureLayerTransitions`
|
|
52
|
-
* map for per-layer fades.
|
|
53
|
-
*
|
|
52
|
+
* map for per-layer fades. A `TransitionName` registered on the nearest
|
|
53
|
+
* `<MotionConfig transitions>` is accepted in both positions. Reduced
|
|
54
|
+
* motion collapses every transition to `no-animation`.
|
|
54
55
|
*/
|
|
55
|
-
transition?:
|
|
56
|
+
transition?: TransitionInput | GestureLayerTransitions;
|
|
56
57
|
}
|
|
57
58
|
interface UseGestureLayerResult {
|
|
58
59
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnimatedStyle } from 'react-native-reanimated';
|
|
2
|
-
import { U as UseGestureHandlers } from '../useGesture-
|
|
3
|
-
import { T as
|
|
2
|
+
import { U as UseGestureHandlers } from '../useGesture-BRLgiNOC.js';
|
|
3
|
+
import { T as TransitionInput, n as GestureLayerTransitions } from '../types-BzEgiUdJ.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'react-native';
|
|
6
6
|
|
|
@@ -49,10 +49,11 @@ interface UseGestureLayerOptions {
|
|
|
49
49
|
/**
|
|
50
50
|
* Transition forwarded to the underlying `useGesture` hook. Either a single
|
|
51
51
|
* `TransitionConfig` for every gesture layer, or a `GestureLayerTransitions`
|
|
52
|
-
* map for per-layer fades.
|
|
53
|
-
*
|
|
52
|
+
* map for per-layer fades. A `TransitionName` registered on the nearest
|
|
53
|
+
* `<MotionConfig transitions>` is accepted in both positions. Reduced
|
|
54
|
+
* motion collapses every transition to `no-animation`.
|
|
54
55
|
*/
|
|
55
|
-
transition?:
|
|
56
|
+
transition?: TransitionInput | GestureLayerTransitions;
|
|
56
57
|
}
|
|
57
58
|
interface UseGestureLayerResult {
|
|
58
59
|
/**
|
|
@@ -6,8 +6,31 @@ var reactNativeWorklets = require('react-native-worklets');
|
|
|
6
6
|
var reactNative = require('react-native');
|
|
7
7
|
|
|
8
8
|
// src/gestureLayer/useGestureLayer.ts
|
|
9
|
+
|
|
10
|
+
// src/transitions/sig.ts
|
|
11
|
+
function stableSig(value) {
|
|
12
|
+
if (value === void 0) return "";
|
|
13
|
+
try {
|
|
14
|
+
return stableStringify(value);
|
|
15
|
+
} catch {
|
|
16
|
+
return String(value);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function stableStringify(v) {
|
|
20
|
+
if (v === null || typeof v !== "object") {
|
|
21
|
+
if (typeof v === "function" || v === void 0) return "null";
|
|
22
|
+
return JSON.stringify(v);
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(v)) {
|
|
25
|
+
return "[" + v.map(stableStringify).join(",") + "]";
|
|
26
|
+
}
|
|
27
|
+
const obj = v;
|
|
28
|
+
const keys = Object.keys(obj).sort();
|
|
29
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
|
|
30
|
+
}
|
|
9
31
|
var DEFAULT_MOTION_CONFIG = {
|
|
10
|
-
reducedMotion: "user"
|
|
32
|
+
reducedMotion: "user",
|
|
33
|
+
transitions: {}
|
|
11
34
|
};
|
|
12
35
|
var MotionConfigContext = react.createContext(
|
|
13
36
|
DEFAULT_MOTION_CONFIG
|
|
@@ -15,6 +38,9 @@ var MotionConfigContext = react.createContext(
|
|
|
15
38
|
function useMotionConfig() {
|
|
16
39
|
return react.useContext(MotionConfigContext);
|
|
17
40
|
}
|
|
41
|
+
function useNamedTransitions() {
|
|
42
|
+
return useMotionConfig().transitions;
|
|
43
|
+
}
|
|
18
44
|
function useShouldReduceMotion() {
|
|
19
45
|
const { reducedMotion } = useMotionConfig();
|
|
20
46
|
const osReduced = reactNativeReanimated.useReducedMotion();
|
|
@@ -22,6 +48,59 @@ function useShouldReduceMotion() {
|
|
|
22
48
|
if (reducedMotion === "always") return true;
|
|
23
49
|
return osReduced;
|
|
24
50
|
}
|
|
51
|
+
|
|
52
|
+
// src/transitions/keys.ts
|
|
53
|
+
var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
54
|
+
"type",
|
|
55
|
+
"tension",
|
|
56
|
+
"friction",
|
|
57
|
+
"mass",
|
|
58
|
+
"velocity",
|
|
59
|
+
"restSpeedThreshold",
|
|
60
|
+
"restDisplacementThreshold",
|
|
61
|
+
"duration",
|
|
62
|
+
"easing",
|
|
63
|
+
"delay",
|
|
64
|
+
"repeat",
|
|
65
|
+
"deceleration",
|
|
66
|
+
"clamp"
|
|
67
|
+
]);
|
|
68
|
+
function isTopLevelTransition(t) {
|
|
69
|
+
if (t === null || typeof t !== "object") return false;
|
|
70
|
+
const keys = Object.keys(t);
|
|
71
|
+
if (keys.length === 0) return false;
|
|
72
|
+
return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/config/namedTransitions.ts
|
|
76
|
+
var UNKNOWN_NAME_FALLBACK = { type: "spring" };
|
|
77
|
+
function lookupNamedTransition(name, registry) {
|
|
78
|
+
const cfg = registry[name];
|
|
79
|
+
if (cfg) return cfg;
|
|
80
|
+
if (__DEV__) {
|
|
81
|
+
console.warn(
|
|
82
|
+
`[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return UNKNOWN_NAME_FALLBACK;
|
|
86
|
+
}
|
|
87
|
+
function resolveNamedTransitionProp(transition, registry) {
|
|
88
|
+
if (transition === void 0) return void 0;
|
|
89
|
+
if (typeof transition === "string") {
|
|
90
|
+
return lookupNamedTransition(transition, registry);
|
|
91
|
+
}
|
|
92
|
+
if (isTopLevelTransition(transition)) return transition;
|
|
93
|
+
const map = transition;
|
|
94
|
+
let out = null;
|
|
95
|
+
for (const key in map) {
|
|
96
|
+
const value = map[key];
|
|
97
|
+
if (typeof value === "string") {
|
|
98
|
+
if (out === null) out = { ...map };
|
|
99
|
+
out[key] = lookupNamedTransition(value, registry);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return out ?? transition;
|
|
103
|
+
}
|
|
25
104
|
function ensureWorkletEasing(easing) {
|
|
26
105
|
if (!easing) return void 0;
|
|
27
106
|
const fn = isEasingFactory(easing) ? easing.factory() : easing;
|
|
@@ -117,29 +196,6 @@ function delayOf(cfg) {
|
|
|
117
196
|
if (cfg.type === "no-animation") return void 0;
|
|
118
197
|
return cfg.delay;
|
|
119
198
|
}
|
|
120
|
-
|
|
121
|
-
// src/transitions/keys.ts
|
|
122
|
-
var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
123
|
-
"type",
|
|
124
|
-
"tension",
|
|
125
|
-
"friction",
|
|
126
|
-
"mass",
|
|
127
|
-
"velocity",
|
|
128
|
-
"restSpeedThreshold",
|
|
129
|
-
"restDisplacementThreshold",
|
|
130
|
-
"duration",
|
|
131
|
-
"easing",
|
|
132
|
-
"delay",
|
|
133
|
-
"repeat",
|
|
134
|
-
"deceleration",
|
|
135
|
-
"clamp"
|
|
136
|
-
]);
|
|
137
|
-
function isTopLevelTransition(t) {
|
|
138
|
-
if (t === null || typeof t !== "object") return false;
|
|
139
|
-
const keys = Object.keys(t);
|
|
140
|
-
if (keys.length === 0) return false;
|
|
141
|
-
return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
|
|
142
|
-
}
|
|
143
199
|
var modality = "keyboard";
|
|
144
200
|
var installed = false;
|
|
145
201
|
function setKeyboard() {
|
|
@@ -171,9 +227,10 @@ function useGesture(transition) {
|
|
|
171
227
|
const focusVisible = reactNativeReanimated.useSharedValue(0);
|
|
172
228
|
const hovered = reactNativeReanimated.useSharedValue(0);
|
|
173
229
|
const shouldReduceMotion = useShouldReduceMotion();
|
|
230
|
+
const resolved = resolveNamedTransitionProp(transition, useNamedTransitions());
|
|
174
231
|
const setLayer = react.useCallback(
|
|
175
232
|
(sv, layer, target) => {
|
|
176
|
-
const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer,
|
|
233
|
+
const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
|
|
177
234
|
sv.value = resolveTransition(cfg, target);
|
|
178
235
|
},
|
|
179
236
|
// The transition is intentionally read on every call rather than cooked
|
|
@@ -212,15 +269,20 @@ function layerTransition(layer, transition) {
|
|
|
212
269
|
|
|
213
270
|
// src/gestureLayer/useGestureLayer.ts
|
|
214
271
|
function useGestureLayer(states, options = {}) {
|
|
215
|
-
const { disabled: isDisabled = false, transition } = options;
|
|
272
|
+
const { disabled: isDisabled = false, transition: transitionInput } = options;
|
|
216
273
|
const shouldReduceMotion = useShouldReduceMotion();
|
|
274
|
+
const transition = resolveNamedTransitionProp(
|
|
275
|
+
transitionInput,
|
|
276
|
+
useNamedTransitions()
|
|
277
|
+
);
|
|
217
278
|
const gesture = useGesture(transition);
|
|
218
279
|
const disabledProgress = reactNativeReanimated.useSharedValue(0);
|
|
280
|
+
const transitionSig = stableSig(transition);
|
|
219
281
|
react.useEffect(() => {
|
|
220
282
|
const target = isDisabled ? 1 : 0;
|
|
221
283
|
const cfg = shouldReduceMotion ? { type: "no-animation" } : disabledTransition(transition) ?? { type: "spring" };
|
|
222
284
|
disabledProgress.value = resolveTransition(cfg, target);
|
|
223
|
-
}, [isDisabled, shouldReduceMotion,
|
|
285
|
+
}, [isDisabled, shouldReduceMotion, transitionSig, disabledProgress]);
|
|
224
286
|
const meta = react.useMemo(() => {
|
|
225
287
|
const layers = {
|
|
226
288
|
rest: states.rest,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/MotionConfigContext.ts","../../src/transitions/easing.ts","../../src/transitions/spring.ts","../../src/transitions/resolve.ts","../../src/transitions/keys.ts","../../src/gestures/focusVisibility.ts","../../src/values/useGesture.ts","../../src/gestureLayer/useGestureLayer.ts"],"names":["createContext","useContext","useReducedMotion","isWorkletFunction","withSpring","withTiming","Easing","withDecay","withRepeat","withDelay","Platform","useSharedValue","useCallback","useMemo","useEffect","useAnimatedStyle","interpolateColor"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext } from 'react'\nimport { useReducedMotion } from 'react-native-reanimated'\n\n/**\n * How descendant Motion primitives should treat reduced-motion preferences.\n *\n * - `'user'` (default): defer to the OS accessibility setting via\n * Reanimated's `useReducedMotion()`. This is the only value that respects\n * user choice and is the right default for app-level wrappers.\n * - `'never'`: animate regardless of OS setting. Use sparingly — e.g. for\n * onboarding transitions you've decided are essential.\n * - `'always'`: never animate, regardless of OS setting. Useful for tests\n * and snapshots.\n */\nexport type ReducedMotion = 'user' | 'never' | 'always'\n\nexport interface MotionConfigValue {\n reducedMotion: ReducedMotion\n}\n\n/**\n * Default config used when a Motion primitive is rendered without a\n * `<MotionConfig>` ancestor. `'user'` means respect the OS setting.\n */\nexport const DEFAULT_MOTION_CONFIG: MotionConfigValue = {\n reducedMotion: 'user',\n}\n\nexport const MotionConfigContext = createContext<MotionConfigValue>(\n DEFAULT_MOTION_CONFIG,\n)\n\n/**\n * Read the active `<MotionConfig>` from a descendant. Returns the default\n * (`'user'`) when no provider is present.\n */\nexport function useMotionConfig(): MotionConfigValue {\n return useContext(MotionConfigContext)\n}\n\n/**\n * Resolve the active reduced-motion mode to a boolean. `'user'` consults\n * Reanimated's OS-backed hook; `'always'` / `'never'` shortcut. Motion\n * primitives call this to decide whether to swap transitions for\n * `no-animation`.\n */\nexport function useShouldReduceMotion(): boolean {\n const { reducedMotion } = useMotionConfig()\n const osReduced = useReducedMotion()\n if (reducedMotion === 'never') return false\n if (reducedMotion === 'always') return true\n return osReduced\n}\n","// `isWorkletFunction` lives in `react-native-worklets` (the Reanimated 4 peer\n// dep); Reanimated's own re-export is deprecated.\nimport { isWorkletFunction } from 'react-native-worklets'\nimport { type EasingInput } from '../types'\n\n/**\n * Reanimated 3.9+ validates that easing functions used in nested-transition\n * contexts (variants, sequences, per-property maps) are worklets, and crashes\n * with `[Reanimated] The easing function is not a worklet` otherwise. The\n * library accepts plain functions on the public surface; this helper wraps\n * them so consumers don't have to think about the worklet boundary.\n *\n * If the input is already a worklet (has been processed by the worklets babel\n * plugin), it's returned as-is. Otherwise it's wrapped in a function whose\n * body declares the `'worklet'` directive — when our source is processed by\n * the consumer's worklets babel plugin (the default Expo/RN setup), the\n * wrapper becomes a real worklet that captures the user fn via closure.\n *\n * Reanimated 4 changed `Easing.bezier(...)` to return an\n * `EasingFunctionFactory` (`{ factory: () => EasingFunction }`) rather than\n * the function itself. The helper accepts both shapes — `EasingFunction` and\n * `EasingFunctionFactory` — and unwraps the factory automatically so\n * consumers don't have to call `.factory()` manually.\n *\n * The user fn must be pure: no JS-thread captured refs, no shared mutable\n * state, no calls to non-worklet APIs.\n */\nexport function ensureWorkletEasing(\n easing: EasingInput | undefined,\n): ((t: number) => number) | undefined {\n if (!easing) return undefined\n // Reanimated 4 `EasingFunctionFactory` — unwrap via `.factory()` before\n // checking worklet status, so the wrapped fn (not the factory wrapper)\n // ends up in the transition config.\n const fn = isEasingFactory(easing) ? easing.factory() : easing\n if (isWorkletFunction(fn)) return fn\n const wrapped = (t: number) => {\n 'worklet'\n return fn(t)\n }\n return wrapped\n}\n\nfunction isEasingFactory(\n value: EasingInput,\n): value is { factory: () => (t: number) => number } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'factory' in value &&\n typeof (value as { factory: unknown }).factory === 'function'\n )\n}\n","import { type SpringTransition } from '../types'\n\n/**\n * Default spring physics, expressed in react-spring vocabulary.\n *\n * `tension: 170` / `friction: 26` / `mass: 1` was picked over Reanimated's\n * raw `stiffness: 100` / `damping: 10` default because the raw default\n * overshoots noticeably for the small (~100px) translates that dominate\n * UI work — buttons, sheets, popovers. These numbers settle in ~350ms with\n * a single, almost-imperceptible overshoot, which matches the perceptual\n * target the rest of the library is tuned against.\n */\nexport const DEFAULT_SPRING: Required<\n Pick<SpringTransition, 'tension' | 'friction' | 'mass'>\n> = {\n tension: 170,\n friction: 26,\n mass: 1,\n}\n\n/**\n * Convert public react-spring vocabulary (`tension` / `friction` / `mass`)\n * to Reanimated's raw `stiffness` / `damping` / `mass`. This is the single\n * place the mapping lives; resolvers, value hooks, and any future surface\n * that needs a Reanimated spring config import from here.\n *\n * The mapping is identity (tension ≡ stiffness, friction ≡ damping) — the\n * names differ but the underlying physics constants are the same. We don't\n * surface the raw names publicly because the react-spring vocabulary is\n * what designers and prior-art consumers expect.\n */\nexport function springToReanimated(t: SpringTransition) {\n 'worklet'\n return {\n stiffness: t.tension ?? DEFAULT_SPRING.tension,\n damping: t.friction ?? DEFAULT_SPRING.friction,\n mass: t.mass ?? DEFAULT_SPRING.mass,\n velocity: t.velocity,\n restSpeedThreshold: t.restSpeedThreshold,\n restDisplacementThreshold: t.restDisplacementThreshold,\n }\n}\n","import {\n Easing,\n withDecay,\n withDelay,\n withRepeat,\n withSpring,\n withTiming,\n} from 'react-native-reanimated'\nimport { ensureWorkletEasing } from './easing'\nimport { springToReanimated } from './spring'\nimport {\n type DecayTransition,\n type RepeatConfig,\n type SpringTransition,\n type TimingTransition,\n type TransitionConfig,\n} from '../types'\n\n/**\n * UI-thread callback Reanimated invokes when an animation settles. Must be a\n * worklet — callers either author one with `'worklet'` or build one via\n * `runOnJS(...)` to bridge to JS-thread code.\n */\nexport type AnimationCallback = (\n finished?: boolean,\n current?: number | string,\n) => void\n\n/**\n * Per-step callback factory. Resolvers call this with the step's phase and\n * sequence index (or `undefined` for non-sequence animations) and attach the\n * resulting callback to the underlying `withSpring` / `withTiming` /\n * `withDecay` call.\n */\nexport type CallbackFactory = (\n phase: 'step' | 'animation',\n step: number | undefined,\n) => AnimationCallback | undefined\n\nconst DEFAULT_TIMING_DURATION = 250\n\nfunction buildSpring(\n cfg: SpringTransition,\n toValue: number | string,\n cb?: AnimationCallback,\n) {\n return withSpring(toValue as number, springToReanimated(cfg), cb as never)\n}\n\nfunction buildTiming(\n cfg: TimingTransition,\n toValue: number | string,\n cb?: AnimationCallback,\n) {\n return withTiming(\n toValue as number,\n {\n duration: cfg.duration ?? DEFAULT_TIMING_DURATION,\n easing: ensureWorkletEasing(cfg.easing) ?? Easing.inOut(Easing.ease),\n },\n cb as never,\n )\n}\n\nfunction buildDecay(cfg: DecayTransition, cb?: AnimationCallback) {\n return withDecay(\n {\n velocity: cfg.velocity ?? 0,\n deceleration: cfg.deceleration,\n clamp: cfg.clamp,\n },\n cb as never,\n )\n}\n\n/**\n * Build a single-step animation (no repeat / no delay / no sequence) for a\n * given config + target. Pulled out so sequence steps can compose without\n * recursing into repeat/delay handling per step. The callback is forwarded\n * to Reanimated; for `no-animation` the callback is fired synchronously\n * since there's nothing to wait for.\n */\nfunction buildOne(\n cfg: TransitionConfig,\n toValue: number | string,\n cb?: AnimationCallback,\n): unknown {\n if (cfg.type === 'no-animation') {\n if (cb) cb(true, toValue)\n return toValue\n }\n if (cfg.type === 'decay') return buildDecay(cfg, cb)\n if (cfg.type === 'timing') return buildTiming(cfg, toValue, cb)\n return buildSpring(cfg as SpringTransition, toValue, cb)\n}\n\n/**\n * Wrap an animation in `withRepeat` per the unified `repeat` shape:\n * - `number` → finite count, alternating direction\n * - `'infinite'` → endless, alternating direction\n * - `{ count, alternate }`→ explicit; `alternate` defaults to `true`\n */\nexport function applyRepeat(\n animation: unknown,\n repeat: RepeatConfig | undefined,\n) {\n if (repeat === undefined) return animation\n if (repeat === 'infinite') {\n return withRepeat(animation as never, -1, true)\n }\n if (typeof repeat === 'number') {\n return withRepeat(animation as never, repeat, true)\n }\n const count = repeat.count === 'infinite' ? -1 : repeat.count\n const alternate = repeat.alternate ?? true\n return withRepeat(animation as never, count, alternate)\n}\n\nfunction applyDelay(animation: unknown, delay: number | undefined) {\n if (!delay || delay <= 0) return animation\n return withDelay(delay, animation as never)\n}\n\n/**\n * Build a Reanimated animation for a single property. Runs on the JS thread\n * once per change and produces a baked `withSpring` / `withTiming` /\n * `withDecay` (optionally wrapped in `withDelay` / `withRepeat`) call. The\n * worklet body only consumes the result.\n *\n * `callback`, when provided, fires once when the underlying single-shot\n * animation settles. Repeat-wrapped animations forward the callback to\n * `withRepeat`, so it fires once per iteration as Reanimated does.\n */\nexport function resolveTransition(\n config: TransitionConfig | undefined,\n toValue: number | string,\n callback?: AnimationCallback,\n): unknown {\n const cfg = config ?? ({ type: 'spring' } as SpringTransition)\n const base = buildOne(cfg, toValue, callback)\n const repeated = applyRepeat(base, repeatOf(cfg))\n return applyDelay(repeated, delayOf(cfg))\n}\n\nexport function repeatOf(cfg: TransitionConfig): RepeatConfig | undefined {\n if (cfg.type === 'no-animation' || cfg.type === 'decay') return undefined\n return cfg.repeat\n}\n\n/**\n * Return `cfg` minus its `repeat` field. Used when peeling top-level repeat\n * off a base transition before passing it down to per-sequence-step\n * resolution — the sequence as a whole is what should repeat, not each step.\n */\nexport function stripRepeat(\n cfg: TransitionConfig | undefined,\n): TransitionConfig | undefined {\n if (!cfg) return cfg\n if (cfg.type === 'no-animation' || cfg.type === 'decay') return cfg\n if (cfg.repeat === undefined) return cfg\n const next = { ...cfg }\n delete next.repeat\n return next\n}\n\nfunction delayOf(cfg: TransitionConfig): number | undefined {\n if (cfg.type === 'no-animation') return undefined\n return cfg.delay\n}\n","import { type TransitionConfig } from '../types'\n\n/**\n * Field names that may appear on a `TransitionConfig` (spring / timing /\n * decay / no-animation). Used as a structural discriminator: if every key on\n * an object is in this set, the object is treated as a top-level transition;\n * otherwise it's a per-property / per-layer transition map.\n *\n * Adding a new field to `TransitionConfig` requires adding the name here.\n */\nexport const TRANSITION_CONFIG_KEYS = new Set([\n 'type',\n 'tension',\n 'friction',\n 'mass',\n 'velocity',\n 'restSpeedThreshold',\n 'restDisplacementThreshold',\n 'duration',\n 'easing',\n 'delay',\n 'repeat',\n 'deceleration',\n 'clamp',\n])\n\nexport function isTopLevelTransition(t: unknown): t is TransitionConfig {\n if (t === null || typeof t !== 'object') return false\n const keys = Object.keys(t as object)\n if (keys.length === 0) return false\n return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k))\n}\n","import { Platform } from 'react-native'\n\n/**\n * Input-modality tracker for the `focusVisible` gesture sub-state.\n *\n * Implements the W3C `:focus-visible` heuristic: a focus event counts as\n * \"visible\" only when the most recent user input was keyboard-driven. Mouse,\n * pointer, and touch events flip the modality to `'pointer'`; keyboard events\n * flip it back to `'keyboard'`.\n *\n * On native platforms there is no pointer-vs-keyboard distinction — focus\n * arrives via D-pad, screen reader, or hardware keyboard, all of which are\n * keyboard-equivalent — so `isFocusVisible()` is unconditionally `true`.\n *\n * The web listeners attach lazily on first call (capture phase, so they run\n * before the focus event reaches the focused element) and stay installed for\n * the lifetime of the document. They are passive and idle-cheap; the cost is\n * one boolean read per `onFocus` dispatch.\n */\n\ntype InputModality = 'keyboard' | 'pointer'\n\n// Default to `'keyboard'` so a programmatic / autofocus that happens before\n// any user input still draws a focus ring — matches the W3C polyfill default.\nlet modality: InputModality = 'keyboard'\nlet installed = false\n\nfunction setKeyboard() {\n modality = 'keyboard'\n}\n\nfunction setPointer() {\n modality = 'pointer'\n}\n\nfunction ensureInstalled(): void {\n if (installed) return\n if (Platform.OS !== 'web') return\n if (typeof document === 'undefined') return\n document.addEventListener('keydown', setKeyboard, true)\n document.addEventListener('mousedown', setPointer, true)\n document.addEventListener('pointerdown', setPointer, true)\n document.addEventListener('touchstart', setPointer, true)\n installed = true\n}\n\n/**\n * `true` if the next `onFocus` should be treated as \"focus-visible\" (keyboard\n * focus). On native, always `true`. On web, reflects the most recent user\n * input modality.\n */\nexport function isFocusVisible(): boolean {\n if (Platform.OS !== 'web') return true\n ensureInstalled()\n return modality === 'keyboard'\n}\n\n/** @internal — test-only hook to reset module state between cases. */\nexport function __resetFocusVisibilityForTests(next: InputModality): void {\n modality = next\n}\n","import { useCallback, useMemo } from 'react'\nimport { useSharedValue, type SharedValue } from 'react-native-reanimated'\nimport { useShouldReduceMotion } from '../config'\nimport { isFocusVisible } from '../gestures'\nimport { isTopLevelTransition, resolveTransition } from '../transitions'\nimport { type GestureLayerTransitions, type TransitionConfig } from '../types'\n\ntype LayerName = 'pressed' | 'focused' | 'focusVisible' | 'hovered'\n\n/**\n * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the\n * shared values returned alongside.\n *\n * Hover handlers use `Pressable`'s own `onHoverIn` / `onHoverOut` names (web\n * only — no-ops on native). `onFocus` consults `isFocusVisible()` before\n * raising the keyboard-only `focusVisible` layer; `focused` always raises.\n */\nexport interface UseGestureHandlers {\n onPressIn: () => void\n onPressOut: () => void\n onHoverIn: () => void\n onHoverOut: () => void\n onFocus: () => void\n onBlur: () => void\n}\n\nexport interface UseGestureResult {\n /** 0↔1 progress for the pressed layer. */\n pressed: SharedValue<number>\n /** 0↔1 progress for the focused layer (any focus modality). */\n focused: SharedValue<number>\n /** 0↔1 progress for the focusVisible layer (keyboard focus only). */\n focusVisible: SharedValue<number>\n /** 0↔1 progress for the hovered layer (web only — stays at 0 on native). */\n hovered: SharedValue<number>\n /** Handlers to spread on the receiving `Pressable`. */\n handlers: UseGestureHandlers\n}\n\n/**\n * Build a gesture-layer controller. The hook-form of the `gesture` prop —\n * reach for it when you need to drive multiple animated views from the same\n * gesture state (a focus ring + state-layer halo + content tint all on one\n * Pressable), which the prop-form's \"animate the receiver's own style\" model\n * can't express.\n *\n * Returns four 0↔1 shared values (one per layer) and a handler bag to spread\n * on a `Pressable`. The shared values are stable across renders — feed them\n * into any number of `useAnimatedStyle` blocks anywhere in the tree.\n *\n * Transitions follow the same shape as the `gesture` prop's accompanying\n * `transition`: pass a single `TransitionConfig` to use for every layer, or a\n * `GestureLayerTransitions` map to give each layer its own. Layers without an\n * explicit transition fall back to the library default spring.\n *\n * Reduced motion (via `<MotionConfig reducedMotion>`) collapses every\n * transition to `no-animation` so state changes snap instead of interpolating\n * — same behaviour the gesture prop applies.\n *\n * @example\n * ```tsx\n * import { useAnimatedStyle } from 'react-native-reanimated'\n * import { useGesture } from '@rootnative/inertia'\n *\n * function Card() {\n * const { pressed, focused, hovered, handlers } = useGesture({\n * pressed: { type: 'timing', duration: 100 },\n * hovered: { type: 'timing', duration: 150 },\n * focused: { type: 'timing', duration: 200 },\n * })\n *\n * const ringStyle = useAnimatedStyle(() => ({ opacity: focused.value }))\n * const haloStyle = useAnimatedStyle(() => ({\n * opacity: Math.max(\n * hovered.value * 0.08,\n * focused.value * 0.10,\n * pressed.value * 0.10,\n * ),\n * }))\n *\n * return (\n * <Pressable {...handlers}>\n * <Animated.View style={ringStyle} />\n * <Animated.View style={haloStyle} />\n * </Pressable>\n * )\n * }\n * ```\n */\nexport function useGesture(\n transition?: TransitionConfig | GestureLayerTransitions,\n): UseGestureResult {\n const pressed = useSharedValue(0)\n const focused = useSharedValue(0)\n const focusVisible = useSharedValue(0)\n const hovered = useSharedValue(0)\n const shouldReduceMotion = useShouldReduceMotion()\n\n const setLayer = useCallback(\n (sv: SharedValue<number>, layer: LayerName, target: 0 | 1) => {\n const cfg = shouldReduceMotion\n ? ({ type: 'no-animation' } as const)\n : (layerTransition(layer, transition) ?? ({ type: 'spring' } as const))\n sv.value = resolveTransition(cfg, target) as never\n },\n // The transition is intentionally read on every call rather than cooked\n // into the dep array — a fresh literal each render would otherwise\n // rebuild the handler bag and break composing consumers that key off\n // handler identity. `transition` is read inside the callback closure;\n // shared values are stable so the only dep that matters is the reduce-\n // motion flag.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [shouldReduceMotion],\n )\n\n const handlers = useMemo<UseGestureHandlers>(\n () => ({\n onPressIn: () => setLayer(pressed, 'pressed', 1),\n onPressOut: () => setLayer(pressed, 'pressed', 0),\n onHoverIn: () => setLayer(hovered, 'hovered', 1),\n onHoverOut: () => setLayer(hovered, 'hovered', 0),\n onFocus: () => {\n setLayer(focused, 'focused', 1)\n if (isFocusVisible()) setLayer(focusVisible, 'focusVisible', 1)\n },\n onBlur: () => {\n setLayer(focused, 'focused', 0)\n setLayer(focusVisible, 'focusVisible', 0)\n },\n }),\n [setLayer, pressed, focused, focusVisible, hovered],\n )\n\n return { pressed, focused, focusVisible, hovered, handlers }\n}\n\nfunction layerTransition(\n layer: LayerName,\n transition: TransitionConfig | GestureLayerTransitions | undefined,\n): TransitionConfig | undefined {\n if (!transition) return undefined\n if (isTopLevelTransition(transition)) return transition\n return (transition as GestureLayerTransitions)[layer]\n}\n","import { useEffect, useMemo } from 'react'\nimport {\n interpolateColor,\n useAnimatedStyle,\n useSharedValue,\n type AnimatedStyle,\n} from 'react-native-reanimated'\nimport { useShouldReduceMotion } from '../config'\nimport { isTopLevelTransition, resolveTransition } from '../transitions'\nimport { useGesture, type UseGestureHandlers } from '../values/useGesture'\nimport { type GestureLayerTransitions, type TransitionConfig } from '../types'\n\n/**\n * A single gesture-layer style — a flat map of style keys to a value. Numeric\n * values participate in clamped-max composition (the \"strongest active layer\n * wins\" model used by MD3 state-layer haloes); string values are treated as\n * colors and composed via priority cascade with `interpolateColor`.\n *\n * The hook does not validate that string values are valid colors — passing\n * something like `borderStyle: 'solid'` will crash inside the worklet. Keep\n * string values to color strings.\n */\nexport type GestureLayerStyle = {\n [key: string]: number | string | undefined\n}\n\n/**\n * Per-state style maps. Every key is optional; missing layers default to\n * `rest` (or `0` / `'transparent'` if `rest` is also absent for that key).\n *\n * - `rest` — base values, applied when no other layer is active.\n * - `hovered` / `focused` / `focusVisible` / `pressed` — gesture-driven\n * states tracked via the underlying `useGesture` hook. Each owns an\n * independent 0↔1 progress that fades the layer in/out per the configured\n * transition.\n * - `disabled` — gated by the JS-side `options.disabled` flag rather than a\n * gesture. Sits at the top of the priority cascade and overrides every\n * gesture layer when active.\n */\nexport interface GestureLayerStates {\n rest?: GestureLayerStyle\n hovered?: GestureLayerStyle\n focused?: GestureLayerStyle\n focusVisible?: GestureLayerStyle\n pressed?: GestureLayerStyle\n disabled?: GestureLayerStyle\n}\n\nexport interface UseGestureLayerOptions {\n /**\n * When `true`, the `disabled` layer becomes active (or `rest` if `disabled`\n * is undefined). Animates via the top-level transition or the library\n * default spring; per-layer transitions (`GestureLayerTransitions`) do not\n * apply to `disabled`.\n */\n disabled?: boolean\n /**\n * Transition forwarded to the underlying `useGesture` hook. Either a single\n * `TransitionConfig` for every gesture layer, or a `GestureLayerTransitions`\n * map for per-layer fades. Reduced motion collapses every transition to\n * `no-animation`.\n */\n transition?: TransitionConfig | GestureLayerTransitions\n}\n\nexport interface UseGestureLayerResult {\n /**\n * Animated style produced by `useAnimatedStyle` — spread on an\n * `Animated.View` or pass through `<Motion.View style={...} />`.\n */\n style: AnimatedStyle<Record<string, unknown>>\n /** Handlers to spread on the receiving `Pressable`. */\n handlers: UseGestureHandlers\n}\n\n/**\n * A \"strongest active layer wins\" interactive-feedback primitive. Sits one\n * step above `useGesture()` — the consumer supplies the per-state target\n * values, the hook handles the four gesture progress shared values, the\n * disabled override, the worklet, and the transition.\n *\n * Composition model:\n *\n * - **Numeric keys** (opacity, scale, borderWidth, etc.) compose via\n * clamped-max with `rest` as the floor:\n * `out = max(rest, ...for each active gesture layer: lerp(rest, layer, progress))`.\n * This matches the MD3 state-layer halo pattern — multiple states active\n * simultaneously raise the value to the strongest, not the sum.\n * - **Color keys** (any string value) compose via priority cascade with\n * `interpolateColor`, lowest priority first: `hovered → focused →\n * focusVisible → pressed`. Clamped-max doesn't apply to colors; this\n * matches the cascade used by the declarative `gesture` prop.\n * - **Disabled** sits at the top of the cascade for both numeric and color\n * keys — when active, it lerps the composed value toward the `disabled`\n * target.\n *\n * Reach for this when you want MD3 / iOS-translucent state-layer overlays\n * without rewriting the worklet by hand for every consumer; reach for plain\n * `useGesture()` when you need a composition model this hook doesn't\n * express (additive, multiply, per-key custom blends).\n *\n * @example MD3 state-layer halo\n * ```tsx\n * import { useGestureLayer } from '@rootnative/inertia/gesture-layer'\n * import Animated from 'react-native-reanimated'\n * import { Pressable } from 'react-native'\n *\n * function SwitchHalo({ disabled }: { disabled?: boolean }) {\n * const { style, handlers } = useGestureLayer(\n * {\n * rest: { opacity: 0, backgroundColor: 'transparent' },\n * hovered: { opacity: 0.08, backgroundColor: '#000' },\n * focused: { opacity: 0.10, backgroundColor: '#000' },\n * pressed: { opacity: 0.12, backgroundColor: '#000' },\n * },\n * { disabled, transition: { type: 'timing', duration: 150 } },\n * )\n *\n * return (\n * <Pressable {...handlers}>\n * <Animated.View style={style} />\n * </Pressable>\n * )\n * }\n * ```\n */\nexport function useGestureLayer(\n states: GestureLayerStates,\n options: UseGestureLayerOptions = {},\n): UseGestureLayerResult {\n const { disabled: isDisabled = false, transition } = options\n const shouldReduceMotion = useShouldReduceMotion()\n const gesture = useGesture(transition)\n const disabledProgress = useSharedValue(0)\n\n useEffect(() => {\n const target = isDisabled ? 1 : 0\n const cfg = shouldReduceMotion\n ? ({ type: 'no-animation' } as const)\n : (disabledTransition(transition) ?? ({ type: 'spring' } as const))\n disabledProgress.value = resolveTransition(cfg, target) as never\n }, [isDisabled, shouldReduceMotion, transition, disabledProgress])\n\n // JS-thread precompute: union of keys across all layers, per-key type\n // (number vs color), and a rest-fallback table. The worklet body reads\n // from `meta` instead of probing each layer per frame — the type check\n // only runs when layer identities change.\n const meta = useMemo(() => {\n const layers = {\n rest: states.rest,\n hovered: states.hovered,\n focused: states.focused,\n focusVisible: states.focusVisible,\n pressed: states.pressed,\n disabled: states.disabled,\n }\n const sources = [\n layers.rest,\n layers.hovered,\n layers.focused,\n layers.focusVisible,\n layers.pressed,\n layers.disabled,\n ]\n const keySet = new Set<string>()\n for (const src of sources) {\n if (!src) continue\n for (const k in src) if (src[k] !== undefined) keySet.add(k)\n }\n const keys = Array.from(keySet)\n const types: Record<string, 'number' | 'color'> = {}\n const restValues: Record<string, number | string> = {}\n for (const k of keys) {\n let firstDefined: number | string | undefined\n for (const src of sources) {\n if (src && src[k] !== undefined) {\n firstDefined = src[k]\n break\n }\n }\n const isColor = typeof firstDefined === 'string'\n types[k] = isColor ? 'color' : 'number'\n const restRaw = layers.rest ? layers.rest[k] : undefined\n restValues[k] =\n restRaw !== undefined ? restRaw : isColor ? 'transparent' : 0\n }\n return { layers, keys, types, restValues }\n }, [\n states.rest,\n states.hovered,\n states.focused,\n states.focusVisible,\n states.pressed,\n states.disabled,\n ])\n\n const style = useAnimatedStyle(() => {\n const { layers, keys, types, restValues } = meta\n const ph = gesture.hovered.value\n const pf = gesture.focused.value\n const pfv = gesture.focusVisible.value\n const pp = gesture.pressed.value\n const pd = disabledProgress.value\n\n const hoveredLayer = layers.hovered\n const focusedLayer = layers.focused\n const focusVisibleLayer = layers.focusVisible\n const pressedLayer = layers.pressed\n const disabledLayer = layers.disabled\n\n const out: Record<string, unknown> = {}\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]!\n const isColor = types[k] === 'color'\n const rest = restValues[k]!\n\n if (isColor) {\n let v = rest as string\n if (hoveredLayer && ph > 0 && hoveredLayer[k] !== undefined) {\n v = interpolateColor(ph, [0, 1], [v, hoveredLayer[k] as string])\n }\n if (focusedLayer && pf > 0 && focusedLayer[k] !== undefined) {\n v = interpolateColor(pf, [0, 1], [v, focusedLayer[k] as string])\n }\n if (\n focusVisibleLayer &&\n pfv > 0 &&\n focusVisibleLayer[k] !== undefined\n ) {\n v = interpolateColor(pfv, [0, 1], [v, focusVisibleLayer[k] as string])\n }\n if (pressedLayer && pp > 0 && pressedLayer[k] !== undefined) {\n v = interpolateColor(pp, [0, 1], [v, pressedLayer[k] as string])\n }\n if (disabledLayer && pd > 0 && disabledLayer[k] !== undefined) {\n v = interpolateColor(pd, [0, 1], [v, disabledLayer[k] as string])\n }\n out[k] = v\n } else {\n const base = rest as number\n let m = base\n if (hoveredLayer && ph > 0 && hoveredLayer[k] !== undefined) {\n const c = base + ((hoveredLayer[k] as number) - base) * ph\n if (c > m) m = c\n }\n if (focusedLayer && pf > 0 && focusedLayer[k] !== undefined) {\n const c = base + ((focusedLayer[k] as number) - base) * pf\n if (c > m) m = c\n }\n if (\n focusVisibleLayer &&\n pfv > 0 &&\n focusVisibleLayer[k] !== undefined\n ) {\n const c = base + ((focusVisibleLayer[k] as number) - base) * pfv\n if (c > m) m = c\n }\n if (pressedLayer && pp > 0 && pressedLayer[k] !== undefined) {\n const c = base + ((pressedLayer[k] as number) - base) * pp\n if (c > m) m = c\n }\n if (disabledLayer && pd > 0 && disabledLayer[k] !== undefined) {\n m = m + ((disabledLayer[k] as number) - m) * pd\n }\n out[k] = m\n }\n }\n\n return out\n })\n\n return {\n style: style as AnimatedStyle<Record<string, unknown>>,\n handlers: gesture.handlers,\n }\n}\n\nfunction disabledTransition(\n transition: TransitionConfig | GestureLayerTransitions | undefined,\n): TransitionConfig | undefined {\n if (!transition) return undefined\n if (isTopLevelTransition(transition)) return transition\n return undefined\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/transitions/sig.ts","../../src/config/MotionConfigContext.ts","../../src/transitions/keys.ts","../../src/config/namedTransitions.ts","../../src/transitions/easing.ts","../../src/transitions/spring.ts","../../src/transitions/resolve.ts","../../src/gestures/focusVisibility.ts","../../src/values/useGesture.ts","../../src/gestureLayer/useGestureLayer.ts"],"names":["createContext","useContext","useReducedMotion","isWorkletFunction","withSpring","withTiming","Easing","withDecay","withRepeat","withDelay","Platform","useSharedValue","useCallback","useMemo","useEffect","useAnimatedStyle","interpolateColor"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Stable string signature for an arbitrary value — used as a dep-array\n * member so a fresh object literal each render doesn't re-fire an effect\n * unless something structurally changed. Functions serialize as `null`\n * (their identity isn't useful in a sig); `undefined` collapses to an empty\n * string so omitted props compare equal across renders.\n */\nexport function stableSig(value: unknown): string {\n if (value === undefined) return ''\n try {\n return stableStringify(value)\n } catch {\n return String(value)\n }\n}\n\n/**\n * JSON.stringify with keys sorted at every level so a sig is invariant under\n * property-declaration order. Functions and `undefined` both serialize as\n * `null` — we accept the latter's information loss (rare in practice) in\n * exchange for not crashing on circular function-bearing graphs.\n */\nfunction stableStringify(v: unknown): string {\n if (v === null || typeof v !== 'object') {\n if (typeof v === 'function' || v === undefined) return 'null'\n return JSON.stringify(v)\n }\n if (Array.isArray(v)) {\n return '[' + v.map(stableStringify).join(',') + ']'\n }\n const obj = v as Record<string, unknown>\n const keys = Object.keys(obj).sort()\n return (\n '{' +\n keys\n .map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k]))\n .join(',') +\n '}'\n )\n}\n","import { createContext, useContext } from 'react'\nimport { useReducedMotion } from 'react-native-reanimated'\nimport { type NamedTransitions } from '../types'\n\n/**\n * How descendant Motion primitives should treat reduced-motion preferences.\n *\n * - `'user'` (default): defer to the OS accessibility setting via\n * Reanimated's `useReducedMotion()`. This is the only value that respects\n * user choice and is the right default for app-level wrappers.\n * - `'never'`: animate regardless of OS setting. Use sparingly — e.g. for\n * onboarding transitions you've decided are essential.\n * - `'always'`: never animate, regardless of OS setting. Useful for tests\n * and snapshots.\n */\nexport type ReducedMotion = 'user' | 'never' | 'always'\n\nexport interface MotionConfigValue {\n reducedMotion: ReducedMotion\n /**\n * Named transitions registered by ancestor `<MotionConfig transitions>`\n * providers, already merged (nearest provider wins per name). Empty with no\n * provider — every name then resolves to the unknown-name fallback.\n */\n transitions: NamedTransitions\n}\n\n/**\n * Default config used when a Motion primitive is rendered without a\n * `<MotionConfig>` ancestor. `'user'` means respect the OS setting; no\n * transitions are registered.\n */\nexport const DEFAULT_MOTION_CONFIG: MotionConfigValue = {\n reducedMotion: 'user',\n transitions: {},\n}\n\nexport const MotionConfigContext = createContext<MotionConfigValue>(\n DEFAULT_MOTION_CONFIG,\n)\n\n/**\n * Read the active `<MotionConfig>` from a descendant. Returns the default\n * (`'user'`) when no provider is present.\n */\nexport function useMotionConfig(): MotionConfigValue {\n return useContext(MotionConfigContext)\n}\n\n/**\n * Resolve the active reduced-motion mode to a boolean. `'user'` consults\n * Reanimated's OS-backed hook; `'always'` / `'never'` shortcut. Motion\n * primitives call this to decide whether to swap transitions for\n * `no-animation`.\n */\n/**\n * Read the merged named-transition registry from the nearest `<MotionConfig>`\n * ancestors. This is what the Motion primitives and value-layer hooks consult\n * when a `TransitionName` string is passed where a `TransitionConfig` is\n * accepted; custom animated components (and adapter packages) use it together\n * with `resolveNamedTransition` to support names on their own surface.\n */\nexport function useNamedTransitions(): NamedTransitions {\n return useMotionConfig().transitions\n}\n\nexport function useShouldReduceMotion(): boolean {\n const { reducedMotion } = useMotionConfig()\n const osReduced = useReducedMotion()\n if (reducedMotion === 'never') return false\n if (reducedMotion === 'always') return true\n return osReduced\n}\n","import { type TransitionConfig } from '../types'\n\n/**\n * Field names that may appear on a `TransitionConfig` (spring / timing /\n * decay / no-animation). Used as a structural discriminator: if every key on\n * an object is in this set, the object is treated as a top-level transition;\n * otherwise it's a per-property / per-layer transition map.\n *\n * Adding a new field to `TransitionConfig` requires adding the name here.\n */\nexport const TRANSITION_CONFIG_KEYS = new Set([\n 'type',\n 'tension',\n 'friction',\n 'mass',\n 'velocity',\n 'restSpeedThreshold',\n 'restDisplacementThreshold',\n 'duration',\n 'easing',\n 'delay',\n 'repeat',\n 'deceleration',\n 'clamp',\n])\n\nexport function isTopLevelTransition(t: unknown): t is TransitionConfig {\n if (t === null || typeof t !== 'object') return false\n const keys = Object.keys(t as object)\n if (keys.length === 0) return false\n return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k))\n}\n","import { isTopLevelTransition } from '../transitions/keys'\nimport {\n type NamedTransitions,\n type Transition,\n type TransitionConfig,\n type TransitionInput,\n} from '../types'\n\ndeclare const __DEV__: boolean\n\n/**\n * Fallback used when a name isn't found in the registry: the library default\n * spring, matching what an omitted transition resolves to everywhere else.\n */\nconst UNKNOWN_NAME_FALLBACK: TransitionConfig = { type: 'spring' }\n\n/**\n * Look a registered transition name up in a registry. Unknown names warn in\n * dev and fall back to the library default spring — the animation still runs,\n * it just isn't the one the token intended, which is the same failure\n * softness the web platform gives an unknown CSS keyword.\n */\nexport function lookupNamedTransition(\n name: string,\n registry: NamedTransitions,\n): TransitionConfig {\n const cfg = registry[name]\n if (cfg) return cfg\n if (__DEV__) {\n console.warn(\n `[inertia] Unknown transition name \"${name}\" — falling back to the ` +\n `default spring. Register it on a provider: ` +\n `<MotionConfig transitions={{ '${name}': { ... } }}>.`,\n )\n }\n return UNKNOWN_NAME_FALLBACK\n}\n\n/**\n * Resolve a single transition input — a `TransitionConfig` passes through\n * untouched, a `TransitionName` is looked up in `registry`. This is the\n * building block adapter packages use to accept names wherever they accept a\n * config (pair it with `useNamedTransitions()` for the registry).\n */\nexport function resolveNamedTransition(\n input: TransitionInput | undefined,\n registry: NamedTransitions,\n): TransitionConfig | undefined {\n if (input === undefined) return undefined\n if (typeof input === 'string') return lookupNamedTransition(input, registry)\n return input\n}\n\n/**\n * Resolve every name inside a `transition` prop value — the top-level string\n * form, and string values on the per-property / gesture-layer map form.\n * Identity-preserving: when the input contains no names it is returned\n * unchanged, so signature- and identity-keyed memoization downstream is\n * unaffected for the config-object path.\n */\nexport function resolveNamedTransitionProp<S>(\n transition: Transition<S> | undefined,\n registry: NamedTransitions,\n): Exclude<Transition<S>, string> | undefined {\n if (transition === undefined) return undefined\n if (typeof transition === 'string') {\n return lookupNamedTransition(transition, registry)\n }\n if (isTopLevelTransition(transition)) return transition\n const map = transition as Record<string, unknown>\n let out: Record<string, unknown> | null = null\n for (const key in map) {\n const value = map[key]\n if (typeof value === 'string') {\n if (out === null) out = { ...map }\n out[key] = lookupNamedTransition(value, registry)\n }\n }\n return (out ?? transition) as Exclude<Transition<S>, string>\n}\n","// `isWorkletFunction` lives in `react-native-worklets` (the Reanimated 4 peer\n// dep); Reanimated's own re-export is deprecated.\nimport { isWorkletFunction } from 'react-native-worklets'\nimport { type EasingInput } from '../types'\n\n/**\n * Reanimated 3.9+ validates that easing functions used in nested-transition\n * contexts (variants, sequences, per-property maps) are worklets, and crashes\n * with `[Reanimated] The easing function is not a worklet` otherwise. The\n * library accepts plain functions on the public surface; this helper wraps\n * them so consumers don't have to think about the worklet boundary.\n *\n * If the input is already a worklet (has been processed by the worklets babel\n * plugin), it's returned as-is. Otherwise it's wrapped in a function whose\n * body declares the `'worklet'` directive — when our source is processed by\n * the consumer's worklets babel plugin (the default Expo/RN setup), the\n * wrapper becomes a real worklet that captures the user fn via closure.\n *\n * Reanimated 4 changed `Easing.bezier(...)` to return an\n * `EasingFunctionFactory` (`{ factory: () => EasingFunction }`) rather than\n * the function itself. The helper accepts both shapes — `EasingFunction` and\n * `EasingFunctionFactory` — and unwraps the factory automatically so\n * consumers don't have to call `.factory()` manually.\n *\n * The user fn must be pure: no JS-thread captured refs, no shared mutable\n * state, no calls to non-worklet APIs.\n */\nexport function ensureWorkletEasing(\n easing: EasingInput | undefined,\n): ((t: number) => number) | undefined {\n if (!easing) return undefined\n // Reanimated 4 `EasingFunctionFactory` — unwrap via `.factory()` before\n // checking worklet status, so the wrapped fn (not the factory wrapper)\n // ends up in the transition config.\n const fn = isEasingFactory(easing) ? easing.factory() : easing\n if (isWorkletFunction(fn)) return fn\n const wrapped = (t: number) => {\n 'worklet'\n return fn(t)\n }\n return wrapped\n}\n\nfunction isEasingFactory(\n value: EasingInput,\n): value is { factory: () => (t: number) => number } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'factory' in value &&\n typeof (value as { factory: unknown }).factory === 'function'\n )\n}\n","import { type SpringTransition } from '../types'\n\n/**\n * Default spring physics, expressed in react-spring vocabulary.\n *\n * `tension: 170` / `friction: 26` / `mass: 1` was picked over Reanimated's\n * raw `stiffness: 100` / `damping: 10` default because the raw default\n * overshoots noticeably for the small (~100px) translates that dominate\n * UI work — buttons, sheets, popovers. These numbers settle in ~350ms with\n * a single, almost-imperceptible overshoot, which matches the perceptual\n * target the rest of the library is tuned against.\n */\nexport const DEFAULT_SPRING: Required<\n Pick<SpringTransition, 'tension' | 'friction' | 'mass'>\n> = {\n tension: 170,\n friction: 26,\n mass: 1,\n}\n\n/**\n * Convert public react-spring vocabulary (`tension` / `friction` / `mass`)\n * to Reanimated's raw `stiffness` / `damping` / `mass`. This is the single\n * place the mapping lives; resolvers, value hooks, and any future surface\n * that needs a Reanimated spring config import from here.\n *\n * The mapping is identity (tension ≡ stiffness, friction ≡ damping) — the\n * names differ but the underlying physics constants are the same. We don't\n * surface the raw names publicly because the react-spring vocabulary is\n * what designers and prior-art consumers expect.\n */\nexport function springToReanimated(t: SpringTransition) {\n 'worklet'\n return {\n stiffness: t.tension ?? DEFAULT_SPRING.tension,\n damping: t.friction ?? DEFAULT_SPRING.friction,\n mass: t.mass ?? DEFAULT_SPRING.mass,\n velocity: t.velocity,\n restSpeedThreshold: t.restSpeedThreshold,\n restDisplacementThreshold: t.restDisplacementThreshold,\n }\n}\n","import {\n Easing,\n withDecay,\n withDelay,\n withRepeat,\n withSpring,\n withTiming,\n} from 'react-native-reanimated'\nimport { ensureWorkletEasing } from './easing'\nimport { springToReanimated } from './spring'\nimport {\n type DecayTransition,\n type RepeatConfig,\n type SpringTransition,\n type TimingTransition,\n type TransitionConfig,\n} from '../types'\n\n/**\n * UI-thread callback Reanimated invokes when an animation settles. Must be a\n * worklet — callers either author one with `'worklet'` or build one via\n * `runOnJS(...)` to bridge to JS-thread code.\n */\nexport type AnimationCallback = (\n finished?: boolean,\n current?: number | string,\n) => void\n\n/**\n * Per-step callback factory. Resolvers call this with the step's phase and\n * sequence index (or `undefined` for non-sequence animations) and attach the\n * resulting callback to the underlying `withSpring` / `withTiming` /\n * `withDecay` call.\n */\nexport type CallbackFactory = (\n phase: 'step' | 'animation',\n step: number | undefined,\n) => AnimationCallback | undefined\n\nconst DEFAULT_TIMING_DURATION = 250\n\nfunction buildSpring(\n cfg: SpringTransition,\n toValue: number | string,\n cb?: AnimationCallback,\n) {\n return withSpring(toValue as number, springToReanimated(cfg), cb as never)\n}\n\nfunction buildTiming(\n cfg: TimingTransition,\n toValue: number | string,\n cb?: AnimationCallback,\n) {\n return withTiming(\n toValue as number,\n {\n duration: cfg.duration ?? DEFAULT_TIMING_DURATION,\n easing: ensureWorkletEasing(cfg.easing) ?? Easing.inOut(Easing.ease),\n },\n cb as never,\n )\n}\n\nfunction buildDecay(cfg: DecayTransition, cb?: AnimationCallback) {\n return withDecay(\n {\n velocity: cfg.velocity ?? 0,\n deceleration: cfg.deceleration,\n clamp: cfg.clamp,\n },\n cb as never,\n )\n}\n\n/**\n * Build a single-step animation (no repeat / no delay / no sequence) for a\n * given config + target. Pulled out so sequence steps can compose without\n * recursing into repeat/delay handling per step. The callback is forwarded\n * to Reanimated; for `no-animation` the callback is fired synchronously\n * since there's nothing to wait for.\n */\nfunction buildOne(\n cfg: TransitionConfig,\n toValue: number | string,\n cb?: AnimationCallback,\n): unknown {\n if (cfg.type === 'no-animation') {\n if (cb) cb(true, toValue)\n return toValue\n }\n if (cfg.type === 'decay') return buildDecay(cfg, cb)\n if (cfg.type === 'timing') return buildTiming(cfg, toValue, cb)\n return buildSpring(cfg as SpringTransition, toValue, cb)\n}\n\n/**\n * Wrap an animation in `withRepeat` per the unified `repeat` shape:\n * - `number` → finite count, alternating direction\n * - `'infinite'` → endless, alternating direction\n * - `{ count, alternate }`→ explicit; `alternate` defaults to `true`\n */\nexport function applyRepeat(\n animation: unknown,\n repeat: RepeatConfig | undefined,\n) {\n if (repeat === undefined) return animation\n if (repeat === 'infinite') {\n return withRepeat(animation as never, -1, true)\n }\n if (typeof repeat === 'number') {\n return withRepeat(animation as never, repeat, true)\n }\n const count = repeat.count === 'infinite' ? -1 : repeat.count\n const alternate = repeat.alternate ?? true\n return withRepeat(animation as never, count, alternate)\n}\n\nfunction applyDelay(animation: unknown, delay: number | undefined) {\n if (!delay || delay <= 0) return animation\n return withDelay(delay, animation as never)\n}\n\n/**\n * Build a Reanimated animation for a single property. Runs on the JS thread\n * once per change and produces a baked `withSpring` / `withTiming` /\n * `withDecay` (optionally wrapped in `withDelay` / `withRepeat`) call. The\n * worklet body only consumes the result.\n *\n * `callback`, when provided, fires once when the underlying single-shot\n * animation settles. Repeat-wrapped animations forward the callback to\n * `withRepeat`, so it fires once per iteration as Reanimated does.\n */\nexport function resolveTransition(\n config: TransitionConfig | undefined,\n toValue: number | string,\n callback?: AnimationCallback,\n): unknown {\n const cfg = config ?? ({ type: 'spring' } as SpringTransition)\n const base = buildOne(cfg, toValue, callback)\n const repeated = applyRepeat(base, repeatOf(cfg))\n return applyDelay(repeated, delayOf(cfg))\n}\n\nexport function repeatOf(cfg: TransitionConfig): RepeatConfig | undefined {\n if (cfg.type === 'no-animation' || cfg.type === 'decay') return undefined\n return cfg.repeat\n}\n\n/**\n * Return `cfg` minus its `repeat` field. Used when peeling top-level repeat\n * off a base transition before passing it down to per-sequence-step\n * resolution — the sequence as a whole is what should repeat, not each step.\n */\nexport function stripRepeat(\n cfg: TransitionConfig | undefined,\n): TransitionConfig | undefined {\n if (!cfg) return cfg\n if (cfg.type === 'no-animation' || cfg.type === 'decay') return cfg\n if (cfg.repeat === undefined) return cfg\n const next = { ...cfg }\n delete next.repeat\n return next\n}\n\nfunction delayOf(cfg: TransitionConfig): number | undefined {\n if (cfg.type === 'no-animation') return undefined\n return cfg.delay\n}\n","import { Platform } from 'react-native'\n\n/**\n * Input-modality tracker for the `focusVisible` gesture sub-state.\n *\n * Implements the W3C `:focus-visible` heuristic: a focus event counts as\n * \"visible\" only when the most recent user input was keyboard-driven. Mouse,\n * pointer, and touch events flip the modality to `'pointer'`; keyboard events\n * flip it back to `'keyboard'`.\n *\n * On native platforms there is no pointer-vs-keyboard distinction — focus\n * arrives via D-pad, screen reader, or hardware keyboard, all of which are\n * keyboard-equivalent — so `isFocusVisible()` is unconditionally `true`.\n *\n * The web listeners attach lazily on first call (capture phase, so they run\n * before the focus event reaches the focused element) and stay installed for\n * the lifetime of the document. They are passive and idle-cheap; the cost is\n * one boolean read per `onFocus` dispatch.\n */\n\ntype InputModality = 'keyboard' | 'pointer'\n\n// Default to `'keyboard'` so a programmatic / autofocus that happens before\n// any user input still draws a focus ring — matches the W3C polyfill default.\nlet modality: InputModality = 'keyboard'\nlet installed = false\n\nfunction setKeyboard() {\n modality = 'keyboard'\n}\n\nfunction setPointer() {\n modality = 'pointer'\n}\n\nfunction ensureInstalled(): void {\n if (installed) return\n if (Platform.OS !== 'web') return\n if (typeof document === 'undefined') return\n document.addEventListener('keydown', setKeyboard, true)\n document.addEventListener('mousedown', setPointer, true)\n document.addEventListener('pointerdown', setPointer, true)\n document.addEventListener('touchstart', setPointer, true)\n installed = true\n}\n\n/**\n * `true` if the next `onFocus` should be treated as \"focus-visible\" (keyboard\n * focus). On native, always `true`. On web, reflects the most recent user\n * input modality.\n */\nexport function isFocusVisible(): boolean {\n if (Platform.OS !== 'web') return true\n ensureInstalled()\n return modality === 'keyboard'\n}\n\n/** @internal — test-only hook to reset module state between cases. */\nexport function __resetFocusVisibilityForTests(next: InputModality): void {\n modality = next\n}\n","import { useCallback, useMemo } from 'react'\nimport { useSharedValue, type SharedValue } from 'react-native-reanimated'\nimport {\n resolveNamedTransitionProp,\n useNamedTransitions,\n useShouldReduceMotion,\n} from '../config'\nimport { isFocusVisible } from '../gestures'\nimport { isTopLevelTransition, resolveTransition } from '../transitions'\nimport {\n type GestureLayerTransitions,\n type TransitionConfig,\n type TransitionInput,\n} from '../types'\n\ntype LayerName = 'pressed' | 'focused' | 'focusVisible' | 'hovered'\n\n/**\n * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the\n * shared values returned alongside.\n *\n * Hover handlers use `Pressable`'s own `onHoverIn` / `onHoverOut` names (web\n * only — no-ops on native). `onFocus` consults `isFocusVisible()` before\n * raising the keyboard-only `focusVisible` layer; `focused` always raises.\n */\nexport interface UseGestureHandlers {\n onPressIn: () => void\n onPressOut: () => void\n onHoverIn: () => void\n onHoverOut: () => void\n onFocus: () => void\n onBlur: () => void\n}\n\nexport interface UseGestureResult {\n /** 0↔1 progress for the pressed layer. */\n pressed: SharedValue<number>\n /** 0↔1 progress for the focused layer (any focus modality). */\n focused: SharedValue<number>\n /** 0↔1 progress for the focusVisible layer (keyboard focus only). */\n focusVisible: SharedValue<number>\n /** 0↔1 progress for the hovered layer (web only — stays at 0 on native). */\n hovered: SharedValue<number>\n /** Handlers to spread on the receiving `Pressable`. */\n handlers: UseGestureHandlers\n}\n\n/**\n * Build a gesture-layer controller. The hook-form of the `gesture` prop —\n * reach for it when you need to drive multiple animated views from the same\n * gesture state (a focus ring + state-layer halo + content tint all on one\n * Pressable), which the prop-form's \"animate the receiver's own style\" model\n * can't express.\n *\n * Returns four 0↔1 shared values (one per layer) and a handler bag to spread\n * on a `Pressable`. The shared values are stable across renders — feed them\n * into any number of `useAnimatedStyle` blocks anywhere in the tree.\n *\n * Transitions follow the same shape as the `gesture` prop's accompanying\n * `transition`: pass a single `TransitionConfig` to use for every layer, or a\n * `GestureLayerTransitions` map to give each layer its own. A `TransitionName`\n * registered on the nearest `<MotionConfig transitions>` is accepted in both\n * positions (top-level and per-layer). Layers without an explicit transition\n * fall back to the library default spring.\n *\n * Reduced motion (via `<MotionConfig reducedMotion>`) collapses every\n * transition to `no-animation` so state changes snap instead of interpolating\n * — same behaviour the gesture prop applies.\n *\n * @example\n * ```tsx\n * import { useAnimatedStyle } from 'react-native-reanimated'\n * import { useGesture } from '@rootnative/inertia'\n *\n * function Card() {\n * const { pressed, focused, hovered, handlers } = useGesture({\n * pressed: { type: 'timing', duration: 100 },\n * hovered: { type: 'timing', duration: 150 },\n * focused: { type: 'timing', duration: 200 },\n * })\n *\n * const ringStyle = useAnimatedStyle(() => ({ opacity: focused.value }))\n * const haloStyle = useAnimatedStyle(() => ({\n * opacity: Math.max(\n * hovered.value * 0.08,\n * focused.value * 0.10,\n * pressed.value * 0.10,\n * ),\n * }))\n *\n * return (\n * <Pressable {...handlers}>\n * <Animated.View style={ringStyle} />\n * <Animated.View style={haloStyle} />\n * </Pressable>\n * )\n * }\n * ```\n */\nexport function useGesture(\n transition?: TransitionInput | GestureLayerTransitions,\n): UseGestureResult {\n const pressed = useSharedValue(0)\n const focused = useSharedValue(0)\n const focusVisible = useSharedValue(0)\n const hovered = useSharedValue(0)\n const shouldReduceMotion = useShouldReduceMotion()\n // Registered transition names (top-level string or per-layer string values)\n // resolve against the nearest <MotionConfig transitions> at render time, so\n // the callbacks below only ever see concrete configs.\n const resolved = resolveNamedTransitionProp(transition, useNamedTransitions())\n\n const setLayer = useCallback(\n (sv: SharedValue<number>, layer: LayerName, target: 0 | 1) => {\n const cfg = shouldReduceMotion\n ? ({ type: 'no-animation' } as const)\n : (layerTransition(layer, resolved) ?? ({ type: 'spring' } as const))\n sv.value = resolveTransition(cfg, target) as never\n },\n // The transition is intentionally read on every call rather than cooked\n // into the dep array — a fresh literal each render would otherwise\n // rebuild the handler bag and break composing consumers that key off\n // handler identity. `transition` is read inside the callback closure;\n // shared values are stable so the only dep that matters is the reduce-\n // motion flag.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [shouldReduceMotion],\n )\n\n const handlers = useMemo<UseGestureHandlers>(\n () => ({\n onPressIn: () => setLayer(pressed, 'pressed', 1),\n onPressOut: () => setLayer(pressed, 'pressed', 0),\n onHoverIn: () => setLayer(hovered, 'hovered', 1),\n onHoverOut: () => setLayer(hovered, 'hovered', 0),\n onFocus: () => {\n setLayer(focused, 'focused', 1)\n if (isFocusVisible()) setLayer(focusVisible, 'focusVisible', 1)\n },\n onBlur: () => {\n setLayer(focused, 'focused', 0)\n setLayer(focusVisible, 'focusVisible', 0)\n },\n }),\n [setLayer, pressed, focused, focusVisible, hovered],\n )\n\n return { pressed, focused, focusVisible, hovered, handlers }\n}\n\n// Runs after name resolution, so the `TransitionInput` values on the map form\n// are concrete configs by the time they're read — hence the return cast.\nfunction layerTransition(\n layer: LayerName,\n transition: TransitionConfig | GestureLayerTransitions | undefined,\n): TransitionConfig | undefined {\n if (!transition) return undefined\n if (isTopLevelTransition(transition)) return transition\n return (transition as GestureLayerTransitions)[layer] as\n | TransitionConfig\n | undefined\n}\n","import { useEffect, useMemo } from 'react'\nimport {\n interpolateColor,\n useAnimatedStyle,\n useSharedValue,\n type AnimatedStyle,\n} from 'react-native-reanimated'\nimport {\n resolveNamedTransitionProp,\n useNamedTransitions,\n useShouldReduceMotion,\n} from '../config'\nimport {\n isTopLevelTransition,\n resolveTransition,\n stableSig,\n} from '../transitions'\nimport { useGesture, type UseGestureHandlers } from '../values/useGesture'\nimport {\n type GestureLayerTransitions,\n type TransitionConfig,\n type TransitionInput,\n} from '../types'\n\n/**\n * A single gesture-layer style — a flat map of style keys to a value. Numeric\n * values participate in clamped-max composition (the \"strongest active layer\n * wins\" model used by MD3 state-layer haloes); string values are treated as\n * colors and composed via priority cascade with `interpolateColor`.\n *\n * The hook does not validate that string values are valid colors — passing\n * something like `borderStyle: 'solid'` will crash inside the worklet. Keep\n * string values to color strings.\n */\nexport type GestureLayerStyle = {\n [key: string]: number | string | undefined\n}\n\n/**\n * Per-state style maps. Every key is optional; missing layers default to\n * `rest` (or `0` / `'transparent'` if `rest` is also absent for that key).\n *\n * - `rest` — base values, applied when no other layer is active.\n * - `hovered` / `focused` / `focusVisible` / `pressed` — gesture-driven\n * states tracked via the underlying `useGesture` hook. Each owns an\n * independent 0↔1 progress that fades the layer in/out per the configured\n * transition.\n * - `disabled` — gated by the JS-side `options.disabled` flag rather than a\n * gesture. Sits at the top of the priority cascade and overrides every\n * gesture layer when active.\n */\nexport interface GestureLayerStates {\n rest?: GestureLayerStyle\n hovered?: GestureLayerStyle\n focused?: GestureLayerStyle\n focusVisible?: GestureLayerStyle\n pressed?: GestureLayerStyle\n disabled?: GestureLayerStyle\n}\n\nexport interface UseGestureLayerOptions {\n /**\n * When `true`, the `disabled` layer becomes active (or `rest` if `disabled`\n * is undefined). Animates via the top-level transition or the library\n * default spring; per-layer transitions (`GestureLayerTransitions`) do not\n * apply to `disabled`.\n */\n disabled?: boolean\n /**\n * Transition forwarded to the underlying `useGesture` hook. Either a single\n * `TransitionConfig` for every gesture layer, or a `GestureLayerTransitions`\n * map for per-layer fades. A `TransitionName` registered on the nearest\n * `<MotionConfig transitions>` is accepted in both positions. Reduced\n * motion collapses every transition to `no-animation`.\n */\n transition?: TransitionInput | GestureLayerTransitions\n}\n\nexport interface UseGestureLayerResult {\n /**\n * Animated style produced by `useAnimatedStyle` — spread on an\n * `Animated.View` or pass through `<Motion.View style={...} />`.\n */\n style: AnimatedStyle<Record<string, unknown>>\n /** Handlers to spread on the receiving `Pressable`. */\n handlers: UseGestureHandlers\n}\n\n/**\n * A \"strongest active layer wins\" interactive-feedback primitive. Sits one\n * step above `useGesture()` — the consumer supplies the per-state target\n * values, the hook handles the four gesture progress shared values, the\n * disabled override, the worklet, and the transition.\n *\n * Composition model:\n *\n * - **Numeric keys** (opacity, scale, borderWidth, etc.) compose via\n * clamped-max with `rest` as the floor:\n * `out = max(rest, ...for each active gesture layer: lerp(rest, layer, progress))`.\n * This matches the MD3 state-layer halo pattern — multiple states active\n * simultaneously raise the value to the strongest, not the sum.\n * - **Color keys** (any string value) compose via priority cascade with\n * `interpolateColor`, lowest priority first: `hovered → focused →\n * focusVisible → pressed`. Clamped-max doesn't apply to colors; this\n * matches the cascade used by the declarative `gesture` prop.\n * - **Disabled** sits at the top of the cascade for both numeric and color\n * keys — when active, it lerps the composed value toward the `disabled`\n * target.\n *\n * Reach for this when you want MD3 / iOS-translucent state-layer overlays\n * without rewriting the worklet by hand for every consumer; reach for plain\n * `useGesture()` when you need a composition model this hook doesn't\n * express (additive, multiply, per-key custom blends).\n *\n * @example MD3 state-layer halo\n * ```tsx\n * import { useGestureLayer } from '@rootnative/inertia/gesture-layer'\n * import Animated from 'react-native-reanimated'\n * import { Pressable } from 'react-native'\n *\n * function SwitchHalo({ disabled }: { disabled?: boolean }) {\n * const { style, handlers } = useGestureLayer(\n * {\n * rest: { opacity: 0, backgroundColor: 'transparent' },\n * hovered: { opacity: 0.08, backgroundColor: '#000' },\n * focused: { opacity: 0.10, backgroundColor: '#000' },\n * pressed: { opacity: 0.12, backgroundColor: '#000' },\n * },\n * { disabled, transition: { type: 'timing', duration: 150 } },\n * )\n *\n * return (\n * <Pressable {...handlers}>\n * <Animated.View style={style} />\n * </Pressable>\n * )\n * }\n * ```\n */\nexport function useGestureLayer(\n states: GestureLayerStates,\n options: UseGestureLayerOptions = {},\n): UseGestureLayerResult {\n const { disabled: isDisabled = false, transition: transitionInput } = options\n const shouldReduceMotion = useShouldReduceMotion()\n // Resolve registered names here (not just in useGesture) because the\n // `disabled` layer reads the top-level transition locally. Identity is\n // preserved when no names are present; when a name resolves, the effect\n // below keys on the structural signature so a per-render resolve of the\n // map form doesn't re-fire it.\n const transition = resolveNamedTransitionProp(\n transitionInput,\n useNamedTransitions(),\n )\n const gesture = useGesture(transition)\n const disabledProgress = useSharedValue(0)\n\n const transitionSig = stableSig(transition)\n useEffect(() => {\n const target = isDisabled ? 1 : 0\n const cfg = shouldReduceMotion\n ? ({ type: 'no-animation' } as const)\n : (disabledTransition(transition) ?? ({ type: 'spring' } as const))\n disabledProgress.value = resolveTransition(cfg, target) as never\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isDisabled, shouldReduceMotion, transitionSig, disabledProgress])\n\n // JS-thread precompute: union of keys across all layers, per-key type\n // (number vs color), and a rest-fallback table. The worklet body reads\n // from `meta` instead of probing each layer per frame — the type check\n // only runs when layer identities change.\n const meta = useMemo(() => {\n const layers = {\n rest: states.rest,\n hovered: states.hovered,\n focused: states.focused,\n focusVisible: states.focusVisible,\n pressed: states.pressed,\n disabled: states.disabled,\n }\n const sources = [\n layers.rest,\n layers.hovered,\n layers.focused,\n layers.focusVisible,\n layers.pressed,\n layers.disabled,\n ]\n const keySet = new Set<string>()\n for (const src of sources) {\n if (!src) continue\n for (const k in src) if (src[k] !== undefined) keySet.add(k)\n }\n const keys = Array.from(keySet)\n const types: Record<string, 'number' | 'color'> = {}\n const restValues: Record<string, number | string> = {}\n for (const k of keys) {\n let firstDefined: number | string | undefined\n for (const src of sources) {\n if (src && src[k] !== undefined) {\n firstDefined = src[k]\n break\n }\n }\n const isColor = typeof firstDefined === 'string'\n types[k] = isColor ? 'color' : 'number'\n const restRaw = layers.rest ? layers.rest[k] : undefined\n restValues[k] =\n restRaw !== undefined ? restRaw : isColor ? 'transparent' : 0\n }\n return { layers, keys, types, restValues }\n }, [\n states.rest,\n states.hovered,\n states.focused,\n states.focusVisible,\n states.pressed,\n states.disabled,\n ])\n\n const style = useAnimatedStyle(() => {\n const { layers, keys, types, restValues } = meta\n const ph = gesture.hovered.value\n const pf = gesture.focused.value\n const pfv = gesture.focusVisible.value\n const pp = gesture.pressed.value\n const pd = disabledProgress.value\n\n const hoveredLayer = layers.hovered\n const focusedLayer = layers.focused\n const focusVisibleLayer = layers.focusVisible\n const pressedLayer = layers.pressed\n const disabledLayer = layers.disabled\n\n const out: Record<string, unknown> = {}\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]!\n const isColor = types[k] === 'color'\n const rest = restValues[k]!\n\n if (isColor) {\n let v = rest as string\n if (hoveredLayer && ph > 0 && hoveredLayer[k] !== undefined) {\n v = interpolateColor(ph, [0, 1], [v, hoveredLayer[k] as string])\n }\n if (focusedLayer && pf > 0 && focusedLayer[k] !== undefined) {\n v = interpolateColor(pf, [0, 1], [v, focusedLayer[k] as string])\n }\n if (\n focusVisibleLayer &&\n pfv > 0 &&\n focusVisibleLayer[k] !== undefined\n ) {\n v = interpolateColor(pfv, [0, 1], [v, focusVisibleLayer[k] as string])\n }\n if (pressedLayer && pp > 0 && pressedLayer[k] !== undefined) {\n v = interpolateColor(pp, [0, 1], [v, pressedLayer[k] as string])\n }\n if (disabledLayer && pd > 0 && disabledLayer[k] !== undefined) {\n v = interpolateColor(pd, [0, 1], [v, disabledLayer[k] as string])\n }\n out[k] = v\n } else {\n const base = rest as number\n let m = base\n if (hoveredLayer && ph > 0 && hoveredLayer[k] !== undefined) {\n const c = base + ((hoveredLayer[k] as number) - base) * ph\n if (c > m) m = c\n }\n if (focusedLayer && pf > 0 && focusedLayer[k] !== undefined) {\n const c = base + ((focusedLayer[k] as number) - base) * pf\n if (c > m) m = c\n }\n if (\n focusVisibleLayer &&\n pfv > 0 &&\n focusVisibleLayer[k] !== undefined\n ) {\n const c = base + ((focusVisibleLayer[k] as number) - base) * pfv\n if (c > m) m = c\n }\n if (pressedLayer && pp > 0 && pressedLayer[k] !== undefined) {\n const c = base + ((pressedLayer[k] as number) - base) * pp\n if (c > m) m = c\n }\n if (disabledLayer && pd > 0 && disabledLayer[k] !== undefined) {\n m = m + ((disabledLayer[k] as number) - m) * pd\n }\n out[k] = m\n }\n }\n\n return out\n })\n\n return {\n style: style as AnimatedStyle<Record<string, unknown>>,\n handlers: gesture.handlers,\n }\n}\n\nfunction disabledTransition(\n transition: TransitionConfig | GestureLayerTransitions | undefined,\n): TransitionConfig | undefined {\n if (!transition) return undefined\n if (isTopLevelTransition(transition)) return transition\n return undefined\n}\n"]}
|
|
@@ -4,8 +4,31 @@ import { isWorkletFunction } from 'react-native-worklets';
|
|
|
4
4
|
import { Platform } from 'react-native';
|
|
5
5
|
|
|
6
6
|
// src/gestureLayer/useGestureLayer.ts
|
|
7
|
+
|
|
8
|
+
// src/transitions/sig.ts
|
|
9
|
+
function stableSig(value) {
|
|
10
|
+
if (value === void 0) return "";
|
|
11
|
+
try {
|
|
12
|
+
return stableStringify(value);
|
|
13
|
+
} catch {
|
|
14
|
+
return String(value);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function stableStringify(v) {
|
|
18
|
+
if (v === null || typeof v !== "object") {
|
|
19
|
+
if (typeof v === "function" || v === void 0) return "null";
|
|
20
|
+
return JSON.stringify(v);
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(v)) {
|
|
23
|
+
return "[" + v.map(stableStringify).join(",") + "]";
|
|
24
|
+
}
|
|
25
|
+
const obj = v;
|
|
26
|
+
const keys = Object.keys(obj).sort();
|
|
27
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
|
|
28
|
+
}
|
|
7
29
|
var DEFAULT_MOTION_CONFIG = {
|
|
8
|
-
reducedMotion: "user"
|
|
30
|
+
reducedMotion: "user",
|
|
31
|
+
transitions: {}
|
|
9
32
|
};
|
|
10
33
|
var MotionConfigContext = createContext(
|
|
11
34
|
DEFAULT_MOTION_CONFIG
|
|
@@ -13,6 +36,9 @@ var MotionConfigContext = createContext(
|
|
|
13
36
|
function useMotionConfig() {
|
|
14
37
|
return useContext(MotionConfigContext);
|
|
15
38
|
}
|
|
39
|
+
function useNamedTransitions() {
|
|
40
|
+
return useMotionConfig().transitions;
|
|
41
|
+
}
|
|
16
42
|
function useShouldReduceMotion() {
|
|
17
43
|
const { reducedMotion } = useMotionConfig();
|
|
18
44
|
const osReduced = useReducedMotion();
|
|
@@ -20,6 +46,59 @@ function useShouldReduceMotion() {
|
|
|
20
46
|
if (reducedMotion === "always") return true;
|
|
21
47
|
return osReduced;
|
|
22
48
|
}
|
|
49
|
+
|
|
50
|
+
// src/transitions/keys.ts
|
|
51
|
+
var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
52
|
+
"type",
|
|
53
|
+
"tension",
|
|
54
|
+
"friction",
|
|
55
|
+
"mass",
|
|
56
|
+
"velocity",
|
|
57
|
+
"restSpeedThreshold",
|
|
58
|
+
"restDisplacementThreshold",
|
|
59
|
+
"duration",
|
|
60
|
+
"easing",
|
|
61
|
+
"delay",
|
|
62
|
+
"repeat",
|
|
63
|
+
"deceleration",
|
|
64
|
+
"clamp"
|
|
65
|
+
]);
|
|
66
|
+
function isTopLevelTransition(t) {
|
|
67
|
+
if (t === null || typeof t !== "object") return false;
|
|
68
|
+
const keys = Object.keys(t);
|
|
69
|
+
if (keys.length === 0) return false;
|
|
70
|
+
return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/config/namedTransitions.ts
|
|
74
|
+
var UNKNOWN_NAME_FALLBACK = { type: "spring" };
|
|
75
|
+
function lookupNamedTransition(name, registry) {
|
|
76
|
+
const cfg = registry[name];
|
|
77
|
+
if (cfg) return cfg;
|
|
78
|
+
if (__DEV__) {
|
|
79
|
+
console.warn(
|
|
80
|
+
`[inertia] Unknown transition name "${name}" \u2014 falling back to the default spring. Register it on a provider: <MotionConfig transitions={{ '${name}': { ... } }}>.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
return UNKNOWN_NAME_FALLBACK;
|
|
84
|
+
}
|
|
85
|
+
function resolveNamedTransitionProp(transition, registry) {
|
|
86
|
+
if (transition === void 0) return void 0;
|
|
87
|
+
if (typeof transition === "string") {
|
|
88
|
+
return lookupNamedTransition(transition, registry);
|
|
89
|
+
}
|
|
90
|
+
if (isTopLevelTransition(transition)) return transition;
|
|
91
|
+
const map = transition;
|
|
92
|
+
let out = null;
|
|
93
|
+
for (const key in map) {
|
|
94
|
+
const value = map[key];
|
|
95
|
+
if (typeof value === "string") {
|
|
96
|
+
if (out === null) out = { ...map };
|
|
97
|
+
out[key] = lookupNamedTransition(value, registry);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return out ?? transition;
|
|
101
|
+
}
|
|
23
102
|
function ensureWorkletEasing(easing) {
|
|
24
103
|
if (!easing) return void 0;
|
|
25
104
|
const fn = isEasingFactory(easing) ? easing.factory() : easing;
|
|
@@ -115,29 +194,6 @@ function delayOf(cfg) {
|
|
|
115
194
|
if (cfg.type === "no-animation") return void 0;
|
|
116
195
|
return cfg.delay;
|
|
117
196
|
}
|
|
118
|
-
|
|
119
|
-
// src/transitions/keys.ts
|
|
120
|
-
var TRANSITION_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
121
|
-
"type",
|
|
122
|
-
"tension",
|
|
123
|
-
"friction",
|
|
124
|
-
"mass",
|
|
125
|
-
"velocity",
|
|
126
|
-
"restSpeedThreshold",
|
|
127
|
-
"restDisplacementThreshold",
|
|
128
|
-
"duration",
|
|
129
|
-
"easing",
|
|
130
|
-
"delay",
|
|
131
|
-
"repeat",
|
|
132
|
-
"deceleration",
|
|
133
|
-
"clamp"
|
|
134
|
-
]);
|
|
135
|
-
function isTopLevelTransition(t) {
|
|
136
|
-
if (t === null || typeof t !== "object") return false;
|
|
137
|
-
const keys = Object.keys(t);
|
|
138
|
-
if (keys.length === 0) return false;
|
|
139
|
-
return keys.every((k) => TRANSITION_CONFIG_KEYS.has(k));
|
|
140
|
-
}
|
|
141
197
|
var modality = "keyboard";
|
|
142
198
|
var installed = false;
|
|
143
199
|
function setKeyboard() {
|
|
@@ -169,9 +225,10 @@ function useGesture(transition) {
|
|
|
169
225
|
const focusVisible = useSharedValue(0);
|
|
170
226
|
const hovered = useSharedValue(0);
|
|
171
227
|
const shouldReduceMotion = useShouldReduceMotion();
|
|
228
|
+
const resolved = resolveNamedTransitionProp(transition, useNamedTransitions());
|
|
172
229
|
const setLayer = useCallback(
|
|
173
230
|
(sv, layer, target) => {
|
|
174
|
-
const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer,
|
|
231
|
+
const cfg = shouldReduceMotion ? { type: "no-animation" } : layerTransition(layer, resolved) ?? { type: "spring" };
|
|
175
232
|
sv.value = resolveTransition(cfg, target);
|
|
176
233
|
},
|
|
177
234
|
// The transition is intentionally read on every call rather than cooked
|
|
@@ -210,15 +267,20 @@ function layerTransition(layer, transition) {
|
|
|
210
267
|
|
|
211
268
|
// src/gestureLayer/useGestureLayer.ts
|
|
212
269
|
function useGestureLayer(states, options = {}) {
|
|
213
|
-
const { disabled: isDisabled = false, transition } = options;
|
|
270
|
+
const { disabled: isDisabled = false, transition: transitionInput } = options;
|
|
214
271
|
const shouldReduceMotion = useShouldReduceMotion();
|
|
272
|
+
const transition = resolveNamedTransitionProp(
|
|
273
|
+
transitionInput,
|
|
274
|
+
useNamedTransitions()
|
|
275
|
+
);
|
|
215
276
|
const gesture = useGesture(transition);
|
|
216
277
|
const disabledProgress = useSharedValue(0);
|
|
278
|
+
const transitionSig = stableSig(transition);
|
|
217
279
|
useEffect(() => {
|
|
218
280
|
const target = isDisabled ? 1 : 0;
|
|
219
281
|
const cfg = shouldReduceMotion ? { type: "no-animation" } : disabledTransition(transition) ?? { type: "spring" };
|
|
220
282
|
disabledProgress.value = resolveTransition(cfg, target);
|
|
221
|
-
}, [isDisabled, shouldReduceMotion,
|
|
283
|
+
}, [isDisabled, shouldReduceMotion, transitionSig, disabledProgress]);
|
|
222
284
|
const meta = useMemo(() => {
|
|
223
285
|
const layers = {
|
|
224
286
|
rest: states.rest,
|