diff --git a/packages/react-navigation/.babelrc b/packages/react-navigation/.babelrc index 0e20a369..9066cadc 100644 --- a/packages/react-navigation/.babelrc +++ b/packages/react-navigation/.babelrc @@ -5,29 +5,32 @@ "development": { "presets": ["react-native"], "plugins": [ - "transform-flow-strip-types", - ], + "flow-react-proptypes", + "transform-flow-strip-types" + ] }, // For Jest "test": { "presets": ["react-native"], "plugins": [ - "transform-flow-strip-types", - ], + "transform-flow-strip-types" + ] }, // For publishing to NPM for RN "publish-rn": { "presets": ["react-native-syntax"], "plugins": [ - "transform-flow-strip-types", - ], + "flow-react-proptypes", + "transform-flow-strip-types" + ] }, // For publishing to NPM for web "publish-web": { "presets": ["es2015", "stage-1", "react"], "plugins": [ - "transform-flow-strip-types", - ], - }, - }, + "flow-react-proptypes", + "transform-flow-strip-types" + ] + } + } } diff --git a/packages/react-navigation/.eslintrc b/packages/react-navigation/.eslintrc index f6b6bc9a..ed710b1e 100644 --- a/packages/react-navigation/.eslintrc +++ b/packages/react-navigation/.eslintrc @@ -23,10 +23,15 @@ "react/jsx-filename-extension": [ 0, { "extensions": [".js", ".jsx"] } ], - "react/forbid-prop-types": 0, + "react/sort-comp": 0, "react/prefer-stateless-function": 0, + "react/forbid-prop-types": 1, + "react/prop-types": 0, + "react/require-default-props": 0, + "react/no-unused-prop-types": 0, + "flowtype/boolean-style": [ 2, "boolean" diff --git a/packages/react-navigation/package.json b/packages/react-navigation/package.json index 93cc0ff3..01b92db2 100644 --- a/packages/react-navigation/package.json +++ b/packages/react-navigation/package.json @@ -28,6 +28,7 @@ "run-playground-ios": "cd examples/NavigationPlayground && react-native run-ios", "run-playground-android": "cd examples/NavigationPlayground && react-native run-android", "test": "jest", + "lint": "eslint src", "flow": "flow", "prepublish": "npm run clean && npm run build" }, @@ -41,6 +42,7 @@ "babel-core": "^6.24.0", "babel-eslint": "^7.0.0", "babel-jest": "^19.0.0", + "babel-plugin-flow-react-proptypes": "^1.0.0", "babel-preset-es2015": "^6.24.0", "babel-preset-react": "^6.23.0", "babel-preset-react-native": "^1.9.0", @@ -54,6 +56,7 @@ "eslint-plugin-react": "^6.10.0", "flow-bin": "^0.37.4", "jest": "^19.0.2", + "prop-types": "^15.5.8", "react": "~15.4.2", "react-native": "^0.41.2", "react-native-vector-icons": "^3.0.0", diff --git a/packages/react-navigation/src/PropTypes.js b/packages/react-navigation/src/PropTypes.js deleted file mode 100644 index c9f95fa3..00000000 --- a/packages/react-navigation/src/PropTypes.js +++ /dev/null @@ -1,122 +0,0 @@ -/* @flow */ - -import { PropTypes } from 'react'; -import { - Animated, -} from 'react-native'; - -import type { - NavigationSceneRendererProps, -} from './TypeDefinition'; - -/** - * React component PropTypes Definitions. Consider using this as a supplementary - * measure with `NavigationTypeDefinition`. This helps to capture the propType - * error at run-time, where as `NavigationTypeDefinition` capture the flow - * type check errors at build time. - */ - -/* NavigationAction */ -const action = PropTypes.shape({ - type: PropTypes.string.isRequired, -}); - -/* NavigationAnimatedValue */ -const animatedValue = PropTypes.instanceOf(Animated.Value); - -/* NavigationRoute */ -const navigationRoute = PropTypes.shape({ - key: PropTypes.string.isRequired, -}); - -/* NavigationState */ -const navigationState = PropTypes.shape({ - index: PropTypes.number.isRequired, - routes: PropTypes.arrayOf(navigationRoute), -}); - -/* NavigationProp */ -const navigation = PropTypes.shape({ - state: navigationState.isRequired, - dispatch: PropTypes.func.isRequired, -}); - -/* NavigationLayout */ -const layout = PropTypes.shape({ - height: animatedValue, - initHeight: PropTypes.number.isRequired, - initWidth: PropTypes.number.isRequired, - isMeasured: PropTypes.bool.isRequired, - width: animatedValue, -}); - -/* NavigationScene */ -const scene = PropTypes.shape({ - index: PropTypes.number.isRequired, - isActive: PropTypes.bool.isRequired, - isStale: PropTypes.bool.isRequired, - key: PropTypes.string.isRequired, - route: navigationRoute.isRequired, -}); - -/* NavigationSceneRendererProps */ -const SceneRendererProps = { - layout: layout.isRequired, - navigation: navigation.isRequired, - position: animatedValue.isRequired, - progress: animatedValue.isRequired, - scene: scene.isRequired, - scenes: PropTypes.arrayOf(scene).isRequired, -}; - -const SceneRenderer = PropTypes.shape(SceneRendererProps); - -/* NavigationPanPanHandlers */ -const panHandlers = PropTypes.shape({ - onMoveShouldSetResponder: PropTypes.func.isRequired, - onMoveShouldSetResponderCapture: PropTypes.func.isRequired, - onResponderEnd: PropTypes.func.isRequired, - onResponderGrant: PropTypes.func.isRequired, - onResponderMove: PropTypes.func.isRequired, - onResponderReject: PropTypes.func.isRequired, - onResponderRelease: PropTypes.func.isRequired, - onResponderStart: PropTypes.func.isRequired, - onResponderTerminate: PropTypes.func.isRequired, - onResponderTerminationRequest: PropTypes.func.isRequired, - onStartShouldSetResponder: PropTypes.func.isRequired, - onStartShouldSetResponderCapture: PropTypes.func.isRequired, -}); - -/** - * Helper function that extracts the props needed for scene renderer. - */ -function extractSceneRendererProps( - props: NavigationSceneRendererProps, -): NavigationSceneRendererProps { - return { - index: props.index, - layout: props.layout, - navigation: props.navigation, - position: props.position, - progress: props.progress, - scene: props.scene, - navigation: props.navigation, - scenes: props.scenes, - }; -} - -export default { - // helpers - extractSceneRendererProps, - - // Bundled propTypes. - SceneRendererProps, - - // propTypes - SceneRenderer, - action, - navigationState, - navigation, - navigationRoute, - panHandlers, -}; diff --git a/packages/react-navigation/src/react-navigation.js b/packages/react-navigation/src/react-navigation.js index 01456120..c54ac2dd 100644 --- a/packages/react-navigation/src/react-navigation.js +++ b/packages/react-navigation/src/react-navigation.js @@ -7,7 +7,6 @@ module.exports = { // Core get createNavigationContainer() { return require('./createNavigationContainer').default; }, get StateUtils() { return require('./StateUtils').default; }, - get PropTypes() { return require('./PropTypes').default; }, get addNavigationHelpers() { return require('./addNavigationHelpers').default; }, get NavigationActions() { return require('./NavigationActions').default; }, diff --git a/packages/react-navigation/src/views/Card.js b/packages/react-navigation/src/views/Card.js index a41d59ad..673fd8b8 100644 --- a/packages/react-navigation/src/views/Card.js +++ b/packages/react-navigation/src/views/Card.js @@ -1,6 +1,6 @@ /* @flow */ -import React, { PropTypes } from 'react'; +import React from 'react'; import { Animated, @@ -8,7 +8,6 @@ import { } from 'react-native'; import createPointerEventsContainer from './PointerEventsContainer'; -import NavigationPropTypes from '../PropTypes'; import type { NavigationSceneRenderer, @@ -28,14 +27,6 @@ type Props = NavigationSceneRendererProps & { class Card extends React.Component { props: Props; - static propTypes = { - ...NavigationPropTypes.SceneRendererProps, - onComponentRef: PropTypes.func.isRequired, - pointerEvents: PropTypes.string.isRequired, - children: PropTypes.any.isRequired, - style: PropTypes.any, - }; - render() { const { children, diff --git a/packages/react-navigation/src/views/CardStack.js b/packages/react-navigation/src/views/CardStack.js index caedddc8..5f640a1f 100644 --- a/packages/react-navigation/src/views/CardStack.js +++ b/packages/react-navigation/src/views/CardStack.js @@ -1,7 +1,7 @@ /* @flow */ -import React, { PropTypes, Component } from 'react'; -import { Animated, StyleSheet, PanResponder, Platform, View, I18nManager, Keyboard } from 'react-native'; +import React, { Component } from 'react'; +import { Animated, StyleSheet, PanResponder, Platform, View, I18nManager } from 'react-native'; import Card from './Card'; import NavigationActions from '../NavigationActions'; @@ -41,7 +41,7 @@ type Props = { cardStyle?: Style, onTransitionStart?: () => void, onTransitionEnd?: () => void, - style: any, + style?: any, /** * Optional custom animation when transitioning between screens. */ @@ -57,12 +57,6 @@ type Props = { index: number, }; -type DefaultProps = { - mode: 'card' | 'modal', - headerComponent: ReactClass<*>, -}; - - /** * The duration of the card animation in milliseconds. */ @@ -85,7 +79,6 @@ const RESPOND_THRESHOLD = 12; */ const GESTURE_RESPONSE_DISTANCE = 35; - /** * The ratio between the gesture velocity and the animation velocity. This allows * the velocity of a swipe release to carry on into the new animation. @@ -94,7 +87,6 @@ const GESTURE_RESPONSE_DISTANCE = 35; */ const GESTURE_ANIMATED_VELOCITY_RATIO = -4; - class CardStack extends Component { /** @@ -123,11 +115,6 @@ class CardStack extends Component { props: Props; - constructor(props: Props) { - console.log('Controlled Card stack init ',props.navigation.state); - super(props); - } - componentWillReceiveProps(props: Props) { if (props.screenProps !== this.props.screenProps) { this._screenDetails = {}; diff --git a/packages/react-navigation/src/views/CardStackTransitioner.js b/packages/react-navigation/src/views/CardStackTransitioner.js index 01124608..861c899c 100644 --- a/packages/react-navigation/src/views/CardStackTransitioner.js +++ b/packages/react-navigation/src/views/CardStackTransitioner.js @@ -1,9 +1,8 @@ /* @flow */ -import React, { PropTypes, Component } from 'react'; +import React, { Component } from 'react'; import { NativeModules, View } from 'react-native'; -import NavigationPropTypes from '../PropTypes'; import CardStack from './CardStack'; import CardStackStyleInterpolator from './CardStackStyleInterpolator'; import Transitioner from './Transitioner'; @@ -56,61 +55,6 @@ type DefaultProps = { class CardStackTransitioner extends Component { _render: NavigationSceneRenderer; - static propTypes = { - /** - * Custom style applied to the card. - */ - cardStyle: PropTypes.any, - - /** - * Style of the stack header. `float` means the header persists and is shared - * for all screens. When set to `screen`, each header is rendered within the - * card, and will animate in together. - * - * The default for `modal` mode is `screen`, and the default for `card` mode - * is `screen` on Android and `float` on iOS. - */ - headerMode: PropTypes.oneOf(['float', 'screen', 'none']), - - /** - * Custom React component to be used as a header - */ - headerComponent: PropTypes.func, - - /** - * Style of the cards movement. Value could be `card` or `modal`. - * Default value is `card`. - */ - mode: PropTypes.oneOf(['card', 'modal']), - - /** - * Optional custom animation when transitioning between screens. - */ - transitionConfig: PropTypes.func, - - /** - * The navigation prop, including the state and the dispatcher for the back - * action. The dispatcher must handle the back action - * ({ type: NavigationActions.BACK }), and the navigation state has this shape: - * - * ```js - * navigation.state = { - * index: 0, // the index of the selected route. - * routes: [ // A list of routes. - * {key: 'page 1'}, // The 1st route. - * {key: 'page 2'}, // The second route. - * ], - * }; - * ``` - */ - navigation: NavigationPropTypes.navigation.isRequired, - - /** - * Custom style applied to the cards stack. - */ - style: View.propTypes.style, - }; - static defaultProps: DefaultProps = { mode: 'card', headerComponent: Header, diff --git a/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js b/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js index 83473370..278407a6 100644 --- a/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js +++ b/packages/react-navigation/src/views/Drawer/DrawerNavigatorItems.js @@ -1,6 +1,6 @@ /* @flow */ -import React, { PropTypes } from 'react'; +import React from 'react'; import { View, Text, @@ -84,15 +84,6 @@ const DrawerNavigatorItems = ({ ); -DrawerNavigatorItems.propTypes = { - navigation: PropTypes.object.isRequired, - activeTintColor: PropTypes.string, - activeBackgroundColor: PropTypes.string, - inactiveTintColor: PropTypes.string, - inactiveBackgroundColor: PropTypes.string, - style: View.propTypes.style, -}; - /* Material design specs - https://material.io/guidelines/patterns/navigation-drawer.html#navigation-drawer-specs */ DrawerNavigatorItems.defaultProps = { activeTintColor: '#2196f3', diff --git a/packages/react-navigation/src/views/Header.js b/packages/react-navigation/src/views/Header.js index dcf78b43..26665ea1 100644 --- a/packages/react-navigation/src/views/Header.js +++ b/packages/react-navigation/src/views/Header.js @@ -1,6 +1,8 @@ +'no babel-plugin-flow-react-proptypes'; // doesn't support intersection yet + /* @flow */ -import React, { PropTypes } from 'react'; +import React from 'react'; import { Animated, @@ -12,7 +14,6 @@ import { import HeaderTitle from './HeaderTitle'; import HeaderBackButton from './HeaderBackButton'; import HeaderStyleInterpolator from './HeaderStyleInterpolator'; -import NavigationPropTypes from '../PropTypes'; import type { NavigationScene, @@ -55,19 +56,10 @@ const STATUSBAR_HEIGHT = Platform.OS === 'ios' ? 20 : 0; const TITLE_OFFSET = Platform.OS === 'ios' ? 70 : 40; class Header extends React.PureComponent { - static HEIGHT = APPBAR_HEIGHT + STATUSBAR_HEIGHT; static Title = HeaderTitle; static BackButton = HeaderBackButton; - // propTypes for people who don't use Flow - static propTypes = { - ...NavigationPropTypes.SceneRendererProps, - router: PropTypes.object, - }; - - props: HeaderProps; - state = { widths: {}, }; diff --git a/packages/react-navigation/src/views/HeaderBackButton.js b/packages/react-navigation/src/views/HeaderBackButton.js index 3d627a29..caab403d 100644 --- a/packages/react-navigation/src/views/HeaderBackButton.js +++ b/packages/react-navigation/src/views/HeaderBackButton.js @@ -1,6 +1,6 @@ /* @flow */ -import React, { PropTypes } from 'react'; +import React from 'react'; import { I18nManager, Image, @@ -34,15 +34,6 @@ type State = { }; class HeaderBackButton extends React.PureComponent { - static propTypes = { - onPress: PropTypes.func.isRequired, - pressColorAndroid: PropTypes.string, - title: PropTypes.string, - tintColor: PropTypes.string, - truncatedTitle: PropTypes.string, - width: PropTypes.number, - }; - static defaultProps = { pressColorAndroid: 'rgba(0, 0, 0, .32)', tintColor: Platform.select({ diff --git a/packages/react-navigation/src/views/HeaderTitle.js b/packages/react-navigation/src/views/HeaderTitle.js index 1beceada..d92bb92d 100644 --- a/packages/react-navigation/src/views/HeaderTitle.js +++ b/packages/react-navigation/src/views/HeaderTitle.js @@ -31,8 +31,4 @@ const styles = StyleSheet.create({ }, }); -HeaderTitle.propTypes = { - style: Text.propTypes.style, -}; - export default HeaderTitle; diff --git a/packages/react-navigation/src/views/SceneView.js b/packages/react-navigation/src/views/SceneView.js index 7e5ec0a3..a8e16077 100644 --- a/packages/react-navigation/src/views/SceneView.js +++ b/packages/react-navigation/src/views/SceneView.js @@ -1,6 +1,7 @@ /* @flow */ import React, { PureComponent } from 'react'; +import propTypes from 'prop-types'; import type { NavigationScreenProp, @@ -17,7 +18,7 @@ type Props = { export default class SceneView extends PureComponent { static childContextTypes = { - navigation: React.PropTypes.object.isRequired, + navigation: propTypes.object.isRequired, }; props: Props; diff --git a/packages/react-navigation/src/views/TouchableItem.js b/packages/react-navigation/src/views/TouchableItem.js index 01f24e36..db9a7bd9 100644 --- a/packages/react-navigation/src/views/TouchableItem.js +++ b/packages/react-navigation/src/views/TouchableItem.js @@ -9,7 +9,7 @@ * On iOS you can pass the props of TouchableOpacity, on Android pass the props * of TouchableNativeFeedback. */ -import React, { Component, PropTypes, Children } from 'react'; +import React, { Component, Children } from 'react'; import { Platform, TouchableNativeFeedback, @@ -37,16 +37,6 @@ type DefaultProps = { }; export default class TouchableItem extends Component { - static propTypes = { - onPress: PropTypes.func, - delayPressIn: PropTypes.number, - borderless: PropTypes.bool, - pressColor: PropTypes.string, - activeOpacity: PropTypes.number, - children: PropTypes.node.isRequired, - style: View.propTypes.style, - }; - static defaultProps = { pressColor: 'rgba(0, 0, 0, .32)', }; diff --git a/packages/react-navigation/src/views/Transitioner.js b/packages/react-navigation/src/views/Transitioner.js index b60caa79..305ebda8 100644 --- a/packages/react-navigation/src/views/Transitioner.js +++ b/packages/react-navigation/src/views/Transitioner.js @@ -12,14 +12,11 @@ import invariant from 'fbjs/lib/invariant'; import NavigationScenesReducer from './ScenesReducer'; import TransitionConfigs from './TransitionConfigs'; -import addNavigationHelpers from '../addNavigationHelpers'; -import NavigationPropTypes from '../PropTypes'; import type { NavigationLayout, NavigationScene, NavigationState, - NavigationRoute, NavigationAction, NavigationScreenProp, NavigationTransitionProps, @@ -32,13 +29,13 @@ type Props = { prevTransitionProps: ?NavigationTransitionProps, ) => NavigationTransitionSpec, navigation: NavigationScreenProp, - onTransitionEnd: () => void, - onTransitionStart: () => void, + onTransitionEnd?: () => void, + onTransitionStart?: () => void, render: ( transitionProps: NavigationTransitionProps, prevTransitionProps: ?NavigationTransitionProps ) => any, - style: any, + style?: any, }; type State = { @@ -48,8 +45,6 @@ type State = { scenes: Array, }; -const { PropTypes } = React; - const DefaultTransitionSpec = TransitionConfigs.DefaultTransitionSpec; class Transitioner extends React.Component<*, Props, State> { @@ -68,16 +63,6 @@ class Transitioner extends React.Component<*, Props, State> { props: Props; state: State; - static propTypes = { - configureTransition: PropTypes.func, - navigation: PropTypes.shape({ - state: NavigationPropTypes.navigationState.isRequired, - }).isRequired, - onTransitionEnd: PropTypes.func, - onTransitionStart: PropTypes.func, - render: PropTypes.func.isRequired, - }; - constructor(props: Props, context: any) { super(props, context); diff --git a/packages/react-navigation/src/views/withNavigation.js b/packages/react-navigation/src/views/withNavigation.js index 6474bc9d..57ec6d99 100644 --- a/packages/react-navigation/src/views/withNavigation.js +++ b/packages/react-navigation/src/views/withNavigation.js @@ -1,6 +1,7 @@ /* @flow */ import React from 'react'; +import propTypes from 'prop-types'; import hoistStatics from 'hoist-non-react-statics'; import type { @@ -26,7 +27,7 @@ export default function withNavigation(Component: ReactClass