@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.
Files changed (126) hide show
  1. package/lib/module/index.js +2 -2
  2. package/lib/module/index.js.map +1 -1
  3. package/lib/module/navigators/createStackNavigator.js +3 -7
  4. package/lib/module/navigators/createStackNavigator.js.map +1 -1
  5. package/lib/module/utils/GestureHandlerContext.js +5 -0
  6. package/lib/module/utils/GestureHandlerContext.js.map +1 -0
  7. package/lib/module/utils/gestureActivationCriteria.js +10 -8
  8. package/lib/module/utils/gestureActivationCriteria.js.map +1 -1
  9. package/lib/module/utils/useCardAnimation.js +1 -1
  10. package/lib/module/utils/useCardAnimation.js.map +1 -1
  11. package/lib/module/utils/useGestureHandler.js +9 -0
  12. package/lib/module/utils/useGestureHandler.js.map +1 -0
  13. package/lib/module/utils/useKeyboardManager.js +71 -26
  14. package/lib/module/utils/useKeyboardManager.js.map +1 -1
  15. package/lib/module/views/GestureHandler.js +15 -14
  16. package/lib/module/views/GestureHandler.js.map +1 -1
  17. package/lib/module/views/GestureHandlerNative.js +16 -10
  18. package/lib/module/views/GestureHandlerNative.js.map +1 -1
  19. package/lib/module/views/Header/Header.js +2 -2
  20. package/lib/module/views/Header/Header.js.map +1 -1
  21. package/lib/module/views/Header/HeaderContainer.js +52 -18
  22. package/lib/module/views/Header/HeaderContainer.js.map +1 -1
  23. package/lib/module/views/Header/HeaderSegment.js +2 -2
  24. package/lib/module/views/Header/HeaderSegment.js.map +1 -1
  25. package/lib/module/views/Stack/Card.js +90 -87
  26. package/lib/module/views/Stack/Card.js.map +1 -1
  27. package/lib/module/views/Stack/CardContainer.js +72 -98
  28. package/lib/module/views/Stack/CardContainer.js.map +1 -1
  29. package/lib/module/views/Stack/CardStack.js +171 -126
  30. package/lib/module/views/Stack/CardStack.js.map +1 -1
  31. package/lib/module/views/Stack/StackView.js +103 -53
  32. package/lib/module/views/Stack/StackView.js.map +1 -1
  33. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts +1 -1
  34. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts.map +1 -1
  35. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts +1 -1
  36. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts.map +1 -1
  37. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts +1 -1
  38. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts.map +1 -1
  39. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts +1 -1
  40. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts.map +1 -1
  41. package/lib/typescript/src/index.d.ts +12 -12
  42. package/lib/typescript/src/index.d.ts.map +1 -1
  43. package/lib/typescript/src/navigators/createStackNavigator.d.ts +10 -15
  44. package/lib/typescript/src/navigators/createStackNavigator.d.ts.map +1 -1
  45. package/lib/typescript/src/types.d.ts +46 -53
  46. package/lib/typescript/src/types.d.ts.map +1 -1
  47. package/lib/typescript/src/utils/CardAnimationContext.d.ts +1 -1
  48. package/lib/typescript/src/utils/CardAnimationContext.d.ts.map +1 -1
  49. package/lib/typescript/src/utils/GestureHandlerContext.d.ts +3 -0
  50. package/lib/typescript/src/utils/GestureHandlerContext.d.ts.map +1 -0
  51. package/lib/typescript/src/utils/gestureActivationCriteria.d.ts +4 -51
  52. package/lib/typescript/src/utils/gestureActivationCriteria.d.ts.map +1 -1
  53. package/lib/typescript/src/utils/getDistanceForDirection.d.ts +1 -1
  54. package/lib/typescript/src/utils/getDistanceForDirection.d.ts.map +1 -1
  55. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts +1 -1
  56. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts.map +1 -1
  57. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts +1 -1
  58. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts.map +1 -1
  59. package/lib/typescript/src/utils/useCardAnimation.d.ts +1 -1
  60. package/lib/typescript/src/utils/useCardAnimation.d.ts.map +1 -1
  61. package/lib/typescript/src/utils/useGestureHandler.d.ts +2 -0
  62. package/lib/typescript/src/utils/useGestureHandler.d.ts.map +1 -0
  63. package/lib/typescript/src/utils/useKeyboardManager.d.ts +12 -2
  64. package/lib/typescript/src/utils/useKeyboardManager.d.ts.map +1 -1
  65. package/lib/typescript/src/views/GestureHandler.android.d.ts +1 -1
  66. package/lib/typescript/src/views/GestureHandler.android.d.ts.map +1 -1
  67. package/lib/typescript/src/views/GestureHandler.d.ts +7 -11
  68. package/lib/typescript/src/views/GestureHandler.d.ts.map +1 -1
  69. package/lib/typescript/src/views/GestureHandler.ios.d.ts +1 -1
  70. package/lib/typescript/src/views/GestureHandler.ios.d.ts.map +1 -1
  71. package/lib/typescript/src/views/GestureHandlerNative.d.ts +9 -4
  72. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +1 -1
  73. package/lib/typescript/src/views/Header/Header.d.ts +2 -2
  74. package/lib/typescript/src/views/Header/Header.d.ts.map +1 -1
  75. package/lib/typescript/src/views/Header/HeaderContainer.d.ts +9 -3
  76. package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
  77. package/lib/typescript/src/views/Header/HeaderSegment.d.ts +5 -4
  78. package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -1
  79. package/lib/typescript/src/views/Stack/Card.d.ts +5 -5
  80. package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
  81. package/lib/typescript/src/views/Stack/CardContainer.d.ts +5 -7
  82. package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
  83. package/lib/typescript/src/views/Stack/CardContent.d.ts +1 -1
  84. package/lib/typescript/src/views/Stack/CardContent.d.ts.map +1 -1
  85. package/lib/typescript/src/views/Stack/CardStack.d.ts +6 -5
  86. package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
  87. package/lib/typescript/src/views/Stack/StackView.d.ts +10 -13
  88. package/lib/typescript/src/views/Stack/StackView.d.ts.map +1 -1
  89. package/package.json +21 -23
  90. package/src/index.tsx +3 -2
  91. package/src/navigators/createStackNavigator.tsx +9 -40
  92. package/src/types.tsx +73 -73
  93. package/src/utils/GestureHandlerContext.tsx +5 -0
  94. package/src/utils/gestureActivationCriteria.tsx +14 -10
  95. package/src/utils/useCardAnimation.tsx +1 -1
  96. package/src/utils/useGestureHandler.tsx +9 -0
  97. package/src/utils/useKeyboardManager.tsx +96 -33
  98. package/src/views/GestureHandler.tsx +27 -16
  99. package/src/views/GestureHandlerNative.tsx +26 -12
  100. package/src/views/Header/Header.tsx +2 -2
  101. package/src/views/Header/HeaderContainer.tsx +67 -24
  102. package/src/views/Header/HeaderSegment.tsx +4 -4
  103. package/src/views/Stack/Card.tsx +134 -115
  104. package/src/views/Stack/CardContainer.tsx +86 -127
  105. package/src/views/Stack/CardStack.tsx +380 -323
  106. package/src/views/Stack/StackView.tsx +173 -71
  107. package/lib/module/utils/GestureHandlerRefContext.js +0 -5
  108. package/lib/module/utils/GestureHandlerRefContext.js.map +0 -1
  109. package/lib/module/utils/findLastIndex.js +0 -11
  110. package/lib/module/utils/findLastIndex.js.map +0 -1
  111. package/lib/module/utils/useGestureHandlerRef.js +0 -12
  112. package/lib/module/utils/useGestureHandlerRef.js.map +0 -1
  113. package/lib/module/views/Stack/CardA11yWrapper.js +0 -43
  114. package/lib/module/views/Stack/CardA11yWrapper.js.map +0 -1
  115. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts +0 -3
  116. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts.map +0 -1
  117. package/lib/typescript/src/utils/findLastIndex.d.ts +0 -2
  118. package/lib/typescript/src/utils/findLastIndex.d.ts.map +0 -1
  119. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts +0 -3
  120. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts.map +0 -1
  121. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +0 -15
  122. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +0 -1
  123. package/src/utils/GestureHandlerRefContext.tsx +0 -5
  124. package/src/utils/findLastIndex.tsx +0 -9
  125. package/src/utils/useGestureHandlerRef.tsx +0 -15
  126. package/src/views/Stack/CardA11yWrapper.tsx +0 -67
@@ -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 (didInitiallyAnimate.current) {
222
- // Make sure to re-open screen if it wasn't removed
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> | null>(null);
279
+ const timeoutRef = React.useRef<ReturnType<typeof setTimeout>>(undefined);
359
280
 
360
- React.useEffect(() => {
361
- if (preloaded) {
362
- return;
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
- if (timeoutRef.current) {
372
- clearTimeout(timeoutRef.current);
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 onGestureEvent = React.useMemo(
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
- gestureDirection === 'vertical' ||
480
- gestureDirection === 'vertical-inverted'
481
- ? { translationY: gesture }
482
- : { translationX: gesture },
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
- <PanGestureHandler
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
- </PanGestureHandler>
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 { Props as HeaderContainerProps } from '../Header/HeaderContainer';
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
- hasAbsoluteFloatHeader: boolean;
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
- isNextScreenTransparent: boolean;
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.useContext(HeaderHeightContext);
96
+ const parentHeaderHeight = React.use(HeaderHeightContext);
103
97
 
104
- const { onPageChangeStart, onPageChangeCancel, onPageChangeConfirm } =
105
- useKeyboardManager(
106
- React.useCallback(() => {
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
- return (
110
- navigation.isFocused() && options.keyboardHandlingEnabled !== false
111
- );
112
- }, [scene.descriptor])
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
- if (!gesture) {
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
- <CardA11yWrapper
240
- ref={wrapperRef}
241
- focused={focused}
242
- active={active}
211
+ <Card
243
212
  animated={animated}
244
- isNextScreenTransparent={isNextScreenTransparent}
245
- detachCurrentScreen={detachCurrentScreen}
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
- <Card
248
- animated={animated}
249
- interpolationIndex={interpolationIndex}
250
- gestureDirection={gestureDirection}
251
- layout={layout}
252
- insets={insets}
253
- direction={direction}
254
- gesture={gesture}
255
- current={scene.progress.current}
256
- next={scene.progress.next}
257
- opening={opening}
258
- closing={closing}
259
- onOpen={handleOpen}
260
- onClose={handleClose}
261
- overlay={cardOverlay}
262
- overlayEnabled={cardOverlayEnabled}
263
- shadowEnabled={cardShadowEnabled}
264
- onTransition={handleTransition}
265
- onGestureBegin={handleGestureBegin}
266
- onGestureCanceled={handleGestureCanceled}
267
- onGestureEnd={handleGestureEnd}
268
- gestureEnabled={index === 0 ? false : gestureEnabled}
269
- gestureResponseDistance={gestureResponseDistance}
270
- gestureVelocityImpact={gestureVelocityImpact}
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
- <HeaderHeightContext.Provider
308
- value={
309
- headerShown !== false
310
- ? headerHeight
311
- : (parentHeaderHeight ?? 0)
312
- }
313
- >
314
- {scene.descriptor.render()}
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