@react-navigation/stack 8.0.0-alpha.3 → 8.0.0-alpha.30
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/lib/module/index.js.map +1 -1
- package/lib/module/navigators/createStackNavigator.js +3 -7
- package/lib/module/navigators/createStackNavigator.js.map +1 -1
- package/lib/module/utils/useCardAnimation.js +1 -1
- package/lib/module/utils/useCardAnimation.js.map +1 -1
- package/lib/module/utils/useGestureHandlerRef.js +1 -1
- package/lib/module/utils/useGestureHandlerRef.js.map +1 -1
- package/lib/module/utils/useKeyboardManager.js +50 -26
- package/lib/module/utils/useKeyboardManager.js.map +1 -1
- package/lib/module/views/Header/Header.js +2 -2
- package/lib/module/views/Header/Header.js.map +1 -1
- package/lib/module/views/Header/HeaderContainer.js +32 -16
- package/lib/module/views/Header/HeaderContainer.js.map +1 -1
- package/lib/module/views/Header/HeaderSegment.js +2 -2
- package/lib/module/views/Header/HeaderSegment.js.map +1 -1
- package/lib/module/views/Stack/Card.js +25 -20
- package/lib/module/views/Stack/Card.js.map +1 -1
- package/lib/module/views/Stack/CardA11yWrapper.js +6 -7
- package/lib/module/views/Stack/CardA11yWrapper.js.map +1 -1
- package/lib/module/views/Stack/CardContainer.js +18 -19
- package/lib/module/views/Stack/CardContainer.js.map +1 -1
- package/lib/module/views/Stack/CardStack.js +105 -133
- package/lib/module/views/Stack/CardStack.js.map +1 -1
- package/lib/module/views/Stack/StackView.js +82 -49
- package/lib/module/views/Stack/StackView.js.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/navigators/createStackNavigator.d.ts +8 -14
- package/lib/typescript/src/navigators/createStackNavigator.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +46 -53
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/utils/gestureActivationCriteria.d.ts +1 -1
- package/lib/typescript/src/utils/gestureActivationCriteria.d.ts.map +1 -1
- package/lib/typescript/src/utils/useKeyboardManager.d.ts +9 -2
- package/lib/typescript/src/utils/useKeyboardManager.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/Header.d.ts +1 -1
- package/lib/typescript/src/views/Header/Header.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts +2 -1
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/HeaderSegment.d.ts +2 -2
- package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/Card.d.ts +3 -3
- package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +2 -2
- package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardContainer.d.ts +2 -2
- package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardStack.d.ts +1 -1
- package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/StackView.d.ts +6 -9
- package/lib/typescript/src/views/Stack/StackView.d.ts.map +1 -1
- package/package.json +20 -22
- package/src/index.tsx +1 -0
- package/src/navigators/createStackNavigator.tsx +9 -40
- package/src/types.tsx +73 -73
- package/src/utils/gestureActivationCriteria.tsx +1 -1
- package/src/utils/useCardAnimation.tsx +1 -1
- package/src/utils/useGestureHandlerRef.tsx +1 -1
- package/src/utils/useKeyboardManager.tsx +67 -33
- package/src/views/Header/Header.tsx +2 -2
- package/src/views/Header/HeaderContainer.tsx +37 -18
- package/src/views/Header/HeaderSegment.tsx +4 -4
- package/src/views/Stack/Card.tsx +32 -23
- package/src/views/Stack/CardA11yWrapper.tsx +40 -51
- package/src/views/Stack/CardContainer.tsx +10 -21
- package/src/views/Stack/CardStack.tsx +291 -328
- package/src/views/Stack/StackView.tsx +138 -66
package/src/views/Stack/Card.tsx
CHANGED
|
@@ -58,7 +58,7 @@ type Props = {
|
|
|
58
58
|
overlayEnabled: boolean;
|
|
59
59
|
shadowEnabled: boolean | undefined;
|
|
60
60
|
gestureEnabled: boolean;
|
|
61
|
-
gestureResponseDistance?: number;
|
|
61
|
+
gestureResponseDistance?: number | undefined;
|
|
62
62
|
gestureVelocityImpact: number | undefined;
|
|
63
63
|
transitionSpec: {
|
|
64
64
|
open: TransitionSpec;
|
|
@@ -66,8 +66,8 @@ type Props = {
|
|
|
66
66
|
};
|
|
67
67
|
preloaded: boolean;
|
|
68
68
|
styleInterpolator: StackCardStyleInterpolator;
|
|
69
|
-
containerStyle?: StyleProp<ViewStyle
|
|
70
|
-
contentStyle?: StyleProp<ViewStyle
|
|
69
|
+
containerStyle?: StyleProp<ViewStyle> | undefined;
|
|
70
|
+
contentStyle?: StyleProp<ViewStyle> | undefined;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
const GESTURE_VELOCITY_IMPACT = 0.3;
|
|
@@ -151,14 +151,14 @@ function Card({
|
|
|
151
151
|
containerStyle: customContainerStyle,
|
|
152
152
|
contentStyle,
|
|
153
153
|
}: Props) {
|
|
154
|
-
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
|
|
155
|
-
|
|
156
154
|
const didInitiallyAnimate = React.useRef(false);
|
|
157
155
|
const lastToValueRef = React.useRef<number | undefined>(undefined);
|
|
158
156
|
|
|
159
157
|
const animationHandleRef = React.useRef<number | undefined>(undefined);
|
|
160
158
|
const pendingGestureCallbackRef =
|
|
161
159
|
React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
160
|
+
const pendingOnCloseCallbackRef =
|
|
161
|
+
React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
162
162
|
|
|
163
163
|
const [isClosing] = React.useState(() => new Animated.Value(FALSE));
|
|
164
164
|
|
|
@@ -218,10 +218,8 @@ function Card({
|
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
animationHandleRef.current = requestAnimationFrame(() => {
|
|
221
|
-
if
|
|
222
|
-
|
|
223
|
-
forceUpdate();
|
|
224
|
-
}
|
|
221
|
+
// Make sure to re-open screen if it wasn't removed
|
|
222
|
+
maybeAnimate();
|
|
225
223
|
});
|
|
226
224
|
};
|
|
227
225
|
|
|
@@ -249,6 +247,8 @@ function Card({
|
|
|
249
247
|
({ nativeEvent }: PanGestureHandlerGestureEvent) => {
|
|
250
248
|
switch (nativeEvent.state) {
|
|
251
249
|
case GestureState.ACTIVE:
|
|
250
|
+
clearTimeout(pendingGestureCallbackRef.current);
|
|
251
|
+
clearTimeout(pendingOnCloseCallbackRef.current);
|
|
252
252
|
isSwiping.setValue(TRUE);
|
|
253
253
|
onGestureBegin?.();
|
|
254
254
|
break;
|
|
@@ -305,10 +305,13 @@ function Card({
|
|
|
305
305
|
pendingGestureCallbackRef.current = setTimeout(() => {
|
|
306
306
|
onClose();
|
|
307
307
|
|
|
308
|
-
//
|
|
309
|
-
//
|
|
310
|
-
|
|
311
|
-
|
|
308
|
+
// Check if the screen is still closing with a delay
|
|
309
|
+
// So state update from onClose has a chance to go through
|
|
310
|
+
// If route wasn't removed after onClose, re-open it
|
|
311
|
+
pendingOnCloseCallbackRef.current = setTimeout(() => {
|
|
312
|
+
maybeAnimate();
|
|
313
|
+
}, 32);
|
|
314
|
+
}, 16);
|
|
312
315
|
}
|
|
313
316
|
|
|
314
317
|
onGestureEnd?.();
|
|
@@ -350,17 +353,15 @@ function Card({
|
|
|
350
353
|
}
|
|
351
354
|
|
|
352
355
|
clearTimeout(pendingGestureCallbackRef.current);
|
|
356
|
+
clearTimeout(pendingOnCloseCallbackRef.current);
|
|
353
357
|
};
|
|
354
|
-
|
|
355
|
-
// We only want to clean up the animation on unmount
|
|
356
358
|
}, []);
|
|
357
359
|
|
|
358
|
-
const timeoutRef = React.useRef<ReturnType<typeof setTimeout
|
|
360
|
+
const timeoutRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
359
361
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
362
|
+
const maybeAnimate = useLatestCallback(() => {
|
|
363
|
+
clearTimeout(pendingGestureCallbackRef.current);
|
|
364
|
+
clearTimeout(pendingOnCloseCallbackRef.current);
|
|
364
365
|
|
|
365
366
|
if (!didInitiallyAnimate.current) {
|
|
366
367
|
// Animate the card in on initial mount
|
|
@@ -368,9 +369,8 @@ function Card({
|
|
|
368
369
|
// rending of the screen is done. This is especially important
|
|
369
370
|
// in the new architecture
|
|
370
371
|
// cf., https://github.com/react-navigation/react-navigation/issues/12401
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
372
|
+
clearTimeout(timeoutRef.current);
|
|
373
|
+
|
|
374
374
|
timeoutRef.current = setTimeout(() => {
|
|
375
375
|
didInitiallyAnimate.current = true;
|
|
376
376
|
animate({ closing });
|
|
@@ -410,6 +410,14 @@ function Card({
|
|
|
410
410
|
animate({ closing });
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
React.useEffect(() => {
|
|
416
|
+
if (preloaded) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
maybeAnimate();
|
|
413
421
|
|
|
414
422
|
previousPropsRef.current = {
|
|
415
423
|
opening,
|
|
@@ -428,6 +436,7 @@ function Card({
|
|
|
428
436
|
layout,
|
|
429
437
|
opening,
|
|
430
438
|
preloaded,
|
|
439
|
+
maybeAnimate,
|
|
431
440
|
]);
|
|
432
441
|
|
|
433
442
|
const interpolationProps = React.useMemo(
|
|
@@ -6,62 +6,51 @@ type Props = {
|
|
|
6
6
|
active: boolean;
|
|
7
7
|
animated: boolean;
|
|
8
8
|
isNextScreenTransparent: boolean;
|
|
9
|
-
detachCurrentScreen: boolean;
|
|
10
9
|
children: React.ReactNode;
|
|
10
|
+
ref?: React.Ref<CardA11yWrapperRef>;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export type CardA11yWrapperRef = { setInert: (value: boolean) => void };
|
|
14
14
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
) => {
|
|
27
|
-
// Manage this in separate component to avoid re-rendering card during gestures
|
|
28
|
-
// Otherwise the gesture animation will be interrupted as state hasn't updated yet
|
|
29
|
-
const [inert, setInert] = React.useState(false);
|
|
15
|
+
export function CardA11yWrapper({
|
|
16
|
+
focused,
|
|
17
|
+
active,
|
|
18
|
+
animated,
|
|
19
|
+
isNextScreenTransparent,
|
|
20
|
+
children,
|
|
21
|
+
ref,
|
|
22
|
+
}: Props) {
|
|
23
|
+
// Manage this in separate component to avoid re-rendering card during gestures
|
|
24
|
+
// Otherwise the gesture animation will be interrupted as state hasn't updated yet
|
|
25
|
+
const [inert, setInert] = React.useState(false);
|
|
30
26
|
|
|
31
|
-
|
|
27
|
+
React.useImperativeHandle(ref, () => ({ setInert }), []);
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
!animated &&
|
|
35
|
-
isNextScreenTransparent === false &&
|
|
36
|
-
detachCurrentScreen !== false &&
|
|
37
|
-
!focused;
|
|
29
|
+
const isHidden = !animated && isNextScreenTransparent === false && !focused;
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
CardA11yWrapper.displayName = 'CardA11yWrapper';
|
|
31
|
+
return (
|
|
32
|
+
<View
|
|
33
|
+
aria-hidden={!focused}
|
|
34
|
+
style={[
|
|
35
|
+
StyleSheet.absoluteFill,
|
|
36
|
+
{
|
|
37
|
+
pointerEvents: (animated ? inert : !focused) ? 'none' : 'box-none',
|
|
38
|
+
// This is necessary to avoid unfocused larger pages increasing scroll area
|
|
39
|
+
// The issue can be seen on the web when a smaller screen is pushed over a larger one
|
|
40
|
+
overflow: active ? undefined : 'hidden',
|
|
41
|
+
// We use visibility on web
|
|
42
|
+
display: Platform.OS !== 'web' && isHidden ? 'none' : 'flex',
|
|
43
|
+
// Hide unfocused screens when animation isn't enabled
|
|
44
|
+
// This is also necessary for a11y on web
|
|
45
|
+
// @ts-expect-error visibility is only available on web
|
|
46
|
+
visibility: isHidden ? 'hidden' : 'visible',
|
|
47
|
+
},
|
|
48
|
+
]}
|
|
49
|
+
// Make sure this view is not removed on the new architecture, as it causes focus loss during navigation on Android.
|
|
50
|
+
// This can happen when the view flattening results in different trees - due to `overflow` style changing in a parent.
|
|
51
|
+
collapsable={false}
|
|
52
|
+
>
|
|
53
|
+
{children}
|
|
54
|
+
</View>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -57,7 +57,7 @@ type Props = {
|
|
|
57
57
|
}) => void;
|
|
58
58
|
isParentHeaderShown: boolean;
|
|
59
59
|
isNextScreenTransparent: boolean;
|
|
60
|
-
|
|
60
|
+
children: React.ReactNode;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
const EPSILON = 0.1;
|
|
@@ -78,7 +78,6 @@ function CardContainerInner({
|
|
|
78
78
|
onHeaderHeightChange,
|
|
79
79
|
isParentHeaderShown,
|
|
80
80
|
isNextScreenTransparent,
|
|
81
|
-
detachCurrentScreen,
|
|
82
81
|
layout,
|
|
83
82
|
onCloseRoute,
|
|
84
83
|
onOpenRoute,
|
|
@@ -94,23 +93,19 @@ function CardContainerInner({
|
|
|
94
93
|
safeAreaInsetRight,
|
|
95
94
|
safeAreaInsetTop,
|
|
96
95
|
scene,
|
|
96
|
+
children,
|
|
97
97
|
}: Props) {
|
|
98
98
|
const wrapperRef = React.useRef<CardA11yWrapperRef>(null);
|
|
99
99
|
|
|
100
100
|
const { direction } = useLocale();
|
|
101
101
|
|
|
102
|
-
const parentHeaderHeight = React.
|
|
102
|
+
const parentHeaderHeight = React.use(HeaderHeightContext);
|
|
103
|
+
|
|
104
|
+
const { options } = scene.descriptor;
|
|
105
|
+
const enabled = focused && options.keyboardHandlingEnabled !== false;
|
|
103
106
|
|
|
104
107
|
const { onPageChangeStart, onPageChangeCancel, onPageChangeConfirm } =
|
|
105
|
-
useKeyboardManager(
|
|
106
|
-
React.useCallback(() => {
|
|
107
|
-
const { options, navigation } = scene.descriptor;
|
|
108
|
-
|
|
109
|
-
return (
|
|
110
|
-
navigation.isFocused() && options.keyboardHandlingEnabled !== false
|
|
111
|
-
);
|
|
112
|
-
}, [scene.descriptor])
|
|
113
|
-
);
|
|
108
|
+
useKeyboardManager({ enabled, focused });
|
|
114
109
|
|
|
115
110
|
const handleOpen = () => {
|
|
116
111
|
const { route } = scene.descriptor;
|
|
@@ -157,13 +152,7 @@ function CardContainerInner({
|
|
|
157
152
|
|
|
158
153
|
const { route } = scene.descriptor;
|
|
159
154
|
|
|
160
|
-
|
|
161
|
-
onPageChangeConfirm?.(true);
|
|
162
|
-
} else if (active && closing) {
|
|
163
|
-
onPageChangeConfirm?.(false);
|
|
164
|
-
} else {
|
|
165
|
-
onPageChangeCancel?.();
|
|
166
|
-
}
|
|
155
|
+
onPageChangeConfirm?.({ gesture, active, closing });
|
|
167
156
|
|
|
168
157
|
onTransitionStart?.({ route }, closing);
|
|
169
158
|
};
|
|
@@ -242,7 +231,6 @@ function CardContainerInner({
|
|
|
242
231
|
active={active}
|
|
243
232
|
animated={animated}
|
|
244
233
|
isNextScreenTransparent={isNextScreenTransparent}
|
|
245
|
-
detachCurrentScreen={detachCurrentScreen}
|
|
246
234
|
>
|
|
247
235
|
<Card
|
|
248
236
|
animated={animated}
|
|
@@ -295,6 +283,7 @@ function CardContainerInner({
|
|
|
295
283
|
scenes: [previousScene, scene],
|
|
296
284
|
getPreviousScene,
|
|
297
285
|
getFocusedRoute,
|
|
286
|
+
contentHeight: headerHeight,
|
|
298
287
|
onContentHeightChange: onHeaderHeightChange,
|
|
299
288
|
style: styles.header,
|
|
300
289
|
})
|
|
@@ -311,7 +300,7 @@ function CardContainerInner({
|
|
|
311
300
|
: (parentHeaderHeight ?? 0)
|
|
312
301
|
}
|
|
313
302
|
>
|
|
314
|
-
{
|
|
303
|
+
{children}
|
|
315
304
|
</HeaderHeightContext.Provider>
|
|
316
305
|
</HeaderShownContext.Provider>
|
|
317
306
|
</HeaderBackContext.Provider>
|