Clean up some flow types code-base wide, reorganize cardstack views

This commit is contained in:
Adam Miskiewicz
2017-07-05 14:19:23 -07:00
parent bbd82dff53
commit eb8434a5b6
19 changed files with 219 additions and 192 deletions

View File

@@ -54,7 +54,7 @@
2,
"boolean"
],
"flowtype/no-weak-types": 1,
"flowtype/no-weak-types": 0,
"flowtype/require-parameter-type": 2,
"flowtype/require-return-type": [
0,

View File

@@ -21,22 +21,72 @@ export type AnimatedTextStyleProp = $PropertyType<
'style'
>;
export type HeaderMode = 'float' | 'screen' | 'none';
/**
* Navigation State + Action
*/
export type HeaderProps = {
...$Exact<NavigationSceneRendererProps>,
mode: HeaderMode,
router: NavigationRouter<
NavigationState,
NavigationAction,
NavigationStackScreenOptions
>,
getScreenDetails: NavigationScene => NavigationScreenDetails<
NavigationStackScreenOptions
>,
style: ViewStyleProp,
export type NavigationParams = {
[key: string]: mixed,
};
export type NavigationNavigateAction = {
type: 'Navigation/NAVIGATE',
routeName: string,
params?: NavigationParams,
// The action to run inside the sub-router
action?: NavigationNavigateAction,
};
export type NavigationBackAction = {
type: 'Navigation/BACK',
key?: ?string,
};
export type NavigationSetParamsAction = {
type: 'Navigation/SET_PARAMS',
// The key of the route where the params should be set
key: string,
// The new params to merge into the existing route params
params?: NavigationParams,
};
export type NavigationInitAction = {
type: 'Navigation/INIT',
params?: NavigationParams,
};
export type NavigationResetAction = {
type: 'Navigation/RESET',
index: number,
key?: ?string,
actions: Array<NavigationNavigateAction>,
};
export type NavigationUriAction = {
type: 'Navigation/URI',
uri: string,
};
export type NavigationStackAction =
| NavigationInitAction
| NavigationNavigateAction
| NavigationBackAction
| NavigationSetParamsAction
| NavigationResetAction;
export type NavigationTabAction =
| NavigationInitAction
| NavigationNavigateAction
| NavigationBackAction;
export type NavigationAction =
| NavigationInitAction
| NavigationStackAction
| NavigationTabAction;
/**
* NavigationState is a tree of routes for a single navigator, where each child
* route may either be a NavigationScreenRoute or a NavigationRouterRoute.
@@ -88,6 +138,10 @@ export type NavigationStateRoute = {
routes: Array<NavigationRoute>,
};
/**
* Router
*/
export type NavigationScreenOptionsGetter<Options, Action> = (
navigation: NavigationScreenProp<NavigationRoute, Action>,
screenProps?: {}
@@ -132,13 +186,6 @@ export type NavigationRouter<State, Action, Options> = {
getScreenOptions: NavigationScreenOptionsGetter<Options, Action>,
};
export type NavigationScreenOption<T> =
| T
| ((
navigation: NavigationScreenProp<NavigationRoute, NavigationAction>,
config: T
) => T);
export type NavigationScreenDetails<T> = {
options: T,
state: NavigationRoute,
@@ -151,18 +198,18 @@ export type NavigationScreenOptions = {
export type NavigationScreenConfigProps = {
navigation: NavigationScreenProp<NavigationRoute, NavigationAction>,
screenProps: Object,
screenProps: {},
};
export type NavigationScreenConfig<Options> =
| Options
| (NavigationScreenConfigProps &
(({
navigationOptions: NavigationScreenProp<
NavigationRoute,
NavigationAction
>,
}) => Options));
| (({
...$Exact<NavigationScreenConfigProps>,
navigationOptions: NavigationScreenProp<
NavigationRoute,
NavigationAction
>,
}) => Options);
export type NavigationComponent =
| NavigationScreenComponent<*, *>
@@ -177,59 +224,51 @@ export type NavigationNavigator<T, State, Action, Options> = ReactClass<T> & {
navigationOptions?: NavigationScreenConfig<Options>,
};
export type NavigationParams = {
[key: string]: mixed,
export type NavigationRouteConfig<T: {}> = {
...$Exact<T>,
navigationOptions?: NavigationScreenConfig<*>,
path?: string,
};
export type NavigationNavigateAction = {
type: 'Navigation/NAVIGATE',
routeName: string,
params?: NavigationParams,
export type NavigationScreenRouteConfig =
| {
screen: NavigationComponent,
}
| {
getScreen: () => NavigationComponent,
};
// The action to run inside the sub-router
action?: NavigationNavigateAction,
export type NavigationPathsConfig = {
[routeName: string]: string,
};
export type NavigationBackAction = {
type: 'Navigation/BACK',
key?: ?string,
export type NavigationRouteConfigMap = {
[routeName: string]: NavigationRouteConfig<*>,
};
export type NavigationSetParamsAction = {
type: 'Navigation/SET_PARAMS',
/**
* Header
*/
// The key of the route where the params should be set
key: string,
export type HeaderMode = 'float' | 'screen' | 'none';
// The new params to merge into the existing route params
params?: NavigationParams,
export type HeaderProps = {
...$Exact<NavigationSceneRendererProps>,
mode: HeaderMode,
router: NavigationRouter<
NavigationState,
NavigationAction,
NavigationStackScreenOptions
>,
getScreenDetails: NavigationScene => NavigationScreenDetails<
NavigationStackScreenOptions
>,
style: ViewStyleProp,
};
export type NavigationInitAction = {
type: 'Navigation/INIT',
params?: NavigationParams,
};
export type NavigationResetAction = {
type: 'Navigation/RESET',
index: number,
key?: ?string,
actions: Array<NavigationNavigateAction>,
};
export type NavigationUriAction = {
type: 'Navigation/URI',
uri: string,
};
export type NavigationStackViewConfig = {
mode?: 'card' | 'modal',
headerMode?: HeaderMode,
cardStyle?: ViewStyleProp,
transitionConfig?: () => TransitionConfig,
onTransitionStart?: () => void,
onTransitionEnd?: () => void,
};
/**
* Stack Navigator
*/
export type NavigationStackScreenOptions = {
...$Exact<NavigationScreenOptions>,
@@ -254,40 +293,24 @@ export type NavigationStackRouterConfig = {
navigationOptions?: NavigationScreenConfig<NavigationStackScreenOptions>,
};
export type NavigationStackAction =
| NavigationInitAction
| NavigationNavigateAction
| NavigationBackAction
| NavigationSetParamsAction
| NavigationResetAction;
export type NavigationTabAction =
| NavigationInitAction
| NavigationNavigateAction
| NavigationBackAction;
export type NavigationAction =
| NavigationInitAction
| NavigationStackAction
| NavigationTabAction;
export type NavigationRouteConfig<T> = T & {
navigationOptions?: NavigationScreenConfig<*>,
path?: string,
export type NavigationStackViewConfig = {
mode?: 'card' | 'modal',
headerMode?: HeaderMode,
cardStyle?: ViewStyleProp,
transitionConfig?: () => TransitionConfig,
onTransitionStart?: () => void,
onTransitionEnd?: () => void,
};
export type NavigationScreenRouteConfig =
| {
screen: NavigationComponent,
}
| {
getScreen: () => NavigationComponent,
};
export type NavigationPathsConfig = {
[routeName: string]: string,
export type StackNavigatorConfig = {
...$Exact<NavigationStackViewConfig>,
...$Exact<NavigationStackRouterConfig>,
};
/**
* Tab Navigator
*/
export type NavigationTabRouterConfig = {
initialRouteName?: string,
paths?: NavigationPathsConfig,
@@ -298,7 +321,8 @@ export type NavigationTabRouterConfig = {
backBehavior?: 'none' | 'initialRoute', // defaults `initialRoute`
};
export type NavigationTabScreenOptions = NavigationScreenOptions & {
export type NavigationTabScreenOptions = {
...$Exact<NavigationScreenOptions>,
tabBarIcon?:
| React.Element<*>
| ((options: { tintColor: ?string, focused: boolean }) => ?React.Element<
@@ -313,7 +337,12 @@ export type NavigationTabScreenOptions = NavigationScreenOptions & {
tabBarVisible?: boolean,
};
export type NavigationDrawerScreenOptions = NavigationScreenOptions & {
/**
* Drawer
*/
export type NavigationDrawerScreenOptions = {
...$Exact<NavigationScreenOptions>,
drawerIcon?:
| React.Element<*>
| ((options: { tintColor: ?string, focused: boolean }) => ?React.Element<
@@ -326,9 +355,9 @@ export type NavigationDrawerScreenOptions = NavigationScreenOptions & {
>),
};
export type NavigationRouteConfigMap = {
[routeName: string]: NavigationRouteConfig<*>,
};
/**
* Navigator Prop
*/
export type NavigationDispatch<A> = (action: A) => boolean;
@@ -349,10 +378,10 @@ export type NavigationScreenProp<S, A> = {
setParams: (newParams: NavigationParams) => boolean,
};
export type NavigationNavigatorProps<T> = {
navigation: NavigationProp<T, NavigationAction>,
export type NavigationNavigatorProps<O, S> = {
navigation: NavigationProp<S, NavigationAction>,
screenProps: *,
navigationOptions: *,
navigationOptions: O,
};
/**
@@ -429,7 +458,7 @@ export type TransitionConfig = {
transitionSpec?: NavigationTransitionSpec,
// How to animate position and opacity of the screen
// based on the value generated by the transitionSpec
screenInterpolator?: (props: NavigationSceneRendererProps) => Object,
screenInterpolator?: (props: NavigationSceneRendererProps) => {},
// The style of the container. Useful when a scene doesn't have
// 100% opacity and the underlying container is visible.
containerStyle?: $PropertyType<ViewProps, 'style'>,

View File

@@ -12,6 +12,7 @@ import type {
NavigationState,
NavigationScreenProp,
NavigationNavigatorProps,
NavigationNavigator,
} from './TypeDefinition';
type NavigationContainerProps = {
@@ -23,7 +24,7 @@ type NavigationContainerProps = {
) => void,
};
type Props<T> = NavigationContainerProps & NavigationNavigatorProps<T>;
type Props<O, S> = NavigationContainerProps & NavigationNavigatorProps<O, S>;
type State = {
nav: ?NavigationState,
@@ -35,18 +36,12 @@ type State = {
* This allows to use e.g. the StackNavigator and TabNavigator as root-level
* components.
*/
export default function createNavigationContainer<T: *>(
Component: ReactClass<NavigationNavigatorProps<T>>,
containerOptions?: {}
export default function createNavigationContainer<S: *, O>(
Component: NavigationNavigator<*, S, *, O>
) {
invariant(
typeof containerOptions === 'undefined',
'containerOptions.URIPrefix has been removed. Pass the uriPrefix prop to the navigator instead'
);
class NavigationContainer extends React.Component<void, Props<T>, State> {
class NavigationContainer extends React.Component<void, Props<O, S>, State> {
state: State;
props: Props<T>;
props: Props<O, S>;
subs: ?{
remove: () => void,
@@ -54,7 +49,7 @@ export default function createNavigationContainer<T: *>(
static router = Component.router;
constructor(props: Props<T>) {
constructor(props: Props<O, S>) {
super(props);
this._validateProps(props);
@@ -70,7 +65,7 @@ export default function createNavigationContainer<T: *>(
return !this.props.navigation;
}
_validateProps(props: Props<T>) {
_validateProps(props: Props<O, S>) {
if (this._isStateful()) {
return;
}

View File

@@ -84,7 +84,7 @@ const DrawerNavigator = (
/>
);
return createNavigationContainer(navigator, containerConfig);
return createNavigationContainer(navigator);
};
export default DrawerNavigator;

View File

@@ -3,21 +3,15 @@
import React from 'react';
import createNavigationContainer from '../createNavigationContainer';
import createNavigator from './createNavigator';
import CardStackTransitioner from '../views/CardStackTransitioner';
import CardStackTransitioner from '../views/CardStack/CardStackTransitioner';
import StackRouter from '../routers/StackRouter';
import NavigatorTypes from './NavigatorTypes';
import type {
NavigationStackRouterConfig,
NavigationStackViewConfig,
NavigationRouteConfigMap,
StackNavigatorConfig,
} from '../TypeDefinition';
export type StackNavigatorConfig = {
containerOptions?: void,
} & NavigationStackViewConfig &
NavigationStackRouterConfig;
export default (
routeConfigMap: NavigationRouteConfigMap,
stackConfig: StackNavigatorConfig = {}
@@ -44,6 +38,7 @@ export default (
const router = StackRouter(routeConfigMap, stackRouterConfig);
// Create a navigator with CardStackTransitioner as the view
const navigator = createNavigator(
router,
routeConfigMap,
@@ -61,5 +56,5 @@ export default (
/>
);
return createNavigationContainer(navigator, stackConfig.containerOptions);
return createNavigationContainer(navigator);
};

View File

@@ -59,7 +59,7 @@ const TabNavigator = (
/>
);
return createNavigationContainer(navigator, tabsConfig.containerOptions);
return createNavigationContainer(navigator);
};
const Presets = {

View File

@@ -14,27 +14,29 @@ import type { NavigatorType } from './NavigatorTypes';
/**
* Creates a navigator based on a router and a view that renders the screens.
*/
const createNavigator = (
router: NavigationRouter<*, *, *>,
export default function createNavigator<C: *, S, A, NavigatorConfig, Options>(
router: NavigationRouter<S, A, Options>,
routeConfigs: NavigationRouteConfigMap,
navigatorConfig: any,
navigatorConfig: NavigatorConfig,
navigatorType: NavigatorType
) => (NavigationView: NavigationNavigator<*, *, *, *>) => {
class Navigator extends React.Component {
props: NavigationNavigatorProps<*>;
) {
return (
NavigationView: ReactClass<C>
): NavigationNavigator<C, S, A, Options> => {
class Navigator extends React.Component {
props: NavigationNavigatorProps<Options, S>;
static router = router;
static router = router;
static routeConfigs = routeConfigs;
static navigatorConfig = navigatorConfig;
static navigatorType = navigatorType;
static routeConfigs = routeConfigs;
static navigatorConfig = navigatorConfig;
static navigatorType = navigatorType;
render() {
return <NavigationView {...this.props} router={router} />;
render() {
return <NavigationView {...this.props} router={router} />;
}
}
}
return Navigator;
};
export default createNavigator;
return Navigator;
};
}

View File

@@ -46,13 +46,13 @@ module.exports = {
return require('./views/Transitioner').default;
},
get CardStackTransitioner() {
return require('./views/CardStackTransitioner').default;
return require('./views/CardStack/CardStackTransitioner').default;
},
get CardStack() {
return require('./views/CardStack').default;
return require('./views/CardStack/CardStack').default;
},
get Card() {
return require('./views/Card').default;
return require('./views/CardStack/Card').default;
},
// Header

View File

@@ -20,6 +20,7 @@ import type {
NavigationState,
NavigationStackAction,
NavigationStackRouterConfig,
NavigationStackScreenOptions,
} from '../TypeDefinition';
const uniqueBaseId = `id-${Date.now()}`;
@@ -31,13 +32,14 @@ function _getUuid() {
export default (
routeConfigs: NavigationRouteConfigMap,
stackConfig: NavigationStackRouterConfig = {}
): NavigationRouter<*, *, *> => {
): NavigationRouter<*, *, NavigationStackScreenOptions> => {
// Fail fast on invalid route definitions
validateRouteConfigMap(routeConfigs);
const childRouters = {};
const routeNames = Object.keys(routeConfigs);
// Loop through routes and find child routers
routeNames.forEach((routeName: string) => {
const screen = getScreenForRouteName(routeConfigs, routeName);
if (screen && screen.router) {
@@ -56,6 +58,7 @@ export default (
const initialChildRouter = childRouters[initialRouteName];
const paths = stackConfig.paths || {};
// Build paths for each route
routeNames.forEach((routeName: string) => {
let pathPattern = paths[routeName] || routeConfigs[routeName].path;
const matchExact = !!pathPattern && !childRouters[routeName];

View File

@@ -18,9 +18,9 @@ import type {
NavigationScreenConfigProps,
} from '../TypeDefinition';
function applyConfig(
configurer: ?NavigationScreenConfig<*>,
navigationOptions: *,
function applyConfig<T: {}>(
configurer: ?NavigationScreenConfig<T>,
navigationOptions: any,
configProps: NavigationScreenConfigProps
): * {
if (typeof configurer === 'function') {

View File

@@ -6,11 +6,12 @@ import { Animated, StyleSheet } from 'react-native';
import createPointerEventsContainer from './PointerEventsContainer';
import type { NavigationSceneRendererProps } from '../TypeDefinition';
import type { NavigationSceneRendererProps } from '../../TypeDefinition';
type Props = NavigationSceneRendererProps & {
type Props = {
...$Exact<NavigationSceneRendererProps>,
children: React.Children<*>,
onComponentRef: (ref: any) => void,
onComponentRef: (ref: React.Element<*>) => void,
pointerEvents: string,
style: any,
};
@@ -18,7 +19,7 @@ type Props = NavigationSceneRendererProps & {
/**
* Component that renders the scene as card for the <NavigationCardStack />.
*/
class Card extends React.Component<any, Props, any> {
class Card extends React.Component<void, Props, void> {
props: Props;
render() {

View File

@@ -14,10 +14,10 @@ import {
} from 'react-native';
import Card from './Card';
import Header from './Header/Header';
import NavigationActions from '../NavigationActions';
import addNavigationHelpers from '../addNavigationHelpers';
import SceneView from './SceneView';
import Header from '../Header/Header';
import NavigationActions from '../../NavigationActions';
import addNavigationHelpers from '../../addNavigationHelpers';
import SceneView from '../SceneView';
import type {
NavigationAction,
@@ -31,7 +31,7 @@ import type {
HeaderMode,
ViewStyleProp,
TransitionConfig,
} from '../TypeDefinition';
} from '../../TypeDefinition';
import TransitionConfigs from './TransitionConfigs';
@@ -42,6 +42,7 @@ type Props = {
headerMode: HeaderMode,
headerComponent?: ReactClass<*>,
mode: 'card' | 'modal',
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
router: NavigationRouter<
NavigationState,
NavigationAction,

View File

@@ -2,7 +2,7 @@
import { I18nManager, type AnimatedViewStylePropTypes } from 'react-native';
import type { NavigationSceneRendererProps } from '../TypeDefinition';
import type { NavigationSceneRendererProps } from '../../TypeDefinition';
/**
* Utility that builds the style for the card in the cards stack.

View File

@@ -5,7 +5,7 @@ import { NativeModules } from 'react-native';
import CardStack from './CardStack';
import CardStackStyleInterpolator from './CardStackStyleInterpolator';
import Transitioner from './Transitioner';
import Transitioner from '../Transitioner';
import TransitionConfigs from './TransitionConfigs';
import type {
@@ -19,7 +19,7 @@ import type {
HeaderMode,
ViewStyleProp,
TransitionConfig,
} from '../TypeDefinition';
} from '../../TypeDefinition';
const NativeAnimatedModule =
NativeModules && NativeModules.NativeAnimatedModule;

View File

@@ -2,11 +2,11 @@
import React from 'react';
import invariant from '../utils/invariant';
import invariant from '../../utils/invariant';
import AnimatedValueSubscription from './AnimatedValueSubscription';
import AnimatedValueSubscription from '../AnimatedValueSubscription';
import type { NavigationSceneRendererProps } from '../TypeDefinition';
import type { NavigationSceneRendererProps } from '../../TypeDefinition';
type Props = NavigationSceneRendererProps;

View File

@@ -6,17 +6,10 @@ import type {
NavigationTransitionProps,
NavigationTransitionSpec,
TransitionConfig,
} from '../TypeDefinition';
} from '../../TypeDefinition';
import CardStackStyleInterpolator from './CardStackStyleInterpolator';
// Used for all animations unless overriden
const DefaultTransitionSpec = ({
duration: 250,
easing: Easing.inOut(Easing.ease),
timing: Animated.timing,
}: NavigationTransitionSpec);
const IOSTransitionSpec = ({
duration: 500,
easing: Easing.bezier(0.2833, 0.99, 0.31833, 0.99),
@@ -113,7 +106,6 @@ function getTransitionConfig(
}
export default {
DefaultTransitionSpec,
defaultTransitionConfig,
getTransitionConfig,
};

View File

@@ -85,9 +85,14 @@ class DrawerSidebar extends PureComponent<void, Props, void> {
_onItemPress = ({ route, focused }: DrawerItem) => {
this.props.navigation.navigate('DrawerClose');
if (!focused) {
const subAction = route.index !== undefined && route.index !== 0 // if the child screen is a StackRouter then always navigate to its first screen (see #1914)
? NavigationActions.navigate({ routeName: route.routes[0].routeName })
: undefined;
let subAction;
// if the child screen is a StackRouter then always navigate to its first screen (see #1914)
if (route.index !== undefined && route.index !== 0) {
route = ((route: any): NavigationStateRoute);
subAction = NavigationActions.navigate({
routeName: route.routes[0].routeName,
});
}
this.props.navigation.navigate(route.routeName, undefined, subAction);
}
};

View File

@@ -10,18 +10,18 @@ import type {
NavigationNavigatorProps,
} from '../TypeDefinition';
type Props = {
type Props<O> = {
screenProps?: {},
navigation: NavigationScreenProp<NavigationRoute, NavigationAction>,
component: ReactClass<NavigationNavigatorProps<NavigationRoute>>,
component: ReactClass<NavigationNavigatorProps<O, NavigationRoute>>,
};
export default class SceneView extends PureComponent<void, Props, void> {
export default class SceneView<O> extends PureComponent<void, Props<O>, void> {
static childContextTypes = {
navigation: propTypes.object.isRequired,
};
props: Props;
props: Props<O>;
getChildContext() {
return {

View File

@@ -2,12 +2,11 @@
import React from 'react';
import { Animated, StyleSheet, View } from 'react-native';
import { Animated, Easing, StyleSheet, View } from 'react-native';
import invariant from '../utils/invariant';
import NavigationScenesReducer from './ScenesReducer';
import TransitionConfigs from './TransitionConfigs';
import type {
NavigationLayout,
@@ -41,7 +40,12 @@ type State = {
scenes: Array<NavigationScene>,
};
const DefaultTransitionSpec = TransitionConfigs.DefaultTransitionSpec;
// Used for all animations unless overriden
const DefaultTransitionSpec = ({
duration: 250,
easing: Easing.inOut(Easing.ease),
timing: Animated.timing,
}: NavigationTransitionSpec);
class Transitioner extends React.Component<*, Props, State> {
_onLayout: (event: any) => void;