@onlynative/inertia 0.0.1-alpha.3 → 0.0.1-alpha.4

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 (60) hide show
  1. package/README.md +19 -5
  2. package/dist/index.d.mts +259 -3
  3. package/dist/index.d.ts +259 -3
  4. package/dist/index.js +1711 -118
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +1709 -122
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/motion/Image.d.mts +1 -1
  9. package/dist/motion/Image.d.ts +1 -1
  10. package/dist/motion/Image.js +1502 -64
  11. package/dist/motion/Image.js.map +1 -1
  12. package/dist/motion/Image.mjs +1504 -66
  13. package/dist/motion/Image.mjs.map +1 -1
  14. package/dist/motion/Pressable.d.mts +1 -1
  15. package/dist/motion/Pressable.d.ts +1 -1
  16. package/dist/motion/Pressable.js +1502 -64
  17. package/dist/motion/Pressable.js.map +1 -1
  18. package/dist/motion/Pressable.mjs +1504 -66
  19. package/dist/motion/Pressable.mjs.map +1 -1
  20. package/dist/motion/ScrollView.d.mts +1 -1
  21. package/dist/motion/ScrollView.d.ts +1 -1
  22. package/dist/motion/ScrollView.js +1502 -64
  23. package/dist/motion/ScrollView.js.map +1 -1
  24. package/dist/motion/ScrollView.mjs +1504 -66
  25. package/dist/motion/ScrollView.mjs.map +1 -1
  26. package/dist/motion/Text.d.mts +1 -1
  27. package/dist/motion/Text.d.ts +1 -1
  28. package/dist/motion/Text.js +1502 -64
  29. package/dist/motion/Text.js.map +1 -1
  30. package/dist/motion/Text.mjs +1504 -66
  31. package/dist/motion/Text.mjs.map +1 -1
  32. package/dist/motion/View.d.mts +1 -1
  33. package/dist/motion/View.d.ts +1 -1
  34. package/dist/motion/View.js +1502 -64
  35. package/dist/motion/View.js.map +1 -1
  36. package/dist/motion/View.mjs +1504 -66
  37. package/dist/motion/View.mjs.map +1 -1
  38. package/dist/{types-DAhX3fC2.d.mts → types-CjztO3RW.d.mts} +49 -4
  39. package/dist/{types-DAhX3fC2.d.ts → types-CjztO3RW.d.ts} +49 -4
  40. package/llms.txt +29 -4
  41. package/package.json +1 -1
  42. package/src/__type-tests__/animate.test-d.tsx +88 -0
  43. package/src/index.ts +16 -1
  44. package/src/layout/index.ts +1 -0
  45. package/src/layout/resolveLayout.ts +54 -0
  46. package/src/motion/createMotionComponent.tsx +38 -60
  47. package/src/transitions/easing.ts +3 -1
  48. package/src/transitions/index.ts +3 -0
  49. package/src/transitions/keys.ts +32 -0
  50. package/src/transitions/resolve.ts +1 -24
  51. package/src/transitions/sig.ts +40 -0
  52. package/src/transitions/spring.ts +41 -0
  53. package/src/types.ts +52 -2
  54. package/src/values/index.ts +14 -0
  55. package/src/values/useAnimation.ts +69 -0
  56. package/src/values/useGesture.ts +144 -0
  57. package/src/values/useMotionValue.ts +33 -0
  58. package/src/values/useScroll.ts +72 -0
  59. package/src/values/useSpring.ts +93 -0
  60. package/src/values/useTransform.ts +132 -0
package/README.md CHANGED
@@ -45,6 +45,8 @@ export function FadeIn() {
45
45
  - **Gestures** — single `gesture` prop on every primitive: `gesture={{ pressed, focused, focusVisible, hovered }}`. Sub-states layer **additively** in priority order (`hovered → focused → focusVisible → pressed`); each layer fades in/out on its own progress so MD3 release-while-hovered cross-fades correctly. Per-layer transitions via `transition.<stateName>`. `focusVisible` engages only on keyboard focus (W3C `:focus-visible`) so click-focus on web doesn't flash a ring; on native it tracks `focused`. Zero overhead when omitted.
46
46
  - **`<Presence>`** — mount/unmount transitions; exiting children automatically receive `pointerEvents: 'none'`.
47
47
  - **`<MotionConfig reducedMotion>`** — OS reduce-motion honored end-to-end (`'user' | 'never' | 'always'`).
48
+ - **`layout` prop** — auto-layout transitions on every primitive, bridging Reanimated's `LinearTransition` via the same react-spring vocab (`tension`/`friction`/`mass`). Accepts `boolean | TransitionConfig`.
49
+ - **Value-layer hooks** — `useMotionValue`, `useSpring`, `useAnimation`, `useTransform`, `useScroll`, `useVariants`, `useGesture`. The escape hatch for animations the prop surface can't express — sibling overlays driven by a parent gesture, indeterminate loops on standalone shared values, gesture-smoothed inputs, etc.
48
50
  - **Per-primitive subpath imports** — `@onlynative/inertia/view`, `/text`, `/image`, `/pressable`, `/scroll-view`.
49
51
  - **JS-thread resolver, memoized worklets** — animate/transition objects compile to baked `withSpring` / `withTiming` / `withDecay` calls on the JS thread; the worklet body never iterates `Object.keys(...)` at frame time.
50
52
 
@@ -86,23 +88,35 @@ Plus, on any transition: `delay`, `repeat`. Per-property transitions take preced
86
88
 
87
89
  Numeric: `opacity`, `translateX`, `translateY`, `scale`, `scaleX`, `scaleY`, `rotate`, `rotateX`, `rotateY`, `width`, `height`, `borderRadius`. Color: `backgroundColor`, `borderColor`, `color`, `tintColor` (Image only — `Motion.View` rejects it at compile time). Layout transforms via `transform: [...]`. Color targets are forwarded straight through `withSpring` / `withTiming`; Reanimated's value setter packs the string to RGBA and interpolates on the UI thread.
88
90
 
89
- Out of scope for `0.x`: SVG path morphing, gradient interpolation, shared-element transitions across screens.
91
+ SVG path morphing ships in the [`@onlynative/inertia-svg`](../svg) adapter (`MotionPath`). Out of scope for `0.x`: shared-element transitions across screens (Reanimated 4 dropped `sharedTransitionTag`; a measure-based replacement is in design).
90
92
 
91
93
  ## When not to use the core package alone
92
94
 
93
- The `gesture` prop in `@onlynative/inertia` covers `pressed` / `focused` / `focusVisible` / `hovered` — the Pressable-shaped sub-states. **Continuous, value-bearing gestures live in the adapter package** [`@onlynative/inertia-gestures`](../gestures), which wraps `react-native-gesture-handler` and ships:
95
+ Three sibling packages extend Inertia for capabilities that need extra peer dependencies. The core stays minimal so apps that don't need these don't pay for them.
96
+
97
+ **Continuous gestures** — the `gesture` prop in `@onlynative/inertia` covers `pressed` / `focused` / `focusVisible` / `hovered` (the Pressable-shaped sub-states). For drag, pan, or swipe, use [`@onlynative/inertia-gestures`](../gestures):
94
98
 
95
99
  - `useDrag` — one- or two-axis drag with optional constraints and rubber-band elasticity
96
100
  - `usePan` — camera-style pan with momentum on release
97
101
  - `useSwipe` — directional commit-or-snap-back (distance + velocity thresholds)
98
102
 
99
- If your screen needs a thumb that follows the finger, a sheet that flicks closed, a carousel with momentum, or any gesture that produces a value other than "active / inactive" — install the adapter:
100
-
101
103
  ```sh
102
104
  pnpm add @onlynative/inertia-gestures react-native-gesture-handler
103
105
  ```
104
106
 
105
- A fully gesture-driven `Slider` (continuous thumb tracking + range clamping) is the canonical example: the core package can't build it on its own, the adapter can. This is intentional — keeping `react-native-gesture-handler` out of the core peer set means apps that animate buttons and sheets don't pay for a gesture engine they never invoke.
107
+ **Animated gradients** colors / start / end / locations interpolation on a linear gradient lives in [`@onlynative/inertia-gradients`](../gradients), wrapping `expo-linear-gradient`:
108
+
109
+ ```sh
110
+ pnpm add @onlynative/inertia-gradients expo-linear-gradient
111
+ ```
112
+
113
+ **SVG path morphing** — `MotionPath` lives in [`@onlynative/inertia-svg`](../svg), wrapping `react-native-svg`. Animates path data (`d`) on structurally-compatible paths via element-wise scalar interpolation, plus `fill` / `stroke` / `strokeWidth` / opacities / `strokeDashoffset`:
114
+
115
+ ```sh
116
+ pnpm add @onlynative/inertia-svg react-native-svg
117
+ ```
118
+
119
+ Keeping `react-native-gesture-handler`, `expo-linear-gradient`, and `react-native-svg` out of the core peer set means apps that animate buttons, sheets, and basic styles don't pay for capabilities they never invoke.
106
120
 
107
121
  ## Documentation
108
122
 
package/dist/index.d.mts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
3
  import * as react_native from 'react-native';
4
- import { M as MotionComponent, A as AnimatableValue, T as TransitionConfig, V as VariantController } from './types-DAhX3fC2.mjs';
5
- export { a as AnimateStyle, b as AnimationCallbackInfo, D as DecayTransition, G as GestureSubStates, c as MotionProps, N as NoAnimationTransition, P as PerPropertyTransition, R as RepeatConfig, S as SequenceStep, d as SpringTransition, e as TimingTransition, f as Transition, g as VariantsMap } from './types-DAhX3fC2.mjs';
4
+ import { NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
5
+ import { M as MotionComponent, A as AnimatableValue, T as TransitionConfig, G as GestureLayerTransitions, S as SpringTransition, V as VariantController } from './types-CjztO3RW.mjs';
6
+ export { a as AnimateStyle, b as AnimationCallbackInfo, D as DecayTransition, c as GestureSubStates, d as MotionProps, N as NoAnimationTransition, P as PerPropertyTransition, R as RepeatConfig, e as SequenceStep, f as TimingTransition, g as Transition, h as VariantsMap } from './types-CjztO3RW.mjs';
7
+ import { SharedValue } from 'react-native-reanimated';
6
8
  export { MotionImage } from './motion/Image.mjs';
7
9
  export { MotionPressable } from './motion/Pressable.mjs';
8
10
  export { MotionScrollView } from './motion/ScrollView.mjs';
@@ -168,6 +170,260 @@ declare function resolveAnimatableValue<V extends number | string>(value: Animat
168
170
  */
169
171
  declare function ensureWorkletEasing(easing: ((t: number) => number) | undefined): ((t: number) => number) | undefined;
170
172
 
173
+ /**
174
+ * Drive a `SharedValue<number>` toward `target` with **any** transition shape
175
+ * — spring, timing, decay, or no-animation. The general-purpose value-layer
176
+ * hook: reach for it when you need raw `useSharedValue + useEffect + withX`
177
+ * outside the declarative `animate` flow.
178
+ *
179
+ * Re-runs whenever `target` changes shape (`target` is in the dep array) or
180
+ * the transition signature changes (kept stable via JSON-style hashing).
181
+ * Reduced motion (via `<MotionConfig reducedMotion>`) collapses the
182
+ * transition to `no-animation` so the value snaps instead of interpolating.
183
+ *
184
+ * **Spring shorthand.** Prefer [`useSpring`](./useSpring) when you only want
185
+ * spring physics — it accepts the same `tension`/`friction`/`mass` config and
186
+ * also supports a `SharedValue<number>` as the target (UI-thread reactive
187
+ * source). `useAnimation` is JS-thread-driven only.
188
+ *
189
+ * **Loops.** Repeat is part of `TransitionConfig` and flows through
190
+ * untouched — `useAnimation(1, { type: 'timing', duration: 1800, repeat: {
191
+ * count: 'infinite', alternate: false } })` produces an indeterminate-style
192
+ * progress driver.
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * // Toggle progress (Switch / Checkbox / Radio).
197
+ * const progress = useAnimation(isChecked ? 1 : 0, {
198
+ * type: 'spring',
199
+ * tension: 380,
200
+ * friction: 33,
201
+ * })
202
+ *
203
+ * // Float a TextField label when the value becomes non-empty.
204
+ * const floated = useAnimation(hasValue ? 1 : 0, {
205
+ * type: 'timing',
206
+ * duration: 150,
207
+ * })
208
+ *
209
+ * // Indeterminate progress slider (loops forever, snaps back).
210
+ * const slide = useAnimation(1, {
211
+ * type: 'timing',
212
+ * duration: 1800,
213
+ * repeat: { count: 'infinite', alternate: false },
214
+ * })
215
+ * ```
216
+ */
217
+ declare function useAnimation(target: number, transition?: TransitionConfig): SharedValue<number>;
218
+
219
+ /**
220
+ * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
221
+ * shared values returned alongside.
222
+ *
223
+ * Hover handlers use `Pressable`'s own `onHoverIn` / `onHoverOut` names (web
224
+ * only — no-ops on native). `onFocus` consults `isFocusVisible()` before
225
+ * raising the keyboard-only `focusVisible` layer; `focused` always raises.
226
+ */
227
+ interface UseGestureHandlers {
228
+ onPressIn: () => void;
229
+ onPressOut: () => void;
230
+ onHoverIn: () => void;
231
+ onHoverOut: () => void;
232
+ onFocus: () => void;
233
+ onBlur: () => void;
234
+ }
235
+ interface UseGestureResult {
236
+ /** 0↔1 progress for the pressed layer. */
237
+ pressed: SharedValue<number>;
238
+ /** 0↔1 progress for the focused layer (any focus modality). */
239
+ focused: SharedValue<number>;
240
+ /** 0↔1 progress for the focusVisible layer (keyboard focus only). */
241
+ focusVisible: SharedValue<number>;
242
+ /** 0↔1 progress for the hovered layer (web only — stays at 0 on native). */
243
+ hovered: SharedValue<number>;
244
+ /** Handlers to spread on the receiving `Pressable`. */
245
+ handlers: UseGestureHandlers;
246
+ }
247
+ /**
248
+ * Build a gesture-layer controller. The hook-form of the `gesture` prop —
249
+ * reach for it when you need to drive multiple animated views from the same
250
+ * gesture state (a focus ring + state-layer halo + content tint all on one
251
+ * Pressable), which the prop-form's "animate the receiver's own style" model
252
+ * can't express.
253
+ *
254
+ * Returns four 0↔1 shared values (one per layer) and a handler bag to spread
255
+ * on a `Pressable`. The shared values are stable across renders — feed them
256
+ * into any number of `useAnimatedStyle` blocks anywhere in the tree.
257
+ *
258
+ * Transitions follow the same shape as the `gesture` prop's accompanying
259
+ * `transition`: pass a single `TransitionConfig` to use for every layer, or a
260
+ * `GestureLayerTransitions` map to give each layer its own. Layers without an
261
+ * explicit transition fall back to the library default spring.
262
+ *
263
+ * Reduced motion (via `<MotionConfig reducedMotion>`) collapses every
264
+ * transition to `no-animation` so state changes snap instead of interpolating
265
+ * — same behaviour the gesture prop applies.
266
+ *
267
+ * @example
268
+ * ```tsx
269
+ * import { useAnimatedStyle } from 'react-native-reanimated'
270
+ * import { useGesture } from '@onlynative/inertia'
271
+ *
272
+ * function Card() {
273
+ * const { pressed, focused, hovered, handlers } = useGesture({
274
+ * pressed: { type: 'timing', duration: 100 },
275
+ * hovered: { type: 'timing', duration: 150 },
276
+ * focused: { type: 'timing', duration: 200 },
277
+ * })
278
+ *
279
+ * const ringStyle = useAnimatedStyle(() => ({ opacity: focused.value }))
280
+ * const haloStyle = useAnimatedStyle(() => ({
281
+ * opacity: Math.max(
282
+ * hovered.value * 0.08,
283
+ * focused.value * 0.10,
284
+ * pressed.value * 0.10,
285
+ * ),
286
+ * }))
287
+ *
288
+ * return (
289
+ * <Pressable {...handlers}>
290
+ * <Animated.View style={ringStyle} />
291
+ * <Animated.View style={haloStyle} />
292
+ * </Pressable>
293
+ * )
294
+ * }
295
+ * ```
296
+ */
297
+ declare function useGesture(transition?: TransitionConfig | GestureLayerTransitions): UseGestureResult;
298
+
299
+ /**
300
+ * Create an animatable value owned by JS but readable from worklets.
301
+ *
302
+ * This is the escape-hatch primitive that the rest of the value-layer hooks
303
+ * (`useSpring`, `useTransform`, `useScroll`) compose against. It is a thin
304
+ * pass-through over Reanimated's `useSharedValue`: a `SharedValue<T>` with
305
+ * `.value` for direct reads/writes (UI-thread reads in worklets, JS-thread
306
+ * writes from event handlers / effects).
307
+ *
308
+ * We intentionally do not introduce a `MotionValue` wrapper class around the
309
+ * shared value. The simplest object that interops with `useAnimatedStyle`,
310
+ * `useDerivedValue`, and every other Reanimated API _is_ the shared value
311
+ * itself; adding a `{ get, set, value }` shell would force consumers to
312
+ * unwrap it at every Reanimated boundary and break worklet capture.
313
+ *
314
+ * Worklet read:
315
+ * ```ts
316
+ * const x = useMotionValue(0)
317
+ * useAnimatedStyle(() => ({ transform: [{ translateX: x.value }] }))
318
+ * ```
319
+ *
320
+ * JS write:
321
+ * ```ts
322
+ * onPress={() => { x.value = 100 }}
323
+ * ```
324
+ */
325
+ declare function useMotionValue<T extends number | string>(initial: T): SharedValue<T>;
326
+
327
+ /**
328
+ * Animate a shared value toward `target` with spring physics, using the
329
+ * library's react-spring vocabulary (`tension` / `friction` / `mass`).
330
+ *
331
+ * `target` may be a plain number or a `SharedValue<number>`. The plain-number
332
+ * path drives the spring from a JS `useEffect`, so the animation re-runs on
333
+ * every render where `target` changes. The shared-value path drives the
334
+ * spring from a Reanimated reaction on the UI thread, so values produced by
335
+ * gestures, scroll handlers, or other worklets flow through without bouncing
336
+ * back to JS.
337
+ *
338
+ * Both call sites end up at the same `withSpring` invocation; the split is
339
+ * just about which thread observes the source change.
340
+ */
341
+ declare function useSpring(target: number | SharedValue<number>, config?: SpringTransition): SharedValue<number>;
342
+
343
+ /**
344
+ * Extrapolation behavior at the edges of the input range. Mirrors
345
+ * Reanimated's enum so consumers don't need a separate import.
346
+ *
347
+ * - `'clamp'` (default) — output stays pinned at the first/last value
348
+ * outside the input range. Matches Framer Motion's default.
349
+ * - `'identity'` — return the input unchanged outside the range.
350
+ * - `'extend'` — continue the linear slope beyond the range.
351
+ */
352
+ type ExtrapolationMode = 'clamp' | 'identity' | 'extend';
353
+ interface UseTransformOptions {
354
+ extrapolateLeft?: ExtrapolationMode;
355
+ extrapolateRight?: ExtrapolationMode;
356
+ }
357
+ /**
358
+ * Derive a value from one or more shared values via a transformer worklet.
359
+ *
360
+ * ```ts
361
+ * const x = useMotionValue(0)
362
+ * const y = useMotionValue(0)
363
+ * const distance = useTransform(() => Math.sqrt(x.value ** 2 + y.value ** 2))
364
+ * ```
365
+ *
366
+ * The transformer must be a worklet (or a plain function we auto-wrap —
367
+ * see the easing wrapper for the rationale). It runs on the UI thread on
368
+ * every frame where any read shared value changes.
369
+ */
370
+ declare function useTransform<T>(transformer: () => T): SharedValue<T>;
371
+ /**
372
+ * Interpolate a numeric shared value onto a range of numbers or colors.
373
+ *
374
+ * ```ts
375
+ * const scroll = useMotionValue(0)
376
+ * const headerOpacity = useTransform(scroll, [0, 100], [1, 0])
377
+ * const headerColor = useTransform(scroll, [0, 100], ['#fff', '#000'])
378
+ * ```
379
+ *
380
+ * When `outputRange` is numeric, this maps to Reanimated's `interpolate`;
381
+ * when it's a tuple of color strings, it maps to `interpolateColor`. The
382
+ * input range must be monotonically increasing.
383
+ */
384
+ declare function useTransform(value: SharedValue<number>, inputRange: readonly number[], outputRange: readonly number[], options?: UseTransformOptions): SharedValue<number>;
385
+ declare function useTransform(value: SharedValue<number>, inputRange: readonly number[], outputRange: readonly string[], options?: UseTransformOptions): SharedValue<string>;
386
+
387
+ interface UseScrollResult {
388
+ /** Horizontal scroll offset in points. */
389
+ scrollX: SharedValue<number>;
390
+ /** Vertical scroll offset in points. */
391
+ scrollY: SharedValue<number>;
392
+ /**
393
+ * Handler to pass to a `Motion.ScrollView`'s `onScroll` prop (or any other
394
+ * Reanimated `Animated.ScrollView`). The handler is opaque to JS — it runs
395
+ * as a worklet — but the type narrows to the same shape RN's native
396
+ * `onScroll` prop expects so it composes cleanly.
397
+ */
398
+ onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
399
+ }
400
+ /**
401
+ * Track the scroll offset of a `Motion.ScrollView` as shared values.
402
+ *
403
+ * ```tsx
404
+ * const { scrollY, onScroll } = useScroll()
405
+ * const headerOpacity = useTransform(scrollY, [0, 100], [1, 0])
406
+ *
407
+ * return (
408
+ * <>
409
+ * <Motion.View animate={{ opacity: headerOpacity }} />
410
+ * <Motion.ScrollView onScroll={onScroll} scrollEventThrottle={16}>
411
+ * …
412
+ * </Motion.ScrollView>
413
+ * </>
414
+ * )
415
+ * ```
416
+ *
417
+ * Scroll events fire on the UI thread, so `scrollX` / `scrollY` are safe to
418
+ * read from any worklet (`useAnimatedStyle`, `useDerivedValue`,
419
+ * `useTransform`) without a JS-thread bounce.
420
+ *
421
+ * Remember to set `scrollEventThrottle={16}` on the `ScrollView` for 60Hz
422
+ * updates — RN's default is to dispatch on every event, which on iOS still
423
+ * means one per frame, but Android benefits from the explicit cap.
424
+ */
425
+ declare function useScroll(): UseScrollResult;
426
+
171
427
  /**
172
428
  * Build a controller for a variants map. The controller is the imperative
173
429
  * escape hatch — pass it to a Motion primitive via `controller={...}` and
@@ -181,4 +437,4 @@ declare function ensureWorkletEasing(easing: ((t: number) => number) | undefined
181
437
  */
182
438
  declare function useVariants<V extends Readonly<Record<string, object>>>(variants: V, initial?: keyof V & string): VariantController<keyof V & string>;
183
439
 
184
- export { AnimatableValue, Motion, MotionComponent, MotionConfig, type MotionConfigValue, Presence, type PresenceContextValue, type ReducedMotion, TransitionConfig, VariantController, createMotionComponent, ensureWorkletEasing, resolveAnimatableValue, resolveTransition, useMotionConfig, usePresence, useShouldReduceMotion, useVariants };
440
+ export { AnimatableValue, type ExtrapolationMode, Motion, MotionComponent, MotionConfig, type MotionConfigValue, Presence, type PresenceContextValue, type ReducedMotion, SpringTransition, TransitionConfig, type UseGestureHandlers, type UseGestureResult, type UseScrollResult, type UseTransformOptions, VariantController, createMotionComponent, ensureWorkletEasing, resolveAnimatableValue, resolveTransition, useAnimation, useGesture, useMotionConfig, useMotionValue, usePresence, useScroll, useShouldReduceMotion, useSpring, useTransform, useVariants };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentType, ReactNode } from 'react';
3
3
  import * as react_native from 'react-native';
4
- import { M as MotionComponent, A as AnimatableValue, T as TransitionConfig, V as VariantController } from './types-DAhX3fC2.js';
5
- export { a as AnimateStyle, b as AnimationCallbackInfo, D as DecayTransition, G as GestureSubStates, c as MotionProps, N as NoAnimationTransition, P as PerPropertyTransition, R as RepeatConfig, S as SequenceStep, d as SpringTransition, e as TimingTransition, f as Transition, g as VariantsMap } from './types-DAhX3fC2.js';
4
+ import { NativeSyntheticEvent, NativeScrollEvent } from 'react-native';
5
+ import { M as MotionComponent, A as AnimatableValue, T as TransitionConfig, G as GestureLayerTransitions, S as SpringTransition, V as VariantController } from './types-CjztO3RW.js';
6
+ export { a as AnimateStyle, b as AnimationCallbackInfo, D as DecayTransition, c as GestureSubStates, d as MotionProps, N as NoAnimationTransition, P as PerPropertyTransition, R as RepeatConfig, e as SequenceStep, f as TimingTransition, g as Transition, h as VariantsMap } from './types-CjztO3RW.js';
7
+ import { SharedValue } from 'react-native-reanimated';
6
8
  export { MotionImage } from './motion/Image.js';
7
9
  export { MotionPressable } from './motion/Pressable.js';
8
10
  export { MotionScrollView } from './motion/ScrollView.js';
@@ -168,6 +170,260 @@ declare function resolveAnimatableValue<V extends number | string>(value: Animat
168
170
  */
169
171
  declare function ensureWorkletEasing(easing: ((t: number) => number) | undefined): ((t: number) => number) | undefined;
170
172
 
173
+ /**
174
+ * Drive a `SharedValue<number>` toward `target` with **any** transition shape
175
+ * — spring, timing, decay, or no-animation. The general-purpose value-layer
176
+ * hook: reach for it when you need raw `useSharedValue + useEffect + withX`
177
+ * outside the declarative `animate` flow.
178
+ *
179
+ * Re-runs whenever `target` changes shape (`target` is in the dep array) or
180
+ * the transition signature changes (kept stable via JSON-style hashing).
181
+ * Reduced motion (via `<MotionConfig reducedMotion>`) collapses the
182
+ * transition to `no-animation` so the value snaps instead of interpolating.
183
+ *
184
+ * **Spring shorthand.** Prefer [`useSpring`](./useSpring) when you only want
185
+ * spring physics — it accepts the same `tension`/`friction`/`mass` config and
186
+ * also supports a `SharedValue<number>` as the target (UI-thread reactive
187
+ * source). `useAnimation` is JS-thread-driven only.
188
+ *
189
+ * **Loops.** Repeat is part of `TransitionConfig` and flows through
190
+ * untouched — `useAnimation(1, { type: 'timing', duration: 1800, repeat: {
191
+ * count: 'infinite', alternate: false } })` produces an indeterminate-style
192
+ * progress driver.
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * // Toggle progress (Switch / Checkbox / Radio).
197
+ * const progress = useAnimation(isChecked ? 1 : 0, {
198
+ * type: 'spring',
199
+ * tension: 380,
200
+ * friction: 33,
201
+ * })
202
+ *
203
+ * // Float a TextField label when the value becomes non-empty.
204
+ * const floated = useAnimation(hasValue ? 1 : 0, {
205
+ * type: 'timing',
206
+ * duration: 150,
207
+ * })
208
+ *
209
+ * // Indeterminate progress slider (loops forever, snaps back).
210
+ * const slide = useAnimation(1, {
211
+ * type: 'timing',
212
+ * duration: 1800,
213
+ * repeat: { count: 'infinite', alternate: false },
214
+ * })
215
+ * ```
216
+ */
217
+ declare function useAnimation(target: number, transition?: TransitionConfig): SharedValue<number>;
218
+
219
+ /**
220
+ * Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
221
+ * shared values returned alongside.
222
+ *
223
+ * Hover handlers use `Pressable`'s own `onHoverIn` / `onHoverOut` names (web
224
+ * only — no-ops on native). `onFocus` consults `isFocusVisible()` before
225
+ * raising the keyboard-only `focusVisible` layer; `focused` always raises.
226
+ */
227
+ interface UseGestureHandlers {
228
+ onPressIn: () => void;
229
+ onPressOut: () => void;
230
+ onHoverIn: () => void;
231
+ onHoverOut: () => void;
232
+ onFocus: () => void;
233
+ onBlur: () => void;
234
+ }
235
+ interface UseGestureResult {
236
+ /** 0↔1 progress for the pressed layer. */
237
+ pressed: SharedValue<number>;
238
+ /** 0↔1 progress for the focused layer (any focus modality). */
239
+ focused: SharedValue<number>;
240
+ /** 0↔1 progress for the focusVisible layer (keyboard focus only). */
241
+ focusVisible: SharedValue<number>;
242
+ /** 0↔1 progress for the hovered layer (web only — stays at 0 on native). */
243
+ hovered: SharedValue<number>;
244
+ /** Handlers to spread on the receiving `Pressable`. */
245
+ handlers: UseGestureHandlers;
246
+ }
247
+ /**
248
+ * Build a gesture-layer controller. The hook-form of the `gesture` prop —
249
+ * reach for it when you need to drive multiple animated views from the same
250
+ * gesture state (a focus ring + state-layer halo + content tint all on one
251
+ * Pressable), which the prop-form's "animate the receiver's own style" model
252
+ * can't express.
253
+ *
254
+ * Returns four 0↔1 shared values (one per layer) and a handler bag to spread
255
+ * on a `Pressable`. The shared values are stable across renders — feed them
256
+ * into any number of `useAnimatedStyle` blocks anywhere in the tree.
257
+ *
258
+ * Transitions follow the same shape as the `gesture` prop's accompanying
259
+ * `transition`: pass a single `TransitionConfig` to use for every layer, or a
260
+ * `GestureLayerTransitions` map to give each layer its own. Layers without an
261
+ * explicit transition fall back to the library default spring.
262
+ *
263
+ * Reduced motion (via `<MotionConfig reducedMotion>`) collapses every
264
+ * transition to `no-animation` so state changes snap instead of interpolating
265
+ * — same behaviour the gesture prop applies.
266
+ *
267
+ * @example
268
+ * ```tsx
269
+ * import { useAnimatedStyle } from 'react-native-reanimated'
270
+ * import { useGesture } from '@onlynative/inertia'
271
+ *
272
+ * function Card() {
273
+ * const { pressed, focused, hovered, handlers } = useGesture({
274
+ * pressed: { type: 'timing', duration: 100 },
275
+ * hovered: { type: 'timing', duration: 150 },
276
+ * focused: { type: 'timing', duration: 200 },
277
+ * })
278
+ *
279
+ * const ringStyle = useAnimatedStyle(() => ({ opacity: focused.value }))
280
+ * const haloStyle = useAnimatedStyle(() => ({
281
+ * opacity: Math.max(
282
+ * hovered.value * 0.08,
283
+ * focused.value * 0.10,
284
+ * pressed.value * 0.10,
285
+ * ),
286
+ * }))
287
+ *
288
+ * return (
289
+ * <Pressable {...handlers}>
290
+ * <Animated.View style={ringStyle} />
291
+ * <Animated.View style={haloStyle} />
292
+ * </Pressable>
293
+ * )
294
+ * }
295
+ * ```
296
+ */
297
+ declare function useGesture(transition?: TransitionConfig | GestureLayerTransitions): UseGestureResult;
298
+
299
+ /**
300
+ * Create an animatable value owned by JS but readable from worklets.
301
+ *
302
+ * This is the escape-hatch primitive that the rest of the value-layer hooks
303
+ * (`useSpring`, `useTransform`, `useScroll`) compose against. It is a thin
304
+ * pass-through over Reanimated's `useSharedValue`: a `SharedValue<T>` with
305
+ * `.value` for direct reads/writes (UI-thread reads in worklets, JS-thread
306
+ * writes from event handlers / effects).
307
+ *
308
+ * We intentionally do not introduce a `MotionValue` wrapper class around the
309
+ * shared value. The simplest object that interops with `useAnimatedStyle`,
310
+ * `useDerivedValue`, and every other Reanimated API _is_ the shared value
311
+ * itself; adding a `{ get, set, value }` shell would force consumers to
312
+ * unwrap it at every Reanimated boundary and break worklet capture.
313
+ *
314
+ * Worklet read:
315
+ * ```ts
316
+ * const x = useMotionValue(0)
317
+ * useAnimatedStyle(() => ({ transform: [{ translateX: x.value }] }))
318
+ * ```
319
+ *
320
+ * JS write:
321
+ * ```ts
322
+ * onPress={() => { x.value = 100 }}
323
+ * ```
324
+ */
325
+ declare function useMotionValue<T extends number | string>(initial: T): SharedValue<T>;
326
+
327
+ /**
328
+ * Animate a shared value toward `target` with spring physics, using the
329
+ * library's react-spring vocabulary (`tension` / `friction` / `mass`).
330
+ *
331
+ * `target` may be a plain number or a `SharedValue<number>`. The plain-number
332
+ * path drives the spring from a JS `useEffect`, so the animation re-runs on
333
+ * every render where `target` changes. The shared-value path drives the
334
+ * spring from a Reanimated reaction on the UI thread, so values produced by
335
+ * gestures, scroll handlers, or other worklets flow through without bouncing
336
+ * back to JS.
337
+ *
338
+ * Both call sites end up at the same `withSpring` invocation; the split is
339
+ * just about which thread observes the source change.
340
+ */
341
+ declare function useSpring(target: number | SharedValue<number>, config?: SpringTransition): SharedValue<number>;
342
+
343
+ /**
344
+ * Extrapolation behavior at the edges of the input range. Mirrors
345
+ * Reanimated's enum so consumers don't need a separate import.
346
+ *
347
+ * - `'clamp'` (default) — output stays pinned at the first/last value
348
+ * outside the input range. Matches Framer Motion's default.
349
+ * - `'identity'` — return the input unchanged outside the range.
350
+ * - `'extend'` — continue the linear slope beyond the range.
351
+ */
352
+ type ExtrapolationMode = 'clamp' | 'identity' | 'extend';
353
+ interface UseTransformOptions {
354
+ extrapolateLeft?: ExtrapolationMode;
355
+ extrapolateRight?: ExtrapolationMode;
356
+ }
357
+ /**
358
+ * Derive a value from one or more shared values via a transformer worklet.
359
+ *
360
+ * ```ts
361
+ * const x = useMotionValue(0)
362
+ * const y = useMotionValue(0)
363
+ * const distance = useTransform(() => Math.sqrt(x.value ** 2 + y.value ** 2))
364
+ * ```
365
+ *
366
+ * The transformer must be a worklet (or a plain function we auto-wrap —
367
+ * see the easing wrapper for the rationale). It runs on the UI thread on
368
+ * every frame where any read shared value changes.
369
+ */
370
+ declare function useTransform<T>(transformer: () => T): SharedValue<T>;
371
+ /**
372
+ * Interpolate a numeric shared value onto a range of numbers or colors.
373
+ *
374
+ * ```ts
375
+ * const scroll = useMotionValue(0)
376
+ * const headerOpacity = useTransform(scroll, [0, 100], [1, 0])
377
+ * const headerColor = useTransform(scroll, [0, 100], ['#fff', '#000'])
378
+ * ```
379
+ *
380
+ * When `outputRange` is numeric, this maps to Reanimated's `interpolate`;
381
+ * when it's a tuple of color strings, it maps to `interpolateColor`. The
382
+ * input range must be monotonically increasing.
383
+ */
384
+ declare function useTransform(value: SharedValue<number>, inputRange: readonly number[], outputRange: readonly number[], options?: UseTransformOptions): SharedValue<number>;
385
+ declare function useTransform(value: SharedValue<number>, inputRange: readonly number[], outputRange: readonly string[], options?: UseTransformOptions): SharedValue<string>;
386
+
387
+ interface UseScrollResult {
388
+ /** Horizontal scroll offset in points. */
389
+ scrollX: SharedValue<number>;
390
+ /** Vertical scroll offset in points. */
391
+ scrollY: SharedValue<number>;
392
+ /**
393
+ * Handler to pass to a `Motion.ScrollView`'s `onScroll` prop (or any other
394
+ * Reanimated `Animated.ScrollView`). The handler is opaque to JS — it runs
395
+ * as a worklet — but the type narrows to the same shape RN's native
396
+ * `onScroll` prop expects so it composes cleanly.
397
+ */
398
+ onScroll: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
399
+ }
400
+ /**
401
+ * Track the scroll offset of a `Motion.ScrollView` as shared values.
402
+ *
403
+ * ```tsx
404
+ * const { scrollY, onScroll } = useScroll()
405
+ * const headerOpacity = useTransform(scrollY, [0, 100], [1, 0])
406
+ *
407
+ * return (
408
+ * <>
409
+ * <Motion.View animate={{ opacity: headerOpacity }} />
410
+ * <Motion.ScrollView onScroll={onScroll} scrollEventThrottle={16}>
411
+ * …
412
+ * </Motion.ScrollView>
413
+ * </>
414
+ * )
415
+ * ```
416
+ *
417
+ * Scroll events fire on the UI thread, so `scrollX` / `scrollY` are safe to
418
+ * read from any worklet (`useAnimatedStyle`, `useDerivedValue`,
419
+ * `useTransform`) without a JS-thread bounce.
420
+ *
421
+ * Remember to set `scrollEventThrottle={16}` on the `ScrollView` for 60Hz
422
+ * updates — RN's default is to dispatch on every event, which on iOS still
423
+ * means one per frame, but Android benefits from the explicit cap.
424
+ */
425
+ declare function useScroll(): UseScrollResult;
426
+
171
427
  /**
172
428
  * Build a controller for a variants map. The controller is the imperative
173
429
  * escape hatch — pass it to a Motion primitive via `controller={...}` and
@@ -181,4 +437,4 @@ declare function ensureWorkletEasing(easing: ((t: number) => number) | undefined
181
437
  */
182
438
  declare function useVariants<V extends Readonly<Record<string, object>>>(variants: V, initial?: keyof V & string): VariantController<keyof V & string>;
183
439
 
184
- export { AnimatableValue, Motion, MotionComponent, MotionConfig, type MotionConfigValue, Presence, type PresenceContextValue, type ReducedMotion, TransitionConfig, VariantController, createMotionComponent, ensureWorkletEasing, resolveAnimatableValue, resolveTransition, useMotionConfig, usePresence, useShouldReduceMotion, useVariants };
440
+ export { AnimatableValue, type ExtrapolationMode, Motion, MotionComponent, MotionConfig, type MotionConfigValue, Presence, type PresenceContextValue, type ReducedMotion, SpringTransition, TransitionConfig, type UseGestureHandlers, type UseGestureResult, type UseScrollResult, type UseTransformOptions, VariantController, createMotionComponent, ensureWorkletEasing, resolveAnimatableValue, resolveTransition, useAnimation, useGesture, useMotionConfig, useMotionValue, usePresence, useScroll, useShouldReduceMotion, useSpring, useTransform, useVariants };