react-native-screen-transitions 3.2.1 → 3.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -10
- package/lib/commonjs/blank-stack/components/adjusted-screen.js +2 -2
- package/lib/commonjs/blank-stack/components/adjusted-screen.js.map +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/constants.js +36 -10
- package/lib/commonjs/shared/constants.js.map +1 -1
- package/lib/commonjs/shared/hooks/animation/use-screen-animation.js +25 -18
- package/lib/commonjs/shared/hooks/animation/use-screen-animation.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js +25 -202
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js +342 -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 +33 -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/utils/animation/{start-screen-transition.js → animate-to-progress.js} +16 -8
- package/lib/commonjs/shared/utils/animation/animate-to-progress.js.map +1 -0
- package/lib/commonjs/shared/utils/gesture/check-gesture-activation.js +138 -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/commonjs/shared/utils/logger.js +22 -0
- package/lib/commonjs/shared/utils/logger.js.map +1 -0
- package/lib/module/blank-stack/components/adjusted-screen.js +1 -1
- package/lib/module/blank-stack/components/adjusted-screen.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/constants.js +34 -9
- package/lib/module/shared/constants.js.map +1 -1
- package/lib/module/shared/hooks/animation/use-screen-animation.js +25 -18
- package/lib/module/shared/hooks/animation/use-screen-animation.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-build-gestures.js +25 -201
- package/lib/module/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js +336 -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 +35 -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/utils/animation/{start-screen-transition.js → animate-to-progress.js} +14 -6
- package/lib/module/shared/utils/animation/animate-to-progress.js.map +1 -0
- package/lib/module/shared/utils/gesture/check-gesture-activation.js +137 -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/module/shared/utils/logger.js +17 -0
- package/lib/module/shared/utils/logger.js.map +1 -0
- package/lib/typescript/blank-stack/components/adjusted-screen.d.ts.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/constants.d.ts +9 -0
- package/lib/typescript/shared/constants.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/animation/use-screen-animation.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 +19 -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 +7 -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/types/animation.types.d.ts +37 -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 +23 -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/lib/typescript/shared/utils/logger.d.ts +6 -0
- package/lib/typescript/shared/utils/logger.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/blank-stack/components/adjusted-screen.tsx +1 -1
- package/src/shared/__tests__/derivations.test.ts +1 -0
- package/src/shared/__tests__/determine-snap-target.test.ts +268 -0
- package/src/shared/__tests__/gesture-activation.test.ts +220 -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/constants.ts +36 -9
- package/src/shared/hooks/animation/use-screen-animation.tsx +32 -21
- package/src/shared/hooks/gestures/use-build-gestures.tsx +23 -275
- package/src/shared/hooks/gestures/use-screen-gesture-handlers.ts +434 -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 +59 -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/types/animation.types.ts +39 -2
- package/src/shared/types/screen.types.ts +29 -0
- package/src/shared/utils/animation/{start-screen-transition.ts → animate-to-progress.ts} +23 -8
- package/src/shared/utils/gesture/check-gesture-activation.ts +129 -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/src/shared/utils/logger.ts +15 -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
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { validateSnapPoints } from "../utils/gesture/validate-snap-points";
|
|
3
|
+
|
|
4
|
+
describe("validateSnapPoints", () => {
|
|
5
|
+
describe("when no snap points provided", () => {
|
|
6
|
+
it("returns hasSnapPoints false", () => {
|
|
7
|
+
const result = validateSnapPoints({});
|
|
8
|
+
expect(result.hasSnapPoints).toBe(false);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("returns empty snapPoints array", () => {
|
|
12
|
+
const result = validateSnapPoints({});
|
|
13
|
+
expect(result.snapPoints).toEqual([]);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("returns -1 for min and max", () => {
|
|
17
|
+
const result = validateSnapPoints({});
|
|
18
|
+
expect(result.minSnapPoint).toBe(-1);
|
|
19
|
+
expect(result.maxSnapPoint).toBe(-1);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("handles undefined snapPoints", () => {
|
|
23
|
+
const result = validateSnapPoints({ snapPoints: undefined });
|
|
24
|
+
expect(result.hasSnapPoints).toBe(false);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("when snap points provided", () => {
|
|
29
|
+
it("returns hasSnapPoints true", () => {
|
|
30
|
+
const result = validateSnapPoints({ snapPoints: [0.3, 0.6, 1] });
|
|
31
|
+
expect(result.hasSnapPoints).toBe(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("sorts snap points in ascending order", () => {
|
|
35
|
+
const result = validateSnapPoints({ snapPoints: [1, 0.3, 0.6] });
|
|
36
|
+
expect(result.snapPoints).toEqual([0.3, 0.6, 1]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("returns correct max snap point", () => {
|
|
40
|
+
const result = validateSnapPoints({ snapPoints: [0.3, 0.6, 1] });
|
|
41
|
+
expect(result.maxSnapPoint).toBe(1);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("handles single snap point", () => {
|
|
45
|
+
const result = validateSnapPoints({ snapPoints: [0.5] });
|
|
46
|
+
expect(result.hasSnapPoints).toBe(true);
|
|
47
|
+
expect(result.snapPoints).toEqual([0.5]);
|
|
48
|
+
expect(result.minSnapPoint).toBe(0.5);
|
|
49
|
+
expect(result.maxSnapPoint).toBe(0.5);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("does not mutate original array", () => {
|
|
53
|
+
const original = [1, 0.3, 0.6];
|
|
54
|
+
validateSnapPoints({ snapPoints: original });
|
|
55
|
+
expect(original).toEqual([1, 0.3, 0.6]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("canDismiss behavior", () => {
|
|
60
|
+
it("sets minSnapPoint to 0 when canDismiss is true", () => {
|
|
61
|
+
const result = validateSnapPoints({
|
|
62
|
+
snapPoints: [0.3, 0.6, 1],
|
|
63
|
+
canDismiss: true,
|
|
64
|
+
});
|
|
65
|
+
expect(result.minSnapPoint).toBe(0);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("sets minSnapPoint to first snap point when canDismiss is false", () => {
|
|
69
|
+
const result = validateSnapPoints({
|
|
70
|
+
snapPoints: [0.3, 0.6, 1],
|
|
71
|
+
canDismiss: false,
|
|
72
|
+
});
|
|
73
|
+
expect(result.minSnapPoint).toBe(0.3);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("defaults canDismiss to falsy (minSnapPoint = first snap)", () => {
|
|
77
|
+
const result = validateSnapPoints({ snapPoints: [0.3, 0.6, 1] });
|
|
78
|
+
expect(result.minSnapPoint).toBe(0.3);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("handles canDismiss with unsorted snap points", () => {
|
|
82
|
+
const result = validateSnapPoints({
|
|
83
|
+
snapPoints: [1, 0.5, 0.25],
|
|
84
|
+
canDismiss: false,
|
|
85
|
+
});
|
|
86
|
+
// After sorting: [0.25, 0.5, 1]
|
|
87
|
+
expect(result.minSnapPoint).toBe(0.25);
|
|
88
|
+
expect(result.maxSnapPoint).toBe(1);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("edge cases", () => {
|
|
93
|
+
it("handles empty array", () => {
|
|
94
|
+
const result = validateSnapPoints({ snapPoints: [] });
|
|
95
|
+
// Empty array is falsy for snap points
|
|
96
|
+
expect(result.hasSnapPoints).toBe(true); // Array exists but is empty
|
|
97
|
+
expect(result.snapPoints).toEqual([]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("handles snap points at 0", () => {
|
|
101
|
+
const result = validateSnapPoints({
|
|
102
|
+
snapPoints: [0, 0.5, 1],
|
|
103
|
+
canDismiss: true,
|
|
104
|
+
});
|
|
105
|
+
expect(result.minSnapPoint).toBe(0);
|
|
106
|
+
expect(result.snapPoints).toEqual([0, 0.5, 1]);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("handles duplicate snap points", () => {
|
|
110
|
+
const result = validateSnapPoints({ snapPoints: [0.5, 0.5, 1] });
|
|
111
|
+
expect(result.snapPoints).toEqual([0.5, 0.5, 1]);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("handles very small snap point values", () => {
|
|
115
|
+
const result = validateSnapPoints({ snapPoints: [0.01, 0.1, 0.5] });
|
|
116
|
+
expect(result.minSnapPoint).toBe(0.01);
|
|
117
|
+
expect(result.maxSnapPoint).toBe(0.5);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("handles snap points greater than 1", () => {
|
|
121
|
+
const result = validateSnapPoints({ snapPoints: [0.5, 1, 1.5] });
|
|
122
|
+
expect(result.maxSnapPoint).toBe(1.5);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -27,10 +27,18 @@ export function createTransitionAwareComponent<P extends object>(
|
|
|
27
27
|
TransitionAwareProps<P>
|
|
28
28
|
>((props: any, ref) => {
|
|
29
29
|
const { nativeGesture } = useGestureContext()!;
|
|
30
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
scrollHandler,
|
|
32
|
+
onContentSizeChange,
|
|
33
|
+
onLayout,
|
|
34
|
+
onTouchStart,
|
|
35
|
+
onTouchEnd,
|
|
36
|
+
} = useScrollRegistry({
|
|
31
37
|
onScroll: props.onScroll,
|
|
32
38
|
onContentSizeChange: props.onContentSizeChange,
|
|
33
39
|
onLayout: props.onLayout,
|
|
40
|
+
onTouchStart: props.onTouchStart,
|
|
41
|
+
onTouchEnd: props.onTouchEnd,
|
|
34
42
|
});
|
|
35
43
|
|
|
36
44
|
return (
|
|
@@ -41,6 +49,8 @@ export function createTransitionAwareComponent<P extends object>(
|
|
|
41
49
|
onScroll={scrollHandler}
|
|
42
50
|
onContentSizeChange={onContentSizeChange}
|
|
43
51
|
onLayout={onLayout}
|
|
52
|
+
onTouchStart={onTouchStart}
|
|
53
|
+
onTouchEnd={onTouchEnd}
|
|
44
54
|
scrollEventThrottle={props.scrollEventThrottle || 16}
|
|
45
55
|
/>
|
|
46
56
|
</GestureDetector>
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { StackActions } from "@react-navigation/native";
|
|
2
|
+
import { memo, useCallback } from "react";
|
|
3
|
+
import { Pressable, StyleSheet, View } from "react-native";
|
|
4
|
+
import Animated, { useAnimatedStyle } from "react-native-reanimated";
|
|
5
|
+
import { NO_STYLES } from "../constants";
|
|
6
|
+
import { useBackdropPointerEvents } from "../hooks/use-backdrop-pointer-events";
|
|
7
|
+
import { useKeys } from "../providers/screen/keys.provider";
|
|
8
|
+
import { useScreenStyles } from "../providers/screen/styles.provider";
|
|
9
|
+
|
|
10
|
+
type Props = {
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const ScreenContainer = memo(({ children }: Props) => {
|
|
15
|
+
const { stylesMap } = useScreenStyles();
|
|
16
|
+
const { current } = useKeys();
|
|
17
|
+
const { pointerEvents, backdropBehavior } = useBackdropPointerEvents();
|
|
18
|
+
|
|
19
|
+
const isDismissable = backdropBehavior === "dismiss";
|
|
20
|
+
|
|
21
|
+
const handleBackdropPress = useCallback(() => {
|
|
22
|
+
current.navigation.dispatch(StackActions.pop());
|
|
23
|
+
}, [current.navigation]);
|
|
24
|
+
|
|
25
|
+
const animatedContentStyle = useAnimatedStyle(() => {
|
|
26
|
+
"worklet";
|
|
27
|
+
return stylesMap.value.contentStyle || NO_STYLES;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const animatedBackdropStyle = useAnimatedStyle(() => {
|
|
31
|
+
"worklet";
|
|
32
|
+
return (
|
|
33
|
+
stylesMap.value.backdropStyle ?? stylesMap.value.overlayStyle ?? NO_STYLES
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<View style={styles.container} pointerEvents={pointerEvents}>
|
|
39
|
+
<Pressable
|
|
40
|
+
style={StyleSheet.absoluteFillObject}
|
|
41
|
+
pointerEvents={isDismissable ? "auto" : "none"}
|
|
42
|
+
onPress={isDismissable ? handleBackdropPress : undefined}
|
|
43
|
+
>
|
|
44
|
+
<Animated.View
|
|
45
|
+
style={[StyleSheet.absoluteFillObject, animatedBackdropStyle]}
|
|
46
|
+
/>
|
|
47
|
+
</Pressable>
|
|
48
|
+
<Animated.View
|
|
49
|
+
style={[styles.content, animatedContentStyle]}
|
|
50
|
+
pointerEvents={isDismissable ? "box-none" : pointerEvents}
|
|
51
|
+
>
|
|
52
|
+
{children}
|
|
53
|
+
</Animated.View>
|
|
54
|
+
</View>
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const styles = StyleSheet.create({
|
|
59
|
+
container: {
|
|
60
|
+
flex: 1,
|
|
61
|
+
},
|
|
62
|
+
content: {
|
|
63
|
+
flex: 1,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -208,7 +208,7 @@ export const ElasticCard = (
|
|
|
208
208
|
contentStyle: {
|
|
209
209
|
transform: [{ scale }, { translateX }, { translateY }],
|
|
210
210
|
},
|
|
211
|
-
|
|
211
|
+
backdropStyle: {
|
|
212
212
|
backgroundColor: !next ? overlayColor : "rgba(0,0,0,0)",
|
|
213
213
|
},
|
|
214
214
|
};
|
|
@@ -281,7 +281,7 @@ export const SharedIGImage = ({
|
|
|
281
281
|
});
|
|
282
282
|
|
|
283
283
|
return {
|
|
284
|
-
|
|
284
|
+
backdropStyle: {
|
|
285
285
|
backgroundColor: "black",
|
|
286
286
|
opacity: interpolate(progress, [0, 1], [0, 0.5]),
|
|
287
287
|
},
|
|
@@ -634,7 +634,7 @@ export const SharedXImage = ({
|
|
|
634
634
|
transform: [{ translateY: contentY }, { translateY: dragY }],
|
|
635
635
|
pointerEvents: current.animating ? "none" : "auto",
|
|
636
636
|
},
|
|
637
|
-
|
|
637
|
+
backdropStyle: {
|
|
638
638
|
backgroundColor: overlayClr,
|
|
639
639
|
},
|
|
640
640
|
};
|
package/src/shared/constants.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { MeasuredDimensions } from "react-native-reanimated";
|
|
|
4
4
|
import type { ScreenTransitionState } from "./types/animation.types";
|
|
5
5
|
import type { ActivationArea } from "./types/gesture.types";
|
|
6
6
|
import type { Layout } from "./types/screen.types";
|
|
7
|
+
import type { BaseStackRoute } from "./types/stack.types";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Masked view integration
|
|
@@ -16,6 +17,35 @@ export const CONTAINER_STYLE_ID = "_ROOT_CONTAINER";
|
|
|
16
17
|
*/
|
|
17
18
|
export const NO_STYLES = Object.freeze({});
|
|
18
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Default gesture values
|
|
22
|
+
*/
|
|
23
|
+
const DEFAULT_GESTURE_VALUES = {
|
|
24
|
+
x: 0,
|
|
25
|
+
y: 0,
|
|
26
|
+
normalizedX: 0,
|
|
27
|
+
normalizedY: 0,
|
|
28
|
+
isDismissing: 0,
|
|
29
|
+
isDragging: 0,
|
|
30
|
+
direction: null,
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new screen transition state object
|
|
35
|
+
*/
|
|
36
|
+
export const createScreenTransitionState = (
|
|
37
|
+
route: BaseStackRoute,
|
|
38
|
+
meta?: Record<string, unknown>,
|
|
39
|
+
): ScreenTransitionState => ({
|
|
40
|
+
progress: 0,
|
|
41
|
+
closing: 0,
|
|
42
|
+
animating: 0,
|
|
43
|
+
entering: 1,
|
|
44
|
+
gesture: { ...DEFAULT_GESTURE_VALUES },
|
|
45
|
+
route,
|
|
46
|
+
meta,
|
|
47
|
+
});
|
|
48
|
+
|
|
19
49
|
/**
|
|
20
50
|
* Default screen transition state
|
|
21
51
|
*/
|
|
@@ -25,15 +55,7 @@ export const DEFAULT_SCREEN_TRANSITION_STATE: ScreenTransitionState =
|
|
|
25
55
|
closing: 0,
|
|
26
56
|
animating: 0,
|
|
27
57
|
entering: 1,
|
|
28
|
-
gesture:
|
|
29
|
-
x: 0,
|
|
30
|
-
y: 0,
|
|
31
|
-
normalizedX: 0,
|
|
32
|
-
normalizedY: 0,
|
|
33
|
-
isDismissing: 0,
|
|
34
|
-
isDragging: 0,
|
|
35
|
-
direction: null,
|
|
36
|
-
},
|
|
58
|
+
gesture: DEFAULT_GESTURE_VALUES,
|
|
37
59
|
route: {} as RouteProp<ParamListBase>,
|
|
38
60
|
});
|
|
39
61
|
|
|
@@ -79,3 +101,8 @@ export const IS_WEB = Platform.OS === "web";
|
|
|
79
101
|
|
|
80
102
|
export const TRUE = 1;
|
|
81
103
|
export const FALSE = 0;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Small value for floating-point comparisons to handle animation/interpolation imprecision
|
|
107
|
+
*/
|
|
108
|
+
export const EPSILON = 1e-5;
|
|
@@ -3,7 +3,10 @@ import { useWindowDimensions } from "react-native";
|
|
|
3
3
|
import { type SharedValue, useDerivedValue } from "react-native-reanimated";
|
|
4
4
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
5
5
|
import type { NativeStackScreenTransitionConfig } from "../../../native-stack/types";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
createScreenTransitionState,
|
|
8
|
+
DEFAULT_SCREEN_TRANSITION_STATE,
|
|
9
|
+
} from "../../constants";
|
|
7
10
|
import {
|
|
8
11
|
type BaseDescriptor,
|
|
9
12
|
useKeys,
|
|
@@ -31,26 +34,26 @@ type BuiltState = {
|
|
|
31
34
|
unwrapped: ScreenTransitionState;
|
|
32
35
|
};
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
37
|
+
/**
|
|
38
|
+
* Computes the animated snap index based on progress and snap points.
|
|
39
|
+
* Returns -1 if no snap points, otherwise interpolates between indices.
|
|
40
|
+
*/
|
|
41
|
+
const computeSnapIndex = (progress: number, snapPoints: number[]): number => {
|
|
42
|
+
"worklet";
|
|
43
|
+
if (snapPoints.length === 0) return -1;
|
|
44
|
+
if (progress <= snapPoints[0]) return 0;
|
|
45
|
+
if (progress >= snapPoints[snapPoints.length - 1])
|
|
46
|
+
return snapPoints.length - 1;
|
|
47
|
+
|
|
48
|
+
for (let i = 0; i < snapPoints.length - 1; i++) {
|
|
49
|
+
if (progress <= snapPoints[i + 1]) {
|
|
50
|
+
const t =
|
|
51
|
+
(progress - snapPoints[i]) / (snapPoints[i + 1] - snapPoints[i]);
|
|
52
|
+
return i + t;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return snapPoints.length - 1;
|
|
56
|
+
};
|
|
54
57
|
|
|
55
58
|
const unwrapInto = (s: BuiltState): ScreenTransitionState => {
|
|
56
59
|
"worklet";
|
|
@@ -123,6 +126,11 @@ export function _useScreenAnimation() {
|
|
|
123
126
|
const currentRouteKey = currentDescriptor?.route?.key;
|
|
124
127
|
const currentIndex = routeKeys.indexOf(currentRouteKey);
|
|
125
128
|
|
|
129
|
+
const sortedSnapPoints = useMemo(() => {
|
|
130
|
+
const points = currentDescriptor?.options?.snapPoints;
|
|
131
|
+
return points ? [...points].sort((a, b) => a - b) : [];
|
|
132
|
+
}, [currentDescriptor?.options?.snapPoints]);
|
|
133
|
+
|
|
126
134
|
const screenInterpolatorProps = useDerivedValue<
|
|
127
135
|
Omit<ScreenInterpolationProps, "bounds">
|
|
128
136
|
>(() => {
|
|
@@ -152,6 +160,8 @@ export function _useScreenAnimation() {
|
|
|
152
160
|
const stackProgress =
|
|
153
161
|
currentIndex >= 0 ? rootStackProgress.value - currentIndex : progress;
|
|
154
162
|
|
|
163
|
+
const snapIndex = computeSnapIndex(current.progress, sortedSnapPoints);
|
|
164
|
+
|
|
155
165
|
return {
|
|
156
166
|
layouts: { screen: dimensions },
|
|
157
167
|
insets,
|
|
@@ -160,6 +170,7 @@ export function _useScreenAnimation() {
|
|
|
160
170
|
next,
|
|
161
171
|
progress,
|
|
162
172
|
stackProgress,
|
|
173
|
+
snapIndex,
|
|
163
174
|
...helpers,
|
|
164
175
|
};
|
|
165
176
|
});
|