@react-navigation/native-stack 7.0.0-alpha.1 → 7.0.0-alpha.11

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 (77) hide show
  1. package/lib/commonjs/index.js +7 -0
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/navigators/createNativeStackNavigator.js +24 -24
  4. package/lib/commonjs/navigators/createNativeStackNavigator.js.map +1 -1
  5. package/lib/commonjs/types.js.map +1 -1
  6. package/lib/commonjs/utils/useAnimatedHeaderHeight.js +19 -0
  7. package/lib/commonjs/utils/useAnimatedHeaderHeight.js.map +1 -0
  8. package/lib/commonjs/utils/useDismissedRouteError.js +3 -4
  9. package/lib/commonjs/utils/useDismissedRouteError.js.map +1 -1
  10. package/lib/commonjs/utils/useInvalidPreventRemoveError.js +4 -5
  11. package/lib/commonjs/utils/useInvalidPreventRemoveError.js.map +1 -1
  12. package/lib/commonjs/views/DebugContainer.js +2 -2
  13. package/lib/commonjs/views/DebugContainer.js.map +1 -1
  14. package/lib/commonjs/views/DebugContainer.native.js +19 -7
  15. package/lib/commonjs/views/DebugContainer.native.js.map +1 -1
  16. package/lib/commonjs/views/FontProcessor.js.map +1 -1
  17. package/lib/commonjs/views/FontProcessor.native.js +2 -4
  18. package/lib/commonjs/views/FontProcessor.native.js.map +1 -1
  19. package/lib/commonjs/views/HeaderConfig.js +10 -23
  20. package/lib/commonjs/views/HeaderConfig.js.map +1 -1
  21. package/lib/commonjs/views/NativeStackView.js +25 -16
  22. package/lib/commonjs/views/NativeStackView.js.map +1 -1
  23. package/lib/commonjs/views/NativeStackView.native.js +124 -47
  24. package/lib/commonjs/views/NativeStackView.native.js.map +1 -1
  25. package/lib/module/index.js +5 -0
  26. package/lib/module/index.js.map +1 -1
  27. package/lib/module/navigators/createNativeStackNavigator.js +21 -20
  28. package/lib/module/navigators/createNativeStackNavigator.js.map +1 -1
  29. package/lib/module/types.js.map +1 -1
  30. package/lib/module/utils/useAnimatedHeaderHeight.js +10 -0
  31. package/lib/module/utils/useAnimatedHeaderHeight.js.map +1 -0
  32. package/lib/module/utils/useDismissedRouteError.js +1 -2
  33. package/lib/module/utils/useDismissedRouteError.js.map +1 -1
  34. package/lib/module/utils/useInvalidPreventRemoveError.js +2 -3
  35. package/lib/module/utils/useInvalidPreventRemoveError.js.map +1 -1
  36. package/lib/module/views/DebugContainer.js.map +1 -1
  37. package/lib/module/views/DebugContainer.native.js +18 -4
  38. package/lib/module/views/DebugContainer.native.js.map +1 -1
  39. package/lib/module/views/FontProcessor.js.map +1 -1
  40. package/lib/module/views/FontProcessor.native.js +2 -4
  41. package/lib/module/views/FontProcessor.native.js.map +1 -1
  42. package/lib/module/views/HeaderConfig.js +10 -23
  43. package/lib/module/views/HeaderConfig.js.map +1 -1
  44. package/lib/module/views/NativeStackView.js +23 -14
  45. package/lib/module/views/NativeStackView.js.map +1 -1
  46. package/lib/module/views/NativeStackView.native.js +123 -46
  47. package/lib/module/views/NativeStackView.native.js.map +1 -1
  48. package/lib/typescript/src/index.d.ts +4 -0
  49. package/lib/typescript/src/index.d.ts.map +1 -1
  50. package/lib/typescript/src/navigators/createNativeStackNavigator.d.ts +4 -4
  51. package/lib/typescript/src/navigators/createNativeStackNavigator.d.ts.map +1 -1
  52. package/lib/typescript/src/types.d.ts +88 -10
  53. package/lib/typescript/src/types.d.ts.map +1 -1
  54. package/lib/typescript/src/utils/useAnimatedHeaderHeight.d.ts +5 -0
  55. package/lib/typescript/src/utils/useAnimatedHeaderHeight.d.ts.map +1 -0
  56. package/lib/typescript/src/views/DebugContainer.d.ts +2 -2
  57. package/lib/typescript/src/views/DebugContainer.d.ts.map +1 -1
  58. package/lib/typescript/src/views/DebugContainer.native.d.ts +7 -2
  59. package/lib/typescript/src/views/DebugContainer.native.d.ts.map +1 -1
  60. package/lib/typescript/src/views/FontProcessor.native.d.ts.map +1 -1
  61. package/lib/typescript/src/views/HeaderConfig.d.ts +2 -3
  62. package/lib/typescript/src/views/HeaderConfig.d.ts.map +1 -1
  63. package/lib/typescript/src/views/NativeStackView.d.ts +3 -3
  64. package/lib/typescript/src/views/NativeStackView.d.ts.map +1 -1
  65. package/lib/typescript/src/views/NativeStackView.native.d.ts +3 -3
  66. package/lib/typescript/src/views/NativeStackView.native.d.ts.map +1 -1
  67. package/package.json +16 -17
  68. package/src/index.tsx +5 -0
  69. package/src/navigators/createNativeStackNavigator.tsx +9 -5
  70. package/src/types.tsx +88 -11
  71. package/src/utils/useAnimatedHeaderHeight.tsx +18 -0
  72. package/src/views/DebugContainer.native.tsx +12 -6
  73. package/src/views/DebugContainer.tsx +1 -1
  74. package/src/views/FontProcessor.native.tsx +1 -2
  75. package/src/views/HeaderConfig.tsx +101 -131
  76. package/src/views/NativeStackView.native.tsx +264 -166
  77. package/src/views/NativeStackView.tsx +131 -123
@@ -9,24 +9,30 @@ import {
9
9
  import {
10
10
  NavigationContext,
11
11
  NavigationRouteContext,
12
- ParamListBase,
13
- Route,
12
+ type ParamListBase,
13
+ type Route,
14
14
  StackActions,
15
- StackNavigationState,
15
+ type StackNavigationState,
16
16
  usePreventRemoveContext,
17
17
  useTheme,
18
18
  } from '@react-navigation/native';
19
19
  import * as React from 'react';
20
- import { Platform, StyleSheet, View } from 'react-native';
20
+ import {
21
+ Animated,
22
+ Platform,
23
+ StyleSheet,
24
+ useAnimatedValue,
25
+ View,
26
+ } from 'react-native';
21
27
  import {
22
28
  useSafeAreaFrame,
23
29
  useSafeAreaInsets,
24
30
  } from 'react-native-safe-area-context';
25
- import type { ScreenProps } from 'react-native-screens';
26
31
  import {
27
32
  Screen,
33
+ type ScreenProps,
28
34
  ScreenStack,
29
- StackPresentationTypes,
35
+ type StackPresentationTypes,
30
36
  } from 'react-native-screens';
31
37
  import warnOnce from 'warn-once';
32
38
 
@@ -36,6 +42,7 @@ import type {
36
42
  NativeStackNavigationHelpers,
37
43
  NativeStackNavigationOptions,
38
44
  } from '../types';
45
+ import { AnimatedHeaderHeightContext } from '../utils/useAnimatedHeaderHeight';
39
46
  import { useDismissedRouteError } from '../utils/useDismissedRouteError';
40
47
  import { useInvalidPreventRemoveError } from '../utils/useInvalidPreventRemoveError';
41
48
  import { DebugContainer } from './DebugContainer';
@@ -97,7 +104,13 @@ const MaybeNestedStack = ({
97
104
  if (isHeaderInModal) {
98
105
  return (
99
106
  <ScreenStack style={styles.container}>
100
- <Screen enabled style={StyleSheet.absoluteFill}>
107
+ <Screen
108
+ enabled
109
+ isNativeStack
110
+ hasLargeHeader={options.headerLargeTitle ?? false}
111
+ style={StyleSheet.absoluteFill}
112
+ >
113
+ {content}
101
114
  <HeaderConfig
102
115
  {...options}
103
116
  route={route}
@@ -105,7 +118,6 @@ const MaybeNestedStack = ({
105
118
  headerTopInsetEnabled={headerTopInsetEnabled}
106
119
  canGoBack
107
120
  />
108
- {content}
109
121
  </Screen>
110
122
  </ScreenStack>
111
123
  );
@@ -121,11 +133,13 @@ type SceneViewProps = {
121
133
  previousDescriptor?: NativeStackDescriptor;
122
134
  nextDescriptor?: NativeStackDescriptor;
123
135
  onWillDisappear: () => void;
136
+ onWillAppear: () => void;
124
137
  onAppear: () => void;
125
138
  onDisappear: () => void;
126
139
  onDismissed: ScreenProps['onDismissed'];
127
140
  onHeaderBackButtonClicked: ScreenProps['onHeaderBackButtonClicked'];
128
141
  onNativeDismissCancelled: ScreenProps['onDismissed'];
142
+ onGestureCancel: ScreenProps['onGestureCancel'];
129
143
  };
130
144
 
131
145
  const SceneView = ({
@@ -135,53 +149,66 @@ const SceneView = ({
135
149
  previousDescriptor,
136
150
  nextDescriptor,
137
151
  onWillDisappear,
152
+ onWillAppear,
138
153
  onAppear,
139
154
  onDisappear,
140
155
  onDismissed,
141
156
  onHeaderBackButtonClicked,
142
157
  onNativeDismissCancelled,
158
+ onGestureCancel,
143
159
  }: SceneViewProps) => {
144
160
  const { route, navigation, options, render } = descriptor;
161
+
162
+ let {
163
+ animation,
164
+ animationMatchesGesture,
165
+ fullScreenGestureEnabled,
166
+ presentation = 'card',
167
+ } = options;
168
+
145
169
  const {
146
170
  animationDuration,
147
171
  animationTypeForReplace = 'push',
148
172
  gestureEnabled,
173
+ gestureDirection = presentation === 'card' ? 'horizontal' : 'vertical',
174
+ gestureResponseDistance,
149
175
  header,
150
176
  headerBackButtonMenuEnabled,
151
177
  headerShown,
178
+ headerBackground,
152
179
  headerTransparent,
153
180
  autoHideHomeIndicator,
181
+ keyboardHandlingEnabled,
154
182
  navigationBarColor,
155
183
  navigationBarHidden,
156
184
  orientation,
185
+ sheetAllowedDetents = 'large',
186
+ sheetLargestUndimmedDetent = 'all',
187
+ sheetGrabberVisible = false,
188
+ sheetCornerRadius = -1.0,
189
+ sheetExpandsWhenScrolledToEdge = true,
157
190
  statusBarAnimation,
158
191
  statusBarHidden,
159
192
  statusBarStyle,
160
193
  statusBarTranslucent,
161
- statusBarColor,
194
+ statusBarBackgroundColor,
162
195
  freezeOnBlur,
163
196
  } = options;
164
197
 
165
- let {
166
- animation,
167
- customAnimationOnGesture,
168
- fullScreenGestureEnabled,
169
- presentation = 'card',
170
- gestureDirection = presentation === 'card' ? 'horizontal' : 'vertical',
171
- } = options;
172
-
173
198
  if (gestureDirection === 'vertical' && Platform.OS === 'ios') {
174
199
  // for `vertical` direction to work, we need to set `fullScreenGestureEnabled` to `true`
175
200
  // so the screen can be dismissed from any point on screen.
176
- // `customAnimationOnGesture` needs to be set to `true` so the `animation` set by user can be used,
201
+ // `animationMatchesGesture` needs to be set to `true` so the `animation` set by user can be used,
177
202
  // otherwise `simple_push` will be used.
178
203
  // Also, the default animation for this direction seems to be `slide_from_bottom`.
179
204
  if (fullScreenGestureEnabled === undefined) {
180
205
  fullScreenGestureEnabled = true;
181
206
  }
182
- if (customAnimationOnGesture === undefined) {
183
- customAnimationOnGesture = true;
207
+
208
+ if (animationMatchesGesture === undefined) {
209
+ animationMatchesGesture = true;
184
210
  }
211
+
185
212
  if (animation === undefined) {
186
213
  animation = 'slide_from_bottom';
187
214
  }
@@ -227,16 +254,23 @@ const SceneView = ({
227
254
  const [customHeaderHeight, setCustomHeaderHeight] =
228
255
  React.useState(defaultHeaderHeight);
229
256
 
257
+ const animatedHeaderHeight = useAnimatedValue(defaultHeaderHeight);
258
+
230
259
  const headerTopInsetEnabled = topInset !== 0;
231
260
  const headerHeight = header ? customHeaderHeight : defaultHeaderHeight;
232
- const headerBack = previousDescriptor
233
- ? {
234
- title: getHeaderTitle(
235
- previousDescriptor.options,
236
- previousDescriptor.route.name
237
- ),
238
- }
239
- : parentHeaderBack;
261
+
262
+ const backTitle = previousDescriptor
263
+ ? getHeaderTitle(previousDescriptor.options, previousDescriptor.route.name)
264
+ : parentHeaderBack?.title;
265
+
266
+ const headerBack = React.useMemo(
267
+ () => ({
268
+ // No href needed for native
269
+ href: undefined,
270
+ title: backTitle,
271
+ }),
272
+ [backTitle]
273
+ );
240
274
 
241
275
  const isRemovePrevented = preventedRoutes[route.key]?.preventRemove;
242
276
 
@@ -244,8 +278,10 @@ const SceneView = ({
244
278
  <Screen
245
279
  key={route.key}
246
280
  enabled
281
+ isNativeStack
247
282
  style={StyleSheet.absoluteFill}
248
- customAnimationOnSwipe={customAnimationOnGesture}
283
+ hasLargeHeader={options.headerLargeTitle ?? false}
284
+ customAnimationOnSwipe={animationMatchesGesture}
249
285
  fullScreenSwipeEnabled={fullScreenGestureEnabled}
250
286
  gestureEnabled={
251
287
  isAndroid
@@ -255,29 +291,50 @@ const SceneView = ({
255
291
  : gestureEnabled
256
292
  }
257
293
  homeIndicatorHidden={autoHideHomeIndicator}
294
+ hideKeyboardOnSwipe={keyboardHandlingEnabled}
258
295
  navigationBarColor={navigationBarColor}
259
296
  navigationBarHidden={navigationBarHidden}
260
297
  replaceAnimation={animationTypeForReplace}
261
298
  stackPresentation={presentation === 'card' ? 'push' : presentation}
262
299
  stackAnimation={animation}
263
300
  screenOrientation={orientation}
301
+ sheetAllowedDetents={sheetAllowedDetents}
302
+ sheetLargestUndimmedDetent={sheetLargestUndimmedDetent}
303
+ sheetGrabberVisible={sheetGrabberVisible}
304
+ sheetCornerRadius={sheetCornerRadius}
305
+ sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
264
306
  statusBarAnimation={statusBarAnimation}
265
307
  statusBarHidden={statusBarHidden}
266
308
  statusBarStyle={statusBarStyle}
267
- statusBarColor={statusBarColor}
309
+ statusBarColor={statusBarBackgroundColor}
268
310
  statusBarTranslucent={statusBarTranslucent}
269
311
  swipeDirection={gestureDirectionOverride}
270
312
  transitionDuration={animationDuration}
313
+ onWillAppear={onWillAppear}
271
314
  onWillDisappear={onWillDisappear}
272
315
  onAppear={onAppear}
273
316
  onDisappear={onDisappear}
274
317
  onDismissed={onDismissed}
275
- isNativeStack
318
+ onGestureCancel={onGestureCancel}
319
+ gestureResponseDistance={gestureResponseDistance}
276
320
  nativeBackButtonDismissalEnabled={false} // on Android
277
321
  onHeaderBackButtonClicked={onHeaderBackButtonClicked}
278
- // @ts-ignore props not exported from rn-screens
279
322
  preventNativeDismiss={isRemovePrevented} // on iOS
280
323
  onNativeDismissCancelled={onNativeDismissCancelled}
324
+ // Unfortunately, because of the bug that exists on Fabric, where native event drivers
325
+ // for Animated objects are being created after the first notifications about the header height
326
+ // from the native side, `onHeaderHeightChange` event does not notify
327
+ // `animatedHeaderHeight` about initial values on appearing screens at the moment.
328
+ onHeaderHeightChange={Animated.event(
329
+ [
330
+ {
331
+ nativeEvent: {
332
+ headerHeight: animatedHeaderHeight,
333
+ },
334
+ },
335
+ ],
336
+ { useNativeDriver: true }
337
+ )}
281
338
  // this prop is available since rn-screens 3.16
282
339
  freezeOnBlur={freezeOnBlur}
283
340
  >
@@ -286,71 +343,92 @@ const SceneView = ({
286
343
  <HeaderShownContext.Provider
287
344
  value={isParentHeaderShown || headerShown !== false}
288
345
  >
289
- <HeaderHeightContext.Provider
290
- value={
291
- headerShown !== false ? headerHeight : parentHeaderHeight ?? 0
292
- }
293
- >
294
- {/**
295
- * `HeaderConfig` needs to be the direct child of `Screen` without any intermediate `View`
296
- * We don't render it conditionally to make it possible to dynamically render a custom `header`
297
- * Otherwise dynamically rendering a custom `header` leaves the native header visible
298
- *
299
- * https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md#screenstackheaderconfig
300
- */}
301
- <HeaderConfig
302
- {...options}
303
- route={route}
304
- headerBackButtonMenuEnabled={
305
- isRemovePrevented !== undefined
306
- ? !isRemovePrevented
307
- : headerBackButtonMenuEnabled
346
+ <AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
347
+ <HeaderHeightContext.Provider
348
+ value={
349
+ headerShown !== false ? headerHeight : parentHeaderHeight ?? 0
308
350
  }
309
- headerShown={header !== undefined ? false : headerShown}
310
- headerHeight={headerHeight}
311
- headerBackTitle={
312
- options.headerBackTitle !== undefined
313
- ? options.headerBackTitle
314
- : undefined
315
- }
316
- headerTopInsetEnabled={headerTopInsetEnabled}
317
- canGoBack={headerBack !== undefined}
318
- />
319
- <View
320
- accessibilityElementsHidden={!focused}
321
- importantForAccessibility={
322
- focused ? 'auto' : 'no-hide-descendants'
323
- }
324
- style={styles.scene}
325
351
  >
326
- <MaybeNestedStack
327
- options={options}
328
- route={route}
329
- presentation={presentation}
330
- headerHeight={headerHeight}
331
- headerTopInsetEnabled={headerTopInsetEnabled}
332
- >
333
- <HeaderBackContext.Provider value={headerBack}>
334
- {render()}
335
- </HeaderBackContext.Provider>
336
- </MaybeNestedStack>
337
- {header !== undefined && headerShown !== false ? (
352
+ {headerBackground != null ? (
353
+ /**
354
+ * To show a custom header background, we render it at the top of the screen below the header
355
+ * The header also needs to be positioned absolutely (with `translucent` style)
356
+ */
338
357
  <View
339
- onLayout={(e) => {
340
- setCustomHeaderHeight(e.nativeEvent.layout.height);
341
- }}
342
- style={headerTransparent ? styles.absolute : null}
358
+ style={[
359
+ styles.background,
360
+ headerTransparent ? styles.translucent : null,
361
+ { height: headerHeight },
362
+ ]}
343
363
  >
344
- {header({
345
- back: headerBack,
346
- options,
347
- route,
348
- navigation,
349
- })}
364
+ {headerBackground()}
350
365
  </View>
351
366
  ) : null}
352
- </View>
353
- </HeaderHeightContext.Provider>
367
+ <View
368
+ accessibilityElementsHidden={!focused}
369
+ importantForAccessibility={
370
+ focused ? 'auto' : 'no-hide-descendants'
371
+ }
372
+ style={styles.scene}
373
+ >
374
+ <MaybeNestedStack
375
+ options={options}
376
+ route={route}
377
+ presentation={presentation}
378
+ headerHeight={headerHeight}
379
+ headerTopInsetEnabled={headerTopInsetEnabled}
380
+ >
381
+ <HeaderBackContext.Provider value={headerBack}>
382
+ {render()}
383
+ </HeaderBackContext.Provider>
384
+ </MaybeNestedStack>
385
+ {header !== undefined && headerShown !== false ? (
386
+ <View
387
+ onLayout={(e) => {
388
+ setCustomHeaderHeight(e.nativeEvent.layout.height);
389
+ }}
390
+ style={headerTransparent ? styles.absolute : null}
391
+ >
392
+ {header({
393
+ back: headerBack,
394
+ options,
395
+ route,
396
+ navigation,
397
+ })}
398
+ </View>
399
+ ) : null}
400
+ </View>
401
+ {/**
402
+ * `HeaderConfig` needs to be the direct child of `Screen` without any intermediate `View`
403
+ * We don't render it conditionally to make it possible to dynamically render a custom `header`
404
+ * Otherwise dynamically rendering a custom `header` leaves the native header visible
405
+ *
406
+ * https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md#screenstackheaderconfig
407
+ *
408
+ * HeaderConfig must not be first child of a Screen.
409
+ * See https://github.com/software-mansion/react-native-screens/pull/1825
410
+ * for detailed explanation
411
+ */}
412
+ <HeaderConfig
413
+ {...options}
414
+ route={route}
415
+ headerBackButtonMenuEnabled={
416
+ isRemovePrevented !== undefined
417
+ ? !isRemovePrevented
418
+ : headerBackButtonMenuEnabled
419
+ }
420
+ headerShown={header !== undefined ? false : headerShown}
421
+ headerHeight={headerHeight}
422
+ headerBackTitle={
423
+ options.headerBackTitle !== undefined
424
+ ? options.headerBackTitle
425
+ : undefined
426
+ }
427
+ headerTopInsetEnabled={headerTopInsetEnabled}
428
+ canGoBack={headerBack !== undefined}
429
+ />
430
+ </HeaderHeightContext.Provider>
431
+ </AnimatedHeaderHeightContext.Provider>
354
432
  </HeaderShownContext.Provider>
355
433
  </NavigationRouteContext.Provider>
356
434
  </NavigationContext.Provider>
@@ -364,86 +442,95 @@ type Props = {
364
442
  descriptors: NativeStackDescriptorMap;
365
443
  };
366
444
 
367
- function NativeStackViewInner({ state, navigation, descriptors }: Props) {
445
+ export function NativeStackView({ state, navigation, descriptors }: Props) {
368
446
  const { setNextDismissedKey } = useDismissedRouteError(state);
369
447
 
370
- useInvalidPreventRemoveError(descriptors);
448
+ const { colors } = useTheme();
371
449
 
372
- return (
373
- <ScreenStack style={styles.container}>
374
- {state.routes.map((route, index) => {
375
- const descriptor = descriptors[route.key];
376
- const isFocused = state.index === index;
377
- const previousKey = state.routes[index - 1]?.key;
378
- const nextKey = state.routes[index + 1]?.key;
379
- const previousDescriptor = previousKey
380
- ? descriptors[previousKey]
381
- : undefined;
382
- const nextDescriptor = nextKey ? descriptors[nextKey] : undefined;
383
-
384
- return (
385
- <SceneView
386
- key={route.key}
387
- index={index}
388
- focused={isFocused}
389
- descriptor={descriptor}
390
- previousDescriptor={previousDescriptor}
391
- nextDescriptor={nextDescriptor}
392
- onWillDisappear={() => {
393
- navigation.emit({
394
- type: 'transitionStart',
395
- data: { closing: true },
396
- target: route.key,
397
- });
398
- }}
399
- onAppear={() => {
400
- navigation.emit({
401
- type: 'transitionEnd',
402
- data: { closing: false },
403
- target: route.key,
404
- });
405
- }}
406
- onDisappear={() => {
407
- navigation.emit({
408
- type: 'transitionEnd',
409
- data: { closing: true },
410
- target: route.key,
411
- });
412
- }}
413
- onDismissed={(event) => {
414
- navigation.dispatch({
415
- ...StackActions.pop(event.nativeEvent.dismissCount),
416
- source: route.key,
417
- target: state.key,
418
- });
419
-
420
- setNextDismissedKey(route.key);
421
- }}
422
- onHeaderBackButtonClicked={() => {
423
- navigation.dispatch({
424
- ...StackActions.pop(),
425
- source: route.key,
426
- target: state.key,
427
- });
428
- }}
429
- onNativeDismissCancelled={(event) => {
430
- navigation.dispatch({
431
- ...StackActions.pop(event.nativeEvent.dismissCount),
432
- source: route.key,
433
- target: state.key,
434
- });
435
- }}
436
- />
437
- );
438
- })}
439
- </ScreenStack>
440
- );
441
- }
450
+ useInvalidPreventRemoveError(descriptors);
442
451
 
443
- export function NativeStackView(props: Props) {
444
452
  return (
445
- <SafeAreaProviderCompat>
446
- <NativeStackViewInner {...props} />
453
+ <SafeAreaProviderCompat style={{ backgroundColor: colors.background }}>
454
+ <ScreenStack style={styles.container}>
455
+ {state.routes.map((route, index) => {
456
+ const descriptor = descriptors[route.key];
457
+ const isFocused = state.index === index;
458
+ const previousKey = state.routes[index - 1]?.key;
459
+ const nextKey = state.routes[index + 1]?.key;
460
+ const previousDescriptor = previousKey
461
+ ? descriptors[previousKey]
462
+ : undefined;
463
+ const nextDescriptor = nextKey ? descriptors[nextKey] : undefined;
464
+
465
+ return (
466
+ <SceneView
467
+ key={route.key}
468
+ index={index}
469
+ focused={isFocused}
470
+ descriptor={descriptor}
471
+ previousDescriptor={previousDescriptor}
472
+ nextDescriptor={nextDescriptor}
473
+ onWillDisappear={() => {
474
+ navigation.emit({
475
+ type: 'transitionStart',
476
+ data: { closing: true },
477
+ target: route.key,
478
+ });
479
+ }}
480
+ onWillAppear={() => {
481
+ navigation.emit({
482
+ type: 'transitionStart',
483
+ data: { closing: false },
484
+ target: route.key,
485
+ });
486
+ }}
487
+ onAppear={() => {
488
+ navigation.emit({
489
+ type: 'transitionEnd',
490
+ data: { closing: false },
491
+ target: route.key,
492
+ });
493
+ }}
494
+ onDisappear={() => {
495
+ navigation.emit({
496
+ type: 'transitionEnd',
497
+ data: { closing: true },
498
+ target: route.key,
499
+ });
500
+ }}
501
+ onDismissed={(event) => {
502
+ navigation.dispatch({
503
+ ...StackActions.pop(event.nativeEvent.dismissCount),
504
+ source: route.key,
505
+ target: state.key,
506
+ });
507
+
508
+ setNextDismissedKey(route.key);
509
+ }}
510
+ onHeaderBackButtonClicked={() => {
511
+ navigation.dispatch({
512
+ ...StackActions.pop(),
513
+ source: route.key,
514
+ target: state.key,
515
+ });
516
+ }}
517
+ onNativeDismissCancelled={(event) => {
518
+ navigation.dispatch({
519
+ ...StackActions.pop(event.nativeEvent.dismissCount),
520
+ source: route.key,
521
+ target: state.key,
522
+ });
523
+ }}
524
+ onGestureCancel={() => {
525
+ navigation.emit({
526
+ type: 'gestureCancel',
527
+ target: route.key,
528
+ });
529
+ }}
530
+ />
531
+ );
532
+ })}
533
+ </ScreenStack>
447
534
  </SafeAreaProviderCompat>
448
535
  );
449
536
  }
@@ -462,4 +549,15 @@ const styles = StyleSheet.create({
462
549
  left: 0,
463
550
  right: 0,
464
551
  },
552
+ translucent: {
553
+ position: 'absolute',
554
+ top: 0,
555
+ left: 0,
556
+ right: 0,
557
+ zIndex: 1,
558
+ elevation: 1,
559
+ },
560
+ background: {
561
+ overflow: 'hidden',
562
+ },
465
563
  });