@react-navigation/stack 8.0.0-alpha.6 → 8.0.0-alpha.60

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 (147) hide show
  1. package/lib/module/TransitionConfigs/CardStyleInterpolators.js +280 -84
  2. package/lib/module/TransitionConfigs/CardStyleInterpolators.js.map +1 -1
  3. package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js +11 -44
  4. package/lib/module/TransitionConfigs/HeaderStyleInterpolators.js.map +1 -1
  5. package/lib/module/TransitionConfigs/TransitionEasings.js +71 -0
  6. package/lib/module/TransitionConfigs/TransitionEasings.js.map +1 -0
  7. package/lib/module/TransitionConfigs/TransitionPresets.js +50 -10
  8. package/lib/module/TransitionConfigs/TransitionPresets.js.map +1 -1
  9. package/lib/module/TransitionConfigs/TransitionSpecs.js +69 -34
  10. package/lib/module/TransitionConfigs/TransitionSpecs.js.map +1 -1
  11. package/lib/module/index.js +2 -2
  12. package/lib/module/index.js.map +1 -1
  13. package/lib/module/navigators/createStackNavigator.js +37 -33
  14. package/lib/module/navigators/createStackNavigator.js.map +1 -1
  15. package/lib/module/utils/GestureHandlerContext.js +5 -0
  16. package/lib/module/utils/GestureHandlerContext.js.map +1 -0
  17. package/lib/module/utils/gestureActivationCriteria.js +10 -8
  18. package/lib/module/utils/gestureActivationCriteria.js.map +1 -1
  19. package/lib/module/utils/useCardAnimation.js +1 -1
  20. package/lib/module/utils/useCardAnimation.js.map +1 -1
  21. package/lib/module/utils/useGestureHandler.js +9 -0
  22. package/lib/module/utils/useGestureHandler.js.map +1 -0
  23. package/lib/module/utils/useKeyboardManager.js +71 -26
  24. package/lib/module/utils/useKeyboardManager.js.map +1 -1
  25. package/lib/module/views/GestureHandler.js +15 -14
  26. package/lib/module/views/GestureHandler.js.map +1 -1
  27. package/lib/module/views/GestureHandlerNative.js +16 -10
  28. package/lib/module/views/GestureHandlerNative.js.map +1 -1
  29. package/lib/module/views/Header/Header.js +4 -2
  30. package/lib/module/views/Header/Header.js.map +1 -1
  31. package/lib/module/views/Header/HeaderContainer.js +60 -21
  32. package/lib/module/views/Header/HeaderContainer.js.map +1 -1
  33. package/lib/module/views/Header/HeaderSegment.js +6 -9
  34. package/lib/module/views/Header/HeaderSegment.js.map +1 -1
  35. package/lib/module/views/Stack/Card.js +170 -123
  36. package/lib/module/views/Stack/Card.js.map +1 -1
  37. package/lib/module/views/Stack/CardContainer.js +96 -98
  38. package/lib/module/views/Stack/CardContainer.js.map +1 -1
  39. package/lib/module/views/Stack/CardContent.js +10 -37
  40. package/lib/module/views/Stack/CardContent.js.map +1 -1
  41. package/lib/module/views/Stack/CardStack.js +211 -147
  42. package/lib/module/views/Stack/CardStack.js.map +1 -1
  43. package/lib/module/views/Stack/StackView.js +106 -57
  44. package/lib/module/views/Stack/StackView.js.map +1 -1
  45. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts +20 -12
  46. package/lib/typescript/src/TransitionConfigs/CardStyleInterpolators.d.ts.map +1 -1
  47. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts +4 -4
  48. package/lib/typescript/src/TransitionConfigs/HeaderStyleInterpolators.d.ts.map +1 -1
  49. package/lib/typescript/src/TransitionConfigs/TransitionEasings.d.ts +38 -0
  50. package/lib/typescript/src/TransitionConfigs/TransitionEasings.d.ts.map +1 -0
  51. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts +15 -3
  52. package/lib/typescript/src/TransitionConfigs/TransitionPresets.d.ts.map +1 -1
  53. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts +44 -15
  54. package/lib/typescript/src/TransitionConfigs/TransitionSpecs.d.ts.map +1 -1
  55. package/lib/typescript/src/index.d.ts +12 -12
  56. package/lib/typescript/src/index.d.ts.map +1 -1
  57. package/lib/typescript/src/navigators/createStackNavigator.d.ts +10 -15
  58. package/lib/typescript/src/navigators/createStackNavigator.d.ts.map +1 -1
  59. package/lib/typescript/src/types.d.ts +120 -108
  60. package/lib/typescript/src/types.d.ts.map +1 -1
  61. package/lib/typescript/src/utils/CardAnimationContext.d.ts +1 -1
  62. package/lib/typescript/src/utils/CardAnimationContext.d.ts.map +1 -1
  63. package/lib/typescript/src/utils/GestureHandlerContext.d.ts +3 -0
  64. package/lib/typescript/src/utils/GestureHandlerContext.d.ts.map +1 -0
  65. package/lib/typescript/src/utils/gestureActivationCriteria.d.ts +4 -51
  66. package/lib/typescript/src/utils/gestureActivationCriteria.d.ts.map +1 -1
  67. package/lib/typescript/src/utils/getDistanceForDirection.d.ts +1 -1
  68. package/lib/typescript/src/utils/getDistanceForDirection.d.ts.map +1 -1
  69. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts +1 -1
  70. package/lib/typescript/src/utils/getInvertedMultiplier.d.ts.map +1 -1
  71. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts +1 -1
  72. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts.map +1 -1
  73. package/lib/typescript/src/utils/getShadowStyle.d.ts +5 -5
  74. package/lib/typescript/src/utils/useCardAnimation.d.ts +1 -1
  75. package/lib/typescript/src/utils/useCardAnimation.d.ts.map +1 -1
  76. package/lib/typescript/src/utils/useGestureHandler.d.ts +2 -0
  77. package/lib/typescript/src/utils/useGestureHandler.d.ts.map +1 -0
  78. package/lib/typescript/src/utils/useKeyboardManager.d.ts +12 -2
  79. package/lib/typescript/src/utils/useKeyboardManager.d.ts.map +1 -1
  80. package/lib/typescript/src/views/GestureHandler.android.d.ts +1 -1
  81. package/lib/typescript/src/views/GestureHandler.android.d.ts.map +1 -1
  82. package/lib/typescript/src/views/GestureHandler.d.ts +7 -11
  83. package/lib/typescript/src/views/GestureHandler.d.ts.map +1 -1
  84. package/lib/typescript/src/views/GestureHandler.ios.d.ts +1 -1
  85. package/lib/typescript/src/views/GestureHandler.ios.d.ts.map +1 -1
  86. package/lib/typescript/src/views/GestureHandlerNative.d.ts +9 -4
  87. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +1 -1
  88. package/lib/typescript/src/views/Header/Header.d.ts +2 -2
  89. package/lib/typescript/src/views/Header/Header.d.ts.map +1 -1
  90. package/lib/typescript/src/views/Header/HeaderContainer.d.ts +9 -3
  91. package/lib/typescript/src/views/Header/HeaderContainer.d.ts.map +1 -1
  92. package/lib/typescript/src/views/Header/HeaderSegment.d.ts +6 -4
  93. package/lib/typescript/src/views/Header/HeaderSegment.d.ts.map +1 -1
  94. package/lib/typescript/src/views/Stack/Card.d.ts +14 -8
  95. package/lib/typescript/src/views/Stack/Card.d.ts.map +1 -1
  96. package/lib/typescript/src/views/Stack/CardContainer.d.ts +7 -7
  97. package/lib/typescript/src/views/Stack/CardContainer.d.ts.map +1 -1
  98. package/lib/typescript/src/views/Stack/CardContent.d.ts +1 -1
  99. package/lib/typescript/src/views/Stack/CardContent.d.ts.map +1 -1
  100. package/lib/typescript/src/views/Stack/CardStack.d.ts +10 -6
  101. package/lib/typescript/src/views/Stack/CardStack.d.ts.map +1 -1
  102. package/lib/typescript/src/views/Stack/StackView.d.ts +14 -17
  103. package/lib/typescript/src/views/Stack/StackView.d.ts.map +1 -1
  104. package/package.json +23 -24
  105. package/src/TransitionConfigs/CardStyleInterpolators.tsx +399 -100
  106. package/src/TransitionConfigs/HeaderStyleInterpolators.tsx +15 -46
  107. package/src/TransitionConfigs/TransitionEasings.tsx +90 -0
  108. package/src/TransitionConfigs/TransitionPresets.tsx +56 -10
  109. package/src/TransitionConfigs/TransitionSpecs.tsx +68 -34
  110. package/src/index.tsx +3 -2
  111. package/src/navigators/createStackNavigator.tsx +74 -91
  112. package/src/types.tsx +149 -123
  113. package/src/utils/GestureHandlerContext.tsx +5 -0
  114. package/src/utils/gestureActivationCriteria.tsx +14 -10
  115. package/src/utils/useCardAnimation.tsx +1 -1
  116. package/src/utils/useGestureHandler.tsx +9 -0
  117. package/src/utils/useKeyboardManager.tsx +96 -33
  118. package/src/views/GestureHandler.tsx +24 -16
  119. package/src/views/GestureHandlerNative.tsx +24 -13
  120. package/src/views/Header/Header.tsx +4 -2
  121. package/src/views/Header/HeaderContainer.tsx +79 -37
  122. package/src/views/Header/HeaderSegment.tsx +10 -11
  123. package/src/views/Stack/Card.tsx +241 -154
  124. package/src/views/Stack/CardContainer.tsx +111 -127
  125. package/src/views/Stack/CardContent.tsx +13 -51
  126. package/src/views/Stack/CardStack.tsx +478 -335
  127. package/src/views/Stack/StackView.tsx +181 -82
  128. package/lib/module/utils/GestureHandlerRefContext.js +0 -5
  129. package/lib/module/utils/GestureHandlerRefContext.js.map +0 -1
  130. package/lib/module/utils/findLastIndex.js +0 -11
  131. package/lib/module/utils/findLastIndex.js.map +0 -1
  132. package/lib/module/utils/useGestureHandlerRef.js +0 -12
  133. package/lib/module/utils/useGestureHandlerRef.js.map +0 -1
  134. package/lib/module/views/Stack/CardA11yWrapper.js +0 -43
  135. package/lib/module/views/Stack/CardA11yWrapper.js.map +0 -1
  136. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts +0 -3
  137. package/lib/typescript/src/utils/GestureHandlerRefContext.d.ts.map +0 -1
  138. package/lib/typescript/src/utils/findLastIndex.d.ts +0 -2
  139. package/lib/typescript/src/utils/findLastIndex.d.ts.map +0 -1
  140. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts +0 -3
  141. package/lib/typescript/src/utils/useGestureHandlerRef.d.ts.map +0 -1
  142. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts +0 -15
  143. package/lib/typescript/src/views/Stack/CardA11yWrapper.d.ts.map +0 -1
  144. package/src/utils/GestureHandlerRefContext.tsx +0 -5
  145. package/src/utils/findLastIndex.tsx +0 -9
  146. package/src/utils/useGestureHandlerRef.tsx +0 -15
  147. package/src/views/Stack/CardA11yWrapper.tsx +0 -67
@@ -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;
@@ -27,6 +29,8 @@ type Props = {
27
29
  focused: boolean;
28
30
  opening: boolean;
29
31
  closing: boolean;
32
+ closingAnimated: Animated.Value;
33
+ nextClosingAnimated: Animated.Value | undefined;
30
34
  modal: boolean;
31
35
  layout: Layout;
32
36
  gesture: Animated.Value;
@@ -49,36 +53,31 @@ type Props = {
49
53
  onGestureStart: (props: { route: Route<string> }) => void;
50
54
  onGestureEnd: (props: { route: Route<string> }) => void;
51
55
  onGestureCancel: (props: { route: Route<string> }) => void;
52
- hasAbsoluteFloatHeader: boolean;
53
- headerHeight: number;
56
+ headerHeight: HeaderHeight | undefined;
54
57
  onHeaderHeightChange: (props: {
55
58
  route: Route<string>;
56
59
  height: number;
57
60
  }) => void;
58
61
  isParentHeaderShown: boolean;
59
- isNextScreenTransparent: boolean;
60
- detachCurrentScreen: boolean;
62
+ children: React.ReactNode;
61
63
  };
62
64
 
63
- const EPSILON = 0.1;
64
-
65
65
  function CardContainerInner({
66
66
  interpolationIndex,
67
67
  index,
68
68
  active,
69
69
  opening,
70
70
  closing,
71
+ closingAnimated,
72
+ nextClosingAnimated,
71
73
  gesture,
72
74
  focused,
73
75
  modal,
74
76
  getPreviousScene,
75
77
  getFocusedRoute,
76
- hasAbsoluteFloatHeader,
77
78
  headerHeight,
78
79
  onHeaderHeightChange,
79
80
  isParentHeaderShown,
80
- isNextScreenTransparent,
81
- detachCurrentScreen,
82
81
  layout,
83
82
  onCloseRoute,
84
83
  onOpenRoute,
@@ -94,23 +93,22 @@ function CardContainerInner({
94
93
  safeAreaInsetRight,
95
94
  safeAreaInsetTop,
96
95
  scene,
96
+ children,
97
97
  }: Props) {
98
- const wrapperRef = React.useRef<CardA11yWrapperRef>(null);
99
-
100
98
  const { direction } = useLocale();
101
99
 
102
- const parentHeaderHeight = React.useContext(HeaderHeightContext);
100
+ const parentHeaderHeight = React.use(HeaderHeightContext);
103
101
 
104
- const { onPageChangeStart, onPageChangeCancel, onPageChangeConfirm } =
105
- useKeyboardManager(
106
- React.useCallback(() => {
107
- const { options, navigation } = scene.descriptor;
102
+ const { options } = scene.descriptor;
103
+ const enabled = options.keyboardHandlingEnabled !== false;
104
+ const contentRef = React.useRef<React.ComponentRef<typeof View>>(null);
108
105
 
109
- return (
110
- navigation.isFocused() && options.keyboardHandlingEnabled !== false
111
- );
112
- }, [scene.descriptor])
113
- );
106
+ const { onPageChangeStart, onPageChangeCancel, onPageChangeConfirm } =
107
+ useKeyboardManager({
108
+ enabled,
109
+ focused,
110
+ contentRef,
111
+ });
114
112
 
115
113
  const handleOpen = () => {
116
114
  const { route } = scene.descriptor;
@@ -153,17 +151,9 @@ function CardContainerInner({
153
151
  closing: boolean;
154
152
  gesture: boolean;
155
153
  }) => {
156
- wrapperRef.current?.setInert(closing);
157
-
158
154
  const { route } = scene.descriptor;
159
155
 
160
- if (!gesture) {
161
- onPageChangeConfirm?.(true);
162
- } else if (active && closing) {
163
- onPageChangeConfirm?.(false);
164
- } else {
165
- onPageChangeCancel?.();
166
- }
156
+ onPageChangeConfirm?.({ gesture, active, closing });
167
157
 
168
158
  onTransitionStart?.({ route }, closing);
169
159
  };
@@ -177,20 +167,6 @@ function CardContainerInner({
177
167
 
178
168
  const { colors } = useTheme();
179
169
 
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
170
  const {
195
171
  presentation,
196
172
  animation,
@@ -235,91 +211,99 @@ function CardContainerInner({
235
211
 
236
212
  const animated = animation !== 'none';
237
213
 
214
+ const { current, next } = React.useMemo(
215
+ () => ({
216
+ current: { progress: scene.progress.current, closing: closingAnimated },
217
+ next:
218
+ scene.progress.next && nextClosingAnimated
219
+ ? { progress: scene.progress.next, closing: nextClosingAnimated }
220
+ : undefined,
221
+ }),
222
+ [closingAnimated, nextClosingAnimated, scene.progress]
223
+ );
224
+
238
225
  return (
239
- <CardA11yWrapper
240
- ref={wrapperRef}
241
- focused={focused}
242
- active={active}
226
+ <Card
243
227
  animated={animated}
244
- isNextScreenTransparent={isNextScreenTransparent}
245
- detachCurrentScreen={detachCurrentScreen}
228
+ interpolationIndex={interpolationIndex}
229
+ gestureDirection={gestureDirection}
230
+ layout={layout}
231
+ insets={insets}
232
+ direction={direction}
233
+ gesture={gesture}
234
+ current={current}
235
+ next={next}
236
+ opening={opening}
237
+ closing={closing}
238
+ onOpen={handleOpen}
239
+ onClose={handleClose}
240
+ overlay={cardOverlay}
241
+ overlayEnabled={cardOverlayEnabled}
242
+ shadowEnabled={cardShadowEnabled}
243
+ onTransition={handleTransition}
244
+ onGestureBegin={handleGestureBegin}
245
+ onGestureCanceled={handleGestureCanceled}
246
+ onGestureEnd={handleGestureEnd}
247
+ gestureEnabled={index === 0 ? false : gestureEnabled}
248
+ gestureResponseDistance={gestureResponseDistance}
249
+ gestureVelocityImpact={gestureVelocityImpact}
250
+ transitionSpec={transitionSpec}
251
+ styleInterpolator={cardStyleInterpolator}
252
+ pageOverflowEnabled={
253
+ // Avoid unfocused larger pages increasing scroll area
254
+ // e.g. when a smaller screen is pushed over a larger one on web
255
+ active &&
256
+ // Float header disables full-page scrolling in browsers
257
+ // So we don't need to keep overflow enabled
258
+ headerMode !== 'float' &&
259
+ // Avoid modals scrolling the whole page
260
+ // Modal content should be scrollable within the modal
261
+ presentation !== 'modal'
262
+ }
263
+ preloaded={preloaded}
264
+ contentStyle={[
265
+ {
266
+ backgroundColor:
267
+ presentation === 'transparentModal'
268
+ ? 'transparent'
269
+ : colors.background,
270
+ },
271
+ cardStyle,
272
+ ]}
246
273
  >
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}
274
+ <View ref={contentRef} style={styles.container}>
275
+ <ModalPresentationContext.Provider value={modal}>
276
+ {headerMode !== 'float'
277
+ ? renderHeader({
278
+ mode: 'screen',
279
+ scenes: [previousScene, scene],
280
+ getPreviousScene,
281
+ getFocusedRoute,
282
+ contentHeight: headerHeight,
283
+ onContentHeightChange: onHeaderHeightChange,
284
+ style: styles.header,
285
+ })
286
+ : null}
287
+ <View style={styles.scene}>
288
+ <HeaderBackContext.Provider value={headerBack}>
289
+ <HeaderShownContext.Provider
290
+ value={isParentHeaderShown || headerShown !== false}
291
+ >
292
+ <HeaderHeightContext.Provider
293
+ value={
294
+ headerShown !== false
295
+ ? (headerHeight?.value ?? 0)
296
+ : (parentHeaderHeight ?? 0)
297
+ }
306
298
  >
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>
299
+ {children}
300
+ </HeaderHeightContext.Provider>
301
+ </HeaderShownContext.Provider>
302
+ </HeaderBackContext.Provider>
303
+ </View>
304
+ </ModalPresentationContext.Provider>
305
+ </View>
306
+ </Card>
323
307
  );
324
308
  }
325
309
 
@@ -7,14 +7,14 @@ type Props = ViewProps & {
7
7
  children: React.ReactNode;
8
8
  };
9
9
 
10
- // This component will render a page which overflows the screen
11
- // if the container fills the body by comparing the size
12
- // This lets the document.body handle scrolling of the content
13
- // It's necessary for mobile browsers to be able to hide address bar on scroll
14
10
  export function CardContent({ enabled, layout, style, ...rest }: Props) {
11
+ // If the container fills the body, we consider it to be a "page" that can overflow the screen
12
+ // So we adjust the style accordingly to let the content take more space if needed
13
+ // This lets the document.body handle scrolling of the content
14
+ // This is necessary for mobile browsers to be able to hide the address bar on scroll
15
15
  const [fill, setFill] = React.useState(false);
16
16
 
17
- React.useEffect(() => {
17
+ React.useLayoutEffect(() => {
18
18
  if (typeof document === 'undefined' || !document.body) {
19
19
  // Only run when DOM is available
20
20
  return;
@@ -23,53 +23,15 @@ export function CardContent({ enabled, layout, style, ...rest }: Props) {
23
23
  const width = document.body.clientWidth;
24
24
  const height = document.body.clientHeight;
25
25
 
26
- // Workaround for mobile Chrome, necessary when a navigation happens
27
- // when the address bar has already collapsed, which resulted in an
28
- // empty space at the bottom of the page (matching the height of the
29
- // address bar). To fix this, it's necessary to update the height of
30
- // the DOM with the current height of the window.
31
- // See https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
32
- const isFullHeight = height === layout.height;
33
- const id = '__react-navigation-stack-mobile-chrome-viewport-fix';
26
+ // `document.body.clientHeight`/`clientWidth` are always rounded integers,
27
+ // But `layout` is sub-pixel precise, so we allow a small difference.
28
+ const approximatelyEqual = (a: number, b: number) => Math.abs(a - b) < 1;
34
29
 
35
- let unsubscribe: (() => void) | undefined;
36
-
37
- if (isFullHeight && navigator.maxTouchPoints > 0) {
38
- const style =
39
- document.getElementById(id) ?? document.createElement('style');
40
-
41
- style.id = id;
42
-
43
- const updateStyle = () => {
44
- const vh = window.innerHeight * 0.01;
45
-
46
- style.textContent = [
47
- `:root { --vh: ${vh}px; }`,
48
- `body { height: calc(var(--vh, 1vh) * 100); }`,
49
- ].join('\n');
50
- };
51
-
52
- updateStyle();
53
-
54
- if (!document.head.contains(style)) {
55
- document.head.appendChild(style);
56
- }
57
-
58
- window.addEventListener('resize', updateStyle);
59
-
60
- unsubscribe = () => {
61
- window.removeEventListener('resize', updateStyle);
62
- };
63
- } else {
64
- // Remove the workaround if the stack does not occupy the whole
65
- // height of the page
66
- document.getElementById(id)?.remove();
67
- }
68
-
69
- // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
70
- setFill(width === layout.width && height === layout.height);
71
-
72
- return unsubscribe;
30
+ // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-layout-effect
31
+ setFill(
32
+ approximatelyEqual(width, layout.width) &&
33
+ approximatelyEqual(height, layout.height)
34
+ );
73
35
  }, [layout.height, layout.width]);
74
36
 
75
37
  return (