@onlynative/inertia 0.0.1-alpha.7 → 0.0.1-alpha.8
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 +1745 -0
- package/dist/gestureLayer/index.js.map +1 -0
- package/dist/gestureLayer/index.mjs +1743 -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 +279 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +279 -44
- 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 +178 -4
- package/dist/motion/Image.js.map +1 -1
- package/dist/motion/Image.mjs +180 -6
- 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 +178 -4
- package/dist/motion/Pressable.js.map +1 -1
- package/dist/motion/Pressable.mjs +180 -6
- 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 +178 -4
- package/dist/motion/ScrollView.js.map +1 -1
- package/dist/motion/ScrollView.mjs +180 -6
- 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 +178 -4
- package/dist/motion/Text.js.map +1 -1
- package/dist/motion/Text.mjs +180 -6
- 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 +178 -4
- package/dist/motion/View.js.map +1 -1
- package/dist/motion/View.mjs +180 -6
- 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-BwyvoH2V.d.mts} +24 -4
- package/dist/{types-NmNeJjo1.d.ts → types-BwyvoH2V.d.ts} +24 -4
- package/dist/useGesture-BPPp9LhV.d.ts +84 -0
- package/dist/useGesture-BnBF4OtT.d.mts +84 -0
- package/llms.txt +12 -3
- package/package.json +15 -1
- 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 +108 -0
- package/src/layout/useSharedLayout.ts +289 -0
- package/src/motion/createMotionComponent.tsx +60 -4
- package/src/touch/index.ts +18 -0
- package/src/touch/useTouchDrag.ts +289 -0
- package/src/types.ts +23 -3
- 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
package/src/types.ts
CHANGED
|
@@ -298,11 +298,31 @@ export interface MotionProps<C> {
|
|
|
298
298
|
* — decay is downgraded to spring (no clear target). Reduced motion gates
|
|
299
299
|
* the prop the same way it gates `animate`.
|
|
300
300
|
*
|
|
301
|
-
* `layoutId`
|
|
302
|
-
*
|
|
303
|
-
*
|
|
301
|
+
* `layoutId` (below) is a related but distinct mechanism for shared
|
|
302
|
+
* element transitions across screens — `layout` animates this element's
|
|
303
|
+
* own layout changes, `layoutId` animates from a different element's
|
|
304
|
+
* last measured rect to this element's current rect.
|
|
304
305
|
*/
|
|
305
306
|
layout?: boolean | TransitionConfig
|
|
307
|
+
/**
|
|
308
|
+
* Shared-element transition id. When a Motion primitive with `layoutId`
|
|
309
|
+
* unmounts, its last on-screen rect is recorded under that id; the next
|
|
310
|
+
* mount of any Motion primitive with the same id animates from the
|
|
311
|
+
* recorded rect to its natural position via a FLIP transform stack.
|
|
312
|
+
*
|
|
313
|
+
* Reanimated 4 removed the `sharedTransitionTag` API — `layoutId` is the
|
|
314
|
+
* Inertia-side measure-based replacement. Rects are stored in window
|
|
315
|
+
* coordinates so the source and target can live on different screens.
|
|
316
|
+
*
|
|
317
|
+
* The same `transition` prop drives the FLIP animation (spring by
|
|
318
|
+
* default; `'timing'` honored; `'decay'` downgrades to spring; reduced
|
|
319
|
+
* motion skips the transition). Out of scope for the first iteration:
|
|
320
|
+
* style-prop interpolation (border radius, colors, etc.) — only the
|
|
321
|
+
* rect-to-rect transform is animated. Two simultaneously-mounted
|
|
322
|
+
* primitives sharing the same `layoutId` are undefined behavior; pick a
|
|
323
|
+
* primitive per id at a time.
|
|
324
|
+
*/
|
|
325
|
+
layoutId?: string
|
|
306
326
|
/**
|
|
307
327
|
* Fired once per logical animation completion. See `AnimationCallbackInfo`
|
|
308
328
|
* for the payload shape — transform parents fire once, not per axis.
|
package/src/values/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
export { useAnimation } from './useAnimation'
|
|
2
|
+
export { useBooleanSpring } from './useBooleanSpring'
|
|
3
|
+
export {
|
|
4
|
+
useColorTransition,
|
|
5
|
+
type ColorStyleKey,
|
|
6
|
+
type UseColorTransitionOptions,
|
|
7
|
+
} from './useColorTransition'
|
|
2
8
|
export {
|
|
3
9
|
useGesture,
|
|
4
10
|
type UseGestureHandlers,
|
|
@@ -12,4 +18,9 @@ export {
|
|
|
12
18
|
type UseTransformOptions,
|
|
13
19
|
} from './useTransform'
|
|
14
20
|
export { useScroll, type UseScrollResult } from './useScroll'
|
|
21
|
+
export {
|
|
22
|
+
useShadow,
|
|
23
|
+
type ShadowConfig,
|
|
24
|
+
type UseShadowOptions,
|
|
25
|
+
} from './useShadow'
|
|
15
26
|
export { useVariants } from './useVariants'
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type SharedValue } from 'react-native-reanimated'
|
|
2
|
+
import { useSpring } from './useSpring'
|
|
3
|
+
import { type SpringTransition } from '../types'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Toggle a 0↔1 progress value with a spring whenever `active` flips.
|
|
7
|
+
*
|
|
8
|
+
* This is the recurring shape behind checkbox checks, accordion expansions,
|
|
9
|
+
* drawer open/closed states, focus rings, and every other binary UI flip
|
|
10
|
+
* that wants spring physics rather than a hard cut. The returned shared
|
|
11
|
+
* value sits at `0` when `active` is `false` and animates toward `1` when
|
|
12
|
+
* `active` flips to `true` (and back again on the reverse flip). Feed it to
|
|
13
|
+
* a `useTransform`, `useShadow`, or a hand-rolled `useAnimatedStyle` to
|
|
14
|
+
* drive whatever the boolean controls visually.
|
|
15
|
+
*
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const progress = useBooleanSpring(isChecked)
|
|
18
|
+
* const indicatorStyle = useAnimatedStyle(() => ({
|
|
19
|
+
* opacity: progress.value,
|
|
20
|
+
* transform: [{ scale: progress.value }],
|
|
21
|
+
* }))
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* The spring config follows the same react-spring vocabulary as the rest of
|
|
25
|
+
* the library (`tension` / `friction` / `mass`); omit it to take the
|
|
26
|
+
* library's defaults.
|
|
27
|
+
*/
|
|
28
|
+
export function useBooleanSpring(
|
|
29
|
+
active: boolean,
|
|
30
|
+
springConfig?: SpringTransition,
|
|
31
|
+
): SharedValue<number> {
|
|
32
|
+
return useSpring(active ? 1 : 0, springConfig)
|
|
33
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {
|
|
2
|
+
interpolateColor,
|
|
3
|
+
useAnimatedStyle,
|
|
4
|
+
type SharedValue,
|
|
5
|
+
} from 'react-native-reanimated'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Color style keys understood by React Native that this hook can target.
|
|
9
|
+
* Sticks to the keys that exist on the v0.1 animatable surface so the
|
|
10
|
+
* returned style fragment is always a legal RN style.
|
|
11
|
+
*/
|
|
12
|
+
export type ColorStyleKey =
|
|
13
|
+
| 'backgroundColor'
|
|
14
|
+
| 'color'
|
|
15
|
+
| 'borderColor'
|
|
16
|
+
| 'borderTopColor'
|
|
17
|
+
| 'borderRightColor'
|
|
18
|
+
| 'borderBottomColor'
|
|
19
|
+
| 'borderLeftColor'
|
|
20
|
+
| 'tintColor'
|
|
21
|
+
| 'shadowColor'
|
|
22
|
+
|
|
23
|
+
export interface UseColorTransitionOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Which style slot the interpolated color is emitted under. Defaults to
|
|
26
|
+
* `backgroundColor` — the dominant case for state-layer haloes, card
|
|
27
|
+
* fills, and chip surfaces. Override for ring colors (`borderColor`),
|
|
28
|
+
* text colors (`color`), image tints (`tintColor`), etc.
|
|
29
|
+
*/
|
|
30
|
+
key?: ColorStyleKey
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Interpolate a single color channel between `from` and `to` as `progress`
|
|
35
|
+
* moves 0→1, returning an animated style fragment that can be spread onto
|
|
36
|
+
* any Reanimated-aware view.
|
|
37
|
+
*
|
|
38
|
+
* ```tsx
|
|
39
|
+
* const progress = useBooleanSpring(isPressed)
|
|
40
|
+
* const fillStyle = useColorTransition(progress, [colors.surface, colors.pressed])
|
|
41
|
+
* const ringStyle = useColorTransition(progress, [colors.outline, colors.primary], {
|
|
42
|
+
* key: 'borderColor',
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* return <Motion.View style={[styles.chip, fillStyle, ringStyle]} />
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* This is a pure interpolator: it does not animate on its own. Drive
|
|
49
|
+
* `progress` upstream with a `useSpring`, `useBooleanSpring`, gesture
|
|
50
|
+
* progress, or scroll-derived `useTransform`. Values outside `[0, 1]`
|
|
51
|
+
* clamp. For a raw `SharedValue<string>` (e.g. to feed a gradient or
|
|
52
|
+
* compose into a hand-rolled `useAnimatedStyle`), use `useTransform`
|
|
53
|
+
* directly with a color output range.
|
|
54
|
+
*/
|
|
55
|
+
export function useColorTransition(
|
|
56
|
+
progress: SharedValue<number>,
|
|
57
|
+
range: readonly [string, string],
|
|
58
|
+
options?: UseColorTransitionOptions,
|
|
59
|
+
): ReturnType<typeof useAnimatedStyle> {
|
|
60
|
+
// Resolve the slot key once on the JS thread so the worklet body
|
|
61
|
+
// consumes a single string literal — consistent with the JS-thread
|
|
62
|
+
// resolver principle that keeps `Object.keys`-style walks off the UI
|
|
63
|
+
// thread (see CLAUDE.md design principle 8).
|
|
64
|
+
const key = options?.key ?? 'backgroundColor'
|
|
65
|
+
const from = range[0]
|
|
66
|
+
const to = range[1]
|
|
67
|
+
|
|
68
|
+
return useAnimatedStyle(() => {
|
|
69
|
+
'worklet'
|
|
70
|
+
return { [key]: interpolateColor(progress.value, [0, 1], [from, to]) }
|
|
71
|
+
})
|
|
72
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
interpolate,
|
|
3
|
+
interpolateColor,
|
|
4
|
+
useAnimatedStyle,
|
|
5
|
+
type SharedValue,
|
|
6
|
+
} from 'react-native-reanimated'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Shape accepted on either end of a `useShadow` tween. Every field is
|
|
10
|
+
* optional — only keys present on at least one side participate in the
|
|
11
|
+
* output style. Mirrors the flat shadow keys on `Motion.View`'s `animate`
|
|
12
|
+
* surface, plus the nested `shadowOffset` source.
|
|
13
|
+
*/
|
|
14
|
+
export interface ShadowConfig {
|
|
15
|
+
shadowOpacity?: number
|
|
16
|
+
shadowRadius?: number
|
|
17
|
+
shadowOffset?: { width?: number; height?: number }
|
|
18
|
+
/** Android elevation. iOS shadow consumers can leave this off. */
|
|
19
|
+
elevation?: number
|
|
20
|
+
shadowColor?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UseShadowOptions {
|
|
24
|
+
/** Shadow state at `progress === 0`. */
|
|
25
|
+
from: ShadowConfig
|
|
26
|
+
/** Shadow state at `progress === 1`. */
|
|
27
|
+
to: ShadowConfig
|
|
28
|
+
/**
|
|
29
|
+
* Driver — typically 0→1. Whatever produces it (a `useSpring`, a gesture
|
|
30
|
+
* progress value, a scroll-derived `useTransform`) is the caller's
|
|
31
|
+
* concern. The hook is a pure interpolator; it does not animate on its
|
|
32
|
+
* own. Values outside `[0, 1]` clamp.
|
|
33
|
+
*/
|
|
34
|
+
progress: SharedValue<number>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Interpolate between two shadow configs as `progress` moves 0→1, returning
|
|
39
|
+
* an animated style fragment that can be spread onto any Reanimated-aware
|
|
40
|
+
* view (including `Motion.*` primitives and a hand-rolled `Animated.View`).
|
|
41
|
+
*
|
|
42
|
+
* ```tsx
|
|
43
|
+
* const progress = useSpring(isElevated ? 1 : 0)
|
|
44
|
+
* const shadowStyle = useShadow({
|
|
45
|
+
* from: { shadowOpacity: 0.08, shadowRadius: 2, shadowOffset: { width: 0, height: 1 }, elevation: 1 },
|
|
46
|
+
* to: { shadowOpacity: 0.24, shadowRadius: 12, shadowOffset: { width: 0, height: 8 }, elevation: 8 },
|
|
47
|
+
* progress,
|
|
48
|
+
* })
|
|
49
|
+
*
|
|
50
|
+
* return <Motion.View style={[styles.card, shadowStyle]} />
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* Only keys present on either `from` or `to` are emitted. A key present on
|
|
54
|
+
* one side and absent on the other tweens from the present value to the
|
|
55
|
+
* absent side's natural zero (`0` for numbers, `'transparent'` for
|
|
56
|
+
* `shadowColor`, `{ width: 0, height: 0 }` for `shadowOffset`). This is a
|
|
57
|
+
* pure interpolator — to "animate" the shadow, drive `progress` with a
|
|
58
|
+
* spring, timing, or gesture upstream.
|
|
59
|
+
*/
|
|
60
|
+
export function useShadow({
|
|
61
|
+
from,
|
|
62
|
+
to,
|
|
63
|
+
progress,
|
|
64
|
+
}: UseShadowOptions): ReturnType<typeof useAnimatedStyle> {
|
|
65
|
+
// Resolve presence + endpoints once on the JS thread so the worklet body
|
|
66
|
+
// consumes flat literals — consistent with the JS-thread resolver
|
|
67
|
+
// principle that keeps `Object.keys`-style walks off the UI thread.
|
|
68
|
+
const hasOpacity =
|
|
69
|
+
from.shadowOpacity !== undefined || to.shadowOpacity !== undefined
|
|
70
|
+
const hasRadius =
|
|
71
|
+
from.shadowRadius !== undefined || to.shadowRadius !== undefined
|
|
72
|
+
const hasElevation =
|
|
73
|
+
from.elevation !== undefined || to.elevation !== undefined
|
|
74
|
+
const hasColor =
|
|
75
|
+
from.shadowColor !== undefined || to.shadowColor !== undefined
|
|
76
|
+
const hasOffset =
|
|
77
|
+
from.shadowOffset !== undefined || to.shadowOffset !== undefined
|
|
78
|
+
|
|
79
|
+
const opacityFrom = from.shadowOpacity ?? 0
|
|
80
|
+
const opacityTo = to.shadowOpacity ?? 0
|
|
81
|
+
const radiusFrom = from.shadowRadius ?? 0
|
|
82
|
+
const radiusTo = to.shadowRadius ?? 0
|
|
83
|
+
const elevationFrom = from.elevation ?? 0
|
|
84
|
+
const elevationTo = to.elevation ?? 0
|
|
85
|
+
const colorFrom = from.shadowColor ?? 'transparent'
|
|
86
|
+
const colorTo = to.shadowColor ?? 'transparent'
|
|
87
|
+
const offsetWFrom = from.shadowOffset?.width ?? 0
|
|
88
|
+
const offsetWTo = to.shadowOffset?.width ?? 0
|
|
89
|
+
const offsetHFrom = from.shadowOffset?.height ?? 0
|
|
90
|
+
const offsetHTo = to.shadowOffset?.height ?? 0
|
|
91
|
+
|
|
92
|
+
return useAnimatedStyle(() => {
|
|
93
|
+
'worklet'
|
|
94
|
+
const t = progress.value
|
|
95
|
+
const out: Record<string, unknown> = {}
|
|
96
|
+
if (hasOpacity) {
|
|
97
|
+
out.shadowOpacity = interpolate(t, [0, 1], [opacityFrom, opacityTo])
|
|
98
|
+
}
|
|
99
|
+
if (hasRadius) {
|
|
100
|
+
out.shadowRadius = interpolate(t, [0, 1], [radiusFrom, radiusTo])
|
|
101
|
+
}
|
|
102
|
+
if (hasElevation) {
|
|
103
|
+
out.elevation = interpolate(t, [0, 1], [elevationFrom, elevationTo])
|
|
104
|
+
}
|
|
105
|
+
if (hasColor) {
|
|
106
|
+
out.shadowColor = interpolateColor(t, [0, 1], [colorFrom, colorTo])
|
|
107
|
+
}
|
|
108
|
+
if (hasOffset) {
|
|
109
|
+
out.shadowOffset = {
|
|
110
|
+
width: interpolate(t, [0, 1], [offsetWFrom, offsetWTo]),
|
|
111
|
+
height: interpolate(t, [0, 1], [offsetHFrom, offsetHTo]),
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out
|
|
115
|
+
})
|
|
116
|
+
}
|