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