Automatically generate prop-types from Flow (#1033)

* Automatically generate prop-types from Flow

* Remove propTypes usage

* Fix flow

* Modify some eslint settings

* Fix flowtype

* Lint tweaks

* use prop-types pkg
This commit is contained in:
Mike Grabowski
2017-04-14 00:19:30 +02:00
parent 9bbbc6063c
commit e044254257
17 changed files with 57 additions and 285 deletions

View File

@@ -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"
]
}
}
}

View File

@@ -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"

View File

@@ -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",

View File

@@ -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,
};

View File

@@ -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; },

View File

@@ -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<any, Props, any> {
props: Props;
static propTypes = {
...NavigationPropTypes.SceneRendererProps,
onComponentRef: PropTypes.func.isRequired,
pointerEvents: PropTypes.string.isRequired,
children: PropTypes.any.isRequired,
style: PropTypes.any,
};
render() {
const {
children,

View File

@@ -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 = {};

View File

@@ -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<DefaultProps, Props, void> {
_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,

View File

@@ -1,6 +1,6 @@
/* @flow */
import React, { PropTypes } from 'react';
import React from 'react';
import {
View,
Text,
@@ -84,15 +84,6 @@ const DrawerNavigatorItems = ({
</View>
);
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',

View File

@@ -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<void, HeaderProps, HeaderState> {
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: {},
};

View File

@@ -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<DefaultProps, Props, State> {
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({

View File

@@ -31,8 +31,4 @@ const styles = StyleSheet.create({
},
});
HeaderTitle.propTypes = {
style: Text.propTypes.style,
};
export default HeaderTitle;

View File

@@ -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<void, Props, void> {
static childContextTypes = {
navigation: React.PropTypes.object.isRequired,
navigation: propTypes.object.isRequired,
};
props: Props;

View File

@@ -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<DefaultProps, Props, void> {
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)',
};

View File

@@ -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<NavigationState, NavigationAction>,
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<NavigationScene>,
};
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);

View File

@@ -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<T: *>(Component: ReactClass<T & InjectedP
componentWithNavigation.displayName = `withNavigation(${Component.displayName || Component.name})`;
componentWithNavigation.contextTypes = {
navigation: React.PropTypes.object.isRequired,
navigation: propTypes.object.isRequired,
};
return hoistStatics(componentWithNavigation, Component);

View File

@@ -267,7 +267,7 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
babel-core@^6.0.0, babel-core@^6.21.0, babel-core@^6.24.0, babel-core@^6.7.2:
babel-core@^6.0.0, babel-core@^6.18.0, babel-core@^6.21.0, babel-core@^6.24.0, babel-core@^6.7.2:
version "6.24.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.0.tgz#8f36a0a77f5c155aed6f920b844d23ba56742a02"
dependencies:
@@ -467,6 +467,15 @@ babel-plugin-external-helpers@^6.18.0:
dependencies:
babel-runtime "^6.22.0"
babel-plugin-flow-react-proptypes@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/babel-plugin-flow-react-proptypes/-/babel-plugin-flow-react-proptypes-1.0.0.tgz#020de47d67f670f53ba96949ea1bd0fa5f670c1d"
dependencies:
babel-core "^6.18.0"
babel-template "^6.16.0"
babel-traverse "^6.18.0"
babel-types "^6.18.0"
babel-plugin-istanbul@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.0.0.tgz#36bde8fbef4837e5ff0366531a2beabd7b1ffa10"
@@ -2035,7 +2044,7 @@ fbjs-scripts@^0.7.0:
semver "^5.1.0"
through2 "^2.0.0"
fbjs@^0.8.4, fbjs@^0.8.5:
fbjs@^0.8.4, fbjs@^0.8.5, fbjs@^0.8.9:
version "0.8.9"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14"
dependencies:
@@ -3755,6 +3764,12 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
prop-types@^15.5.8:
version "15.5.8"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394"
dependencies:
fbjs "^0.8.9"
prr@~0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"