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/lib/module/TabBar.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
|
-
|
|
3
1
|
import * as React from 'react';
|
|
4
|
-
import { Animated,
|
|
5
|
-
import
|
|
2
|
+
import { Animated, I18nManager, Platform, StyleSheet, View } from 'react-native';
|
|
3
|
+
import useLatestCallback from 'use-latest-callback';
|
|
6
4
|
import TabBarIndicator from './TabBarIndicator';
|
|
5
|
+
import TabBarItem from './TabBarItem';
|
|
6
|
+
import useAnimatedValue from './useAnimatedValue';
|
|
7
7
|
|
|
8
8
|
const Separator = _ref => {
|
|
9
9
|
let {
|
|
@@ -16,359 +16,390 @@ const Separator = _ref => {
|
|
|
16
16
|
});
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
_defineProperty(this, "state", {
|
|
24
|
-
layout: {
|
|
25
|
-
width: 0,
|
|
26
|
-
height: 0
|
|
27
|
-
},
|
|
28
|
-
tabWidths: {}
|
|
29
|
-
});
|
|
19
|
+
const getFlattenedTabWidth = style => {
|
|
20
|
+
const tabStyle = StyleSheet.flatten(style);
|
|
21
|
+
return tabStyle === null || tabStyle === void 0 ? void 0 : tabStyle.width;
|
|
22
|
+
};
|
|
30
23
|
|
|
31
|
-
|
|
24
|
+
const getComputedTabWidth = (index, layout, routes, scrollEnabled, tabWidths, flattenedWidth) => {
|
|
25
|
+
if (flattenedWidth === 'auto') {
|
|
26
|
+
return tabWidths[routes[index].key] || 0;
|
|
27
|
+
}
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
switch (typeof flattenedWidth) {
|
|
30
|
+
case 'number':
|
|
31
|
+
return flattenedWidth;
|
|
34
32
|
|
|
35
|
-
|
|
33
|
+
case 'string':
|
|
34
|
+
if (flattenedWidth.endsWith('%')) {
|
|
35
|
+
const width = parseFloat(flattenedWidth);
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
_defineProperty(this, "getComputedTabWidth", (index, layout, routes, scrollEnabled, tabWidths, flattenedWidth) => {
|
|
43
|
-
if (flattenedWidth === 'auto') {
|
|
44
|
-
return tabWidths[routes[index].key] || 0;
|
|
37
|
+
if (Number.isFinite(width)) {
|
|
38
|
+
return layout.width * (width / 100);
|
|
39
|
+
}
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
case 'number':
|
|
49
|
-
return flattenedWidth;
|
|
42
|
+
}
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
if (scrollEnabled) {
|
|
45
|
+
return layout.width / 5 * 2;
|
|
46
|
+
}
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
}
|
|
48
|
+
return layout.width / routes.length;
|
|
49
|
+
};
|
|
59
50
|
|
|
60
|
-
|
|
51
|
+
const getMaxScrollDistance = (tabBarWidth, layoutWidth) => tabBarWidth - layoutWidth;
|
|
61
52
|
|
|
62
|
-
|
|
63
|
-
return layout.width / 5 * 2;
|
|
64
|
-
}
|
|
53
|
+
const getTranslateX = (scrollAmount, maxScrollDistance) => Animated.multiply(Platform.OS === 'android' && I18nManager.isRTL ? Animated.add(maxScrollDistance, Animated.multiply(scrollAmount, -1)) : scrollAmount, I18nManager.isRTL ? 1 : -1);
|
|
65
54
|
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
const getTabBarWidth = _ref2 => {
|
|
56
|
+
let {
|
|
57
|
+
navigationState,
|
|
58
|
+
layout,
|
|
59
|
+
gap,
|
|
60
|
+
scrollEnabled,
|
|
61
|
+
flattenedTabWidth,
|
|
62
|
+
tabWidths
|
|
63
|
+
} = _ref2;
|
|
64
|
+
const {
|
|
65
|
+
routes
|
|
66
|
+
} = navigationState;
|
|
67
|
+
return routes.reduce((acc, _, i) => acc + (i > 0 ? gap !== null && gap !== void 0 ? gap : 0 : 0) + getComputedTabWidth(i, layout, routes, scrollEnabled, tabWidths, flattenedTabWidth), 0);
|
|
68
|
+
};
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
70
|
+
const normalizeScrollValue = _ref3 => {
|
|
71
|
+
let {
|
|
72
|
+
layout,
|
|
73
|
+
navigationState,
|
|
74
|
+
gap,
|
|
75
|
+
scrollEnabled,
|
|
76
|
+
tabWidths,
|
|
77
|
+
value,
|
|
78
|
+
flattenedTabWidth
|
|
79
|
+
} = _ref3;
|
|
80
|
+
const tabBarWidth = getTabBarWidth({
|
|
81
|
+
layout,
|
|
82
|
+
navigationState,
|
|
83
|
+
tabWidths,
|
|
84
|
+
gap,
|
|
85
|
+
scrollEnabled,
|
|
86
|
+
flattenedTabWidth
|
|
87
|
+
});
|
|
88
|
+
const maxDistance = getMaxScrollDistance(tabBarWidth, layout.width);
|
|
89
|
+
const scrollValue = Math.max(Math.min(value, maxDistance), 0);
|
|
85
90
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const maxDistance = this.getMaxScrollDistance(tabBarWidth, layout.width);
|
|
92
|
-
const scrollValue = Math.max(Math.min(value, maxDistance), 0);
|
|
93
|
-
|
|
94
|
-
if (Platform.OS === 'android' && I18nManager.isRTL) {
|
|
95
|
-
// On Android, scroll value is not applied in reverse in RTL
|
|
96
|
-
// so we need to manually adjust it to apply correct value
|
|
97
|
-
return maxDistance - scrollValue;
|
|
98
|
-
}
|
|
91
|
+
if (Platform.OS === 'android' && I18nManager.isRTL) {
|
|
92
|
+
// On Android, scroll value is not applied in reverse in RTL
|
|
93
|
+
// so we need to manually adjust it to apply correct value
|
|
94
|
+
return maxDistance - scrollValue;
|
|
95
|
+
}
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
return scrollValue;
|
|
98
|
+
};
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
100
|
+
const getScrollAmount = _ref4 => {
|
|
101
|
+
let {
|
|
102
|
+
layout,
|
|
103
|
+
navigationState,
|
|
104
|
+
gap,
|
|
105
|
+
scrollEnabled,
|
|
106
|
+
flattenedTabWidth,
|
|
107
|
+
tabWidths
|
|
108
|
+
} = _ref4;
|
|
109
|
+
const centerDistance = Array.from({
|
|
110
|
+
length: navigationState.index + 1
|
|
111
|
+
}).reduce((total, _, i) => {
|
|
112
|
+
const tabWidth = getComputedTabWidth(i, layout, navigationState.routes, scrollEnabled, tabWidths, flattenedTabWidth); // To get the current index centered we adjust scroll amount by width of indexes
|
|
113
|
+
// 0 through (i - 1) and add half the width of current index i
|
|
114
|
+
|
|
115
|
+
return total + (navigationState.index === i ? (tabWidth + (gap !== null && gap !== void 0 ? gap : 0)) / 2 : tabWidth + (gap !== null && gap !== void 0 ? gap : 0));
|
|
116
|
+
}, 0);
|
|
117
|
+
const scrollAmount = centerDistance - layout.width / 2;
|
|
118
|
+
return normalizeScrollValue({
|
|
119
|
+
layout,
|
|
120
|
+
navigationState,
|
|
121
|
+
tabWidths,
|
|
122
|
+
value: scrollAmount,
|
|
123
|
+
gap,
|
|
124
|
+
scrollEnabled,
|
|
125
|
+
flattenedTabWidth
|
|
126
|
+
});
|
|
127
|
+
};
|
|
126
128
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
const getLabelTextDefault = _ref5 => {
|
|
130
|
+
let {
|
|
131
|
+
route
|
|
132
|
+
} = _ref5;
|
|
133
|
+
return route.title;
|
|
134
|
+
};
|
|
130
135
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
const getAccessibleDefault = _ref6 => {
|
|
137
|
+
let {
|
|
138
|
+
route
|
|
139
|
+
} = _ref6;
|
|
140
|
+
return typeof route.accessible !== 'undefined' ? route.accessible : true;
|
|
141
|
+
};
|
|
137
142
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
+
const getAccessibilityLabelDefault = _ref7 => {
|
|
144
|
+
let {
|
|
145
|
+
route
|
|
146
|
+
} = _ref7;
|
|
147
|
+
return typeof route.accessibilityLabel === 'string' ? route.accessibilityLabel : typeof route.title === 'string' ? route.title : undefined;
|
|
148
|
+
};
|
|
143
149
|
|
|
144
|
-
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
150
|
+
const renderIndicatorDefault = props => /*#__PURE__*/React.createElement(TabBarIndicator, props);
|
|
147
151
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
const getTestIdDefault = _ref8 => {
|
|
153
|
+
let {
|
|
154
|
+
route
|
|
155
|
+
} = _ref8;
|
|
156
|
+
return route.testID;
|
|
157
|
+
}; // How many items measurements should we update per batch.
|
|
158
|
+
// Defaults to 10, since that's whats FlatList is using in initialNumToRender.
|
|
155
159
|
|
|
156
|
-
_defineProperty(this, "getTranslateX", (scrollAmount, maxScrollDistance) => Animated.multiply(Platform.OS === 'android' && I18nManager.isRTL ? Animated.add(maxScrollDistance, Animated.multiply(scrollAmount, -1)) : scrollAmount, I18nManager.isRTL ? 1 : -1));
|
|
157
|
-
}
|
|
158
160
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
161
|
+
const MEASURE_PER_BATCH = 10;
|
|
162
|
+
export default function TabBar(_ref9) {
|
|
163
|
+
let {
|
|
164
|
+
getLabelText = getLabelTextDefault,
|
|
165
|
+
getAccessible = getAccessibleDefault,
|
|
166
|
+
getAccessibilityLabel = getAccessibilityLabelDefault,
|
|
167
|
+
getTestID = getTestIdDefault,
|
|
168
|
+
renderIndicator = renderIndicatorDefault,
|
|
169
|
+
gap = 0,
|
|
170
|
+
scrollEnabled,
|
|
171
|
+
jumpTo,
|
|
172
|
+
navigationState,
|
|
173
|
+
position,
|
|
174
|
+
activeColor,
|
|
175
|
+
bounces,
|
|
176
|
+
contentContainerStyle,
|
|
177
|
+
inactiveColor,
|
|
178
|
+
indicatorContainerStyle,
|
|
179
|
+
indicatorStyle,
|
|
180
|
+
labelStyle,
|
|
181
|
+
onTabLongPress,
|
|
182
|
+
onTabPress,
|
|
183
|
+
pressColor,
|
|
184
|
+
pressOpacity,
|
|
185
|
+
renderBadge,
|
|
186
|
+
renderIcon,
|
|
187
|
+
renderLabel,
|
|
188
|
+
renderTabBarItem,
|
|
189
|
+
style,
|
|
190
|
+
tabStyle,
|
|
191
|
+
testID
|
|
192
|
+
} = _ref9;
|
|
193
|
+
const [layout, setLayout] = React.useState({
|
|
194
|
+
width: 0,
|
|
195
|
+
height: 0
|
|
196
|
+
});
|
|
197
|
+
const [tabWidths, setTabWidths] = React.useState({});
|
|
198
|
+
const flatListRef = React.useRef(null);
|
|
199
|
+
const isFirst = React.useRef(true);
|
|
200
|
+
const scrollAmount = useAnimatedValue(0);
|
|
201
|
+
const measuredTabWidths = React.useRef({});
|
|
202
|
+
const {
|
|
203
|
+
routes
|
|
204
|
+
} = navigationState;
|
|
205
|
+
const flattenedTabWidth = getFlattenedTabWidth(tabStyle);
|
|
206
|
+
const isWidthDynamic = flattenedTabWidth === 'auto';
|
|
207
|
+
const scrollOffset = getScrollAmount({
|
|
208
|
+
layout,
|
|
209
|
+
navigationState,
|
|
210
|
+
tabWidths,
|
|
211
|
+
gap,
|
|
212
|
+
scrollEnabled,
|
|
213
|
+
flattenedTabWidth
|
|
214
|
+
});
|
|
215
|
+
const hasMeasuredTabWidths = Boolean(layout.width) && routes.slice(0, navigationState.index).every(r => typeof tabWidths[r.key] === 'number');
|
|
216
|
+
React.useEffect(() => {
|
|
217
|
+
if (isFirst.current) {
|
|
218
|
+
isFirst.current = false;
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
173
221
|
|
|
174
|
-
|
|
222
|
+
if (isWidthDynamic && !hasMeasuredTabWidths) {
|
|
223
|
+
return;
|
|
175
224
|
}
|
|
176
|
-
} // to store the layout.width of each tab
|
|
177
|
-
// when all onLayout's are fired, this would be set in state
|
|
178
225
|
|
|
226
|
+
if (scrollEnabled) {
|
|
227
|
+
var _flatListRef$current;
|
|
179
228
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
getAccessible,
|
|
189
|
-
getLabelText,
|
|
190
|
-
getTestID,
|
|
191
|
-
renderBadge,
|
|
192
|
-
renderIcon,
|
|
193
|
-
renderLabel,
|
|
194
|
-
renderTabBarItem,
|
|
195
|
-
activeColor,
|
|
196
|
-
inactiveColor,
|
|
197
|
-
pressColor,
|
|
198
|
-
pressOpacity,
|
|
199
|
-
onTabPress,
|
|
200
|
-
onTabLongPress,
|
|
201
|
-
tabStyle,
|
|
202
|
-
labelStyle,
|
|
203
|
-
indicatorStyle,
|
|
204
|
-
contentContainerStyle,
|
|
205
|
-
style,
|
|
206
|
-
indicatorContainerStyle,
|
|
207
|
-
gap = 0
|
|
208
|
-
} = this.props;
|
|
209
|
-
const {
|
|
210
|
-
layout,
|
|
211
|
-
tabWidths
|
|
212
|
-
} = this.state;
|
|
229
|
+
(_flatListRef$current = flatListRef.current) === null || _flatListRef$current === void 0 ? void 0 : _flatListRef$current.scrollToOffset({
|
|
230
|
+
offset: scrollOffset,
|
|
231
|
+
animated: true
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
}, [hasMeasuredTabWidths, isWidthDynamic, scrollEnabled, scrollOffset]);
|
|
235
|
+
|
|
236
|
+
const handleLayout = e => {
|
|
213
237
|
const {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
route
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
getLabelText: getLabelText,
|
|
278
|
-
getTestID: getTestID,
|
|
279
|
-
renderBadge: renderBadge,
|
|
280
|
-
renderIcon: renderIcon,
|
|
281
|
-
renderLabel: renderLabel,
|
|
282
|
-
activeColor: activeColor,
|
|
283
|
-
inactiveColor: inactiveColor,
|
|
284
|
-
pressColor: pressColor,
|
|
285
|
-
pressOpacity: pressOpacity,
|
|
286
|
-
onLayout: isWidthDynamic ? e => {
|
|
287
|
-
this.measuredTabWidths[route.key] = e.nativeEvent.layout.width; // When we have measured widths for all of the tabs, we should updates the state
|
|
288
|
-
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
|
|
289
|
-
|
|
290
|
-
if (routes.every(r => typeof this.measuredTabWidths[r.key] === 'number')) {
|
|
291
|
-
this.setState({
|
|
292
|
-
tabWidths: { ...this.measuredTabWidths
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
} : undefined,
|
|
297
|
-
onPress: () => {
|
|
298
|
-
const event = {
|
|
299
|
-
route,
|
|
300
|
-
defaultPrevented: false,
|
|
301
|
-
preventDefault: () => {
|
|
302
|
-
event.defaultPrevented = true;
|
|
303
|
-
}
|
|
304
|
-
};
|
|
305
|
-
onTabPress === null || onTabPress === void 0 ? void 0 : onTabPress(event);
|
|
306
|
-
|
|
307
|
-
if (event.defaultPrevented) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
this.props.jumpTo(route.key);
|
|
312
|
-
},
|
|
313
|
-
onLongPress: () => onTabLongPress === null || onTabLongPress === void 0 ? void 0 : onTabLongPress({
|
|
314
|
-
route
|
|
315
|
-
}),
|
|
316
|
-
labelStyle: labelStyle,
|
|
317
|
-
style: [tabStyle, // Calculate the deafult width for tab for FlatList to work.
|
|
318
|
-
this.getFlattenedTabWidth(tabStyle) === undefined && {
|
|
319
|
-
width: this.getComputedTabWidth(index, layout, routes, scrollEnabled, tabWidths, this.getFlattenedTabWidth(tabStyle))
|
|
320
|
-
}]
|
|
321
|
-
};
|
|
322
|
-
return /*#__PURE__*/React.createElement(React.Fragment, {
|
|
323
|
-
key: route.key
|
|
324
|
-
}, gap > 0 && index > 0 ? /*#__PURE__*/React.createElement(Separator, {
|
|
325
|
-
width: gap
|
|
326
|
-
}) : null, renderTabBarItem ? renderTabBarItem(props) : /*#__PURE__*/React.createElement(TabBarItem, props));
|
|
327
|
-
},
|
|
328
|
-
onScroll: Animated.event([{
|
|
329
|
-
nativeEvent: {
|
|
330
|
-
contentOffset: {
|
|
331
|
-
x: this.scrollAmount
|
|
238
|
+
height,
|
|
239
|
+
width
|
|
240
|
+
} = e.nativeEvent.layout;
|
|
241
|
+
setLayout(layout => layout.width === width && layout.height === height ? layout : {
|
|
242
|
+
width,
|
|
243
|
+
height
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const tabBarWidth = getTabBarWidth({
|
|
248
|
+
layout,
|
|
249
|
+
navigationState,
|
|
250
|
+
tabWidths,
|
|
251
|
+
gap,
|
|
252
|
+
scrollEnabled,
|
|
253
|
+
flattenedTabWidth
|
|
254
|
+
});
|
|
255
|
+
const separatorsWidth = Math.max(0, routes.length - 1) * gap;
|
|
256
|
+
const separatorPercent = separatorsWidth / tabBarWidth * 100;
|
|
257
|
+
const tabBarWidthPercent = `${routes.length * 40}%`;
|
|
258
|
+
const translateX = React.useMemo(() => getTranslateX(scrollAmount, getMaxScrollDistance(tabBarWidth, layout.width)), [layout.width, scrollAmount, tabBarWidth]);
|
|
259
|
+
const renderItem = React.useCallback(_ref10 => {
|
|
260
|
+
let {
|
|
261
|
+
item: route,
|
|
262
|
+
index
|
|
263
|
+
} = _ref10;
|
|
264
|
+
const props = {
|
|
265
|
+
key: route.key,
|
|
266
|
+
position: position,
|
|
267
|
+
route: route,
|
|
268
|
+
navigationState: navigationState,
|
|
269
|
+
getAccessibilityLabel: getAccessibilityLabel,
|
|
270
|
+
getAccessible: getAccessible,
|
|
271
|
+
getLabelText: getLabelText,
|
|
272
|
+
getTestID: getTestID,
|
|
273
|
+
renderBadge: renderBadge,
|
|
274
|
+
renderIcon: renderIcon,
|
|
275
|
+
renderLabel: renderLabel,
|
|
276
|
+
activeColor: activeColor,
|
|
277
|
+
inactiveColor: inactiveColor,
|
|
278
|
+
pressColor: pressColor,
|
|
279
|
+
pressOpacity: pressOpacity,
|
|
280
|
+
onLayout: isWidthDynamic ? e => {
|
|
281
|
+
measuredTabWidths.current[route.key] = e.nativeEvent.layout.width; // When we have measured widths for all of the tabs, we should updates the state
|
|
282
|
+
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
|
|
283
|
+
// If we have more than 10 routes divide updating tabWidths into multiple batches. Here we update only first batch of 10 items.
|
|
284
|
+
|
|
285
|
+
if (routes.length > MEASURE_PER_BATCH && index === MEASURE_PER_BATCH && routes.slice(0, MEASURE_PER_BATCH).every(r => typeof measuredTabWidths.current[r.key] === 'number')) {
|
|
286
|
+
setTabWidths({ ...measuredTabWidths.current
|
|
287
|
+
});
|
|
288
|
+
} else if (routes.every(r => typeof measuredTabWidths.current[r.key] === 'number')) {
|
|
289
|
+
// When we have measured widths for all of the tabs, we should updates the state
|
|
290
|
+
// We avoid doing separate setState for each layout since it triggers multiple renders and slows down app
|
|
291
|
+
setTabWidths({ ...measuredTabWidths.current
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
} : undefined,
|
|
295
|
+
onPress: () => {
|
|
296
|
+
const event = {
|
|
297
|
+
route,
|
|
298
|
+
defaultPrevented: false,
|
|
299
|
+
preventDefault: () => {
|
|
300
|
+
event.defaultPrevented = true;
|
|
332
301
|
}
|
|
302
|
+
};
|
|
303
|
+
onTabPress === null || onTabPress === void 0 ? void 0 : onTabPress(event);
|
|
304
|
+
|
|
305
|
+
if (event.defaultPrevented) {
|
|
306
|
+
return;
|
|
333
307
|
}
|
|
334
|
-
|
|
335
|
-
|
|
308
|
+
|
|
309
|
+
jumpTo(route.key);
|
|
310
|
+
},
|
|
311
|
+
onLongPress: () => onTabLongPress === null || onTabLongPress === void 0 ? void 0 : onTabLongPress({
|
|
312
|
+
route
|
|
336
313
|
}),
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
314
|
+
labelStyle: labelStyle,
|
|
315
|
+
style: tabStyle,
|
|
316
|
+
// Calculate the deafult width for tab for FlatList to work
|
|
317
|
+
defaultTabWidth: !isWidthDynamic ? getComputedTabWidth(index, layout, routes, scrollEnabled, tabWidths, getFlattenedTabWidth(tabStyle)) : undefined
|
|
318
|
+
};
|
|
319
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, gap > 0 && index > 0 ? /*#__PURE__*/React.createElement(Separator, {
|
|
320
|
+
width: gap
|
|
321
|
+
}) : null, renderTabBarItem ? renderTabBarItem(props) : /*#__PURE__*/React.createElement(TabBarItem, props));
|
|
322
|
+
}, [activeColor, gap, getAccessibilityLabel, getAccessible, getLabelText, getTestID, inactiveColor, isWidthDynamic, jumpTo, labelStyle, layout, navigationState, onTabLongPress, onTabPress, position, pressColor, pressOpacity, renderBadge, renderIcon, renderLabel, renderTabBarItem, routes, scrollEnabled, tabStyle, tabWidths]);
|
|
323
|
+
const keyExtractor = React.useCallback(item => item.key, []);
|
|
324
|
+
const contentContainerStyleMemoized = React.useMemo(() => [styles.tabContent, scrollEnabled ? {
|
|
325
|
+
width: tabBarWidth > separatorsWidth ? tabBarWidth : tabBarWidthPercent
|
|
326
|
+
} : styles.container, contentContainerStyle], [contentContainerStyle, scrollEnabled, separatorsWidth, tabBarWidth, tabBarWidthPercent]);
|
|
327
|
+
const handleScroll = React.useMemo(() => Animated.event([{
|
|
328
|
+
nativeEvent: {
|
|
329
|
+
contentOffset: {
|
|
330
|
+
x: scrollAmount
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}], {
|
|
334
|
+
useNativeDriver: true
|
|
335
|
+
}), [scrollAmount]);
|
|
336
|
+
const handleViewableItemsChanged = useLatestCallback(_ref11 => {
|
|
337
|
+
let {
|
|
338
|
+
changed
|
|
339
|
+
} = _ref11;
|
|
340
340
|
|
|
341
|
-
|
|
341
|
+
if (routes.length <= MEASURE_PER_BATCH) {
|
|
342
|
+
return;
|
|
343
|
+
} // Get next vievable item
|
|
342
344
|
|
|
343
|
-
_defineProperty(TabBar, "defaultProps", {
|
|
344
|
-
getLabelText: _ref3 => {
|
|
345
|
-
let {
|
|
346
|
-
route
|
|
347
|
-
} = _ref3;
|
|
348
|
-
return route.title;
|
|
349
|
-
},
|
|
350
|
-
getAccessible: _ref4 => {
|
|
351
|
-
let {
|
|
352
|
-
route
|
|
353
|
-
} = _ref4;
|
|
354
|
-
return typeof route.accessible !== 'undefined' ? route.accessible : true;
|
|
355
|
-
},
|
|
356
|
-
getAccessibilityLabel: _ref5 => {
|
|
357
|
-
let {
|
|
358
|
-
route
|
|
359
|
-
} = _ref5;
|
|
360
|
-
return typeof route.accessibilityLabel === 'string' ? route.accessibilityLabel : typeof route.title === 'string' ? route.title : undefined;
|
|
361
|
-
},
|
|
362
|
-
getTestID: _ref6 => {
|
|
363
|
-
let {
|
|
364
|
-
route
|
|
365
|
-
} = _ref6;
|
|
366
|
-
return route.testID;
|
|
367
|
-
},
|
|
368
|
-
renderIndicator: props => /*#__PURE__*/React.createElement(TabBarIndicator, props),
|
|
369
|
-
gap: 0
|
|
370
|
-
});
|
|
371
345
|
|
|
346
|
+
const item = changed[changed.length - 1];
|
|
347
|
+
const index = (item === null || item === void 0 ? void 0 : item.index) || 0;
|
|
348
|
+
|
|
349
|
+
if (item.isViewable && (index % 10 === 0 || index === navigationState.index || index === routes.length - 1)) {
|
|
350
|
+
setTabWidths({ ...measuredTabWidths.current
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
return /*#__PURE__*/React.createElement(Animated.View, {
|
|
355
|
+
onLayout: handleLayout,
|
|
356
|
+
style: [styles.tabBar, style]
|
|
357
|
+
}, /*#__PURE__*/React.createElement(Animated.View, {
|
|
358
|
+
pointerEvents: "none",
|
|
359
|
+
style: [styles.indicatorContainer, scrollEnabled ? {
|
|
360
|
+
transform: [{
|
|
361
|
+
translateX
|
|
362
|
+
}]
|
|
363
|
+
} : null, tabBarWidth > separatorsWidth ? {
|
|
364
|
+
width: tabBarWidth - separatorsWidth
|
|
365
|
+
} : scrollEnabled ? {
|
|
366
|
+
width: tabBarWidthPercent
|
|
367
|
+
} : null, indicatorContainerStyle]
|
|
368
|
+
}, renderIndicator({
|
|
369
|
+
position,
|
|
370
|
+
layout,
|
|
371
|
+
navigationState,
|
|
372
|
+
jumpTo,
|
|
373
|
+
width: isWidthDynamic ? 'auto' : `${(100 - separatorPercent) / routes.length}%`,
|
|
374
|
+
style: indicatorStyle,
|
|
375
|
+
getTabWidth: i => getComputedTabWidth(i, layout, routes, scrollEnabled, tabWidths, flattenedTabWidth),
|
|
376
|
+
gap
|
|
377
|
+
})), /*#__PURE__*/React.createElement(View, {
|
|
378
|
+
style: styles.scroll
|
|
379
|
+
}, /*#__PURE__*/React.createElement(Animated.FlatList, {
|
|
380
|
+
data: routes,
|
|
381
|
+
keyExtractor: keyExtractor,
|
|
382
|
+
horizontal: true,
|
|
383
|
+
accessibilityRole: "tablist",
|
|
384
|
+
keyboardShouldPersistTaps: "handled",
|
|
385
|
+
scrollEnabled: scrollEnabled,
|
|
386
|
+
bounces: bounces,
|
|
387
|
+
initialNumToRender: MEASURE_PER_BATCH,
|
|
388
|
+
onViewableItemsChanged: handleViewableItemsChanged,
|
|
389
|
+
alwaysBounceHorizontal: false,
|
|
390
|
+
scrollsToTop: false,
|
|
391
|
+
showsHorizontalScrollIndicator: false,
|
|
392
|
+
showsVerticalScrollIndicator: false,
|
|
393
|
+
automaticallyAdjustContentInsets: false,
|
|
394
|
+
overScrollMode: "never",
|
|
395
|
+
contentContainerStyle: contentContainerStyleMemoized,
|
|
396
|
+
scrollEventThrottle: 16,
|
|
397
|
+
renderItem: renderItem,
|
|
398
|
+
onScroll: handleScroll,
|
|
399
|
+
ref: flatListRef,
|
|
400
|
+
testID: testID
|
|
401
|
+
})));
|
|
402
|
+
}
|
|
372
403
|
const styles = StyleSheet.create({
|
|
373
404
|
container: {
|
|
374
405
|
flex: 1
|