@react-navigation/native-stack 7.0.0-rc.9 → 7.0.1

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 (173) hide show
  1. package/lib/commonjs/{index.cjs → index.js} +3 -3
  2. package/lib/commonjs/navigators/{createNativeStackNavigator.cjs → createNativeStackNavigator.js} +4 -2
  3. package/lib/commonjs/navigators/createNativeStackNavigator.js.map +1 -0
  4. package/lib/commonjs/package.json +1 -0
  5. package/lib/commonjs/{types.cjs → types.js} +1 -1
  6. package/lib/commonjs/utils/{debounce.cjs → debounce.js} +1 -1
  7. package/lib/commonjs/utils/{debounce.cjs.map → debounce.js.map} +1 -1
  8. package/lib/commonjs/utils/{getModalRoutesKeys.cjs → getModalRoutesKeys.js} +1 -1
  9. package/lib/commonjs/utils/{useAnimatedHeaderHeight.cjs → useAnimatedHeaderHeight.js} +1 -1
  10. package/lib/commonjs/utils/{useDismissedRouteError.cjs → useDismissedRouteError.js} +1 -1
  11. package/lib/commonjs/utils/{useInvalidPreventRemoveError.cjs → useInvalidPreventRemoveError.js} +1 -1
  12. package/lib/commonjs/views/{FontProcessor.cjs → FontProcessor.js} +1 -1
  13. package/lib/commonjs/views/{FontProcessor.native.cjs → FontProcessor.native.js} +1 -1
  14. package/lib/commonjs/views/FooterComponent.js +19 -0
  15. package/lib/commonjs/views/FooterComponent.js.map +1 -0
  16. package/lib/commonjs/views/{NativeStackView.cjs → NativeStackView.js} +46 -50
  17. package/lib/commonjs/views/NativeStackView.js.map +1 -0
  18. package/lib/commonjs/views/{NativeStackView.native.cjs → NativeStackView.native.js} +132 -145
  19. package/lib/commonjs/views/NativeStackView.native.js.map +1 -0
  20. package/lib/commonjs/views/{HeaderConfig.cjs → useHeaderConfigProps.js} +69 -48
  21. package/lib/commonjs/views/useHeaderConfigProps.js.map +1 -0
  22. package/lib/module/{index.mjs → index.js} +5 -3
  23. package/lib/module/index.js.map +1 -0
  24. package/lib/module/navigators/{createNativeStackNavigator.mjs → createNativeStackNavigator.js} +6 -2
  25. package/lib/module/navigators/createNativeStackNavigator.js.map +1 -0
  26. package/lib/module/package.json +1 -0
  27. package/lib/module/types.js +4 -0
  28. package/lib/module/utils/{debounce.mjs → debounce.js} +3 -1
  29. package/lib/module/utils/debounce.js.map +1 -0
  30. package/lib/module/utils/{getModalRoutesKeys.mjs → getModalRoutesKeys.js} +3 -1
  31. package/lib/module/utils/getModalRoutesKeys.js.map +1 -0
  32. package/lib/module/utils/{useAnimatedHeaderHeight.mjs → useAnimatedHeaderHeight.js} +3 -1
  33. package/lib/module/utils/useAnimatedHeaderHeight.js.map +1 -0
  34. package/lib/module/utils/{useDismissedRouteError.mjs → useDismissedRouteError.js} +3 -1
  35. package/lib/module/utils/useDismissedRouteError.js.map +1 -0
  36. package/lib/module/utils/{useInvalidPreventRemoveError.mjs → useInvalidPreventRemoveError.js} +3 -1
  37. package/lib/module/utils/useInvalidPreventRemoveError.js.map +1 -0
  38. package/lib/module/views/{FontProcessor.mjs → FontProcessor.js} +3 -1
  39. package/lib/module/views/{FontProcessor.mjs.map → FontProcessor.js.map} +1 -1
  40. package/lib/module/views/{FontProcessor.native.mjs → FontProcessor.native.js} +3 -1
  41. package/lib/module/views/FontProcessor.native.js.map +1 -0
  42. package/lib/module/views/FooterComponent.js +14 -0
  43. package/lib/module/views/FooterComponent.js.map +1 -0
  44. package/lib/module/views/{NativeStackView.mjs → NativeStackView.js} +50 -52
  45. package/lib/module/views/NativeStackView.js.map +1 -0
  46. package/lib/module/views/{NativeStackView.native.mjs → NativeStackView.native.js} +135 -145
  47. package/lib/module/views/NativeStackView.native.js.map +1 -0
  48. package/lib/module/views/{HeaderConfig.mjs → useHeaderConfigProps.js} +71 -48
  49. package/lib/module/views/useHeaderConfigProps.js.map +1 -0
  50. package/lib/typescript/commonjs/package.json +1 -0
  51. package/lib/typescript/{src → commonjs/src}/index.d.ts +1 -1
  52. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  53. package/lib/typescript/{src → commonjs/src}/navigators/createNativeStackNavigator.d.ts +2 -2
  54. package/lib/typescript/commonjs/src/navigators/createNativeStackNavigator.d.ts.map +1 -0
  55. package/lib/typescript/{src → commonjs/src}/types.d.ts +113 -35
  56. package/lib/typescript/commonjs/src/types.d.ts.map +1 -0
  57. package/lib/typescript/commonjs/src/utils/debounce.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/src/utils/getModalRoutesKeys.d.ts.map +1 -0
  59. package/lib/typescript/commonjs/src/utils/useAnimatedHeaderHeight.d.ts.map +1 -0
  60. package/lib/typescript/commonjs/src/utils/useDismissedRouteError.d.ts.map +1 -0
  61. package/lib/typescript/commonjs/src/utils/useInvalidPreventRemoveError.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/src/views/FontProcessor.d.ts.map +1 -0
  63. package/lib/typescript/commonjs/src/views/FontProcessor.native.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/src/views/FooterComponent.d.ts +7 -0
  65. package/lib/typescript/commonjs/src/views/FooterComponent.d.ts.map +1 -0
  66. package/lib/typescript/commonjs/src/views/NativeStackView.d.ts +11 -0
  67. package/lib/typescript/commonjs/src/views/NativeStackView.d.ts.map +1 -0
  68. package/lib/typescript/commonjs/src/views/NativeStackView.native.d.ts +11 -0
  69. package/lib/typescript/commonjs/src/views/NativeStackView.native.d.ts.map +1 -0
  70. package/lib/typescript/commonjs/src/views/useHeaderConfigProps.d.ts +41 -0
  71. package/lib/typescript/commonjs/src/views/useHeaderConfigProps.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/tsconfig.build.tsbuildinfo +1 -0
  73. package/lib/typescript/module/package.json +1 -0
  74. package/lib/typescript/module/src/index.d.ts +17 -0
  75. package/lib/typescript/module/src/index.d.ts.map +1 -0
  76. package/lib/typescript/module/src/navigators/createNativeStackNavigator.d.ts +16 -0
  77. package/lib/typescript/module/src/navigators/createNativeStackNavigator.d.ts.map +1 -0
  78. package/lib/typescript/module/src/types.d.ts +623 -0
  79. package/lib/typescript/module/src/types.d.ts.map +1 -0
  80. package/lib/typescript/module/src/utils/debounce.d.ts +2 -0
  81. package/lib/typescript/module/src/utils/debounce.d.ts.map +1 -0
  82. package/lib/typescript/module/src/utils/getModalRoutesKeys.d.ts +4 -0
  83. package/lib/typescript/module/src/utils/getModalRoutesKeys.d.ts.map +1 -0
  84. package/lib/typescript/module/src/utils/useAnimatedHeaderHeight.d.ts +5 -0
  85. package/lib/typescript/module/src/utils/useAnimatedHeaderHeight.d.ts.map +1 -0
  86. package/lib/typescript/module/src/utils/useDismissedRouteError.d.ts +6 -0
  87. package/lib/typescript/module/src/utils/useDismissedRouteError.d.ts.map +1 -0
  88. package/lib/typescript/module/src/utils/useInvalidPreventRemoveError.d.ts +3 -0
  89. package/lib/typescript/module/src/utils/useInvalidPreventRemoveError.d.ts.map +1 -0
  90. package/lib/typescript/module/src/views/FontProcessor.d.ts +2 -0
  91. package/lib/typescript/module/src/views/FontProcessor.d.ts.map +1 -0
  92. package/lib/typescript/module/src/views/FontProcessor.native.d.ts +2 -0
  93. package/lib/typescript/module/src/views/FontProcessor.native.d.ts.map +1 -0
  94. package/lib/typescript/module/src/views/FooterComponent.d.ts +7 -0
  95. package/lib/typescript/module/src/views/FooterComponent.d.ts.map +1 -0
  96. package/lib/typescript/module/src/views/NativeStackView.d.ts +11 -0
  97. package/lib/typescript/module/src/views/NativeStackView.d.ts.map +1 -0
  98. package/lib/typescript/module/src/views/NativeStackView.native.d.ts +11 -0
  99. package/lib/typescript/module/src/views/NativeStackView.native.d.ts.map +1 -0
  100. package/lib/typescript/module/src/views/useHeaderConfigProps.d.ts +41 -0
  101. package/lib/typescript/module/src/views/useHeaderConfigProps.d.ts.map +1 -0
  102. package/lib/typescript/module/tsconfig.build.tsbuildinfo +1 -0
  103. package/package.json +36 -19
  104. package/src/index.tsx +2 -0
  105. package/src/navigators/createNativeStackNavigator.tsx +6 -5
  106. package/src/types.tsx +107 -35
  107. package/src/utils/debounce.tsx +1 -1
  108. package/src/views/FooterComponent.tsx +10 -0
  109. package/src/views/NativeStackView.native.tsx +168 -202
  110. package/src/views/NativeStackView.tsx +62 -50
  111. package/src/views/{HeaderConfig.tsx → useHeaderConfigProps.tsx} +80 -63
  112. package/lib/commonjs/navigators/createNativeStackNavigator.cjs.map +0 -1
  113. package/lib/commonjs/views/DebugContainer.cjs +0 -22
  114. package/lib/commonjs/views/DebugContainer.cjs.map +0 -1
  115. package/lib/commonjs/views/DebugContainer.native.cjs +0 -49
  116. package/lib/commonjs/views/DebugContainer.native.cjs.map +0 -1
  117. package/lib/commonjs/views/HeaderConfig.cjs.map +0 -1
  118. package/lib/commonjs/views/NativeStackView.cjs.map +0 -1
  119. package/lib/commonjs/views/NativeStackView.native.cjs.map +0 -1
  120. package/lib/module/index.mjs.map +0 -1
  121. package/lib/module/navigators/createNativeStackNavigator.mjs.map +0 -1
  122. package/lib/module/types.mjs +0 -2
  123. package/lib/module/utils/debounce.mjs.map +0 -1
  124. package/lib/module/utils/getModalRoutesKeys.mjs.map +0 -1
  125. package/lib/module/utils/useAnimatedHeaderHeight.mjs.map +0 -1
  126. package/lib/module/utils/useDismissedRouteError.mjs.map +0 -1
  127. package/lib/module/utils/useInvalidPreventRemoveError.mjs.map +0 -1
  128. package/lib/module/views/DebugContainer.mjs +0 -14
  129. package/lib/module/views/DebugContainer.mjs.map +0 -1
  130. package/lib/module/views/DebugContainer.native.mjs +0 -38
  131. package/lib/module/views/DebugContainer.native.mjs.map +0 -1
  132. package/lib/module/views/FontProcessor.native.mjs.map +0 -1
  133. package/lib/module/views/HeaderConfig.mjs.map +0 -1
  134. package/lib/module/views/NativeStackView.mjs.map +0 -1
  135. package/lib/module/views/NativeStackView.native.mjs.map +0 -1
  136. package/lib/typescript/src/index.d.ts.map +0 -1
  137. package/lib/typescript/src/navigators/createNativeStackNavigator.d.ts.map +0 -1
  138. package/lib/typescript/src/types.d.ts.map +0 -1
  139. package/lib/typescript/src/utils/debounce.d.ts.map +0 -1
  140. package/lib/typescript/src/utils/getModalRoutesKeys.d.ts.map +0 -1
  141. package/lib/typescript/src/utils/useAnimatedHeaderHeight.d.ts.map +0 -1
  142. package/lib/typescript/src/utils/useDismissedRouteError.d.ts.map +0 -1
  143. package/lib/typescript/src/utils/useInvalidPreventRemoveError.d.ts.map +0 -1
  144. package/lib/typescript/src/views/DebugContainer.d.ts +0 -10
  145. package/lib/typescript/src/views/DebugContainer.d.ts.map +0 -1
  146. package/lib/typescript/src/views/DebugContainer.native.d.ts +0 -15
  147. package/lib/typescript/src/views/DebugContainer.native.d.ts.map +0 -1
  148. package/lib/typescript/src/views/FontProcessor.d.ts.map +0 -1
  149. package/lib/typescript/src/views/FontProcessor.native.d.ts.map +0 -1
  150. package/lib/typescript/src/views/HeaderConfig.d.ts +0 -11
  151. package/lib/typescript/src/views/HeaderConfig.d.ts.map +0 -1
  152. package/lib/typescript/src/views/NativeStackView.d.ts +0 -10
  153. package/lib/typescript/src/views/NativeStackView.d.ts.map +0 -1
  154. package/lib/typescript/src/views/NativeStackView.native.d.ts +0 -10
  155. package/lib/typescript/src/views/NativeStackView.native.d.ts.map +0 -1
  156. package/src/views/DebugContainer.native.tsx +0 -36
  157. package/src/views/DebugContainer.tsx +0 -14
  158. /package/lib/commonjs/{index.cjs.map → index.js.map} +0 -0
  159. /package/lib/commonjs/{types.cjs.map → types.js.map} +0 -0
  160. /package/lib/commonjs/utils/{getModalRoutesKeys.cjs.map → getModalRoutesKeys.js.map} +0 -0
  161. /package/lib/commonjs/utils/{useAnimatedHeaderHeight.cjs.map → useAnimatedHeaderHeight.js.map} +0 -0
  162. /package/lib/commonjs/utils/{useDismissedRouteError.cjs.map → useDismissedRouteError.js.map} +0 -0
  163. /package/lib/commonjs/utils/{useInvalidPreventRemoveError.cjs.map → useInvalidPreventRemoveError.js.map} +0 -0
  164. /package/lib/commonjs/views/{FontProcessor.cjs.map → FontProcessor.js.map} +0 -0
  165. /package/lib/commonjs/views/{FontProcessor.native.cjs.map → FontProcessor.native.js.map} +0 -0
  166. /package/lib/module/{types.mjs.map → types.js.map} +0 -0
  167. /package/lib/typescript/{src → commonjs/src}/utils/debounce.d.ts +0 -0
  168. /package/lib/typescript/{src → commonjs/src}/utils/getModalRoutesKeys.d.ts +0 -0
  169. /package/lib/typescript/{src → commonjs/src}/utils/useAnimatedHeaderHeight.d.ts +0 -0
  170. /package/lib/typescript/{src → commonjs/src}/utils/useDismissedRouteError.d.ts +0 -0
  171. /package/lib/typescript/{src → commonjs/src}/utils/useInvalidPreventRemoveError.d.ts +0 -0
  172. /package/lib/typescript/{src → commonjs/src}/views/FontProcessor.d.ts +0 -0
  173. /package/lib/typescript/{src → commonjs/src}/views/FontProcessor.native.d.ts +0 -0
@@ -10,7 +10,7 @@ import {
10
10
  NavigationContext,
11
11
  NavigationRouteContext,
12
12
  type ParamListBase,
13
- type Route,
13
+ type RouteProp,
14
14
  StackActions,
15
15
  type StackNavigationState,
16
16
  usePreventRemoveContext,
@@ -30,104 +30,25 @@ import {
30
30
  useSafeAreaInsets,
31
31
  } from 'react-native-safe-area-context';
32
32
  import {
33
- Screen,
34
33
  type ScreenProps,
35
34
  ScreenStack,
36
- type StackPresentationTypes,
35
+ ScreenStackItem,
37
36
  } from 'react-native-screens';
38
- import warnOnce from 'warn-once';
39
37
 
40
38
  import type {
41
39
  NativeStackDescriptor,
42
40
  NativeStackDescriptorMap,
43
41
  NativeStackNavigationHelpers,
44
- NativeStackNavigationOptions,
45
42
  } from '../types';
46
43
  import { debounce } from '../utils/debounce';
47
44
  import { getModalRouteKeys } from '../utils/getModalRoutesKeys';
48
45
  import { AnimatedHeaderHeightContext } from '../utils/useAnimatedHeaderHeight';
49
46
  import { useDismissedRouteError } from '../utils/useDismissedRouteError';
50
47
  import { useInvalidPreventRemoveError } from '../utils/useInvalidPreventRemoveError';
51
- import { DebugContainer } from './DebugContainer';
52
- import { HeaderConfig } from './HeaderConfig';
53
-
54
- const isAndroid = Platform.OS === 'android';
55
-
56
- const MaybeNestedStack = ({
57
- options,
58
- route,
59
- presentation,
60
- headerHeight,
61
- headerTopInsetEnabled,
62
- children,
63
- }: {
64
- options: NativeStackNavigationOptions;
65
- route: Route<string>;
66
- presentation: Exclude<StackPresentationTypes, 'push'> | 'card';
67
- headerHeight: number;
68
- headerTopInsetEnabled: boolean;
69
- children: React.ReactNode;
70
- }) => {
71
- const { colors } = useTheme();
72
- const { header, headerShown = true, contentStyle } = options;
73
-
74
- const isHeaderInModal = isAndroid
75
- ? false
76
- : presentation !== 'card' && headerShown === true && header === undefined;
77
-
78
- const headerShownPreviousRef = React.useRef(headerShown);
79
-
80
- React.useEffect(() => {
81
- warnOnce(
82
- !isAndroid &&
83
- presentation !== 'card' &&
84
- headerShownPreviousRef.current !== headerShown,
85
- `Dynamically changing 'headerShown' in modals will result in remounting the screen and losing all local state. See options for the screen '${route.name}'.`
86
- );
87
-
88
- headerShownPreviousRef.current = headerShown;
89
- }, [headerShown, presentation, route.name]);
90
-
91
- const content = (
92
- <DebugContainer
93
- style={[
94
- styles.container,
95
- presentation !== 'transparentModal' &&
96
- presentation !== 'containedTransparentModal' && {
97
- backgroundColor: colors.background,
98
- },
99
- contentStyle,
100
- ]}
101
- stackPresentation={presentation === 'card' ? 'push' : presentation}
102
- >
103
- {children}
104
- </DebugContainer>
105
- );
48
+ import { FooterComponent } from './FooterComponent';
49
+ import { useHeaderConfigProps } from './useHeaderConfigProps';
106
50
 
107
- if (isHeaderInModal) {
108
- return (
109
- <ScreenStack style={styles.container}>
110
- <Screen
111
- enabled
112
- isNativeStack
113
- hasLargeHeader={options.headerLargeTitle ?? false}
114
- style={StyleSheet.absoluteFill}
115
- >
116
- {content}
117
- <HeaderConfig
118
- {...options}
119
- route={route}
120
- headerHeight={headerHeight}
121
- headerTopInsetEnabled={headerTopInsetEnabled}
122
- canGoBack
123
- />
124
- </Screen>
125
- </ScreenStack>
126
- );
127
- }
128
-
129
- return content;
130
- };
51
+ const ANDROID_DEFAULT_HEADER_HEIGHT = 56;
131
52
 
132
53
  type SceneViewProps = {
133
54
  index: number;
@@ -136,6 +57,7 @@ type SceneViewProps = {
136
57
  previousDescriptor?: NativeStackDescriptor;
137
58
  nextDescriptor?: NativeStackDescriptor;
138
59
  isPresentationModal?: boolean;
60
+ isPreloaded?: boolean;
139
61
  onWillDisappear: () => void;
140
62
  onWillAppear: () => void;
141
63
  onAppear: () => void;
@@ -144,6 +66,7 @@ type SceneViewProps = {
144
66
  onHeaderBackButtonClicked: ScreenProps['onHeaderBackButtonClicked'];
145
67
  onNativeDismissCancelled: ScreenProps['onDismissed'];
146
68
  onGestureCancel: ScreenProps['onGestureCancel'];
69
+ onSheetDetentChanged: ScreenProps['onSheetDetentChanged'];
147
70
  };
148
71
 
149
72
  const SceneView = ({
@@ -153,6 +76,7 @@ const SceneView = ({
153
76
  previousDescriptor,
154
77
  nextDescriptor,
155
78
  isPresentationModal,
79
+ isPreloaded,
156
80
  onWillDisappear,
157
81
  onWillAppear,
158
82
  onAppear,
@@ -161,6 +85,7 @@ const SceneView = ({
161
85
  onHeaderBackButtonClicked,
162
86
  onNativeDismissCancelled,
163
87
  onGestureCancel,
88
+ onSheetDetentChanged,
164
89
  }: SceneViewProps) => {
165
90
  const { route, navigation, options, render } = descriptor;
166
91
 
@@ -174,6 +99,7 @@ const SceneView = ({
174
99
  const {
175
100
  animationDuration,
176
101
  animationTypeForReplace = 'push',
102
+ fullScreenGestureShadowEnabled = true,
177
103
  gestureEnabled,
178
104
  gestureDirection = presentation === 'card' ? 'horizontal' : 'vertical',
179
105
  gestureResponseDistance,
@@ -188,17 +114,21 @@ const SceneView = ({
188
114
  navigationBarTranslucent,
189
115
  navigationBarHidden,
190
116
  orientation,
191
- sheetAllowedDetents = 'large',
192
- sheetLargestUndimmedDetent = 'all',
117
+ sheetAllowedDetents = [1.0],
118
+ sheetLargestUndimmedDetentIndex = -1,
193
119
  sheetGrabberVisible = false,
194
120
  sheetCornerRadius = -1.0,
121
+ sheetElevation = 24,
195
122
  sheetExpandsWhenScrolledToEdge = true,
123
+ sheetInitialDetentIndex = 0,
196
124
  statusBarAnimation,
197
125
  statusBarHidden,
198
126
  statusBarStyle,
199
127
  statusBarTranslucent,
200
128
  statusBarBackgroundColor,
129
+ unstable_sheetFooter = null,
201
130
  freezeOnBlur,
131
+ contentStyle,
202
132
  } = options;
203
133
 
204
134
  if (gestureDirection === 'vertical' && Platform.OS === 'ios') {
@@ -232,6 +162,7 @@ const SceneView = ({
232
162
  presentation = 'card';
233
163
  }
234
164
 
165
+ const { colors } = useTheme();
235
166
  const insets = useSafeAreaInsets();
236
167
  const frame = useSafeAreaFrame();
237
168
 
@@ -259,7 +190,7 @@ const SceneView = ({
259
190
  // FIXME: Currently screens isn't using Material 3
260
191
  // So our `getDefaultHeaderHeight` doesn't return the correct value
261
192
  // So we hardcode the value here for now until screens is updated
262
- android: 56 + topInset,
193
+ android: ANDROID_DEFAULT_HEADER_HEIGHT + topInset,
263
194
  default: getDefaultHeaderHeight(frame, isModal, topInset),
264
195
  });
265
196
 
@@ -276,7 +207,7 @@ const SceneView = ({
276
207
 
277
208
  let headerHeightCorrectionOffset = 0;
278
209
 
279
- if (isAndroid && !hasCustomHeader) {
210
+ if (Platform.OS === 'android' && !hasCustomHeader) {
280
211
  const statusBarHeight = StatusBar.currentHeight ?? 0;
281
212
 
282
213
  // FIXME: On Android, the native header height is not correctly calculated
@@ -307,32 +238,55 @@ const SceneView = ({
307
238
  ? statusBarTranslucent
308
239
  : topInset !== 0;
309
240
 
241
+ const canGoBack = previousDescriptor != null || parentHeaderBack != null;
310
242
  const backTitle = previousDescriptor
311
243
  ? getHeaderTitle(previousDescriptor.options, previousDescriptor.route.name)
312
244
  : parentHeaderBack?.title;
313
245
 
314
- const headerBack = React.useMemo(
315
- () => ({
316
- // No href needed for native
317
- href: undefined,
318
- title: backTitle,
319
- }),
320
- [backTitle]
321
- );
246
+ const headerBack = React.useMemo(() => {
247
+ if (canGoBack) {
248
+ return {
249
+ href: undefined, // No href needed for native
250
+ title: backTitle,
251
+ };
252
+ }
253
+
254
+ return undefined;
255
+ }, [canGoBack, backTitle]);
322
256
 
323
257
  const isRemovePrevented = preventedRoutes[route.key]?.preventRemove;
324
258
 
259
+ const headerConfig = useHeaderConfigProps({
260
+ ...options,
261
+ route,
262
+ canGoBack,
263
+ headerBackButtonMenuEnabled:
264
+ isRemovePrevented !== undefined
265
+ ? !isRemovePrevented
266
+ : headerBackButtonMenuEnabled,
267
+ headerBackTitle:
268
+ options.headerBackTitle !== undefined
269
+ ? options.headerBackTitle
270
+ : undefined,
271
+ headerHeight,
272
+ headerShown: header !== undefined ? false : headerShown,
273
+ headerTopInsetEnabled,
274
+ });
275
+
325
276
  return (
326
- <Screen
277
+ <ScreenStackItem
327
278
  key={route.key}
328
- enabled
329
- isNativeStack
279
+ screenId={route.key}
280
+ activityState={isPreloaded ? 0 : 2}
330
281
  style={StyleSheet.absoluteFill}
331
- hasLargeHeader={options.headerLargeTitle ?? false}
282
+ accessibilityElementsHidden={!focused}
283
+ importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
332
284
  customAnimationOnSwipe={animationMatchesGesture}
333
285
  fullScreenSwipeEnabled={fullScreenGestureEnabled}
286
+ fullScreenSwipeShadowEnabled={fullScreenGestureShadowEnabled}
287
+ freezeOnBlur={freezeOnBlur}
334
288
  gestureEnabled={
335
- isAndroid
289
+ Platform.OS === 'android'
336
290
  ? // This prop enables handling of system back gestures on Android
337
291
  // Since we handle them in JS side, we disable this
338
292
  false
@@ -341,7 +295,6 @@ const SceneView = ({
341
295
  homeIndicatorHidden={autoHideHomeIndicator}
342
296
  hideKeyboardOnSwipe={keyboardHandlingEnabled}
343
297
  navigationBarColor={navigationBarColor}
344
- // @ts-expect-error prop supported from react-native-screens 3.32.0 onwards
345
298
  navigationBarTranslucent={navigationBarTranslucent}
346
299
  navigationBarHidden={navigationBarHidden}
347
300
  replaceAnimation={animationTypeForReplace}
@@ -349,9 +302,11 @@ const SceneView = ({
349
302
  stackAnimation={animation}
350
303
  screenOrientation={orientation}
351
304
  sheetAllowedDetents={sheetAllowedDetents}
352
- sheetLargestUndimmedDetent={sheetLargestUndimmedDetent}
305
+ sheetLargestUndimmedDetentIndex={sheetLargestUndimmedDetentIndex}
353
306
  sheetGrabberVisible={sheetGrabberVisible}
307
+ sheetInitialDetentIndex={sheetInitialDetentIndex}
354
308
  sheetCornerRadius={sheetCornerRadius}
309
+ sheetElevation={sheetElevation}
355
310
  sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
356
311
  statusBarAnimation={statusBarAnimation}
357
312
  statusBarHidden={statusBarHidden}
@@ -366,6 +321,7 @@ const SceneView = ({
366
321
  onDisappear={onDisappear}
367
322
  onDismissed={onDismissed}
368
323
  onGestureCancel={onGestureCancel}
324
+ onSheetDetentChanged={onSheetDetentChanged}
369
325
  gestureResponseDistance={gestureResponseDistance}
370
326
  nativeBackButtonDismissalEnabled={false} // on Android
371
327
  onHeaderBackButtonClicked={onHeaderBackButtonClicked}
@@ -386,6 +342,16 @@ const SceneView = ({
386
342
  {
387
343
  useNativeDriver: true,
388
344
  listener: (e) => {
345
+ if (
346
+ Platform.OS === 'android' &&
347
+ (options.headerBackground != null || options.headerTransparent)
348
+ ) {
349
+ // FIXME: On Android, we get 0 if the header is translucent
350
+ // So we set a default height in that case
351
+ setHeaderHeight(ANDROID_DEFAULT_HEADER_HEIGHT + topInset);
352
+ return;
353
+ }
354
+
389
355
  if (
390
356
  e.nativeEvent &&
391
357
  typeof e.nativeEvent === 'object' &&
@@ -410,107 +376,77 @@ const SceneView = ({
410
376
  },
411
377
  }
412
378
  )}
413
- // this prop is available since rn-screens 3.16
414
- freezeOnBlur={freezeOnBlur}
379
+ contentStyle={[
380
+ presentation !== 'transparentModal' &&
381
+ presentation !== 'containedTransparentModal' && {
382
+ backgroundColor: colors.background,
383
+ },
384
+ contentStyle,
385
+ ]}
386
+ headerConfig={headerConfig}
387
+ // When ts-expect-error is added, it affects all the props below it
388
+ // So we keep any props that need it at the end
389
+ // Otherwise invalid props may not be caught by TypeScript
415
390
  >
416
391
  <NavigationContext.Provider value={navigation}>
417
392
  <NavigationRouteContext.Provider value={route}>
418
- <HeaderShownContext.Provider
419
- value={isParentHeaderShown || headerShown !== false}
420
- >
421
- <AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
422
- <HeaderHeightContext.Provider
423
- value={
424
- headerShown !== false ? headerHeight : parentHeaderHeight ?? 0
425
- }
426
- >
427
- {headerBackground != null ? (
428
- /**
429
- * To show a custom header background, we render it at the top of the screen below the header
430
- * The header also needs to be positioned absolutely (with `translucent` style)
431
- */
432
- <View
433
- style={[
434
- styles.background,
435
- headerTransparent ? styles.translucent : null,
436
- { height: headerHeight },
437
- ]}
438
- >
439
- {headerBackground()}
440
- </View>
441
- ) : null}
393
+ <AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
394
+ <HeaderHeightContext.Provider
395
+ value={
396
+ headerShown !== false ? headerHeight : parentHeaderHeight ?? 0
397
+ }
398
+ >
399
+ {headerBackground != null ? (
400
+ /**
401
+ * To show a custom header background, we render it at the top of the screen below the header
402
+ * The header also needs to be positioned absolutely (with `translucent` style)
403
+ */
404
+ <View
405
+ style={[
406
+ styles.background,
407
+ headerTransparent ? styles.translucent : null,
408
+ { height: headerHeight },
409
+ ]}
410
+ >
411
+ {headerBackground()}
412
+ </View>
413
+ ) : null}
414
+ {header !== undefined && headerShown !== false ? (
442
415
  <View
443
- accessibilityElementsHidden={!focused}
444
- importantForAccessibility={
445
- focused ? 'auto' : 'no-hide-descendants'
446
- }
447
- style={styles.scene}
416
+ onLayout={(e) => {
417
+ const headerHeight = e.nativeEvent.layout.height;
418
+
419
+ setHeaderHeight(headerHeight);
420
+ rawAnimatedHeaderHeight.setValue(headerHeight);
421
+ }}
422
+ style={[
423
+ styles.header,
424
+ headerTransparent ? styles.absolute : null,
425
+ ]}
448
426
  >
449
- <MaybeNestedStack
450
- options={options}
451
- route={route}
452
- presentation={presentation}
453
- headerHeight={headerHeight}
454
- headerTopInsetEnabled={headerTopInsetEnabled}
455
- >
456
- <HeaderBackContext.Provider value={headerBack}>
457
- {render()}
458
- </HeaderBackContext.Provider>
459
- </MaybeNestedStack>
460
- {header !== undefined && headerShown !== false ? (
461
- <View
462
- onLayout={(e) => {
463
- const headerHeight = e.nativeEvent.layout.height;
464
-
465
- setHeaderHeight(headerHeight);
466
- rawAnimatedHeaderHeight.setValue(headerHeight);
467
- }}
468
- style={headerTransparent ? styles.absolute : null}
469
- >
470
- {header({
471
- back: headerBack,
472
- options,
473
- route,
474
- navigation,
475
- })}
476
- </View>
477
- ) : null}
427
+ {header({
428
+ back: headerBack,
429
+ options,
430
+ route,
431
+ navigation,
432
+ })}
478
433
  </View>
479
- {/**
480
- * `HeaderConfig` needs to be the direct child of `Screen` without any intermediate `View`
481
- * We don't render it conditionally to make it possible to dynamically render a custom `header`
482
- * Otherwise dynamically rendering a custom `header` leaves the native header visible
483
- *
484
- * https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md#screenstackheaderconfig
485
- *
486
- * HeaderConfig must not be first child of a Screen.
487
- * See https://github.com/software-mansion/react-native-screens/pull/1825
488
- * for detailed explanation
489
- */}
490
- <HeaderConfig
491
- {...options}
492
- route={route}
493
- headerBackButtonMenuEnabled={
494
- isRemovePrevented !== undefined
495
- ? !isRemovePrevented
496
- : headerBackButtonMenuEnabled
497
- }
498
- headerShown={header !== undefined ? false : headerShown}
499
- headerHeight={headerHeight}
500
- headerBackTitle={
501
- options.headerBackTitle !== undefined
502
- ? options.headerBackTitle
503
- : undefined
504
- }
505
- headerTopInsetEnabled={headerTopInsetEnabled}
506
- canGoBack={headerBack !== undefined}
507
- />
508
- </HeaderHeightContext.Provider>
509
- </AnimatedHeaderHeightContext.Provider>
510
- </HeaderShownContext.Provider>
434
+ ) : null}
435
+ <HeaderShownContext.Provider
436
+ value={isParentHeaderShown || headerShown !== false}
437
+ >
438
+ <HeaderBackContext.Provider value={headerBack}>
439
+ {render()}
440
+ </HeaderBackContext.Provider>
441
+ </HeaderShownContext.Provider>
442
+ {presentation === 'formSheet' && unstable_sheetFooter && (
443
+ <FooterComponent>{unstable_sheetFooter()}</FooterComponent>
444
+ )}
445
+ </HeaderHeightContext.Provider>
446
+ </AnimatedHeaderHeightContext.Provider>
511
447
  </NavigationRouteContext.Provider>
512
448
  </NavigationContext.Provider>
513
- </Screen>
449
+ </ScreenStackItem>
514
450
  );
515
451
  };
516
452
 
@@ -518,9 +454,18 @@ type Props = {
518
454
  state: StackNavigationState<ParamListBase>;
519
455
  navigation: NativeStackNavigationHelpers;
520
456
  descriptors: NativeStackDescriptorMap;
457
+ describe: (
458
+ route: RouteProp<ParamListBase>,
459
+ placeholder: boolean
460
+ ) => NativeStackDescriptor;
521
461
  };
522
462
 
523
- export function NativeStackView({ state, navigation, descriptors }: Props) {
463
+ export function NativeStackView({
464
+ state,
465
+ navigation,
466
+ descriptors,
467
+ describe,
468
+ }: Props) {
524
469
  const { setNextDismissedKey } = useDismissedRouteError(state);
525
470
 
526
471
  const { colors } = useTheme();
@@ -529,11 +474,18 @@ export function NativeStackView({ state, navigation, descriptors }: Props) {
529
474
 
530
475
  const modalRouteKeys = getModalRouteKeys(state.routes, descriptors);
531
476
 
477
+ const preloadedDescriptors =
478
+ state.preloadedRoutes.reduce<NativeStackDescriptorMap>((acc, route) => {
479
+ acc[route.key] = acc[route.key] || describe(route, true);
480
+ return acc;
481
+ }, {});
482
+
532
483
  return (
533
484
  <SafeAreaProviderCompat style={{ backgroundColor: colors.background }}>
534
485
  <ScreenStack style={styles.container}>
535
- {state.routes.map((route, index) => {
536
- const descriptor = descriptors[route.key];
486
+ {state.routes.concat(state.preloadedRoutes).map((route, index) => {
487
+ const descriptor =
488
+ descriptors[route.key] ?? preloadedDescriptors[route.key];
537
489
  const isFocused = state.index === index;
538
490
  const previousKey = state.routes[index - 1]?.key;
539
491
  const nextKey = state.routes[index + 1]?.key;
@@ -544,6 +496,10 @@ export function NativeStackView({ state, navigation, descriptors }: Props) {
544
496
 
545
497
  const isModal = modalRouteKeys.includes(route.key);
546
498
 
499
+ const isPreloaded =
500
+ preloadedDescriptors[route.key] !== undefined &&
501
+ descriptors[route.key] === undefined;
502
+
547
503
  return (
548
504
  <SceneView
549
505
  key={route.key}
@@ -553,6 +509,7 @@ export function NativeStackView({ state, navigation, descriptors }: Props) {
553
509
  previousDescriptor={previousDescriptor}
554
510
  nextDescriptor={nextDescriptor}
555
511
  isPresentationModal={isModal}
512
+ isPreloaded={isPreloaded}
556
513
  onWillDisappear={() => {
557
514
  navigation.emit({
558
515
  type: 'transitionStart',
@@ -610,6 +567,16 @@ export function NativeStackView({ state, navigation, descriptors }: Props) {
610
567
  target: route.key,
611
568
  });
612
569
  }}
570
+ onSheetDetentChanged={(event) => {
571
+ navigation.emit({
572
+ type: 'sheetDetentChange',
573
+ target: route.key,
574
+ data: {
575
+ index: event.nativeEvent.index,
576
+ stable: event.nativeEvent.isStable,
577
+ },
578
+ });
579
+ }}
613
580
  />
614
581
  );
615
582
  })}
@@ -622,9 +589,8 @@ const styles = StyleSheet.create({
622
589
  container: {
623
590
  flex: 1,
624
591
  },
625
- scene: {
626
- flex: 1,
627
- flexDirection: 'column-reverse',
592
+ header: {
593
+ zIndex: 1,
628
594
  },
629
595
  absolute: {
630
596
  position: 'absolute',