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.
Files changed (66) hide show
  1. package/{LICENSE.md → LICENSE} +0 -0
  2. package/README.md +5 -36
  3. package/lib/commonjs/PagerViewAdapter.js +2 -1
  4. package/lib/commonjs/PagerViewAdapter.js.map +1 -1
  5. package/lib/commonjs/PanResponderAdapter.js +2 -1
  6. package/lib/commonjs/PanResponderAdapter.js.map +1 -1
  7. package/lib/commonjs/SceneMap.js +9 -12
  8. package/lib/commonjs/SceneMap.js.map +1 -1
  9. package/lib/commonjs/SceneView.js +54 -101
  10. package/lib/commonjs/SceneView.js.map +1 -1
  11. package/lib/commonjs/TabBar.js +358 -325
  12. package/lib/commonjs/TabBar.js.map +1 -1
  13. package/lib/commonjs/TabBarIndicator.js +81 -99
  14. package/lib/commonjs/TabBarIndicator.js.map +1 -1
  15. package/lib/commonjs/TabBarItem.js +184 -161
  16. package/lib/commonjs/TabBarItem.js.map +1 -1
  17. package/lib/commonjs/TabView.js +2 -2
  18. package/lib/commonjs/TabView.js.map +1 -1
  19. package/lib/commonjs/index.js +3 -3
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/module/PagerViewAdapter.js +2 -1
  22. package/lib/module/PagerViewAdapter.js.map +1 -1
  23. package/lib/module/PanResponderAdapter.js +3 -2
  24. package/lib/module/PanResponderAdapter.js.map +1 -1
  25. package/lib/module/SceneMap.js +9 -14
  26. package/lib/module/SceneMap.js.map +1 -1
  27. package/lib/module/SceneView.js +54 -99
  28. package/lib/module/SceneView.js.map +1 -1
  29. package/lib/module/TabBar.js +355 -324
  30. package/lib/module/TabBar.js.map +1 -1
  31. package/lib/module/TabBarIndicator.js +75 -93
  32. package/lib/module/TabBarIndicator.js.map +1 -1
  33. package/lib/module/TabBarItem.js +178 -154
  34. package/lib/module/TabBarItem.js.map +1 -1
  35. package/lib/module/TabView.js +2 -2
  36. package/lib/module/TabView.js.map +1 -1
  37. package/lib/module/index.js +2 -2
  38. package/lib/module/index.js.map +1 -1
  39. package/lib/typescript/{Pager.android.d.ts → src/Pager.android.d.ts} +0 -0
  40. package/lib/typescript/{Pager.d.ts → src/Pager.d.ts} +0 -0
  41. package/lib/typescript/{Pager.ios.d.ts → src/Pager.ios.d.ts} +0 -0
  42. package/lib/typescript/{PagerViewAdapter.d.ts → src/PagerViewAdapter.d.ts} +1 -1
  43. package/lib/typescript/{PanResponderAdapter.d.ts → src/PanResponderAdapter.d.ts} +1 -1
  44. package/lib/typescript/{PlatformPressable.d.ts → src/PlatformPressable.d.ts} +0 -0
  45. package/lib/typescript/{SceneMap.d.ts → src/SceneMap.d.ts} +5 -3
  46. package/lib/typescript/src/SceneView.d.ts +15 -0
  47. package/lib/typescript/src/TabBar.d.ts +42 -0
  48. package/lib/typescript/src/TabBarIndicator.d.ts +12 -0
  49. package/lib/typescript/{TabBarItem.d.ts → src/TabBarItem.d.ts} +5 -7
  50. package/lib/typescript/{TabView.d.ts → src/TabView.d.ts} +1 -1
  51. package/lib/typescript/{index.d.ts → src/index.d.ts} +7 -7
  52. package/lib/typescript/{types.d.ts → src/types.d.ts} +0 -0
  53. package/lib/typescript/{useAnimatedValue.d.ts → src/useAnimatedValue.d.ts} +0 -0
  54. package/package.json +28 -58
  55. package/src/PagerViewAdapter.tsx +11 -5
  56. package/src/PanResponderAdapter.tsx +16 -12
  57. package/src/SceneMap.tsx +12 -7
  58. package/src/SceneView.tsx +73 -108
  59. package/src/TabBar.tsx +506 -401
  60. package/src/TabBarIndicator.tsx +114 -117
  61. package/src/TabBarItem.tsx +230 -200
  62. package/src/TabView.tsx +6 -5
  63. package/src/index.tsx +7 -12
  64. package/lib/typescript/SceneView.d.ts +0 -32
  65. package/lib/typescript/TabBar.d.ts +0 -72
  66. package/lib/typescript/TabBarIndicator.d.ts +0 -20
@@ -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, NavigationState } from './types';
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
- export default class TabBarIndicator<T extends Route> extends React.Component<
25
- Props<T>
26
- > {
27
- componentDidMount() {
28
- this.fadeInIndicator();
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
- componentDidUpdate() {
32
- this.fadeInIndicator();
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
- private fadeInIndicator = () => {
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
- // every index contains widths at all previous indices
69
- const outputRange = routes.reduce<number[]>((acc, _, i) => {
70
- if (i === 0) return [0];
71
- return [...acc, acc[i - 1] + getTabWidth(i - 1) + (gap ?? 0)];
72
- }, []);
73
-
74
- const translateX = position.interpolate({
75
- inputRange,
76
- outputRange,
77
- extrapolate: 'clamp',
78
- });
79
-
80
- return Animated.multiply(translateX, I18nManager.isRTL ? -1 : 1);
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({