react-native-screens 3.25.0 → 3.27.0

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 (138) hide show
  1. package/README.md +1 -1
  2. package/RNScreens.podspec +53 -32
  3. package/android/build.gradle +13 -11
  4. package/android/src/main/java/com/swmansion/rnscreens/FragmentHolder.kt +7 -0
  5. package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +41 -10
  6. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +35 -36
  7. package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +7 -7
  8. package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +21 -0
  9. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +46 -38
  10. package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +22 -0
  11. package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +40 -39
  12. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +35 -10
  13. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +15 -0
  14. package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +7 -5
  15. package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +11 -18
  16. package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +1 -1
  17. package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +1 -1
  18. package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +23 -7
  19. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +3 -5
  20. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +3 -5
  21. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +3 -5
  22. package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +26 -0
  23. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +3 -5
  24. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +3 -5
  25. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +4 -7
  26. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +7 -8
  27. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +3 -5
  28. package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +3 -5
  29. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +3 -5
  30. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +5 -6
  31. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +3 -5
  32. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +3 -5
  33. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +3 -5
  34. package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +4 -6
  35. package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +3 -5
  36. package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +12 -0
  37. package/ios/RNSScreen.h +5 -0
  38. package/ios/RNSScreen.mm +163 -7
  39. package/ios/RNSScreenStack.mm +18 -0
  40. package/ios/RNSScreenStackHeaderConfig.mm +17 -0
  41. package/ios/events/RNSHeaderHeightChangeEvent.h +8 -0
  42. package/ios/events/RNSHeaderHeightChangeEvent.mm +59 -0
  43. package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
  44. package/lib/commonjs/index.native.js +11 -11
  45. package/lib/commonjs/index.native.js.map +1 -1
  46. package/lib/commonjs/native-stack/index.js +14 -0
  47. package/lib/commonjs/native-stack/index.js.map +1 -1
  48. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js +1 -1
  49. package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  50. package/lib/commonjs/native-stack/types.js.map +1 -1
  51. package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js +13 -0
  52. package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
  53. package/lib/commonjs/native-stack/utils/SafeAreaProviderCompat.js.map +1 -1
  54. package/lib/commonjs/native-stack/utils/getStatusBarHeight.js +22 -0
  55. package/lib/commonjs/native-stack/utils/getStatusBarHeight.js.map +1 -0
  56. package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js +19 -0
  57. package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
  58. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js +2 -2
  59. package/lib/commonjs/native-stack/utils/useBackPressSubscription.js.map +1 -1
  60. package/lib/commonjs/native-stack/views/HeaderConfig.js +2 -2
  61. package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
  62. package/lib/commonjs/native-stack/views/NativeStackView.js +39 -21
  63. package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
  64. package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js +13 -0
  65. package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
  66. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +37 -6
  67. package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  68. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +2 -2
  69. package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -1
  70. package/lib/commonjs/reanimated/index.js +7 -0
  71. package/lib/commonjs/reanimated/index.js.map +1 -1
  72. package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js +19 -0
  73. package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js.map +1 -0
  74. package/lib/commonjs/types.js.map +1 -1
  75. package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
  76. package/lib/module/index.native.js +12 -12
  77. package/lib/module/index.native.js.map +1 -1
  78. package/lib/module/native-stack/index.js +2 -0
  79. package/lib/module/native-stack/index.js.map +1 -1
  80. package/lib/module/native-stack/navigators/createNativeStackNavigator.js +1 -1
  81. package/lib/module/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
  82. package/lib/module/native-stack/types.js.map +1 -1
  83. package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js +4 -0
  84. package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
  85. package/lib/module/native-stack/utils/SafeAreaProviderCompat.js.map +1 -1
  86. package/lib/module/native-stack/utils/getStatusBarHeight.js +16 -0
  87. package/lib/module/native-stack/utils/getStatusBarHeight.js.map +1 -0
  88. package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js +10 -0
  89. package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
  90. package/lib/module/native-stack/utils/useBackPressSubscription.js +2 -2
  91. package/lib/module/native-stack/utils/useBackPressSubscription.js.map +1 -1
  92. package/lib/module/native-stack/views/HeaderConfig.js +2 -2
  93. package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
  94. package/lib/module/native-stack/views/NativeStackView.js +40 -22
  95. package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
  96. package/lib/module/reanimated/ReanimatedHeaderHeightContext.js +5 -0
  97. package/lib/module/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
  98. package/lib/module/reanimated/ReanimatedNativeStackScreen.js +37 -6
  99. package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
  100. package/lib/module/reanimated/ReanimatedScreenProvider.js +2 -2
  101. package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -1
  102. package/lib/module/reanimated/index.js +1 -0
  103. package/lib/module/reanimated/index.js.map +1 -1
  104. package/lib/module/reanimated/useReanimatedHeaderHeight.js +10 -0
  105. package/lib/module/reanimated/useReanimatedHeaderHeight.js.map +1 -0
  106. package/lib/module/types.js.map +1 -1
  107. package/lib/typescript/fabric/ScreenNativeComponent.d.ts +4 -0
  108. package/lib/typescript/native-stack/index.d.ts +2 -0
  109. package/lib/typescript/native-stack/types.d.ts +8 -0
  110. package/lib/typescript/native-stack/utils/AnimatedHeaderHeightContext.d.ts +4 -0
  111. package/lib/typescript/native-stack/utils/getStatusBarHeight.d.ts +2 -0
  112. package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -0
  113. package/lib/typescript/reanimated/ReanimatedHeaderHeightContext.d.ts +4 -0
  114. package/lib/typescript/reanimated/index.d.ts +1 -0
  115. package/lib/typescript/reanimated/useReanimatedHeaderHeight.d.ts +3 -0
  116. package/lib/typescript/types.d.ts +11 -0
  117. package/native-stack/README.md +16 -1
  118. package/package.json +36 -38
  119. package/src/fabric/ScreenNativeComponent.ts +5 -0
  120. package/src/index.native.tsx +17 -19
  121. package/src/native-stack/index.tsx +3 -0
  122. package/src/native-stack/types.tsx +10 -1
  123. package/src/native-stack/utils/AnimatedHeaderHeightContext.tsx +8 -0
  124. package/src/native-stack/utils/SafeAreaProviderCompat.tsx +1 -1
  125. package/src/native-stack/utils/getStatusBarHeight.tsx +22 -0
  126. package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +15 -0
  127. package/src/native-stack/views/HeaderConfig.tsx +1 -2
  128. package/src/native-stack/views/NativeStackView.tsx +78 -44
  129. package/src/reanimated/ReanimatedHeaderHeightContext.tsx +7 -0
  130. package/src/reanimated/ReanimatedNativeStackScreen.tsx +58 -11
  131. package/src/reanimated/index.tsx +1 -0
  132. package/src/reanimated/useReanimatedHeaderHeight.tsx +14 -0
  133. package/src/types.tsx +14 -0
  134. package/windows/RNScreens/RNScreens.vcxproj +6 -3
  135. package/windows/RNScreens/ScreenStack.cpp +16 -0
  136. package/windows/RNScreens/ScreenStack.h +1 -0
  137. /package/ios/{RNSScreenViewEvent.h → events/RNSScreenViewEvent.h} +0 -0
  138. /package/ios/{RNSScreenViewEvent.mm → events/RNSScreenViewEvent.mm} +0 -0
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { Platform, StyleSheet, View, ViewProps } from 'react-native';
2
+ import { Animated, Platform, StyleSheet, View, ViewProps } from 'react-native';
3
3
  // @ts-ignore Getting private component
4
4
  // eslint-disable-next-line import/no-named-as-default, import/default, import/no-named-as-default-member, import/namespace
5
5
  import AppContainer from 'react-native/Libraries/ReactNative/AppContainer';
@@ -22,7 +22,6 @@ import {
22
22
  useSafeAreaFrame,
23
23
  useSafeAreaInsets,
24
24
  } from 'react-native-safe-area-context';
25
-
26
25
  import {
27
26
  NativeStackDescriptorMap,
28
27
  NativeStackNavigationHelpers,
@@ -31,7 +30,9 @@ import {
31
30
  import HeaderConfig from './HeaderConfig';
32
31
  import SafeAreaProviderCompat from '../utils/SafeAreaProviderCompat';
33
32
  import getDefaultHeaderHeight from '../utils/getDefaultHeaderHeight';
33
+ import getStatusBarHeight from '../utils/getStatusBarHeight';
34
34
  import HeaderHeightContext from '../utils/HeaderHeightContext';
35
+ import AnimatedHeaderHeightContext from '../utils/AnimatedHeaderHeightContext';
35
36
 
36
37
  const isAndroid = Platform.OS === 'android';
37
38
 
@@ -103,32 +104,37 @@ const MaybeNestedStack = ({
103
104
  // This view must *not* be flattened.
104
105
  // See https://github.com/software-mansion/react-native-screens/pull/1825
105
106
  // for detailed explanation.
106
- collapsable={false}
107
- >
107
+ collapsable={false}>
108
108
  {children}
109
109
  </Container>
110
110
  );
111
111
 
112
112
  const dimensions = useSafeAreaFrame();
113
113
  const topInset = useSafeAreaInsets().top;
114
- let statusBarHeight = topInset;
115
- const hasDynamicIsland = Platform.OS === 'ios' && topInset === 59;
116
- const isLargeHeader = options.headerLargeTitle ?? false;
117
- if (hasDynamicIsland) {
118
- // On models with Dynamic Island the status bar height is smaller than the safe area top inset.
119
- statusBarHeight = 54;
120
- }
114
+ const isStatusBarTranslucent = options.statusBarTranslucent ?? false;
115
+ const statusBarHeight = getStatusBarHeight(
116
+ topInset,
117
+ dimensions,
118
+ isStatusBarTranslucent
119
+ );
120
+
121
+ const hasLargeHeader = options.headerLargeTitle ?? false;
122
+
121
123
  const headerHeight = getDefaultHeaderHeight(
122
124
  dimensions,
123
125
  statusBarHeight,
124
126
  stackPresentation,
125
- isLargeHeader
127
+ hasLargeHeader
126
128
  );
127
129
 
128
130
  if (isHeaderInModal) {
129
131
  return (
130
132
  <ScreenStack style={styles.container}>
131
- <Screen enabled isNativeStack style={StyleSheet.absoluteFill}>
133
+ <Screen
134
+ enabled
135
+ isNativeStack
136
+ hasLargeHeader={hasLargeHeader}
137
+ style={StyleSheet.absoluteFill}>
132
138
  <HeaderHeightContext.Provider value={headerHeight}>
133
139
  <HeaderConfig {...options} route={route} />
134
140
  {content}
@@ -217,27 +223,42 @@ const RouteView = ({
217
223
  stackPresentation = 'push';
218
224
  }
219
225
 
220
- const isHeaderInPush = isAndroid
221
- ? headerShown
222
- : stackPresentation === 'push' && headerShown !== false;
223
-
224
226
  const dimensions = useSafeAreaFrame();
225
227
  const topInset = useSafeAreaInsets().top;
226
- let statusBarHeight = topInset;
227
- const hasDynamicIsland = Platform.OS === 'ios' && topInset === 59;
228
- const isLargeHeader = options.headerLargeTitle ?? false;
228
+ const isStatusBarTranslucent = options.statusBarTranslucent ?? false;
229
+ const statusBarHeight = getStatusBarHeight(
230
+ topInset,
231
+ dimensions,
232
+ isStatusBarTranslucent
233
+ );
229
234
 
230
- if (hasDynamicIsland) {
231
- // On models with Dynamic Island the status bar height is smaller than the safe area top inset.
232
- statusBarHeight = 54;
233
- }
234
- const headerHeight = getDefaultHeaderHeight(
235
+ const hasLargeHeader = options.headerLargeTitle ?? false;
236
+
237
+ const defaultHeaderHeight = getDefaultHeaderHeight(
235
238
  dimensions,
236
239
  statusBarHeight,
237
240
  stackPresentation,
238
- isLargeHeader
241
+ hasLargeHeader
239
242
  );
243
+
240
244
  const parentHeaderHeight = React.useContext(HeaderHeightContext);
245
+ const isHeaderInPush = isAndroid
246
+ ? headerShown
247
+ : stackPresentation === 'push' && headerShown !== false;
248
+
249
+ const staticHeaderHeight =
250
+ isHeaderInPush !== false ? defaultHeaderHeight : parentHeaderHeight ?? 0;
251
+
252
+ // We need to ensure the first retrieved header height will be cached and set in animatedHeaderHeight.
253
+ // We're caching the header height here, as on iOS native side events are not always coming to the JS on first notify.
254
+ // TODO: Check why first event is not being received once it is cached on the native side.
255
+ const cachedAnimatedHeaderHeight = React.useRef(defaultHeaderHeight);
256
+ const animatedHeaderHeight = React.useRef(
257
+ new Animated.Value(staticHeaderHeight, {
258
+ useNativeDriver: true,
259
+ })
260
+ ).current;
261
+
241
262
  const Screen = React.useContext(ScreenContext);
242
263
 
243
264
  const { dark } = useTheme();
@@ -247,6 +268,7 @@ const RouteView = ({
247
268
  key={route.key}
248
269
  enabled
249
270
  isNativeStack
271
+ hasLargeHeader={hasLargeHeader}
250
272
  style={StyleSheet.absoluteFill}
251
273
  sheetAllowedDetents={sheetAllowedDetents}
252
274
  sheetLargestUndimmedDetent={sheetLargestUndimmedDetent}
@@ -313,7 +335,19 @@ const RouteView = ({
313
335
  target: route.key,
314
336
  });
315
337
  }}
316
- onDismissed={(e) => {
338
+ onHeaderHeightChange={e => {
339
+ const headerHeight = e.nativeEvent.headerHeight;
340
+
341
+ if (cachedAnimatedHeaderHeight.current !== headerHeight) {
342
+ // Currently, we're setting value by Animated#setValue, because we want to cache animated value.
343
+ // Also, in React Native 0.72 there was a bug on Fabric causing a large delay between the screen transition,
344
+ // which should not occur.
345
+ // TODO: Check if it's possible to replace animated#setValue to Animated#event.
346
+ animatedHeaderHeight.setValue(headerHeight);
347
+ cachedAnimatedHeaderHeight.current = headerHeight;
348
+ }
349
+ }}
350
+ onDismissed={e => {
317
351
  navigation.emit({
318
352
  type: 'dismiss',
319
353
  target: route.key,
@@ -333,25 +367,25 @@ const RouteView = ({
333
367
  type: 'gestureCancel',
334
368
  target: route.key,
335
369
  });
336
- }}
337
- >
338
- <HeaderHeightContext.Provider
339
- value={
340
- isHeaderInPush !== false ? headerHeight : parentHeaderHeight ?? 0
341
- }
342
- >
343
- <MaybeNestedStack
344
- options={options}
345
- route={route}
346
- stackPresentation={stackPresentation}
347
- >
348
- {renderScene()}
349
- </MaybeNestedStack>
350
- {/* HeaderConfig must not be first child of a Screen.
370
+ }}>
371
+ <AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
372
+ <HeaderHeightContext.Provider value={staticHeaderHeight}>
373
+ <MaybeNestedStack
374
+ options={options}
375
+ route={route}
376
+ stackPresentation={stackPresentation}>
377
+ {renderScene()}
378
+ </MaybeNestedStack>
379
+ {/* HeaderConfig must not be first child of a Screen.
351
380
  See https://github.com/software-mansion/react-native-screens/pull/1825
352
381
  for detailed explanation */}
353
- <HeaderConfig {...options} route={route} headerShown={isHeaderInPush} />
354
- </HeaderHeightContext.Provider>
382
+ <HeaderConfig
383
+ {...options}
384
+ route={route}
385
+ headerShown={isHeaderInPush}
386
+ />
387
+ </HeaderHeightContext.Provider>
388
+ </AnimatedHeaderHeightContext.Provider>
355
389
  </Screen>
356
390
  );
357
391
  };
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ // @ts-ignore file to be used only if `react-native-reanimated` available in the project
3
+ import Animated from 'react-native-reanimated';
4
+
5
+ export default React.createContext<Animated.SharedValue<number> | undefined>(
6
+ undefined
7
+ );
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { Platform } from 'react-native';
3
3
  import {
4
+ HeaderHeightChangeEventType,
4
5
  InnerScreen,
5
6
  ScreenProps,
6
7
  TransitionProgressEventType,
@@ -9,6 +10,13 @@ import {
9
10
  // @ts-ignore file to be used only if `react-native-reanimated` available in the project
10
11
  import Animated, { useEvent, useSharedValue } from 'react-native-reanimated';
11
12
  import ReanimatedTransitionProgressContext from './ReanimatedTransitionProgressContext';
13
+ import {
14
+ useSafeAreaFrame,
15
+ useSafeAreaInsets,
16
+ } from 'react-native-safe-area-context';
17
+ import getDefaultHeaderHeight from '../native-stack/utils/getDefaultHeaderHeight';
18
+ import getStatusBarHeight from '../native-stack/utils/getStatusBarHeight';
19
+ import ReanimatedHeaderHeightContext from './ReanimatedHeaderHeightContext';
12
20
 
13
21
  const AnimatedScreen = Animated.createAnimatedComponent(
14
22
  InnerScreen as unknown as React.ComponentClass
@@ -24,6 +32,28 @@ const ReanimatedNativeStackScreen = React.forwardRef<
24
32
  ScreenProps
25
33
  >((props, ref) => {
26
34
  const { children, ...rest } = props;
35
+ const { stackPresentation = 'push', hasLargeHeader } = rest;
36
+
37
+ const dimensions = useSafeAreaFrame();
38
+ const topInset = useSafeAreaInsets().top;
39
+ const isStatusBarTranslucent = rest.statusBarTranslucent ?? false;
40
+ const statusBarHeight = getStatusBarHeight(
41
+ topInset,
42
+ dimensions,
43
+ isStatusBarTranslucent
44
+ );
45
+
46
+ // Default header height, normally used in `useHeaderHeight` hook.
47
+ // Here, it is used for returning a default value for shared value.
48
+ const defaultHeaderHeight = getDefaultHeaderHeight(
49
+ dimensions,
50
+ statusBarHeight,
51
+ stackPresentation,
52
+ hasLargeHeader
53
+ );
54
+
55
+ const cachedHeaderHeight = React.useRef(defaultHeaderHeight);
56
+ const headerHeight = useSharedValue(defaultHeaderHeight);
27
57
 
28
58
  const progress = useSharedValue(0);
29
59
  const closing = useSharedValue(0);
@@ -51,17 +81,34 @@ const ReanimatedNativeStackScreen = React.forwardRef<
51
81
  : 'topTransitionProgress',
52
82
  ]
53
83
  )}
54
- {...rest}
55
- >
56
- <ReanimatedTransitionProgressContext.Provider
57
- value={{
58
- progress: progress,
59
- closing: closing,
60
- goingForward: goingForward,
61
- }}
62
- >
63
- {children}
64
- </ReanimatedTransitionProgressContext.Provider>
84
+ onHeaderHeightChangeReanimated={useEvent(
85
+ (event: HeaderHeightChangeEventType) => {
86
+ 'worklet';
87
+ if (event.headerHeight !== cachedHeaderHeight.current) {
88
+ headerHeight.value = event.headerHeight;
89
+ cachedHeaderHeight.current = event.headerHeight;
90
+ }
91
+ },
92
+ [
93
+ // @ts-ignore wrong type
94
+ Platform.OS === 'android'
95
+ ? 'onHeaderHeightChange'
96
+ : ENABLE_FABRIC
97
+ ? 'onHeaderHeightChange'
98
+ : 'topHeaderHeightChange',
99
+ ]
100
+ )}
101
+ {...rest}>
102
+ <ReanimatedHeaderHeightContext.Provider value={headerHeight}>
103
+ <ReanimatedTransitionProgressContext.Provider
104
+ value={{
105
+ progress,
106
+ closing,
107
+ goingForward,
108
+ }}>
109
+ {children}
110
+ </ReanimatedTransitionProgressContext.Provider>
111
+ </ReanimatedHeaderHeightContext.Provider>
65
112
  </AnimatedScreen>
66
113
  );
67
114
  });
@@ -1,2 +1,3 @@
1
1
  export { default as ReanimatedScreenProvider } from './ReanimatedScreenProvider';
2
2
  export { default as useReanimatedTransitionProgress } from './useReanimatedTransitionProgress';
3
+ export { default as useReanimatedHeaderHeight } from './useReanimatedHeaderHeight';
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ import ReanimatedHeaderHeightContext from './ReanimatedHeaderHeightContext';
3
+
4
+ export default function useReanimatedHeaderHeight() {
5
+ const height = React.useContext(ReanimatedHeaderHeightContext);
6
+
7
+ if (height === undefined) {
8
+ throw new Error(
9
+ "Couldn't find the header height using Reanimated. Are you inside a screen in a navigator with a header and your NavigationContainer is wrapped in ReanimatedScreenProvider?"
10
+ );
11
+ }
12
+
13
+ return height;
14
+ }
package/src/types.tsx CHANGED
@@ -73,6 +73,10 @@ export type HeaderSubviewTypes =
73
73
  | 'center'
74
74
  | 'searchBar';
75
75
 
76
+ export type HeaderHeightChangeEventType = {
77
+ headerHeight: number;
78
+ };
79
+
76
80
  export type TransitionProgressEventType = {
77
81
  progress: number;
78
82
  closing: number;
@@ -107,6 +111,10 @@ export interface ScreenProps extends ViewProps {
107
111
  * Internal boolean used to not attach events used only by native-stack. It prevents non native-stack navigators from sending transition progress from their Screen components.
108
112
  */
109
113
  isNativeStack?: boolean;
114
+ /**
115
+ * Internal boolean used to detect if current header has large title on iOS.
116
+ */
117
+ hasLargeHeader?: boolean;
110
118
  /**
111
119
  * Whether inactive screens should be suspended from re-rendering. Defaults to `false`.
112
120
  * When `enableFreeze()` is run at the top of the application defaults to `true`.
@@ -178,6 +186,12 @@ export interface ScreenProps extends ViewProps {
178
186
  * The callback takes the number of dismissed screens as an argument since iOS 14 native header back button can pop more than 1 screen at a time.
179
187
  */
180
188
  onDismissed?: (e: NativeSyntheticEvent<{ dismissCount: number }>) => void;
189
+ /**
190
+ * A callback that gets called when the header height has changed.
191
+ */
192
+ onHeaderHeightChange?: (
193
+ e: NativeSyntheticEvent<HeaderHeightChangeEventType>
194
+ ) => void;
181
195
  /**
182
196
  * A callback that gets called after swipe back is canceled.
183
197
  */
@@ -13,13 +13,16 @@
13
13
  <AppContainerApplication>true</AppContainerApplication>
14
14
  <ApplicationType>Windows Store</ApplicationType>
15
15
  <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
16
- <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
17
- <WindowsTargetPlatformMinVersion>10.0.16299.0</WindowsTargetPlatformMinVersion>
18
16
  </PropertyGroup>
19
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
20
17
  <PropertyGroup Label="ReactNativeWindowsProps">
21
18
  <ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir>
22
19
  </PropertyGroup>
20
+ <Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.WindowsSdk.Default.props" Condition="Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.WindowsSdk.Default.props')" />
21
+ <PropertyGroup Label="Fallback Windows SDK Versions">
22
+ <WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
23
+ <WindowsTargetPlatformMinVersion Condition=" '$(WindowsTargetPlatformMinVersion)' == '' ">10.0.16299.0</WindowsTargetPlatformMinVersion>
24
+ </PropertyGroup>
25
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
23
26
  <ItemGroup Label="ProjectConfigurations">
24
27
  <ProjectConfiguration Include="Debug|ARM">
25
28
  <Configuration>Debug</Configuration>
@@ -35,6 +35,7 @@ void ScreenStack::removeAllChildren() {
35
35
 
36
36
  void ScreenStack::removeChildAt(int64_t index) {
37
37
  m_children.RemoveAt(static_cast<uint32_t>(index));
38
+ onChildModified(index);
38
39
  }
39
40
 
40
41
  void ScreenStack::replaceChild(
@@ -45,5 +46,20 @@ void ScreenStack::replaceChild(
45
46
  return;
46
47
 
47
48
  m_children.SetAt(index, newChild);
49
+ onChildModified(index);
50
+ }
51
+
52
+ void ScreenStack::onChildModified(int64_t index) {
53
+ // Was it the topmost item in the stack?
54
+ if (index >= m_children.Size() - 1) {
55
+ if (m_children.Size() == 0) {
56
+ // Nobody left
57
+ Content(nullptr);
58
+ } else {
59
+ // Focus on the top item
60
+ auto uiElement = m_children.GetAt(m_children.Size() - 1);
61
+ Content(uiElement);
62
+ }
63
+ }
48
64
  }
49
65
  } // namespace winrt::RNScreens::implementation
@@ -17,6 +17,7 @@ class ScreenStack
17
17
  m_children;
18
18
 
19
19
  private:
20
+ void onChildModified(int64_t index);
20
21
  winrt::Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
21
22
  };
22
23
  } // namespace winrt::RNScreens::implementation