@onlynative/inertia 0.0.1-alpha.7 → 0.0.1-alpha.9
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/README.md +1 -1
- package/dist/gestureLayer/index.d.mts +119 -0
- package/dist/gestureLayer/index.d.ts +119 -0
- package/dist/gestureLayer/index.js +346 -0
- package/dist/gestureLayer/index.js.map +1 -0
- package/dist/gestureLayer/index.mjs +344 -0
- package/dist/gestureLayer/index.mjs.map +1 -0
- package/dist/index.d.mts +114 -74
- package/dist/index.d.ts +114 -74
- package/dist/index.js +388 -1542
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +388 -1545
- 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 +244 -1462
- package/dist/motion/Image.js.map +1 -1
- package/dist/motion/Image.mjs +247 -1465
- 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 +244 -1462
- package/dist/motion/Pressable.js.map +1 -1
- package/dist/motion/Pressable.mjs +247 -1465
- 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 +244 -1462
- package/dist/motion/ScrollView.js.map +1 -1
- package/dist/motion/ScrollView.mjs +247 -1465
- 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 +244 -1462
- package/dist/motion/Text.js.map +1 -1
- package/dist/motion/Text.mjs +247 -1465
- 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 +244 -1462
- package/dist/motion/View.js.map +1 -1
- package/dist/motion/View.mjs +247 -1465
- package/dist/motion/View.mjs.map +1 -1
- package/dist/touch/index.d.mts +146 -0
- package/dist/touch/index.d.ts +146 -0
- package/dist/touch/index.js +166 -0
- package/dist/touch/index.js.map +1 -0
- package/dist/touch/index.mjs +164 -0
- package/dist/touch/index.mjs.map +1 -0
- package/dist/{types-NmNeJjo1.d.mts → types-cU43dEmH.d.mts} +64 -17
- package/dist/{types-NmNeJjo1.d.ts → types-cU43dEmH.d.ts} +64 -17
- package/dist/useGesture-B7A_1DVg.d.ts +84 -0
- package/dist/useGesture-cimMrzC1.d.mts +84 -0
- package/jest-setup.js +4 -0
- package/llms.txt +12 -3
- package/package.json +22 -2
- package/src/__type-tests__/variants.test-d.tsx +67 -0
- package/src/gestureLayer/index.ts +21 -0
- package/src/gestureLayer/useGestureLayer.ts +285 -0
- package/src/index.ts +7 -0
- package/src/layout/index.ts +15 -0
- package/src/layout/sharedRegistry.ts +111 -0
- package/src/layout/useSharedLayout.ts +289 -0
- package/src/motion/createMotionComponent.tsx +123 -37
- package/src/motion/installCheck.ts +7 -11
- package/src/touch/index.ts +18 -0
- package/src/touch/useTouchDrag.ts +289 -0
- package/src/types.ts +79 -20
- package/src/values/index.ts +11 -0
- package/src/values/useBooleanSpring.ts +33 -0
- package/src/values/useColorTransition.ts +72 -0
- package/src/values/useShadow.ts +116 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/transitions/spring.ts","../../src/transitions/runtime.ts","../../src/touch/useTouchDrag.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["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 withSpring,\n withTiming,\n} from 'react-native-reanimated'\nimport { springToReanimated } from './spring'\nimport { type TransitionConfig } from '../types'\n\nconst DEFAULT_TIMING_DURATION = 250\n\n/**\n * Worklet-safe single-step animation builder. Mirrors a subset of\n * `resolveTransition` for the UI-thread path where the transition config is\n * picked at gesture-release time, not at render time.\n *\n * Supported: spring / timing / decay / no-animation, single-step only.\n * Not supported: sequences, top-level repeat, easing-function\n * auto-worklet-wrapping (pass an already-worklet easing if you need a custom\n * one — most release transitions don't).\n *\n * Use this from gesture worklets (`useDrag` / `usePan` release callbacks, or\n * any custom `Gesture.Pan().onEnd(() => ...)` worklet) to animate a shared\n * value with an Inertia transition without the JS round-trip that would lose\n * the release velocity.\n *\n * For decay transitions, `toValue` is ignored — decay decelerates from the\n * SV's current position via its own physics. Pass `0` if you don't have one.\n */\nexport function buildReleaseAnimation(\n transition: TransitionConfig,\n toValue: number,\n): unknown {\n 'worklet'\n if (transition.type === 'no-animation') return toValue\n if (transition.type === 'decay') {\n const cfg: {\n velocity: number\n deceleration?: number\n clamp?: [number, number]\n } = { velocity: transition.velocity ?? 0 }\n if (transition.deceleration !== undefined) {\n cfg.deceleration = transition.deceleration\n }\n if (transition.clamp !== undefined) cfg.clamp = transition.clamp\n return withDecay(cfg)\n }\n if (transition.type === 'timing') {\n // Reanimated 4's `Easing.bezier(...)` returns an `EasingFunctionFactory`\n // rather than the function itself. Unwrap inline so consumers calling\n // `buildReleaseAnimation` from a gesture worklet don't have to.\n const e = transition.easing\n const easingFn =\n e && typeof e === 'object' && 'factory' in e\n ? e.factory()\n : (e ?? Easing.inOut(Easing.ease))\n return withTiming(toValue, {\n duration: transition.duration ?? DEFAULT_TIMING_DURATION,\n easing: easingFn,\n })\n }\n return withSpring(toValue, springToReanimated(transition))\n}\n","import { useMemo } from 'react'\nimport {\n PanResponder,\n type PanResponderGestureState,\n type PanResponderInstance,\n} from 'react-native'\nimport {\n useAnimatedStyle,\n useSharedValue,\n type SharedValue,\n} from 'react-native-reanimated'\nimport { buildReleaseAnimation } from '../transitions'\nimport type { TransitionConfig } from '../types'\n\n/**\n * Same drag-result shape as `useDrag` from `@onlynative/inertia-gestures`,\n * minus the `gesture` field (PanResponder spreads handlers, no\n * `<GestureDetector>` wrapper). The shared values + animatedStyle are\n * interchangeable across both hooks; consumers can swap implementations\n * without touching their `useAnimatedStyle` consumers.\n */\nexport interface UseTouchDragResult {\n /** Spread onto a `View` / `Pressable` to install the pan responder. */\n panHandlers: PanResponderInstance['panHandlers']\n /** Stable animated `transform` style. */\n animatedStyle: ReturnType<typeof useAnimatedStyle>\n /** Live x translation, persistent across gestures. */\n dragX: SharedValue<number>\n /** Live y translation, persistent across gestures. */\n dragY: SharedValue<number>\n /** True while the gesture is active. */\n isDragging: SharedValue<boolean>\n}\n\n/**\n * Release transition shape for PanResponder's JS-thread `onRelease`. Mirrors\n * the gesture-handler adapter's `ReleaseTransition` but with `to` typed as\n * required for spring/timing/no-animation (decay omits it).\n */\nexport type TouchReleaseTransition =\n | (TransitionConfig & { type: 'spring'; to: number })\n | (TransitionConfig & { type: 'timing'; to: number })\n | (TransitionConfig & { type: 'decay' })\n | (TransitionConfig & { type: 'no-animation'; to: number })\n\nexport interface TouchReleaseInfo {\n x: number\n y: number\n velocity: { x: number; y: number }\n}\n\nexport interface TouchReleaseResult {\n x?: TouchReleaseTransition\n y?: TouchReleaseTransition\n}\n\nexport interface UseTouchDragOptions {\n /**\n * Restrict the drag to one axis. Defaults to `'both'`. When `'x'` is set\n * the y-axis shared value never updates (and vice versa); velocity is\n * still reported on both for `onDragEnd`.\n */\n axis?: 'x' | 'y' | 'both'\n /**\n * Travel bounds (px from resting). Each side is independently optional.\n * Out-of-bounds values clamp to the limit unless `elastic > 0`.\n */\n constraints?: {\n left?: number\n right?: number\n top?: number\n bottom?: number\n }\n /**\n * Rubber-band coefficient applied to overshoot past `constraints`. `0`\n * (default) hard-clamps; `0.2`-`0.4` is a typical Framer-Motion feel.\n */\n elastic?: number\n /**\n * Fires when the user starts dragging. JS thread.\n */\n onDragStart?: () => void\n /**\n * Fires when the user releases or the gesture terminates. JS thread.\n *\n * Velocity is in px/sec to match the `@onlynative/inertia-gestures` API\n * (PanResponder's native `vx` / `vy` are px/ms; the hook normalizes).\n */\n onDragEnd?: (info: TouchReleaseInfo) => void\n /**\n * Optional release-animation callback. Return per-axis release transitions\n * to animate the SVs to a settled position via Inertia's transition\n * resolver — spring snap-to-tick, decay with bounds, timing settle.\n *\n * Unlike the gesture-handler version, this callback runs on the **JS\n * thread** (PanResponder is JS-only). The returned transitions still drive\n * UI-thread animations via Reanimated — only the decision logic is JS-side.\n */\n onRelease?: (info: TouchReleaseInfo) => TouchReleaseResult | void\n}\n\n/**\n * PanResponder-backed drag hook. Pointer-equivalent of `useDrag` from\n * `@onlynative/inertia-gestures`, with two differences:\n *\n * 1. No `react-native-gesture-handler` peer dep required — PanResponder is\n * built into React Native, so this lives in core.\n * 2. Returns `panHandlers` to spread on a `View` / `Pressable` instead of\n * a `gesture` to plug into `<GestureDetector>`.\n *\n * Use this when:\n * - You need keyboard a11y alongside drag (a slider with arrow-key step,\n * a scrollbar with `PageUp` / `PageDown`). PanResponder composes\n * cleanly with `onKeyDown`; gesture-handler doesn't surface keyboard.\n * - You don't want to take `react-native-gesture-handler` as a dependency\n * (smaller bundle, simpler install).\n *\n * Skip this when:\n * - You're already using `react-native-gesture-handler` elsewhere (use\n * `useDrag` from `@onlynative/inertia-gestures` for consistency and\n * better worklet-thread fidelity on release velocity).\n * - You need momentum semantics like the gesture-handler `usePan` —\n * PanResponder's release velocity is JS-thread and slightly less precise.\n *\n * @example\n * ```tsx\n * import { useTouchDrag } from '@onlynative/inertia/touch'\n *\n * function Slider({ ticks }: { ticks: number[] }) {\n * const drag = useTouchDrag({\n * axis: 'x',\n * constraints: { left: 0, right: 280 },\n * onRelease: (e) => {\n * const snap = nearestTick(e.x, ticks)\n * return { x: { type: 'spring', to: snap, velocity: e.velocity.x } }\n * },\n * })\n *\n * return (\n * <Motion.View\n * style={[styles.thumb, drag.animatedStyle]}\n * {...drag.panHandlers}\n * />\n * )\n * }\n * ```\n */\nexport function useTouchDrag(\n options: UseTouchDragOptions = {},\n): UseTouchDragResult {\n const { axis = 'both', constraints, elastic = 0 } = options\n\n const dragX = useSharedValue(0)\n const dragY = useSharedValue(0)\n const startX = useSharedValue(0)\n const startY = useSharedValue(0)\n const isDragging = useSharedValue(false)\n\n // Snapshot scalars into local consts so the responder callbacks close over\n // primitives, not the `options` literal — a fresh `options` each render\n // would otherwise force the PanResponder identity to change.\n const lockX = axis !== 'y'\n const lockY = axis !== 'x'\n const left = constraints?.left\n const right = constraints?.right\n const top = constraints?.top\n const bottom = constraints?.bottom\n const elasticCoef = elastic\n const { onDragStart, onDragEnd, onRelease } = options\n\n const responder = useMemo(\n () => buildResponder(),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n lockX,\n lockY,\n left,\n right,\n top,\n bottom,\n elasticCoef,\n onDragStart,\n onDragEnd,\n onRelease,\n ],\n )\n\n // Hoisted out of the inline `useMemo` factory to keep the dep list readable\n // and avoid re-declaring closure helpers each render.\n function buildResponder(): PanResponderInstance {\n const handleEnd = (g: PanResponderGestureState) => {\n isDragging.value = false\n const x = dragX.value\n const y = dragY.value\n // PanResponder velocity is px/ms; multiply to match the\n // `@onlynative/inertia-gestures` API (px/sec from gesture-handler).\n const vx = g.vx * 1000\n const vy = g.vy * 1000\n if (onRelease) {\n const result = onRelease({ x, y, velocity: { x: vx, y: vy } })\n if (result) {\n if (result.x && lockX) {\n const toX = 'to' in result.x ? result.x.to : x\n dragX.value = buildReleaseAnimation(\n result.x,\n toX,\n ) as unknown as number\n }\n if (result.y && lockY) {\n const toY = 'to' in result.y ? result.y.to : y\n dragY.value = buildReleaseAnimation(\n result.y,\n toY,\n ) as unknown as number\n }\n }\n }\n if (onDragEnd) onDragEnd({ x, y, velocity: { x: vx, y: vy } })\n }\n\n return PanResponder.create({\n // Always claim the start so taps that turn into drags don't slip\n // through to a parent ScrollView. Consumers can compose their own\n // capture predicates by wrapping the returned `panHandlers`.\n onStartShouldSetPanResponder: () => true,\n onMoveShouldSetPanResponder: () => true,\n onPanResponderGrant: () => {\n startX.value = dragX.value\n startY.value = dragY.value\n isDragging.value = true\n if (onDragStart) onDragStart()\n },\n onPanResponderMove: (_e, g) => {\n if (lockX) {\n dragX.value = applyBounds(\n startX.value + g.dx,\n left,\n right,\n elasticCoef,\n )\n }\n if (lockY) {\n dragY.value = applyBounds(\n startY.value + g.dy,\n top,\n bottom,\n elasticCoef,\n )\n }\n },\n onPanResponderRelease: (_e, g) => handleEnd(g),\n onPanResponderTerminate: (_e, g) => handleEnd(g),\n })\n }\n\n const animatedStyle = useAnimatedStyle(() => ({\n transform: [{ translateX: dragX.value }, { translateY: dragY.value }],\n }))\n\n return {\n panHandlers: responder.panHandlers,\n animatedStyle,\n dragX,\n dragY,\n isDragging,\n }\n}\n\n/**\n * Clamp `value` to `[min, max]`. When `elastic > 0` the overshoot past a\n * bound is scaled by `elastic`, giving a rubber-band feel. `min` / `max`\n * may be `undefined` to leave that side unbounded.\n *\n * JS-thread (PanResponder callbacks are JS, not worklets).\n */\nfunction applyBounds(\n value: number,\n min: number | undefined,\n max: number | undefined,\n elastic: number,\n): number {\n if (min !== undefined && value < min) {\n return elastic > 0 ? min + (value - min) * elastic : min\n }\n if (max !== undefined && value > max) {\n return elastic > 0 ? max + (value - max) * elastic : max\n }\n return value\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
1
|
+
import { ComponentType, ComponentProps, Ref, ReactElement } from 'react';
|
|
2
2
|
import { StyleProp } from 'react-native';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -210,8 +210,15 @@ interface VariantController<K extends string = string> {
|
|
|
210
210
|
}
|
|
211
211
|
/**
|
|
212
212
|
* Props injected onto every Motion primitive.
|
|
213
|
+
*
|
|
214
|
+
* The second type parameter `V` is the concrete `variants` map. It is inferred
|
|
215
|
+
* from the `variants` prop at each JSX use (see `MotionComponent`), which is
|
|
216
|
+
* what lets `animate` narrow to the variant key union and reject typos. When
|
|
217
|
+
* no `variants` prop is passed, `V` falls back to `VariantsMap<C>` — whose key
|
|
218
|
+
* type is the open `string`, so `animate` still accepts any string and nothing
|
|
219
|
+
* regresses for the variant-less case.
|
|
213
220
|
*/
|
|
214
|
-
interface MotionProps<C> {
|
|
221
|
+
interface MotionProps<C, V extends VariantsMap<C> = VariantsMap<C>> {
|
|
215
222
|
/**
|
|
216
223
|
* Initial values applied on mount. Read once on mount and intentionally
|
|
217
224
|
* non-reactive — to reset after a state change, change the component `key`,
|
|
@@ -222,10 +229,11 @@ interface MotionProps<C> {
|
|
|
222
229
|
initial?: AnimateStyle<C> | false;
|
|
223
230
|
/**
|
|
224
231
|
* The animation target. A style object, a variant key (when `variants` is
|
|
225
|
-
* supplied), or an array of sequence steps.
|
|
226
|
-
*
|
|
232
|
+
* supplied), or an array of sequence steps. When `variants` is set, the
|
|
233
|
+
* string form is narrowed to the map's keys, so a key typo is a compile
|
|
234
|
+
* error and the keys autocomplete — no `as const` required.
|
|
227
235
|
*/
|
|
228
|
-
animate?: AnimateStyle<C> | string;
|
|
236
|
+
animate?: AnimateStyle<C> | (keyof V & string);
|
|
229
237
|
/**
|
|
230
238
|
* Values applied while the component exits via `<Presence>`.
|
|
231
239
|
*/
|
|
@@ -234,13 +242,13 @@ interface MotionProps<C> {
|
|
|
234
242
|
* Named animation states. With `variants` set, `animate` accepts a key from
|
|
235
243
|
* this map.
|
|
236
244
|
*/
|
|
237
|
-
variants?:
|
|
245
|
+
variants?: V;
|
|
238
246
|
/**
|
|
239
247
|
* Imperative controller from `useVariants(...)`. When supplied, `animate`
|
|
240
248
|
* is read from `controller.current` and re-applied whenever the controller
|
|
241
249
|
* transitions. `animate` and `controller` should not both be set.
|
|
242
250
|
*/
|
|
243
|
-
controller?: VariantController
|
|
251
|
+
controller?: VariantController<keyof V & string>;
|
|
244
252
|
/**
|
|
245
253
|
* Gesture-driven sub-states (`pressed`, `focused`, `focusVisible`,
|
|
246
254
|
* `hovered`). When omitted, no handlers are mounted on the underlying
|
|
@@ -269,11 +277,34 @@ interface MotionProps<C> {
|
|
|
269
277
|
* — decay is downgraded to spring (no clear target). Reduced motion gates
|
|
270
278
|
* the prop the same way it gates `animate`.
|
|
271
279
|
*
|
|
272
|
-
* `layoutId`
|
|
273
|
-
*
|
|
274
|
-
*
|
|
280
|
+
* `layoutId` (below) is a related but distinct mechanism for shared
|
|
281
|
+
* element transitions across screens — `layout` animates this element's
|
|
282
|
+
* own layout changes, `layoutId` animates from a different element's
|
|
283
|
+
* last measured rect to this element's current rect.
|
|
275
284
|
*/
|
|
276
285
|
layout?: boolean | TransitionConfig;
|
|
286
|
+
/**
|
|
287
|
+
* Shared-element transition id. When a Motion primitive with `layoutId`
|
|
288
|
+
* unmounts, its last on-screen rect is recorded under that id; the next
|
|
289
|
+
* mount of any Motion primitive with the same id animates from the
|
|
290
|
+
* recorded rect to its natural position via a FLIP transform stack.
|
|
291
|
+
*
|
|
292
|
+
* Reanimated 4 removed the `sharedTransitionTag` API — `layoutId` is the
|
|
293
|
+
* Inertia-side measure-based replacement. Rects are recorded in
|
|
294
|
+
* parent-relative coordinates (from `onLayout`), which composes when the
|
|
295
|
+
* source and target screens share an outer content container (the common
|
|
296
|
+
* stack-navigator case); nested-parent layouts need the v2
|
|
297
|
+
* window-coordinate path.
|
|
298
|
+
*
|
|
299
|
+
* The same `transition` prop drives the FLIP animation (spring by
|
|
300
|
+
* default; `'timing'` honored; `'decay'` downgrades to spring; reduced
|
|
301
|
+
* motion skips the transition). Out of scope for the first iteration:
|
|
302
|
+
* style-prop interpolation (border radius, colors, etc.) — only the
|
|
303
|
+
* rect-to-rect transform is animated. Two simultaneously-mounted
|
|
304
|
+
* primitives sharing the same `layoutId` are undefined behavior; pick a
|
|
305
|
+
* primitive per id at a time.
|
|
306
|
+
*/
|
|
307
|
+
layoutId?: string;
|
|
277
308
|
/**
|
|
278
309
|
* Fired once per logical animation completion. See `AnimationCallbackInfo`
|
|
279
310
|
* for the payload shape — transform parents fire once, not per axis.
|
|
@@ -281,12 +312,28 @@ interface MotionProps<C> {
|
|
|
281
312
|
onAnimationEnd?: (info: AnimationCallbackInfo<AnimateStyle<C>>) => void;
|
|
282
313
|
}
|
|
283
314
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* animated style) with the Motion
|
|
315
|
+
* Props of a Motion primitive for a given underlying component `C` and a
|
|
316
|
+
* concrete variants map `V`: the component's own props (minus `style`, which
|
|
317
|
+
* we replace with an animated style) intersected with the Motion props.
|
|
287
318
|
*/
|
|
288
|
-
type
|
|
289
|
-
style?:
|
|
290
|
-
|
|
319
|
+
type MotionComponentProps<C extends ComponentType<any>, V extends VariantsMap<ComponentProps<C>> = VariantsMap<ComponentProps<C>>> = Omit<ComponentProps<C>, 'style'> & MotionProps<ComponentProps<C>, V> & {
|
|
320
|
+
style?: ComponentProps<C>['style'];
|
|
321
|
+
ref?: Ref<unknown>;
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* The component type produced by `createMotionComponent`.
|
|
325
|
+
*
|
|
326
|
+
* It is a **generic call signature**, not a plain `ComponentType`: the variant
|
|
327
|
+
* map `V` is inferred from the `variants` prop at each JSX use. That inference
|
|
328
|
+
* is what narrows `animate`'s string form to the variant keys, so
|
|
329
|
+
* `<Motion.View variants={{ open, closed }} animate="opne" />` is a compile
|
|
330
|
+
* error and `open` / `closed` autocomplete. With no `variants` prop, `V` falls
|
|
331
|
+
* back to the open `VariantsMap`, so `animate` still accepts any string and the
|
|
332
|
+
* variant-less call site is unchanged.
|
|
333
|
+
*/
|
|
334
|
+
interface MotionComponent<C extends ComponentType<any>> {
|
|
335
|
+
<V extends VariantsMap<ComponentProps<C>> = VariantsMap<ComponentProps<C>>>(props: MotionComponentProps<C, V>): ReactElement | null;
|
|
336
|
+
displayName?: string;
|
|
337
|
+
}
|
|
291
338
|
|
|
292
|
-
export type { AnimatableValue as A, DecayTransition as D, EasingInput as E,
|
|
339
|
+
export type { AnimatableValue as A, DecayTransition as D, EasingInput as E, GestureSubStates as G, MotionComponent as M, NoAnimationTransition as N, PerPropertyTransition as P, RepeatConfig as R, SpringTransition as S, TransitionConfig as T, VariantController as V, AnimateStyle as a, AnimationCallbackInfo as b, MotionProps as c, SequenceStep as d, TimingTransition as e, Transition as f, VariantsMap as g, GestureLayerTransitions as h };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
1
|
+
import { ComponentType, ComponentProps, Ref, ReactElement } from 'react';
|
|
2
2
|
import { StyleProp } from 'react-native';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -210,8 +210,15 @@ interface VariantController<K extends string = string> {
|
|
|
210
210
|
}
|
|
211
211
|
/**
|
|
212
212
|
* Props injected onto every Motion primitive.
|
|
213
|
+
*
|
|
214
|
+
* The second type parameter `V` is the concrete `variants` map. It is inferred
|
|
215
|
+
* from the `variants` prop at each JSX use (see `MotionComponent`), which is
|
|
216
|
+
* what lets `animate` narrow to the variant key union and reject typos. When
|
|
217
|
+
* no `variants` prop is passed, `V` falls back to `VariantsMap<C>` — whose key
|
|
218
|
+
* type is the open `string`, so `animate` still accepts any string and nothing
|
|
219
|
+
* regresses for the variant-less case.
|
|
213
220
|
*/
|
|
214
|
-
interface MotionProps<C> {
|
|
221
|
+
interface MotionProps<C, V extends VariantsMap<C> = VariantsMap<C>> {
|
|
215
222
|
/**
|
|
216
223
|
* Initial values applied on mount. Read once on mount and intentionally
|
|
217
224
|
* non-reactive — to reset after a state change, change the component `key`,
|
|
@@ -222,10 +229,11 @@ interface MotionProps<C> {
|
|
|
222
229
|
initial?: AnimateStyle<C> | false;
|
|
223
230
|
/**
|
|
224
231
|
* The animation target. A style object, a variant key (when `variants` is
|
|
225
|
-
* supplied), or an array of sequence steps.
|
|
226
|
-
*
|
|
232
|
+
* supplied), or an array of sequence steps. When `variants` is set, the
|
|
233
|
+
* string form is narrowed to the map's keys, so a key typo is a compile
|
|
234
|
+
* error and the keys autocomplete — no `as const` required.
|
|
227
235
|
*/
|
|
228
|
-
animate?: AnimateStyle<C> | string;
|
|
236
|
+
animate?: AnimateStyle<C> | (keyof V & string);
|
|
229
237
|
/**
|
|
230
238
|
* Values applied while the component exits via `<Presence>`.
|
|
231
239
|
*/
|
|
@@ -234,13 +242,13 @@ interface MotionProps<C> {
|
|
|
234
242
|
* Named animation states. With `variants` set, `animate` accepts a key from
|
|
235
243
|
* this map.
|
|
236
244
|
*/
|
|
237
|
-
variants?:
|
|
245
|
+
variants?: V;
|
|
238
246
|
/**
|
|
239
247
|
* Imperative controller from `useVariants(...)`. When supplied, `animate`
|
|
240
248
|
* is read from `controller.current` and re-applied whenever the controller
|
|
241
249
|
* transitions. `animate` and `controller` should not both be set.
|
|
242
250
|
*/
|
|
243
|
-
controller?: VariantController
|
|
251
|
+
controller?: VariantController<keyof V & string>;
|
|
244
252
|
/**
|
|
245
253
|
* Gesture-driven sub-states (`pressed`, `focused`, `focusVisible`,
|
|
246
254
|
* `hovered`). When omitted, no handlers are mounted on the underlying
|
|
@@ -269,11 +277,34 @@ interface MotionProps<C> {
|
|
|
269
277
|
* — decay is downgraded to spring (no clear target). Reduced motion gates
|
|
270
278
|
* the prop the same way it gates `animate`.
|
|
271
279
|
*
|
|
272
|
-
* `layoutId`
|
|
273
|
-
*
|
|
274
|
-
*
|
|
280
|
+
* `layoutId` (below) is a related but distinct mechanism for shared
|
|
281
|
+
* element transitions across screens — `layout` animates this element's
|
|
282
|
+
* own layout changes, `layoutId` animates from a different element's
|
|
283
|
+
* last measured rect to this element's current rect.
|
|
275
284
|
*/
|
|
276
285
|
layout?: boolean | TransitionConfig;
|
|
286
|
+
/**
|
|
287
|
+
* Shared-element transition id. When a Motion primitive with `layoutId`
|
|
288
|
+
* unmounts, its last on-screen rect is recorded under that id; the next
|
|
289
|
+
* mount of any Motion primitive with the same id animates from the
|
|
290
|
+
* recorded rect to its natural position via a FLIP transform stack.
|
|
291
|
+
*
|
|
292
|
+
* Reanimated 4 removed the `sharedTransitionTag` API — `layoutId` is the
|
|
293
|
+
* Inertia-side measure-based replacement. Rects are recorded in
|
|
294
|
+
* parent-relative coordinates (from `onLayout`), which composes when the
|
|
295
|
+
* source and target screens share an outer content container (the common
|
|
296
|
+
* stack-navigator case); nested-parent layouts need the v2
|
|
297
|
+
* window-coordinate path.
|
|
298
|
+
*
|
|
299
|
+
* The same `transition` prop drives the FLIP animation (spring by
|
|
300
|
+
* default; `'timing'` honored; `'decay'` downgrades to spring; reduced
|
|
301
|
+
* motion skips the transition). Out of scope for the first iteration:
|
|
302
|
+
* style-prop interpolation (border radius, colors, etc.) — only the
|
|
303
|
+
* rect-to-rect transform is animated. Two simultaneously-mounted
|
|
304
|
+
* primitives sharing the same `layoutId` are undefined behavior; pick a
|
|
305
|
+
* primitive per id at a time.
|
|
306
|
+
*/
|
|
307
|
+
layoutId?: string;
|
|
277
308
|
/**
|
|
278
309
|
* Fired once per logical animation completion. See `AnimationCallbackInfo`
|
|
279
310
|
* for the payload shape — transform parents fire once, not per axis.
|
|
@@ -281,12 +312,28 @@ interface MotionProps<C> {
|
|
|
281
312
|
onAnimationEnd?: (info: AnimationCallbackInfo<AnimateStyle<C>>) => void;
|
|
282
313
|
}
|
|
283
314
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
* animated style) with the Motion
|
|
315
|
+
* Props of a Motion primitive for a given underlying component `C` and a
|
|
316
|
+
* concrete variants map `V`: the component's own props (minus `style`, which
|
|
317
|
+
* we replace with an animated style) intersected with the Motion props.
|
|
287
318
|
*/
|
|
288
|
-
type
|
|
289
|
-
style?:
|
|
290
|
-
|
|
319
|
+
type MotionComponentProps<C extends ComponentType<any>, V extends VariantsMap<ComponentProps<C>> = VariantsMap<ComponentProps<C>>> = Omit<ComponentProps<C>, 'style'> & MotionProps<ComponentProps<C>, V> & {
|
|
320
|
+
style?: ComponentProps<C>['style'];
|
|
321
|
+
ref?: Ref<unknown>;
|
|
322
|
+
};
|
|
323
|
+
/**
|
|
324
|
+
* The component type produced by `createMotionComponent`.
|
|
325
|
+
*
|
|
326
|
+
* It is a **generic call signature**, not a plain `ComponentType`: the variant
|
|
327
|
+
* map `V` is inferred from the `variants` prop at each JSX use. That inference
|
|
328
|
+
* is what narrows `animate`'s string form to the variant keys, so
|
|
329
|
+
* `<Motion.View variants={{ open, closed }} animate="opne" />` is a compile
|
|
330
|
+
* error and `open` / `closed` autocomplete. With no `variants` prop, `V` falls
|
|
331
|
+
* back to the open `VariantsMap`, so `animate` still accepts any string and the
|
|
332
|
+
* variant-less call site is unchanged.
|
|
333
|
+
*/
|
|
334
|
+
interface MotionComponent<C extends ComponentType<any>> {
|
|
335
|
+
<V extends VariantsMap<ComponentProps<C>> = VariantsMap<ComponentProps<C>>>(props: MotionComponentProps<C, V>): ReactElement | null;
|
|
336
|
+
displayName?: string;
|
|
337
|
+
}
|
|
291
338
|
|
|
292
|
-
export type { AnimatableValue as A, DecayTransition as D, EasingInput as E,
|
|
339
|
+
export type { AnimatableValue as A, DecayTransition as D, EasingInput as E, GestureSubStates as G, MotionComponent as M, NoAnimationTransition as N, PerPropertyTransition as P, RepeatConfig as R, SpringTransition as S, TransitionConfig as T, VariantController as V, AnimateStyle as a, AnimationCallbackInfo as b, MotionProps as c, SequenceStep as d, TimingTransition as e, Transition as f, VariantsMap as g, GestureLayerTransitions as h };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { SharedValue } from 'react-native-reanimated';
|
|
2
|
+
import { T as TransitionConfig, h as GestureLayerTransitions } from './types-cU43dEmH.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
|
|
6
|
+
* shared values returned alongside.
|
|
7
|
+
*
|
|
8
|
+
* Hover handlers use `Pressable`'s own `onHoverIn` / `onHoverOut` names (web
|
|
9
|
+
* only — no-ops on native). `onFocus` consults `isFocusVisible()` before
|
|
10
|
+
* raising the keyboard-only `focusVisible` layer; `focused` always raises.
|
|
11
|
+
*/
|
|
12
|
+
interface UseGestureHandlers {
|
|
13
|
+
onPressIn: () => void;
|
|
14
|
+
onPressOut: () => void;
|
|
15
|
+
onHoverIn: () => void;
|
|
16
|
+
onHoverOut: () => void;
|
|
17
|
+
onFocus: () => void;
|
|
18
|
+
onBlur: () => void;
|
|
19
|
+
}
|
|
20
|
+
interface UseGestureResult {
|
|
21
|
+
/** 0↔1 progress for the pressed layer. */
|
|
22
|
+
pressed: SharedValue<number>;
|
|
23
|
+
/** 0↔1 progress for the focused layer (any focus modality). */
|
|
24
|
+
focused: SharedValue<number>;
|
|
25
|
+
/** 0↔1 progress for the focusVisible layer (keyboard focus only). */
|
|
26
|
+
focusVisible: SharedValue<number>;
|
|
27
|
+
/** 0↔1 progress for the hovered layer (web only — stays at 0 on native). */
|
|
28
|
+
hovered: SharedValue<number>;
|
|
29
|
+
/** Handlers to spread on the receiving `Pressable`. */
|
|
30
|
+
handlers: UseGestureHandlers;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build a gesture-layer controller. The hook-form of the `gesture` prop —
|
|
34
|
+
* reach for it when you need to drive multiple animated views from the same
|
|
35
|
+
* gesture state (a focus ring + state-layer halo + content tint all on one
|
|
36
|
+
* Pressable), which the prop-form's "animate the receiver's own style" model
|
|
37
|
+
* can't express.
|
|
38
|
+
*
|
|
39
|
+
* Returns four 0↔1 shared values (one per layer) and a handler bag to spread
|
|
40
|
+
* on a `Pressable`. The shared values are stable across renders — feed them
|
|
41
|
+
* into any number of `useAnimatedStyle` blocks anywhere in the tree.
|
|
42
|
+
*
|
|
43
|
+
* Transitions follow the same shape as the `gesture` prop's accompanying
|
|
44
|
+
* `transition`: pass a single `TransitionConfig` to use for every layer, or a
|
|
45
|
+
* `GestureLayerTransitions` map to give each layer its own. Layers without an
|
|
46
|
+
* explicit transition fall back to the library default spring.
|
|
47
|
+
*
|
|
48
|
+
* Reduced motion (via `<MotionConfig reducedMotion>`) collapses every
|
|
49
|
+
* transition to `no-animation` so state changes snap instead of interpolating
|
|
50
|
+
* — same behaviour the gesture prop applies.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* import { useAnimatedStyle } from 'react-native-reanimated'
|
|
55
|
+
* import { useGesture } from '@onlynative/inertia'
|
|
56
|
+
*
|
|
57
|
+
* function Card() {
|
|
58
|
+
* const { pressed, focused, hovered, handlers } = useGesture({
|
|
59
|
+
* pressed: { type: 'timing', duration: 100 },
|
|
60
|
+
* hovered: { type: 'timing', duration: 150 },
|
|
61
|
+
* focused: { type: 'timing', duration: 200 },
|
|
62
|
+
* })
|
|
63
|
+
*
|
|
64
|
+
* const ringStyle = useAnimatedStyle(() => ({ opacity: focused.value }))
|
|
65
|
+
* const haloStyle = useAnimatedStyle(() => ({
|
|
66
|
+
* opacity: Math.max(
|
|
67
|
+
* hovered.value * 0.08,
|
|
68
|
+
* focused.value * 0.10,
|
|
69
|
+
* pressed.value * 0.10,
|
|
70
|
+
* ),
|
|
71
|
+
* }))
|
|
72
|
+
*
|
|
73
|
+
* return (
|
|
74
|
+
* <Pressable {...handlers}>
|
|
75
|
+
* <Animated.View style={ringStyle} />
|
|
76
|
+
* <Animated.View style={haloStyle} />
|
|
77
|
+
* </Pressable>
|
|
78
|
+
* )
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
declare function useGesture(transition?: TransitionConfig | GestureLayerTransitions): UseGestureResult;
|
|
83
|
+
|
|
84
|
+
export { type UseGestureHandlers as U, type UseGestureResult as a, useGesture as u };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { SharedValue } from 'react-native-reanimated';
|
|
2
|
+
import { T as TransitionConfig, h as GestureLayerTransitions } from './types-cU43dEmH.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Handler bag returned by `useGesture`. Spread on a `Pressable` to drive the
|
|
6
|
+
* shared values returned alongside.
|
|
7
|
+
*
|
|
8
|
+
* Hover handlers use `Pressable`'s own `onHoverIn` / `onHoverOut` names (web
|
|
9
|
+
* only — no-ops on native). `onFocus` consults `isFocusVisible()` before
|
|
10
|
+
* raising the keyboard-only `focusVisible` layer; `focused` always raises.
|
|
11
|
+
*/
|
|
12
|
+
interface UseGestureHandlers {
|
|
13
|
+
onPressIn: () => void;
|
|
14
|
+
onPressOut: () => void;
|
|
15
|
+
onHoverIn: () => void;
|
|
16
|
+
onHoverOut: () => void;
|
|
17
|
+
onFocus: () => void;
|
|
18
|
+
onBlur: () => void;
|
|
19
|
+
}
|
|
20
|
+
interface UseGestureResult {
|
|
21
|
+
/** 0↔1 progress for the pressed layer. */
|
|
22
|
+
pressed: SharedValue<number>;
|
|
23
|
+
/** 0↔1 progress for the focused layer (any focus modality). */
|
|
24
|
+
focused: SharedValue<number>;
|
|
25
|
+
/** 0↔1 progress for the focusVisible layer (keyboard focus only). */
|
|
26
|
+
focusVisible: SharedValue<number>;
|
|
27
|
+
/** 0↔1 progress for the hovered layer (web only — stays at 0 on native). */
|
|
28
|
+
hovered: SharedValue<number>;
|
|
29
|
+
/** Handlers to spread on the receiving `Pressable`. */
|
|
30
|
+
handlers: UseGestureHandlers;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build a gesture-layer controller. The hook-form of the `gesture` prop —
|
|
34
|
+
* reach for it when you need to drive multiple animated views from the same
|
|
35
|
+
* gesture state (a focus ring + state-layer halo + content tint all on one
|
|
36
|
+
* Pressable), which the prop-form's "animate the receiver's own style" model
|
|
37
|
+
* can't express.
|
|
38
|
+
*
|
|
39
|
+
* Returns four 0↔1 shared values (one per layer) and a handler bag to spread
|
|
40
|
+
* on a `Pressable`. The shared values are stable across renders — feed them
|
|
41
|
+
* into any number of `useAnimatedStyle` blocks anywhere in the tree.
|
|
42
|
+
*
|
|
43
|
+
* Transitions follow the same shape as the `gesture` prop's accompanying
|
|
44
|
+
* `transition`: pass a single `TransitionConfig` to use for every layer, or a
|
|
45
|
+
* `GestureLayerTransitions` map to give each layer its own. Layers without an
|
|
46
|
+
* explicit transition fall back to the library default spring.
|
|
47
|
+
*
|
|
48
|
+
* Reduced motion (via `<MotionConfig reducedMotion>`) collapses every
|
|
49
|
+
* transition to `no-animation` so state changes snap instead of interpolating
|
|
50
|
+
* — same behaviour the gesture prop applies.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* import { useAnimatedStyle } from 'react-native-reanimated'
|
|
55
|
+
* import { useGesture } from '@onlynative/inertia'
|
|
56
|
+
*
|
|
57
|
+
* function Card() {
|
|
58
|
+
* const { pressed, focused, hovered, handlers } = useGesture({
|
|
59
|
+
* pressed: { type: 'timing', duration: 100 },
|
|
60
|
+
* hovered: { type: 'timing', duration: 150 },
|
|
61
|
+
* focused: { type: 'timing', duration: 200 },
|
|
62
|
+
* })
|
|
63
|
+
*
|
|
64
|
+
* const ringStyle = useAnimatedStyle(() => ({ opacity: focused.value }))
|
|
65
|
+
* const haloStyle = useAnimatedStyle(() => ({
|
|
66
|
+
* opacity: Math.max(
|
|
67
|
+
* hovered.value * 0.08,
|
|
68
|
+
* focused.value * 0.10,
|
|
69
|
+
* pressed.value * 0.10,
|
|
70
|
+
* ),
|
|
71
|
+
* }))
|
|
72
|
+
*
|
|
73
|
+
* return (
|
|
74
|
+
* <Pressable {...handlers}>
|
|
75
|
+
* <Animated.View style={ringStyle} />
|
|
76
|
+
* <Animated.View style={haloStyle} />
|
|
77
|
+
* </Pressable>
|
|
78
|
+
* )
|
|
79
|
+
* }
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
declare function useGesture(transition?: TransitionConfig | GestureLayerTransitions): UseGestureResult;
|
|
83
|
+
|
|
84
|
+
export { type UseGestureHandlers as U, type UseGestureResult as a, useGesture as u };
|
package/jest-setup.js
CHANGED
|
@@ -104,6 +104,10 @@ jest.mock('react-native-reanimated', () => {
|
|
|
104
104
|
}
|
|
105
105
|
},
|
|
106
106
|
useReducedMotion: () => false,
|
|
107
|
+
// Inertia's dev-time install check reads this to detect a too-old
|
|
108
|
+
// Reanimated. The check is skipped under NODE_ENV=test, but the named
|
|
109
|
+
// import must still resolve for consumers' test suites.
|
|
110
|
+
reanimatedVersion: '4.0.0',
|
|
107
111
|
isWorkletFunction: () => false,
|
|
108
112
|
cancelAnimation: () => {},
|
|
109
113
|
runOnJS: (fn) => fn,
|
package/llms.txt
CHANGED
|
@@ -22,10 +22,15 @@ import {
|
|
|
22
22
|
useMotionValue,
|
|
23
23
|
useAnimation,
|
|
24
24
|
useSpring,
|
|
25
|
+
useBooleanSpring,
|
|
25
26
|
useTransform,
|
|
27
|
+
useShadow,
|
|
28
|
+
useColorTransition,
|
|
26
29
|
useScroll,
|
|
27
30
|
} from '@onlynative/inertia'
|
|
28
|
-
//
|
|
31
|
+
// Opt-in MD3 / iOS state-layer overlay helper:
|
|
32
|
+
import { useGestureLayer } from '@onlynative/inertia/gesture-layer'
|
|
33
|
+
// or for tree-shaking the primitives:
|
|
29
34
|
import { MotionView } from '@onlynative/inertia/view'
|
|
30
35
|
import { MotionText } from '@onlynative/inertia/text'
|
|
31
36
|
import { MotionImage } from '@onlynative/inertia/image'
|
|
@@ -39,11 +44,15 @@ import { MotionScrollView } from '@onlynative/inertia/scroll-view'
|
|
|
39
44
|
- `<Presence>` — mount / unmount transitions; children need explicit `key`s. Exiting children get `pointerEvents: 'none'` automatically.
|
|
40
45
|
- `<MotionConfig reducedMotion="user" | "never" | "always">` — gates motion against the OS reduce-motion setting (default `"user"`).
|
|
41
46
|
- `useGesture(transition?)` — hook-form of the `gesture` prop. Returns 0↔1 progress shared values (`pressed`, `focused`, `focusVisible`, `hovered`) plus a `handlers` bag to spread on a `Pressable`. Use when one gesture needs to drive multiple animated siblings (focus rings, MD3 state-layer halos, multi-element compositions).
|
|
47
|
+
- `useGestureLayer(states, options?)` — opt-in helper at `@onlynative/inertia/gesture-layer` for the **strongest-active-layer-wins** composition (MD3 state-layer haloes, iOS-translucent overlays). Supply per-state target maps (`rest` / `hovered` / `focused` / `focusVisible` / `pressed` / `disabled`); the hook owns the worklet. Numeric keys compose via clamped-max with `rest` as the floor; color keys compose via priority cascade with `interpolateColor`; `disabled` (JS-side flag) overrides every gesture layer. Returns `{ style, handlers }`. Reach for plain `useGesture` for additive blends or per-key custom rules.
|
|
42
48
|
- `useVariants(variants, initial?)` — returns `{ current, transitionTo }` controller for the `controller` prop.
|
|
43
49
|
- `useMotionValue(initial)` — thin pass-through over `useSharedValue<T>`. Returns a `SharedValue<T>` directly so it interops with every Reanimated API without unwrapping.
|
|
44
50
|
- `useAnimation(target, transition?)` — drive a `SharedValue<number>` toward `target` with any `TransitionConfig` (spring / timing / decay / no-animation, plus `repeat`). The general-purpose value-layer hook for boolean-state progress, indeterminate loops, and anywhere the same value needs to feed multiple `useAnimatedStyle` blocks.
|
|
45
51
|
- `useSpring(target, config?)` — spring-only shorthand. Animates a `SharedValue<number>` toward `target` with react-spring vocab. `target` may be a plain number (effect-driven) or a `SharedValue<number>` (UI-thread reaction); the latter is the gesture-smoothing path.
|
|
52
|
+
- `useBooleanSpring(active, config?)` — sugar over `useSpring` for the recurring "spring 0↔1 progress from a boolean" shape (checkbox checks, accordion expansions, drawer open/closed). Identical mechanics to `useSpring(active ? 1 : 0, config)` — the named form so the call site reads as the boolean it represents.
|
|
46
53
|
- `useTransform(value, inputRange, outputRange, options?)` / `useTransform(transformer)` — interpolate a numeric shared value onto a number or color range, or derive any value from any number of shared values via a worklet. Non-worklet transformers are auto-wrapped.
|
|
54
|
+
- `useShadow({ from, to, progress })` — pure value-layer interpolator between two `ShadowConfig`s (`shadowOpacity` / `shadowRadius` / `shadowOffset` / `elevation` / `shadowColor`) driven by a `SharedValue<number>` (0→1). Returns an animated style fragment to spread onto `style`; only emits keys present on either side, absent sides default to natural zero. The hook does not animate on its own — drive `progress` with a spring, a scroll-derived `useTransform`, or any other shared value source.
|
|
55
|
+
- `useColorTransition(progress, [from, to], options?)` — pure value-layer interpolator for a single color channel, driven by a `SharedValue<number>` (0→1). Returns an animated style fragment with one color key (default `backgroundColor`; configurable via `options.key` to `color` / `borderColor` / `tintColor` / `shadowColor` / per-side border colors). For raw `SharedValue<string>` output, use `useTransform(progress, [0, 1], [from, to])` instead.
|
|
47
56
|
- `useScroll()` — returns `{ scrollX, scrollY, onScroll }` for use with `Motion.ScrollView`. Scroll events fire on the UI thread.
|
|
48
57
|
- `createMotionComponent<C>(C)` — wrap any component with the same Motion prop surface, inferring style from `C`.
|
|
49
58
|
- `buildReleaseAnimation(transition, toValue)` — worklet-safe single-step animation builder (spring / timing / decay / no-animation). For assigning Inertia-resolved animations to shared values from inside a gesture worklet. Used internally by `@onlynative/inertia-gestures`'s `useDrag({ onRelease })`.
|
|
@@ -107,7 +116,7 @@ transition={{
|
|
|
107
116
|
|
|
108
117
|
## Caveats
|
|
109
118
|
|
|
110
|
-
- `Motion
|
|
119
|
+
- Every `Motion.*` primitive **throws in dev** when `style` is a function. Reanimated's animated-component wrapper would silently drop the function-form `style={({ pressed }) => ...}` that RN's `Pressable` accepts, so the throw catches the footgun at the source. Drive press/focus/hover styling through `gesture` instead, or compute conditional styles once in render. Production builds skip the check (the styles would still be dropped — catching it in dev is the safety net).
|
|
111
120
|
- `initial` is read once on mount and intentionally non-reactive. To reset after a state change, change the component `key`, remount via `<Presence>`, or drive the value through a controller. Pass `initial={false}` to skip the initial-mount animation.
|
|
112
121
|
|
|
113
122
|
## Animatable properties (alpha)
|
|
@@ -118,7 +127,7 @@ Color: `backgroundColor`, `borderColor`, `color`, `tintColor` (Image only), `sha
|
|
|
118
127
|
|
|
119
128
|
Nested object: `shadowOffset: { width, height }`. The only nested-object style on the surface — internally decomposes into two synthetic axis SVs that the worklet recomposes into a single `shadowOffset` prop. v0.1 supports the **single-value form only** (`{ width: 0, height: 4 }`); sequences / array keyframes / per-axis transition splits are out of scope, drop to `useMotionValue` for those.
|
|
120
129
|
|
|
121
|
-
Auto-layout transitions ship via the `layout` prop (`true` / `TransitionConfig`) on every `Motion.*` primitive — see Layout. Shared element transitions
|
|
130
|
+
Auto-layout transitions ship via the `layout` prop (`true` / `TransitionConfig`) on every `Motion.*` primitive — see Layout. Shared element transitions ship via the `layoutId` prop: pair the same id on a source and target `Motion.*` and Inertia FLIPs between them on mount (parent-relative coords, rect-only animation, 1s TTL).
|
|
122
131
|
|
|
123
132
|
## Optional adapter packages
|
|
124
133
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onlynative/inertia",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.9",
|
|
4
4
|
"description": "Declarative animation primitives for React Native, built on react-native-reanimated.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "OnlyNative",
|
|
@@ -79,6 +79,20 @@
|
|
|
79
79
|
"import": "./dist/testing/index.mjs",
|
|
80
80
|
"require": "./dist/testing/index.js"
|
|
81
81
|
},
|
|
82
|
+
"./touch": {
|
|
83
|
+
"types": "./dist/touch/index.d.ts",
|
|
84
|
+
"react-native": "./src/touch/index.ts",
|
|
85
|
+
"source": "./src/touch/index.ts",
|
|
86
|
+
"import": "./dist/touch/index.mjs",
|
|
87
|
+
"require": "./dist/touch/index.js"
|
|
88
|
+
},
|
|
89
|
+
"./gesture-layer": {
|
|
90
|
+
"types": "./dist/gestureLayer/index.d.ts",
|
|
91
|
+
"react-native": "./src/gestureLayer/index.ts",
|
|
92
|
+
"source": "./src/gestureLayer/index.ts",
|
|
93
|
+
"import": "./dist/gestureLayer/index.mjs",
|
|
94
|
+
"require": "./dist/gestureLayer/index.js"
|
|
95
|
+
},
|
|
82
96
|
"./jest-preset": "./jest-preset.js",
|
|
83
97
|
"./jest-setup": "./jest-setup.js",
|
|
84
98
|
"./package.json": "./package.json"
|
|
@@ -98,7 +112,13 @@
|
|
|
98
112
|
"peerDependencies": {
|
|
99
113
|
"react": ">=19.0.0",
|
|
100
114
|
"react-native": ">=0.81.0",
|
|
101
|
-
"react-native-reanimated": ">=4.0.0"
|
|
115
|
+
"react-native-reanimated": ">=4.0.0",
|
|
116
|
+
"react-native-worklets": ">=0.5.0"
|
|
117
|
+
},
|
|
118
|
+
"peerDependenciesMeta": {
|
|
119
|
+
"react-native-worklets": {
|
|
120
|
+
"optional": true
|
|
121
|
+
}
|
|
102
122
|
},
|
|
103
123
|
"devDependencies": {
|
|
104
124
|
"@react-native/babel-preset": "^0.81.5",
|