react-native-screen-transitions 3.2.0 → 3.3.0-beta.0
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/lib/commonjs/shared/components/create-transition-aware-component.js +8 -2
- package/lib/commonjs/shared/components/create-transition-aware-component.js.map +1 -1
- package/lib/commonjs/shared/components/{root-transition-aware.js → screen-container.js} +28 -12
- package/lib/commonjs/shared/components/screen-container.js.map +1 -0
- package/lib/commonjs/shared/configs/presets.js +3 -3
- package/lib/commonjs/shared/configs/presets.js.map +1 -1
- package/lib/commonjs/shared/configs/specs.js +6 -1
- package/lib/commonjs/shared/configs/specs.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js +36 -188
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js +334 -0
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -0
- package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js +47 -4
- package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
- package/lib/commonjs/shared/hooks/lifecycle/use-close-transition.js +3 -3
- package/lib/commonjs/shared/hooks/lifecycle/use-close-transition.js.map +1 -1
- package/lib/commonjs/shared/hooks/lifecycle/use-open-transition.js +25 -3
- package/lib/commonjs/shared/hooks/lifecycle/use-open-transition.js.map +1 -1
- package/lib/commonjs/shared/hooks/navigation/use-screen-state.js +61 -2
- package/lib/commonjs/shared/hooks/navigation/use-screen-state.js.map +1 -1
- package/lib/commonjs/shared/hooks/use-backdrop-pointer-events.js +32 -0
- package/lib/commonjs/shared/hooks/use-backdrop-pointer-events.js.map +1 -0
- package/lib/commonjs/shared/providers/gestures.provider.js +4 -2
- package/lib/commonjs/shared/providers/gestures.provider.js.map +1 -1
- package/lib/commonjs/shared/providers/screen/screen-composer.js +2 -2
- package/lib/commonjs/shared/providers/screen/screen-composer.js.map +1 -1
- package/lib/commonjs/shared/providers/screen/styles.provider.js +41 -32
- package/lib/commonjs/shared/providers/screen/styles.provider.js.map +1 -1
- package/lib/commonjs/shared/utils/animation/{start-screen-transition.js → animate-to-progress.js} +11 -7
- package/lib/commonjs/shared/utils/animation/animate-to-progress.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js +71 -0
- package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js.map +1 -1
- package/lib/commonjs/shared/utils/gesture/determine-snap-target.js +56 -0
- package/lib/commonjs/shared/utils/gesture/determine-snap-target.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/validate-snap-points.js +31 -0
- package/lib/commonjs/shared/utils/gesture/validate-snap-points.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/velocity.js +11 -0
- package/lib/commonjs/shared/utils/gesture/velocity.js.map +1 -1
- package/lib/module/shared/components/create-transition-aware-component.js +8 -2
- package/lib/module/shared/components/create-transition-aware-component.js.map +1 -1
- package/lib/module/shared/components/screen-container.js +64 -0
- package/lib/module/shared/components/screen-container.js.map +1 -0
- package/lib/module/shared/configs/presets.js +3 -3
- package/lib/module/shared/configs/presets.js.map +1 -1
- package/lib/module/shared/configs/specs.js +5 -0
- package/lib/module/shared/configs/specs.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-build-gestures.js +36 -187
- package/lib/module/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js +328 -0
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -0
- package/lib/module/shared/hooks/gestures/use-scroll-registry.js +47 -4
- package/lib/module/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
- package/lib/module/shared/hooks/lifecycle/use-close-transition.js +3 -3
- package/lib/module/shared/hooks/lifecycle/use-close-transition.js.map +1 -1
- package/lib/module/shared/hooks/lifecycle/use-open-transition.js +25 -3
- package/lib/module/shared/hooks/lifecycle/use-open-transition.js.map +1 -1
- package/lib/module/shared/hooks/navigation/use-screen-state.js +63 -4
- package/lib/module/shared/hooks/navigation/use-screen-state.js.map +1 -1
- package/lib/module/shared/hooks/use-backdrop-pointer-events.js +28 -0
- package/lib/module/shared/hooks/use-backdrop-pointer-events.js.map +1 -0
- package/lib/module/shared/providers/gestures.provider.js +4 -2
- package/lib/module/shared/providers/gestures.provider.js.map +1 -1
- package/lib/module/shared/providers/screen/screen-composer.js +2 -2
- package/lib/module/shared/providers/screen/screen-composer.js.map +1 -1
- package/lib/module/shared/providers/screen/styles.provider.js +41 -32
- package/lib/module/shared/providers/screen/styles.provider.js.map +1 -1
- package/lib/module/shared/utils/animation/{start-screen-transition.js → animate-to-progress.js} +9 -5
- package/lib/module/shared/utils/animation/animate-to-progress.js.map +1 -0
- package/lib/module/shared/utils/gesture/check-gesture-activation.js +70 -0
- package/lib/module/shared/utils/gesture/check-gesture-activation.js.map +1 -1
- package/lib/module/shared/utils/gesture/determine-snap-target.js +52 -0
- package/lib/module/shared/utils/gesture/determine-snap-target.js.map +1 -0
- package/lib/module/shared/utils/gesture/validate-snap-points.js +26 -0
- package/lib/module/shared/utils/gesture/validate-snap-points.js.map +1 -0
- package/lib/module/shared/utils/gesture/velocity.js +11 -0
- package/lib/module/shared/utils/gesture/velocity.js.map +1 -1
- package/lib/typescript/shared/components/create-transition-aware-component.d.ts.map +1 -1
- package/lib/typescript/shared/components/screen-container.d.ts +6 -0
- package/lib/typescript/shared/components/screen-container.d.ts.map +1 -0
- package/lib/typescript/shared/configs/specs.d.ts +1 -0
- package/lib/typescript/shared/configs/specs.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts +1 -1
- package/lib/typescript/shared/hooks/gestures/use-build-gestures.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts +34 -0
- package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts.map +1 -0
- package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts +5 -1
- package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/lifecycle/use-open-transition.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/navigation/use-screen-state.d.ts +14 -0
- package/lib/typescript/shared/hooks/navigation/use-screen-state.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/use-backdrop-pointer-events.d.ts +15 -0
- package/lib/typescript/shared/hooks/use-backdrop-pointer-events.d.ts.map +1 -0
- package/lib/typescript/shared/providers/gestures.provider.d.ts +1 -0
- package/lib/typescript/shared/providers/gestures.provider.d.ts.map +1 -1
- package/lib/typescript/shared/providers/screen/styles.provider.d.ts.map +1 -1
- package/lib/typescript/shared/types/animation.types.d.ts +28 -2
- package/lib/typescript/shared/types/animation.types.d.ts.map +1 -1
- package/lib/typescript/shared/types/screen.types.d.ts +26 -0
- package/lib/typescript/shared/types/screen.types.d.ts.map +1 -1
- package/lib/typescript/shared/utils/animation/animate-to-progress.d.ts +19 -0
- package/lib/typescript/shared/utils/animation/animate-to-progress.d.ts.map +1 -0
- package/lib/typescript/shared/utils/gesture/check-gesture-activation.d.ts +24 -0
- package/lib/typescript/shared/utils/gesture/check-gesture-activation.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts +26 -0
- package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts.map +1 -0
- package/lib/typescript/shared/utils/gesture/validate-snap-points.d.ts +13 -0
- package/lib/typescript/shared/utils/gesture/validate-snap-points.d.ts.map +1 -0
- package/lib/typescript/shared/utils/gesture/velocity.d.ts +1 -0
- package/lib/typescript/shared/utils/gesture/velocity.d.ts.map +1 -1
- package/package.json +29 -2
- package/src/shared/__tests__/determine-snap-target.test.ts +268 -0
- package/src/shared/__tests__/gesture-activation.test.ts +247 -0
- package/src/shared/__tests__/validate-snap-points.test.ts +125 -0
- package/src/shared/components/create-transition-aware-component.tsx +11 -1
- package/src/shared/components/screen-container.tsx +65 -0
- package/src/shared/configs/presets.ts +3 -3
- package/src/shared/configs/specs.ts +6 -0
- package/src/shared/hooks/gestures/use-build-gestures.tsx +33 -253
- package/src/shared/hooks/gestures/use-screen-gesture-handlers.ts +436 -0
- package/src/shared/hooks/gestures/use-scroll-registry.tsx +52 -1
- package/src/shared/hooks/lifecycle/use-close-transition.ts +3 -3
- package/src/shared/hooks/lifecycle/use-open-transition.ts +27 -3
- package/src/shared/hooks/navigation/use-screen-state.tsx +106 -2
- package/src/shared/hooks/use-backdrop-pointer-events.ts +32 -0
- package/src/shared/providers/gestures.provider.tsx +3 -2
- package/src/shared/providers/screen/screen-composer.tsx +2 -2
- package/src/shared/providers/screen/styles.provider.tsx +40 -34
- package/src/shared/types/animation.types.ts +29 -2
- package/src/shared/types/screen.types.ts +29 -0
- package/src/shared/utils/animation/{start-screen-transition.ts → animate-to-progress.ts} +19 -7
- package/src/shared/utils/gesture/check-gesture-activation.ts +78 -0
- package/src/shared/utils/gesture/determine-snap-target.ts +75 -0
- package/src/shared/utils/gesture/validate-snap-points.ts +37 -0
- package/src/shared/utils/gesture/velocity.ts +10 -0
- package/lib/commonjs/shared/components/root-transition-aware.js.map +0 -1
- package/lib/commonjs/shared/hooks/use-stack-pointer-events.js +0 -23
- package/lib/commonjs/shared/hooks/use-stack-pointer-events.js.map +0 -1
- package/lib/commonjs/shared/utils/animation/start-screen-transition.js.map +0 -1
- package/lib/module/shared/components/root-transition-aware.js +0 -48
- package/lib/module/shared/components/root-transition-aware.js.map +0 -1
- package/lib/module/shared/hooks/use-stack-pointer-events.js +0 -20
- package/lib/module/shared/hooks/use-stack-pointer-events.js.map +0 -1
- package/lib/module/shared/utils/animation/start-screen-transition.js.map +0 -1
- package/lib/typescript/shared/components/root-transition-aware.d.ts +0 -6
- package/lib/typescript/shared/components/root-transition-aware.d.ts.map +0 -1
- package/lib/typescript/shared/hooks/use-stack-pointer-events.d.ts +0 -10
- package/lib/typescript/shared/hooks/use-stack-pointer-events.d.ts.map +0 -1
- package/lib/typescript/shared/utils/animation/start-screen-transition.d.ts +0 -13
- package/lib/typescript/shared/utils/animation/start-screen-transition.d.ts.map +0 -1
- package/src/shared/components/root-transition-aware.tsx +0 -49
- package/src/shared/hooks/use-stack-pointer-events.ts +0 -15
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import type { Route } from "@react-navigation/native";
|
|
2
|
-
import { useMemo } from "react";
|
|
3
|
-
import {
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
3
|
+
import {
|
|
4
|
+
runOnUI,
|
|
5
|
+
type SharedValue,
|
|
6
|
+
useDerivedValue,
|
|
7
|
+
} from "react-native-reanimated";
|
|
8
|
+
import { DefaultSnapSpec } from "../../configs/specs";
|
|
4
9
|
import {
|
|
5
10
|
type BaseDescriptor,
|
|
6
11
|
useKeys,
|
|
7
12
|
} from "../../providers/screen/keys.provider";
|
|
13
|
+
import { AnimationStore } from "../../stores/animation.store";
|
|
8
14
|
import type { ScreenTransitionConfig } from "../../types/screen.types";
|
|
9
15
|
import type { BaseStackNavigation } from "../../types/stack.types";
|
|
16
|
+
import { animateToProgress } from "../../utils/animation/animate-to-progress";
|
|
10
17
|
import { useSharedValueState } from "../reanimated/use-shared-value-state";
|
|
11
18
|
import { type StackContextValue, useStack } from "./use-stack";
|
|
12
19
|
|
|
@@ -47,6 +54,21 @@ export interface ScreenState<
|
|
|
47
54
|
* Navigation object for this screen.
|
|
48
55
|
*/
|
|
49
56
|
navigation: TNavigation;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Programmatically snap to a specific snap point by index.
|
|
60
|
+
* Only works if the screen has snapPoints defined.
|
|
61
|
+
*
|
|
62
|
+
* @param index - The index of the snap point to snap to (0-based)
|
|
63
|
+
*/
|
|
64
|
+
snapTo: (index: number) => void;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Animated value representing the current snap point index.
|
|
68
|
+
* Interpolates between indices during gestures (e.g., 0.5 means halfway between snap 0 and 1).
|
|
69
|
+
* Returns -1 if no snap points are defined.
|
|
70
|
+
*/
|
|
71
|
+
animatedSnapIndex: SharedValue<number>;
|
|
50
72
|
}
|
|
51
73
|
|
|
52
74
|
/**
|
|
@@ -77,6 +99,84 @@ export function useScreenState<
|
|
|
77
99
|
return scenes[focusedIndex] ?? scenes[scenes.length - 1];
|
|
78
100
|
}, [scenes, focusedIndex]);
|
|
79
101
|
|
|
102
|
+
const currentOptions = current.options;
|
|
103
|
+
const snapPoints = currentOptions?.snapPoints;
|
|
104
|
+
const animations = useMemo(
|
|
105
|
+
() => AnimationStore.getAll(current.route.key),
|
|
106
|
+
[current.route.key],
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Pre-sort snap points for the derived value (avoids sorting in worklet)
|
|
110
|
+
const sortedSnapPoints = useMemo(
|
|
111
|
+
() => (snapPoints ? [...snapPoints].sort((a, b) => a - b) : []),
|
|
112
|
+
[snapPoints],
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const animatedSnapIndex = useDerivedValue(() => {
|
|
116
|
+
if (sortedSnapPoints.length === 0) {
|
|
117
|
+
return -1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const progress = animations.progress.value;
|
|
121
|
+
|
|
122
|
+
// Below first snap point
|
|
123
|
+
if (progress <= sortedSnapPoints[0]) {
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Above last snap point
|
|
128
|
+
if (progress >= sortedSnapPoints[sortedSnapPoints.length - 1]) {
|
|
129
|
+
return sortedSnapPoints.length - 1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Find segment and interpolate
|
|
133
|
+
for (let i = 0; i < sortedSnapPoints.length - 1; i++) {
|
|
134
|
+
if (progress <= sortedSnapPoints[i + 1]) {
|
|
135
|
+
const t =
|
|
136
|
+
(progress - sortedSnapPoints[i]) /
|
|
137
|
+
(sortedSnapPoints[i + 1] - sortedSnapPoints[i]);
|
|
138
|
+
return i + t;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return sortedSnapPoints.length - 1;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const snapTo = useCallback(
|
|
146
|
+
(targetIndex: number) => {
|
|
147
|
+
if (!sortedSnapPoints || sortedSnapPoints.length === 0) {
|
|
148
|
+
console.warn("snapTo called but no snapPoints defined");
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (targetIndex < 0 || targetIndex >= sortedSnapPoints.length) {
|
|
153
|
+
console.warn(
|
|
154
|
+
`snapTo index ${targetIndex} out of bounds (0-${sortedSnapPoints.length - 1})`,
|
|
155
|
+
);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const targetProgress = sortedSnapPoints[targetIndex];
|
|
160
|
+
|
|
161
|
+
runOnUI(() => {
|
|
162
|
+
"worklet";
|
|
163
|
+
animateToProgress({
|
|
164
|
+
target: targetProgress,
|
|
165
|
+
animations,
|
|
166
|
+
spec: {
|
|
167
|
+
open:
|
|
168
|
+
focusedScene.descriptor.options.transitionSpec?.expand ??
|
|
169
|
+
DefaultSnapSpec,
|
|
170
|
+
close:
|
|
171
|
+
focusedScene.descriptor.options.transitionSpec?.collapse ??
|
|
172
|
+
DefaultSnapSpec,
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
})();
|
|
176
|
+
},
|
|
177
|
+
[sortedSnapPoints, animations, focusedScene],
|
|
178
|
+
);
|
|
179
|
+
|
|
80
180
|
return useMemo(
|
|
81
181
|
() => ({
|
|
82
182
|
index,
|
|
@@ -86,6 +186,8 @@ export function useScreenState<
|
|
|
86
186
|
focusedIndex,
|
|
87
187
|
meta: focusedScene?.descriptor?.options?.meta,
|
|
88
188
|
navigation: current.navigation as TNavigation,
|
|
189
|
+
snapTo,
|
|
190
|
+
animatedSnapIndex,
|
|
89
191
|
}),
|
|
90
192
|
[
|
|
91
193
|
index,
|
|
@@ -94,6 +196,8 @@ export function useScreenState<
|
|
|
94
196
|
focusedIndex,
|
|
95
197
|
current.navigation,
|
|
96
198
|
current.route,
|
|
199
|
+
snapTo,
|
|
200
|
+
animatedSnapIndex,
|
|
97
201
|
],
|
|
98
202
|
);
|
|
99
203
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useKeys } from "../providers/screen/keys.provider";
|
|
2
|
+
import { useStackCoreContext } from "../providers/stack/core.provider";
|
|
3
|
+
import { StackType } from "../types/stack.types";
|
|
4
|
+
|
|
5
|
+
type BackdropBehavior = "block" | "passthrough" | "dismiss";
|
|
6
|
+
|
|
7
|
+
interface BackdropPointerEventsResult {
|
|
8
|
+
pointerEvents: "box-none" | undefined;
|
|
9
|
+
backdropBehavior: BackdropBehavior;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns pointer events and backdrop behavior based on screen options.
|
|
14
|
+
*
|
|
15
|
+
* - Explicit `backdropBehavior` option takes precedence
|
|
16
|
+
* - Component stacks default to 'passthrough' (box-none)
|
|
17
|
+
* - Other stacks default to 'block' (undefined = normal touch handling)
|
|
18
|
+
*/
|
|
19
|
+
export function useBackdropPointerEvents(): BackdropPointerEventsResult {
|
|
20
|
+
const { current } = useKeys();
|
|
21
|
+
const { flags } = useStackCoreContext();
|
|
22
|
+
|
|
23
|
+
const isComponentStack = flags.STACK_TYPE === StackType.COMPONENT;
|
|
24
|
+
const backdropBehavior: BackdropBehavior =
|
|
25
|
+
current.options.backdropBehavior ??
|
|
26
|
+
(isComponentStack ? "passthrough" : "block");
|
|
27
|
+
|
|
28
|
+
const pointerEvents =
|
|
29
|
+
backdropBehavior === "passthrough" ? "box-none" : undefined;
|
|
30
|
+
|
|
31
|
+
return { pointerEvents, backdropBehavior };
|
|
32
|
+
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import type { SharedValue } from "react-native-reanimated";
|
|
7
7
|
import { useSharedValue } from "react-native-reanimated";
|
|
8
8
|
import { useBuildGestures } from "../hooks/gestures/use-build-gestures";
|
|
9
|
-
import {
|
|
9
|
+
import { useBackdropPointerEvents } from "../hooks/use-backdrop-pointer-events";
|
|
10
10
|
import type { GestureStoreMap } from "../stores/gesture.store";
|
|
11
11
|
import createProvider from "../utils/create-provider";
|
|
12
12
|
import { useKeys } from "./screen/keys.provider";
|
|
@@ -18,6 +18,7 @@ export type ScrollConfig = {
|
|
|
18
18
|
contentWidth: number;
|
|
19
19
|
layoutHeight: number;
|
|
20
20
|
layoutWidth: number;
|
|
21
|
+
isTouched: boolean;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
export interface GestureContextType {
|
|
@@ -42,9 +43,9 @@ export const {
|
|
|
42
43
|
GestureContextType
|
|
43
44
|
>(({ children }) => {
|
|
44
45
|
const { current } = useKeys();
|
|
45
|
-
const pointerEvents = useStackPointerEvents();
|
|
46
46
|
const ancestorContext = useGestureContext();
|
|
47
47
|
const scrollConfig = useSharedValue<ScrollConfig | null>(null);
|
|
48
|
+
const { pointerEvents } = useBackdropPointerEvents();
|
|
48
49
|
|
|
49
50
|
const hasGestures = current.options.gestureEnabled === true;
|
|
50
51
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { ScreenContainer } from "../../components/screen-container";
|
|
3
3
|
import { ScreenLifecycle } from "../../components/screen-lifecycle";
|
|
4
4
|
import { ScreenGestureProvider } from "../gestures.provider";
|
|
5
5
|
import { type BaseDescriptor, KeysProvider } from "./keys.provider";
|
|
@@ -23,7 +23,7 @@ export function ScreenComposer<TDescriptor extends BaseDescriptor>({
|
|
|
23
23
|
<KeysProvider previous={previous} current={current} next={next}>
|
|
24
24
|
<ScreenGestureProvider>
|
|
25
25
|
<ScreenStylesProvider>
|
|
26
|
-
<
|
|
26
|
+
<ScreenContainer>{children}</ScreenContainer>
|
|
27
27
|
</ScreenStylesProvider>
|
|
28
28
|
</ScreenGestureProvider>
|
|
29
29
|
</KeysProvider>
|
|
@@ -28,56 +28,62 @@ export function ScreenStylesProvider({ children }: Props) {
|
|
|
28
28
|
const { screenInterpolatorProps, nextInterpolator, currentInterpolator } =
|
|
29
29
|
_useScreenAnimation();
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Tracks when user starts a gesture while another screen is still closing.
|
|
33
|
+
* This persists until both the gesture ends AND the closing animation completes.
|
|
34
|
+
*/
|
|
35
|
+
const isGesturingDuringCloseAnimation = useSharedValue(false);
|
|
33
36
|
|
|
34
37
|
const stylesMap = useDerivedValue<TransitionInterpolatedStyle>(() => {
|
|
35
38
|
"worklet";
|
|
36
39
|
const props = screenInterpolatorProps.value;
|
|
37
|
-
const
|
|
40
|
+
const { current, next, progress, stackProgress } = props;
|
|
41
|
+
const isDragging = current.gesture.isDragging;
|
|
42
|
+
const isNextClosing = !!next?.closing;
|
|
38
43
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
hasTriggeredGestureWhileInFlight.value = true;
|
|
44
|
+
if (isDragging && isNextClosing) {
|
|
45
|
+
isGesturingDuringCloseAnimation.value = true;
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
!props.current.gesture.isDragging &&
|
|
47
|
-
!props.next?.closing &&
|
|
48
|
-
hasTriggeredGestureWhileInFlight.value
|
|
49
|
-
) {
|
|
50
|
-
hasTriggeredGestureWhileInFlight.value = false;
|
|
48
|
+
if (!isDragging && !isNextClosing) {
|
|
49
|
+
isGesturingDuringCloseAnimation.value = false;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
// otherwise use next interpolator if available (normal case)
|
|
55
|
-
const shouldUseCurrentInterpolator =
|
|
56
|
-
props.current.gesture.isDragging ||
|
|
57
|
-
hasTriggeredGestureWhileInFlight.value;
|
|
52
|
+
const isInGestureMode = isDragging || isGesturingDuringCloseAnimation.value;
|
|
58
53
|
|
|
59
|
-
const
|
|
54
|
+
const hasPushedScreenWhileClosing =
|
|
55
|
+
!isInGestureMode && isNextClosing && stackProgress > progress;
|
|
56
|
+
|
|
57
|
+
// Select interpolator
|
|
58
|
+
// - If in gesture mode, use current screen's interpolator since we're driving
|
|
59
|
+
// the animation from this screen (dragging back to dismiss next).
|
|
60
|
+
const interpolator = isInGestureMode
|
|
60
61
|
? currentInterpolator
|
|
61
62
|
: (nextInterpolator ?? currentInterpolator);
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
if (!interpolator) return NO_STYLES;
|
|
65
|
+
|
|
66
|
+
// Build effective props with corrected progress
|
|
67
|
+
// - Gesture mode: use current.progress only (avoids jumps during drag)
|
|
68
|
+
// - Pushed while closing: use stackProgress (includes new screen)
|
|
69
|
+
// - Normal: use derived progress as-is
|
|
70
|
+
|
|
71
|
+
let effectiveProgress = progress;
|
|
72
|
+
let effectiveNext = next;
|
|
73
|
+
|
|
74
|
+
if (isInGestureMode) {
|
|
75
|
+
effectiveProgress = current.progress;
|
|
76
|
+
effectiveNext = undefined;
|
|
77
|
+
} else if (hasPushedScreenWhileClosing) {
|
|
78
|
+
effectiveProgress = stackProgress;
|
|
79
|
+
}
|
|
75
80
|
|
|
76
81
|
try {
|
|
77
|
-
if (!interpolator) return NO_STYLES;
|
|
78
82
|
return interpolator({
|
|
79
|
-
...
|
|
80
|
-
|
|
83
|
+
...props,
|
|
84
|
+
progress: effectiveProgress,
|
|
85
|
+
next: effectiveNext,
|
|
86
|
+
bounds: createBounds(props),
|
|
81
87
|
});
|
|
82
88
|
} catch (err) {
|
|
83
89
|
if (__DEV__) {
|
|
@@ -182,7 +182,18 @@ export type TransitionInterpolatedStyle = {
|
|
|
182
182
|
contentStyle?: StyleProps;
|
|
183
183
|
|
|
184
184
|
/**
|
|
185
|
-
* Animated style for
|
|
185
|
+
* Animated style for the semi-transparent backdrop layer behind screen content.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* backdropStyle: {
|
|
189
|
+
* backgroundColor: "black",
|
|
190
|
+
* opacity: interpolate(progress, [0, 1], [0, 0.5]),
|
|
191
|
+
* }
|
|
192
|
+
*/
|
|
193
|
+
backdropStyle?: StyleProps;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @deprecated Use `backdropStyle` instead. Will be removed in next major version.
|
|
186
197
|
*/
|
|
187
198
|
overlayStyle?: StyleProps;
|
|
188
199
|
|
|
@@ -198,9 +209,25 @@ export type TransitionInterpolatedStyle = {
|
|
|
198
209
|
export type AnimationConfig = WithSpringConfig | WithTimingConfig;
|
|
199
210
|
|
|
200
211
|
/**
|
|
201
|
-
* Defines separate animation configurations for
|
|
212
|
+
* Defines separate animation configurations for screen transitions and snap point changes.
|
|
202
213
|
*/
|
|
203
214
|
export interface TransitionSpec {
|
|
215
|
+
/**
|
|
216
|
+
* Animation config for opening/entering a screen.
|
|
217
|
+
*/
|
|
204
218
|
open?: AnimationConfig;
|
|
219
|
+
/**
|
|
220
|
+
* Animation config for closing/exiting a screen.
|
|
221
|
+
*/
|
|
205
222
|
close?: AnimationConfig;
|
|
223
|
+
/**
|
|
224
|
+
* Animation config for expanding to a higher snap point.
|
|
225
|
+
* Uses lower intensity than `open` to match smaller movement distances.
|
|
226
|
+
*/
|
|
227
|
+
expand?: AnimationConfig;
|
|
228
|
+
/**
|
|
229
|
+
* Animation config for collapsing to a lower snap point.
|
|
230
|
+
* Uses lower intensity than `close` to match smaller movement distances.
|
|
231
|
+
*/
|
|
232
|
+
collapse?: AnimationConfig;
|
|
206
233
|
}
|
|
@@ -136,4 +136,33 @@ export type ScreenTransitionConfig = {
|
|
|
136
136
|
* @default false
|
|
137
137
|
*/
|
|
138
138
|
experimental_enableHighRefreshRate?: boolean;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Describes heights where a screen can rest, as fractions of screen height.
|
|
142
|
+
* Pass an array of ascending values from 0 to 1.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* snapPoints={[0.5, 1.0]} // 50% and 100% of screen height
|
|
146
|
+
*
|
|
147
|
+
* @default [1.0]
|
|
148
|
+
*/
|
|
149
|
+
snapPoints?: number[];
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The initial snap point index when the screen opens.
|
|
153
|
+
*
|
|
154
|
+
* @default 0
|
|
155
|
+
*/
|
|
156
|
+
initialSnapIndex?: number;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Controls how touches interact with the backdrop area (outside the screen content).
|
|
160
|
+
*
|
|
161
|
+
* - `'block'`: Backdrop catches all touches (default for most screens)
|
|
162
|
+
* - `'passthrough'`: Touches pass through to content behind (default for component stacks)
|
|
163
|
+
* - `'dismiss'`: Tapping backdrop dismisses the screen
|
|
164
|
+
*
|
|
165
|
+
* @default 'block' (or 'passthrough' for component stacks)
|
|
166
|
+
*/
|
|
167
|
+
backdropBehavior?: "block" | "passthrough" | "dismiss";
|
|
139
168
|
};
|
|
@@ -4,8 +4,14 @@ import type { AnimationStoreMap } from "../../stores/animation.store";
|
|
|
4
4
|
import type { TransitionSpec } from "../../types/animation.types";
|
|
5
5
|
import { animate } from "./animate";
|
|
6
6
|
|
|
7
|
-
interface
|
|
8
|
-
|
|
7
|
+
interface AnimateToProgressProps {
|
|
8
|
+
/**
|
|
9
|
+
* Target for the animation:
|
|
10
|
+
* - "open" = animate to progress 1
|
|
11
|
+
* - "close" = animate to progress 0
|
|
12
|
+
* - number = animate to specific progress value (e.g., 0.5 for snap point)
|
|
13
|
+
*/
|
|
14
|
+
target: "open" | "close" | number;
|
|
9
15
|
spec?: TransitionSpec;
|
|
10
16
|
onAnimationFinish?: (finished: boolean) => void;
|
|
11
17
|
animations: AnimationStoreMap;
|
|
@@ -13,16 +19,22 @@ interface StartScreenTransitionProps {
|
|
|
13
19
|
initialVelocity?: number;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
export const
|
|
22
|
+
export const animateToProgress = ({
|
|
17
23
|
target,
|
|
18
24
|
spec,
|
|
19
25
|
onAnimationFinish,
|
|
20
26
|
animations,
|
|
21
27
|
initialVelocity,
|
|
22
|
-
}:
|
|
28
|
+
}: AnimateToProgressProps) => {
|
|
23
29
|
"worklet";
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
|
|
31
|
+
// Determine target value and direction
|
|
32
|
+
const isClosing =
|
|
33
|
+
target === "close" || (typeof target === "number" && target === 0);
|
|
34
|
+
const value = typeof target === "number" ? target : target === "open" ? 1 : 0;
|
|
35
|
+
|
|
36
|
+
// Select spec based on direction (closing uses close spec, otherwise open)
|
|
37
|
+
const config = isClosing ? spec?.close : spec?.open;
|
|
26
38
|
|
|
27
39
|
const isSpringConfig =
|
|
28
40
|
!!config && !("duration" in config) && !("easing" in config);
|
|
@@ -34,7 +46,7 @@ export const startScreenTransition = ({
|
|
|
34
46
|
|
|
35
47
|
const { progress, animating, closing, entering } = animations;
|
|
36
48
|
|
|
37
|
-
if (
|
|
49
|
+
if (isClosing) {
|
|
38
50
|
closing.set(TRUE);
|
|
39
51
|
entering.set(FALSE);
|
|
40
52
|
} else {
|
|
@@ -308,3 +308,81 @@ export const applyOffsetRules = ({
|
|
|
308
308
|
isSwipingLeft,
|
|
309
309
|
};
|
|
310
310
|
};
|
|
311
|
+
|
|
312
|
+
interface ScrollAwareActivationParams {
|
|
313
|
+
swipeInfo: {
|
|
314
|
+
isSwipingDown: boolean;
|
|
315
|
+
isSwipingUp: boolean;
|
|
316
|
+
isSwipingRight: boolean;
|
|
317
|
+
isSwipingLeft: boolean;
|
|
318
|
+
};
|
|
319
|
+
directions: Directions;
|
|
320
|
+
scrollX: number;
|
|
321
|
+
scrollY: number;
|
|
322
|
+
maxScrollX: number;
|
|
323
|
+
maxScrollY: number;
|
|
324
|
+
hasSnapPoints?: boolean;
|
|
325
|
+
canExpandMore?: boolean;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
type GestureDirection =
|
|
329
|
+
| "vertical"
|
|
330
|
+
| "vertical-inverted"
|
|
331
|
+
| "horizontal"
|
|
332
|
+
| "horizontal-inverted";
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Checks if a gesture should activate based on scroll position.
|
|
336
|
+
* Returns the direction to activate for, or null if activation should not occur.
|
|
337
|
+
*/
|
|
338
|
+
export function checkScrollAwareActivation({
|
|
339
|
+
swipeInfo,
|
|
340
|
+
directions,
|
|
341
|
+
scrollX,
|
|
342
|
+
scrollY,
|
|
343
|
+
maxScrollX,
|
|
344
|
+
maxScrollY,
|
|
345
|
+
hasSnapPoints,
|
|
346
|
+
canExpandMore,
|
|
347
|
+
}: ScrollAwareActivationParams): {
|
|
348
|
+
shouldActivate: boolean;
|
|
349
|
+
direction: GestureDirection | null;
|
|
350
|
+
} {
|
|
351
|
+
"worklet";
|
|
352
|
+
|
|
353
|
+
const { isSwipingDown, isSwipingUp, isSwipingRight, isSwipingLeft } =
|
|
354
|
+
swipeInfo;
|
|
355
|
+
|
|
356
|
+
if (directions.vertical && isSwipingDown && scrollY <= 0) {
|
|
357
|
+
return { shouldActivate: true, direction: "vertical" };
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (directions.horizontal && isSwipingRight && scrollX <= 0) {
|
|
361
|
+
return { shouldActivate: true, direction: "horizontal" };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (directions.verticalInverted && isSwipingUp && scrollY >= maxScrollY) {
|
|
365
|
+
return { shouldActivate: true, direction: "vertical-inverted" };
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (directions.horizontalInverted && isSwipingLeft && scrollX >= maxScrollX) {
|
|
369
|
+
return { shouldActivate: true, direction: "horizontal-inverted" };
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (hasSnapPoints && canExpandMore) {
|
|
373
|
+
// Vertical sheet: swipe up at scroll top → expand
|
|
374
|
+
const enabledYAxis = directions.vertical || directions.verticalInverted;
|
|
375
|
+
const enabledXAxis = directions.horizontal || directions.horizontalInverted;
|
|
376
|
+
|
|
377
|
+
if (enabledYAxis && isSwipingUp && scrollY <= 0) {
|
|
378
|
+
return { shouldActivate: true, direction: "vertical-inverted" };
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Horizontal sheet: swipe left at scroll left → expand
|
|
382
|
+
if (enabledXAxis && isSwipingLeft && scrollX <= 0) {
|
|
383
|
+
return { shouldActivate: true, direction: "horizontal-inverted" };
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return { shouldActivate: false, direction: null };
|
|
388
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
interface DetermineSnapTargetProps {
|
|
2
|
+
currentProgress: number;
|
|
3
|
+
snapPoints: number[];
|
|
4
|
+
/** Velocity along the snap axis (positive = toward dismiss) */
|
|
5
|
+
velocity: number;
|
|
6
|
+
/** Screen dimension along the snap axis (width or height) */
|
|
7
|
+
dimension: number;
|
|
8
|
+
/** How much velocity affects the snap decision (0-1). Default 0.15 */
|
|
9
|
+
velocityFactor?: number;
|
|
10
|
+
/** Whether dismiss (progress=0) is allowed. Default true */
|
|
11
|
+
canDismiss?: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface DetermineSnapTargetResult {
|
|
15
|
+
targetProgress: number;
|
|
16
|
+
shouldDismiss: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Determines which snap point to animate to based on current progress and velocity.
|
|
21
|
+
*
|
|
22
|
+
* Logic: Snap to whichever point is closest, factoring in velocity.
|
|
23
|
+
* The "zones" between snap points are split at midpoints.
|
|
24
|
+
* Velocity can push you into the next zone.
|
|
25
|
+
*/
|
|
26
|
+
export function determineSnapTarget({
|
|
27
|
+
currentProgress,
|
|
28
|
+
snapPoints,
|
|
29
|
+
velocity,
|
|
30
|
+
dimension,
|
|
31
|
+
velocityFactor = 0.15,
|
|
32
|
+
canDismiss = true,
|
|
33
|
+
}: DetermineSnapTargetProps): DetermineSnapTargetResult {
|
|
34
|
+
"worklet";
|
|
35
|
+
|
|
36
|
+
// Convert velocity to progress units (positive = toward dismiss = decreasing progress)
|
|
37
|
+
const velocityInProgress = (velocity / dimension) * velocityFactor;
|
|
38
|
+
|
|
39
|
+
// Project where we'd end up with velocity
|
|
40
|
+
const projectedProgress = currentProgress - velocityInProgress;
|
|
41
|
+
|
|
42
|
+
// Build all possible targets: dismiss (0) only if allowed, plus all snap points
|
|
43
|
+
const allTargets = canDismiss
|
|
44
|
+
? [0, ...snapPoints].sort((a, b) => a - b)
|
|
45
|
+
: [...snapPoints].sort((a, b) => a - b);
|
|
46
|
+
|
|
47
|
+
// Find the target whose zone contains the projected progress
|
|
48
|
+
// Zones are split at midpoints between adjacent targets
|
|
49
|
+
let targetProgress = allTargets[0];
|
|
50
|
+
|
|
51
|
+
for (let i = 0; i < allTargets.length; i++) {
|
|
52
|
+
const current = allTargets[i];
|
|
53
|
+
const next = allTargets[i + 1];
|
|
54
|
+
|
|
55
|
+
if (next === undefined) {
|
|
56
|
+
// Last target - if we're above the midpoint to here, snap to it
|
|
57
|
+
targetProgress = current;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const midpoint = (current + next) / 2;
|
|
62
|
+
|
|
63
|
+
if (projectedProgress < midpoint) {
|
|
64
|
+
targetProgress = current;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
targetProgress = next;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
targetProgress,
|
|
73
|
+
shouldDismiss: targetProgress === 0,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
interface ValidateSnapPointsResult {
|
|
2
|
+
hasSnapPoints: boolean;
|
|
3
|
+
snapPoints: number[];
|
|
4
|
+
minSnapPoint: number;
|
|
5
|
+
maxSnapPoint: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface ValidateSnapPointsOptions {
|
|
9
|
+
snapPoints?: number[];
|
|
10
|
+
canDismiss?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const validateSnapPoints = ({
|
|
14
|
+
snapPoints,
|
|
15
|
+
canDismiss,
|
|
16
|
+
}: ValidateSnapPointsOptions): ValidateSnapPointsResult => {
|
|
17
|
+
if (!snapPoints) {
|
|
18
|
+
return {
|
|
19
|
+
hasSnapPoints: false,
|
|
20
|
+
snapPoints: [],
|
|
21
|
+
minSnapPoint: -1,
|
|
22
|
+
maxSnapPoint: -1,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const sortedSnaps = snapPoints.slice().sort((a, b) => a - b);
|
|
27
|
+
// Clamp to snap point bounds (dismiss at 0 only if allowed)
|
|
28
|
+
const minProgress = canDismiss ? 0 : sortedSnaps[0];
|
|
29
|
+
const maxProgress = sortedSnaps[sortedSnaps.length - 1];
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
hasSnapPoints: true,
|
|
33
|
+
snapPoints: sortedSnaps,
|
|
34
|
+
minSnapPoint: minProgress,
|
|
35
|
+
maxSnapPoint: maxProgress,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
@@ -34,6 +34,15 @@ const normalize = (velocityPixelsPerSecond: number, screenSize: number) => {
|
|
|
34
34
|
);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Normalizes translation to -1...1 range (for gesture tracking).
|
|
39
|
+
* Used to convert pixel translation to normalized gesture values.
|
|
40
|
+
*/
|
|
41
|
+
const normalizeTranslation = (translation: number, dimension: number) => {
|
|
42
|
+
"worklet";
|
|
43
|
+
return clamp(translation / Math.max(1, dimension), -1, 1);
|
|
44
|
+
};
|
|
45
|
+
|
|
37
46
|
/**
|
|
38
47
|
* Calculates a normalized velocity that moves the current value toward zero.
|
|
39
48
|
* Used for spring-back animations when dismissing gestures.
|
|
@@ -137,6 +146,7 @@ const shouldPassDismissalThreshold = (
|
|
|
137
146
|
|
|
138
147
|
export const velocity = {
|
|
139
148
|
normalize,
|
|
149
|
+
normalizeTranslation,
|
|
140
150
|
calculateRestoreVelocity,
|
|
141
151
|
calculateProgressVelocity,
|
|
142
152
|
shouldPassDismissalThreshold,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_reactNative","_reactNativeReanimated","_interopRequireWildcard","_constants","_useStackPointerEvents","_styles","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","RootTransitionAware","exports","memo","children","stylesMap","useScreenStyles","pointerEvents","useStackPointerEvents","animatedContentStyle","useAnimatedStyle","value","contentStyle","NO_STYLES","animatedOverlayStyle","overlayStyle","jsxs","View","style","styles","container","jsx","StyleSheet","absoluteFillObject","content","create","flex"],"sourceRoot":"../../../../src","sources":["shared/components/root-transition-aware.tsx"],"mappings":"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","ignoreList":[]}
|