@amazon-devices/react-navigation__react-native-tab-view 7.0.9000000000 → 8.0.9000000000-rn-83
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 +2 -646
- package/SystemBundles/adbcd18d13758315355457809fdb5587894f9f3c2c9838769a5a47bf860685c8.bundle +8564 -0
- package/SystemBundles/adbcd18d13758315355457809fdb5587894f9f3c2c9838769a5a47bf860685c8.map +3217 -0
- package/SystemModules/amzn__react-navigation__react-native-tab-view-8.modules.txt +12 -0
- package/SystemModules/amzn__react-navigation__react-native-tab-view-8.private.modules.txt +63 -0
- package/SystemModules/keplerscript-system-bundle-config.json +4 -4
- package/kepler-compatibility.json +2 -2
- package/lib/module/Pager.android.js +3 -1
- package/lib/module/Pager.android.js.map +1 -1
- package/lib/module/Pager.ios.js +3 -1
- package/lib/module/Pager.ios.js.map +1 -1
- package/lib/module/Pager.js +3 -1
- package/lib/module/Pager.js.map +1 -1
- package/lib/module/PagerViewAdapter.js +29 -22
- package/lib/module/PagerViewAdapter.js.map +1 -1
- package/lib/module/PanResponderAdapter.js +46 -32
- package/lib/module/PanResponderAdapter.js.map +1 -1
- package/lib/module/PlatformPressable.js +38 -12
- package/lib/module/PlatformPressable.js.map +1 -1
- package/lib/module/SceneMap.js +7 -4
- package/lib/module/SceneMap.js.map +1 -1
- package/lib/module/SceneView.js +16 -14
- package/lib/module/SceneView.js.map +1 -1
- package/lib/module/TabBar.js +232 -156
- package/lib/module/TabBar.js.map +1 -1
- package/lib/module/TabBarIndicator.js +47 -26
- package/lib/module/TabBarIndicator.js.map +1 -1
- package/lib/module/TabBarItem.js +106 -107
- package/lib/module/TabBarItem.js.map +1 -1
- package/lib/module/TabBarItemLabel.js +33 -0
- package/lib/module/TabBarItemLabel.js.map +1 -0
- package/lib/module/TabView.js +91 -63
- package/lib/module/TabView.js.map +1 -1
- package/lib/module/index.js +7 -5
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -1
- package/lib/module/useAnimatedValue.js +4 -2
- package/lib/module/useAnimatedValue.js.map +1 -1
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/Pager.android.d.ts +1 -1
- package/lib/typescript/src/Pager.android.d.ts.map +1 -1
- package/lib/typescript/src/Pager.d.ts +1 -1
- package/lib/typescript/src/Pager.d.ts.map +1 -1
- package/lib/typescript/src/Pager.ios.d.ts +1 -1
- package/lib/typescript/src/Pager.ios.d.ts.map +1 -1
- package/lib/typescript/src/PagerViewAdapter.d.ts +4 -1
- package/lib/typescript/src/PagerViewAdapter.d.ts.map +1 -1
- package/lib/typescript/src/PanResponderAdapter.d.ts +4 -1
- package/lib/typescript/src/PanResponderAdapter.d.ts.map +1 -1
- package/lib/typescript/src/PlatformPressable.d.ts +6 -8
- package/lib/typescript/src/PlatformPressable.d.ts.map +1 -1
- package/lib/typescript/src/SceneMap.d.ts +2 -2
- package/lib/typescript/src/SceneMap.d.ts.map +1 -1
- package/lib/typescript/src/SceneView.d.ts +2 -2
- package/lib/typescript/src/SceneView.d.ts.map +1 -1
- package/lib/typescript/src/TabBar.d.ts +7 -19
- package/lib/typescript/src/TabBar.d.ts.map +1 -1
- package/lib/typescript/src/TabBarIndicator.d.ts +8 -6
- package/lib/typescript/src/TabBarIndicator.d.ts.map +1 -1
- package/lib/typescript/src/TabBarItem.d.ts +4 -22
- package/lib/typescript/src/TabBarItem.d.ts.map +1 -1
- package/lib/typescript/src/TabBarItemLabel.d.ts +11 -0
- package/lib/typescript/src/TabBarItemLabel.d.ts.map +1 -0
- package/lib/typescript/src/TabView.d.ts +14 -8
- package/lib/typescript/src/TabView.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +6 -6
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +29 -1
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useAnimatedValue.d.ts +1 -1
- package/lib/typescript/src/useAnimatedValue.d.ts.map +1 -1
- package/oss-attribution/attribution.txt +0 -0
- package/oss-attribution/licenseInfos.json +1 -0
- package/package.json +93 -1
- package/src/Pager.android.tsx +1 -1
- package/src/Pager.ios.tsx +1 -1
- package/src/Pager.tsx +1 -1
- package/src/PagerViewAdapter.tsx +26 -21
- package/src/PanResponderAdapter.tsx +32 -28
- package/src/PlatformPressable.tsx +59 -10
- package/src/SceneMap.tsx +3 -3
- package/src/SceneView.tsx +6 -7
- package/src/TabBar.tsx +282 -193
- package/src/TabBarIndicator.tsx +65 -28
- package/src/TabBarItem.tsx +119 -130
- package/src/TabBarItemLabel.tsx +42 -0
- package/src/TabView.tsx +59 -16
- package/src/index.tsx +11 -6
- package/src/types.tsx +29 -1
- package/src/useAnimatedValue.tsx +2 -2
- package/SystemBundles/df77923df6c02233e2967296227684cd416c9a363cc8fc6fd81f573829bc74e9.bundle +0 -13783
- package/SystemBundles/df77923df6c02233e2967296227684cd416c9a363cc8fc6fd81f573829bc74e9.map +0 -4787
- package/SystemModules/amzn__react-navigation__react-native-tab-view-7.modules.txt +0 -41
- package/SystemModules/amzn__react-navigation__react-native-tab-view-7.private.modules.txt +0 -96
- package/THIRD_PARTY_NOTICES.txt +0 -24
- package/lib/commonjs/Pager.android.js +0 -14
- package/lib/commonjs/Pager.android.js.map +0 -1
- package/lib/commonjs/Pager.ios.js +0 -14
- package/lib/commonjs/Pager.ios.js.map +0 -1
- package/lib/commonjs/Pager.js +0 -14
- package/lib/commonjs/Pager.js.map +0 -1
- package/lib/commonjs/PagerViewAdapter.js +0 -132
- package/lib/commonjs/PagerViewAdapter.js.map +0 -1
- package/lib/commonjs/PanResponderAdapter.js +0 -204
- package/lib/commonjs/PanResponderAdapter.js.map +0 -1
- package/lib/commonjs/PlatformPressable.js +0 -43
- package/lib/commonjs/PlatformPressable.js.map +0 -1
- package/lib/commonjs/SceneMap.js +0 -29
- package/lib/commonjs/SceneMap.js.map +0 -1
- package/lib/commonjs/SceneView.js +0 -78
- package/lib/commonjs/SceneView.js.map +0 -1
- package/lib/commonjs/TabBar.js +0 -405
- package/lib/commonjs/TabBar.js.map +0 -1
- package/lib/commonjs/TabBarIndicator.js +0 -110
- package/lib/commonjs/TabBarIndicator.js.map +0 -1
- package/lib/commonjs/TabBarItem.js +0 -227
- package/lib/commonjs/TabBarItem.js.map +0 -1
- package/lib/commonjs/TabView.js +0 -122
- package/lib/commonjs/TabView.js.map +0 -1
- package/lib/commonjs/index.js +0 -42
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/types.js +0 -6
- package/lib/commonjs/types.js.map +0 -1
- package/lib/commonjs/useAnimatedValue.js +0 -18
- package/lib/commonjs/useAnimatedValue.js.map +0 -1
package/src/TabBarIndicator.tsx
CHANGED
|
@@ -1,40 +1,63 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
|
-
DimensionValue,
|
|
5
4
|
Easing,
|
|
6
|
-
I18nManager,
|
|
7
5
|
Platform,
|
|
8
|
-
StyleProp,
|
|
6
|
+
type StyleProp,
|
|
9
7
|
StyleSheet,
|
|
10
|
-
ViewStyle,
|
|
8
|
+
type ViewStyle,
|
|
11
9
|
} from 'react-native';
|
|
12
10
|
|
|
13
|
-
import type {
|
|
14
|
-
|
|
11
|
+
import type {
|
|
12
|
+
LocaleDirection,
|
|
13
|
+
NavigationState,
|
|
14
|
+
Route,
|
|
15
|
+
SceneRendererProps,
|
|
16
|
+
} from './types';
|
|
17
|
+
import { useAnimatedValue } from './useAnimatedValue';
|
|
15
18
|
|
|
16
19
|
export type GetTabWidth = (index: number) => number;
|
|
17
20
|
|
|
18
21
|
export type Props<T extends Route> = SceneRendererProps & {
|
|
19
22
|
navigationState: NavigationState<T>;
|
|
20
|
-
width:
|
|
21
|
-
style?: StyleProp<ViewStyle>;
|
|
23
|
+
width: 'auto' | `${number}%` | number;
|
|
22
24
|
getTabWidth: GetTabWidth;
|
|
25
|
+
direction: LocaleDirection;
|
|
26
|
+
style?: StyleProp<ViewStyle>;
|
|
23
27
|
gap?: number;
|
|
28
|
+
children?: React.ReactNode;
|
|
24
29
|
};
|
|
25
30
|
|
|
31
|
+
const useNativeDriver = Platform.OS !== 'web';
|
|
32
|
+
|
|
26
33
|
const getTranslateX = (
|
|
27
34
|
position: Animated.AnimatedInterpolation<number>,
|
|
28
35
|
routes: Route[],
|
|
29
36
|
getTabWidth: GetTabWidth,
|
|
30
|
-
|
|
37
|
+
direction: LocaleDirection,
|
|
38
|
+
gap?: number,
|
|
39
|
+
width?: number | string
|
|
31
40
|
) => {
|
|
32
41
|
const inputRange = routes.map((_, i) => i);
|
|
33
42
|
|
|
34
43
|
// every index contains widths at all previous indices
|
|
35
44
|
const outputRange = routes.reduce<number[]>((acc, _, i) => {
|
|
36
|
-
if (
|
|
37
|
-
|
|
45
|
+
if (typeof width === 'number') {
|
|
46
|
+
if (i === 0) return [getTabWidth(i) / 2 - width / 2];
|
|
47
|
+
|
|
48
|
+
let sumTabWidth = 0;
|
|
49
|
+
for (let j = 0; j < i; j++) {
|
|
50
|
+
sumTabWidth += getTabWidth(j);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return [
|
|
54
|
+
...acc,
|
|
55
|
+
sumTabWidth + getTabWidth(i) / 2 + (gap ? gap * i : 0) - width / 2,
|
|
56
|
+
];
|
|
57
|
+
} else {
|
|
58
|
+
if (i === 0) return [0];
|
|
59
|
+
return [...acc, acc[i - 1] + getTabWidth(i - 1) + (gap ?? 0)];
|
|
60
|
+
}
|
|
38
61
|
}, []);
|
|
39
62
|
|
|
40
63
|
const translateX = position.interpolate({
|
|
@@ -43,17 +66,19 @@ const getTranslateX = (
|
|
|
43
66
|
extrapolate: 'clamp',
|
|
44
67
|
});
|
|
45
68
|
|
|
46
|
-
return Animated.multiply(translateX,
|
|
69
|
+
return Animated.multiply(translateX, direction === 'rtl' ? -1 : 1);
|
|
47
70
|
};
|
|
48
71
|
|
|
49
|
-
export
|
|
72
|
+
export function TabBarIndicator<T extends Route>({
|
|
50
73
|
getTabWidth,
|
|
51
74
|
layout,
|
|
52
75
|
navigationState,
|
|
53
76
|
position,
|
|
54
77
|
width,
|
|
78
|
+
direction,
|
|
55
79
|
gap,
|
|
56
80
|
style,
|
|
81
|
+
children,
|
|
57
82
|
}: Props<T>) {
|
|
58
83
|
const isIndicatorShown = React.useRef(false);
|
|
59
84
|
const isWidthDynamic = width === 'auto';
|
|
@@ -81,7 +106,7 @@ export default function TabBarIndicator<T extends Route>({
|
|
|
81
106
|
toValue: 1,
|
|
82
107
|
duration: 150,
|
|
83
108
|
easing: Easing.in(Easing.linear),
|
|
84
|
-
useNativeDriver
|
|
109
|
+
useNativeDriver,
|
|
85
110
|
}).start();
|
|
86
111
|
}
|
|
87
112
|
};
|
|
@@ -97,7 +122,9 @@ export default function TabBarIndicator<T extends Route>({
|
|
|
97
122
|
|
|
98
123
|
if (layout.width) {
|
|
99
124
|
const translateX =
|
|
100
|
-
routes.length > 1
|
|
125
|
+
routes.length > 1
|
|
126
|
+
? getTranslateX(position, routes, getTabWidth, direction, gap, width)
|
|
127
|
+
: 0;
|
|
101
128
|
|
|
102
129
|
transform.push({ translateX });
|
|
103
130
|
}
|
|
@@ -117,7 +144,23 @@ export default function TabBarIndicator<T extends Route>({
|
|
|
117
144
|
})
|
|
118
145
|
: outputRange[0],
|
|
119
146
|
},
|
|
120
|
-
{ translateX: 0.5 }
|
|
147
|
+
{ translateX: direction === 'rtl' ? -0.5 : 0.5 }
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const styleList: StyleProp<ViewStyle> = [];
|
|
152
|
+
|
|
153
|
+
// scaleX doesn't work properly on chrome and opera for linux and android
|
|
154
|
+
if (Platform.OS === 'web' && width === 'auto') {
|
|
155
|
+
styleList.push(
|
|
156
|
+
{ width: transform[1].scaleX },
|
|
157
|
+
{ left: transform[0].translateX }
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
styleList.push(
|
|
161
|
+
{ width: width === 'auto' ? 1 : width },
|
|
162
|
+
{ start: `${(100 / routes.length) * navigationState.index}%` },
|
|
163
|
+
{ transform }
|
|
121
164
|
);
|
|
122
165
|
}
|
|
123
166
|
|
|
@@ -125,19 +168,13 @@ export default function TabBarIndicator<T extends Route>({
|
|
|
125
168
|
<Animated.View
|
|
126
169
|
style={[
|
|
127
170
|
styles.indicator,
|
|
128
|
-
|
|
129
|
-
// If layout is not available, use `left` property for positioning the indicator
|
|
130
|
-
// This avoids rendering delay until we are able to calculate translateX
|
|
131
|
-
// If platform is macos use `left` property as `transform` is broken at the moment.
|
|
132
|
-
// See: https://github.com/microsoft/react-native-macos/issues/280
|
|
133
|
-
layout.width && Platform.OS !== 'macos'
|
|
134
|
-
? { left: 0 }
|
|
135
|
-
: { left: `${(100 / routes.length) * navigationState.index}%` },
|
|
136
|
-
{ transform },
|
|
171
|
+
styleList,
|
|
137
172
|
width === 'auto' ? { opacity: opacity } : null,
|
|
138
173
|
style,
|
|
139
174
|
]}
|
|
140
|
-
|
|
175
|
+
>
|
|
176
|
+
{children}
|
|
177
|
+
</Animated.View>
|
|
141
178
|
);
|
|
142
179
|
}
|
|
143
180
|
|
|
@@ -145,9 +182,9 @@ const styles = StyleSheet.create({
|
|
|
145
182
|
indicator: {
|
|
146
183
|
backgroundColor: '#ffeb3b',
|
|
147
184
|
position: 'absolute',
|
|
148
|
-
|
|
185
|
+
start: 0,
|
|
149
186
|
bottom: 0,
|
|
150
|
-
|
|
187
|
+
end: 0,
|
|
151
188
|
height: 2,
|
|
152
189
|
},
|
|
153
190
|
});
|
package/src/TabBarItem.tsx
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
|
-
LayoutChangeEvent,
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
type LayoutChangeEvent,
|
|
5
|
+
Platform,
|
|
6
|
+
type PressableAndroidRippleConfig,
|
|
7
|
+
type StyleProp,
|
|
7
8
|
StyleSheet,
|
|
8
|
-
TextStyle,
|
|
9
9
|
View,
|
|
10
|
-
ViewStyle,
|
|
10
|
+
type ViewStyle,
|
|
11
11
|
} from 'react-native';
|
|
12
12
|
import useLatestCallback from 'use-latest-callback';
|
|
13
13
|
|
|
14
|
-
import PlatformPressable from './PlatformPressable';
|
|
15
|
-
import
|
|
14
|
+
import { PlatformPressable } from './PlatformPressable';
|
|
15
|
+
import { TabBarItemLabel } from './TabBarItemLabel';
|
|
16
|
+
import type { NavigationState, Route, TabDescriptor } from './types';
|
|
16
17
|
|
|
17
|
-
export type Props<T extends Route> = {
|
|
18
|
+
export type Props<T extends Route> = TabDescriptor<T> & {
|
|
18
19
|
position: Animated.AnimatedInterpolation<number>;
|
|
19
20
|
route: T;
|
|
20
21
|
navigationState: NavigationState<T>;
|
|
@@ -22,32 +23,17 @@ export type Props<T extends Route> = {
|
|
|
22
23
|
inactiveColor?: string;
|
|
23
24
|
pressColor?: string;
|
|
24
25
|
pressOpacity?: number;
|
|
25
|
-
getLabelText: (scene: Scene<T>) => string | undefined;
|
|
26
|
-
getAccessible: (scene: Scene<T>) => boolean | undefined;
|
|
27
|
-
getAccessibilityLabel: (scene: Scene<T>) => string | undefined;
|
|
28
|
-
getTestID: (scene: Scene<T>) => string | undefined;
|
|
29
|
-
renderLabel?: (scene: {
|
|
30
|
-
route: T;
|
|
31
|
-
focused: boolean;
|
|
32
|
-
color: string;
|
|
33
|
-
}) => React.ReactNode;
|
|
34
|
-
renderIcon?: (scene: {
|
|
35
|
-
route: T;
|
|
36
|
-
focused: boolean;
|
|
37
|
-
color: string;
|
|
38
|
-
}) => React.ReactNode;
|
|
39
|
-
renderBadge?: (scene: Scene<T>) => React.ReactNode;
|
|
40
26
|
onLayout?: (event: LayoutChangeEvent) => void;
|
|
41
27
|
onPress: () => void;
|
|
42
28
|
onLongPress: () => void;
|
|
43
29
|
defaultTabWidth?: number;
|
|
44
|
-
labelStyle?: StyleProp<TextStyle>;
|
|
45
30
|
style: StyleProp<ViewStyle>;
|
|
46
31
|
android_ripple?: PressableAndroidRippleConfig;
|
|
47
32
|
};
|
|
48
33
|
|
|
49
34
|
const DEFAULT_ACTIVE_COLOR = 'rgba(255, 255, 255, 1)';
|
|
50
35
|
const DEFAULT_INACTIVE_COLOR = 'rgba(255, 255, 255, 0.7)';
|
|
36
|
+
const ICON_SIZE = 24;
|
|
51
37
|
|
|
52
38
|
const getActiveOpacity = (
|
|
53
39
|
position: Animated.AnimatedInterpolation<number>,
|
|
@@ -85,23 +71,29 @@ const getInactiveOpacity = (
|
|
|
85
71
|
|
|
86
72
|
type TabBarItemInternalProps<T extends Route> = Omit<
|
|
87
73
|
Props<T>,
|
|
88
|
-
'navigationState'
|
|
74
|
+
| 'navigationState'
|
|
75
|
+
| 'getAccessibilityLabel'
|
|
76
|
+
| 'getLabelText'
|
|
77
|
+
| 'getTestID'
|
|
78
|
+
| 'getAccessible'
|
|
79
|
+
| 'options'
|
|
89
80
|
> & {
|
|
90
81
|
isFocused: boolean;
|
|
91
82
|
index: number;
|
|
92
83
|
routesLength: number;
|
|
93
|
-
}
|
|
84
|
+
} & TabDescriptor<T>;
|
|
85
|
+
|
|
86
|
+
const ANDROID_RIPPLE_DEFAULT = { borderless: true };
|
|
94
87
|
|
|
95
88
|
const TabBarItemInternal = <T extends Route>({
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
89
|
+
accessibilityLabel,
|
|
90
|
+
accessible,
|
|
91
|
+
label: customlabel,
|
|
92
|
+
testID,
|
|
100
93
|
onLongPress,
|
|
101
94
|
onPress,
|
|
102
95
|
isFocused,
|
|
103
96
|
position,
|
|
104
|
-
route,
|
|
105
97
|
style,
|
|
106
98
|
inactiveColor: inactiveColorCustom,
|
|
107
99
|
activeColor: activeColorCustom,
|
|
@@ -110,12 +102,15 @@ const TabBarItemInternal = <T extends Route>({
|
|
|
110
102
|
index: tabIndex,
|
|
111
103
|
pressColor,
|
|
112
104
|
pressOpacity,
|
|
113
|
-
renderBadge,
|
|
114
|
-
renderIcon,
|
|
115
105
|
defaultTabWidth,
|
|
106
|
+
icon: customIcon,
|
|
107
|
+
badge: customBadge,
|
|
108
|
+
href,
|
|
109
|
+
labelText,
|
|
116
110
|
routesLength,
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
android_ripple = ANDROID_RIPPLE_DEFAULT,
|
|
112
|
+
labelAllowFontScaling,
|
|
113
|
+
route,
|
|
119
114
|
}: TabBarItemInternalProps<T>) => {
|
|
120
115
|
const labelColorFromStyle = StyleSheet.flatten(labelStyle || {}).color;
|
|
121
116
|
|
|
@@ -123,98 +118,88 @@ const TabBarItemInternal = <T extends Route>({
|
|
|
123
118
|
activeColorCustom !== undefined
|
|
124
119
|
? activeColorCustom
|
|
125
120
|
: typeof labelColorFromStyle === 'string'
|
|
126
|
-
|
|
127
|
-
|
|
121
|
+
? labelColorFromStyle
|
|
122
|
+
: DEFAULT_ACTIVE_COLOR;
|
|
128
123
|
const inactiveColor =
|
|
129
124
|
inactiveColorCustom !== undefined
|
|
130
125
|
? inactiveColorCustom
|
|
131
126
|
: typeof labelColorFromStyle === 'string'
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
? labelColorFromStyle
|
|
128
|
+
: DEFAULT_INACTIVE_COLOR;
|
|
134
129
|
|
|
135
130
|
const activeOpacity = getActiveOpacity(position, routesLength, tabIndex);
|
|
136
131
|
const inactiveOpacity = getInactiveOpacity(position, routesLength, tabIndex);
|
|
137
132
|
|
|
138
|
-
|
|
139
|
-
|
|
133
|
+
const icon = React.useMemo(() => {
|
|
134
|
+
if (!customIcon) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
140
137
|
|
|
141
|
-
|
|
142
|
-
const activeIcon = renderIcon({
|
|
143
|
-
route,
|
|
144
|
-
focused: true,
|
|
145
|
-
color: activeColor,
|
|
146
|
-
});
|
|
147
|
-
const inactiveIcon = renderIcon({
|
|
148
|
-
route,
|
|
138
|
+
const inactiveIcon = customIcon({
|
|
149
139
|
focused: false,
|
|
150
140
|
color: inactiveColor,
|
|
141
|
+
size: ICON_SIZE,
|
|
142
|
+
route,
|
|
151
143
|
});
|
|
152
144
|
|
|
153
|
-
|
|
154
|
-
icon = (
|
|
155
|
-
<View style={styles.icon}>
|
|
156
|
-
<Animated.View style={{ opacity: inactiveOpacity }}>
|
|
157
|
-
{inactiveIcon}
|
|
158
|
-
</Animated.View>
|
|
159
|
-
<Animated.View
|
|
160
|
-
style={[StyleSheet.absoluteFill, { opacity: activeOpacity }]}
|
|
161
|
-
>
|
|
162
|
-
{activeIcon}
|
|
163
|
-
</Animated.View>
|
|
164
|
-
</View>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const renderLabel =
|
|
170
|
-
renderLabelCustom !== undefined
|
|
171
|
-
? renderLabelCustom
|
|
172
|
-
: (labelProps: { route: T; color: string }) => {
|
|
173
|
-
const labelText = getLabelText({ route: labelProps.route });
|
|
174
|
-
|
|
175
|
-
if (typeof labelText === 'string') {
|
|
176
|
-
return (
|
|
177
|
-
<Animated.Text
|
|
178
|
-
style={[
|
|
179
|
-
styles.label,
|
|
180
|
-
icon ? { marginTop: 0 } : null,
|
|
181
|
-
labelStyle,
|
|
182
|
-
{ color: labelProps.color },
|
|
183
|
-
]}
|
|
184
|
-
>
|
|
185
|
-
{labelText}
|
|
186
|
-
</Animated.Text>
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return labelText;
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
if (renderLabel) {
|
|
194
|
-
const activeLabel = renderLabel({
|
|
195
|
-
route,
|
|
145
|
+
const activeIcon = customIcon({
|
|
196
146
|
focused: true,
|
|
197
147
|
color: activeColor,
|
|
198
|
-
|
|
199
|
-
const inactiveLabel = renderLabel({
|
|
148
|
+
size: ICON_SIZE,
|
|
200
149
|
route,
|
|
201
|
-
focused: false,
|
|
202
|
-
color: inactiveColor,
|
|
203
150
|
});
|
|
204
151
|
|
|
205
|
-
|
|
206
|
-
<View>
|
|
152
|
+
return (
|
|
153
|
+
<View style={styles.icon}>
|
|
207
154
|
<Animated.View style={{ opacity: inactiveOpacity }}>
|
|
208
|
-
{
|
|
155
|
+
{inactiveIcon}
|
|
209
156
|
</Animated.View>
|
|
210
157
|
<Animated.View
|
|
211
158
|
style={[StyleSheet.absoluteFill, { opacity: activeOpacity }]}
|
|
212
159
|
>
|
|
213
|
-
{
|
|
160
|
+
{activeIcon}
|
|
214
161
|
</Animated.View>
|
|
215
162
|
</View>
|
|
216
163
|
);
|
|
217
|
-
}
|
|
164
|
+
}, [
|
|
165
|
+
activeColor,
|
|
166
|
+
activeOpacity,
|
|
167
|
+
customIcon,
|
|
168
|
+
inactiveColor,
|
|
169
|
+
inactiveOpacity,
|
|
170
|
+
route,
|
|
171
|
+
]);
|
|
172
|
+
|
|
173
|
+
const renderLabel = React.useCallback(
|
|
174
|
+
(focused: boolean) =>
|
|
175
|
+
customlabel ? (
|
|
176
|
+
customlabel({
|
|
177
|
+
focused,
|
|
178
|
+
color: focused ? activeColor : inactiveColor,
|
|
179
|
+
style: labelStyle,
|
|
180
|
+
labelText,
|
|
181
|
+
allowFontScaling: labelAllowFontScaling,
|
|
182
|
+
route,
|
|
183
|
+
})
|
|
184
|
+
) : (
|
|
185
|
+
<TabBarItemLabel
|
|
186
|
+
color={focused ? activeColor : inactiveColor}
|
|
187
|
+
icon={icon}
|
|
188
|
+
label={labelText}
|
|
189
|
+
style={labelStyle}
|
|
190
|
+
/>
|
|
191
|
+
),
|
|
192
|
+
[
|
|
193
|
+
customlabel,
|
|
194
|
+
activeColor,
|
|
195
|
+
labelStyle,
|
|
196
|
+
labelText,
|
|
197
|
+
labelAllowFontScaling,
|
|
198
|
+
route,
|
|
199
|
+
inactiveColor,
|
|
200
|
+
icon,
|
|
201
|
+
]
|
|
202
|
+
);
|
|
218
203
|
|
|
219
204
|
const tabStyle = StyleSheet.flatten(style);
|
|
220
205
|
const isWidthSet = tabStyle?.width !== undefined;
|
|
@@ -223,39 +208,41 @@ const TabBarItemInternal = <T extends Route>({
|
|
|
223
208
|
? null
|
|
224
209
|
: { width: defaultTabWidth };
|
|
225
210
|
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
let accessibilityLabel = getAccessibilityLabel(scene);
|
|
229
|
-
|
|
230
|
-
accessibilityLabel =
|
|
231
|
-
typeof accessibilityLabel !== 'undefined'
|
|
232
|
-
? accessibilityLabel
|
|
233
|
-
: getLabelText(scene);
|
|
234
|
-
|
|
235
|
-
const badge = renderBadge ? renderBadge(scene) : null;
|
|
211
|
+
const ariaLabel =
|
|
212
|
+
typeof accessibilityLabel !== 'undefined' ? accessibilityLabel : labelText;
|
|
236
213
|
|
|
237
214
|
return (
|
|
238
215
|
<PlatformPressable
|
|
239
216
|
android_ripple={android_ripple}
|
|
240
|
-
testID={
|
|
241
|
-
accessible={
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
// @ts-ignore: this is to support older React Native versions
|
|
246
|
-
accessibilityStates={isFocused ? ['selected'] : []}
|
|
217
|
+
testID={testID}
|
|
218
|
+
accessible={accessible}
|
|
219
|
+
role="tab"
|
|
220
|
+
aria-label={ariaLabel}
|
|
221
|
+
aria-selected={isFocused}
|
|
247
222
|
pressColor={pressColor}
|
|
248
223
|
pressOpacity={pressOpacity}
|
|
249
|
-
|
|
224
|
+
unstable_pressDelay={0}
|
|
250
225
|
onLayout={onLayout}
|
|
251
226
|
onPress={onPress}
|
|
252
227
|
onLongPress={onLongPress}
|
|
228
|
+
href={href}
|
|
253
229
|
style={[styles.pressable, tabContainerStyle]}
|
|
254
230
|
>
|
|
255
231
|
<View pointerEvents="none" style={[styles.item, tabStyle]}>
|
|
256
232
|
{icon}
|
|
257
|
-
|
|
258
|
-
|
|
233
|
+
<View>
|
|
234
|
+
<Animated.View style={{ opacity: inactiveOpacity }}>
|
|
235
|
+
{renderLabel(false)}
|
|
236
|
+
</Animated.View>
|
|
237
|
+
<Animated.View
|
|
238
|
+
style={[StyleSheet.absoluteFill, { opacity: activeOpacity }]}
|
|
239
|
+
>
|
|
240
|
+
{renderLabel(true)}
|
|
241
|
+
</Animated.View>
|
|
242
|
+
</View>
|
|
243
|
+
{customBadge != null ? (
|
|
244
|
+
<View style={styles.badge}>{customBadge({ route })}</View>
|
|
245
|
+
) : null}
|
|
259
246
|
</View>
|
|
260
247
|
</PlatformPressable>
|
|
261
248
|
);
|
|
@@ -265,9 +252,10 @@ const MemoizedTabBarItemInternal = React.memo(
|
|
|
265
252
|
TabBarItemInternal
|
|
266
253
|
) as typeof TabBarItemInternal;
|
|
267
254
|
|
|
268
|
-
function TabBarItem<T extends Route>(props: Props<T>) {
|
|
255
|
+
export function TabBarItem<T extends Route>(props: Props<T>) {
|
|
269
256
|
const { onPress, onLongPress, onLayout, navigationState, route, ...rest } =
|
|
270
257
|
props;
|
|
258
|
+
|
|
271
259
|
const onPressLatest = useLatestCallback(onPress);
|
|
272
260
|
const onLongPressLatest = useLatestCallback(onLongPress);
|
|
273
261
|
const onLayoutLatest = useLatestCallback(onLayout ? onLayout : () => {});
|
|
@@ -288,14 +276,7 @@ function TabBarItem<T extends Route>(props: Props<T>) {
|
|
|
288
276
|
);
|
|
289
277
|
}
|
|
290
278
|
|
|
291
|
-
export default TabBarItem;
|
|
292
|
-
|
|
293
279
|
const styles = StyleSheet.create({
|
|
294
|
-
label: {
|
|
295
|
-
margin: 4,
|
|
296
|
-
backgroundColor: 'transparent',
|
|
297
|
-
textTransform: 'uppercase',
|
|
298
|
-
},
|
|
299
280
|
icon: {
|
|
300
281
|
margin: 2,
|
|
301
282
|
},
|
|
@@ -309,11 +290,19 @@ const styles = StyleSheet.create({
|
|
|
309
290
|
badge: {
|
|
310
291
|
position: 'absolute',
|
|
311
292
|
top: 0,
|
|
312
|
-
|
|
293
|
+
end: 0,
|
|
313
294
|
},
|
|
314
295
|
pressable: {
|
|
315
296
|
// The label is not pressable on Windows
|
|
316
297
|
// Adding backgroundColor: 'transparent' seems to fix it
|
|
317
298
|
backgroundColor: 'transparent',
|
|
299
|
+
...Platform.select({
|
|
300
|
+
// Roundness for iPad hover effect
|
|
301
|
+
ios: {
|
|
302
|
+
borderRadius: 10,
|
|
303
|
+
borderCurve: 'continuous',
|
|
304
|
+
},
|
|
305
|
+
default: null,
|
|
306
|
+
}),
|
|
318
307
|
},
|
|
319
308
|
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { StyleProp, ViewStyle } from 'react-native';
|
|
3
|
+
import { Animated, StyleSheet } from 'react-native';
|
|
4
|
+
|
|
5
|
+
interface TabBarItemLabelProps {
|
|
6
|
+
color: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
style: StyleProp<ViewStyle>;
|
|
9
|
+
icon: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const TabBarItemLabel = React.memo(
|
|
13
|
+
({ color, label, style, icon }: TabBarItemLabelProps) => {
|
|
14
|
+
if (!label) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Animated.Text
|
|
20
|
+
style={[
|
|
21
|
+
styles.label,
|
|
22
|
+
icon ? { marginTop: 0 } : null,
|
|
23
|
+
style,
|
|
24
|
+
{ color: color },
|
|
25
|
+
]}
|
|
26
|
+
>
|
|
27
|
+
{label}
|
|
28
|
+
</Animated.Text>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
TabBarItemLabel.displayName = 'TabBarItemLabel';
|
|
34
|
+
|
|
35
|
+
const styles = StyleSheet.create({
|
|
36
|
+
label: {
|
|
37
|
+
margin: 4,
|
|
38
|
+
fontSize: 14,
|
|
39
|
+
fontWeight: '500',
|
|
40
|
+
backgroundColor: 'transparent',
|
|
41
|
+
},
|
|
42
|
+
});
|