react-native-tab-view 3.2.1 → 3.3.2
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/{LICENSE.md → LICENSE} +0 -0
- package/README.md +5 -36
- package/lib/commonjs/PagerViewAdapter.js +2 -1
- package/lib/commonjs/PagerViewAdapter.js.map +1 -1
- package/lib/commonjs/PanResponderAdapter.js +2 -1
- package/lib/commonjs/PanResponderAdapter.js.map +1 -1
- package/lib/commonjs/SceneMap.js +9 -12
- package/lib/commonjs/SceneMap.js.map +1 -1
- package/lib/commonjs/SceneView.js +54 -101
- package/lib/commonjs/SceneView.js.map +1 -1
- package/lib/commonjs/TabBar.js +358 -325
- package/lib/commonjs/TabBar.js.map +1 -1
- package/lib/commonjs/TabBarIndicator.js +81 -99
- package/lib/commonjs/TabBarIndicator.js.map +1 -1
- package/lib/commonjs/TabBarItem.js +184 -161
- package/lib/commonjs/TabBarItem.js.map +1 -1
- package/lib/commonjs/TabView.js +2 -2
- package/lib/commonjs/TabView.js.map +1 -1
- package/lib/commonjs/index.js +3 -3
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/PagerViewAdapter.js +2 -1
- package/lib/module/PagerViewAdapter.js.map +1 -1
- package/lib/module/PanResponderAdapter.js +3 -2
- package/lib/module/PanResponderAdapter.js.map +1 -1
- package/lib/module/SceneMap.js +9 -14
- package/lib/module/SceneMap.js.map +1 -1
- package/lib/module/SceneView.js +54 -99
- package/lib/module/SceneView.js.map +1 -1
- package/lib/module/TabBar.js +355 -324
- package/lib/module/TabBar.js.map +1 -1
- package/lib/module/TabBarIndicator.js +75 -93
- package/lib/module/TabBarIndicator.js.map +1 -1
- package/lib/module/TabBarItem.js +178 -154
- package/lib/module/TabBarItem.js.map +1 -1
- package/lib/module/TabView.js +2 -2
- package/lib/module/TabView.js.map +1 -1
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/{Pager.android.d.ts → src/Pager.android.d.ts} +0 -0
- package/lib/typescript/{Pager.d.ts → src/Pager.d.ts} +0 -0
- package/lib/typescript/{Pager.ios.d.ts → src/Pager.ios.d.ts} +0 -0
- package/lib/typescript/{PagerViewAdapter.d.ts → src/PagerViewAdapter.d.ts} +1 -1
- package/lib/typescript/{PanResponderAdapter.d.ts → src/PanResponderAdapter.d.ts} +1 -1
- package/lib/typescript/{PlatformPressable.d.ts → src/PlatformPressable.d.ts} +0 -0
- package/lib/typescript/{SceneMap.d.ts → src/SceneMap.d.ts} +5 -3
- package/lib/typescript/src/SceneView.d.ts +15 -0
- package/lib/typescript/src/TabBar.d.ts +42 -0
- package/lib/typescript/src/TabBarIndicator.d.ts +12 -0
- package/lib/typescript/{TabBarItem.d.ts → src/TabBarItem.d.ts} +5 -7
- package/lib/typescript/{TabView.d.ts → src/TabView.d.ts} +1 -1
- package/lib/typescript/{index.d.ts → src/index.d.ts} +7 -7
- package/lib/typescript/{types.d.ts → src/types.d.ts} +0 -0
- package/lib/typescript/{useAnimatedValue.d.ts → src/useAnimatedValue.d.ts} +0 -0
- package/package.json +28 -58
- package/src/PagerViewAdapter.tsx +11 -5
- package/src/PanResponderAdapter.tsx +16 -12
- package/src/SceneMap.tsx +12 -7
- package/src/SceneView.tsx +73 -108
- package/src/TabBar.tsx +506 -401
- package/src/TabBarIndicator.tsx +114 -117
- package/src/TabBarItem.tsx +230 -200
- package/src/TabView.tsx +6 -5
- package/src/index.tsx +7 -12
- package/lib/typescript/SceneView.d.ts +0 -32
- package/lib/typescript/TabBar.d.ts +0 -72
- package/lib/typescript/TabBarIndicator.d.ts +0 -20
package/src/TabBarIndicator.tsx
CHANGED
|
@@ -2,14 +2,15 @@ import * as React from 'react';
|
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
4
|
Easing,
|
|
5
|
-
StyleSheet,
|
|
6
5
|
I18nManager,
|
|
6
|
+
Platform,
|
|
7
7
|
StyleProp,
|
|
8
|
+
StyleSheet,
|
|
8
9
|
ViewStyle,
|
|
9
|
-
Platform,
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
|
|
12
|
-
import type { Route, SceneRendererProps
|
|
12
|
+
import type { NavigationState, Route, SceneRendererProps } from './types';
|
|
13
|
+
import useAnimatedValue from './useAnimatedValue';
|
|
13
14
|
|
|
14
15
|
export type GetTabWidth = (index: number) => number;
|
|
15
16
|
|
|
@@ -21,126 +22,122 @@ export type Props<T extends Route> = SceneRendererProps & {
|
|
|
21
22
|
gap?: number;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
const getTranslateX = (
|
|
26
|
+
position: Animated.AnimatedInterpolation,
|
|
27
|
+
routes: Route[],
|
|
28
|
+
getTabWidth: GetTabWidth,
|
|
29
|
+
gap?: number
|
|
30
|
+
) => {
|
|
31
|
+
const inputRange = routes.map((_, i) => i);
|
|
32
|
+
|
|
33
|
+
// every index contains widths at all previous indices
|
|
34
|
+
const outputRange = routes.reduce<number[]>((acc, _, i) => {
|
|
35
|
+
if (i === 0) return [0];
|
|
36
|
+
return [...acc, acc[i - 1] + getTabWidth(i - 1) + (gap ?? 0)];
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
39
|
+
const translateX = position.interpolate({
|
|
40
|
+
inputRange,
|
|
41
|
+
outputRange,
|
|
42
|
+
extrapolate: 'clamp',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return Animated.multiply(translateX, I18nManager.isRTL ? -1 : 1);
|
|
46
|
+
};
|
|
30
47
|
|
|
31
|
-
|
|
32
|
-
|
|
48
|
+
export default function TabBarIndicator<T extends Route>({
|
|
49
|
+
getTabWidth,
|
|
50
|
+
layout,
|
|
51
|
+
navigationState,
|
|
52
|
+
position,
|
|
53
|
+
width,
|
|
54
|
+
gap,
|
|
55
|
+
style,
|
|
56
|
+
}: Props<T>) {
|
|
57
|
+
const isIndicatorShown = React.useRef(false);
|
|
58
|
+
const isWidthDynamic = width === 'auto';
|
|
59
|
+
|
|
60
|
+
const opacity = useAnimatedValue(isWidthDynamic ? 0 : 1);
|
|
61
|
+
|
|
62
|
+
const indicatorVisible = isWidthDynamic
|
|
63
|
+
? layout.width &&
|
|
64
|
+
navigationState.routes
|
|
65
|
+
.slice(0, navigationState.index)
|
|
66
|
+
.every((_, r) => getTabWidth(r))
|
|
67
|
+
: true;
|
|
68
|
+
|
|
69
|
+
React.useEffect(() => {
|
|
70
|
+
const fadeInIndicator = () => {
|
|
71
|
+
if (
|
|
72
|
+
!isIndicatorShown.current &&
|
|
73
|
+
isWidthDynamic &&
|
|
74
|
+
// We should fade-in the indicator when we have widths for all the tab items
|
|
75
|
+
indicatorVisible
|
|
76
|
+
) {
|
|
77
|
+
isIndicatorShown.current = true;
|
|
78
|
+
|
|
79
|
+
Animated.timing(opacity, {
|
|
80
|
+
toValue: 1,
|
|
81
|
+
duration: 150,
|
|
82
|
+
easing: Easing.in(Easing.linear),
|
|
83
|
+
useNativeDriver: true,
|
|
84
|
+
}).start();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
fadeInIndicator();
|
|
89
|
+
|
|
90
|
+
return () => opacity.stopAnimation();
|
|
91
|
+
}, [indicatorVisible, isWidthDynamic, opacity]);
|
|
92
|
+
|
|
93
|
+
const { routes } = navigationState;
|
|
94
|
+
|
|
95
|
+
const transform = [];
|
|
96
|
+
|
|
97
|
+
if (layout.width) {
|
|
98
|
+
const translateX =
|
|
99
|
+
routes.length > 1 ? getTranslateX(position, routes, getTabWidth, gap) : 0;
|
|
100
|
+
|
|
101
|
+
transform.push({ translateX });
|
|
33
102
|
}
|
|
34
103
|
|
|
35
|
-
|
|
36
|
-
const { navigationState, layout, width, getTabWidth } = this.props;
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
!this.isIndicatorShown &&
|
|
40
|
-
width === 'auto' &&
|
|
41
|
-
layout.width &&
|
|
42
|
-
// We should fade-in the indicator when we have widths for all the tab items
|
|
43
|
-
navigationState.routes.every((_, i) => getTabWidth(i))
|
|
44
|
-
) {
|
|
45
|
-
this.isIndicatorShown = true;
|
|
46
|
-
|
|
47
|
-
Animated.timing(this.opacity, {
|
|
48
|
-
toValue: 1,
|
|
49
|
-
duration: 150,
|
|
50
|
-
easing: Easing.in(Easing.linear),
|
|
51
|
-
useNativeDriver: true,
|
|
52
|
-
}).start();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
private isIndicatorShown = false;
|
|
57
|
-
|
|
58
|
-
private opacity = new Animated.Value(this.props.width === 'auto' ? 0 : 1);
|
|
59
|
-
|
|
60
|
-
private getTranslateX = (
|
|
61
|
-
position: Animated.AnimatedInterpolation,
|
|
62
|
-
routes: Route[],
|
|
63
|
-
getTabWidth: GetTabWidth,
|
|
64
|
-
gap?: number
|
|
65
|
-
) => {
|
|
104
|
+
if (width === 'auto') {
|
|
66
105
|
const inputRange = routes.map((_, i) => i);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
render() {
|
|
84
|
-
const {
|
|
85
|
-
position,
|
|
86
|
-
navigationState,
|
|
87
|
-
getTabWidth,
|
|
88
|
-
width,
|
|
89
|
-
style,
|
|
90
|
-
layout,
|
|
91
|
-
gap,
|
|
92
|
-
} = this.props;
|
|
93
|
-
const { routes } = navigationState;
|
|
94
|
-
|
|
95
|
-
const transform = [];
|
|
96
|
-
|
|
97
|
-
if (layout.width) {
|
|
98
|
-
const translateX =
|
|
99
|
-
routes.length > 1
|
|
100
|
-
? this.getTranslateX(position, routes, getTabWidth, gap)
|
|
101
|
-
: 0;
|
|
102
|
-
|
|
103
|
-
transform.push({ translateX });
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (width === 'auto') {
|
|
107
|
-
const inputRange = routes.map((_, i) => i);
|
|
108
|
-
const outputRange = inputRange.map(getTabWidth);
|
|
109
|
-
|
|
110
|
-
transform.push(
|
|
111
|
-
{
|
|
112
|
-
scaleX:
|
|
113
|
-
routes.length > 1
|
|
114
|
-
? position.interpolate({
|
|
115
|
-
inputRange,
|
|
116
|
-
outputRange,
|
|
117
|
-
extrapolate: 'clamp',
|
|
118
|
-
})
|
|
119
|
-
: outputRange[0],
|
|
120
|
-
},
|
|
121
|
-
{ translateX: 0.5 }
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return (
|
|
126
|
-
<Animated.View
|
|
127
|
-
style={[
|
|
128
|
-
styles.indicator,
|
|
129
|
-
{ width: width === 'auto' ? 1 : width },
|
|
130
|
-
// If layout is not available, use `left` property for positioning the indicator
|
|
131
|
-
// This avoids rendering delay until we are able to calculate translateX
|
|
132
|
-
// If platform is macos use `left` property as `transform` is broken at the moment.
|
|
133
|
-
// See: https://github.com/microsoft/react-native-macos/issues/280
|
|
134
|
-
layout.width && Platform.OS !== 'macos'
|
|
135
|
-
? { left: 0 }
|
|
136
|
-
: { left: `${(100 / routes.length) * navigationState.index}%` },
|
|
137
|
-
{ transform },
|
|
138
|
-
width === 'auto' ? { opacity: this.opacity } : null,
|
|
139
|
-
style,
|
|
140
|
-
]}
|
|
141
|
-
/>
|
|
106
|
+
const outputRange = inputRange.map(getTabWidth);
|
|
107
|
+
|
|
108
|
+
transform.push(
|
|
109
|
+
{
|
|
110
|
+
scaleX:
|
|
111
|
+
routes.length > 1
|
|
112
|
+
? position.interpolate({
|
|
113
|
+
inputRange,
|
|
114
|
+
outputRange,
|
|
115
|
+
extrapolate: 'clamp',
|
|
116
|
+
})
|
|
117
|
+
: outputRange[0],
|
|
118
|
+
},
|
|
119
|
+
{ translateX: 0.5 }
|
|
142
120
|
);
|
|
143
121
|
}
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<Animated.View
|
|
125
|
+
style={[
|
|
126
|
+
styles.indicator,
|
|
127
|
+
{ width: width === 'auto' ? 1 : width },
|
|
128
|
+
// If layout is not available, use `left` property for positioning the indicator
|
|
129
|
+
// This avoids rendering delay until we are able to calculate translateX
|
|
130
|
+
// If platform is macos use `left` property as `transform` is broken at the moment.
|
|
131
|
+
// See: https://github.com/microsoft/react-native-macos/issues/280
|
|
132
|
+
layout.width && Platform.OS !== 'macos'
|
|
133
|
+
? { left: 0 }
|
|
134
|
+
: { left: `${(100 / routes.length) * navigationState.index}%` },
|
|
135
|
+
{ transform },
|
|
136
|
+
width === 'auto' ? { opacity: opacity } : null,
|
|
137
|
+
style,
|
|
138
|
+
]}
|
|
139
|
+
/>
|
|
140
|
+
);
|
|
144
141
|
}
|
|
145
142
|
|
|
146
143
|
const styles = StyleSheet.create({
|