@react-navigation/native-stack 7.8.6 → 8.0.0-alpha.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/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/navigators/createNativeStackNavigator.js +7 -6
- package/lib/module/navigators/createNativeStackNavigator.js.map +1 -1
- package/lib/module/views/NativeStackView.js +4 -4
- package/lib/module/views/NativeStackView.js.map +1 -1
- package/lib/module/views/NativeStackView.native.js +159 -200
- package/lib/module/views/NativeStackView.native.js.map +1 -1
- package/lib/module/views/useHeaderConfigProps.js +44 -24
- package/lib/module/views/useHeaderConfigProps.js.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/navigators/createNativeStackNavigator.d.ts +10 -6
- package/lib/typescript/src/navigators/createNativeStackNavigator.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +72 -67
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/views/NativeStackView.d.ts.map +1 -1
- package/lib/typescript/src/views/NativeStackView.native.d.ts.map +1 -1
- package/lib/typescript/src/views/useHeaderConfigProps.d.ts +1 -1
- package/lib/typescript/src/views/useHeaderConfigProps.d.ts.map +1 -1
- package/package.json +15 -17
- package/src/index.tsx +4 -1
- package/src/navigators/createNativeStackNavigator.tsx +48 -25
- package/src/types.tsx +72 -72
- package/src/views/NativeStackView.native.tsx +191 -253
- package/src/views/NativeStackView.tsx +6 -9
- package/src/views/useHeaderConfigProps.tsx +32 -30
- package/lib/module/views/FontProcessor.js +0 -6
- package/lib/module/views/FontProcessor.js.map +0 -1
- package/lib/module/views/FontProcessor.native.js +0 -12
- package/lib/module/views/FontProcessor.native.js.map +0 -1
- package/lib/typescript/src/views/FontProcessor.d.ts +0 -2
- package/lib/typescript/src/views/FontProcessor.d.ts.map +0 -1
- package/lib/typescript/src/views/FontProcessor.native.d.ts +0 -2
- package/lib/typescript/src/views/FontProcessor.native.d.ts.map +0 -1
- package/src/views/FontProcessor.native.tsx +0 -12
- package/src/views/FontProcessor.tsx +0 -5
|
@@ -4,12 +4,11 @@ import {
|
|
|
4
4
|
HeaderBackContext,
|
|
5
5
|
HeaderHeightContext,
|
|
6
6
|
HeaderShownContext,
|
|
7
|
-
SafeAreaProviderCompat,
|
|
8
7
|
useFrameSize,
|
|
9
8
|
} from '@react-navigation/elements';
|
|
9
|
+
import { SafeAreaProviderCompat } from '@react-navigation/elements/internal';
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
NavigationRouteContext,
|
|
11
|
+
NavigationProvider,
|
|
13
12
|
type ParamListBase,
|
|
14
13
|
type RouteProp,
|
|
15
14
|
StackActions,
|
|
@@ -21,7 +20,6 @@ import * as React from 'react';
|
|
|
21
20
|
import {
|
|
22
21
|
Animated,
|
|
23
22
|
Platform,
|
|
24
|
-
StatusBar,
|
|
25
23
|
StyleSheet,
|
|
26
24
|
useAnimatedValue,
|
|
27
25
|
View,
|
|
@@ -79,7 +77,6 @@ const SceneView = ({
|
|
|
79
77
|
shouldFreeze,
|
|
80
78
|
descriptor,
|
|
81
79
|
previousDescriptor,
|
|
82
|
-
nextDescriptor,
|
|
83
80
|
isPresentationModal,
|
|
84
81
|
isPreloaded,
|
|
85
82
|
onWillDisappear,
|
|
@@ -94,19 +91,15 @@ const SceneView = ({
|
|
|
94
91
|
}: SceneViewProps) => {
|
|
95
92
|
const { route, navigation, options, render } = descriptor;
|
|
96
93
|
|
|
97
|
-
let {
|
|
98
|
-
animation,
|
|
99
|
-
animationMatchesGesture,
|
|
100
|
-
presentation = isPresentationModal ? 'modal' : 'card',
|
|
101
|
-
fullScreenGestureEnabled,
|
|
102
|
-
} = options;
|
|
103
|
-
|
|
104
94
|
const {
|
|
95
|
+
animation,
|
|
105
96
|
animationDuration,
|
|
97
|
+
animationMatchesGesture,
|
|
106
98
|
animationTypeForReplace = 'push',
|
|
99
|
+
fullScreenGestureEnabled,
|
|
107
100
|
fullScreenGestureShadowEnabled = true,
|
|
108
101
|
gestureEnabled,
|
|
109
|
-
gestureDirection
|
|
102
|
+
gestureDirection,
|
|
110
103
|
gestureResponseDistance,
|
|
111
104
|
header,
|
|
112
105
|
headerBackButtonMenuEnabled,
|
|
@@ -115,8 +108,6 @@ const SceneView = ({
|
|
|
115
108
|
headerTransparent,
|
|
116
109
|
autoHideHomeIndicator,
|
|
117
110
|
keyboardHandlingEnabled,
|
|
118
|
-
navigationBarColor,
|
|
119
|
-
navigationBarTranslucent,
|
|
120
111
|
navigationBarHidden,
|
|
121
112
|
orientation,
|
|
122
113
|
sheetAllowedDetents = [1.0],
|
|
@@ -129,38 +120,13 @@ const SceneView = ({
|
|
|
129
120
|
statusBarAnimation,
|
|
130
121
|
statusBarHidden,
|
|
131
122
|
statusBarStyle,
|
|
132
|
-
statusBarTranslucent,
|
|
133
|
-
statusBarBackgroundColor,
|
|
134
123
|
unstable_sheetFooter,
|
|
135
124
|
scrollEdgeEffects,
|
|
136
125
|
freezeOnBlur,
|
|
137
126
|
contentStyle,
|
|
138
127
|
} = options;
|
|
139
128
|
|
|
140
|
-
|
|
141
|
-
// for `vertical` direction to work, we need to set `fullScreenGestureEnabled` to `true`
|
|
142
|
-
// so the screen can be dismissed from any point on screen.
|
|
143
|
-
// `animationMatchesGesture` needs to be set to `true` so the `animation` set by user can be used,
|
|
144
|
-
// otherwise `simple_push` will be used.
|
|
145
|
-
// Also, the default animation for this direction seems to be `slide_from_bottom`.
|
|
146
|
-
if (fullScreenGestureEnabled === undefined) {
|
|
147
|
-
fullScreenGestureEnabled = true;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (animationMatchesGesture === undefined) {
|
|
151
|
-
animationMatchesGesture = true;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (animation === undefined) {
|
|
155
|
-
animation = 'slide_from_bottom';
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// workaround for rn-screens where gestureDirection has to be set on both
|
|
160
|
-
// current and previous screen - software-mansion/react-native-screens/pull/1509
|
|
161
|
-
const nextGestureDirection = nextDescriptor?.options.gestureDirection;
|
|
162
|
-
const gestureDirectionOverride =
|
|
163
|
-
nextGestureDirection != null ? nextGestureDirection : gestureDirection;
|
|
129
|
+
let { presentation = isPresentationModal ? 'modal' : 'card' } = options;
|
|
164
130
|
|
|
165
131
|
if (index === 0) {
|
|
166
132
|
// first screen should always be treated as `card`, it resolves problems with no header animation
|
|
@@ -199,7 +165,11 @@ const SceneView = ({
|
|
|
199
165
|
// So our `getDefaultHeaderHeight` doesn't return the correct value
|
|
200
166
|
// So we hardcode the value here for now until screens is updated
|
|
201
167
|
android: ANDROID_DEFAULT_HEADER_HEIGHT + topInset,
|
|
202
|
-
default: getDefaultHeaderHeight(
|
|
168
|
+
default: getDefaultHeaderHeight({
|
|
169
|
+
landscape: frame.width > frame.height,
|
|
170
|
+
modalPresentation: isModal,
|
|
171
|
+
topInset,
|
|
172
|
+
}),
|
|
203
173
|
})
|
|
204
174
|
);
|
|
205
175
|
|
|
@@ -216,38 +186,7 @@ const SceneView = ({
|
|
|
216
186
|
|
|
217
187
|
const hasCustomHeader = header != null;
|
|
218
188
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (Platform.OS === 'android' && !hasCustomHeader) {
|
|
222
|
-
const statusBarHeight = StatusBar.currentHeight ?? 0;
|
|
223
|
-
|
|
224
|
-
// FIXME: On Android, the native header height is not correctly calculated
|
|
225
|
-
// It includes status bar height even if statusbar is not translucent
|
|
226
|
-
// And the statusbar value itself doesn't match the actual status bar height
|
|
227
|
-
// So we subtract the bogus status bar height and add the actual top inset
|
|
228
|
-
headerHeightCorrectionOffset = -statusBarHeight + topInset;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const rawAnimatedHeaderHeight = useAnimatedValue(defaultHeaderHeight);
|
|
232
|
-
const animatedHeaderHeight = React.useMemo(
|
|
233
|
-
() =>
|
|
234
|
-
Animated.add<number>(
|
|
235
|
-
rawAnimatedHeaderHeight,
|
|
236
|
-
headerHeightCorrectionOffset
|
|
237
|
-
),
|
|
238
|
-
[headerHeightCorrectionOffset, rawAnimatedHeaderHeight]
|
|
239
|
-
);
|
|
240
|
-
|
|
241
|
-
// During the very first render topInset is > 0 when running
|
|
242
|
-
// in non edge-to-edge mode on Android, while on every consecutive render
|
|
243
|
-
// topInset === 0, causing header content to jump, as we add padding on the first frame,
|
|
244
|
-
// just to remove it in next one. To prevent this, when statusBarTranslucent is set,
|
|
245
|
-
// we apply additional padding in header only if its true.
|
|
246
|
-
// For more details see: https://github.com/react-navigation/react-navigation/pull/12014
|
|
247
|
-
const headerTopInsetEnabled =
|
|
248
|
-
typeof statusBarTranslucent === 'boolean'
|
|
249
|
-
? statusBarTranslucent
|
|
250
|
-
: topInset !== 0;
|
|
189
|
+
const headerTopInsetEnabled = topInset !== 0;
|
|
251
190
|
|
|
252
191
|
const canGoBack = previousDescriptor != null || parentHeaderBack != null;
|
|
253
192
|
const backTitle = previousDescriptor
|
|
@@ -267,6 +206,8 @@ const SceneView = ({
|
|
|
267
206
|
|
|
268
207
|
const isRemovePrevented = preventedRoutes[route.key]?.preventRemove;
|
|
269
208
|
|
|
209
|
+
const animatedHeaderHeight = useAnimatedValue(defaultHeaderHeight);
|
|
210
|
+
|
|
270
211
|
const headerConfig = useHeaderConfigProps({
|
|
271
212
|
...options,
|
|
272
213
|
route,
|
|
@@ -281,195 +222,192 @@ const SceneView = ({
|
|
|
281
222
|
headerHeight,
|
|
282
223
|
headerShown: header !== undefined ? false : headerShown,
|
|
283
224
|
headerTopInsetEnabled,
|
|
284
|
-
headerTransparent,
|
|
285
225
|
headerBack,
|
|
286
226
|
});
|
|
287
227
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
statusBarAnimation={statusBarAnimation}
|
|
325
|
-
statusBarHidden={statusBarHidden}
|
|
326
|
-
statusBarStyle={statusBarStyle}
|
|
327
|
-
statusBarColor={statusBarBackgroundColor}
|
|
328
|
-
statusBarTranslucent={statusBarTranslucent}
|
|
329
|
-
swipeDirection={gestureDirectionOverride}
|
|
330
|
-
transitionDuration={animationDuration}
|
|
331
|
-
onWillAppear={onWillAppear}
|
|
332
|
-
onWillDisappear={onWillDisappear}
|
|
333
|
-
onAppear={onAppear}
|
|
334
|
-
onDisappear={onDisappear}
|
|
335
|
-
onDismissed={onDismissed}
|
|
336
|
-
onGestureCancel={onGestureCancel}
|
|
337
|
-
onSheetDetentChanged={onSheetDetentChanged}
|
|
338
|
-
gestureResponseDistance={gestureResponseDistance}
|
|
339
|
-
nativeBackButtonDismissalEnabled={false} // on Android
|
|
340
|
-
onHeaderBackButtonClicked={onHeaderBackButtonClicked}
|
|
341
|
-
preventNativeDismiss={isRemovePrevented} // on iOS
|
|
342
|
-
scrollEdgeEffects={{
|
|
343
|
-
bottom: scrollEdgeEffects?.bottom ?? 'automatic',
|
|
344
|
-
top: scrollEdgeEffects?.top ?? 'automatic',
|
|
345
|
-
left: scrollEdgeEffects?.left ?? 'automatic',
|
|
346
|
-
right: scrollEdgeEffects?.right ?? 'automatic',
|
|
347
|
-
}}
|
|
348
|
-
onNativeDismissCancelled={onNativeDismissCancelled}
|
|
349
|
-
// Unfortunately, because of the bug that exists on Fabric, where native event drivers
|
|
350
|
-
// for Animated objects are being created after the first notifications about the header height
|
|
351
|
-
// from the native side, `onHeaderHeightChange` event does not notify
|
|
352
|
-
// `animatedHeaderHeight` about initial values on appearing screens at the moment.
|
|
353
|
-
onHeaderHeightChange={Animated.event(
|
|
354
|
-
[
|
|
355
|
-
{
|
|
356
|
-
nativeEvent: {
|
|
357
|
-
headerHeight: rawAnimatedHeaderHeight,
|
|
358
|
-
},
|
|
359
|
-
},
|
|
360
|
-
],
|
|
361
|
-
{
|
|
362
|
-
useNativeDriver,
|
|
363
|
-
listener: (e) => {
|
|
364
|
-
if (hasCustomHeader) {
|
|
365
|
-
// If we have a custom header, don't use native header height
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
|
|
228
|
+
const onHeaderHeightChange = hasCustomHeader
|
|
229
|
+
? // If we have a custom header, don't use native header height
|
|
230
|
+
undefined
|
|
231
|
+
: // On Fabric, there's a bug where native event drivers for Animated objects
|
|
232
|
+
// are created after the first notifications about the header height
|
|
233
|
+
// from the native side, `onHeaderHeightChange` event does not notify
|
|
234
|
+
// `animatedHeaderHeight` about initial values on appearing screens at the moment.
|
|
235
|
+
Animated.event(
|
|
236
|
+
[
|
|
237
|
+
{
|
|
238
|
+
nativeEvent: {
|
|
239
|
+
headerHeight: animatedHeaderHeight,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
{
|
|
244
|
+
useNativeDriver,
|
|
245
|
+
listener: (e) => {
|
|
246
|
+
if (
|
|
247
|
+
e.nativeEvent &&
|
|
248
|
+
typeof e.nativeEvent === 'object' &&
|
|
249
|
+
'headerHeight' in e.nativeEvent &&
|
|
250
|
+
typeof e.nativeEvent.headerHeight === 'number'
|
|
251
|
+
) {
|
|
252
|
+
const headerHeight = e.nativeEvent.headerHeight;
|
|
253
|
+
|
|
254
|
+
// Only debounce if header has large title or search bar
|
|
255
|
+
// As it's the only case where the header height can change frequently
|
|
256
|
+
const doesHeaderAnimate =
|
|
257
|
+
Platform.OS === 'ios' &&
|
|
258
|
+
(options.headerLargeTitleEnabled ||
|
|
259
|
+
options.headerSearchBarOptions);
|
|
260
|
+
|
|
261
|
+
if (doesHeaderAnimate) {
|
|
262
|
+
setHeaderHeightDebounced(headerHeight);
|
|
263
|
+
} else {
|
|
369
264
|
if (
|
|
370
265
|
Platform.OS === 'android' &&
|
|
371
|
-
|
|
266
|
+
headerHeight !== 0 &&
|
|
267
|
+
headerHeight <= ANDROID_DEFAULT_HEADER_HEIGHT
|
|
372
268
|
) {
|
|
373
|
-
// FIXME: On Android,
|
|
374
|
-
//
|
|
375
|
-
|
|
376
|
-
|
|
269
|
+
// FIXME: On Android, events may get delivered out-of-order
|
|
270
|
+
// https://github.com/facebook/react-native/issues/54636
|
|
271
|
+
// We seem to get header height without status bar height first,
|
|
272
|
+
// and then the correct height with status bar height included
|
|
273
|
+
// But due to out-of-order delivery, we may get the correct height first
|
|
274
|
+
// and then the one without status bar height
|
|
275
|
+
// This is hack to include status bar height if it's not already included
|
|
276
|
+
// It only works because header height doesn't change dynamically on Android
|
|
277
|
+
setHeaderHeight(headerHeight + insets.top);
|
|
278
|
+
} else {
|
|
279
|
+
setHeaderHeight(headerHeight);
|
|
377
280
|
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
}
|
|
285
|
+
);
|
|
378
286
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
287
|
+
return (
|
|
288
|
+
<NavigationProvider navigation={navigation} route={route}>
|
|
289
|
+
<ScreenStackItem
|
|
290
|
+
key={route.key}
|
|
291
|
+
screenId={route.key}
|
|
292
|
+
activityState={isPreloaded ? 0 : 2}
|
|
293
|
+
style={StyleSheet.absoluteFill}
|
|
294
|
+
aria-hidden={!focused}
|
|
295
|
+
customAnimationOnSwipe={animationMatchesGesture}
|
|
296
|
+
fullScreenSwipeEnabled={fullScreenGestureEnabled}
|
|
297
|
+
fullScreenSwipeShadowEnabled={fullScreenGestureShadowEnabled}
|
|
298
|
+
freezeOnBlur={freezeOnBlur}
|
|
299
|
+
gestureEnabled={
|
|
300
|
+
Platform.OS === 'android'
|
|
301
|
+
? // This prop enables handling of system back gestures on Android
|
|
302
|
+
// Since we handle them in JS side, we disable this
|
|
303
|
+
false
|
|
304
|
+
: gestureEnabled
|
|
305
|
+
}
|
|
306
|
+
homeIndicatorHidden={autoHideHomeIndicator}
|
|
307
|
+
hideKeyboardOnSwipe={keyboardHandlingEnabled}
|
|
308
|
+
navigationBarHidden={navigationBarHidden}
|
|
309
|
+
replaceAnimation={animationTypeForReplace}
|
|
310
|
+
stackPresentation={presentation === 'card' ? 'push' : presentation}
|
|
311
|
+
stackAnimation={animation}
|
|
312
|
+
screenOrientation={orientation}
|
|
313
|
+
sheetAllowedDetents={sheetAllowedDetents}
|
|
314
|
+
sheetLargestUndimmedDetentIndex={sheetLargestUndimmedDetentIndex}
|
|
315
|
+
sheetGrabberVisible={sheetGrabberVisible}
|
|
316
|
+
sheetInitialDetentIndex={sheetInitialDetentIndex}
|
|
317
|
+
sheetCornerRadius={sheetCornerRadius}
|
|
318
|
+
sheetElevation={sheetElevation}
|
|
319
|
+
sheetExpandsWhenScrolledToEdge={sheetExpandsWhenScrolledToEdge}
|
|
320
|
+
statusBarAnimation={statusBarAnimation}
|
|
321
|
+
statusBarHidden={statusBarHidden}
|
|
322
|
+
statusBarStyle={statusBarStyle}
|
|
323
|
+
swipeDirection={gestureDirection}
|
|
324
|
+
transitionDuration={animationDuration}
|
|
325
|
+
onWillAppear={onWillAppear}
|
|
326
|
+
onWillDisappear={onWillDisappear}
|
|
327
|
+
onAppear={onAppear}
|
|
328
|
+
onDisappear={onDisappear}
|
|
329
|
+
onDismissed={onDismissed}
|
|
330
|
+
onGestureCancel={onGestureCancel}
|
|
331
|
+
onSheetDetentChanged={onSheetDetentChanged}
|
|
332
|
+
gestureResponseDistance={gestureResponseDistance}
|
|
333
|
+
nativeBackButtonDismissalEnabled={false} // on Android
|
|
334
|
+
onHeaderBackButtonClicked={onHeaderBackButtonClicked}
|
|
335
|
+
preventNativeDismiss={isRemovePrevented} // on iOS
|
|
336
|
+
scrollEdgeEffects={{
|
|
337
|
+
bottom: scrollEdgeEffects?.bottom ?? 'automatic',
|
|
338
|
+
top: scrollEdgeEffects?.top ?? 'automatic',
|
|
339
|
+
left: scrollEdgeEffects?.left ?? 'automatic',
|
|
340
|
+
right: scrollEdgeEffects?.right ?? 'automatic',
|
|
341
|
+
}}
|
|
342
|
+
onNativeDismissCancelled={onNativeDismissCancelled}
|
|
343
|
+
onHeaderHeightChange={onHeaderHeightChange}
|
|
344
|
+
contentStyle={[
|
|
345
|
+
presentation !== 'transparentModal' &&
|
|
346
|
+
presentation !== 'containedTransparentModal' && {
|
|
347
|
+
backgroundColor: colors.background,
|
|
348
|
+
},
|
|
349
|
+
contentStyle,
|
|
350
|
+
]}
|
|
351
|
+
headerConfig={headerConfig}
|
|
352
|
+
unstable_sheetFooter={unstable_sheetFooter}
|
|
353
|
+
// When ts-expect-error is added, it affects all the props below it
|
|
354
|
+
// So we keep any props that need it at the end
|
|
355
|
+
// Otherwise invalid props may not be caught by TypeScript
|
|
356
|
+
shouldFreeze={shouldFreeze}
|
|
357
|
+
>
|
|
358
|
+
<AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
|
|
359
|
+
<HeaderHeightContext.Provider
|
|
360
|
+
value={
|
|
361
|
+
headerShown !== false ? headerHeight : (parentHeaderHeight ?? 0)
|
|
403
362
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
// Otherwise invalid props may not be caught by TypeScript
|
|
417
|
-
shouldFreeze={shouldFreeze}
|
|
418
|
-
>
|
|
419
|
-
<AnimatedHeaderHeightContext.Provider value={animatedHeaderHeight}>
|
|
420
|
-
<HeaderHeightContext.Provider
|
|
421
|
-
value={
|
|
422
|
-
headerShown !== false ? headerHeight : (parentHeaderHeight ?? 0)
|
|
423
|
-
}
|
|
424
|
-
>
|
|
425
|
-
{headerBackground != null ? (
|
|
426
|
-
/**
|
|
427
|
-
* To show a custom header background, we render it at the top of the screen below the header
|
|
428
|
-
* The header also needs to be positioned absolutely (with `translucent` style)
|
|
429
|
-
*/
|
|
430
|
-
<View
|
|
431
|
-
style={[
|
|
432
|
-
styles.background,
|
|
433
|
-
headerTransparent ? styles.translucent : null,
|
|
434
|
-
{ height: headerHeight },
|
|
435
|
-
]}
|
|
436
|
-
>
|
|
437
|
-
{headerBackground()}
|
|
438
|
-
</View>
|
|
439
|
-
) : null}
|
|
440
|
-
{header != null && headerShown !== false ? (
|
|
441
|
-
<View
|
|
442
|
-
onLayout={(e) => {
|
|
443
|
-
const headerHeight = e.nativeEvent.layout.height;
|
|
444
|
-
|
|
445
|
-
setHeaderHeight(headerHeight);
|
|
446
|
-
rawAnimatedHeaderHeight.setValue(headerHeight);
|
|
447
|
-
}}
|
|
448
|
-
style={[
|
|
449
|
-
styles.header,
|
|
450
|
-
headerTransparent ? styles.absolute : null,
|
|
451
|
-
]}
|
|
452
|
-
>
|
|
453
|
-
{header({
|
|
454
|
-
back: headerBack,
|
|
455
|
-
options,
|
|
456
|
-
route,
|
|
457
|
-
navigation,
|
|
458
|
-
})}
|
|
459
|
-
</View>
|
|
460
|
-
) : null}
|
|
461
|
-
<HeaderShownContext.Provider
|
|
462
|
-
value={isParentHeaderShown || headerShown !== false}
|
|
363
|
+
>
|
|
364
|
+
{headerBackground != null ? (
|
|
365
|
+
/**
|
|
366
|
+
* To show a custom header background, we render it at the top of the screen below the header
|
|
367
|
+
* The header also needs to be positioned absolutely (with `translucent` style)
|
|
368
|
+
*/
|
|
369
|
+
<View
|
|
370
|
+
style={[
|
|
371
|
+
styles.background,
|
|
372
|
+
headerTransparent ? styles.translucent : null,
|
|
373
|
+
{ height: headerHeight },
|
|
374
|
+
]}
|
|
463
375
|
>
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
376
|
+
{headerBackground()}
|
|
377
|
+
</View>
|
|
378
|
+
) : null}
|
|
379
|
+
{header != null && headerShown !== false ? (
|
|
380
|
+
<View
|
|
381
|
+
onLayout={(e) => {
|
|
382
|
+
const headerHeight = e.nativeEvent.layout.height;
|
|
383
|
+
|
|
384
|
+
animatedHeaderHeight.setValue(headerHeight);
|
|
385
|
+
setHeaderHeight(headerHeight);
|
|
386
|
+
}}
|
|
387
|
+
style={[
|
|
388
|
+
styles.header,
|
|
389
|
+
headerTransparent ? styles.absolute : null,
|
|
390
|
+
]}
|
|
391
|
+
>
|
|
392
|
+
{header({
|
|
393
|
+
back: headerBack,
|
|
394
|
+
options,
|
|
395
|
+
route,
|
|
396
|
+
navigation,
|
|
397
|
+
})}
|
|
398
|
+
</View>
|
|
399
|
+
) : null}
|
|
400
|
+
<HeaderShownContext.Provider
|
|
401
|
+
value={isParentHeaderShown || headerShown !== false}
|
|
402
|
+
>
|
|
403
|
+
<HeaderBackContext.Provider value={headerBack}>
|
|
404
|
+
{render()}
|
|
405
|
+
</HeaderBackContext.Provider>
|
|
406
|
+
</HeaderShownContext.Provider>
|
|
407
|
+
</HeaderHeightContext.Provider>
|
|
408
|
+
</AnimatedHeaderHeightContext.Provider>
|
|
409
|
+
</ScreenStackItem>
|
|
410
|
+
</NavigationProvider>
|
|
473
411
|
);
|
|
474
412
|
};
|
|
475
413
|
|
|
@@ -3,10 +3,12 @@ import {
|
|
|
3
3
|
Header,
|
|
4
4
|
HeaderBackButton,
|
|
5
5
|
HeaderBackContext,
|
|
6
|
-
SafeAreaProviderCompat,
|
|
7
|
-
Screen,
|
|
8
6
|
useHeaderHeight,
|
|
9
7
|
} from '@react-navigation/elements';
|
|
8
|
+
import {
|
|
9
|
+
SafeAreaProviderCompat,
|
|
10
|
+
Screen,
|
|
11
|
+
} from '@react-navigation/elements/internal';
|
|
10
12
|
import {
|
|
11
13
|
type ParamListBase,
|
|
12
14
|
type RouteProp,
|
|
@@ -81,7 +83,6 @@ export function NativeStackView({ state, descriptors, describe }: Props) {
|
|
|
81
83
|
header,
|
|
82
84
|
headerShown,
|
|
83
85
|
headerBackIcon,
|
|
84
|
-
headerBackImageSource,
|
|
85
86
|
headerLeft,
|
|
86
87
|
headerTransparent,
|
|
87
88
|
headerBackTitle,
|
|
@@ -131,14 +132,10 @@ export function NativeStackView({ state, descriptors, describe }: Props) {
|
|
|
131
132
|
label={headerBackTitle ?? label}
|
|
132
133
|
tintColor={tintColor}
|
|
133
134
|
backImage={
|
|
134
|
-
headerBackIcon !== undefined
|
|
135
|
-
headerBackImageSource !== undefined
|
|
135
|
+
headerBackIcon !== undefined
|
|
136
136
|
? () => (
|
|
137
137
|
<Image
|
|
138
|
-
source={
|
|
139
|
-
headerBackIcon?.source ??
|
|
140
|
-
headerBackImageSource
|
|
141
|
-
}
|
|
138
|
+
source={headerBackIcon.source}
|
|
142
139
|
resizeMode="contain"
|
|
143
140
|
tintColor={tintColor}
|
|
144
141
|
style={styles.backImage}
|