react-native-screen-transitions 3.3.0-rc.2 → 3.3.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/LICENSE +21 -0
- package/README.md +51 -7
- package/lib/commonjs/blank-stack/components/stack-view.js +2 -1
- package/lib/commonjs/blank-stack/components/stack-view.js.map +1 -1
- package/lib/commonjs/blank-stack/components/stack-view.native.js +2 -1
- package/lib/commonjs/blank-stack/components/stack-view.native.js.map +1 -1
- package/lib/commonjs/component-stack/components/stack-view.js +2 -1
- package/lib/commonjs/component-stack/components/stack-view.js.map +1 -1
- package/lib/commonjs/shared/animation/resolve-snap-target.js +48 -0
- package/lib/commonjs/shared/animation/resolve-snap-target.js.map +1 -0
- package/lib/commonjs/shared/animation/snap-to.js +35 -34
- package/lib/commonjs/shared/animation/snap-to.js.map +1 -1
- package/lib/commonjs/shared/components/create-transition-aware-component.js +15 -7
- package/lib/commonjs/shared/components/create-transition-aware-component.js.map +1 -1
- package/lib/commonjs/shared/components/overlay/helpers/get-active-overlay.js +3 -2
- package/lib/commonjs/shared/components/overlay/helpers/get-active-overlay.js.map +1 -1
- package/lib/commonjs/shared/components/overlay/variations/float-overlay.js +46 -9
- package/lib/commonjs/shared/components/overlay/variations/float-overlay.js.map +1 -1
- package/lib/commonjs/shared/components/overlay/variations/overlay-host.js +7 -7
- package/lib/commonjs/shared/components/overlay/variations/overlay-host.js.map +1 -1
- package/lib/commonjs/shared/components/overlay/variations/screen-overlay.js +23 -3
- package/lib/commonjs/shared/components/overlay/variations/screen-overlay.js.map +1 -1
- package/lib/commonjs/shared/components/screen-container.js +2 -1
- package/lib/commonjs/shared/components/screen-container.js.map +1 -1
- package/lib/commonjs/shared/hooks/animation/use-screen-animation.js +6 -6
- package/lib/commonjs/shared/hooks/animation/use-screen-animation.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js +7 -1
- package/lib/commonjs/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js +37 -8
- package/lib/commonjs/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -1
- package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js +12 -13
- package/lib/commonjs/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
- package/lib/commonjs/shared/hooks/lifecycle/use-close-transition.js +5 -2
- package/lib/commonjs/shared/hooks/lifecycle/use-close-transition.js.map +1 -1
- package/lib/commonjs/shared/hooks/lifecycle/use-screen-events.js +14 -4
- package/lib/commonjs/shared/hooks/lifecycle/use-screen-events.js.map +1 -1
- package/lib/commonjs/shared/hooks/navigation/use-optimistic-focused-index.js +20 -0
- package/lib/commonjs/shared/hooks/navigation/use-optimistic-focused-index.js.map +1 -0
- package/lib/commonjs/shared/hooks/navigation/use-screen-state.js +11 -8
- package/lib/commonjs/shared/hooks/navigation/use-screen-state.js.map +1 -1
- package/lib/commonjs/shared/hooks/reanimated/use-shared-value-state.js +4 -1
- package/lib/commonjs/shared/hooks/reanimated/use-shared-value-state.js.map +1 -1
- package/lib/commonjs/shared/providers/gestures.provider.js +17 -6
- package/lib/commonjs/shared/providers/gestures.provider.js.map +1 -1
- package/lib/commonjs/shared/providers/layout-anchor.provider.js +7 -5
- package/lib/commonjs/shared/providers/layout-anchor.provider.js.map +1 -1
- package/lib/commonjs/shared/providers/register-bounds.provider.js +25 -6
- package/lib/commonjs/shared/providers/register-bounds.provider.js.map +1 -1
- package/lib/commonjs/shared/providers/screen/styles.provider.js +1 -6
- package/lib/commonjs/shared/providers/screen/styles.provider.js.map +1 -1
- package/lib/commonjs/shared/providers/stack/direct.provider.js +15 -16
- package/lib/commonjs/shared/providers/stack/direct.provider.js.map +1 -1
- package/lib/commonjs/shared/providers/stack/managed.provider.js +19 -16
- package/lib/commonjs/shared/providers/stack/managed.provider.js.map +1 -1
- package/lib/commonjs/shared/stores/bounds.store.js +46 -0
- package/lib/commonjs/shared/stores/bounds.store.js.map +1 -1
- package/lib/commonjs/shared/utils/bounds/index.js +6 -4
- package/lib/commonjs/shared/utils/bounds/index.js.map +1 -1
- package/lib/commonjs/shared/utils/gesture/determine-snap-target.js +9 -2
- package/lib/commonjs/shared/utils/gesture/determine-snap-target.js.map +1 -1
- package/lib/commonjs/shared/utils/gesture/find-collapse-target.js +11 -1
- package/lib/commonjs/shared/utils/gesture/find-collapse-target.js.map +1 -1
- package/lib/commonjs/shared/utils/gesture/validate-snap-points.js +11 -2
- package/lib/commonjs/shared/utils/gesture/validate-snap-points.js.map +1 -1
- package/lib/commonjs/shared/utils/overlay/visibility.js +19 -0
- package/lib/commonjs/shared/utils/overlay/visibility.js.map +1 -0
- package/lib/module/blank-stack/components/stack-view.js +2 -1
- package/lib/module/blank-stack/components/stack-view.js.map +1 -1
- package/lib/module/blank-stack/components/stack-view.native.js +2 -1
- package/lib/module/blank-stack/components/stack-view.native.js.map +1 -1
- package/lib/module/component-stack/components/stack-view.js +2 -1
- package/lib/module/component-stack/components/stack-view.js.map +1 -1
- package/lib/module/shared/animation/resolve-snap-target.js +44 -0
- package/lib/module/shared/animation/resolve-snap-target.js.map +1 -0
- package/lib/module/shared/animation/snap-to.js +34 -34
- package/lib/module/shared/animation/snap-to.js.map +1 -1
- package/lib/module/shared/components/create-transition-aware-component.js +16 -8
- package/lib/module/shared/components/create-transition-aware-component.js.map +1 -1
- package/lib/module/shared/components/overlay/helpers/get-active-overlay.js +4 -2
- package/lib/module/shared/components/overlay/helpers/get-active-overlay.js.map +1 -1
- package/lib/module/shared/components/overlay/variations/float-overlay.js +47 -11
- package/lib/module/shared/components/overlay/variations/float-overlay.js.map +1 -1
- package/lib/module/shared/components/overlay/variations/overlay-host.js +7 -7
- package/lib/module/shared/components/overlay/variations/overlay-host.js.map +1 -1
- package/lib/module/shared/components/overlay/variations/screen-overlay.js +24 -5
- package/lib/module/shared/components/overlay/variations/screen-overlay.js.map +1 -1
- package/lib/module/shared/components/screen-container.js +2 -1
- package/lib/module/shared/components/screen-container.js.map +1 -1
- package/lib/module/shared/hooks/animation/use-screen-animation.js +6 -6
- package/lib/module/shared/hooks/animation/use-screen-animation.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-build-gestures.js +7 -1
- package/lib/module/shared/hooks/gestures/use-build-gestures.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js +37 -8
- package/lib/module/shared/hooks/gestures/use-screen-gesture-handlers.js.map +1 -1
- package/lib/module/shared/hooks/gestures/use-scroll-registry.js +12 -13
- package/lib/module/shared/hooks/gestures/use-scroll-registry.js.map +1 -1
- package/lib/module/shared/hooks/lifecycle/use-close-transition.js +5 -2
- package/lib/module/shared/hooks/lifecycle/use-close-transition.js.map +1 -1
- package/lib/module/shared/hooks/lifecycle/use-screen-events.js +13 -4
- package/lib/module/shared/hooks/lifecycle/use-screen-events.js.map +1 -1
- package/lib/module/shared/hooks/navigation/use-optimistic-focused-index.js +17 -0
- package/lib/module/shared/hooks/navigation/use-optimistic-focused-index.js.map +1 -0
- package/lib/module/shared/hooks/navigation/use-screen-state.js +12 -9
- package/lib/module/shared/hooks/navigation/use-screen-state.js.map +1 -1
- package/lib/module/shared/hooks/reanimated/use-shared-value-state.js +4 -1
- package/lib/module/shared/hooks/reanimated/use-shared-value-state.js.map +1 -1
- package/lib/module/shared/providers/gestures.provider.js +17 -6
- package/lib/module/shared/providers/gestures.provider.js.map +1 -1
- package/lib/module/shared/providers/layout-anchor.provider.js +7 -5
- package/lib/module/shared/providers/layout-anchor.provider.js.map +1 -1
- package/lib/module/shared/providers/register-bounds.provider.js +25 -6
- package/lib/module/shared/providers/register-bounds.provider.js.map +1 -1
- package/lib/module/shared/providers/screen/styles.provider.js +1 -6
- package/lib/module/shared/providers/screen/styles.provider.js.map +1 -1
- package/lib/module/shared/providers/stack/direct.provider.js +15 -16
- package/lib/module/shared/providers/stack/direct.provider.js.map +1 -1
- package/lib/module/shared/providers/stack/managed.provider.js +19 -16
- package/lib/module/shared/providers/stack/managed.provider.js.map +1 -1
- package/lib/module/shared/stores/bounds.store.js +46 -0
- package/lib/module/shared/stores/bounds.store.js.map +1 -1
- package/lib/module/shared/utils/bounds/index.js +6 -4
- package/lib/module/shared/utils/bounds/index.js.map +1 -1
- package/lib/module/shared/utils/gesture/determine-snap-target.js +9 -2
- package/lib/module/shared/utils/gesture/determine-snap-target.js.map +1 -1
- package/lib/module/shared/utils/gesture/find-collapse-target.js +11 -1
- package/lib/module/shared/utils/gesture/find-collapse-target.js.map +1 -1
- package/lib/module/shared/utils/gesture/validate-snap-points.js +11 -2
- package/lib/module/shared/utils/gesture/validate-snap-points.js.map +1 -1
- package/lib/module/shared/utils/overlay/visibility.js +12 -0
- package/lib/module/shared/utils/overlay/visibility.js.map +1 -0
- package/lib/typescript/blank-stack/components/stack-view.d.ts.map +1 -1
- package/lib/typescript/blank-stack/components/stack-view.native.d.ts.map +1 -1
- package/lib/typescript/component-stack/components/stack-view.d.ts.map +1 -1
- package/lib/typescript/shared/animation/resolve-snap-target.d.ts +3 -0
- package/lib/typescript/shared/animation/resolve-snap-target.d.ts.map +1 -0
- package/lib/typescript/shared/animation/snap-to.d.ts +2 -0
- package/lib/typescript/shared/animation/snap-to.d.ts.map +1 -1
- package/lib/typescript/shared/components/create-transition-aware-component.d.ts +1 -0
- package/lib/typescript/shared/components/create-transition-aware-component.d.ts.map +1 -1
- package/lib/typescript/shared/components/overlay/helpers/get-active-overlay.d.ts +1 -1
- package/lib/typescript/shared/components/overlay/helpers/get-active-overlay.d.ts.map +1 -1
- package/lib/typescript/shared/components/overlay/variations/float-overlay.d.ts.map +1 -1
- package/lib/typescript/shared/components/overlay/variations/overlay-host.d.ts +7 -0
- package/lib/typescript/shared/components/overlay/variations/overlay-host.d.ts.map +1 -1
- package/lib/typescript/shared/components/overlay/variations/screen-overlay.d.ts.map +1 -1
- package/lib/typescript/shared/components/screen-container.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.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts +1 -1
- package/lib/typescript/shared/hooks/gestures/use-screen-gesture-handlers.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts +0 -2
- package/lib/typescript/shared/hooks/gestures/use-scroll-registry.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/lifecycle/use-close-transition.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/lifecycle/use-screen-events.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/navigation/use-optimistic-focused-index.d.ts +7 -0
- package/lib/typescript/shared/hooks/navigation/use-optimistic-focused-index.d.ts.map +1 -0
- package/lib/typescript/shared/hooks/navigation/use-screen-state.d.ts +6 -0
- package/lib/typescript/shared/hooks/navigation/use-screen-state.d.ts.map +1 -1
- package/lib/typescript/shared/hooks/reanimated/use-shared-value-state.d.ts.map +1 -1
- package/lib/typescript/shared/index.d.ts +4 -0
- package/lib/typescript/shared/index.d.ts.map +1 -1
- package/lib/typescript/shared/providers/gestures.provider.d.ts.map +1 -1
- package/lib/typescript/shared/providers/layout-anchor.provider.d.ts +1 -1
- package/lib/typescript/shared/providers/layout-anchor.provider.d.ts.map +1 -1
- package/lib/typescript/shared/providers/register-bounds.provider.d.ts +1 -0
- package/lib/typescript/shared/providers/register-bounds.provider.d.ts.map +1 -1
- package/lib/typescript/shared/providers/screen/styles.provider.d.ts.map +1 -1
- package/lib/typescript/shared/providers/stack/direct.provider.d.ts.map +1 -1
- package/lib/typescript/shared/providers/stack/managed.provider.d.ts.map +1 -1
- package/lib/typescript/shared/stores/bounds.store.d.ts +2 -0
- package/lib/typescript/shared/stores/bounds.store.d.ts.map +1 -1
- package/lib/typescript/shared/types/screen.types.d.ts +36 -1
- package/lib/typescript/shared/types/screen.types.d.ts.map +1 -1
- package/lib/typescript/shared/utils/bounds/index.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/determine-snap-target.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/find-collapse-target.d.ts.map +1 -1
- package/lib/typescript/shared/utils/gesture/validate-snap-points.d.ts.map +1 -1
- package/lib/typescript/shared/utils/overlay/visibility.d.ts +11 -0
- package/lib/typescript/shared/utils/overlay/visibility.d.ts.map +1 -0
- package/package.json +8 -2
- package/src/blank-stack/components/stack-view.native.tsx +2 -1
- package/src/blank-stack/components/stack-view.tsx +2 -1
- package/src/component-stack/components/stack-view.tsx +2 -1
- package/src/shared/animation/resolve-snap-target.ts +53 -0
- package/src/shared/animation/snap-to.ts +47 -38
- package/src/shared/components/create-transition-aware-component.tsx +34 -10
- package/src/shared/components/overlay/helpers/get-active-overlay.ts +3 -2
- package/src/shared/components/overlay/variations/float-overlay.tsx +53 -8
- package/src/shared/components/overlay/variations/overlay-host.tsx +16 -6
- package/src/shared/components/overlay/variations/screen-overlay.tsx +35 -3
- package/src/shared/components/screen-container.tsx +15 -9
- package/src/shared/hooks/animation/use-screen-animation.tsx +8 -8
- package/src/shared/hooks/gestures/use-build-gestures.tsx +5 -1
- package/src/shared/hooks/gestures/use-screen-gesture-handlers.ts +63 -16
- package/src/shared/hooks/gestures/use-scroll-registry.tsx +10 -9
- package/src/shared/hooks/lifecycle/use-close-transition.ts +6 -3
- package/src/shared/hooks/lifecycle/use-screen-events.ts +15 -4
- package/src/shared/hooks/navigation/use-optimistic-focused-index.ts +19 -0
- package/src/shared/hooks/navigation/use-screen-state.tsx +24 -8
- package/src/shared/hooks/reanimated/use-shared-value-state.ts +4 -1
- package/src/shared/providers/gestures.provider.tsx +49 -22
- package/src/shared/providers/layout-anchor.provider.tsx +28 -25
- package/src/shared/providers/register-bounds.provider.tsx +43 -6
- package/src/shared/providers/screen/styles.provider.tsx +1 -7
- package/src/shared/providers/stack/direct.provider.tsx +18 -19
- package/src/shared/providers/stack/managed.provider.tsx +22 -19
- package/src/shared/stores/bounds.store.ts +56 -0
- package/src/shared/types/screen.types.ts +39 -1
- package/src/shared/utils/bounds/index.ts +6 -4
- package/src/shared/utils/gesture/determine-snap-target.ts +15 -4
- package/src/shared/utils/gesture/find-collapse-target.ts +11 -1
- package/src/shared/utils/gesture/validate-snap-points.ts +15 -2
- package/src/shared/utils/overlay/visibility.ts +23 -0
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
|
+
import { snapDescriptorToIndex } from "../../../animation/snap-to";
|
|
3
|
+
import { useOptimisticFocusedIndex } from "../../../hooks/navigation/use-optimistic-focused-index";
|
|
2
4
|
import {
|
|
3
5
|
type StackDescriptor,
|
|
4
6
|
type StackScene,
|
|
5
7
|
useStack,
|
|
6
8
|
} from "../../../hooks/navigation/use-stack";
|
|
7
9
|
import { useKeys } from "../../../providers/screen/keys.provider";
|
|
10
|
+
import type { OverlayProps } from "../../../types/overlay.types";
|
|
11
|
+
import { isScreenOverlayVisible } from "../../../utils/overlay/visibility";
|
|
8
12
|
import { OverlayHost } from "./overlay-host";
|
|
9
13
|
|
|
14
|
+
type OverlayScreenState = Omit<
|
|
15
|
+
OverlayProps<StackDescriptor["navigation"]>,
|
|
16
|
+
"progress" | "overlayAnimation" | "screenAnimation"
|
|
17
|
+
> & {
|
|
18
|
+
index: number;
|
|
19
|
+
snapTo: (index: number) => void;
|
|
20
|
+
};
|
|
21
|
+
|
|
10
22
|
/**
|
|
11
23
|
* Screen overlay component that renders per-screen.
|
|
12
24
|
* Gets current descriptor from keys context.
|
|
@@ -17,7 +29,11 @@ import { OverlayHost } from "./overlay-host";
|
|
|
17
29
|
*/
|
|
18
30
|
export function ScreenOverlay() {
|
|
19
31
|
const { current } = useKeys<StackDescriptor>();
|
|
20
|
-
const { flags } = useStack();
|
|
32
|
+
const { flags, routes, optimisticFocusedIndex, routeKeys } = useStack();
|
|
33
|
+
const focusedIndex = useOptimisticFocusedIndex(
|
|
34
|
+
optimisticFocusedIndex,
|
|
35
|
+
routeKeys.length,
|
|
36
|
+
);
|
|
21
37
|
|
|
22
38
|
const options = current.options;
|
|
23
39
|
|
|
@@ -29,14 +45,30 @@ export function ScreenOverlay() {
|
|
|
29
45
|
[current],
|
|
30
46
|
);
|
|
31
47
|
|
|
48
|
+
const overlayScreenState = useMemo<OverlayScreenState>(
|
|
49
|
+
() => ({
|
|
50
|
+
index: routeKeys.indexOf(current.route.key),
|
|
51
|
+
options: current.options,
|
|
52
|
+
routes,
|
|
53
|
+
focusedRoute: routes[focusedIndex] ?? current.route,
|
|
54
|
+
focusedIndex,
|
|
55
|
+
meta: current.options?.meta,
|
|
56
|
+
navigation: current.navigation,
|
|
57
|
+
snapTo: (index: number) => {
|
|
58
|
+
snapDescriptorToIndex(current, index);
|
|
59
|
+
},
|
|
60
|
+
}),
|
|
61
|
+
[current, routeKeys, routes, focusedIndex],
|
|
62
|
+
);
|
|
63
|
+
|
|
32
64
|
// Skip screens without enableTransitions (native-stack only)
|
|
33
65
|
if (!flags.TRANSITIONS_ALWAYS_ON && !options.enableTransitions) {
|
|
34
66
|
return null;
|
|
35
67
|
}
|
|
36
68
|
|
|
37
|
-
if (!options
|
|
69
|
+
if (!isScreenOverlayVisible(options)) {
|
|
38
70
|
return null;
|
|
39
71
|
}
|
|
40
72
|
|
|
41
|
-
return <OverlayHost scene={scene} />;
|
|
73
|
+
return <OverlayHost scene={scene} overlayScreenState={overlayScreenState} />;
|
|
42
74
|
}
|
|
@@ -25,6 +25,8 @@ export const ScreenContainer = memo(({ children }: Props) => {
|
|
|
25
25
|
const { pointerEvents, backdropBehavior } = useBackdropPointerEvents();
|
|
26
26
|
const gestureContext = useGestureContext();
|
|
27
27
|
|
|
28
|
+
const BackdropComponent = current.options.backdropComponent;
|
|
29
|
+
|
|
28
30
|
const isBackdropActive =
|
|
29
31
|
backdropBehavior === "dismiss" || backdropBehavior === "collapse";
|
|
30
32
|
|
|
@@ -101,15 +103,19 @@ export const ScreenContainer = memo(({ children }: Props) => {
|
|
|
101
103
|
|
|
102
104
|
return (
|
|
103
105
|
<View style={styles.container} pointerEvents={pointerEvents}>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
106
|
+
{BackdropComponent ? (
|
|
107
|
+
<BackdropComponent />
|
|
108
|
+
) : (
|
|
109
|
+
<Pressable
|
|
110
|
+
style={StyleSheet.absoluteFillObject}
|
|
111
|
+
pointerEvents={isBackdropActive ? "auto" : "none"}
|
|
112
|
+
onPress={isBackdropActive ? handleBackdropPress : undefined}
|
|
113
|
+
>
|
|
114
|
+
<Animated.View
|
|
115
|
+
style={[StyleSheet.absoluteFillObject, animatedBackdropStyle]}
|
|
116
|
+
/>
|
|
117
|
+
</Pressable>
|
|
118
|
+
)}
|
|
113
119
|
<GestureDetector gesture={gestureContext!.panGesture}>
|
|
114
120
|
<Animated.View
|
|
115
121
|
style={[styles.content, animatedContentStyle]}
|
|
@@ -80,11 +80,12 @@ const useBuildScreenTransitionState = (
|
|
|
80
80
|
): BuiltState | undefined => {
|
|
81
81
|
const key = descriptor?.route?.key;
|
|
82
82
|
const meta = descriptor?.options?.meta;
|
|
83
|
+
const route = descriptor?.route;
|
|
83
84
|
|
|
84
85
|
return useMemo(() => {
|
|
85
|
-
if (!key || !
|
|
86
|
+
if (!key || !route) return undefined;
|
|
86
87
|
|
|
87
|
-
const plainRoute = toPlainRoute(
|
|
88
|
+
const plainRoute = toPlainRoute(route);
|
|
88
89
|
const plainMeta = meta
|
|
89
90
|
? (toPlainValue(meta) as Record<string, unknown>)
|
|
90
91
|
: undefined;
|
|
@@ -99,7 +100,7 @@ const useBuildScreenTransitionState = (
|
|
|
99
100
|
meta: plainMeta,
|
|
100
101
|
unwrapped: createScreenTransitionState(plainRoute, plainMeta),
|
|
101
102
|
};
|
|
102
|
-
}, [key, meta,
|
|
103
|
+
}, [key, meta, route]);
|
|
103
104
|
};
|
|
104
105
|
|
|
105
106
|
const hasTransitionsEnabled = (
|
|
@@ -135,11 +136,10 @@ export function _useScreenAnimation() {
|
|
|
135
136
|
return points ? [...points].sort((a, b) => a - b) : [];
|
|
136
137
|
}, [currentDescriptor?.options?.snapPoints]);
|
|
137
138
|
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}, [nextDescriptor, transitionsAlwaysOn]);
|
|
139
|
+
const nextRouteKey = nextDescriptor?.route?.key;
|
|
140
|
+
const nextHasTransitions =
|
|
141
|
+
!!nextRouteKey &&
|
|
142
|
+
hasTransitionsEnabled(nextDescriptor?.options, transitionsAlwaysOn);
|
|
143
143
|
|
|
144
144
|
const screenInterpolatorProps = useDerivedValue<
|
|
145
145
|
Omit<ScreenInterpolationProps, "bounds">
|
|
@@ -12,6 +12,7 @@ import { GestureStore, type GestureStoreMap } from "../../stores/gesture.store";
|
|
|
12
12
|
import type { ClaimedDirections, Direction } from "../../types/ownership.types";
|
|
13
13
|
import { claimsAnyDirection } from "../../utils/gesture/compute-claimed-directions";
|
|
14
14
|
import { resolveOwnership } from "../../utils/gesture/resolve-ownership";
|
|
15
|
+
import { validateSnapPoints } from "../../utils/gesture/validate-snap-points";
|
|
15
16
|
import { useScreenGestureHandlers } from "./use-screen-gesture-handlers";
|
|
16
17
|
|
|
17
18
|
const DIRECTIONS: Direction[] = [
|
|
@@ -94,7 +95,10 @@ export const useBuildGestures = ({
|
|
|
94
95
|
const canDismiss = Boolean(
|
|
95
96
|
isFirstScreen ? false : current.options.gestureEnabled,
|
|
96
97
|
);
|
|
97
|
-
const hasSnapPoints =
|
|
98
|
+
const { hasSnapPoints } = useMemo(
|
|
99
|
+
() => validateSnapPoints({ snapPoints, canDismiss }),
|
|
100
|
+
[snapPoints, canDismiss],
|
|
101
|
+
);
|
|
98
102
|
const gestureEnabled = canDismiss || hasSnapPoints;
|
|
99
103
|
|
|
100
104
|
const ownershipStatus = useMemo(
|
|
@@ -110,8 +110,6 @@ export const useScreenGestureHandlers = ({
|
|
|
110
110
|
canDismiss,
|
|
111
111
|
handleDismiss,
|
|
112
112
|
ownershipStatus,
|
|
113
|
-
claimedDirections,
|
|
114
|
-
ancestorContext,
|
|
115
113
|
childDirectionClaims,
|
|
116
114
|
}: UseScreenGestureHandlersProps) => {
|
|
117
115
|
const dimensions = useWindowDimensions();
|
|
@@ -132,6 +130,7 @@ export const useScreenGestureHandlers = ({
|
|
|
132
130
|
transitionSpec,
|
|
133
131
|
snapPoints: rawSnapPoints,
|
|
134
132
|
expandViaScrollView = true,
|
|
133
|
+
gestureSnapLocked = false,
|
|
135
134
|
} = current.options;
|
|
136
135
|
|
|
137
136
|
const { hasSnapPoints, snapPoints, minSnapPoint, maxSnapPoint } = useMemo(
|
|
@@ -200,11 +199,25 @@ export const useScreenGestureHandlers = ({
|
|
|
200
199
|
? "horizontal"
|
|
201
200
|
: "vertical";
|
|
202
201
|
|
|
202
|
+
const isExpandGesture = (swipeDirection: Direction): boolean => {
|
|
203
|
+
"worklet";
|
|
204
|
+
if (snapAxis === "horizontal") {
|
|
205
|
+
return directions.snapAxisInverted
|
|
206
|
+
? swipeDirection === "horizontal"
|
|
207
|
+
: swipeDirection === "horizontal-inverted";
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return directions.snapAxisInverted
|
|
211
|
+
? swipeDirection === "vertical"
|
|
212
|
+
: swipeDirection === "vertical-inverted";
|
|
213
|
+
};
|
|
214
|
+
|
|
203
215
|
const initialTouch = useSharedValue({ x: 0, y: 0 });
|
|
204
216
|
const gestureOffsetState = useSharedValue<GestureOffsetState>(
|
|
205
217
|
GestureOffsetState.PENDING,
|
|
206
218
|
);
|
|
207
219
|
const gestureStartProgress = useSharedValue(1);
|
|
220
|
+
const lockedSnapPoint = useSharedValue(maxSnapPoint);
|
|
208
221
|
|
|
209
222
|
const onTouchesDown = useStableCallbackValue((e: GestureTouchEvent) => {
|
|
210
223
|
"worklet";
|
|
@@ -280,6 +293,15 @@ export const useScreenGestureHandlers = ({
|
|
|
280
293
|
return;
|
|
281
294
|
}
|
|
282
295
|
|
|
296
|
+
if (
|
|
297
|
+
hasSnapPoints &&
|
|
298
|
+
gestureSnapLocked &&
|
|
299
|
+
isExpandGesture(swipeDirection)
|
|
300
|
+
) {
|
|
301
|
+
manager.fail();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
283
305
|
// Snap sheets can interrupt their own animation; non-snap cannot
|
|
284
306
|
if (!hasSnapPoints && gestureAnimationValues.isDismissing?.value) {
|
|
285
307
|
return;
|
|
@@ -303,23 +325,19 @@ export const useScreenGestureHandlers = ({
|
|
|
303
325
|
|
|
304
326
|
// Step 7: Expand check for snap sheets
|
|
305
327
|
if (hasSnapPoints) {
|
|
306
|
-
|
|
307
|
-
(directions.snapAxisInverted && swipeDirection === "vertical") ||
|
|
308
|
-
(!directions.snapAxisInverted &&
|
|
309
|
-
swipeDirection === "vertical-inverted") ||
|
|
310
|
-
(directions.snapAxisInverted && swipeDirection === "horizontal") ||
|
|
311
|
-
(!directions.snapAxisInverted &&
|
|
312
|
-
swipeDirection === "horizontal-inverted");
|
|
313
|
-
|
|
314
|
-
if (isExpandGesture) {
|
|
328
|
+
if (isExpandGesture(swipeDirection)) {
|
|
315
329
|
if (!expandViaScrollView) {
|
|
316
330
|
manager.fail();
|
|
317
331
|
return;
|
|
318
332
|
}
|
|
319
333
|
|
|
334
|
+
const effectiveMaxSnapPoint = gestureSnapLocked
|
|
335
|
+
? lockedSnapPoint.value
|
|
336
|
+
: maxSnapPoint;
|
|
337
|
+
|
|
320
338
|
const canExpandMore =
|
|
321
|
-
animations.progress.value <
|
|
322
|
-
animations.targetProgress.value <
|
|
339
|
+
animations.progress.value < effectiveMaxSnapPoint - EPSILON &&
|
|
340
|
+
animations.targetProgress.value < effectiveMaxSnapPoint - EPSILON;
|
|
323
341
|
|
|
324
342
|
if (!canExpandMore) {
|
|
325
343
|
manager.fail();
|
|
@@ -336,6 +354,24 @@ export const useScreenGestureHandlers = ({
|
|
|
336
354
|
|
|
337
355
|
const onStart = useStableCallbackValue(() => {
|
|
338
356
|
"worklet";
|
|
357
|
+
if (hasSnapPoints && gestureSnapLocked) {
|
|
358
|
+
let nearest = snapPoints[0] ?? animations.progress.value;
|
|
359
|
+
let smallestDistance = Math.abs(animations.progress.value - nearest);
|
|
360
|
+
|
|
361
|
+
for (let i = 1; i < snapPoints.length; i++) {
|
|
362
|
+
const point = snapPoints[i];
|
|
363
|
+
const distance = Math.abs(animations.progress.value - point);
|
|
364
|
+
if (distance < smallestDistance) {
|
|
365
|
+
smallestDistance = distance;
|
|
366
|
+
nearest = point;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
lockedSnapPoint.value = nearest;
|
|
371
|
+
} else {
|
|
372
|
+
lockedSnapPoint.value = maxSnapPoint;
|
|
373
|
+
}
|
|
374
|
+
|
|
339
375
|
gestureAnimationValues.isDragging.value = TRUE;
|
|
340
376
|
gestureAnimationValues.isDismissing.value = FALSE;
|
|
341
377
|
gestureStartProgress.value = animations.progress.value;
|
|
@@ -369,10 +405,21 @@ export const useScreenGestureHandlers = ({
|
|
|
369
405
|
const baseSign = -1;
|
|
370
406
|
const sign = directions.snapAxisInverted ? -baseSign : baseSign;
|
|
371
407
|
const progressDelta = (sign * translation) / dimension;
|
|
408
|
+
const maxProgressForGesture = gestureSnapLocked
|
|
409
|
+
? lockedSnapPoint.value
|
|
410
|
+
: maxSnapPoint;
|
|
411
|
+
const minProgressForGesture = gestureSnapLocked
|
|
412
|
+
? canDismiss
|
|
413
|
+
? 0
|
|
414
|
+
: lockedSnapPoint.value
|
|
415
|
+
: minSnapPoint;
|
|
372
416
|
|
|
373
417
|
animations.progress.value = Math.max(
|
|
374
|
-
|
|
375
|
-
Math.min(
|
|
418
|
+
minProgressForGesture,
|
|
419
|
+
Math.min(
|
|
420
|
+
maxProgressForGesture,
|
|
421
|
+
gestureStartProgress.value + progressDelta,
|
|
422
|
+
),
|
|
376
423
|
);
|
|
377
424
|
} else if (gestureDrivesProgress) {
|
|
378
425
|
let maxProgress = 0;
|
|
@@ -427,7 +474,7 @@ export const useScreenGestureHandlers = ({
|
|
|
427
474
|
|
|
428
475
|
const result = determineSnapTarget({
|
|
429
476
|
currentProgress: animations.progress.value,
|
|
430
|
-
snapPoints,
|
|
477
|
+
snapPoints: gestureSnapLocked ? [lockedSnapPoint.value] : snapPoints,
|
|
431
478
|
velocity: snapVelocity,
|
|
432
479
|
dimension: axisDimension,
|
|
433
480
|
velocityFactor: snapVelocityImpact,
|
|
@@ -17,7 +17,6 @@ import type { LayoutChangeEvent } from "react-native";
|
|
|
17
17
|
import { Gesture, type GestureType } from "react-native-gesture-handler";
|
|
18
18
|
import type { SharedValue } from "react-native-reanimated";
|
|
19
19
|
import { useAnimatedScrollHandler } from "react-native-reanimated";
|
|
20
|
-
import type { ReanimatedScrollEvent } from "react-native-reanimated/lib/typescript/hook/commonTypes";
|
|
21
20
|
import {
|
|
22
21
|
type GestureContextType,
|
|
23
22
|
type ScrollConfig,
|
|
@@ -76,7 +75,6 @@ function findGestureOwnersForAxis(
|
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
interface ScrollProgressHookProps {
|
|
79
|
-
onScroll?: (event: ReanimatedScrollEvent) => void;
|
|
80
78
|
onContentSizeChange?: (width: number, height: number) => void;
|
|
81
79
|
onLayout?: (event: LayoutChangeEvent) => void;
|
|
82
80
|
direction?: "vertical" | "horizontal";
|
|
@@ -125,18 +123,22 @@ export const useScrollRegistry = (props: ScrollProgressHookProps) => {
|
|
|
125
123
|
const setIsTouched = () => {
|
|
126
124
|
"worklet";
|
|
127
125
|
for (const scrollConfig of scrollConfigs) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
scrollConfig.modify((v) => {
|
|
127
|
+
"worklet";
|
|
128
|
+
if (v) v.isTouched = true;
|
|
129
|
+
return v;
|
|
130
|
+
});
|
|
131
131
|
}
|
|
132
132
|
};
|
|
133
133
|
|
|
134
134
|
const clearIsTouched = () => {
|
|
135
135
|
"worklet";
|
|
136
136
|
for (const scrollConfig of scrollConfigs) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
scrollConfig.modify((v) => {
|
|
138
|
+
"worklet";
|
|
139
|
+
if (v) v.isTouched = false;
|
|
140
|
+
return v;
|
|
141
|
+
});
|
|
140
142
|
}
|
|
141
143
|
};
|
|
142
144
|
|
|
@@ -156,7 +158,6 @@ export const useScrollRegistry = (props: ScrollProgressHookProps) => {
|
|
|
156
158
|
|
|
157
159
|
const scrollHandler = useAnimatedScrollHandler({
|
|
158
160
|
onScroll: (event) => {
|
|
159
|
-
props.onScroll?.(event);
|
|
160
161
|
if (scrollConfigs.length === 0) return;
|
|
161
162
|
|
|
162
163
|
const update = (v: any) => {
|
|
@@ -47,9 +47,12 @@ const useManagedClose = ({
|
|
|
47
47
|
const transitionSpec = current.options.transitionSpec;
|
|
48
48
|
|
|
49
49
|
useAnimatedReaction(
|
|
50
|
-
() =>
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
() => {
|
|
51
|
+
const keys = closingRouteKeysShared.value;
|
|
52
|
+
return keys?.includes(routeKey) ?? false;
|
|
53
|
+
},
|
|
54
|
+
(isClosing, wasClosing) => {
|
|
55
|
+
if (!isClosing || wasClosing) return;
|
|
53
56
|
|
|
54
57
|
runOnJS(activate)();
|
|
55
58
|
animateToProgress({
|
|
@@ -5,16 +5,27 @@ import type { AnimationStoreMap } from "../../stores/animation.store";
|
|
|
5
5
|
import { HistoryStore } from "../../stores/history.store";
|
|
6
6
|
import useStableCallback from "../use-stable-callback";
|
|
7
7
|
|
|
8
|
+
function hasSnapPoints(descriptor: BaseDescriptor): boolean {
|
|
9
|
+
const snapPoints = descriptor.options?.snapPoints;
|
|
10
|
+
return Boolean(snapPoints && snapPoints.length > 0);
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
/**
|
|
9
14
|
* Check if a screen is a leaf (renders visible content) vs a navigator container.
|
|
10
15
|
* Navigator containers have nested state with routes.
|
|
11
16
|
*/
|
|
12
17
|
function isLeafScreen(navigation: BaseDescriptor["navigation"]): boolean {
|
|
13
18
|
const state = navigation.getState();
|
|
14
|
-
const
|
|
19
|
+
const index = state?.index ?? -1;
|
|
20
|
+
const currentRoute = state?.routes?.[index];
|
|
21
|
+
if (!currentRoute) return false;
|
|
15
22
|
return !("state" in currentRoute);
|
|
16
23
|
}
|
|
17
24
|
|
|
25
|
+
function shouldTrackInHistory(descriptor: BaseDescriptor): boolean {
|
|
26
|
+
return hasSnapPoints(descriptor) || isLeafScreen(descriptor.navigation);
|
|
27
|
+
}
|
|
28
|
+
|
|
18
29
|
/**
|
|
19
30
|
* Updates the HistoryStore for navigation history tracking.
|
|
20
31
|
*/
|
|
@@ -29,13 +40,13 @@ export function useScreenEvents(
|
|
|
29
40
|
// biome-ignore lint/correctness/useExhaustiveDependencies: Must only run once on mount
|
|
30
41
|
useEffect(() => {
|
|
31
42
|
// Check on mount (after paint, nested navs initialized)
|
|
32
|
-
if (
|
|
43
|
+
if (shouldTrackInHistory(current)) {
|
|
33
44
|
HistoryStore.focus(current, navigatorKey);
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
// Also listen for focus events
|
|
37
48
|
const unsubscribe = current.navigation.addListener?.("focus", () => {
|
|
38
|
-
if (
|
|
49
|
+
if (shouldTrackInHistory(current)) {
|
|
39
50
|
HistoryStore.focus(current, navigatorKey);
|
|
40
51
|
}
|
|
41
52
|
});
|
|
@@ -45,7 +56,7 @@ export function useScreenEvents(
|
|
|
45
56
|
|
|
46
57
|
// When closing starts, focus previous in history
|
|
47
58
|
const handleBlur = useStableCallback(() => {
|
|
48
|
-
if (previous &&
|
|
59
|
+
if (previous && shouldTrackInHistory(previous)) {
|
|
49
60
|
const prevNavigatorKey = previous.navigation.getState()?.key ?? "";
|
|
50
61
|
HistoryStore.focus(previous, prevNavigatorKey);
|
|
51
62
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type DerivedValue, useDerivedValue } from "react-native-reanimated";
|
|
2
|
+
import { useSharedValueState } from "../reanimated/use-shared-value-state";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a JS-focused index derived from optimisticFocusedIndex and clamped to route count.
|
|
6
|
+
* Keeps callers aligned on focus behavior during transitions with closing screens.
|
|
7
|
+
*/
|
|
8
|
+
export function useOptimisticFocusedIndex(
|
|
9
|
+
optimisticFocusedIndex: DerivedValue<number>,
|
|
10
|
+
routeCount: number,
|
|
11
|
+
): number {
|
|
12
|
+
return useSharedValueState(
|
|
13
|
+
useDerivedValue(() => {
|
|
14
|
+
const globalIndex = optimisticFocusedIndex.get();
|
|
15
|
+
if (routeCount <= 0) return 0;
|
|
16
|
+
return Math.max(0, Math.min(globalIndex, routeCount - 1));
|
|
17
|
+
}),
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { Route } from "@react-navigation/native";
|
|
2
|
-
import { useMemo } from "react";
|
|
3
|
-
import {
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
3
|
+
import { snapDescriptorToIndex } from "../../animation/snap-to";
|
|
4
4
|
import {
|
|
5
5
|
type BaseDescriptor,
|
|
6
6
|
useKeys,
|
|
7
7
|
} from "../../providers/screen/keys.provider";
|
|
8
8
|
import type { ScreenTransitionConfig } from "../../types/screen.types";
|
|
9
9
|
import type { BaseStackNavigation } from "../../types/stack.types";
|
|
10
|
-
import {
|
|
10
|
+
import { useOptimisticFocusedIndex } from "./use-optimistic-focused-index";
|
|
11
11
|
import { type StackContextValue, useStack } from "./use-stack";
|
|
12
12
|
|
|
13
13
|
export interface ScreenState<
|
|
@@ -47,6 +47,13 @@ export interface ScreenState<
|
|
|
47
47
|
* Navigation object for this screen.
|
|
48
48
|
*/
|
|
49
49
|
navigation: TNavigation;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Programmatically snap the focused screen to a snap point index.
|
|
53
|
+
*
|
|
54
|
+
* Scoped to this screen's stack context, avoiding global history ambiguity.
|
|
55
|
+
*/
|
|
56
|
+
snapTo: (index: number) => void;
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
/**
|
|
@@ -66,17 +73,24 @@ export function useScreenState<
|
|
|
66
73
|
[routeKeys, current.route.key],
|
|
67
74
|
);
|
|
68
75
|
|
|
69
|
-
const focusedIndex =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return Math.max(0, Math.min(globalIndex, routeKeys.length - 1));
|
|
73
|
-
}),
|
|
76
|
+
const focusedIndex = useOptimisticFocusedIndex(
|
|
77
|
+
optimisticFocusedIndex,
|
|
78
|
+
routeKeys.length,
|
|
74
79
|
);
|
|
75
80
|
|
|
76
81
|
const focusedScene = useMemo(() => {
|
|
77
82
|
return scenes[focusedIndex] ?? scenes[scenes.length - 1];
|
|
78
83
|
}, [scenes, focusedIndex]);
|
|
79
84
|
|
|
85
|
+
const snapTo = useCallback(
|
|
86
|
+
(targetIndex: number) => {
|
|
87
|
+
const descriptor = focusedScene?.descriptor;
|
|
88
|
+
if (!descriptor) return;
|
|
89
|
+
snapDescriptorToIndex(descriptor, targetIndex);
|
|
90
|
+
},
|
|
91
|
+
[focusedScene],
|
|
92
|
+
);
|
|
93
|
+
|
|
80
94
|
return useMemo(
|
|
81
95
|
() => ({
|
|
82
96
|
index,
|
|
@@ -86,6 +100,7 @@ export function useScreenState<
|
|
|
86
100
|
focusedIndex,
|
|
87
101
|
meta: focusedScene?.descriptor?.options?.meta,
|
|
88
102
|
navigation: current.navigation as TNavigation,
|
|
103
|
+
snapTo,
|
|
89
104
|
}),
|
|
90
105
|
[
|
|
91
106
|
index,
|
|
@@ -94,6 +109,7 @@ export function useScreenState<
|
|
|
94
109
|
focusedIndex,
|
|
95
110
|
current.navigation,
|
|
96
111
|
current.route,
|
|
112
|
+
snapTo,
|
|
97
113
|
],
|
|
98
114
|
);
|
|
99
115
|
}
|
|
@@ -26,7 +26,10 @@ export function useSharedValueState<T>(sharedValue: SharedValue<T>): T {
|
|
|
26
26
|
|
|
27
27
|
useAnimatedReaction(
|
|
28
28
|
() => sharedValue.value,
|
|
29
|
-
(value) =>
|
|
29
|
+
(value, previousValue) => {
|
|
30
|
+
if (Object.is(value, previousValue)) return;
|
|
31
|
+
runOnJS(setState)(value);
|
|
32
|
+
},
|
|
30
33
|
);
|
|
31
34
|
|
|
32
35
|
return state;
|
|
@@ -22,6 +22,7 @@ import type { ClaimedDirections, Direction } from "../types/ownership.types";
|
|
|
22
22
|
import { StackType } from "../types/stack.types";
|
|
23
23
|
import createProvider from "../utils/create-provider";
|
|
24
24
|
import { computeClaimedDirections } from "../utils/gesture/compute-claimed-directions";
|
|
25
|
+
import { validateSnapPoints } from "../utils/gesture/validate-snap-points";
|
|
25
26
|
import { useKeys } from "./screen/keys.provider";
|
|
26
27
|
import { useStackCoreContext } from "./stack/core.provider";
|
|
27
28
|
|
|
@@ -159,30 +160,43 @@ export const {
|
|
|
159
160
|
} = createProvider("ScreenGesture", { guarded: false })<
|
|
160
161
|
ScreenGestureProviderProps,
|
|
161
162
|
GestureContextType
|
|
162
|
-
>(({ children }) => {
|
|
163
|
+
>(({ children }): { value: GestureContextType; children: React.ReactNode } => {
|
|
163
164
|
const { current } = useKeys();
|
|
164
165
|
const { flags } = useStackCoreContext();
|
|
165
|
-
const ancestorContext = useGestureContext();
|
|
166
|
-
|
|
167
|
-
const hasGestures = current.options.gestureEnabled === true;
|
|
166
|
+
const ancestorContext: GestureContextType | null = useGestureContext();
|
|
168
167
|
const isIsolated = flags.STACK_TYPE === StackType.COMPONENT;
|
|
168
|
+
const routeKey = current.route.key;
|
|
169
169
|
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
const isFirstScreen = useNavigationState((state) => {
|
|
171
|
+
const index = state.routes.findIndex((route) => route.key === routeKey);
|
|
172
|
+
return index === 0;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const canDismiss = Boolean(
|
|
176
|
+
isFirstScreen ? false : current.options.gestureEnabled,
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const { hasSnapPoints } = useMemo(
|
|
180
|
+
() =>
|
|
181
|
+
validateSnapPoints({
|
|
182
|
+
snapPoints: current.options.snapPoints,
|
|
183
|
+
canDismiss,
|
|
184
|
+
}),
|
|
185
|
+
[current.options.snapPoints, canDismiss],
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const gestureEnabled = canDismiss || hasSnapPoints;
|
|
173
189
|
|
|
174
190
|
const claimedDirections = useMemo(
|
|
175
191
|
() =>
|
|
176
192
|
computeClaimedDirections(
|
|
177
|
-
|
|
193
|
+
gestureEnabled,
|
|
178
194
|
current.options.gestureDirection,
|
|
179
195
|
hasSnapPoints,
|
|
180
196
|
),
|
|
181
|
-
[
|
|
197
|
+
[gestureEnabled, current.options.gestureDirection, hasSnapPoints],
|
|
182
198
|
);
|
|
183
199
|
|
|
184
|
-
const routeKey = current.route.key;
|
|
185
|
-
|
|
186
200
|
// Check if this screen is the current (topmost) route in its navigator
|
|
187
201
|
const isCurrentRoute = useNavigationState(
|
|
188
202
|
(state) => state.routes[state.index]?.key === routeKey,
|
|
@@ -208,17 +222,30 @@ export const {
|
|
|
208
222
|
isIsolated,
|
|
209
223
|
});
|
|
210
224
|
|
|
211
|
-
const value
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
const value = useMemo<GestureContextType>(
|
|
226
|
+
() => ({
|
|
227
|
+
panGesture,
|
|
228
|
+
panGestureRef,
|
|
229
|
+
scrollConfig,
|
|
230
|
+
gestureAnimationValues,
|
|
231
|
+
ancestorContext,
|
|
232
|
+
gestureEnabled,
|
|
233
|
+
isIsolated,
|
|
234
|
+
claimedDirections,
|
|
235
|
+
childDirectionClaims,
|
|
236
|
+
}),
|
|
237
|
+
[
|
|
238
|
+
panGesture,
|
|
239
|
+
panGestureRef,
|
|
240
|
+
scrollConfig,
|
|
241
|
+
gestureAnimationValues,
|
|
242
|
+
ancestorContext,
|
|
243
|
+
gestureEnabled,
|
|
244
|
+
isIsolated,
|
|
245
|
+
claimedDirections,
|
|
246
|
+
childDirectionClaims,
|
|
247
|
+
],
|
|
248
|
+
);
|
|
222
249
|
|
|
223
250
|
return {
|
|
224
251
|
value,
|