feat: upgrade react-native-tab-view to 2.0

BREAKING CHANGES:

- Animated nodes are not from `react-native-reanimated`, which means custom tab bars need to be updated
- Changed behaviour: `activeTintColor` and `inactiveTintColor` also controls opacity now
- Removed props: `animationsEnabled`, `optimizationsEnabled`
- Dropped support for React < 16.3, which means the minimum supported React Native version is 0.56

New features:

- Added prop: `lazyPlaceholderComponent`
This commit is contained in:
Satyajit Sahoo
2019-02-26 22:40:51 +01:00
parent 6dfe7033ab
commit 6486c4b7dd
12 changed files with 289 additions and 360 deletions

View File

@@ -12,9 +12,5 @@
"env": {
"es6": true,
"react-native-globals/all": true,
},
"rules": {
"flowtype/no-dupe-keys": "off"
}
}

View File

@@ -17,7 +17,7 @@
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",
"react-native-safe-area-view": "^0.13.1",
"react-native-screens": "^1.0.0-alpha.22",
"react-native-tab-view": "^1.2.0",
"react-native-tab-view": "^2.0.1",
"react-navigation": "^3.3.2"
},
"devDependencies": {
@@ -27,7 +27,6 @@
},
"resolutions": {
"**/hoist-non-react-statics": "2.5.0",
"**/react-native-tab-view": "1.2.0",
"**/prop-types": "15.6.1"
"**/react-native-tab-view": "2.0.1"
}
}

View File

@@ -741,9 +741,9 @@
integrity sha512-ORj7IBWj13iYufXt/VXrCNMbUuCTJfhzme5kx9U/UtcIPdJYuvPDUAlHlbNhz/8lKCLy9XGIZnGrqXOtQbPGoQ==
"@types/qs@^6.5.1":
version "6.5.2"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.2.tgz#7f347062655056662845ba4bb79dcbfdc382cd61"
integrity sha512-47kAAs3yV/hROraCTQYDMh4p/6zI9+gtssjD0kq9OWsGdLcBge59rl49FnCuJ+iWxEKiqFz6KXzeGH5DRVjNJA==
version "6.5.1"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.1.tgz#a38f69c62528d56ba7bd1f91335a8004988d72f7"
integrity sha512-mNhVdZHdtKHMMxbqzNK3RzkBcN1cux3AvuCYGTvjEIQT2uheH3eCAyYsbMbh2Bq8nXkeOWs1kyDiF7geWRFQ4Q==
"@types/uuid-js@^0.7.1":
version "0.7.2"
@@ -1846,11 +1846,16 @@ core-js@^1.0.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=
core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0, core-js@^2.5.7:
core-js@^2.2.2, core-js@^2.4.1, core-js@^2.5.7:
version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==
core-js@^2.4.0, core-js@^2.5.0:
version "2.6.5"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.5.tgz#44bc8d249e7fb2ff5d00e0341a7ffb94fbf67895"
integrity sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -2232,9 +2237,9 @@ expo-contacts@~2.0.0:
uuid-js "^0.7.5"
expo-core@~2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/expo-core/-/expo-core-2.0.2.tgz#61e1e5cc6c4341a834a0d7f37c68887cee8d971f"
integrity sha512-QKkICJ06m/J1PxTJqtVu03+fUXwjLqb2YPF5J9DT7W4EknPq1sHY3ZKJgAr1PhK24fzvVoxWOKqiIstliZdBOA==
version "2.0.1"
resolved "https://registry.yarnpkg.com/expo-core/-/expo-core-2.0.1.tgz#b7437761adc40ac7689043327c287b6413d0fabd"
integrity sha512-BmQqSHThhnI2xSEWFm4J0uQv5iATwLcY2A0pArjUOT+JK0h2V3x2lt0EZFekjrKwZwIPOwyEYFO1Drzn41Oxsg==
expo-errors@~1.0.0:
version "1.0.0"
@@ -2611,7 +2616,7 @@ fbjs-scripts@^0.8.1:
semver "^5.1.0"
through2 "^2.0.0"
fbjs@0.8.17, fbjs@^0.8.0, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.9:
fbjs@0.8.17, fbjs@^0.8.0, fbjs@^0.8.4, fbjs@^0.8.9:
version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
integrity sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=
@@ -3478,7 +3483,7 @@ lodash@^4.0.0, lodash@^4.16.6, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4,
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -4454,14 +4459,14 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
prop-types@15.6.1, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
version "15.6.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
integrity sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
dependencies:
fbjs "^0.8.16"
loose-envify "^1.3.1"
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.8.1"
pseudomap@^1.0.2:
version "1.0.2"
@@ -4533,6 +4538,11 @@ react-is@^16.5.2:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.5.2.tgz#e2a7b7c3f5d48062eb769fcb123505eb928722e3"
integrity sha512-hSl7E6l25GTjNEZATqZIuWOgSnpXb3kD0DVCujmg46K5zLxsbiKaaT6VO9slkSBDPZfYs30lwfJwbOFOnoEnKQ==
react-is@^16.8.1:
version "16.8.3"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d"
integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA==
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@@ -4544,9 +4554,9 @@ react-native-branch@2.2.5:
integrity sha1-QHTdY7SXPmOX2c5Q6XtXx3pRjp0=
react-native-gesture-handler@~1.0.14:
version "1.0.17"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.17.tgz#a046f371f277092157fc2781323d35a02a93daaf"
integrity sha512-0czy7SZvF4q2aCQUGFaBu/yBjYYEbcqSU1/r2bZ/IoXj+DgYuIPBL60SSXhJdYJU8G3brfUHmtgSdcNte8Lh0w==
version "1.0.16"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.16.tgz#bee54981575e581857c2298e133ce2ffac240a3e"
integrity sha512-KhUjDaiGKESfVa/lywuYfdZ2pomPC4q/dRQo18qlSZuRxEiOCxzSo9Q1TV7JK3PpyyMEXpsU04kYSSVypWiSxg==
dependencies:
hoist-non-react-statics "^2.3.1"
invariant "^2.2.2"
@@ -4561,7 +4571,14 @@ react-native-reanimated@1.0.0-alpha.11:
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-1.0.0-alpha.11.tgz#b78c839bae878d149561b56a3c750414957ea86d"
integrity sha512-lDakjY8CXmZiSN71hyc276b3d7M9mKV9ZyYw4W/rTnnJbgBFaqdIxSHq4S4LxSbVqpAoQMfUJqPTE0BKbAz7Aw==
react-native-safe-area-view@^0.13.0, react-native-safe-area-view@^0.13.1:
react-native-safe-area-view@^0.13.0:
version "0.13.0"
resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.13.0.tgz#f2374f256121647e8aa2f1e9ada083426a266367"
integrity sha512-k8F527IHtQrRSynibY49ryrHLtOvjtE1GqLxULMnH0PIjSITe+nbq4nx75xrZTwd7sSoLbX6lgroZTG8AO3iUw==
dependencies:
hoist-non-react-statics "^2.3.1"
react-native-safe-area-view@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.13.1.tgz#834bbb6d22f76a7ff07de56725ee5667ba1386b0"
integrity sha512-d/pu2866jApSwLtK/xWAvMXZkNTIQcFrjjbcTATBrmIfFNnu8TNFUcMRFpfJ+eOn5nmx7uGmDvs9B53Ft7JGpQ==
@@ -4589,12 +4606,10 @@ react-native-svg@8.0.10:
lodash "^4.16.6"
pegjs "^0.10.0"
react-native-tab-view@1.2.0, react-native-tab-view@^1.0.0, react-native-tab-view@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-1.2.0.tgz#0cc26a1c8e49b6c0d58a30363dbbe43954907c31"
integrity sha512-lpiWi3dog86Fu/W60DU12RKrFv3XuTv0lHMC56t2jlDqxLfVzG9ufV7li6Afl2S2ZicNU1Bob8WPgxVZc8egAA==
dependencies:
prop-types "^15.6.1"
react-native-tab-view@2.0.1, react-native-tab-view@^1.0.0, react-native-tab-view@^1.2.0, react-native-tab-view@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.0.1.tgz#67ad94be00d751f35367838bb7b089361e58af5d"
integrity sha512-kA8CHrcJk7TJA1S55FUL2sN9zjnKzEBg0FpK8MnZnvuuopUQOiLgLauX/rJeQMWg3uBIpGdMajNkRxGwvJkgyA==
react-native-vector-icons@6.0.0:
version "6.0.0"

View File

@@ -37,9 +37,8 @@
"homepage": "https://github.com/react-navigation/react-navigation-tabs#readme",
"dependencies": {
"hoist-non-react-statics": "^2.5.0",
"prop-types": "^15.6.1",
"react-lifecycles-compat": "^3.0.4",
"react-native-tab-view": "^1.2.0"
"react-native-tab-view": "^2.0.1"
},
"devDependencies": {
"@commitlint/config-conventional": "^7.5.0",
@@ -68,6 +67,8 @@
"peerDependencies": {
"react": "*",
"react-native": "*",
"react-native-gesture-handler": "^1.0.0",
"react-native-reanimated": "^1.0.0-alpha",
"react-native-screens": "^1.0.0 || ^1.0.0-alpha"
},
"husky": {

View File

@@ -2,7 +2,6 @@
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import { polyfill } from 'react-lifecycles-compat';
// eslint-disable-next-line import/no-unresolved
import { ScreenContainer } from 'react-native-screens';
@@ -43,6 +42,18 @@ class TabNavigationView extends React.PureComponent<Props, State> {
loaded: [this.props.navigation.state.index],
};
_getButtonComponent = ({ route }) => {
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
const options = descriptor.options;
if (options.tabBarButtonComponent) {
return options.tabBarButtonComponent;
}
return null;
};
_renderTabBar = () => {
const {
tabBarComponent: TabBarComponent = BottomTabBar,
@@ -51,7 +62,6 @@ class TabNavigationView extends React.PureComponent<Props, State> {
screenProps,
getLabelText,
getAccessibilityLabel,
getButtonComponent,
getTestID,
renderIcon,
onTabPress,
@@ -77,7 +87,7 @@ class TabNavigationView extends React.PureComponent<Props, State> {
onTabPress={onTabPress}
onTabLongPress={onTabLongPress}
getLabelText={getLabelText}
getButtonComponent={getButtonComponent}
getButtonComponent={this._getButtonComponent}
getAccessibilityLabel={getAccessibilityLabel}
getTestID={getTestID}
renderIcon={renderIcon}
@@ -126,8 +136,6 @@ class TabNavigationView extends React.PureComponent<Props, State> {
}
}
polyfill(TabNavigationView);
const styles = StyleSheet.create({
container: {
flex: 1,

View File

@@ -1,77 +1,44 @@
/* @flow */
import * as React from 'react';
import { View, Platform } from 'react-native';
import { polyfill } from 'react-lifecycles-compat';
import { TabView, PagerPan } from 'react-native-tab-view';
import { TabView } from 'react-native-tab-view';
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
import createTabNavigator, {
type InjectedProps,
} from '../utils/createTabNavigator';
import MaterialTopTabBar, {
type TabBarOptions,
} from '../views/MaterialTopTabBar';
import ResourceSavingScene from '../views/ResourceSavingScene';
type Props = InjectedProps & {
animationEnabled?: boolean,
lazy?: boolean,
optimizationsEnabled?: boolean,
type Route = {
key: string,
routeName: string,
};
type Props = {|
...InjectedProps,
keyboardDismissMode?: 'none' | 'on-drag',
swipeEnabled?: boolean,
renderPager?: (props: *) => React.Node,
swipeDistanceThreshold?: number,
swipeVelocityThreshold?: number,
onSwipeStart?: () => mixed,
onSwipeEnd?: () => mixed,
initialLayout?: { width?: number, height?: number },
lazy?: boolean,
lazyPlaceholderComponent?: React.ComponentType<{ route: Route }>,
tabBarComponent?: React.ComponentType<*>,
tabBarOptions?: TabBarOptions,
tabBarPosition?: 'top' | 'bottom',
};
sceneContainerStyle?: ViewStyleProp,
style?: ViewStyleProp,
|};
type State = {
index: number,
isSwiping: boolean,
loaded: Array<number>,
transitioningFromIndex: ?number,
};
class MaterialTabView extends React.PureComponent<Props> {
_renderLazyPlaceholder = props => {
const { lazyPlaceholderComponent: LazyPlaceholder } = this.props;
class MaterialTabView extends React.PureComponent<Props, State> {
static defaultProps = {
// fix for https://github.com/react-native-community/react-native-tab-view/issues/312
initialLayout: Platform.select({
android: { width: 1, height: 0 },
}),
animationEnabled: true,
lazy: false,
optimizationsEnabled: false,
};
static getDerivedStateFromProps(nextProps, prevState) {
const { index } = nextProps.navigation.state;
if (prevState.index === index) {
return null;
}
return {
loaded: prevState.loaded.includes(index)
? prevState.loaded
: [...prevState.loaded, index],
index,
};
}
state = {
index: 0,
isSwiping: false,
loaded: [this.props.navigation.state.index],
transitioningFromIndex: null,
};
_renderIcon = ({ focused, route, tintColor }) => {
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
const options = descriptor.options;
if (options.tabBarIcon) {
return typeof options.tabBarIcon === 'function'
? options.tabBarIcon({ tintColor, focused })
: options.tabBarIcon;
if (LazyPlaceholder != null) {
return <LazyPlaceholder {...props} />;
}
return null;
@@ -88,9 +55,17 @@ class MaterialTabView extends React.PureComponent<Props, State> {
options.tabBarVisible == null ? true : options.tabBarVisible;
const {
navigation,
getLabelText,
getAccessibilityLabel,
getTestID,
renderIcon,
onTabPress,
onTabLongPress,
tabBarComponent: TabBarComponent = MaterialTopTabBar,
tabBarPosition,
tabBarOptions,
screenProps,
} = this.props;
if (TabBarComponent === null || !tabBarVisible) {
@@ -98,136 +73,44 @@ class MaterialTabView extends React.PureComponent<Props, State> {
}
return (
/* $FlowFixMe */
<TabBarComponent
{...tabBarOptions}
{...props}
tabBarPosition={tabBarPosition}
screenProps={this.props.screenProps}
navigation={this.props.navigation}
getLabelText={this.props.getLabelText}
getAccessibilityLabel={this.props.getAccessibilityLabel}
getTestID={this.props.getTestID}
renderIcon={this._renderIcon}
onTabPress={this.props.onTabPress}
onTabLongPress={this.props.onTabLongPress}
screenProps={screenProps}
navigation={navigation}
getLabelText={getLabelText}
getAccessibilityLabel={getAccessibilityLabel}
getTestID={getTestID}
renderIcon={renderIcon}
onTabPress={onTabPress}
onTabLongPress={onTabLongPress}
/>
);
};
_renderPanPager = props => <PagerPan {...props} />;
_handleAnimationEnd = () => {
const { lazy } = this.props;
if (lazy) {
this.setState({
transitioningFromIndex: null,
isSwiping: false,
});
}
};
_handleSwipeStart = () => {
const { navigation, lazy } = this.props;
if (lazy) {
this.setState({
isSwiping: true,
loaded: [
...new Set([
...this.state.loaded,
Math.max(navigation.state.index - 1, 0),
Math.min(
navigation.state.index + 1,
navigation.state.routes.length - 1
),
]),
],
});
}
};
_handleIndexChange = index => {
const { animationEnabled, navigation, onIndexChange, lazy } = this.props;
if (lazy && animationEnabled) {
this.setState({
transitioningFromIndex: navigation.state.index || 0,
});
}
onIndexChange(index);
};
_mustBeVisible = ({ index, focused }) => {
const { animationEnabled, navigation } = this.props;
const { isSwiping, transitioningFromIndex } = this.state;
if (isSwiping) {
const isSibling =
navigation.state.index === index - 1 ||
navigation.state.index === index + 1;
if (isSibling) {
return true;
}
}
// The previous tab should remain visible while transitioning
if (animationEnabled && transitioningFromIndex === index) {
return true;
}
return focused;
};
_renderScene = ({ route }) => {
const { renderScene, descriptors, lazy, optimizationsEnabled } = this.props;
if (lazy) {
const { loaded } = this.state;
const { routes } = this.props.navigation.state;
const index = routes.findIndex(({ key }) => key === route.key);
const { navigation } = descriptors[route.key];
const mustBeVisible = this._mustBeVisible({
index,
focused: navigation.isFocused(),
});
if (!loaded.includes(index) && !mustBeVisible) {
return <View />;
}
if (optimizationsEnabled) {
return (
<ResourceSavingScene isVisible={mustBeVisible}>
{renderScene({ route })}
</ResourceSavingScene>
);
}
}
return renderScene({ route });
};
render() {
const {
/* eslint-disable no-unused-vars */
getLabelText,
getAccessibilityLabel,
getTestID,
renderIcon,
onTabPress,
onTabLongPress,
screenProps,
lazyPlaceholderComponent,
tabBarComponent,
tabBarOptions,
/* eslint-enable no-unused-vars */
navigation,
animationEnabled,
// eslint-disable-next-line no-unused-vars
renderScene,
// eslint-disable-next-line no-unused-vars
onIndexChange,
descriptors,
...rest
} = this.props;
let renderPager = rest.renderPager;
const { state } = this.props.navigation;
const { state } = navigation;
const route = state.routes[state.index];
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
const options = descriptor.options;
@@ -240,30 +123,16 @@ class MaterialTabView extends React.PureComponent<Props, State> {
swipeEnabled = swipeEnabled(state);
}
if (animationEnabled === false && swipeEnabled === false) {
renderPager = this._renderPanPager;
}
return (
<TabView
{...rest}
navigationState={navigation.state}
animationEnabled={animationEnabled}
swipeEnabled={swipeEnabled}
onAnimationEnd={this._handleAnimationEnd}
onIndexChange={this._handleIndexChange}
onSwipeStart={this._handleSwipeStart}
renderPager={renderPager}
renderTabBar={this._renderTabBar}
renderScene={
/* $FlowFixMe */
this._renderScene
}
renderLazyPlaceholder={this._renderLazyPlaceholder}
/>
);
}
}
polyfill(MaterialTabView);
export default createTabNavigator(MaterialTabView);

View File

@@ -9,16 +9,15 @@ import {
NavigationActions,
} from '@react-navigation/core';
export type InjectedProps = {
export type InjectedProps = {|
getLabelText: (props: { route: any }) => any,
getAccessibilityLabel: (props: { route: any }) => string,
getTestID: (props: { route: any }) => string,
getButtonComponent: (props: { route: any }) => ?React.Component<*>,
renderIcon: (props: {
route: any,
focused: boolean,
tintColor: string,
horizontal: boolean,
horizontal?: boolean,
}) => React.Node,
renderScene: (props: { route: any }) => ?React.Node,
onIndexChange: (index: number) => any,
@@ -27,7 +26,7 @@ export type InjectedProps = {
navigation: any,
descriptors: any,
screenProps?: any,
};
|};
export default function createTabNavigator(TabView: React.ComponentType<*>) {
class NavigationView extends React.Component<*, *> {
@@ -44,12 +43,7 @@ export default function createTabNavigator(TabView: React.ComponentType<*>) {
);
};
_renderIcon = ({
route,
focused = true,
tintColor,
horizontal = false,
}) => {
_renderIcon = ({ route, focused, tintColor, horizontal = false }) => {
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
const options = descriptor.options;
@@ -63,18 +57,6 @@ export default function createTabNavigator(TabView: React.ComponentType<*>) {
return null;
};
_getButtonComponent = ({ route }) => {
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
const options = descriptor.options;
if (options.tabBarButtonComponent) {
return options.tabBarButtonComponent;
}
return null;
};
_getLabelText = ({ route }) => {
const { descriptors } = this.props;
const descriptor = descriptors[route.key];
@@ -197,7 +179,6 @@ export default function createTabNavigator(TabView: React.ComponentType<*>) {
<TabView
{...options}
getLabelText={this._getLabelText}
getButtonComponent={this._getButtonComponent}
getAccessibilityLabel={this._getAccessibilityLabel}
getTestID={this._getTestID}
renderIcon={this._renderIcon}

View File

@@ -2,13 +2,13 @@
import React from 'react';
import {
Animated,
TouchableWithoutFeedback,
StyleSheet,
View,
Platform,
} from 'react-native';
import { SafeAreaView } from '@react-navigation/native';
import Animated from 'react-native-reanimated';
import CrossFadeIcon from './CrossFadeIcon';
import withDimensions from '../utils/withDimensions';

View File

@@ -1,7 +1,8 @@
/* @flow */
import React from 'react';
import { Animated, View, StyleSheet } from 'react-native';
import { View, StyleSheet } from 'react-native';
import Animated from 'react-native-reanimated';
type Props = {
route: any,

View File

@@ -1,55 +1,83 @@
/* @flow */
import * as React from 'react';
import { Animated, StyleSheet } from 'react-native';
import { View, StyleSheet } from 'react-native';
import { TabBar } from 'react-native-tab-view';
import CrossFadeIcon from './CrossFadeIcon';
import Animated from 'react-native-reanimated';
import type {
ViewStyleProp,
TextStyleProp,
} from 'react-native/Libraries/StyleSheet/StyleSheet';
export type TabBarOptions = {
activeTintColor?: string,
inactiveTintColor?: string,
showLabel?: boolean,
showIcon?: boolean,
upperCaseLabel?: boolean,
labelStyle?: any,
iconStyle?: any,
allowFontScaling?: boolean,
type Route = {
key: string,
routeName: string,
};
type Props = TabBarOptions & {
position: Animated.Value,
offsetX: Animated.Value,
panX: Animated.Value,
layout: any,
navigation: any,
renderIcon: (props: {
route: any,
type Layout = {|
width: number,
height: number,
|};
type Listener = (value: number) => mixed;
export type TabBarOptions = {|
activeTintColor?: string,
allowFontScaling?: boolean,
bounces?: boolean,
inactiveTintColor?: string,
pressColor?: string,
pressOpacity?: number,
scrollEnabled?: boolean,
showIcon?: boolean,
showLabel?: boolean,
upperCaseLabel?: boolean,
tabStyle?: ViewStyleProp,
indicatorStyle?: ViewStyleProp,
iconStyle?: any,
labelStyle?: TextStyleProp,
contentContainerStyle?: ViewStyleProp,
style?: ViewStyleProp,
|};
type Props = {|
...TabBarOptions,
layout: Layout,
position: Animated.Node<number>,
jumpTo: (key: string) => void,
addListener: (type: 'position', listener: Listener) => void,
removeListener: (type: 'position', listener: Listener) => void,
getLabelText: (scene: { route: Route }) => ?string,
getAccessible?: (scene: { route: Route }) => ?boolean,
getAccessibilityLabel: (scene: { route: Route }) => ?string,
getTestID: (scene: { route: Route }) => ?string,
renderIcon: (scene: {
route: Route,
focused: boolean,
tintColor: string,
horizontal?: boolean,
}) => React.Node,
getLabelText: (props: { route: any }) => any,
getAccessibilityLabel: (props: { route: any }) => string,
getTestID: (props: { route: any }) => string,
useNativeDriver?: boolean,
jumpTo: (key: string) => any,
};
renderBadge?: (scene: { route: Route }) => React.Node,
onTabPress?: (scene: { route: Route }) => mixed,
onTabLongPress?: (scene: { route: Route }) => mixed,
tabBarPosition: 'top' | 'bottom',
navigationState: any,
screenProps: any,
navigation: any,
|};
export default class TabBarTop extends React.PureComponent<Props> {
static defaultProps = {
activeTintColor: '#fff',
inactiveTintColor: '#fff',
activeTintColor: 'rgba(255, 255, 255, 1)',
inactiveTintColor: 'rgba(255, 255, 255, 0.7)',
showIcon: false,
showLabel: true,
upperCaseLabel: true,
allowFontScaling: true,
};
_renderLabel = ({ route }) => {
_renderLabel = ({ route, focused, color }) => {
const {
position,
navigation,
activeTintColor,
inactiveTintColor,
showLabel,
upperCaseLabel,
labelStyle,
@@ -60,21 +88,6 @@ export default class TabBarTop extends React.PureComponent<Props> {
return null;
}
const { routes } = navigation.state;
const index = routes.indexOf(route);
const focused = index === navigation.state.index;
// Prepend '-1', so there are always at least 2 items in inputRange
const inputRange = [-1, ...routes.map((x, i) => i)];
const outputRange = inputRange.map(inputIndex =>
inputIndex === index ? activeTintColor : inactiveTintColor
);
const color = position.interpolate({
inputRange,
outputRange: outputRange,
});
const tintColor = focused ? activeTintColor : inactiveTintColor;
const label = this.props.getLabelText({ route });
if (typeof label === 'string') {
@@ -87,63 +100,57 @@ export default class TabBarTop extends React.PureComponent<Props> {
</Animated.Text>
);
}
if (typeof label === 'function') {
return label({ focused, tintColor });
return label({ focused, tintColor: color });
}
return label;
};
_renderIcon = ({ route }) => {
const {
position,
navigation,
activeTintColor,
inactiveTintColor,
renderIcon,
showIcon,
iconStyle,
} = this.props;
_renderIcon = ({ route, focused, color }) => {
const { renderIcon, showIcon, iconStyle } = this.props;
if (showIcon === false) {
return null;
}
const index = navigation.state.routes.indexOf(route);
// Prepend '-1', so there are always at least 2 items in inputRange
const inputRange = [-1, ...navigation.state.routes.map((x, i) => i)];
const activeOpacity = position.interpolate({
inputRange,
outputRange: inputRange.map(i => (i === index ? 1 : 0)),
});
const inactiveOpacity = position.interpolate({
inputRange,
outputRange: inputRange.map(i => (i === index ? 0 : 1)),
});
return (
<CrossFadeIcon
route={route}
navigation={navigation}
activeOpacity={activeOpacity}
inactiveOpacity={inactiveOpacity}
activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor}
renderIcon={renderIcon}
style={[styles.icon, iconStyle]}
/>
<View style={[styles.icon, iconStyle]}>
{renderIcon({
route,
focused,
tintColor: color,
})}
</View>
);
};
render() {
/* eslint-disable no-unused-vars */
const { navigation, renderIcon, getLabelText, ...rest } = this.props;
const {
navigation,
activeTintColor,
inactiveTintColor,
/* eslint-disable no-unused-vars */
renderIcon,
getLabelText,
allowFontScaling,
showLabel,
showIcon,
upperCaseLabel,
tabBarPosition,
navigationState,
screenProps,
iconStyle,
/* eslint-enable no-unused-vars */
...rest
} = this.props;
return (
/* $FlowFixMe */
<TabBar
{...rest}
activeColor={activeTintColor}
inactiveColor={inactiveTintColor}
navigationState={navigation.state}
renderIcon={this._renderIcon}
renderLabel={this._renderLabel}
@@ -160,7 +167,7 @@ const styles = StyleSheet.create({
label: {
textAlign: 'center',
fontSize: 13,
margin: 8,
margin: 4,
backgroundColor: 'transparent',
},
});

View File

@@ -20,6 +20,7 @@ export default class ResourceSavingScene extends React.Component<Props> {
const { isVisible, ...rest } = this.props;
return <Screen active={isVisible ? 1 : 0} {...rest} />;
}
const { isVisible, children, style, ...rest } = this.props;
return (

View File

@@ -47,7 +47,7 @@
source-map "^0.5.0"
trim-right "^1.0.1"
"@babel/generator@^7.0.0", "@babel/generator@^7.3.4":
"@babel/generator@^7.0.0", "@babel/generator@^7.1.3", "@babel/generator@^7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e"
integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg==
@@ -283,7 +283,7 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4":
"@babel/parser@^7.0.0", "@babel/parser@^7.1.2", "@babel/parser@^7.1.3", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c"
integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ==
@@ -344,9 +344,9 @@
"@babel/plugin-syntax-optional-chaining" "^7.2.0"
"@babel/plugin-syntax-class-properties@^7.0.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.2.0.tgz#23b3b7b9bcdabd73672a9149f728cd3be6214812"
integrity sha512-UxYaGXYQ7rrKJS/PxIKRkv3exi05oH7rokBAsmCSsCxz1sVPZ7Fu6FzKoGgUvmY+0YgSkYHgUoCh5R5bCNBQlw==
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0.tgz#e051af5d300cbfbcec4a7476e37a803489881634"
integrity sha512-cR12g0Qzn4sgkjrbrzWy2GE7m9vMl/sFkqZ3gIpAQdrvPDnLM8180i+ANDFIXfjHo9aqp0ccJlQ0QNZcFUbf9w==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
@@ -371,7 +371,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.2.0":
"@babel/plugin-syntax-jsx@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.0.0.tgz#034d5e2b4e14ccaea2e4c137af7e4afb39375ffd"
integrity sha512-PdmL2AoPsCLWxhIr3kG2+F9v4WH06Q3z+NoGVpQgnUNGcagXHq5sB3OXxkSahKq9TLdNMN/AJzFYSOo8UKDMHg==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-jsx@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.2.0.tgz#0b85a3b4bc7cdf4cc4b8bf236335b907ca22e7c7"
integrity sha512-VyN4QANJkRW6lDBmENzRszvZf3/4AXaj9YR7GwrWeeN9tEBPuXbmDYVU9bYBN0D70zCWVwUy0HWq2553VCb6Hw==
@@ -385,7 +392,14 @@
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.2.0":
"@babel/plugin-syntax-object-rest-spread@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b"
integrity sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==
dependencies:
"@babel/helper-plugin-utils" "^7.0.0"
"@babel/plugin-syntax-object-rest-spread@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
integrity sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==
@@ -675,7 +689,7 @@
babylon "7.0.0-beta.44"
lodash "^4.2.0"
"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2", "@babel/template@^7.2.2":
"@babel/template@^7.0.0", "@babel/template@^7.2.2":
version "7.2.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907"
integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==
@@ -684,6 +698,15 @@
"@babel/parser" "^7.2.2"
"@babel/types" "^7.2.2"
"@babel/template@^7.1.0", "@babel/template@^7.1.2":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644"
integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/parser" "^7.1.2"
"@babel/types" "^7.1.2"
"@babel/traverse@7.0.0-beta.44":
version "7.0.0-beta.44"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966"
@@ -700,7 +723,7 @@
invariant "^2.2.0"
lodash "^4.2.0"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4":
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06"
integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ==
@@ -715,6 +738,21 @@
globals "^11.1.0"
lodash "^4.17.11"
"@babel/traverse@^7.1.0":
version "7.1.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.4.tgz#f4f83b93d649b4b2c91121a9087fa2fa949ec2b4"
integrity sha512-my9mdrAIGdDiSVBuMjpn/oXYpva0/EZwWL3sm3Wcy/AVWO2eXnsoZruOT9jOGNRXU8KbCIu5zsKnXcAJ6PcV6Q==
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/generator" "^7.1.3"
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-split-export-declaration" "^7.0.0"
"@babel/parser" "^7.1.3"
"@babel/types" "^7.1.3"
debug "^3.1.0"
globals "^11.1.0"
lodash "^4.17.10"
"@babel/types@7.0.0-beta.44":
version "7.0.0-beta.44"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757"
@@ -724,7 +762,16 @@
lodash "^4.2.0"
to-fast-properties "^2.0.0"
"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.4":
"@babel/types@^7.0.0":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d"
integrity sha512-RpPOVfK+yatXyn8n4PB1NW6k9qjinrXrRR8ugBN8fD6hCy5RXI6PSbVqpOJBO9oSaY7Nom4ohj35feb0UR9hSA==
dependencies:
esutils "^2.0.2"
lodash "^4.17.10"
to-fast-properties "^2.0.0"
"@babel/types@^7.1.2", "@babel/types@^7.1.3", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.3.4":
version "7.3.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed"
integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==
@@ -5329,7 +5376,7 @@ log-symbols@^2.2.0:
dependencies:
chalk "^2.0.1"
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -6642,13 +6689,12 @@ promise@^7.1.1:
asap "~2.0.3"
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
integrity sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==
dependencies:
loose-envify "^1.4.0"
loose-envify "^1.3.1"
object-assign "^4.1.1"
react-is "^16.8.1"
protocols@^1.1.0, protocols@^1.4.0:
version "1.4.7"
@@ -6783,7 +6829,7 @@ react-dom@16.5.0:
prop-types "^15.6.2"
schedule "^0.3.0"
react-is@^16.5.0, react-is@^16.5.2, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.3:
react-is@^16.5.0, react-is@^16.5.2, react-is@^16.7.0, react-is@^16.8.3:
version "16.8.3"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d"
integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA==
@@ -6794,9 +6840,9 @@ react-lifecycles-compat@^3.0.4:
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-native-gesture-handler@~1.0.14:
version "1.0.17"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.17.tgz#a046f371f277092157fc2781323d35a02a93daaf"
integrity sha512-0czy7SZvF4q2aCQUGFaBu/yBjYYEbcqSU1/r2bZ/IoXj+DgYuIPBL60SSXhJdYJU8G3brfUHmtgSdcNte8Lh0w==
version "1.0.16"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.16.tgz#bee54981575e581857c2298e133ce2ffac240a3e"
integrity sha512-KhUjDaiGKESfVa/lywuYfdZ2pomPC4q/dRQo18qlSZuRxEiOCxzSo9Q1TV7JK3PpyyMEXpsU04kYSSVypWiSxg==
dependencies:
hoist-non-react-statics "^2.3.1"
invariant "^2.2.2"
@@ -6808,9 +6854,9 @@ react-native-reanimated@^1.0.0-alpha.12:
integrity sha512-jZDPxz8IjpoZ7VAW5X6WJhemmpuLkX6Y9lxKuHJAXls1EwRYkyXIPwvSG34umeqqYSE8Hl3A5TS4pfLORoqm/A==
react-native-safe-area-view@^0.13.0:
version "0.13.1"
resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.13.1.tgz#834bbb6d22f76a7ff07de56725ee5667ba1386b0"
integrity sha512-d/pu2866jApSwLtK/xWAvMXZkNTIQcFrjjbcTATBrmIfFNnu8TNFUcMRFpfJ+eOn5nmx7uGmDvs9B53Ft7JGpQ==
version "0.13.0"
resolved "https://registry.yarnpkg.com/react-native-safe-area-view/-/react-native-safe-area-view-0.13.0.tgz#f2374f256121647e8aa2f1e9ada083426a266367"
integrity sha512-k8F527IHtQrRSynibY49ryrHLtOvjtE1GqLxULMnH0PIjSITe+nbq4nx75xrZTwd7sSoLbX6lgroZTG8AO3iUw==
dependencies:
hoist-non-react-statics "^2.3.1"
@@ -6826,6 +6872,11 @@ react-native-tab-view@^1.0.0, react-native-tab-view@^1.2.0:
dependencies:
prop-types "^15.6.1"
react-native-tab-view@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.0.1.tgz#67ad94be00d751f35367838bb7b089361e58af5d"
integrity sha512-kA8CHrcJk7TJA1S55FUL2sN9zjnKzEBg0FpK8MnZnvuuopUQOiLgLauX/rJeQMWg3uBIpGdMajNkRxGwvJkgyA==
react-native-vector-icons@4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-4.5.0.tgz#6b95619e64f62f05f579f74a01fe5640df95158b"