react-native-screens 3.24.0 → 3.26.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.
- package/README.md +1 -1
- package/RNScreens.podspec +53 -32
- package/android/build.gradle +13 -11
- package/android/src/main/java/com/swmansion/rnscreens/FragmentHolder.kt +7 -0
- package/android/src/main/java/com/swmansion/rnscreens/Screen.kt +41 -10
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainer.kt +35 -36
- package/android/src/main/java/com/swmansion/rnscreens/ScreenContainerViewManager.kt +7 -7
- package/android/src/main/java/com/swmansion/rnscreens/ScreenEventDispatcher.kt +21 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragment.kt +46 -38
- package/android/src/main/java/com/swmansion/rnscreens/ScreenFragmentWrapper.kt +22 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStack.kt +40 -39
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragment.kt +35 -10
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackFragmentWrapper.kt +15 -0
- package/android/src/main/java/com/swmansion/rnscreens/ScreenStackHeaderConfig.kt +6 -4
- package/android/src/main/java/com/swmansion/rnscreens/ScreenViewManager.kt +11 -18
- package/android/src/main/java/com/swmansion/rnscreens/ScreenWindowTraits.kt +27 -7
- package/android/src/main/java/com/swmansion/rnscreens/ScreensShadowNode.kt +1 -1
- package/android/src/main/java/com/swmansion/rnscreens/SearchBarView.kt +23 -7
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderAttachedEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderBackButtonClickedEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderDetachedEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/HeaderHeightChangeEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenAppearEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDisappearEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenDismissedEvent.kt +4 -7
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenTransitionProgressEvent.kt +7 -8
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillAppearEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/ScreenWillDisappearEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarBlurEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarChangeTextEvent.kt +5 -6
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarCloseEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarFocusEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarOpenEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/events/SearchBarSearchButtonPressEvent.kt +4 -6
- package/android/src/main/java/com/swmansion/rnscreens/events/StackFinishTransitioningEvent.kt +3 -5
- package/android/src/main/java/com/swmansion/rnscreens/utils/DeviceUtils.kt +12 -0
- package/android/src/main/res/v33/anim-v33/rns_default_enter_out.xml +1 -1
- package/ios/RNSFullWindowOverlay.mm +2 -2
- package/ios/RNSScreen.h +5 -0
- package/ios/RNSScreen.mm +164 -7
- package/ios/RNSScreenStack.mm +18 -0
- package/ios/RNSScreenStackHeaderConfig.mm +18 -0
- package/ios/events/RNSHeaderHeightChangeEvent.h +8 -0
- package/ios/events/RNSHeaderHeightChangeEvent.mm +44 -0
- package/lib/commonjs/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/commonjs/index.native.js +11 -11
- package/lib/commonjs/index.native.js.map +1 -1
- package/lib/commonjs/native-stack/index.js +14 -0
- package/lib/commonjs/native-stack/index.js.map +1 -1
- package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js +1 -1
- package/lib/commonjs/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
- package/lib/commonjs/native-stack/types.js.map +1 -1
- package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js +13 -0
- package/lib/commonjs/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
- package/lib/commonjs/native-stack/utils/SafeAreaProviderCompat.js.map +1 -1
- package/lib/commonjs/native-stack/utils/getStatusBarHeight.js +22 -0
- package/lib/commonjs/native-stack/utils/getStatusBarHeight.js.map +1 -0
- package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js +19 -0
- package/lib/commonjs/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
- package/lib/commonjs/native-stack/utils/useBackPressSubscription.js +2 -2
- package/lib/commonjs/native-stack/utils/useBackPressSubscription.js.map +1 -1
- package/lib/commonjs/native-stack/views/HeaderConfig.js +2 -2
- package/lib/commonjs/native-stack/views/HeaderConfig.js.map +1 -1
- package/lib/commonjs/native-stack/views/NativeStackView.js +39 -21
- package/lib/commonjs/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js +13 -0
- package/lib/commonjs/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
- package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js +37 -6
- package/lib/commonjs/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
- package/lib/commonjs/reanimated/ReanimatedScreenProvider.js +2 -2
- package/lib/commonjs/reanimated/ReanimatedScreenProvider.js.map +1 -1
- package/lib/commonjs/reanimated/index.js +7 -0
- package/lib/commonjs/reanimated/index.js.map +1 -1
- package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js +19 -0
- package/lib/commonjs/reanimated/useReanimatedHeaderHeight.js.map +1 -0
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/fabric/ScreenNativeComponent.js.map +1 -1
- package/lib/module/index.native.js +12 -12
- package/lib/module/index.native.js.map +1 -1
- package/lib/module/native-stack/index.js +2 -0
- package/lib/module/native-stack/index.js.map +1 -1
- package/lib/module/native-stack/navigators/createNativeStackNavigator.js +1 -1
- package/lib/module/native-stack/navigators/createNativeStackNavigator.js.map +1 -1
- package/lib/module/native-stack/types.js.map +1 -1
- package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js +4 -0
- package/lib/module/native-stack/utils/AnimatedHeaderHeightContext.js.map +1 -0
- package/lib/module/native-stack/utils/SafeAreaProviderCompat.js.map +1 -1
- package/lib/module/native-stack/utils/getStatusBarHeight.js +16 -0
- package/lib/module/native-stack/utils/getStatusBarHeight.js.map +1 -0
- package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js +10 -0
- package/lib/module/native-stack/utils/useAnimatedHeaderHeight.js.map +1 -0
- package/lib/module/native-stack/utils/useBackPressSubscription.js +2 -2
- package/lib/module/native-stack/utils/useBackPressSubscription.js.map +1 -1
- package/lib/module/native-stack/views/HeaderConfig.js +2 -2
- package/lib/module/native-stack/views/HeaderConfig.js.map +1 -1
- package/lib/module/native-stack/views/NativeStackView.js +40 -22
- package/lib/module/native-stack/views/NativeStackView.js.map +1 -1
- package/lib/module/reanimated/ReanimatedHeaderHeightContext.js +5 -0
- package/lib/module/reanimated/ReanimatedHeaderHeightContext.js.map +1 -0
- package/lib/module/reanimated/ReanimatedNativeStackScreen.js +37 -6
- package/lib/module/reanimated/ReanimatedNativeStackScreen.js.map +1 -1
- package/lib/module/reanimated/ReanimatedScreenProvider.js +2 -2
- package/lib/module/reanimated/ReanimatedScreenProvider.js.map +1 -1
- package/lib/module/reanimated/index.js +1 -0
- package/lib/module/reanimated/index.js.map +1 -1
- package/lib/module/reanimated/useReanimatedHeaderHeight.js +10 -0
- package/lib/module/reanimated/useReanimatedHeaderHeight.js.map +1 -0
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/fabric/ScreenNativeComponent.d.ts +4 -0
- package/lib/typescript/native-stack/index.d.ts +2 -0
- package/lib/typescript/native-stack/types.d.ts +20 -12
- package/lib/typescript/native-stack/utils/AnimatedHeaderHeightContext.d.ts +4 -0
- package/lib/typescript/native-stack/utils/getStatusBarHeight.d.ts +2 -0
- package/lib/typescript/native-stack/utils/useAnimatedHeaderHeight.d.ts +1 -0
- package/lib/typescript/reanimated/ReanimatedHeaderHeightContext.d.ts +4 -0
- package/lib/typescript/reanimated/index.d.ts +1 -0
- package/lib/typescript/reanimated/useReanimatedHeaderHeight.d.ts +3 -0
- package/lib/typescript/types.d.ts +26 -15
- package/native-stack/README.md +16 -1
- package/package.json +36 -38
- package/src/fabric/ScreenNativeComponent.ts +5 -0
- package/src/index.native.tsx +17 -19
- package/src/native-stack/index.tsx +3 -0
- package/src/native-stack/types.tsx +21 -12
- package/src/native-stack/utils/AnimatedHeaderHeightContext.tsx +8 -0
- package/src/native-stack/utils/SafeAreaProviderCompat.tsx +1 -1
- package/src/native-stack/utils/getStatusBarHeight.tsx +22 -0
- package/src/native-stack/utils/useAnimatedHeaderHeight.tsx +15 -0
- package/src/native-stack/views/HeaderConfig.tsx +1 -2
- package/src/native-stack/views/NativeStackView.tsx +78 -44
- package/src/reanimated/ReanimatedHeaderHeightContext.tsx +7 -0
- package/src/reanimated/ReanimatedNativeStackScreen.tsx +58 -11
- package/src/reanimated/index.tsx +1 -0
- package/src/reanimated/useReanimatedHeaderHeight.tsx +14 -0
- package/src/types.tsx +29 -14
- package/windows/RNScreens/RNScreens.vcxproj +6 -3
- package/windows/RNScreens/ScreenStack.cpp +16 -0
- package/windows/RNScreens/ScreenStack.h +1 -0
- /package/ios/{RNSScreenViewEvent.h → events/RNSScreenViewEvent.h} +0 -0
- /package/ios/{RNSScreenViewEvent.mm → events/RNSScreenViewEvent.mm} +0 -0
package/src/index.native.tsx
CHANGED
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
Image,
|
|
6
6
|
ImageProps,
|
|
7
7
|
Platform,
|
|
8
|
-
requireNativeComponent,
|
|
9
8
|
StyleProp,
|
|
10
9
|
StyleSheet,
|
|
11
10
|
UIManager,
|
|
@@ -137,28 +136,29 @@ const ScreensNativeModules = {
|
|
|
137
136
|
NativeScreenNavigationContainerValue =
|
|
138
137
|
NativeScreenNavigationContainerValue ||
|
|
139
138
|
(Platform.OS === 'ios'
|
|
140
|
-
?
|
|
139
|
+
? require('./fabric/ScreenNavigationContainerNativeComponent').default
|
|
141
140
|
: this.NativeScreenContainer);
|
|
142
141
|
return NativeScreenNavigationContainerValue;
|
|
143
142
|
},
|
|
144
143
|
|
|
145
144
|
get NativeScreenStack() {
|
|
146
145
|
NativeScreenStack =
|
|
147
|
-
NativeScreenStack ||
|
|
146
|
+
NativeScreenStack ||
|
|
147
|
+
require('./fabric/ScreenStackNativeComponent').default;
|
|
148
148
|
return NativeScreenStack;
|
|
149
149
|
},
|
|
150
150
|
|
|
151
151
|
get NativeScreenStackHeaderConfig() {
|
|
152
152
|
NativeScreenStackHeaderConfig =
|
|
153
153
|
NativeScreenStackHeaderConfig ||
|
|
154
|
-
|
|
154
|
+
require('./fabric/ScreenStackHeaderConfigNativeComponent').default;
|
|
155
155
|
return NativeScreenStackHeaderConfig;
|
|
156
156
|
},
|
|
157
157
|
|
|
158
158
|
get NativeScreenStackHeaderSubview() {
|
|
159
159
|
NativeScreenStackHeaderSubview =
|
|
160
160
|
NativeScreenStackHeaderSubview ||
|
|
161
|
-
|
|
161
|
+
require('./fabric/ScreenStackHeaderSubviewNativeComponent').default;
|
|
162
162
|
return NativeScreenStackHeaderSubview;
|
|
163
163
|
},
|
|
164
164
|
|
|
@@ -167,6 +167,7 @@ const ScreensNativeModules = {
|
|
|
167
167
|
NativeSearchBar || require('./fabric/SearchBarNativeComponent').default;
|
|
168
168
|
return NativeSearchBar;
|
|
169
169
|
},
|
|
170
|
+
|
|
170
171
|
get NativeSearchBarCommands() {
|
|
171
172
|
NativeSearchBarCommands =
|
|
172
173
|
NativeSearchBarCommands ||
|
|
@@ -176,7 +177,8 @@ const ScreensNativeModules = {
|
|
|
176
177
|
|
|
177
178
|
get NativeFullWindowOverlay() {
|
|
178
179
|
NativeFullWindowOverlay =
|
|
179
|
-
NativeFullWindowOverlay ||
|
|
180
|
+
NativeFullWindowOverlay ||
|
|
181
|
+
require('./fabric/FullWindowOverlayNativeComponent').default;
|
|
180
182
|
return NativeFullWindowOverlay;
|
|
181
183
|
},
|
|
182
184
|
};
|
|
@@ -346,8 +348,7 @@ class InnerScreen extends React.Component<ScreenProps> {
|
|
|
346
348
|
(() => {
|
|
347
349
|
// for internal use
|
|
348
350
|
})
|
|
349
|
-
}
|
|
350
|
-
>
|
|
351
|
+
}>
|
|
351
352
|
{!isNativeStack ? ( // see comment of this prop in types.tsx for information why it is needed
|
|
352
353
|
children
|
|
353
354
|
) : (
|
|
@@ -356,8 +357,7 @@ class InnerScreen extends React.Component<ScreenProps> {
|
|
|
356
357
|
progress: this.progress,
|
|
357
358
|
closing: this.closing,
|
|
358
359
|
goingForward: this.goingForward,
|
|
359
|
-
}}
|
|
360
|
-
>
|
|
360
|
+
}}>
|
|
361
361
|
{children}
|
|
362
362
|
</TransitionProgressContext.Provider>
|
|
363
363
|
)}
|
|
@@ -408,8 +408,7 @@ function FullWindowOverlay(props: { children: ReactNode }) {
|
|
|
408
408
|
}
|
|
409
409
|
return (
|
|
410
410
|
<ScreensNativeModules.NativeFullWindowOverlay
|
|
411
|
-
style={{ position: 'absolute', width: '100%', height: '100%' }}
|
|
412
|
-
>
|
|
411
|
+
style={{ position: 'absolute', width: '100%', height: '100%' }}>
|
|
413
412
|
{props.children}
|
|
414
413
|
</ScreensNativeModules.NativeFullWindowOverlay>
|
|
415
414
|
);
|
|
@@ -429,8 +428,7 @@ const styles = StyleSheet.create({
|
|
|
429
428
|
const ScreenStackHeaderBackButtonImage = (props: ImageProps): JSX.Element => (
|
|
430
429
|
<ScreensNativeModules.NativeScreenStackHeaderSubview
|
|
431
430
|
type="back"
|
|
432
|
-
style={styles.headerSubview}
|
|
433
|
-
>
|
|
431
|
+
style={styles.headerSubview}>
|
|
434
432
|
<Image resizeMode="center" fadeDuration={0} {...props} />
|
|
435
433
|
</ScreensNativeModules.NativeScreenStackHeaderSubview>
|
|
436
434
|
);
|
|
@@ -455,31 +453,31 @@ class SearchBar extends React.Component<SearchBarProps> {
|
|
|
455
453
|
}
|
|
456
454
|
|
|
457
455
|
blur() {
|
|
458
|
-
this._callMethodWithRef(
|
|
456
|
+
this._callMethodWithRef(ref =>
|
|
459
457
|
ScreensNativeModules.NativeSearchBarCommands.blur(ref)
|
|
460
458
|
);
|
|
461
459
|
}
|
|
462
460
|
|
|
463
461
|
focus() {
|
|
464
|
-
this._callMethodWithRef(
|
|
462
|
+
this._callMethodWithRef(ref =>
|
|
465
463
|
ScreensNativeModules.NativeSearchBarCommands.focus(ref)
|
|
466
464
|
);
|
|
467
465
|
}
|
|
468
466
|
|
|
469
467
|
toggleCancelButton(flag: boolean) {
|
|
470
|
-
this._callMethodWithRef(
|
|
468
|
+
this._callMethodWithRef(ref =>
|
|
471
469
|
ScreensNativeModules.NativeSearchBarCommands.toggleCancelButton(ref, flag)
|
|
472
470
|
);
|
|
473
471
|
}
|
|
474
472
|
|
|
475
473
|
clearText() {
|
|
476
|
-
this._callMethodWithRef(
|
|
474
|
+
this._callMethodWithRef(ref =>
|
|
477
475
|
ScreensNativeModules.NativeSearchBarCommands.clearText(ref)
|
|
478
476
|
);
|
|
479
477
|
}
|
|
480
478
|
|
|
481
479
|
setText(text: string) {
|
|
482
|
-
this._callMethodWithRef(
|
|
480
|
+
this._callMethodWithRef(ref =>
|
|
483
481
|
ScreensNativeModules.NativeSearchBarCommands.setText(ref, text)
|
|
484
482
|
);
|
|
485
483
|
}
|
|
@@ -14,6 +14,9 @@ export { default as NativeStackView } from './views/NativeStackView';
|
|
|
14
14
|
export { default as useHeaderHeight } from './utils/useHeaderHeight';
|
|
15
15
|
export { default as HeaderHeightContext } from './utils/HeaderHeightContext';
|
|
16
16
|
|
|
17
|
+
export { default as useAnimatedHeaderHeight } from './utils/useAnimatedHeaderHeight';
|
|
18
|
+
export { default as AnimatedHeaderHeightContext } from './utils/AnimatedHeaderHeightContext';
|
|
19
|
+
|
|
17
20
|
/**
|
|
18
21
|
* Types
|
|
19
22
|
*/
|
|
@@ -10,7 +10,12 @@ import {
|
|
|
10
10
|
RouteProp,
|
|
11
11
|
} from '@react-navigation/native';
|
|
12
12
|
import * as React from 'react';
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
ImageSourcePropType,
|
|
15
|
+
StyleProp,
|
|
16
|
+
ViewStyle,
|
|
17
|
+
ColorValue,
|
|
18
|
+
} from 'react-native';
|
|
14
19
|
import {
|
|
15
20
|
ScreenProps,
|
|
16
21
|
ScreenStackHeaderConfigProps,
|
|
@@ -41,6 +46,10 @@ export type NativeStackNavigationEventMap = {
|
|
|
41
46
|
* Event which fires when a swipe back is canceled on iOS.
|
|
42
47
|
*/
|
|
43
48
|
gestureCancel: { data: undefined };
|
|
49
|
+
/**
|
|
50
|
+
* Event which fires when a header height gets changed.
|
|
51
|
+
*/
|
|
52
|
+
headerHeightChange: { data: { headerHeight: number } };
|
|
44
53
|
};
|
|
45
54
|
|
|
46
55
|
export type NativeStackNavigationProp<
|
|
@@ -157,7 +166,7 @@ export type NativeStackNavigationOptions = {
|
|
|
157
166
|
/**
|
|
158
167
|
* Function which returns a React Element to display in the center of the header.
|
|
159
168
|
*/
|
|
160
|
-
headerCenter?: (props: { tintColor?:
|
|
169
|
+
headerCenter?: (props: { tintColor?: ColorValue }) => React.ReactNode;
|
|
161
170
|
/**
|
|
162
171
|
* Boolean indicating whether to hide the back button in header.
|
|
163
172
|
*/
|
|
@@ -173,7 +182,7 @@ export type NativeStackNavigationOptions = {
|
|
|
173
182
|
* @platform ios
|
|
174
183
|
*/
|
|
175
184
|
headerLargeStyle?: {
|
|
176
|
-
backgroundColor?:
|
|
185
|
+
backgroundColor?: ColorValue;
|
|
177
186
|
};
|
|
178
187
|
/**
|
|
179
188
|
* Boolean to set native property to prefer large title header (like in iOS setting).
|
|
@@ -202,16 +211,16 @@ export type NativeStackNavigationOptions = {
|
|
|
202
211
|
fontFamily?: string;
|
|
203
212
|
fontSize?: number;
|
|
204
213
|
fontWeight?: string;
|
|
205
|
-
color?:
|
|
214
|
+
color?: ColorValue;
|
|
206
215
|
};
|
|
207
216
|
/**
|
|
208
217
|
* Function which returns a React Element to display on the left side of the header.
|
|
209
218
|
*/
|
|
210
|
-
headerLeft?: (props: { tintColor?:
|
|
219
|
+
headerLeft?: (props: { tintColor?: ColorValue }) => React.ReactNode;
|
|
211
220
|
/**
|
|
212
221
|
* Function which returns a React Element to display on the right side of the header.
|
|
213
222
|
*/
|
|
214
|
-
headerRight?: (props: { tintColor?:
|
|
223
|
+
headerRight?: (props: { tintColor?: ColorValue }) => React.ReactNode;
|
|
215
224
|
/**
|
|
216
225
|
* Whether to show the header.
|
|
217
226
|
*/
|
|
@@ -222,13 +231,13 @@ export type NativeStackNavigationOptions = {
|
|
|
222
231
|
* - blurEffect
|
|
223
232
|
*/
|
|
224
233
|
headerStyle?: {
|
|
225
|
-
backgroundColor?:
|
|
234
|
+
backgroundColor?: ColorValue;
|
|
226
235
|
blurEffect?: ScreenStackHeaderConfigProps['blurEffect'];
|
|
227
236
|
};
|
|
228
237
|
/**
|
|
229
238
|
* Tint color for the header. Changes the color of back button and title.
|
|
230
239
|
*/
|
|
231
|
-
headerTintColor?:
|
|
240
|
+
headerTintColor?: ColorValue;
|
|
232
241
|
/**
|
|
233
242
|
* String to display in the header as title. Defaults to scene `title`.
|
|
234
243
|
*/
|
|
@@ -244,7 +253,7 @@ export type NativeStackNavigationOptions = {
|
|
|
244
253
|
fontFamily?: string;
|
|
245
254
|
fontSize?: number;
|
|
246
255
|
fontWeight?: string;
|
|
247
|
-
color?:
|
|
256
|
+
color?: ColorValue;
|
|
248
257
|
};
|
|
249
258
|
/**
|
|
250
259
|
* A flag to that lets you opt out of insetting the header. You may want to
|
|
@@ -284,7 +293,7 @@ export type NativeStackNavigationOptions = {
|
|
|
284
293
|
*
|
|
285
294
|
* @platform android
|
|
286
295
|
*/
|
|
287
|
-
navigationBarColor?:
|
|
296
|
+
navigationBarColor?: ColorValue;
|
|
288
297
|
/**
|
|
289
298
|
* Sets the visibility of the navigation bar. Defaults to `false`.
|
|
290
299
|
*
|
|
@@ -341,7 +350,7 @@ export type NativeStackNavigationOptions = {
|
|
|
341
350
|
* The corner radius that the sheet will try to render with.
|
|
342
351
|
* Works only when `stackPresentation` is set to `formSheet`.
|
|
343
352
|
*
|
|
344
|
-
* If set to non-negative value it will try to render sheet with provided radius, else
|
|
353
|
+
* If set to non-negative value it will try to render sheet with provided radius, else it will apply system default.
|
|
345
354
|
*
|
|
346
355
|
* If left unset system default is used.
|
|
347
356
|
*
|
|
@@ -406,7 +415,7 @@ export type NativeStackNavigationOptions = {
|
|
|
406
415
|
*
|
|
407
416
|
* @platform android
|
|
408
417
|
*/
|
|
409
|
-
statusBarColor?:
|
|
418
|
+
statusBarColor?: ColorValue;
|
|
410
419
|
/**
|
|
411
420
|
* Whether the status bar should be hidden on this screen. Requires enabling (or deleting) `View controller-based status bar appearance` in your Info.plist file on iOS. Defaults to `false`.
|
|
412
421
|
*/
|
|
@@ -36,7 +36,7 @@ const initialMetrics =
|
|
|
36
36
|
export default function SafeAreaProviderCompat({ children, style }: Props) {
|
|
37
37
|
return (
|
|
38
38
|
<SafeAreaInsetsContext.Consumer>
|
|
39
|
-
{
|
|
39
|
+
{insets => {
|
|
40
40
|
if (insets) {
|
|
41
41
|
// If we already have insets, don't wrap the stack in another safe area provider
|
|
42
42
|
// This avoids an issue with updates at the cost of potentially incorrect values
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Rect } from 'react-native-safe-area-context';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export default function getStatusBarHeight(
|
|
5
|
+
topInset: number,
|
|
6
|
+
dimensions: Rect,
|
|
7
|
+
isStatusBarTranslucent: boolean
|
|
8
|
+
) {
|
|
9
|
+
if (Platform.OS === 'ios') {
|
|
10
|
+
// It looks like some iOS devices don't have strictly set status bar height to 44.
|
|
11
|
+
// Thus, if the top inset is higher than 50, then the device should have a dynamic island.
|
|
12
|
+
// On models with Dynamic Island the status bar height is smaller than the safe area top inset by 5 pixels.
|
|
13
|
+
// See https://developer.apple.com/forums/thread/662466 for more details about status bar height.
|
|
14
|
+
const hasDynamicIsland = topInset > 50;
|
|
15
|
+
return hasDynamicIsland ? topInset - 5 : topInset;
|
|
16
|
+
} else if (Platform.OS === 'android') {
|
|
17
|
+
// On Android we should also rely on frame's y-axis position, as topInset is 0 on visible status bar.
|
|
18
|
+
return isStatusBarTranslucent ? topInset : dimensions.y;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return topInset;
|
|
22
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import AnimatedHeaderHeightContext from './AnimatedHeaderHeightContext';
|
|
4
|
+
|
|
5
|
+
export default function useAnimatedHeaderHeight() {
|
|
6
|
+
const animatedValue = React.useContext(AnimatedHeaderHeightContext);
|
|
7
|
+
|
|
8
|
+
if (animatedValue === undefined) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"Couldn't find the header height. Are you inside a screen in a navigator with a header?"
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return animatedValue;
|
|
15
|
+
}
|
|
@@ -140,8 +140,7 @@ export default function HeaderConfig({
|
|
|
140
140
|
topInsetEnabled={headerTopInsetEnabled}
|
|
141
141
|
translucent={headerTranslucent === true}
|
|
142
142
|
onAttached={handleAttached}
|
|
143
|
-
onDetached={handleDetached}
|
|
144
|
-
>
|
|
143
|
+
onDetached={handleDetached}>
|
|
145
144
|
{headerRight !== undefined ? (
|
|
146
145
|
<ScreenStackHeaderRightView>
|
|
147
146
|
{headerRight({ tintColor })}
|
|
@@ -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
|
-
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
127
|
+
hasLargeHeader
|
|
126
128
|
);
|
|
127
129
|
|
|
128
130
|
if (isHeaderInModal) {
|
|
129
131
|
return (
|
|
130
132
|
<ScreenStack style={styles.container}>
|
|
131
|
-
<Screen
|
|
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
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
228
|
+
const isStatusBarTranslucent = options.statusBarTranslucent ?? false;
|
|
229
|
+
const statusBarHeight = getStatusBarHeight(
|
|
230
|
+
topInset,
|
|
231
|
+
dimensions,
|
|
232
|
+
isStatusBarTranslucent
|
|
233
|
+
);
|
|
229
234
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
354
|
-
|
|
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
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
});
|
package/src/reanimated/index.tsx
CHANGED
|
@@ -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
|
+
}
|