@react-navigation/bottom-tabs 7.20.0 → 7.22.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/unstable/Deferred.js +3 -10
- package/lib/module/unstable/Deferred.js.map +1 -1
- package/lib/module/unstable/NativeBottomTabView.native.js +288 -196
- package/lib/module/unstable/NativeBottomTabView.native.js.map +1 -1
- package/lib/module/unstable/NativeScreen/NativeScreen.js +1 -1
- package/lib/module/unstable/NativeScreen/useAnimatedHeaderHeight.js.map +1 -1
- package/lib/module/unstable/NativeScreen/useHeaderConfig.js +11 -11
- package/lib/module/unstable/NativeScreen/useHeaderConfig.js.map +1 -1
- package/lib/module/views/BottomTabBar.js +130 -67
- package/lib/module/views/BottomTabBar.js.map +1 -1
- package/lib/module/views/BottomTabItem.js +4 -4
- package/lib/module/views/BottomTabItem.js.map +1 -1
- package/lib/module/views/BottomTabView.js +78 -57
- package/lib/module/views/BottomTabView.js.map +1 -1
- package/lib/module/views/TabBarIcon.js +6 -2
- package/lib/module/views/TabBarIcon.js.map +1 -1
- package/lib/typescript/src/types.d.ts +17 -4
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/unstable/Deferred.d.ts.map +1 -1
- package/lib/typescript/src/unstable/NativeBottomTabView.d.ts +1 -1
- package/lib/typescript/src/unstable/NativeBottomTabView.d.ts.map +1 -1
- package/lib/typescript/src/unstable/NativeBottomTabView.native.d.ts.map +1 -1
- package/lib/typescript/src/unstable/NativeScreen/types.d.ts +1 -6
- package/lib/typescript/src/unstable/NativeScreen/types.d.ts.map +1 -1
- package/lib/typescript/src/unstable/NativeScreen/useAnimatedHeaderHeight.d.ts.map +1 -1
- package/lib/typescript/src/unstable/NativeScreen/useHeaderConfig.d.ts.map +1 -1
- package/lib/typescript/src/unstable/types.d.ts +125 -5
- package/lib/typescript/src/unstable/types.d.ts.map +1 -1
- package/lib/typescript/src/views/BottomTabBar.d.ts +1 -1
- package/lib/typescript/src/views/BottomTabBar.d.ts.map +1 -1
- package/lib/typescript/src/views/BottomTabItem.d.ts +5 -1
- package/lib/typescript/src/views/BottomTabItem.d.ts.map +1 -1
- package/lib/typescript/src/views/BottomTabView.d.ts.map +1 -1
- package/lib/typescript/src/views/TabBarIcon.d.ts +2 -1
- package/lib/typescript/src/views/TabBarIcon.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/types.tsx +33 -4
- package/src/unstable/Deferred.tsx +3 -11
- package/src/unstable/NativeBottomTabView.native.tsx +356 -218
- package/src/unstable/NativeBottomTabView.tsx +3 -3
- package/src/unstable/NativeScreen/NativeScreen.tsx +1 -1
- package/src/unstable/NativeScreen/types.ts +3 -6
- package/src/unstable/NativeScreen/useAnimatedHeaderHeight.tsx +5 -3
- package/src/unstable/NativeScreen/useHeaderConfig.tsx +8 -14
- package/src/unstable/types.tsx +134 -8
- package/src/views/BottomTabBar.tsx +176 -86
- package/src/views/BottomTabItem.tsx +11 -2
- package/src/views/BottomTabView.tsx +100 -66
- package/src/views/TabBarIcon.tsx +9 -2
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Screen,
|
|
6
6
|
} from '@react-navigation/elements';
|
|
7
7
|
import {
|
|
8
|
+
type NavigationRoute,
|
|
8
9
|
type ParamListBase,
|
|
9
10
|
StackActions,
|
|
10
11
|
type TabNavigationState,
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
} from '../TransitionConfigs/TransitionPresets';
|
|
20
21
|
import type {
|
|
21
22
|
BottomTabBarProps,
|
|
23
|
+
BottomTabDescriptor,
|
|
22
24
|
BottomTabDescriptorMap,
|
|
23
25
|
BottomTabHeaderProps,
|
|
24
26
|
BottomTabNavigationConfig,
|
|
@@ -283,12 +285,7 @@ export function BottomTabView(props: Props) {
|
|
|
283
285
|
>
|
|
284
286
|
{routes.map((route, index) => {
|
|
285
287
|
const descriptor = descriptors[route.key];
|
|
286
|
-
const {
|
|
287
|
-
lazy = true,
|
|
288
|
-
animation = 'none',
|
|
289
|
-
sceneStyleInterpolator = NAMED_TRANSITIONS_PRESETS[animation]
|
|
290
|
-
.sceneStyleInterpolator,
|
|
291
|
-
} = descriptor.options;
|
|
288
|
+
const { lazy = true } = descriptor.options;
|
|
292
289
|
const isFocused = state.index === index;
|
|
293
290
|
const isPreloaded = state.preloadedRouteKeys.includes(route.key);
|
|
294
291
|
|
|
@@ -302,73 +299,23 @@ export function BottomTabView(props: Props) {
|
|
|
302
299
|
return null;
|
|
303
300
|
}
|
|
304
301
|
|
|
305
|
-
const {
|
|
306
|
-
freezeOnBlur,
|
|
307
|
-
header = ({ layout, options }: BottomTabHeaderProps) => (
|
|
308
|
-
<Header
|
|
309
|
-
{...options}
|
|
310
|
-
layout={layout}
|
|
311
|
-
title={getHeaderTitle(options, route.name)}
|
|
312
|
-
/>
|
|
313
|
-
),
|
|
314
|
-
headerShown,
|
|
315
|
-
headerStatusBarHeight,
|
|
316
|
-
headerTransparent,
|
|
317
|
-
sceneStyle: customSceneStyle,
|
|
318
|
-
} = descriptor.options;
|
|
319
|
-
|
|
320
|
-
const { sceneStyle } =
|
|
321
|
-
sceneStyleInterpolator?.({
|
|
322
|
-
current: {
|
|
323
|
-
progress: tabAnims[route.key],
|
|
324
|
-
},
|
|
325
|
-
}) ?? {};
|
|
326
|
-
|
|
327
|
-
const animationEnabled = hasAnimation(descriptor.options);
|
|
328
302
|
const isAnimatingRoute =
|
|
329
303
|
lastUpdate.animating &&
|
|
330
304
|
(lastUpdate.previous === route.key ||
|
|
331
305
|
lastUpdate.current === route.key);
|
|
332
306
|
|
|
333
|
-
const activityState = isFocused
|
|
334
|
-
? STATE_ON_TOP // the screen is on top after the transition
|
|
335
|
-
: animationEnabled && isAnimatingRoute
|
|
336
|
-
? STATE_TRANSITIONING_OR_BELOW_TOP // screen visible during transition
|
|
337
|
-
: STATE_INACTIVE;
|
|
338
|
-
|
|
339
307
|
return (
|
|
340
|
-
<
|
|
308
|
+
<TabScene
|
|
341
309
|
key={route.key}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
>
|
|
352
|
-
<Screen
|
|
353
|
-
focused={isFocused}
|
|
354
|
-
route={descriptor.route}
|
|
355
|
-
navigation={descriptor.navigation}
|
|
356
|
-
headerShown={headerShown}
|
|
357
|
-
headerStatusBarHeight={headerStatusBarHeight}
|
|
358
|
-
headerTransparent={headerTransparent}
|
|
359
|
-
header={header({
|
|
360
|
-
layout: dimensions,
|
|
361
|
-
route: descriptor.route,
|
|
362
|
-
navigation:
|
|
363
|
-
descriptor.navigation as BottomTabNavigationProp<ParamListBase>,
|
|
364
|
-
options: descriptor.options,
|
|
365
|
-
})}
|
|
366
|
-
style={[customSceneStyle, animationEnabled && sceneStyle]}
|
|
367
|
-
>
|
|
368
|
-
{descriptor.render()}
|
|
369
|
-
</Screen>
|
|
370
|
-
</BottomTabBarHeightContext.Provider>
|
|
371
|
-
</MaybeScreen>
|
|
310
|
+
route={route}
|
|
311
|
+
descriptor={descriptor}
|
|
312
|
+
isFocused={isFocused}
|
|
313
|
+
isPreloaded={isPreloaded}
|
|
314
|
+
isAnimatingRoute={isAnimatingRoute}
|
|
315
|
+
tabAnimation={tabAnims[route.key]}
|
|
316
|
+
tabBarHeight={tabBarPosition === 'bottom' ? tabBarHeight : 0}
|
|
317
|
+
detachInactiveScreens={detachInactiveScreens}
|
|
318
|
+
/>
|
|
372
319
|
);
|
|
373
320
|
})}
|
|
374
321
|
</MaybeScreenContainer>
|
|
@@ -379,6 +326,93 @@ export function BottomTabView(props: Props) {
|
|
|
379
326
|
);
|
|
380
327
|
}
|
|
381
328
|
|
|
329
|
+
type TabSceneProps = {
|
|
330
|
+
route: NavigationRoute<ParamListBase, string>;
|
|
331
|
+
descriptor: BottomTabDescriptor;
|
|
332
|
+
isFocused: boolean;
|
|
333
|
+
isPreloaded: boolean;
|
|
334
|
+
isAnimatingRoute: boolean;
|
|
335
|
+
tabAnimation: Animated.Value;
|
|
336
|
+
tabBarHeight: number;
|
|
337
|
+
detachInactiveScreens: boolean;
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
const TabScene = React.memo(function TabScene({
|
|
341
|
+
route,
|
|
342
|
+
descriptor,
|
|
343
|
+
isFocused,
|
|
344
|
+
isPreloaded,
|
|
345
|
+
isAnimatingRoute,
|
|
346
|
+
tabAnimation,
|
|
347
|
+
tabBarHeight,
|
|
348
|
+
detachInactiveScreens,
|
|
349
|
+
}: TabSceneProps) {
|
|
350
|
+
const {
|
|
351
|
+
animation = 'none',
|
|
352
|
+
sceneStyleInterpolator = NAMED_TRANSITIONS_PRESETS[animation]
|
|
353
|
+
.sceneStyleInterpolator,
|
|
354
|
+
freezeOnBlur,
|
|
355
|
+
header = ({ layout, options }: BottomTabHeaderProps) => (
|
|
356
|
+
<Header
|
|
357
|
+
{...options}
|
|
358
|
+
layout={layout}
|
|
359
|
+
title={getHeaderTitle(options, route.name)}
|
|
360
|
+
/>
|
|
361
|
+
),
|
|
362
|
+
headerShown,
|
|
363
|
+
headerStatusBarHeight,
|
|
364
|
+
headerTransparent,
|
|
365
|
+
sceneStyle: customSceneStyle,
|
|
366
|
+
} = descriptor.options;
|
|
367
|
+
|
|
368
|
+
const { sceneStyle } =
|
|
369
|
+
sceneStyleInterpolator?.({
|
|
370
|
+
current: {
|
|
371
|
+
progress: tabAnimation,
|
|
372
|
+
},
|
|
373
|
+
}) ?? {};
|
|
374
|
+
|
|
375
|
+
const animationEnabled = hasAnimation(descriptor.options);
|
|
376
|
+
|
|
377
|
+
const activityState = isFocused
|
|
378
|
+
? STATE_ON_TOP // the screen is on top after the transition
|
|
379
|
+
: animationEnabled && isAnimatingRoute
|
|
380
|
+
? STATE_TRANSITIONING_OR_BELOW_TOP // screen visible during transition
|
|
381
|
+
: STATE_INACTIVE;
|
|
382
|
+
|
|
383
|
+
return (
|
|
384
|
+
<MaybeScreen
|
|
385
|
+
style={[StyleSheet.absoluteFill, { zIndex: isFocused ? 0 : -1 }]}
|
|
386
|
+
active={activityState}
|
|
387
|
+
enabled={detachInactiveScreens}
|
|
388
|
+
freezeOnBlur={freezeOnBlur}
|
|
389
|
+
shouldFreeze={activityState === STATE_INACTIVE && !isPreloaded}
|
|
390
|
+
pointerEvents={isFocused ? 'box-none' : 'none'}
|
|
391
|
+
>
|
|
392
|
+
<BottomTabBarHeightContext.Provider value={tabBarHeight}>
|
|
393
|
+
<Screen
|
|
394
|
+
focused={isFocused}
|
|
395
|
+
route={descriptor.route}
|
|
396
|
+
navigation={descriptor.navigation}
|
|
397
|
+
headerShown={headerShown}
|
|
398
|
+
headerStatusBarHeight={headerStatusBarHeight}
|
|
399
|
+
headerTransparent={headerTransparent}
|
|
400
|
+
header={header({
|
|
401
|
+
layout: SafeAreaProviderCompat.initialMetrics.frame,
|
|
402
|
+
route: descriptor.route,
|
|
403
|
+
navigation:
|
|
404
|
+
descriptor.navigation as BottomTabNavigationProp<ParamListBase>,
|
|
405
|
+
options: descriptor.options,
|
|
406
|
+
})}
|
|
407
|
+
style={[customSceneStyle, animationEnabled && sceneStyle]}
|
|
408
|
+
>
|
|
409
|
+
{descriptor.render()}
|
|
410
|
+
</Screen>
|
|
411
|
+
</BottomTabBarHeightContext.Provider>
|
|
412
|
+
</MaybeScreen>
|
|
413
|
+
);
|
|
414
|
+
});
|
|
415
|
+
|
|
382
416
|
const styles = StyleSheet.create({
|
|
383
417
|
screens: {
|
|
384
418
|
flex: 1,
|
package/src/views/TabBarIcon.tsx
CHANGED
|
@@ -13,6 +13,7 @@ type Props = {
|
|
|
13
13
|
route: Route<string>;
|
|
14
14
|
variant: 'uikit' | 'material';
|
|
15
15
|
size: 'compact' | 'regular';
|
|
16
|
+
iconSize?: number;
|
|
16
17
|
badge?: string | number;
|
|
17
18
|
badgeStyle?: StyleProp<TextStyle>;
|
|
18
19
|
activeOpacity: number;
|
|
@@ -44,6 +45,7 @@ export function TabBarIcon({
|
|
|
44
45
|
route: _,
|
|
45
46
|
variant,
|
|
46
47
|
size,
|
|
48
|
+
iconSize: iconSizeOverride,
|
|
47
49
|
badge,
|
|
48
50
|
badgeStyle,
|
|
49
51
|
activeOpacity,
|
|
@@ -55,11 +57,12 @@ export function TabBarIcon({
|
|
|
55
57
|
style,
|
|
56
58
|
}: Props) {
|
|
57
59
|
const iconSize =
|
|
58
|
-
|
|
60
|
+
iconSizeOverride ??
|
|
61
|
+
(variant === 'material'
|
|
59
62
|
? ICON_SIZE_MATERIAL
|
|
60
63
|
: size === 'compact'
|
|
61
64
|
? ICON_SIZE_ROUND_COMPACT
|
|
62
|
-
: ICON_SIZE_ROUND;
|
|
65
|
+
: ICON_SIZE_ROUND);
|
|
63
66
|
|
|
64
67
|
// We render the icon twice at the same position on top of each other:
|
|
65
68
|
// active and inactive one, so we can fade between them.
|
|
@@ -71,6 +74,10 @@ export function TabBarIcon({
|
|
|
71
74
|
: size === 'compact'
|
|
72
75
|
? styles.wrapperUikitCompact
|
|
73
76
|
: styles.wrapperUikit,
|
|
77
|
+
iconSizeOverride != null && {
|
|
78
|
+
width: iconSizeOverride,
|
|
79
|
+
height: iconSizeOverride,
|
|
80
|
+
},
|
|
74
81
|
style,
|
|
75
82
|
]}
|
|
76
83
|
>
|