@react-navigation/stack 8.0.0-alpha.4 → 8.0.0-alpha.41
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 +2 -2
- 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/GestureHandlerContext.js +5 -0
- package/lib/module/utils/GestureHandlerContext.js.map +1 -0
- package/lib/module/utils/gestureActivationCriteria.js +10 -8
- package/lib/module/utils/gestureActivationCriteria.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/useGestureHandler.js +9 -0
- package/lib/module/utils/useGestureHandler.js.map +1 -0
- package/lib/module/utils/useKeyboardManager.js +71 -26
- package/lib/module/utils/useKeyboardManager.js.map +1 -1
- package/lib/module/views/GestureHandler.js +15 -14
- package/lib/module/views/GestureHandler.js.map +1 -1
- package/lib/module/views/GestureHandlerNative.js +16 -10
- package/lib/module/views/GestureHandlerNative.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 +52 -18
- 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 +90 -87
- package/lib/module/views/Stack/Card.js.map +1 -1
- package/lib/module/views/Stack/CardContainer.js +72 -98
- package/lib/module/views/Stack/CardContainer.js.map +1 -1
- package/lib/module/views/Stack/CardStack.js +171 -126
- package/lib/module/views/Stack/CardStack.js.map +1 -1
- package/lib/module/views/Stack/StackView.js +103 -53
- package/lib/module/views/Stack/StackView.js.map +1 -1
- package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts +1 -1
- package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts.map +1 -1
- package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts +1 -1
- package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts.map +1 -1
- package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts +1 -1
- package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts.map +1 -1
- package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts +1 -1
- package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +12 -12
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/navigators/createStackNavigator.d.ts +10 -15
- 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/CardAnimationContext.d.ts +1 -1
- package/lib/typescript/src/utils/CardAnimationContext.d.ts.map +1 -1
- package/lib/typescript/src/utils/GestureHandlerContext.d.ts +3 -0
- package/lib/typescript/src/utils/GestureHandlerContext.d.ts.map +1 -0
- package/lib/typescript/src/utils/gestureActivationCriteria.d.ts +4 -51
- package/lib/typescript/src/utils/gestureActivationCriteria.d.ts.map +1 -1
- package/lib/typescript/src/utils/getDistanceForDirection.d.ts +1 -1
- package/lib/typescript/src/utils/getDistanceForDirection.d.ts.map +1 -1
- package/lib/typescript/src/utils/getInvertedMultiplier.d.ts +1 -1
- package/lib/typescript/src/utils/getInvertedMultiplier.d.ts.map +1 -1
- package/lib/typescript/src/utils/getModalRoutesKeys.d.ts +1 -1
- package/lib/typescript/src/utils/getModalRoutesKeys.d.ts.map +1 -1
- package/lib/typescript/src/utils/useCardAnimation.d.ts +1 -1
- package/lib/typescript/src/utils/useCardAnimation.d.ts.map +1 -1
- package/lib/typescript/src/utils/useGestureHandler.d.ts +2 -0
- package/lib/typescript/src/utils/useGestureHandler.d.ts.map +1 -0
- package/lib/typescript/src/utils/useKeyboardManager.d.ts +12 -2
- package/lib/typescript/src/utils/useKeyboardManager.d.ts.map +1 -1
- package/lib/typescript/src/views/GestureHandler.android.d.ts +1 -1
- package/lib/typescript/src/views/GestureHandler.android.d.ts.map +1 -1
- package/lib/typescript/src/views/GestureHandler.d.ts +7 -11
- package/lib/typescript/src/views/GestureHandler.d.ts.map +1 -1
- package/lib/typescript/src/views/GestureHandler.ios.d.ts +1 -1
- package/lib/typescript/src/views/GestureHandler.ios.d.ts.map +1 -1
- package/lib/typescript/src/views/GestureHandlerNative.d.ts +9 -4
- package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/Header.d.ts +2 -2
- package/lib/typescript/src/views/Header/Header.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts +9 -3
- package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Header/HeaderSegment.d.ts +5 -4
- package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/Card.d.ts +5 -5
- package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardContainer.d.ts +5 -7
- package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardContent.d.ts +1 -1
- package/lib/typescript/src/views/Stack/CardContent.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/CardStack.d.ts +6 -5
- package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
- package/lib/typescript/src/views/Stack/StackView.d.ts +10 -13
- package/lib/typescript/src/views/Stack/StackView.d.ts.map +1 -1
- package/package.json +21 -23
- package/src/index.tsx +3 -2
- package/src/navigators/createStackNavigator.tsx +9 -40
- package/src/types.tsx +73 -73
- package/src/utils/GestureHandlerContext.tsx +5 -0
- package/src/utils/gestureActivationCriteria.tsx +14 -10
- package/src/utils/useCardAnimation.tsx +1 -1
- package/src/utils/useGestureHandler.tsx +9 -0
- package/src/utils/useKeyboardManager.tsx +96 -33
- package/src/views/GestureHandler.tsx +27 -16
- package/src/views/GestureHandlerNative.tsx +26 -12
- package/src/views/Header/Header.tsx +2 -2
- package/src/views/Header/HeaderContainer.tsx +67 -24
- package/src/views/Header/HeaderSegment.tsx +4 -4
- package/src/views/Stack/Card.tsx +134 -115
- package/src/views/Stack/CardContainer.tsx +86 -127
- package/src/views/Stack/CardStack.tsx +380 -323
- package/src/views/Stack/StackView.tsx +173 -71
- package/lib/module/utils/GestureHandlerRefContext.js +0 -5
- package/lib/module/utils/GestureHandlerRefContext.js.map +0 -1
- package/lib/module/utils/findLastIndex.js +0 -11
- package/lib/module/utils/findLastIndex.js.map +0 -1
- package/lib/module/utils/useGestureHandlerRef.js +0 -12
- package/lib/module/utils/useGestureHandlerRef.js.map +0 -1
- package/lib/module/views/Stack/CardA11yWrapper.js +0 -43
- package/lib/module/views/Stack/CardA11yWrapper.js.map +0 -1
- package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts +0 -3
- package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts.map +0 -1
- package/lib/typescript/src/utils/findLastIndex.d.ts +0 -2
- package/lib/typescript/src/utils/findLastIndex.d.ts.map +0 -1
- package/lib/typescript/src/utils/useGestureHandlerRef.d.ts +0 -3
- package/lib/typescript/src/utils/useGestureHandlerRef.d.ts.map +0 -1
- package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +0 -15
- package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +0 -1
- package/src/utils/GestureHandlerRefContext.tsx +0 -5
- package/src/utils/findLastIndex.tsx +0 -9
- package/src/utils/useGestureHandlerRef.tsx +0 -15
- package/src/views/Stack/CardA11yWrapper.tsx +0 -67
package/src/views/Stack/Card.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
View,
|
|
10
10
|
type ViewStyle,
|
|
11
11
|
} from 'react-native';
|
|
12
|
+
import type { PanGestureConfig } from 'react-native-gesture-handler';
|
|
12
13
|
import type { EdgeInsets } from 'react-native-safe-area-context';
|
|
13
14
|
import useLatestCallback from 'use-latest-callback';
|
|
14
15
|
|
|
@@ -23,11 +24,7 @@ import { gestureActivationCriteria } from '../../utils/gestureActivationCriteria
|
|
|
23
24
|
import { getDistanceForDirection } from '../../utils/getDistanceForDirection';
|
|
24
25
|
import { getInvertedMultiplier } from '../../utils/getInvertedMultiplier';
|
|
25
26
|
import { getShadowStyle } from '../../utils/getShadowStyle';
|
|
26
|
-
import {
|
|
27
|
-
GestureState,
|
|
28
|
-
PanGestureHandler,
|
|
29
|
-
type PanGestureHandlerGestureEvent,
|
|
30
|
-
} from '../GestureHandler';
|
|
27
|
+
import { GestureDetector, usePanGesture } from '../GestureHandler';
|
|
31
28
|
import { CardContent } from './CardContent';
|
|
32
29
|
|
|
33
30
|
type Props = {
|
|
@@ -58,7 +55,7 @@ type Props = {
|
|
|
58
55
|
overlayEnabled: boolean;
|
|
59
56
|
shadowEnabled: boolean | undefined;
|
|
60
57
|
gestureEnabled: boolean;
|
|
61
|
-
gestureResponseDistance?: number;
|
|
58
|
+
gestureResponseDistance?: number | undefined;
|
|
62
59
|
gestureVelocityImpact: number | undefined;
|
|
63
60
|
transitionSpec: {
|
|
64
61
|
open: TransitionSpec;
|
|
@@ -66,8 +63,8 @@ type Props = {
|
|
|
66
63
|
};
|
|
67
64
|
preloaded: boolean;
|
|
68
65
|
styleInterpolator: StackCardStyleInterpolator;
|
|
69
|
-
containerStyle?: StyleProp<ViewStyle
|
|
70
|
-
contentStyle?: StyleProp<ViewStyle
|
|
66
|
+
containerStyle?: StyleProp<ViewStyle> | undefined;
|
|
67
|
+
contentStyle?: StyleProp<ViewStyle> | undefined;
|
|
71
68
|
};
|
|
72
69
|
|
|
73
70
|
const GESTURE_VELOCITY_IMPACT = 0.3;
|
|
@@ -151,14 +148,14 @@ function Card({
|
|
|
151
148
|
containerStyle: customContainerStyle,
|
|
152
149
|
contentStyle,
|
|
153
150
|
}: Props) {
|
|
154
|
-
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
|
|
155
|
-
|
|
156
151
|
const didInitiallyAnimate = React.useRef(false);
|
|
157
152
|
const lastToValueRef = React.useRef<number | undefined>(undefined);
|
|
158
153
|
|
|
159
154
|
const animationHandleRef = React.useRef<number | undefined>(undefined);
|
|
160
155
|
const pendingGestureCallbackRef =
|
|
161
156
|
React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
157
|
+
const pendingOnCloseCallbackRef =
|
|
158
|
+
React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
162
159
|
|
|
163
160
|
const [isClosing] = React.useState(() => new Animated.Value(FALSE));
|
|
164
161
|
|
|
@@ -218,10 +215,8 @@ function Card({
|
|
|
218
215
|
}
|
|
219
216
|
|
|
220
217
|
animationHandleRef.current = requestAnimationFrame(() => {
|
|
221
|
-
if
|
|
222
|
-
|
|
223
|
-
forceUpdate();
|
|
224
|
-
}
|
|
218
|
+
// Make sure to re-open screen if it wasn't removed
|
|
219
|
+
maybeAnimate();
|
|
225
220
|
});
|
|
226
221
|
};
|
|
227
222
|
|
|
@@ -245,79 +240,6 @@ function Card({
|
|
|
245
240
|
}
|
|
246
241
|
);
|
|
247
242
|
|
|
248
|
-
const onGestureStateChange = useLatestCallback(
|
|
249
|
-
({ nativeEvent }: PanGestureHandlerGestureEvent) => {
|
|
250
|
-
switch (nativeEvent.state) {
|
|
251
|
-
case GestureState.ACTIVE:
|
|
252
|
-
isSwiping.setValue(TRUE);
|
|
253
|
-
onGestureBegin?.();
|
|
254
|
-
break;
|
|
255
|
-
case GestureState.CANCELLED:
|
|
256
|
-
case GestureState.FAILED: {
|
|
257
|
-
isSwiping.setValue(FALSE);
|
|
258
|
-
|
|
259
|
-
const velocity =
|
|
260
|
-
gestureDirection === 'vertical' ||
|
|
261
|
-
gestureDirection === 'vertical-inverted'
|
|
262
|
-
? nativeEvent.velocityY
|
|
263
|
-
: nativeEvent.velocityX;
|
|
264
|
-
|
|
265
|
-
animate({
|
|
266
|
-
closing,
|
|
267
|
-
velocity,
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
onGestureCanceled?.();
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
273
|
-
case GestureState.END: {
|
|
274
|
-
isSwiping.setValue(FALSE);
|
|
275
|
-
|
|
276
|
-
let distance;
|
|
277
|
-
let translation;
|
|
278
|
-
let velocity;
|
|
279
|
-
|
|
280
|
-
if (
|
|
281
|
-
gestureDirection === 'vertical' ||
|
|
282
|
-
gestureDirection === 'vertical-inverted'
|
|
283
|
-
) {
|
|
284
|
-
distance = layout.height;
|
|
285
|
-
translation = nativeEvent.translationY;
|
|
286
|
-
velocity = nativeEvent.velocityY;
|
|
287
|
-
} else {
|
|
288
|
-
distance = layout.width;
|
|
289
|
-
translation = nativeEvent.translationX;
|
|
290
|
-
velocity = nativeEvent.velocityX;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const shouldClose =
|
|
294
|
-
(translation + velocity * gestureVelocityImpact) *
|
|
295
|
-
getInvertedMultiplier(gestureDirection, direction === 'rtl') >
|
|
296
|
-
distance / 2
|
|
297
|
-
? velocity !== 0 || translation !== 0
|
|
298
|
-
: closing;
|
|
299
|
-
|
|
300
|
-
animate({ closing: shouldClose, velocity });
|
|
301
|
-
|
|
302
|
-
if (shouldClose) {
|
|
303
|
-
// We call onClose with a delay to make sure that the animation has already started
|
|
304
|
-
// This will make sure that the state update caused by this doesn't affect start of animation
|
|
305
|
-
pendingGestureCallbackRef.current = setTimeout(() => {
|
|
306
|
-
onClose();
|
|
307
|
-
|
|
308
|
-
// Trigger an update after we dispatch the action to remove the screen
|
|
309
|
-
// This will make sure that we check if the screen didn't get removed so we can cancel the animation
|
|
310
|
-
forceUpdate();
|
|
311
|
-
}, 32);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
onGestureEnd?.();
|
|
315
|
-
break;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
);
|
|
320
|
-
|
|
321
243
|
React.useLayoutEffect(() => {
|
|
322
244
|
layoutAnim.width.setValue(layout.width);
|
|
323
245
|
layoutAnim.height.setValue(layout.height);
|
|
@@ -350,17 +272,15 @@ function Card({
|
|
|
350
272
|
}
|
|
351
273
|
|
|
352
274
|
clearTimeout(pendingGestureCallbackRef.current);
|
|
275
|
+
clearTimeout(pendingOnCloseCallbackRef.current);
|
|
353
276
|
};
|
|
354
|
-
|
|
355
|
-
// We only want to clean up the animation on unmount
|
|
356
277
|
}, []);
|
|
357
278
|
|
|
358
|
-
const timeoutRef = React.useRef<ReturnType<typeof setTimeout
|
|
279
|
+
const timeoutRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
359
280
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
281
|
+
const maybeAnimate = useLatestCallback(() => {
|
|
282
|
+
clearTimeout(pendingGestureCallbackRef.current);
|
|
283
|
+
clearTimeout(pendingOnCloseCallbackRef.current);
|
|
364
284
|
|
|
365
285
|
if (!didInitiallyAnimate.current) {
|
|
366
286
|
// Animate the card in on initial mount
|
|
@@ -368,9 +288,8 @@ function Card({
|
|
|
368
288
|
// rending of the screen is done. This is especially important
|
|
369
289
|
// in the new architecture
|
|
370
290
|
// cf., https://github.com/react-navigation/react-navigation/issues/12401
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
291
|
+
clearTimeout(timeoutRef.current);
|
|
292
|
+
|
|
374
293
|
timeoutRef.current = setTimeout(() => {
|
|
375
294
|
didInitiallyAnimate.current = true;
|
|
376
295
|
animate({ closing });
|
|
@@ -410,6 +329,14 @@ function Card({
|
|
|
410
329
|
animate({ closing });
|
|
411
330
|
}
|
|
412
331
|
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
React.useEffect(() => {
|
|
335
|
+
if (preloaded) {
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
maybeAnimate();
|
|
413
340
|
|
|
414
341
|
previousPropsRef.current = {
|
|
415
342
|
opening,
|
|
@@ -428,6 +355,7 @@ function Card({
|
|
|
428
355
|
layout,
|
|
429
356
|
opening,
|
|
430
357
|
preloaded,
|
|
358
|
+
maybeAnimate,
|
|
431
359
|
]);
|
|
432
360
|
|
|
433
361
|
const interpolationProps = React.useMemo(
|
|
@@ -469,17 +397,89 @@ function Card({
|
|
|
469
397
|
[styleInterpolator, interpolationProps]
|
|
470
398
|
);
|
|
471
399
|
|
|
472
|
-
const
|
|
400
|
+
const onGestureActivate: PanGestureConfig['onActivate'] = useLatestCallback(
|
|
401
|
+
() => {
|
|
402
|
+
clearTimeout(pendingGestureCallbackRef.current);
|
|
403
|
+
clearTimeout(pendingOnCloseCallbackRef.current);
|
|
404
|
+
isSwiping.setValue(TRUE);
|
|
405
|
+
onGestureBegin?.();
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
const onGestureDeactivate: PanGestureConfig['onDeactivate'] =
|
|
410
|
+
useLatestCallback((event) => {
|
|
411
|
+
isSwiping.setValue(FALSE);
|
|
412
|
+
|
|
413
|
+
let distance;
|
|
414
|
+
let translation;
|
|
415
|
+
let velocity;
|
|
416
|
+
|
|
417
|
+
if (
|
|
418
|
+
gestureDirection === 'vertical' ||
|
|
419
|
+
gestureDirection === 'vertical-inverted'
|
|
420
|
+
) {
|
|
421
|
+
distance = layout.height;
|
|
422
|
+
translation = event.translationY;
|
|
423
|
+
velocity = event.velocityY;
|
|
424
|
+
} else {
|
|
425
|
+
distance = layout.width;
|
|
426
|
+
translation = event.translationX;
|
|
427
|
+
velocity = event.velocityX;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
gesture.setValue(translation);
|
|
431
|
+
|
|
432
|
+
if (event.canceled) {
|
|
433
|
+
animate({
|
|
434
|
+
closing,
|
|
435
|
+
velocity,
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
onGestureCanceled?.();
|
|
439
|
+
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const shouldClose =
|
|
444
|
+
(translation + velocity * gestureVelocityImpact) *
|
|
445
|
+
getInvertedMultiplier(gestureDirection, direction === 'rtl') >
|
|
446
|
+
distance / 2
|
|
447
|
+
? velocity !== 0 || translation !== 0
|
|
448
|
+
: closing;
|
|
449
|
+
|
|
450
|
+
animate({ closing: shouldClose, velocity });
|
|
451
|
+
|
|
452
|
+
if (shouldClose) {
|
|
453
|
+
// We call onClose with a delay to make sure that the animation has already started
|
|
454
|
+
// This will make sure that the state update caused by this doesn't affect start of animation
|
|
455
|
+
pendingGestureCallbackRef.current = setTimeout(() => {
|
|
456
|
+
onClose();
|
|
457
|
+
|
|
458
|
+
// Check if the screen is still closing with a delay
|
|
459
|
+
// So state update from onClose has a chance to go through
|
|
460
|
+
// If route wasn't removed after onClose, re-open it
|
|
461
|
+
pendingOnCloseCallbackRef.current = setTimeout(() => {
|
|
462
|
+
maybeAnimate();
|
|
463
|
+
}, 32);
|
|
464
|
+
}, 16);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
onGestureEnd?.();
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
const onGestureEvent: PanGestureConfig['onUpdate'] = React.useMemo(
|
|
473
471
|
() =>
|
|
474
472
|
gestureEnabled
|
|
475
473
|
? Animated.event(
|
|
476
474
|
[
|
|
477
475
|
{
|
|
478
|
-
nativeEvent:
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
476
|
+
nativeEvent: {
|
|
477
|
+
handlerData:
|
|
478
|
+
gestureDirection === 'vertical' ||
|
|
479
|
+
gestureDirection === 'vertical-inverted'
|
|
480
|
+
? { translationY: gesture }
|
|
481
|
+
: { translationX: gesture },
|
|
482
|
+
},
|
|
483
483
|
},
|
|
484
484
|
],
|
|
485
485
|
{ useNativeDriver }
|
|
@@ -488,6 +488,35 @@ function Card({
|
|
|
488
488
|
[gesture, gestureDirection, gestureEnabled]
|
|
489
489
|
);
|
|
490
490
|
|
|
491
|
+
const panGestureConfig = React.useMemo(
|
|
492
|
+
(): PanGestureConfig => ({
|
|
493
|
+
enabled: layout.width !== 0 && gestureEnabled,
|
|
494
|
+
onActivate: onGestureActivate,
|
|
495
|
+
onDeactivate: onGestureDeactivate,
|
|
496
|
+
onUpdate: onGestureEvent,
|
|
497
|
+
disableReanimated: true,
|
|
498
|
+
useAnimated: true,
|
|
499
|
+
...gestureActivationCriteria({
|
|
500
|
+
layout,
|
|
501
|
+
direction,
|
|
502
|
+
gestureDirection,
|
|
503
|
+
gestureResponseDistance,
|
|
504
|
+
}),
|
|
505
|
+
}),
|
|
506
|
+
[
|
|
507
|
+
direction,
|
|
508
|
+
gestureDirection,
|
|
509
|
+
gestureEnabled,
|
|
510
|
+
gestureResponseDistance,
|
|
511
|
+
layout,
|
|
512
|
+
onGestureActivate,
|
|
513
|
+
onGestureDeactivate,
|
|
514
|
+
onGestureEvent,
|
|
515
|
+
]
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
const panGesture = usePanGesture(panGestureConfig);
|
|
519
|
+
|
|
491
520
|
const { backgroundColor } = StyleSheet.flatten(contentStyle || {});
|
|
492
521
|
|
|
493
522
|
const isTransparent =
|
|
@@ -519,17 +548,7 @@ function Card({
|
|
|
519
548
|
<Animated.View
|
|
520
549
|
style={[styles.container, containerStyle, customContainerStyle]}
|
|
521
550
|
>
|
|
522
|
-
<
|
|
523
|
-
enabled={layout.width !== 0 && gestureEnabled}
|
|
524
|
-
onGestureEvent={onGestureEvent}
|
|
525
|
-
onHandlerStateChange={onGestureStateChange}
|
|
526
|
-
{...gestureActivationCriteria({
|
|
527
|
-
layout,
|
|
528
|
-
direction,
|
|
529
|
-
gestureDirection,
|
|
530
|
-
gestureResponseDistance,
|
|
531
|
-
})}
|
|
532
|
-
>
|
|
551
|
+
<GestureDetector gesture={panGesture}>
|
|
533
552
|
<Animated.View
|
|
534
553
|
needsOffscreenAlphaCompositing={hasOpacityStyle(cardStyle)}
|
|
535
554
|
style={[styles.container, cardStyle]}
|
|
@@ -558,7 +577,7 @@ function Card({
|
|
|
558
577
|
{children}
|
|
559
578
|
</CardContent>
|
|
560
579
|
</Animated.View>
|
|
561
|
-
</
|
|
580
|
+
</GestureDetector>
|
|
562
581
|
</Animated.View>
|
|
563
582
|
</CardAnimationContext.Provider>
|
|
564
583
|
);
|
|
@@ -16,9 +16,11 @@ import { Animated, StyleSheet, View } from 'react-native';
|
|
|
16
16
|
import type { Layout, Scene } from '../../types';
|
|
17
17
|
import { ModalPresentationContext } from '../../utils/ModalPresentationContext';
|
|
18
18
|
import { useKeyboardManager } from '../../utils/useKeyboardManager';
|
|
19
|
-
import type {
|
|
19
|
+
import type {
|
|
20
|
+
HeaderHeight,
|
|
21
|
+
Props as HeaderContainerProps,
|
|
22
|
+
} from '../Header/HeaderContainer';
|
|
20
23
|
import { Card } from './Card';
|
|
21
|
-
import { CardA11yWrapper, type CardA11yWrapperRef } from './CardA11yWrapper';
|
|
22
24
|
|
|
23
25
|
type Props = {
|
|
24
26
|
interpolationIndex: number;
|
|
@@ -49,19 +51,15 @@ type Props = {
|
|
|
49
51
|
onGestureStart: (props: { route: Route<string> }) => void;
|
|
50
52
|
onGestureEnd: (props: { route: Route<string> }) => void;
|
|
51
53
|
onGestureCancel: (props: { route: Route<string> }) => void;
|
|
52
|
-
|
|
53
|
-
headerHeight: number;
|
|
54
|
+
headerHeight: HeaderHeight | undefined;
|
|
54
55
|
onHeaderHeightChange: (props: {
|
|
55
56
|
route: Route<string>;
|
|
56
57
|
height: number;
|
|
57
58
|
}) => void;
|
|
58
59
|
isParentHeaderShown: boolean;
|
|
59
|
-
|
|
60
|
-
detachCurrentScreen: boolean;
|
|
60
|
+
children: React.ReactNode;
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
const EPSILON = 0.1;
|
|
64
|
-
|
|
65
63
|
function CardContainerInner({
|
|
66
64
|
interpolationIndex,
|
|
67
65
|
index,
|
|
@@ -73,12 +71,9 @@ function CardContainerInner({
|
|
|
73
71
|
modal,
|
|
74
72
|
getPreviousScene,
|
|
75
73
|
getFocusedRoute,
|
|
76
|
-
hasAbsoluteFloatHeader,
|
|
77
74
|
headerHeight,
|
|
78
75
|
onHeaderHeightChange,
|
|
79
76
|
isParentHeaderShown,
|
|
80
|
-
isNextScreenTransparent,
|
|
81
|
-
detachCurrentScreen,
|
|
82
77
|
layout,
|
|
83
78
|
onCloseRoute,
|
|
84
79
|
onOpenRoute,
|
|
@@ -94,23 +89,22 @@ function CardContainerInner({
|
|
|
94
89
|
safeAreaInsetRight,
|
|
95
90
|
safeAreaInsetTop,
|
|
96
91
|
scene,
|
|
92
|
+
children,
|
|
97
93
|
}: Props) {
|
|
98
|
-
const wrapperRef = React.useRef<CardA11yWrapperRef>(null);
|
|
99
|
-
|
|
100
94
|
const { direction } = useLocale();
|
|
101
95
|
|
|
102
|
-
const parentHeaderHeight = React.
|
|
96
|
+
const parentHeaderHeight = React.use(HeaderHeightContext);
|
|
103
97
|
|
|
104
|
-
const {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const { options, navigation } = scene.descriptor;
|
|
98
|
+
const { options } = scene.descriptor;
|
|
99
|
+
const enabled = options.keyboardHandlingEnabled !== false;
|
|
100
|
+
const contentRef = React.useRef<View>(null);
|
|
108
101
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
102
|
+
const { onPageChangeStart, onPageChangeCancel, onPageChangeConfirm } =
|
|
103
|
+
useKeyboardManager({
|
|
104
|
+
enabled,
|
|
105
|
+
focused,
|
|
106
|
+
contentRef,
|
|
107
|
+
});
|
|
114
108
|
|
|
115
109
|
const handleOpen = () => {
|
|
116
110
|
const { route } = scene.descriptor;
|
|
@@ -153,17 +147,9 @@ function CardContainerInner({
|
|
|
153
147
|
closing: boolean;
|
|
154
148
|
gesture: boolean;
|
|
155
149
|
}) => {
|
|
156
|
-
wrapperRef.current?.setInert(closing);
|
|
157
|
-
|
|
158
150
|
const { route } = scene.descriptor;
|
|
159
151
|
|
|
160
|
-
|
|
161
|
-
onPageChangeConfirm?.(true);
|
|
162
|
-
} else if (active && closing) {
|
|
163
|
-
onPageChangeConfirm?.(false);
|
|
164
|
-
} else {
|
|
165
|
-
onPageChangeCancel?.();
|
|
166
|
-
}
|
|
152
|
+
onPageChangeConfirm?.({ gesture, active, closing });
|
|
167
153
|
|
|
168
154
|
onTransitionStart?.({ route }, closing);
|
|
169
155
|
};
|
|
@@ -177,20 +163,6 @@ function CardContainerInner({
|
|
|
177
163
|
|
|
178
164
|
const { colors } = useTheme();
|
|
179
165
|
|
|
180
|
-
React.useEffect(() => {
|
|
181
|
-
const listener = scene.progress.next?.addListener?.(
|
|
182
|
-
({ value }: { value: number }) => {
|
|
183
|
-
wrapperRef.current?.setInert(value > EPSILON);
|
|
184
|
-
}
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
return () => {
|
|
188
|
-
if (listener) {
|
|
189
|
-
scene.progress.next?.removeListener?.(listener);
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
}, [scene.progress.next]);
|
|
193
|
-
|
|
194
166
|
const {
|
|
195
167
|
presentation,
|
|
196
168
|
animation,
|
|
@@ -236,90 +208,77 @@ function CardContainerInner({
|
|
|
236
208
|
const animated = animation !== 'none';
|
|
237
209
|
|
|
238
210
|
return (
|
|
239
|
-
<
|
|
240
|
-
ref={wrapperRef}
|
|
241
|
-
focused={focused}
|
|
242
|
-
active={active}
|
|
211
|
+
<Card
|
|
243
212
|
animated={animated}
|
|
244
|
-
|
|
245
|
-
|
|
213
|
+
interpolationIndex={interpolationIndex}
|
|
214
|
+
gestureDirection={gestureDirection}
|
|
215
|
+
layout={layout}
|
|
216
|
+
insets={insets}
|
|
217
|
+
direction={direction}
|
|
218
|
+
gesture={gesture}
|
|
219
|
+
current={scene.progress.current}
|
|
220
|
+
next={scene.progress.next}
|
|
221
|
+
opening={opening}
|
|
222
|
+
closing={closing}
|
|
223
|
+
onOpen={handleOpen}
|
|
224
|
+
onClose={handleClose}
|
|
225
|
+
overlay={cardOverlay}
|
|
226
|
+
overlayEnabled={cardOverlayEnabled}
|
|
227
|
+
shadowEnabled={cardShadowEnabled}
|
|
228
|
+
onTransition={handleTransition}
|
|
229
|
+
onGestureBegin={handleGestureBegin}
|
|
230
|
+
onGestureCanceled={handleGestureCanceled}
|
|
231
|
+
onGestureEnd={handleGestureEnd}
|
|
232
|
+
gestureEnabled={index === 0 ? false : gestureEnabled}
|
|
233
|
+
gestureResponseDistance={gestureResponseDistance}
|
|
234
|
+
gestureVelocityImpact={gestureVelocityImpact}
|
|
235
|
+
transitionSpec={transitionSpec}
|
|
236
|
+
styleInterpolator={cardStyleInterpolator}
|
|
237
|
+
pageOverflowEnabled={headerMode !== 'float' && presentation !== 'modal'}
|
|
238
|
+
preloaded={preloaded}
|
|
239
|
+
contentStyle={[
|
|
240
|
+
{
|
|
241
|
+
backgroundColor:
|
|
242
|
+
presentation === 'transparentModal'
|
|
243
|
+
? 'transparent'
|
|
244
|
+
: colors.background,
|
|
245
|
+
},
|
|
246
|
+
cardStyle,
|
|
247
|
+
]}
|
|
246
248
|
>
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
transitionSpec={transitionSpec}
|
|
272
|
-
styleInterpolator={cardStyleInterpolator}
|
|
273
|
-
pageOverflowEnabled={headerMode !== 'float' && presentation !== 'modal'}
|
|
274
|
-
preloaded={preloaded}
|
|
275
|
-
containerStyle={
|
|
276
|
-
hasAbsoluteFloatHeader && headerMode !== 'screen'
|
|
277
|
-
? { marginTop: headerHeight }
|
|
278
|
-
: null
|
|
279
|
-
}
|
|
280
|
-
contentStyle={[
|
|
281
|
-
{
|
|
282
|
-
backgroundColor:
|
|
283
|
-
presentation === 'transparentModal'
|
|
284
|
-
? 'transparent'
|
|
285
|
-
: colors.background,
|
|
286
|
-
},
|
|
287
|
-
cardStyle,
|
|
288
|
-
]}
|
|
289
|
-
>
|
|
290
|
-
<View style={styles.container}>
|
|
291
|
-
<ModalPresentationContext.Provider value={modal}>
|
|
292
|
-
{headerMode !== 'float'
|
|
293
|
-
? renderHeader({
|
|
294
|
-
mode: 'screen',
|
|
295
|
-
scenes: [previousScene, scene],
|
|
296
|
-
getPreviousScene,
|
|
297
|
-
getFocusedRoute,
|
|
298
|
-
onContentHeightChange: onHeaderHeightChange,
|
|
299
|
-
style: styles.header,
|
|
300
|
-
})
|
|
301
|
-
: null}
|
|
302
|
-
<View style={styles.scene}>
|
|
303
|
-
<HeaderBackContext.Provider value={headerBack}>
|
|
304
|
-
<HeaderShownContext.Provider
|
|
305
|
-
value={isParentHeaderShown || headerShown !== false}
|
|
249
|
+
<View ref={contentRef} style={styles.container}>
|
|
250
|
+
<ModalPresentationContext.Provider value={modal}>
|
|
251
|
+
{headerMode !== 'float'
|
|
252
|
+
? renderHeader({
|
|
253
|
+
mode: 'screen',
|
|
254
|
+
scenes: [previousScene, scene],
|
|
255
|
+
getPreviousScene,
|
|
256
|
+
getFocusedRoute,
|
|
257
|
+
contentHeight: headerHeight,
|
|
258
|
+
onContentHeightChange: onHeaderHeightChange,
|
|
259
|
+
style: styles.header,
|
|
260
|
+
})
|
|
261
|
+
: null}
|
|
262
|
+
<View style={styles.scene}>
|
|
263
|
+
<HeaderBackContext.Provider value={headerBack}>
|
|
264
|
+
<HeaderShownContext.Provider
|
|
265
|
+
value={isParentHeaderShown || headerShown !== false}
|
|
266
|
+
>
|
|
267
|
+
<HeaderHeightContext.Provider
|
|
268
|
+
value={
|
|
269
|
+
headerShown !== false
|
|
270
|
+
? (headerHeight?.value ?? 0)
|
|
271
|
+
: (parentHeaderHeight ?? 0)
|
|
272
|
+
}
|
|
306
273
|
>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
</HeaderHeightContext.Provider>
|
|
316
|
-
</HeaderShownContext.Provider>
|
|
317
|
-
</HeaderBackContext.Provider>
|
|
318
|
-
</View>
|
|
319
|
-
</ModalPresentationContext.Provider>
|
|
320
|
-
</View>
|
|
321
|
-
</Card>
|
|
322
|
-
</CardA11yWrapper>
|
|
274
|
+
{children}
|
|
275
|
+
</HeaderHeightContext.Provider>
|
|
276
|
+
</HeaderShownContext.Provider>
|
|
277
|
+
</HeaderBackContext.Provider>
|
|
278
|
+
</View>
|
|
279
|
+
</ModalPresentationContext.Provider>
|
|
280
|
+
</View>
|
|
281
|
+
</Card>
|
|
323
282
|
);
|
|
324
283
|
}
|
|
325
284
|
|