From 6486c4b7dddf321470c357b85ab5d63dd8bcc511 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Tue, 26 Feb 2019 22:40:51 +0100 Subject: [PATCH] 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` --- packages/tabs/.eslintrc | 4 - packages/tabs/example/package.json | 5 +- packages/tabs/example/yarn.lock | 65 +++-- packages/tabs/package.json | 5 +- .../navigators/createBottomTabNavigator.js | 18 +- .../createMaterialTopTabNavigator.js | 245 ++++-------------- packages/tabs/src/utils/createTabNavigator.js | 27 +- packages/tabs/src/views/BottomTabBar.js | 2 +- packages/tabs/src/views/CrossFadeIcon.js | 3 +- packages/tabs/src/views/MaterialTopTabBar.js | 177 +++++++------ .../tabs/src/views/ResourceSavingScene.js | 1 + packages/tabs/yarn.lock | 97 +++++-- 12 files changed, 289 insertions(+), 360 deletions(-) diff --git a/packages/tabs/.eslintrc b/packages/tabs/.eslintrc index ca33a085..bf4c186c 100644 --- a/packages/tabs/.eslintrc +++ b/packages/tabs/.eslintrc @@ -12,9 +12,5 @@ "env": { "es6": true, "react-native-globals/all": true, - }, - - "rules": { - "flowtype/no-dupe-keys": "off" } } diff --git a/packages/tabs/example/package.json b/packages/tabs/example/package.json index 38b9ba4b..17acb7fb 100644 --- a/packages/tabs/example/package.json +++ b/packages/tabs/example/package.json @@ -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" } } diff --git a/packages/tabs/example/yarn.lock b/packages/tabs/example/yarn.lock index aa0adf70..9443143a 100644 --- a/packages/tabs/example/yarn.lock +++ b/packages/tabs/example/yarn.lock @@ -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" diff --git a/packages/tabs/package.json b/packages/tabs/package.json index cf433f31..a4ecef23 100644 --- a/packages/tabs/package.json +++ b/packages/tabs/package.json @@ -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": { diff --git a/packages/tabs/src/navigators/createBottomTabNavigator.js b/packages/tabs/src/navigators/createBottomTabNavigator.js index 09748f83..3d2e307f 100644 --- a/packages/tabs/src/navigators/createBottomTabNavigator.js +++ b/packages/tabs/src/navigators/createBottomTabNavigator.js @@ -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 { 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 { screenProps, getLabelText, getAccessibilityLabel, - getButtonComponent, getTestID, renderIcon, onTabPress, @@ -77,7 +87,7 @@ class TabNavigationView extends React.PureComponent { 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 { } } -polyfill(TabNavigationView); - const styles = StyleSheet.create({ container: { flex: 1, diff --git a/packages/tabs/src/navigators/createMaterialTopTabNavigator.js b/packages/tabs/src/navigators/createMaterialTopTabNavigator.js index 79d2e727..076b98c7 100644 --- a/packages/tabs/src/navigators/createMaterialTopTabNavigator.js +++ b/packages/tabs/src/navigators/createMaterialTopTabNavigator.js @@ -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, - transitioningFromIndex: ?number, -}; +class MaterialTabView extends React.PureComponent { + _renderLazyPlaceholder = props => { + const { lazyPlaceholderComponent: LazyPlaceholder } = this.props; -class MaterialTabView extends React.PureComponent { - 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 ; } return null; @@ -88,9 +55,17 @@ class MaterialTabView extends React.PureComponent { 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 { } return ( - /* $FlowFixMe */ ); }; - _renderPanPager = 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 ; - } - - if (optimizationsEnabled) { - return ( - - {renderScene({ route })} - - ); - } - } - - 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 { swipeEnabled = swipeEnabled(state); } - if (animationEnabled === false && swipeEnabled === false) { - renderPager = this._renderPanPager; - } - return ( ); } } -polyfill(MaterialTabView); - export default createTabNavigator(MaterialTabView); diff --git a/packages/tabs/src/utils/createTabNavigator.js b/packages/tabs/src/utils/createTabNavigator.js index bba47634..73789f1b 100644 --- a/packages/tabs/src/utils/createTabNavigator.js +++ b/packages/tabs/src/utils/createTabNavigator.js @@ -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<*>) { 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, + 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 { 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 { 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 { ); } + 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 ( - + + {renderIcon({ + route, + focused, + tintColor: color, + })} + ); }; 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 */ { const { isVisible, ...rest } = this.props; return ; } + const { isVisible, children, style, ...rest } = this.props; return ( diff --git a/packages/tabs/yarn.lock b/packages/tabs/yarn.lock index f125a5e8..d4b4b532 100644 --- a/packages/tabs/yarn.lock +++ b/packages/tabs/yarn.lock @@ -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"