mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-15 09:17:26 +08:00
Update/Fix Prettier + Eslint config for codebase
Run Prettier/Eslint on entire codebase, fix issues
This commit is contained in:
6
packages/react-navigation/.eslintignore
Normal file
6
packages/react-navigation/.eslintignore
Normal file
@@ -0,0 +1,6 @@
|
||||
flow-typed
|
||||
node_modules
|
||||
lib*
|
||||
|
||||
## Temporary
|
||||
examples
|
||||
@@ -1,12 +1,16 @@
|
||||
{
|
||||
"extends": [
|
||||
"airbnb",
|
||||
"plugin:flowtype/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:import/errors",
|
||||
"plugin:import/warnings",
|
||||
"prettier",
|
||||
"prettier/flowtype",
|
||||
"prettier/react"
|
||||
],
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react",
|
||||
"flowtype",
|
||||
"prettier"
|
||||
],
|
||||
@@ -18,7 +22,7 @@
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": ["error", {
|
||||
"trailingComma": "all",
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true
|
||||
}],
|
||||
|
||||
@@ -65,7 +69,7 @@
|
||||
},
|
||||
"settings": {
|
||||
"flowtype": {
|
||||
"onlyFilesWithFlowAnnotation": false
|
||||
"onlyFilesWithFlowAnnotation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<PROJECT_ROOT>/website/node_modules/react-native/.*
|
||||
<PROJECT_ROOT>/website/node_modules/fbjs/.*
|
||||
|
||||
; Ignore misc packages
|
||||
.*/node_modules/eslint-.*
|
||||
|
||||
; Ignore duplicate module providers
|
||||
; For RN Apps installed via npm, "Libraries" folder is inside
|
||||
; "node_modules/react-native" but in the source repo it is in the root
|
||||
@@ -55,6 +58,3 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
|
||||
|
||||
unsafe.enable_getters_and_setters=true
|
||||
|
||||
[version]
|
||||
^0.40.0
|
||||
|
||||
@@ -9,13 +9,16 @@ const path = require('path');
|
||||
const config = require('../../../rn-cli.config');
|
||||
|
||||
config.getBlacklist = () => [
|
||||
new RegExp(`${path.resolve(__dirname, '../../..')}/node_modules/react-native/(.*)`),
|
||||
new RegExp(
|
||||
`${path.resolve(__dirname, '../../..')}/node_modules/react-native/(.*)`
|
||||
),
|
||||
new RegExp(`${path.resolve(__dirname, '../../..')}/node_modules/react/(.*)`),
|
||||
...config.getBlacklistForExample('NavigationPlayground'),
|
||||
new RegExp(`^${path.resolve(__dirname, '..')}/package.json$`),
|
||||
];
|
||||
|
||||
config.getTransformModulePath = () => path.resolve(__dirname, './transformer.js');
|
||||
config.getTransformModulePath = () =>
|
||||
path.resolve(__dirname, './transformer.js');
|
||||
|
||||
config.getTransformOptions = () => ({
|
||||
reactNativePath: path.resolve(__dirname, '../node_modules/react-native/'),
|
||||
|
||||
@@ -19,21 +19,23 @@ const reactTransformPlugin = require('babel-plugin-react-transform').default;
|
||||
const hmrTransform = 'react-transform-hmr/lib/index.js';
|
||||
const transformPath = require.resolve(hmrTransform);
|
||||
|
||||
const makeHMRConfig = function(options, filename) {
|
||||
const transform = filename ?
|
||||
'./' + path.relative(path.dirname(filename), transformPath) : // packager can't handle absolute paths
|
||||
hmrTransform;
|
||||
const makeHMRConfig = function(options, filename) {
|
||||
const transform = filename
|
||||
? './' + path.relative(path.dirname(filename), transformPath) // packager can't handle absolute paths
|
||||
: hmrTransform;
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
[
|
||||
reactTransformPlugin,
|
||||
{
|
||||
transforms: [{
|
||||
transform,
|
||||
imports: ['react-native'],
|
||||
locals: ['module'],
|
||||
}],
|
||||
transforms: [
|
||||
{
|
||||
transform,
|
||||
imports: ['react-native'],
|
||||
locals: ['module'],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
],
|
||||
@@ -42,13 +44,22 @@ const makeHMRConfig = function(options, filename) {
|
||||
|
||||
const buildAliasPreset = (reactNativePath, reactPath) => ({
|
||||
plugins: [
|
||||
[require('babel-plugin-module-resolver').default, {
|
||||
alias: Object.assign({}, {
|
||||
'react-native': path.resolve(`${reactNativePath || './node_modules/react-native'}`),
|
||||
react: path.resolve(`${reactPath || './node_modules/react'}`),
|
||||
}, require('babel-preset-exponent').plugins[0][1].alias),
|
||||
cwd: path.resolve(__dirname, '..'),
|
||||
}],
|
||||
[
|
||||
require('babel-plugin-module-resolver').default,
|
||||
{
|
||||
alias: Object.assign(
|
||||
{},
|
||||
{
|
||||
'react-native': path.resolve(
|
||||
`${reactNativePath || './node_modules/react-native'}`
|
||||
),
|
||||
react: path.resolve(`${reactPath || './node_modules/react'}`),
|
||||
},
|
||||
require('babel-preset-exponent').plugins[0][1].alias
|
||||
),
|
||||
cwd: path.resolve(__dirname, '..'),
|
||||
},
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
@@ -59,7 +70,10 @@ const buildAliasPreset = (reactNativePath, reactPath) => ({
|
||||
function buildBabelConfig(filename, options) {
|
||||
const exponentBabelPreset = require('babel-preset-exponent');
|
||||
const babelConfig = {
|
||||
presets: [...exponentBabelPreset.presets, buildAliasPreset(options.reactNativePath, options.reactPath)],
|
||||
presets: [
|
||||
...exponentBabelPreset.presets,
|
||||
buildAliasPreset(options.reactNativePath, options.reactPath),
|
||||
],
|
||||
plugins: [],
|
||||
};
|
||||
|
||||
@@ -97,7 +111,7 @@ function transform(src, filename, options) {
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function (data, callback) {
|
||||
module.exports = function(data, callback) {
|
||||
let result;
|
||||
try {
|
||||
result = transform(data.sourceCode, data.filename, data.options);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import {
|
||||
AppRegistry,
|
||||
} from 'react-native';
|
||||
import { AppRegistry } from 'react-native';
|
||||
|
||||
import App from './js/App';
|
||||
|
||||
|
||||
@@ -49,8 +49,12 @@ const ExampleRoutes = {
|
||||
screen: CustomTabs,
|
||||
},
|
||||
ModalStack: {
|
||||
name: Platform.OS === 'ios' ? 'Modal Stack Example' : 'Stack with Dynamic Header',
|
||||
description: Platform.OS === 'ios' ? 'Stack navigation with modals' : 'Dynamically showing and hiding the header',
|
||||
name: Platform.OS === 'ios'
|
||||
? 'Modal Stack Example'
|
||||
: 'Stack with Dynamic Header',
|
||||
description: Platform.OS === 'ios'
|
||||
? 'Stack navigation with modals'
|
||||
: 'Dynamically showing and hiding the header',
|
||||
screen: ModalStack,
|
||||
},
|
||||
StacksInTabs: {
|
||||
@@ -80,7 +84,7 @@ const ExampleRoutes = {
|
||||
const MainScreen = ({ navigation }) => (
|
||||
<ScrollView>
|
||||
<Banner />
|
||||
{Object.keys(ExampleRoutes).map((routeName: string) =>
|
||||
{Object.keys(ExampleRoutes).map((routeName: string) => (
|
||||
<TouchableOpacity
|
||||
key={routeName}
|
||||
onPress={() => {
|
||||
@@ -92,28 +96,33 @@ const MainScreen = ({ navigation }) => (
|
||||
>
|
||||
<View style={styles.item}>
|
||||
<Text style={styles.title}>{ExampleRoutes[routeName].name}</Text>
|
||||
<Text style={styles.description}>{ExampleRoutes[routeName].description}</Text>
|
||||
<Text style={styles.description}>
|
||||
{ExampleRoutes[routeName].description}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
))}
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const AppNavigator = StackNavigator({
|
||||
...ExampleRoutes,
|
||||
Index: {
|
||||
screen: MainScreen,
|
||||
const AppNavigator = StackNavigator(
|
||||
{
|
||||
...ExampleRoutes,
|
||||
Index: {
|
||||
screen: MainScreen,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
initialRouteName: 'Index',
|
||||
headerMode: 'none',
|
||||
{
|
||||
initialRouteName: 'Index',
|
||||
headerMode: 'none',
|
||||
|
||||
/*
|
||||
/*
|
||||
* Use modal on iOS because the card mode comes from the right,
|
||||
* which conflicts with the drawer example gesture
|
||||
*/
|
||||
mode: Platform.OS === 'ios' ? 'modal' : 'card',
|
||||
});
|
||||
mode: Platform.OS === 'ios' ? 'modal' : 'card',
|
||||
}
|
||||
);
|
||||
|
||||
export default () => <AppNavigator />;
|
||||
|
||||
|
||||
@@ -2,20 +2,11 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
Image,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { Image, Platform, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const Banner = () => (
|
||||
<View style={styles.banner}>
|
||||
<Image
|
||||
source={require('./assets/NavLogo.png')}
|
||||
style={styles.image}
|
||||
/>
|
||||
<Image source={require('./assets/NavLogo.png')} style={styles.image} />
|
||||
<Text style={styles.title}>React Navigation Examples</Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -33,29 +33,18 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
);
|
||||
|
||||
const MyHomeScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Home Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Home Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MyNotificationsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Notifications Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MySettingsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Settings Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Settings Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const CustomTabBar = ({
|
||||
navigation,
|
||||
}) => {
|
||||
const CustomTabBar = ({ navigation }) => {
|
||||
const { routes } = navigation.state;
|
||||
return (
|
||||
<View style={styles.tabContainer}>
|
||||
@@ -70,12 +59,9 @@ const CustomTabBar = ({
|
||||
))}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const CustomTabView = ({
|
||||
router,
|
||||
navigation,
|
||||
}) => {
|
||||
const CustomTabView = ({ router, navigation }) => {
|
||||
const { routes, index } = navigation.state;
|
||||
const ActiveScreen = router.getComponentForState(navigation.state);
|
||||
return (
|
||||
@@ -91,25 +77,30 @@ const CustomTabView = ({
|
||||
);
|
||||
};
|
||||
|
||||
const CustomTabRouter = TabRouter({
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
path: '',
|
||||
const CustomTabRouter = TabRouter(
|
||||
{
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
path: '',
|
||||
},
|
||||
Notifications: {
|
||||
screen: MyNotificationsScreen,
|
||||
path: 'notifications',
|
||||
},
|
||||
Settings: {
|
||||
screen: MySettingsScreen,
|
||||
path: 'settings',
|
||||
},
|
||||
},
|
||||
Notifications: {
|
||||
screen: MyNotificationsScreen,
|
||||
path: 'notifications',
|
||||
},
|
||||
Settings: {
|
||||
screen: MySettingsScreen,
|
||||
path: 'settings',
|
||||
},
|
||||
}, {
|
||||
// Change this to start on a different tab
|
||||
initialRouteName: 'Home',
|
||||
});
|
||||
{
|
||||
// Change this to start on a different tab
|
||||
initialRouteName: 'Home',
|
||||
}
|
||||
);
|
||||
|
||||
const CustomTabs = createNavigationContainer(createNavigator(CustomTabRouter)(CustomTabView));
|
||||
const CustomTabs = createNavigationContainer(
|
||||
createNavigator(CustomTabRouter)(CustomTabView)
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
@@ -127,7 +118,7 @@ const styles = StyleSheet.create({
|
||||
borderWidth: 1,
|
||||
borderColor: '#ddd',
|
||||
borderRadius: 4,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default CustomTabs;
|
||||
|
||||
@@ -3,15 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
} from 'react-native';
|
||||
import {
|
||||
DrawerNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, Platform, ScrollView, StyleSheet } from 'react-native';
|
||||
import { DrawerNavigator } from 'react-navigation';
|
||||
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
@@ -22,18 +15,12 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
onPress={() => navigation.navigate('DrawerOpen')}
|
||||
title="Open drawer"
|
||||
/>
|
||||
<Button
|
||||
onPress={() => navigation.goBack(null)}
|
||||
title="Go back"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const InboxScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner={'Inbox Screen'}
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner={'Inbox Screen'} navigation={navigation} />
|
||||
);
|
||||
InboxScreen.navigationOptions = {
|
||||
drawerLabel: 'Inbox',
|
||||
@@ -47,37 +34,33 @@ InboxScreen.navigationOptions = {
|
||||
};
|
||||
|
||||
const DraftsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner={'Drafts Screen'}
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner={'Drafts Screen'} navigation={navigation} />
|
||||
);
|
||||
DraftsScreen.navigationOptions = {
|
||||
drawerLabel: 'Drafts',
|
||||
drawerIcon: ({ tintColor }) => (
|
||||
<MaterialIcons
|
||||
name="drafts"
|
||||
size={24}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
<MaterialIcons name="drafts" size={24} style={{ color: tintColor }} />
|
||||
),
|
||||
};
|
||||
|
||||
const DrawerExample = DrawerNavigator({
|
||||
Inbox: {
|
||||
path: '/',
|
||||
screen: InboxScreen,
|
||||
const DrawerExample = DrawerNavigator(
|
||||
{
|
||||
Inbox: {
|
||||
path: '/',
|
||||
screen: InboxScreen,
|
||||
},
|
||||
Drafts: {
|
||||
path: '/sent',
|
||||
screen: DraftsScreen,
|
||||
},
|
||||
},
|
||||
Drafts: {
|
||||
path: '/sent',
|
||||
screen: DraftsScreen,
|
||||
},
|
||||
}, {
|
||||
initialRouteName: 'Drafts',
|
||||
contentOptions: {
|
||||
activeTintColor: '#e91e63',
|
||||
},
|
||||
});
|
||||
{
|
||||
initialRouteName: 'Drafts',
|
||||
contentOptions: {
|
||||
activeTintColor: '#e91e63',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
||||
@@ -3,14 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
ScrollView,
|
||||
Text,
|
||||
} from 'react-native';
|
||||
import {
|
||||
StackNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, ScrollView, Text } from 'react-native';
|
||||
import { StackNavigator } from 'react-navigation';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
const MyNavScreen = ({ navigation, banner }) => (
|
||||
@@ -24,24 +18,21 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
onPress={() => navigation.navigate('HeaderTest')}
|
||||
title="Go to a header toggle screen"
|
||||
/>
|
||||
{navigation.state.routeName === 'HeaderTest' && <Button
|
||||
title="Toggle Header"
|
||||
onPress={() => navigation.setParams({
|
||||
headerVisible: (!navigation.state.params || !navigation.state.params.headerVisible),
|
||||
})}
|
||||
/>}
|
||||
<Button
|
||||
onPress={() => navigation.goBack(null)}
|
||||
title="Go back"
|
||||
/>
|
||||
{navigation.state.routeName === 'HeaderTest' &&
|
||||
<Button
|
||||
title="Toggle Header"
|
||||
onPress={() =>
|
||||
navigation.setParams({
|
||||
headerVisible: !navigation.state.params ||
|
||||
!navigation.state.params.headerVisible,
|
||||
})}
|
||||
/>}
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const MyHomeScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Home Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Home Screen" navigation={navigation} />
|
||||
);
|
||||
MyHomeScreen.navigationOptions = {
|
||||
title: 'Welcome',
|
||||
@@ -57,44 +48,48 @@ MyProfileScreen.navigationOptions = ({ navigation }) => ({
|
||||
title: `${navigation.state.params.name}'s Profile!`,
|
||||
});
|
||||
|
||||
const ProfileNavigator = StackNavigator({
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
const ProfileNavigator = StackNavigator(
|
||||
{
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
},
|
||||
Profile: {
|
||||
path: 'people/:name',
|
||||
screen: MyProfileScreen,
|
||||
},
|
||||
},
|
||||
Profile: {
|
||||
path: 'people/:name',
|
||||
screen: MyProfileScreen,
|
||||
},
|
||||
}, {
|
||||
navigationOptions: {
|
||||
header: null,
|
||||
},
|
||||
});
|
||||
{
|
||||
navigationOptions: {
|
||||
header: null,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const MyHeaderTestScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner={`Full screen view`}
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner={`Full screen view`} navigation={navigation} />
|
||||
);
|
||||
MyHeaderTestScreen.navigationOptions = ({ navigation }) => {
|
||||
const headerVisible = navigation.state.params && navigation.state.params.headerVisible;
|
||||
const headerVisible =
|
||||
navigation.state.params && navigation.state.params.headerVisible;
|
||||
return {
|
||||
header: headerVisible ? undefined : null,
|
||||
title: 'Now you see me',
|
||||
};
|
||||
};
|
||||
|
||||
const ModalStack = StackNavigator({
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
const ModalStack = StackNavigator(
|
||||
{
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
},
|
||||
ProfileNavigator: {
|
||||
screen: ProfileNavigator,
|
||||
},
|
||||
HeaderTest: { screen: MyHeaderTestScreen },
|
||||
},
|
||||
ProfileNavigator: {
|
||||
screen: ProfileNavigator,
|
||||
},
|
||||
HeaderTest: {screen: MyHeaderTestScreen},
|
||||
}, {
|
||||
mode: 'modal',
|
||||
});
|
||||
{
|
||||
mode: 'modal',
|
||||
}
|
||||
);
|
||||
|
||||
export default ModalStack;
|
||||
|
||||
@@ -2,21 +2,14 @@
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
} from 'react-native';
|
||||
import { StyleSheet, Text } from 'react-native';
|
||||
|
||||
/**
|
||||
* Used across examples as a screen placeholder.
|
||||
*/
|
||||
import type { Children } from 'react';
|
||||
import type { Children } from 'react';
|
||||
|
||||
const SampleText = ({
|
||||
children
|
||||
}: {
|
||||
children?: Children
|
||||
}) => (
|
||||
const SampleText = ({ children }: { children?: Children }) => (
|
||||
<Text style={styles.sampleText}>{children}</Text>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,13 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
ScrollView,
|
||||
} from 'react-native';
|
||||
import {
|
||||
StackNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, ScrollView } from 'react-native';
|
||||
import { StackNavigator } from 'react-navigation';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
const MyNavScreen = ({ navigation, banner }) => (
|
||||
@@ -23,18 +18,12 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
onPress={() => navigation.navigate('Photos', { name: 'Jane' })}
|
||||
title="Go to a photos screen"
|
||||
/>
|
||||
<Button
|
||||
onPress={() => navigation.goBack(null)}
|
||||
title="Go back"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const MyHomeScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Home Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Home Screen" navigation={navigation} />
|
||||
);
|
||||
MyHomeScreen.navigationOptions = {
|
||||
title: 'Welcome',
|
||||
@@ -52,18 +41,15 @@ MyPhotosScreen.navigationOptions = {
|
||||
|
||||
const MyProfileScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner={
|
||||
`${navigation.state.params.mode === 'edit' ? 'Now Editing ' : ''
|
||||
}${navigation.state.params.name}'s Profile`
|
||||
}
|
||||
banner={`${navigation.state.params.mode === 'edit' ? 'Now Editing ' : ''}${navigation.state.params.name}'s Profile`}
|
||||
navigation={navigation}
|
||||
/>
|
||||
);
|
||||
|
||||
MyProfileScreen.navigationOptions = props => {
|
||||
const {navigation} = props;
|
||||
const {state, setParams} = navigation;
|
||||
const {params} = state;
|
||||
const { navigation } = props;
|
||||
const { state, setParams } = navigation;
|
||||
const { params } = state;
|
||||
return {
|
||||
headerTitle: `${params.name}'s Profile!`,
|
||||
// Render a button on the right side of the header.
|
||||
@@ -71,7 +57,8 @@ MyProfileScreen.navigationOptions = props => {
|
||||
headerRight: (
|
||||
<Button
|
||||
title={params.mode === 'edit' ? 'Done' : 'Edit'}
|
||||
onPress={() => setParams({ mode: params.mode === 'edit' ? '' : 'edit' })}
|
||||
onPress={() =>
|
||||
setParams({ mode: params.mode === 'edit' ? '' : 'edit' })}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
@@ -3,15 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
} from 'react-native';
|
||||
import {
|
||||
TabNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, Platform, ScrollView, StyleSheet } from 'react-native';
|
||||
import { TabNavigator } from 'react-navigation';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
@@ -26,18 +19,12 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
onPress={() => navigation.navigate('Settings')}
|
||||
title="Go to settings tab"
|
||||
/>
|
||||
<Button
|
||||
onPress={() => navigation.goBack(null)}
|
||||
title="Go back"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const MyHomeScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Home Tab"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Home Tab" navigation={navigation} />
|
||||
);
|
||||
|
||||
MyHomeScreen.navigationOptions = {
|
||||
@@ -52,10 +39,7 @@ MyHomeScreen.navigationOptions = {
|
||||
};
|
||||
|
||||
const MyPeopleScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="People Tab"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="People Tab" navigation={navigation} />
|
||||
);
|
||||
|
||||
MyPeopleScreen.navigationOptions = {
|
||||
@@ -70,10 +54,7 @@ MyPeopleScreen.navigationOptions = {
|
||||
};
|
||||
|
||||
const MyChatScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Chat Tab"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Chat Tab" navigation={navigation} />
|
||||
);
|
||||
|
||||
MyChatScreen.navigationOptions = {
|
||||
@@ -88,10 +69,7 @@ MyChatScreen.navigationOptions = {
|
||||
};
|
||||
|
||||
const MySettingsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Settings Tab"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Settings Tab" navigation={navigation} />
|
||||
);
|
||||
|
||||
MySettingsScreen.navigationOptions = {
|
||||
@@ -105,28 +83,31 @@ MySettingsScreen.navigationOptions = {
|
||||
),
|
||||
};
|
||||
|
||||
const SimpleTabs = TabNavigator({
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
path: '',
|
||||
const SimpleTabs = TabNavigator(
|
||||
{
|
||||
Home: {
|
||||
screen: MyHomeScreen,
|
||||
path: '',
|
||||
},
|
||||
People: {
|
||||
screen: MyPeopleScreen,
|
||||
path: 'cart',
|
||||
},
|
||||
Chat: {
|
||||
screen: MyChatScreen,
|
||||
path: 'chat',
|
||||
},
|
||||
Settings: {
|
||||
screen: MySettingsScreen,
|
||||
path: 'settings',
|
||||
},
|
||||
},
|
||||
People: {
|
||||
screen: MyPeopleScreen,
|
||||
path: 'cart',
|
||||
},
|
||||
Chat: {
|
||||
screen: MyChatScreen,
|
||||
path: 'chat',
|
||||
},
|
||||
Settings: {
|
||||
screen: MySettingsScreen,
|
||||
path: 'settings',
|
||||
},
|
||||
}, {
|
||||
tabBarOptions: {
|
||||
activeTintColor: Platform.OS === 'ios' ? '#e91e63' : '#fff',
|
||||
},
|
||||
});
|
||||
{
|
||||
tabBarOptions: {
|
||||
activeTintColor: Platform.OS === 'ios' ? '#e91e63' : '#fff',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
||||
@@ -3,14 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
ScrollView,
|
||||
} from 'react-native';
|
||||
import {
|
||||
StackNavigator,
|
||||
TabNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, ScrollView } from 'react-native';
|
||||
import { StackNavigator, TabNavigator } from 'react-navigation';
|
||||
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import SampleText from './SampleText';
|
||||
@@ -30,18 +24,12 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
onPress={() => navigation.navigate('SettingsTab')}
|
||||
title="Go to settings tab"
|
||||
/>
|
||||
<Button
|
||||
onPress={() => navigation.goBack(null)}
|
||||
title="Go back"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const MyHomeScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Home Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Home Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MyProfileScreen = ({ navigation }) => (
|
||||
@@ -52,17 +40,11 @@ const MyProfileScreen = ({ navigation }) => (
|
||||
);
|
||||
|
||||
const MyNotificationsSettingsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Notifications Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MySettingsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Settings Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Settings Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MainTab = StackNavigator({
|
||||
@@ -98,39 +80,42 @@ const SettingsTab = StackNavigator({
|
||||
},
|
||||
});
|
||||
|
||||
const StacksInTabs = TabNavigator({
|
||||
MainTab: {
|
||||
screen: MainTab,
|
||||
path: '/',
|
||||
navigationOptions: {
|
||||
tabBarLabel: 'Home',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-home' : 'ios-home-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
const StacksInTabs = TabNavigator(
|
||||
{
|
||||
MainTab: {
|
||||
screen: MainTab,
|
||||
path: '/',
|
||||
navigationOptions: {
|
||||
tabBarLabel: 'Home',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-home' : 'ios-home-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
SettingsTab: {
|
||||
screen: SettingsTab,
|
||||
path: '/settings',
|
||||
navigationOptions: {
|
||||
tabBarLabel: 'Settings',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-settings' : 'ios-settings-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
SettingsTab: {
|
||||
screen: SettingsTab,
|
||||
path: '/settings',
|
||||
navigationOptions: {
|
||||
tabBarLabel: 'Settings',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-settings' : 'ios-settings-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
}, {
|
||||
tabBarPosition: 'bottom',
|
||||
animationEnabled: false,
|
||||
swipeEnabled: false,
|
||||
});
|
||||
{
|
||||
tabBarPosition: 'bottom',
|
||||
animationEnabled: false,
|
||||
swipeEnabled: false,
|
||||
}
|
||||
);
|
||||
|
||||
export default StacksInTabs;
|
||||
|
||||
@@ -3,14 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
ScrollView,
|
||||
} from 'react-native';
|
||||
import {
|
||||
StackNavigator,
|
||||
TabNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, ScrollView } from 'react-native';
|
||||
import { StackNavigator, TabNavigator } from 'react-navigation';
|
||||
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import SampleText from './SampleText';
|
||||
@@ -30,18 +24,12 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
onPress={() => navigation.navigate('SettingsTab')}
|
||||
title="Go to settings tab"
|
||||
/>
|
||||
<Button
|
||||
onPress={() => navigation.goBack(null)}
|
||||
title="Go back"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const MyHomeScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Home Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Home Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MyProfileScreen = ({ navigation }) => (
|
||||
@@ -52,54 +40,51 @@ const MyProfileScreen = ({ navigation }) => (
|
||||
);
|
||||
|
||||
const MyNotificationsSettingsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Notifications Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const MySettingsScreen = ({ navigation }) => (
|
||||
<MyNavScreen
|
||||
banner="Settings Screen"
|
||||
navigation={navigation}
|
||||
/>
|
||||
<MyNavScreen banner="Settings Screen" navigation={navigation} />
|
||||
);
|
||||
|
||||
const TabNav = TabNavigator({
|
||||
MainTab: {
|
||||
screen: MyHomeScreen,
|
||||
path: '/',
|
||||
navigationOptions: {
|
||||
title: 'Welcome',
|
||||
tabBarLabel: 'Home',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-home' : 'ios-home-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
const TabNav = TabNavigator(
|
||||
{
|
||||
MainTab: {
|
||||
screen: MyHomeScreen,
|
||||
path: '/',
|
||||
navigationOptions: {
|
||||
title: 'Welcome',
|
||||
tabBarLabel: 'Home',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-home' : 'ios-home-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
SettingsTab: {
|
||||
screen: MySettingsScreen,
|
||||
path: '/settings',
|
||||
navigationOptions: {
|
||||
title: 'Settings',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-settings' : 'ios-settings-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
SettingsTab: {
|
||||
screen: MySettingsScreen,
|
||||
path: '/settings',
|
||||
navigationOptions: {
|
||||
title: 'Settings',
|
||||
tabBarIcon: ({ tintColor, focused }) => (
|
||||
<Ionicons
|
||||
name={focused ? 'ios-settings' : 'ios-settings-outline'}
|
||||
size={26}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
},
|
||||
},
|
||||
}, {
|
||||
tabBarPosition: 'bottom',
|
||||
animationEnabled: false,
|
||||
swipeEnabled: false,
|
||||
});
|
||||
{
|
||||
tabBarPosition: 'bottom',
|
||||
animationEnabled: false,
|
||||
swipeEnabled: false,
|
||||
}
|
||||
);
|
||||
|
||||
const StacksOverTabs = StackNavigator({
|
||||
Root: {
|
||||
@@ -115,7 +100,7 @@ const StacksOverTabs = StackNavigator({
|
||||
screen: MyProfileScreen,
|
||||
path: '/people/:name',
|
||||
navigationOptions: ({ navigation }) => {
|
||||
title: `${navigation.state.params.name}'s Profile!`
|
||||
title: `${navigation.state.params.name}'s Profile!`;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,16 +3,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Button,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
} from 'react-native';
|
||||
import {
|
||||
TabNavigator,
|
||||
DrawerNavigator,
|
||||
} from 'react-navigation';
|
||||
import { Button, Platform, ScrollView, StyleSheet } from 'react-native';
|
||||
import { TabNavigator, DrawerNavigator } from 'react-navigation';
|
||||
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
||||
import SimpleTabs from './SimpleTabs';
|
||||
import StacksOverTabs from './StacksOverTabs';
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "16.0.0-alpha.6",
|
||||
"react-native": "0.43.3",
|
||||
"react-redux": "5.0.4",
|
||||
|
||||
@@ -22,7 +22,8 @@ const mapStateToProps = state => ({
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
logout: () => dispatch({ type: 'Logout' }),
|
||||
loginScreen: () => dispatch(NavigationActions.navigate({ routeName: 'Login' })),
|
||||
loginScreen: () =>
|
||||
dispatch(NavigationActions.navigate({ routeName: 'Login' })),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AuthButton);
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import {
|
||||
Button,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { Button, StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
Button,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { Button, StyleSheet, Text, View } from 'react-native';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -26,7 +21,8 @@ const LoginStatusMessage = ({ isLoggedIn, dispatch }) => {
|
||||
{'You are "logged in" right now'}
|
||||
</Text>
|
||||
<Button
|
||||
onPress={() => dispatch(NavigationActions.navigate({ routeName: 'Profile' }))}
|
||||
onPress={() =>
|
||||
dispatch(NavigationActions.navigate({ routeName: 'Profile' }))}
|
||||
title="Profile"
|
||||
/>
|
||||
</View>
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { connect } from 'react-redux';
|
||||
import { addNavigationHelpers, StackNavigator } from 'react-navigation';
|
||||
|
||||
|
||||
@@ -7,16 +7,25 @@ import { AppNavigator } from '../navigators/AppNavigator';
|
||||
const firstAction = AppNavigator.router.getActionForPathAndParams('Main');
|
||||
const tempNavState = AppNavigator.router.getStateForAction(firstAction);
|
||||
const secondAction = AppNavigator.router.getActionForPathAndParams('Login');
|
||||
const initialNavState = AppNavigator.router.getStateForAction(secondAction, tempNavState);
|
||||
const initialNavState = AppNavigator.router.getStateForAction(
|
||||
secondAction,
|
||||
tempNavState
|
||||
);
|
||||
|
||||
function nav(state = initialNavState, action) {
|
||||
let nextState;
|
||||
switch (action.type) {
|
||||
case 'Login':
|
||||
nextState = AppNavigator.router.getStateForAction(NavigationActions.back(), state);
|
||||
nextState = AppNavigator.router.getStateForAction(
|
||||
NavigationActions.back(),
|
||||
state
|
||||
);
|
||||
break;
|
||||
case 'Logout':
|
||||
nextState = AppNavigator.router.getStateForAction(NavigationActions.navigate({ routeName: 'Login' }), state);
|
||||
nextState = AppNavigator.router.getStateForAction(
|
||||
NavigationActions.navigate({ routeName: 'Login' }),
|
||||
state
|
||||
);
|
||||
break;
|
||||
default:
|
||||
nextState = AppNavigator.router.getStateForAction(action, state);
|
||||
|
||||
@@ -2471,7 +2471,7 @@ longest@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0:
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
|
||||
dependencies:
|
||||
@@ -2908,6 +2908,13 @@ prop-types@^15.0.0, prop-types@^15.5.8:
|
||||
dependencies:
|
||||
fbjs "^0.8.9"
|
||||
|
||||
prop-types@^15.5.10:
|
||||
version "15.5.10"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
|
||||
dependencies:
|
||||
fbjs "^0.8.9"
|
||||
loose-envify "^1.3.1"
|
||||
|
||||
prr@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a"
|
||||
|
||||
13
packages/react-navigation/jest-setup.js
vendored
13
packages/react-navigation/jest-setup.js
vendored
@@ -1,4 +1,7 @@
|
||||
/* eslint-env jest */
|
||||
/**
|
||||
* @flow
|
||||
* eslint-env jest
|
||||
*/
|
||||
|
||||
// See https://github.com/facebook/jest/issues/2208
|
||||
jest.mock('Linking', () => ({
|
||||
@@ -6,16 +9,20 @@ jest.mock('Linking', () => ({
|
||||
removeEventListener: jest.fn(),
|
||||
openURL: jest.fn(),
|
||||
canOpenURL: jest.fn(),
|
||||
getInitialURL: jest.fn().mockImplementation((value: string) => Promise.resolve(value)),
|
||||
getInitialURL: jest
|
||||
.fn()
|
||||
.mockImplementation((value: string) => Promise.resolve(value)),
|
||||
}));
|
||||
|
||||
// See https://github.com/facebook/react-native/issues/11659
|
||||
jest.mock('ScrollView', () => {
|
||||
// $FlowExpectedError
|
||||
const RealComponent = require.requireActual('ScrollView');
|
||||
class ScrollView extends RealComponent {
|
||||
scrollTo = () => {}
|
||||
scrollTo = () => {};
|
||||
}
|
||||
return ScrollView;
|
||||
});
|
||||
|
||||
// $FlowExpectedError
|
||||
Date.now = jest.fn(() => 0);
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
"run-playground-android": "cd examples/NavigationPlayground && react-native run-android",
|
||||
"test": "npm run lint && npm run flow && npm run jest",
|
||||
"jest": "jest",
|
||||
"lint": "eslint src",
|
||||
"format": "eslint --fix src",
|
||||
"lint": "eslint .",
|
||||
"format": "eslint --fix .",
|
||||
"flow": "flow",
|
||||
"prepublish": "npm run clean && npm run build"
|
||||
},
|
||||
@@ -40,27 +40,27 @@
|
||||
"src"
|
||||
],
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.0",
|
||||
"babel-core": "^6.24.0",
|
||||
"babel-eslint": "^7.0.0",
|
||||
"babel-jest": "^19.0.0",
|
||||
"babel-plugin-flow-react-proptypes": "^1.2.0",
|
||||
"babel-preset-es2015": "^6.24.0",
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"babel-preset-react-native": "^1.9.0",
|
||||
"babel-cli": "^6.24.1",
|
||||
"babel-core": "^6.24.1",
|
||||
"babel-eslint": "^7.2.3",
|
||||
"babel-jest": "^20.0.1",
|
||||
"babel-plugin-flow-react-proptypes": "^2.2.1",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-preset-react-native": "^1.9.2",
|
||||
"babel-preset-react-native-syntax": "^1.0.0",
|
||||
"babel-preset-stage-1": "^6.16.0",
|
||||
"eslint": "^3.17.1",
|
||||
"eslint-config-airbnb": "^14.1.0",
|
||||
"eslint-config-prettier": "^1.5.0",
|
||||
"eslint-plugin-flowtype": "^2.30.3",
|
||||
"babel-preset-stage-1": "^6.24.1",
|
||||
"eslint": "^3.19.0",
|
||||
"eslint-config-prettier": "^2.1.0",
|
||||
"eslint-plugin-flowtype": "^2.33.0",
|
||||
"eslint-plugin-import": "^2.2.0",
|
||||
"eslint-plugin-jsx-a11y": "^4.0.0",
|
||||
"eslint-plugin-jsx-a11y": "^5.0.1",
|
||||
"eslint-plugin-prettier": "^2.0.1",
|
||||
"eslint-plugin-react": "^6.10.0",
|
||||
"flow-bin": "^0.40.0",
|
||||
"jest": "^19.0.2",
|
||||
"prettier": "^0.22.0",
|
||||
"eslint-plugin-react": "^7.0.1",
|
||||
"flow-bin": "0.40.0",
|
||||
"jest": "^20.0.1",
|
||||
"prettier": "^1.3.1",
|
||||
"prettier-eslint": "^6.2.2",
|
||||
"react": "16.0.0-alpha.6",
|
||||
"react-native": "^0.43.2",
|
||||
"react-native-vector-icons": "^3.0.0",
|
||||
@@ -72,11 +72,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"clamp": "^1.0.1",
|
||||
"fbjs": "^0.8.5",
|
||||
"fbjs": "^0.8.12",
|
||||
"hoist-non-react-statics": "^1.2.0",
|
||||
"path-to-regexp": "^1.7.0",
|
||||
"prop-types": "^15.5.8",
|
||||
"react-native-drawer-layout-polyfill": "1.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-native-drawer-layout-polyfill": "^1.3.0",
|
||||
"react-native-tab-view": "^0.0.65"
|
||||
},
|
||||
"jest": {
|
||||
|
||||
@@ -10,23 +10,27 @@
|
||||
const blacklist = require('react-native/packager/blacklist');
|
||||
const config = require('react-native/packager/rn-cli.config');
|
||||
|
||||
const examples = [
|
||||
'NavigationPlayground',
|
||||
'ReduxExample',
|
||||
];
|
||||
const examples = ['NavigationPlayground', 'ReduxExample'];
|
||||
|
||||
config.getBlacklist = () => (
|
||||
examples.reduce((a, example) => a.concat([
|
||||
...config.getBlacklistForExample(example),
|
||||
new RegExp(`examples/${example}/__exponent/(.*)`),
|
||||
]), [])
|
||||
);
|
||||
config.getBlacklist = () =>
|
||||
examples.reduce(
|
||||
(a, example) =>
|
||||
a.concat([
|
||||
...config.getBlacklistForExample(example),
|
||||
new RegExp(`examples/${example}/__exponent/(.*)`),
|
||||
]),
|
||||
[]
|
||||
);
|
||||
|
||||
config.getBlacklistForExample = (example) => ([
|
||||
...examples.filter(x => x !== example).map(x => new RegExp(`examples/${x}/node_modules/react-native/(.*)`)),
|
||||
...examples.filter(x => x !== example).map(x => new RegExp(`examples/${x}/node_modules/react/(.*)`)),
|
||||
config.getBlacklistForExample = example => [
|
||||
...examples
|
||||
.filter(x => x !== example)
|
||||
.map(x => new RegExp(`examples/${x}/node_modules/react-native/(.*)`)),
|
||||
...examples
|
||||
.filter(x => x !== example)
|
||||
.map(x => new RegExp(`examples/${x}/node_modules/react/(.*)`)),
|
||||
new RegExp(`examples/${example}/node_modules/react-navigation/(.*)`),
|
||||
]);
|
||||
];
|
||||
|
||||
config.getBlacklistRE = () => blacklist(config.getBlacklist());
|
||||
|
||||
@@ -34,9 +38,7 @@ config.getProjectRoots = () => getRoots();
|
||||
config.getAssetRoots = () => getRoots();
|
||||
|
||||
function getRoots() {
|
||||
return [
|
||||
__dirname,
|
||||
];
|
||||
return [__dirname];
|
||||
}
|
||||
|
||||
module.exports = config;
|
||||
|
||||
@@ -17,7 +17,7 @@ function crawl(location) {
|
||||
crawl('docs');
|
||||
|
||||
var names = files.map(function(file) {
|
||||
const nameWithExt = file.split('docs'+path.sep)[1];
|
||||
const nameWithExt = file.split('docs' + path.sep)[1];
|
||||
const name = nameWithExt.split('.md')[0];
|
||||
return name;
|
||||
});
|
||||
@@ -25,7 +25,12 @@ var names = files.map(function(file) {
|
||||
var mdData = {};
|
||||
|
||||
names.map(function(name) {
|
||||
mdData[name] = fs.readFileSync('docs'+path.sep+name+'.md', {encoding: 'utf8'});
|
||||
mdData[name] = fs.readFileSync('docs' + path.sep + name + '.md', {
|
||||
encoding: 'utf8',
|
||||
});
|
||||
});
|
||||
|
||||
fs.writeFileSync('website'+path.sep+'docs-dist.json', JSON.stringify(mdData));
|
||||
fs.writeFileSync(
|
||||
'website' + path.sep + 'docs-dist.json',
|
||||
JSON.stringify(mdData)
|
||||
);
|
||||
|
||||
@@ -7,11 +7,10 @@ const RESET = namespacedAction('RESET');
|
||||
const SET_PARAMS = namespacedAction('SET_PARAMS');
|
||||
const URI = namespacedAction('URI');
|
||||
|
||||
const createAction = (type: string) =>
|
||||
(payload: Object = {}) => ({
|
||||
type,
|
||||
...payload,
|
||||
});
|
||||
const createAction = (type: string) => (payload: Object = {}) => ({
|
||||
type,
|
||||
...payload,
|
||||
});
|
||||
|
||||
const back = createAction(BACK);
|
||||
const init = createAction(INIT);
|
||||
@@ -44,7 +43,7 @@ const mapDeprecatedActionAndWarn = (action: Object) => {
|
||||
"the 'actions' object.",
|
||||
'See https://github.com/react-community/react-navigation/pull/120 for',
|
||||
'more details.',
|
||||
].join(' '),
|
||||
].join(' ')
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
12
packages/react-navigation/src/StateUtils.js
vendored
12
packages/react-navigation/src/StateUtils.js
vendored
@@ -45,7 +45,7 @@ const StateUtils = {
|
||||
invariant(
|
||||
StateUtils.indexOf(state, route.key) === -1,
|
||||
'should not push route with duplicated key %s',
|
||||
route.key,
|
||||
route.key
|
||||
);
|
||||
|
||||
const routes = state.routes.slice();
|
||||
@@ -126,7 +126,7 @@ const StateUtils = {
|
||||
replaceAt(
|
||||
state: NavigationState,
|
||||
key: string,
|
||||
route: NavigationRoute,
|
||||
route: NavigationRoute
|
||||
): NavigationState {
|
||||
const index = StateUtils.indexOf(state, key);
|
||||
return StateUtils.replaceAtIndex(state, index, route);
|
||||
@@ -140,13 +140,13 @@ const StateUtils = {
|
||||
replaceAtIndex(
|
||||
state: NavigationState,
|
||||
index: number,
|
||||
route: NavigationRoute,
|
||||
route: NavigationRoute
|
||||
): NavigationState {
|
||||
invariant(
|
||||
!!state.routes[index],
|
||||
'invalid index %s for replacing route %s',
|
||||
index,
|
||||
route.key,
|
||||
route.key
|
||||
);
|
||||
|
||||
if (state.routes[index] === route) {
|
||||
@@ -171,11 +171,11 @@ const StateUtils = {
|
||||
reset(
|
||||
state: NavigationState,
|
||||
routes: Array<NavigationRoute>,
|
||||
index?: number,
|
||||
index?: number
|
||||
): NavigationState {
|
||||
invariant(
|
||||
routes.length && Array.isArray(routes),
|
||||
'invalid routes to replace',
|
||||
'invalid routes to replace'
|
||||
);
|
||||
|
||||
const nextIndex: number = index === undefined ? routes.length - 1 : index;
|
||||
|
||||
66
packages/react-navigation/src/TypeDefinition.js
vendored
66
packages/react-navigation/src/TypeDefinition.js
vendored
@@ -10,10 +10,14 @@ export type HeaderMode = 'float' | 'screen' | 'none';
|
||||
|
||||
export type HeaderProps = NavigationSceneRendererProps & {
|
||||
mode: HeaderMode,
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationStackScreenOptions>,
|
||||
getScreenDetails: (
|
||||
NavigationScene,
|
||||
) => NavigationScreenDetails<NavigationStackScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationStackScreenOptions
|
||||
>,
|
||||
getScreenDetails: NavigationScene => NavigationScreenDetails<
|
||||
NavigationStackScreenOptions
|
||||
>,
|
||||
style: Style,
|
||||
};
|
||||
|
||||
@@ -69,7 +73,7 @@ export type NavigationStateRoute = NavigationLeafRoute & {
|
||||
|
||||
export type NavigationScreenOptionsGetter<Options, Action> = (
|
||||
navigation: NavigationScreenProp<NavigationRoute, Action>,
|
||||
screenProps?: {},
|
||||
screenProps?: {}
|
||||
) => Options;
|
||||
|
||||
export type NavigationRouter<State, Action, Options> = {
|
||||
@@ -86,10 +90,12 @@ export type NavigationRouter<State, Action, Options> = {
|
||||
*/
|
||||
getActionForPathAndParams: (
|
||||
path: string,
|
||||
params?: NavigationParams,
|
||||
params?: NavigationParams
|
||||
) => ?Action,
|
||||
|
||||
getPathAndParamsForState: (state: State) => {
|
||||
getPathAndParamsForState: (
|
||||
state: State
|
||||
) => {
|
||||
path: string,
|
||||
params?: NavigationParams,
|
||||
},
|
||||
@@ -113,7 +119,7 @@ export type NavigationScreenOption<T> =
|
||||
| T
|
||||
| ((
|
||||
navigation: NavigationScreenProp<NavigationRoute, NavigationAction>,
|
||||
config: T,
|
||||
config: T
|
||||
) => T);
|
||||
|
||||
export type Style =
|
||||
@@ -141,11 +147,13 @@ export type NavigationScreenConfigProps = {
|
||||
|
||||
export type NavigationScreenConfig<Options> =
|
||||
| Options
|
||||
| (NavigationScreenConfigProps & ((
|
||||
{
|
||||
navigationOptions: NavigationScreenProp<NavigationRoute, NavigationAction>,
|
||||
},
|
||||
) => Options));
|
||||
| (NavigationScreenConfigProps &
|
||||
(({
|
||||
navigationOptions: NavigationScreenProp<
|
||||
NavigationRoute,
|
||||
NavigationAction
|
||||
>,
|
||||
}) => Options));
|
||||
|
||||
export type NavigationComponent =
|
||||
| NavigationScreenComponent<*, *>
|
||||
@@ -215,7 +223,7 @@ export type NavigationStackViewConfig = {
|
||||
};
|
||||
|
||||
export type NavigationStackScreenOptions = NavigationScreenOptions & {
|
||||
header?: ?(React.Element<*> | ((HeaderProps) => React.Element<*>)),
|
||||
header?: ?(React.Element<*> | (HeaderProps => React.Element<*>)),
|
||||
headerTitle?: string | React.Element<*>,
|
||||
headerTitleStyle?: Style,
|
||||
headerTintColor?: string,
|
||||
@@ -283,29 +291,29 @@ export type NavigationTabRouterConfig = {
|
||||
export type NavigationTabScreenOptions = NavigationScreenOptions & {
|
||||
tabBarIcon?:
|
||||
| React.Element<*>
|
||||
| ((
|
||||
options: { tintColor: ?string, focused: boolean },
|
||||
) => ?React.Element<*>),
|
||||
| ((options: { tintColor: ?string, focused: boolean }) => ?React.Element<
|
||||
*
|
||||
>),
|
||||
tabBarLabel?:
|
||||
| string
|
||||
| React.Element<*>
|
||||
| ((
|
||||
options: { tintColor: ?string, focused: boolean },
|
||||
) => ?React.Element<*>),
|
||||
| ((options: { tintColor: ?string, focused: boolean }) => ?React.Element<
|
||||
*
|
||||
>),
|
||||
tabBarVisible?: boolean,
|
||||
};
|
||||
|
||||
export type NavigationDrawerScreenOptions = NavigationScreenOptions & {
|
||||
drawerIcon?:
|
||||
| React.Element<*>
|
||||
| ((
|
||||
options: { tintColor: ?string, focused: boolean },
|
||||
) => ?React.Element<*>),
|
||||
| ((options: { tintColor: ?string, focused: boolean }) => ?React.Element<
|
||||
*
|
||||
>),
|
||||
drawerLabel?:
|
||||
| React.Element<*>
|
||||
| ((
|
||||
options: { tintColor: ?string, focused: boolean },
|
||||
) => ?React.Element<*>),
|
||||
| ((options: { tintColor: ?string, focused: boolean }) => ?React.Element<
|
||||
*
|
||||
>),
|
||||
};
|
||||
|
||||
export type NavigationRouteConfigMap = {
|
||||
@@ -326,7 +334,7 @@ export type NavigationScreenProp<S, A> = {
|
||||
navigate: (
|
||||
routeName: string,
|
||||
params?: NavigationParams,
|
||||
action?: NavigationAction,
|
||||
action?: NavigationAction
|
||||
) => boolean,
|
||||
setParams: (newParams: NavigationParams) => boolean,
|
||||
};
|
||||
@@ -417,13 +425,13 @@ export type TransitionConfig = {
|
||||
export type NavigationAnimationSetter = (
|
||||
position: AnimatedValue,
|
||||
newState: NavigationState,
|
||||
lastState: NavigationState,
|
||||
lastState: NavigationState
|
||||
) => void;
|
||||
|
||||
export type NavigationSceneRenderer = () => ?React.Element<*>;
|
||||
|
||||
export type NavigationStyleInterpolator = (
|
||||
props: NavigationSceneRendererProps,
|
||||
props: NavigationSceneRendererProps
|
||||
) => Style;
|
||||
|
||||
export type LayoutEvent = {
|
||||
|
||||
@@ -42,14 +42,15 @@ describe('StateUtils', () => {
|
||||
routes: [{ key: 'a', routeName }, { key: 'b', routeName }],
|
||||
};
|
||||
expect(NavigationStateUtils.push(state, { key: 'b', routeName })).toEqual(
|
||||
newState,
|
||||
newState
|
||||
);
|
||||
});
|
||||
|
||||
it('does not push duplicated route', () => {
|
||||
const state = { index: 0, routes: [{ key: 'a', routeName }] };
|
||||
expect(() =>
|
||||
NavigationStateUtils.push(state, { key: 'a', routeName })).toThrow();
|
||||
NavigationStateUtils.push(state, { key: 'a', routeName })
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
// Pop
|
||||
@@ -147,7 +148,7 @@ describe('StateUtils', () => {
|
||||
routes: [{ key: 'a', routeName }, { key: 'c', routeName }],
|
||||
};
|
||||
expect(
|
||||
NavigationStateUtils.replaceAt(state, 'b', { key: 'c', routeName }),
|
||||
NavigationStateUtils.replaceAt(state, 'b', { key: 'c', routeName })
|
||||
).toEqual(newState);
|
||||
});
|
||||
|
||||
@@ -161,7 +162,7 @@ describe('StateUtils', () => {
|
||||
routes: [{ key: 'a', routeName }, { key: 'c', routeName }],
|
||||
};
|
||||
expect(
|
||||
NavigationStateUtils.replaceAtIndex(state, 1, { key: 'c', routeName }),
|
||||
NavigationStateUtils.replaceAtIndex(state, 1, { key: 'c', routeName })
|
||||
).toEqual(newState);
|
||||
});
|
||||
|
||||
@@ -171,7 +172,7 @@ describe('StateUtils', () => {
|
||||
routes: [{ key: 'a', routeName }, { key: 'b', routeName }],
|
||||
};
|
||||
expect(
|
||||
NavigationStateUtils.replaceAtIndex(state, 1, state.routes[1]),
|
||||
NavigationStateUtils.replaceAtIndex(state, 1, state.routes[1])
|
||||
).toEqual(state);
|
||||
});
|
||||
|
||||
@@ -189,7 +190,7 @@ describe('StateUtils', () => {
|
||||
NavigationStateUtils.reset(state, [
|
||||
{ key: 'x', routeName },
|
||||
{ key: 'y', routeName },
|
||||
]),
|
||||
])
|
||||
).toEqual(newState);
|
||||
|
||||
expect(() => {
|
||||
@@ -210,15 +211,15 @@ describe('StateUtils', () => {
|
||||
NavigationStateUtils.reset(
|
||||
state,
|
||||
[{ key: 'x', routeName }, { key: 'y', routeName }],
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
).toEqual(newState);
|
||||
|
||||
expect(() => {
|
||||
NavigationStateUtils.reset(
|
||||
state,
|
||||
[{ key: 'x', routeName }, { key: 'y', routeName }],
|
||||
100,
|
||||
100
|
||||
);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@ describe('addNavigationHelpers', () => {
|
||||
addNavigationHelpers({
|
||||
state: { key: 'A', routeName: 'Home' },
|
||||
dispatch: mockedDispatch,
|
||||
}).goBack('A'),
|
||||
}).goBack('A')
|
||||
).toEqual(true);
|
||||
expect(mockedDispatch).toBeCalledWith({
|
||||
type: NavigationActions.BACK,
|
||||
@@ -29,7 +29,7 @@ describe('addNavigationHelpers', () => {
|
||||
addNavigationHelpers({
|
||||
state: { routeName: 'Home' },
|
||||
dispatch: mockedDispatch,
|
||||
}).goBack(),
|
||||
}).goBack()
|
||||
).toEqual(true);
|
||||
expect(mockedDispatch).toBeCalledWith({ type: NavigationActions.BACK });
|
||||
expect(mockedDispatch.mock.calls.length).toBe(1);
|
||||
@@ -43,7 +43,7 @@ describe('addNavigationHelpers', () => {
|
||||
addNavigationHelpers({
|
||||
state: { routeName: 'Home' },
|
||||
dispatch: mockedDispatch,
|
||||
}).navigate('Profile', { name: 'Matt' }),
|
||||
}).navigate('Profile', { name: 'Matt' })
|
||||
).toEqual(true);
|
||||
expect(mockedDispatch).toBeCalledWith({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
@@ -61,7 +61,7 @@ describe('addNavigationHelpers', () => {
|
||||
addNavigationHelpers({
|
||||
state: { key: 'B', routeName: 'Settings' },
|
||||
dispatch: mockedDispatch,
|
||||
}).setParams({ notificationsEnabled: 'yes' }),
|
||||
}).setParams({ notificationsEnabled: 'yes' })
|
||||
).toEqual(true);
|
||||
expect(mockedDispatch).toBeCalledWith({
|
||||
type: NavigationActions.SET_PARAMS,
|
||||
|
||||
@@ -19,19 +19,19 @@ export default function<S: *>(navigation: NavigationProp<S, NavigationAction>) {
|
||||
navigation.dispatch(
|
||||
NavigationActions.back({
|
||||
key: key === undefined ? navigation.state.key : key,
|
||||
}),
|
||||
})
|
||||
),
|
||||
navigate: (
|
||||
routeName: string,
|
||||
params?: NavigationParams,
|
||||
action?: NavigationAction,
|
||||
action?: NavigationAction
|
||||
): boolean =>
|
||||
navigation.dispatch(
|
||||
NavigationActions.navigate({
|
||||
routeName,
|
||||
params,
|
||||
action,
|
||||
}),
|
||||
})
|
||||
),
|
||||
/**
|
||||
* For updating current route params. For example the nav bar title and
|
||||
@@ -43,7 +43,7 @@ export default function<S: *>(navigation: NavigationProp<S, NavigationAction>) {
|
||||
NavigationActions.setParams({
|
||||
params,
|
||||
key: navigation.state.key,
|
||||
}),
|
||||
})
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ type NavigationContainerProps = {
|
||||
onNavigationStateChange?: (
|
||||
NavigationState,
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationAction
|
||||
) => void,
|
||||
};
|
||||
|
||||
@@ -37,11 +37,11 @@ type State = {
|
||||
*/
|
||||
export default function createNavigationContainer<T: *>(
|
||||
Component: ReactClass<NavigationNavigatorProps<T>>,
|
||||
containerOptions?: {},
|
||||
containerOptions?: {}
|
||||
) {
|
||||
invariant(
|
||||
typeof containerOptions === 'undefined',
|
||||
'containerOptions.URIPrefix has been removed. Pass the uriPrefix prop to the navigator instead',
|
||||
'containerOptions.URIPrefix has been removed. Pass the uriPrefix prop to the navigator instead'
|
||||
);
|
||||
|
||||
class NavigationContainer extends React.Component<void, Props<T>, State> {
|
||||
@@ -75,11 +75,7 @@ export default function createNavigationContainer<T: *>(
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
navigation,
|
||||
screenProps,
|
||||
...containerProps
|
||||
} = props;
|
||||
const { navigation, screenProps, ...containerProps } = props;
|
||||
|
||||
const keys = Object.keys(containerProps);
|
||||
|
||||
@@ -88,7 +84,7 @@ export default function createNavigationContainer<T: *>(
|
||||
'This navigator has both navigation and container props, so it is ' +
|
||||
`unclear if it should own its own state. Remove props: "${keys.join(', ')}" ` +
|
||||
'if the navigator should get its state from the navigation prop. If the ' +
|
||||
'navigator should maintain its own state, do not pass a navigation prop.',
|
||||
'navigator should maintain its own state, do not pass a navigation prop.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,7 +115,7 @@ export default function createNavigationContainer<T: *>(
|
||||
_onNavigationStateChange(
|
||||
prevNav: NavigationState,
|
||||
nav: NavigationState,
|
||||
action: NavigationAction,
|
||||
action: NavigationAction
|
||||
) {
|
||||
if (
|
||||
typeof this.props.onNavigationStateChange === 'undefined' &&
|
||||
@@ -158,14 +154,15 @@ export default function createNavigationContainer<T: *>(
|
||||
}
|
||||
|
||||
this.subs = BackAndroid.addEventListener('backPress', () =>
|
||||
this.dispatch(NavigationActions.back()));
|
||||
this.dispatch(NavigationActions.back())
|
||||
);
|
||||
|
||||
Linking.addEventListener('url', ({ url }: { url: string }) => {
|
||||
this._handleOpenURL(url);
|
||||
});
|
||||
|
||||
Linking.getInitialURL().then(
|
||||
(url: string) => url && this._handleOpenURL(url),
|
||||
(url: string) => url && this._handleOpenURL(url)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,7 +179,8 @@ export default function createNavigationContainer<T: *>(
|
||||
const nav = Component.router.getStateForAction(action, state.nav);
|
||||
if (nav && nav !== state.nav) {
|
||||
this.setState({ nav }, () =>
|
||||
this._onNavigationStateChange(state.nav, nav, action));
|
||||
this._onNavigationStateChange(state.nav, nav, action)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -18,10 +18,10 @@ import type {
|
||||
NavigationTabRouterConfig,
|
||||
} from '../TypeDefinition';
|
||||
|
||||
export type DrawerNavigatorConfig =
|
||||
& { containerConfig?: void }
|
||||
& NavigationTabRouterConfig
|
||||
& DrawerViewConfig;
|
||||
export type DrawerNavigatorConfig = {
|
||||
containerConfig?: void,
|
||||
} & NavigationTabRouterConfig &
|
||||
DrawerViewConfig;
|
||||
|
||||
const DefaultDrawerConfig = {
|
||||
/*
|
||||
@@ -36,7 +36,7 @@ const DefaultDrawerConfig = {
|
||||
|
||||
const DrawerNavigator = (
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
config: DrawerNavigatorConfig,
|
||||
config: DrawerNavigatorConfig
|
||||
) => {
|
||||
const mergedConfig = { ...DefaultDrawerConfig, ...config };
|
||||
const {
|
||||
@@ -57,7 +57,7 @@ const DrawerNavigator = (
|
||||
contentRouter,
|
||||
routeConfigs,
|
||||
config,
|
||||
NavigatorTypes.DRAWER,
|
||||
NavigatorTypes.DRAWER
|
||||
)((props: *) => <DrawerScreen {...props} />),
|
||||
},
|
||||
DrawerOpen: {
|
||||
@@ -66,14 +66,14 @@ const DrawerNavigator = (
|
||||
},
|
||||
{
|
||||
initialRouteName: 'DrawerClose',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const navigator = createNavigator(
|
||||
drawerRouter,
|
||||
routeConfigs,
|
||||
config,
|
||||
NavigatorTypes.DRAWER,
|
||||
NavigatorTypes.DRAWER
|
||||
)((props: *) => (
|
||||
<DrawerView
|
||||
{...props}
|
||||
|
||||
@@ -13,14 +13,14 @@ import type {
|
||||
NavigationRouteConfigMap,
|
||||
} from '../TypeDefinition';
|
||||
|
||||
export type StackNavigatorConfig =
|
||||
& { containerOptions?: void }
|
||||
& NavigationStackViewConfig
|
||||
& NavigationStackRouterConfig;
|
||||
export type StackNavigatorConfig = {
|
||||
containerOptions?: void,
|
||||
} & NavigationStackViewConfig &
|
||||
NavigationStackRouterConfig;
|
||||
|
||||
export default (
|
||||
routeConfigMap: NavigationRouteConfigMap,
|
||||
stackConfig: StackNavigatorConfig = {},
|
||||
stackConfig: StackNavigatorConfig = {}
|
||||
) => {
|
||||
const {
|
||||
initialRouteName,
|
||||
@@ -47,7 +47,7 @@ export default (
|
||||
router,
|
||||
routeConfigMap,
|
||||
stackConfig,
|
||||
NavigatorTypes.STACK,
|
||||
NavigatorTypes.STACK
|
||||
)((props: *) => (
|
||||
<CardStackTransitioner
|
||||
{...props}
|
||||
|
||||
@@ -19,14 +19,14 @@ import type {
|
||||
NavigationTabRouterConfig,
|
||||
} from '../TypeDefinition';
|
||||
|
||||
export type TabNavigatorConfig =
|
||||
& { containerOptions?: void }
|
||||
& NavigationTabRouterConfig
|
||||
& TabViewConfig;
|
||||
export type TabNavigatorConfig = {
|
||||
containerOptions?: void,
|
||||
} & NavigationTabRouterConfig &
|
||||
TabViewConfig;
|
||||
|
||||
const TabNavigator = (
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
config: TabNavigatorConfig = {},
|
||||
config: TabNavigatorConfig = {}
|
||||
) => {
|
||||
// Use the look native to the platform by default
|
||||
const mergedConfig = { ...TabNavigator.Presets.Default, ...config };
|
||||
@@ -46,7 +46,7 @@ const TabNavigator = (
|
||||
router,
|
||||
routeConfigs,
|
||||
config,
|
||||
NavigatorTypes.STACK,
|
||||
NavigatorTypes.STACK
|
||||
)((props: *) => (
|
||||
<TabView
|
||||
{...props}
|
||||
|
||||
@@ -18,24 +18,23 @@ const createNavigator = (
|
||||
router: NavigationRouter<*, *, *>,
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
navigatorConfig: any,
|
||||
navigatorType: NavigatorType,
|
||||
) =>
|
||||
(View: NavigationNavigator<*, *, *, *>) => {
|
||||
class Navigator extends React.Component {
|
||||
props: NavigationNavigatorProps<*>;
|
||||
navigatorType: NavigatorType
|
||||
) => (View: NavigationNavigator<*, *, *, *>) => {
|
||||
class Navigator extends React.Component {
|
||||
props: NavigationNavigatorProps<*>;
|
||||
|
||||
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 <View {...this.props} router={router} />;
|
||||
}
|
||||
render() {
|
||||
return <View {...this.props} router={router} />;
|
||||
}
|
||||
}
|
||||
|
||||
return Navigator;
|
||||
};
|
||||
return Navigator;
|
||||
};
|
||||
|
||||
export default createNavigator;
|
||||
|
||||
@@ -30,7 +30,7 @@ function _getUuid() {
|
||||
|
||||
export default (
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
stackConfig: NavigationStackRouterConfig = {},
|
||||
stackConfig: NavigationStackRouterConfig = {}
|
||||
): NavigationRouter<*, *, *> => {
|
||||
// Fail fast on invalid route definitions
|
||||
validateRouteConfigMap(routeConfigs);
|
||||
@@ -49,9 +49,7 @@ export default (
|
||||
}
|
||||
});
|
||||
|
||||
const {
|
||||
initialRouteParams,
|
||||
} = stackConfig;
|
||||
const { initialRouteParams } = stackConfig;
|
||||
|
||||
const initialRouteName = stackConfig.initialRouteName || routeNames[0];
|
||||
|
||||
@@ -90,7 +88,7 @@ export default (
|
||||
|
||||
getStateForAction(
|
||||
passedAction: NavigationStackAction,
|
||||
state: ?NavigationState,
|
||||
state: ?NavigationState
|
||||
) {
|
||||
const action = NavigationActions.mapDeprecatedActionAndWarn(passedAction);
|
||||
|
||||
@@ -117,7 +115,7 @@ export default (
|
||||
NavigationActions.navigate({
|
||||
routeName: initialRouteName,
|
||||
params: initialRouteParams,
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
const params = (route.params ||
|
||||
@@ -167,8 +165,8 @@ export default (
|
||||
const childRouter = childRouters[action.routeName];
|
||||
let route;
|
||||
if (childRouter) {
|
||||
const childAction = action.action ||
|
||||
NavigationActions.init({ params: action.params });
|
||||
const childAction =
|
||||
action.action || NavigationActions.init({ params: action.params });
|
||||
route = {
|
||||
params: action.params,
|
||||
...childRouter.getStateForAction(childAction),
|
||||
@@ -194,12 +192,12 @@ export default (
|
||||
if (childRouter) {
|
||||
// For each child router, start with a blank state
|
||||
const initChildRoute = childRouter.getStateForAction(
|
||||
NavigationActions.init(),
|
||||
NavigationActions.init()
|
||||
);
|
||||
// Then check to see if the router handles our navigate action
|
||||
const navigatedChildRoute = childRouter.getStateForAction(
|
||||
action,
|
||||
initChildRoute,
|
||||
initChildRoute
|
||||
);
|
||||
let routeToPush = null;
|
||||
if (navigatedChildRoute === null) {
|
||||
@@ -223,7 +221,7 @@ export default (
|
||||
if (action.type === NavigationActions.SET_PARAMS) {
|
||||
const lastRoute = state.routes.find(
|
||||
/* $FlowFixMe */
|
||||
(route: *) => route.key === action.key,
|
||||
(route: *) => route.key === action.key
|
||||
);
|
||||
if (lastRoute) {
|
||||
const params = {
|
||||
@@ -264,7 +262,7 @@ export default (
|
||||
};
|
||||
delete route.type;
|
||||
return route;
|
||||
},
|
||||
}
|
||||
),
|
||||
index: action.index,
|
||||
};
|
||||
@@ -275,7 +273,7 @@ export default (
|
||||
if (action.key) {
|
||||
const backRoute = state.routes.find(
|
||||
/* $FlowFixMe */
|
||||
(route: *) => route.key === action.key,
|
||||
(route: *) => route.key === action.key
|
||||
);
|
||||
/* $FlowFixMe */
|
||||
backRouteIndex = state.routes.indexOf(backRoute);
|
||||
@@ -295,7 +293,7 @@ export default (
|
||||
},
|
||||
|
||||
getPathAndParamsForState(
|
||||
state: NavigationState,
|
||||
state: NavigationState
|
||||
): { path: string, params?: NavigationParams } {
|
||||
const route = state.routes[state.index];
|
||||
const routeName = route.routeName;
|
||||
@@ -359,14 +357,15 @@ export default (
|
||||
if (childRouters[matchedRouteName]) {
|
||||
nestedAction = childRouters[matchedRouteName].getActionForPathAndParams(
|
||||
/* $FlowFixMe */
|
||||
pathMatch.slice(pathMatchKeys.length).join('/'),
|
||||
pathMatch.slice(pathMatchKeys.length).join('/')
|
||||
);
|
||||
}
|
||||
|
||||
// reduce the items of the query string. any query params may
|
||||
// be overridden by path params
|
||||
const queryParams = (queryString || '').split('&').reduce(
|
||||
(result: *, item: string) => {
|
||||
const queryParams = (queryString || '')
|
||||
.split('&')
|
||||
.reduce((result: *, item: string) => {
|
||||
if (item !== '') {
|
||||
const nextResult = result || {};
|
||||
const [key, value] = item.split('=');
|
||||
@@ -374,15 +373,14 @@ export default (
|
||||
return nextResult;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
null,
|
||||
);
|
||||
}, null);
|
||||
|
||||
// reduce the matched pieces of the path into the params
|
||||
// of the route. `params` is null if there are no params.
|
||||
/* $FlowFixMe */
|
||||
const params = pathMatch.slice(1).reduce(
|
||||
(result: *, matchResult: *, i: number) => {
|
||||
const params = pathMatch
|
||||
.slice(1)
|
||||
.reduce((result: *, matchResult: *, i: number) => {
|
||||
const key = pathMatchKeys[i];
|
||||
if (key.asterisk || !key) {
|
||||
return result;
|
||||
@@ -391,9 +389,7 @@ export default (
|
||||
const paramName = key.name;
|
||||
nextResult[paramName] = matchResult;
|
||||
return nextResult;
|
||||
},
|
||||
queryParams,
|
||||
);
|
||||
}, queryParams);
|
||||
|
||||
return NavigationActions.navigate({
|
||||
routeName: matchedRouteName,
|
||||
@@ -404,7 +400,7 @@ export default (
|
||||
|
||||
getScreenOptions: createConfigGetter(
|
||||
routeConfigs,
|
||||
stackConfig.navigationOptions,
|
||||
stackConfig.navigationOptions
|
||||
),
|
||||
|
||||
getScreenConfig: getScreenConfigDeprecated,
|
||||
|
||||
@@ -24,7 +24,7 @@ import type {
|
||||
|
||||
export default (
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
config: NavigationTabRouterConfig = {},
|
||||
config: NavigationTabRouterConfig = {}
|
||||
): NavigationRouter<*, *, *> => {
|
||||
// Fail fast on invalid route definitions
|
||||
validateRouteConfigMap(routeConfigs);
|
||||
@@ -49,12 +49,12 @@ export default (
|
||||
invariant(
|
||||
initialRouteIndex !== -1,
|
||||
`Invalid initialRouteName '${initialRouteName}' for TabRouter. ` +
|
||||
`Should be one of ${order.map((n: *) => `"${n}"`).join(', ')}`,
|
||||
`Should be one of ${order.map((n: *) => `"${n}"`).join(', ')}`
|
||||
);
|
||||
return {
|
||||
getStateForAction(
|
||||
action: NavigationAction | { action: NavigationAction },
|
||||
inputState?: ?NavigationState,
|
||||
inputState?: ?NavigationState
|
||||
): ?NavigationState {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
action = NavigationActions.mapDeprecatedActionAndWarn(action);
|
||||
@@ -65,7 +65,8 @@ export default (
|
||||
const routes = order.map((routeName: string) => {
|
||||
const tabRouter = tabRouters[routeName];
|
||||
if (tabRouter) {
|
||||
const childAction = action.action ||
|
||||
const childAction =
|
||||
action.action ||
|
||||
NavigationActions.init({
|
||||
...(action.params ? { params: action.params } : {}),
|
||||
});
|
||||
@@ -99,7 +100,7 @@ export default (
|
||||
...route.params,
|
||||
...params,
|
||||
},
|
||||
}: NavigationRoute),
|
||||
}: NavigationRoute)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -110,7 +111,7 @@ export default (
|
||||
if (activeTabRouter) {
|
||||
const activeTabState = activeTabRouter.getStateForAction(
|
||||
action.action || action,
|
||||
activeTabLastState,
|
||||
activeTabLastState
|
||||
);
|
||||
if (!activeTabState && inputState) {
|
||||
return null;
|
||||
@@ -128,8 +129,8 @@ export default (
|
||||
// Handle tab changing. Do this after letting the current tab try to
|
||||
// handle the action, to allow inner tabs to change first
|
||||
let activeTabIndex = state.index;
|
||||
const isBackEligible = action.key == null ||
|
||||
action.key === activeTabLastState.key;
|
||||
const isBackEligible =
|
||||
action.key == null || action.key === activeTabLastState.key;
|
||||
if (
|
||||
action.type === NavigationActions.BACK &&
|
||||
isBackEligible &&
|
||||
@@ -181,7 +182,7 @@ export default (
|
||||
if (action.type === NavigationActions.SET_PARAMS) {
|
||||
const lastRoute = state.routes.find(
|
||||
/* $FlowFixMe */
|
||||
(route: *) => route.key === action.key,
|
||||
(route: *) => route.key === action.key
|
||||
);
|
||||
if (lastRoute) {
|
||||
const params = {
|
||||
@@ -249,13 +250,13 @@ export default (
|
||||
},
|
||||
|
||||
getComponentForState(
|
||||
state: NavigationState,
|
||||
state: NavigationState
|
||||
): NavigationScreenComponent<*, NavigationTabScreenOptions> {
|
||||
const routeName = order[state.index];
|
||||
invariant(
|
||||
routeName,
|
||||
`There is no route defined for index ${state.index}. Check that
|
||||
that you passed in a navigation state with a valid tab/screen index.`,
|
||||
that you passed in a navigation state with a valid tab/screen index.`
|
||||
);
|
||||
const childRouter = tabRouters[routeName];
|
||||
if (childRouter) {
|
||||
@@ -294,43 +295,46 @@ export default (
|
||||
* This will return null if there is no action matched
|
||||
*/
|
||||
getActionForPathAndParams(path: string, params: ?NavigationParams) {
|
||||
return order
|
||||
.map((tabId: string) => {
|
||||
const parts = path.split('/');
|
||||
const pathToTest = paths[tabId];
|
||||
if (parts[0] === pathToTest) {
|
||||
const tabRouter = tabRouters[tabId];
|
||||
const action: NavigationNavigateAction = NavigationActions.navigate(
|
||||
{
|
||||
routeName: tabId,
|
||||
},
|
||||
);
|
||||
if (tabRouter && tabRouter.getActionForPathAndParams) {
|
||||
action.action = tabRouter.getActionForPathAndParams(
|
||||
parts.slice(1).join('/'),
|
||||
params,
|
||||
return (
|
||||
order
|
||||
.map((tabId: string) => {
|
||||
const parts = path.split('/');
|
||||
const pathToTest = paths[tabId];
|
||||
if (parts[0] === pathToTest) {
|
||||
const tabRouter = tabRouters[tabId];
|
||||
const action: NavigationNavigateAction = NavigationActions.navigate(
|
||||
{
|
||||
routeName: tabId,
|
||||
}
|
||||
);
|
||||
} else if (params) {
|
||||
action.params = params;
|
||||
if (tabRouter && tabRouter.getActionForPathAndParams) {
|
||||
action.action = tabRouter.getActionForPathAndParams(
|
||||
parts.slice(1).join('/'),
|
||||
params
|
||||
);
|
||||
} else if (params) {
|
||||
action.params = params;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.find((action: *) => !!action) ||
|
||||
return null;
|
||||
})
|
||||
.find((action: *) => !!action) ||
|
||||
order
|
||||
.map((tabId: string) => {
|
||||
const tabRouter = tabRouters[tabId];
|
||||
return tabRouter &&
|
||||
tabRouter.getActionForPathAndParams(path, params);
|
||||
return (
|
||||
tabRouter && tabRouter.getActionForPathAndParams(path, params)
|
||||
);
|
||||
})
|
||||
.find((action: *) => !!action) ||
|
||||
null;
|
||||
null
|
||||
);
|
||||
},
|
||||
|
||||
getScreenOptions: createConfigGetter(
|
||||
routeConfigs,
|
||||
config.navigationOptions,
|
||||
config.navigationOptions
|
||||
),
|
||||
|
||||
getScreenConfig: getScreenConfigDeprecated,
|
||||
|
||||
@@ -51,20 +51,20 @@ Object.keys(ROUTERS).forEach((routerName: string) => {
|
||||
expect(
|
||||
router.getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[0], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual(undefined);
|
||||
expect(
|
||||
router.getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[1], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual('BarTitle');
|
||||
expect(
|
||||
router.getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[2], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual('Baz-123');
|
||||
});
|
||||
});
|
||||
@@ -99,7 +99,7 @@ test('Handles no-op actions with tabs within stack router', () => {
|
||||
expect(state1).toEqual(state2);
|
||||
const state3 = TestRouter.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Zap' },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state2).toEqual(state3);
|
||||
});
|
||||
@@ -132,7 +132,7 @@ test('Handles deep action', () => {
|
||||
routeName: 'Foo',
|
||||
action: { type: NavigationActions.NAVIGATE, routeName: 'Zoo' },
|
||||
},
|
||||
state1,
|
||||
state1
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(1);
|
||||
/* $FlowFixMe */
|
||||
@@ -168,7 +168,7 @@ test('Supports lazily-evaluated getScreen', () => {
|
||||
expect(state1).toEqual(state2);
|
||||
const state3 = TestRouter.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Zap' },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state2).toEqual(state3);
|
||||
});
|
||||
|
||||
@@ -89,7 +89,7 @@ describe('StackRouter', () => {
|
||||
{ key: 'b', routeName: 'bar' },
|
||||
{ key: 'c', routeName: 'foo' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
).toBe(FooScreen);
|
||||
expect(
|
||||
router.getComponentForState({
|
||||
@@ -98,7 +98,7 @@ describe('StackRouter', () => {
|
||||
{ key: 'a', routeName: 'foo' },
|
||||
{ key: 'b', routeName: 'bar' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
).toBe(BarScreen);
|
||||
});
|
||||
|
||||
@@ -122,7 +122,7 @@ describe('StackRouter', () => {
|
||||
{ key: 'b', routeName: 'bar' },
|
||||
{ key: 'c', routeName: 'foo' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
).toBe(FooScreen);
|
||||
expect(
|
||||
router.getComponentForState({
|
||||
@@ -131,7 +131,7 @@ describe('StackRouter', () => {
|
||||
{ key: 'a', routeName: 'foo' },
|
||||
{ key: 'b', routeName: 'bar' },
|
||||
],
|
||||
}),
|
||||
})
|
||||
).toBe(BarScreen);
|
||||
});
|
||||
|
||||
@@ -212,7 +212,7 @@ describe('StackRouter', () => {
|
||||
|
||||
test('Parses paths with a query', () => {
|
||||
expect(
|
||||
TestStackRouter.getActionForPathAndParams('people/foo?code=test&foo=bar'),
|
||||
TestStackRouter.getActionForPathAndParams('people/foo?code=test&foo=bar')
|
||||
).toEqual({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'person',
|
||||
@@ -226,7 +226,7 @@ describe('StackRouter', () => {
|
||||
|
||||
test('Parses paths with an empty query value', () => {
|
||||
expect(
|
||||
TestStackRouter.getActionForPathAndParams('people/foo?code=&foo=bar'),
|
||||
TestStackRouter.getActionForPathAndParams('people/foo?code=&foo=bar')
|
||||
).toEqual({
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'person',
|
||||
@@ -329,7 +329,7 @@ describe('StackRouter', () => {
|
||||
});
|
||||
const pushedState = TestRouter.getStateForAction(
|
||||
NavigationActions.navigate({ routeName: 'qux' }),
|
||||
initState,
|
||||
initState
|
||||
);
|
||||
// $FlowFixMe
|
||||
expect(pushedState.index).toEqual(1);
|
||||
@@ -366,7 +366,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { name: 'Zoom' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(1);
|
||||
expect(state2 && state2.routes[1].routeName).toEqual('Bar');
|
||||
@@ -374,7 +374,7 @@ describe('StackRouter', () => {
|
||||
expect(state2 && state2.routes.length).toEqual(2);
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.BACK },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state3).toEqual({
|
||||
index: 0,
|
||||
@@ -419,7 +419,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { name: 'Zoom' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(1);
|
||||
expect(state2 && state2.routes[1].routeName).toEqual('Bar');
|
||||
@@ -427,7 +427,7 @@ describe('StackRouter', () => {
|
||||
expect(state2 && state2.routes.length).toEqual(2);
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.BACK },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state3).toEqual({
|
||||
index: 0,
|
||||
@@ -458,7 +458,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { name: 'Zoom' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
const state3 = router.getStateForAction(
|
||||
{
|
||||
@@ -466,16 +466,16 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { name: 'Foo' },
|
||||
},
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
const state4 = router.getStateForAction(
|
||||
{ type: NavigationActions.BACK, key: 'wrongKey' },
|
||||
state3,
|
||||
state3
|
||||
);
|
||||
expect(state3).toEqual(state4);
|
||||
const state5 = router.getStateForAction(
|
||||
{ type: NavigationActions.BACK, key: state3 && state3.routes[1].key },
|
||||
state4,
|
||||
state4
|
||||
);
|
||||
expect(state5).toEqual(state);
|
||||
});
|
||||
@@ -492,7 +492,7 @@ describe('StackRouter', () => {
|
||||
screen: BarScreen,
|
||||
},
|
||||
},
|
||||
{ initialRouteName: 'Bar' },
|
||||
{ initialRouteName: 'Bar' }
|
||||
);
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
expect(state).toEqual({
|
||||
@@ -514,7 +514,7 @@ describe('StackRouter', () => {
|
||||
screen: FooScreen,
|
||||
},
|
||||
},
|
||||
{ initialRouteName: 'Bar', initialRouteParams: { foo: 'bar' } },
|
||||
{ initialRouteName: 'Bar', initialRouteParams: { foo: 'bar' } }
|
||||
);
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
expect(state).toEqual({
|
||||
@@ -547,7 +547,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { bar: '42' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2).not.toBeNull();
|
||||
expect(state2 && state2.index).toEqual(1);
|
||||
@@ -567,7 +567,7 @@ describe('StackRouter', () => {
|
||||
{
|
||||
initialRouteName: 'Bar',
|
||||
initialRouteParams: { name: 'Zoo' },
|
||||
},
|
||||
}
|
||||
);
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
@@ -576,7 +576,7 @@ describe('StackRouter', () => {
|
||||
params: { name: 'Qux' },
|
||||
key: 'Init-id-0-16',
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(0);
|
||||
expect(state2 && state2.routes[0].params).toEqual({ name: 'Qux' });
|
||||
@@ -604,7 +604,7 @@ describe('StackRouter', () => {
|
||||
params: { name: 'foobar' },
|
||||
key: 'Init-id-0-17',
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(0);
|
||||
/* $FlowFixMe */
|
||||
@@ -640,7 +640,7 @@ describe('StackRouter', () => {
|
||||
],
|
||||
index: 1,
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(1);
|
||||
expect(state2 && state2.routes[0].params).toEqual({ bar: '42' });
|
||||
@@ -673,7 +673,7 @@ describe('StackRouter', () => {
|
||||
actions: [{ type: NavigationActions.NAVIGATE, routeName: 'Foo' }],
|
||||
index: 0,
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
|
||||
expect(state2 && state2.index).toEqual(0);
|
||||
@@ -707,7 +707,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Foo',
|
||||
action: { type: NavigationActions.NAVIGATE, routeName: 'baz' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
const state3 = router.getStateForAction(
|
||||
{
|
||||
@@ -716,7 +716,7 @@ describe('StackRouter', () => {
|
||||
actions: [{ type: NavigationActions.NAVIGATE, routeName: 'Foo' }],
|
||||
index: 0,
|
||||
},
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
const state4 = router.getStateForAction(
|
||||
{
|
||||
@@ -725,7 +725,7 @@ describe('StackRouter', () => {
|
||||
actions: [{ type: NavigationActions.NAVIGATE, routeName: 'Bar' }],
|
||||
index: 0,
|
||||
},
|
||||
state3,
|
||||
state3
|
||||
);
|
||||
|
||||
expect(state4 && state4.index).toEqual(0);
|
||||
@@ -747,7 +747,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { foo: '42' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.routes[1].params).toEqual({ foo: '42' });
|
||||
/* $FlowFixMe */
|
||||
@@ -778,7 +778,7 @@ describe('StackRouter', () => {
|
||||
routeName: 'Bar',
|
||||
params: { foo: '42' },
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.routes[1].params).toEqual({ foo: '42' });
|
||||
/* $FlowFixMe */
|
||||
@@ -806,7 +806,7 @@ describe('StackRouter', () => {
|
||||
screen: () => <div />,
|
||||
},
|
||||
},
|
||||
{ initialRouteName: 'Bar' },
|
||||
{ initialRouteName: 'Bar' }
|
||||
);
|
||||
const action = router.getActionForPathAndParams('');
|
||||
expect(action).toEqual({
|
||||
@@ -889,7 +889,7 @@ describe('StackRouter', () => {
|
||||
],
|
||||
index: 1,
|
||||
},
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2 && state2.index).toEqual(1);
|
||||
expect(state2 && state2.routes[0].params).toEqual({ bar: '42' });
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('TabRouter', () => {
|
||||
expect(state).toEqual(expectedState);
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
const expectedState2 = {
|
||||
index: 1,
|
||||
@@ -44,7 +44,7 @@ describe('TabRouter', () => {
|
||||
expect(router.getComponentForState(expectedState2)).toEqual(ScreenB);
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state3).toEqual(null);
|
||||
});
|
||||
@@ -67,7 +67,7 @@ describe('TabRouter', () => {
|
||||
expect(state).toEqual(expectedState);
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
const expectedState2 = {
|
||||
index: 1,
|
||||
@@ -81,7 +81,7 @@ describe('TabRouter', () => {
|
||||
expect(router.getComponentForState(expectedState2)).toEqual(ScreenB);
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state3).toEqual(null);
|
||||
});
|
||||
@@ -89,7 +89,7 @@ describe('TabRouter', () => {
|
||||
test('Can set the initial tab', () => {
|
||||
const router = TabRouter(
|
||||
{ Foo: BareLeafRouteConfig, Bar: BareLeafRouteConfig },
|
||||
{ initialRouteName: 'Bar' },
|
||||
{ initialRouteName: 'Bar' }
|
||||
);
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
expect(state).toEqual({
|
||||
@@ -121,12 +121,12 @@ describe('TabRouter', () => {
|
||||
test('getStateForAction returns null when navigating to same tab', () => {
|
||||
const router = TabRouter(
|
||||
{ Foo: BareLeafRouteConfig, Bar: BareLeafRouteConfig },
|
||||
{ initialRouteName: 'Bar' },
|
||||
{ initialRouteName: 'Bar' }
|
||||
);
|
||||
const state = router.getStateForAction({ type: NavigationActions.INIT });
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2).toEqual(null);
|
||||
});
|
||||
@@ -233,11 +233,11 @@ describe('TabRouter', () => {
|
||||
// Ensure that navigating back and forth doesn't overwrite
|
||||
state = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
state = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Boo' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state && state.routes[1]).toEqual({
|
||||
index: 0,
|
||||
@@ -283,7 +283,7 @@ describe('TabRouter', () => {
|
||||
});
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Foo' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2).toEqual({
|
||||
index: 1,
|
||||
@@ -303,7 +303,7 @@ describe('TabRouter', () => {
|
||||
});
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Foo' },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state3).toEqual(null);
|
||||
});
|
||||
@@ -362,7 +362,7 @@ describe('TabRouter', () => {
|
||||
});
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Zap' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2).toEqual({
|
||||
index: 0,
|
||||
@@ -397,7 +397,7 @@ describe('TabRouter', () => {
|
||||
});
|
||||
const state3 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'Zap' },
|
||||
state2,
|
||||
state2
|
||||
);
|
||||
expect(state3).toEqual(null);
|
||||
const state4 = router.getStateForAction({
|
||||
@@ -550,14 +550,14 @@ describe('TabRouter', () => {
|
||||
test('Maps old actions (uses "getStateForAction returns null when navigating to same tab" test)', () => {
|
||||
const router = TabRouter(
|
||||
{ Foo: BareLeafRouteConfig, Bar: BareLeafRouteConfig },
|
||||
{ initialRouteName: 'Bar' },
|
||||
{ initialRouteName: 'Bar' }
|
||||
);
|
||||
/* $FlowFixMe: these are for deprecated action names */
|
||||
const state = router.getStateForAction({ type: 'Init' });
|
||||
/* $FlowFixMe: these are for deprecated action names */
|
||||
const state2 = router.getStateForAction(
|
||||
{ type: 'Navigate', routeName: 'Bar' },
|
||||
state,
|
||||
state
|
||||
);
|
||||
expect(state2).toEqual(null);
|
||||
});
|
||||
@@ -582,7 +582,7 @@ describe('TabRouter', () => {
|
||||
|
||||
const state1 = router.getStateForAction(
|
||||
{ type: NavigationActions.NAVIGATE, routeName: 'b', params },
|
||||
state0,
|
||||
state0
|
||||
);
|
||||
|
||||
expect(state1).toEqual({
|
||||
|
||||
@@ -46,18 +46,19 @@ test('should get config for screen', () => {
|
||||
}
|
||||
}
|
||||
|
||||
const getScreenOptions: NavigationScreenOptionsGetter<NavigationStackScreenOptions, *> = createConfigGetter(
|
||||
{
|
||||
Home: { screen: HomeScreen },
|
||||
Settings: { screen: SettingsScreen },
|
||||
Notifications: {
|
||||
screen: NotificationScreen,
|
||||
navigationOptions: {
|
||||
title: '10 new notifications',
|
||||
},
|
||||
const getScreenOptions: NavigationScreenOptionsGetter<
|
||||
NavigationStackScreenOptions,
|
||||
*
|
||||
> = createConfigGetter({
|
||||
Home: { screen: HomeScreen },
|
||||
Settings: { screen: SettingsScreen },
|
||||
Notifications: {
|
||||
screen: NotificationScreen,
|
||||
navigationOptions: {
|
||||
title: '10 new notifications',
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const routes = [
|
||||
{ key: 'A', routeName: 'Home' },
|
||||
@@ -70,50 +71,50 @@ test('should get config for screen', () => {
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[0], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual('Welcome anonymous');
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[1], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual('Welcome jane');
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[0], dispatch: () => false }),
|
||||
{},
|
||||
).gesturesEnabled,
|
||||
{}
|
||||
).gesturesEnabled
|
||||
).toEqual(true);
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[2], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual('Settings!!!');
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[2], dispatch: () => false }),
|
||||
{},
|
||||
).gesturesEnabled,
|
||||
{}
|
||||
).gesturesEnabled
|
||||
).toEqual(false);
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[3], dispatch: () => false }),
|
||||
{},
|
||||
).title,
|
||||
{}
|
||||
).title
|
||||
).toEqual('10 new notifications');
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[3], dispatch: () => false }),
|
||||
{},
|
||||
).gesturesEnabled,
|
||||
{}
|
||||
).gesturesEnabled
|
||||
).toEqual(true);
|
||||
expect(
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[4], dispatch: () => false }),
|
||||
{},
|
||||
).gesturesEnabled,
|
||||
{}
|
||||
).gesturesEnabled
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
@@ -135,9 +136,10 @@ test('should throw if the route does not exist', () => {
|
||||
expect(() =>
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[0], dispatch: () => false }),
|
||||
{},
|
||||
)).toThrowError(
|
||||
"There is no route defined for key Settings.\nMust be one of: 'Home'",
|
||||
{}
|
||||
)
|
||||
).toThrowError(
|
||||
"There is no route defined for key Settings.\nMust be one of: 'Home'"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -152,6 +154,7 @@ test('should throw if the screen is not defined under the route config', () => {
|
||||
|
||||
expect(() =>
|
||||
getScreenOptions(
|
||||
addNavigationHelpers({ state: routes[0], dispatch: () => false }),
|
||||
)).toThrowError('Route Home must define a screen or a getScreen.');
|
||||
addNavigationHelpers({ state: routes[0], dispatch: () => false })
|
||||
)
|
||||
).toThrowError('Route Home must define a screen or a getScreen.');
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ import type {
|
||||
function applyConfig(
|
||||
configurer: ?NavigationScreenConfig<*>,
|
||||
navigationOptions: *,
|
||||
configProps: NavigationScreenConfigProps,
|
||||
configProps: NavigationScreenConfigProps
|
||||
): * {
|
||||
if (typeof configurer === 'function') {
|
||||
return {
|
||||
@@ -43,62 +43,61 @@ function applyConfig(
|
||||
|
||||
export default (
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
navigatorScreenConfig?: NavigationScreenConfig<*>,
|
||||
) =>
|
||||
(
|
||||
navigation: NavigationScreenProp<NavigationRoute, NavigationAction>,
|
||||
screenProps: *,
|
||||
) => {
|
||||
const { state, dispatch } = navigation;
|
||||
const route = state;
|
||||
// $FlowFixMe
|
||||
const { routes, index } = (route: NavigationStateRoute);
|
||||
navigatorScreenConfig?: NavigationScreenConfig<*>
|
||||
) => (
|
||||
navigation: NavigationScreenProp<NavigationRoute, NavigationAction>,
|
||||
screenProps: *
|
||||
) => {
|
||||
const { state, dispatch } = navigation;
|
||||
const route = state;
|
||||
// $FlowFixMe
|
||||
const { routes, index } = (route: NavigationStateRoute);
|
||||
|
||||
invariant(
|
||||
route.routeName && typeof route.routeName === 'string',
|
||||
'Cannot get config because the route does not have a routeName.'
|
||||
);
|
||||
|
||||
const Component = getScreenForRouteName(routeConfigs, route.routeName);
|
||||
|
||||
let outputConfig = {};
|
||||
|
||||
if (Component.router) {
|
||||
invariant(
|
||||
route.routeName && typeof route.routeName === 'string',
|
||||
'Cannot get config because the route does not have a routeName.',
|
||||
route && routes && index != null,
|
||||
`Expect nav state to have routes and index, ${JSON.stringify(route)}`
|
||||
);
|
||||
|
||||
const Component = getScreenForRouteName(routeConfigs, route.routeName);
|
||||
|
||||
let outputConfig = {};
|
||||
|
||||
if (Component.router) {
|
||||
invariant(
|
||||
route && routes && index != null,
|
||||
`Expect nav state to have routes and index, ${JSON.stringify(route)}`,
|
||||
);
|
||||
const childRoute = routes[index];
|
||||
const childNavigation = addNavigationHelpers({
|
||||
state: childRoute,
|
||||
dispatch,
|
||||
});
|
||||
outputConfig = Component.router.getScreenOptions(
|
||||
childNavigation,
|
||||
screenProps,
|
||||
);
|
||||
}
|
||||
|
||||
const routeConfig = routeConfigs[route.routeName];
|
||||
|
||||
const routeScreenConfig = routeConfig.navigationOptions;
|
||||
const componentScreenConfig = Component.navigationOptions;
|
||||
|
||||
const configOptions = { navigation, screenProps: screenProps || {} };
|
||||
|
||||
outputConfig = applyConfig(
|
||||
navigatorScreenConfig,
|
||||
outputConfig,
|
||||
configOptions,
|
||||
const childRoute = routes[index];
|
||||
const childNavigation = addNavigationHelpers({
|
||||
state: childRoute,
|
||||
dispatch,
|
||||
});
|
||||
outputConfig = Component.router.getScreenOptions(
|
||||
childNavigation,
|
||||
screenProps
|
||||
);
|
||||
outputConfig = applyConfig(
|
||||
componentScreenConfig,
|
||||
outputConfig,
|
||||
configOptions,
|
||||
);
|
||||
outputConfig = applyConfig(routeScreenConfig, outputConfig, configOptions);
|
||||
}
|
||||
|
||||
validateScreenOptions(outputConfig, route);
|
||||
const routeConfig = routeConfigs[route.routeName];
|
||||
|
||||
return outputConfig;
|
||||
};
|
||||
const routeScreenConfig = routeConfig.navigationOptions;
|
||||
const componentScreenConfig = Component.navigationOptions;
|
||||
|
||||
const configOptions = { navigation, screenProps: screenProps || {} };
|
||||
|
||||
outputConfig = applyConfig(
|
||||
navigatorScreenConfig,
|
||||
outputConfig,
|
||||
configOptions
|
||||
);
|
||||
outputConfig = applyConfig(
|
||||
componentScreenConfig,
|
||||
outputConfig,
|
||||
configOptions
|
||||
);
|
||||
outputConfig = applyConfig(routeScreenConfig, outputConfig, configOptions);
|
||||
|
||||
validateScreenOptions(outputConfig, route);
|
||||
|
||||
return outputConfig;
|
||||
};
|
||||
|
||||
@@ -6,5 +6,5 @@ import invariant from 'fbjs/lib/invariant';
|
||||
export default () =>
|
||||
invariant(
|
||||
false,
|
||||
'`getScreenConfig` has been replaced with `getScreenOptions`',
|
||||
'`getScreenConfig` has been replaced with `getScreenOptions`'
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
*/
|
||||
export default function getScreenForRouteName( // eslint-disable-line consistent-return
|
||||
routeConfigs: NavigationRouteConfigMap,
|
||||
routeName: string,
|
||||
routeName: string
|
||||
): NavigationComponent {
|
||||
const routeConfig = routeConfigs[routeName];
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function getScreenForRouteName( // eslint-disable-line consistent
|
||||
`There is no route defined for key ${routeName}.\n` +
|
||||
`Must be one of: ${Object.keys(routeConfigs)
|
||||
.map((a: string) => `'${a}'`)
|
||||
.join(',')}`,
|
||||
.join(',')}`
|
||||
);
|
||||
|
||||
if (routeConfig.screen) {
|
||||
@@ -36,7 +36,7 @@ export default function getScreenForRouteName( // eslint-disable-line consistent
|
||||
`The getScreen defined for route '${routeName} didn't return a valid ` +
|
||||
'screen or navigator.\n\n' +
|
||||
'Please pass it like this:\n' +
|
||||
`${routeName}: {\n getScreen: () => require('./MyScreen').default\n}`,
|
||||
`${routeName}: {\n getScreen: () => require('./MyScreen').default\n}`
|
||||
);
|
||||
return screen;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ function validateRouteConfigMap(routeConfigs: NavigationRouteConfigMap) {
|
||||
const routeNames = Object.keys(routeConfigs);
|
||||
invariant(
|
||||
routeNames.length > 0,
|
||||
'Please specify at least one route when configuring a navigator.',
|
||||
'Please specify at least one route when configuring a navigator.'
|
||||
);
|
||||
|
||||
routeNames.forEach((routeName: string) => {
|
||||
@@ -26,14 +26,14 @@ function validateRouteConfigMap(routeConfigs: NavigationRouteConfigMap) {
|
||||
'...\n' +
|
||||
`${routeName}: {\n` +
|
||||
' screen: MyScreen,\n' +
|
||||
'}',
|
||||
'}'
|
||||
);
|
||||
|
||||
if (routeConfig.screen && routeConfig.getScreen) {
|
||||
invariant(
|
||||
false,
|
||||
`Route '${routeName}' should declare a screen or ` +
|
||||
'a getScreen, not both.',
|
||||
'a getScreen, not both.'
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ function validateRouteConfigMap(routeConfigs: NavigationRouteConfigMap) {
|
||||
'...\n' +
|
||||
`${routeName}: {\n` +
|
||||
' screen: MyNavigator,\n' +
|
||||
'}',
|
||||
'}'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ export default (screenOptions: *, route: NavigationRoute) => {
|
||||
'({ navigation }) => ({',
|
||||
' title: navigation.state...',
|
||||
'})',
|
||||
].join('\n'),
|
||||
].join('\n')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export default (screenOptions: *, route: NavigationRoute) => {
|
||||
'({ navigation }) => ({',
|
||||
` ${deprecatedKey}Key: navigation.state...`,
|
||||
'})',
|
||||
].join('\n'),
|
||||
].join('\n')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export default (screenOptions: *, route: NavigationRoute) => {
|
||||
'{',
|
||||
` ${deprecatedKey}: {`,
|
||||
...Object.keys(screenOptions[deprecatedKey]).map(
|
||||
(key: string) => ` ${key}: ...,`,
|
||||
(key: string) => ` ${key}: ...,`
|
||||
),
|
||||
' },',
|
||||
'}',
|
||||
@@ -71,10 +71,10 @@ export default (screenOptions: *, route: NavigationRoute) => {
|
||||
'{',
|
||||
...Object.keys(screenOptions[deprecatedKey]).map(
|
||||
(key: string) =>
|
||||
` ${deprecatedKey + key[0].toUpperCase() + key.slice(1)}: ...,`,
|
||||
` ${deprecatedKey + key[0].toUpperCase() + key.slice(1)}: ...,`
|
||||
),
|
||||
'}',
|
||||
].join('\n'),
|
||||
].join('\n')
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
6
packages/react-navigation/src/views/Card.js
vendored
6
packages/react-navigation/src/views/Card.js
vendored
@@ -22,11 +22,7 @@ class Card extends React.Component<any, Props, any> {
|
||||
props: Props;
|
||||
|
||||
render() {
|
||||
const {
|
||||
children,
|
||||
pointerEvents,
|
||||
style,
|
||||
} = this.props;
|
||||
const { children, pointerEvents, style } = this.props;
|
||||
return (
|
||||
<Animated.View
|
||||
pointerEvents={pointerEvents}
|
||||
|
||||
36
packages/react-navigation/src/views/CardStack.js
vendored
36
packages/react-navigation/src/views/CardStack.js
vendored
@@ -43,7 +43,11 @@ type Props = {
|
||||
headerComponent?: ReactClass<*>,
|
||||
mode: 'card' | 'modal',
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationStackScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationStackScreenOptions
|
||||
>,
|
||||
cardStyle?: Style,
|
||||
onTransitionStart?: () => void,
|
||||
onTransitionEnd?: () => void,
|
||||
@@ -158,7 +162,7 @@ class CardStack extends Component {
|
||||
|
||||
_renderHeader(
|
||||
scene: NavigationScene,
|
||||
headerMode: HeaderMode,
|
||||
headerMode: HeaderMode
|
||||
): ?React.Element<*> {
|
||||
const { header } = this._getScreenDetails(scene).options;
|
||||
|
||||
@@ -221,7 +225,7 @@ class CardStack extends Component {
|
||||
const backFromScene = scenes.find((s: *) => s.index === toValue + 1);
|
||||
if (!this._isResponding && backFromScene) {
|
||||
navigation.dispatch(
|
||||
NavigationActions.back({ key: backFromScene.route.key }),
|
||||
NavigationActions.back({ key: backFromScene.route.key })
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -250,7 +254,7 @@ class CardStack extends Component {
|
||||
},
|
||||
onMoveShouldSetPanResponder: (
|
||||
event: { nativeEvent: { pageY: number, pageX: number } },
|
||||
gesture: any,
|
||||
gesture: any
|
||||
) => {
|
||||
if (index !== scene.index) {
|
||||
return false;
|
||||
@@ -259,9 +263,8 @@ class CardStack extends Component {
|
||||
? index
|
||||
: this._immediateIndex;
|
||||
const currentDragDistance = gesture[isVertical ? 'dy' : 'dx'];
|
||||
const currentDragPosition = event.nativeEvent[
|
||||
isVertical ? 'pageY' : 'pageX'
|
||||
];
|
||||
const currentDragPosition =
|
||||
event.nativeEvent[isVertical ? 'pageY' : 'pageX'];
|
||||
const axisLength = isVertical
|
||||
? layout.height.__getValue()
|
||||
: layout.width.__getValue();
|
||||
@@ -279,13 +282,12 @@ class CardStack extends Component {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hasDraggedEnough = Math.abs(currentDragDistance) >
|
||||
RESPOND_THRESHOLD;
|
||||
const hasDraggedEnough =
|
||||
Math.abs(currentDragDistance) > RESPOND_THRESHOLD;
|
||||
|
||||
const isOnFirstCard = immediateIndex === 0;
|
||||
const shouldSetResponder = hasDraggedEnough &&
|
||||
axisHasBeenMeasured &&
|
||||
!isOnFirstCard;
|
||||
const shouldSetResponder =
|
||||
hasDraggedEnough && axisHasBeenMeasured && !isOnFirstCard;
|
||||
return shouldSetResponder;
|
||||
},
|
||||
onPanResponderMove: (event: any, gesture: any) => {
|
||||
@@ -379,7 +381,7 @@ class CardStack extends Component {
|
||||
|
||||
_renderInnerScene(
|
||||
SceneComponent: ReactClass<*>,
|
||||
scene: NavigationScene,
|
||||
scene: NavigationScene
|
||||
): React.Element<any> {
|
||||
const { navigation } = this._getScreenDetails(scene);
|
||||
const { screenProps } = this.props;
|
||||
@@ -415,13 +417,13 @@ class CardStack extends Component {
|
||||
this.props.transitionConfig,
|
||||
{},
|
||||
{},
|
||||
isModal,
|
||||
isModal
|
||||
);
|
||||
const style = screenInterpolator &&
|
||||
screenInterpolator({ ...this.props, scene });
|
||||
const style =
|
||||
screenInterpolator && screenInterpolator({ ...this.props, scene });
|
||||
|
||||
const SceneComponent = this.props.router.getComponentForRouteName(
|
||||
scene.route.routeName,
|
||||
scene.route.routeName
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,10 +23,7 @@ import type { NavigationSceneRendererProps } from '../TypeDefinition';
|
||||
* Render the initial style when the initial layout isn't measured yet.
|
||||
*/
|
||||
function forInitial(props: NavigationSceneRendererProps): Object {
|
||||
const {
|
||||
navigation,
|
||||
scene,
|
||||
} = props;
|
||||
const { navigation, scene } = props;
|
||||
|
||||
const focused = navigation.state.index === scene.index;
|
||||
const opacity = focused ? 1 : 0;
|
||||
@@ -42,11 +39,7 @@ function forInitial(props: NavigationSceneRendererProps): Object {
|
||||
* Standard iOS-style slide in from the right.
|
||||
*/
|
||||
function forHorizontal(props: NavigationSceneRendererProps): Object {
|
||||
const {
|
||||
layout,
|
||||
position,
|
||||
scene,
|
||||
} = props;
|
||||
const { layout, position, scene } = props;
|
||||
|
||||
if (!layout.isMeasured) {
|
||||
return forInitial(props);
|
||||
@@ -89,11 +82,7 @@ function forHorizontal(props: NavigationSceneRendererProps): Object {
|
||||
* Standard iOS-style slide in from the bottom (used for modals).
|
||||
*/
|
||||
function forVertical(props: NavigationSceneRendererProps): Object {
|
||||
const {
|
||||
layout,
|
||||
position,
|
||||
scene,
|
||||
} = props;
|
||||
const { layout, position, scene } = props;
|
||||
|
||||
if (!layout.isMeasured) {
|
||||
return forInitial(props);
|
||||
@@ -129,11 +118,7 @@ function forVertical(props: NavigationSceneRendererProps): Object {
|
||||
* Standard Android-style fade in from the bottom.
|
||||
*/
|
||||
function forFadeFromBottomAndroid(props: NavigationSceneRendererProps): Object {
|
||||
const {
|
||||
layout,
|
||||
position,
|
||||
scene,
|
||||
} = props;
|
||||
const { layout, position, scene } = props;
|
||||
|
||||
if (!layout.isMeasured) {
|
||||
return forInitial(props);
|
||||
|
||||
@@ -21,15 +21,19 @@ import type {
|
||||
TransitionConfig,
|
||||
} from '../TypeDefinition';
|
||||
|
||||
const NativeAnimatedModule = NativeModules &&
|
||||
NativeModules.NativeAnimatedModule;
|
||||
const NativeAnimatedModule =
|
||||
NativeModules && NativeModules.NativeAnimatedModule;
|
||||
|
||||
type Props = {
|
||||
screenProps?: {},
|
||||
headerMode: HeaderMode,
|
||||
mode: 'card' | 'modal',
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationStackScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationStackScreenOptions
|
||||
>,
|
||||
cardStyle?: Style,
|
||||
onTransitionStart?: () => void,
|
||||
onTransitionEnd?: () => void,
|
||||
@@ -68,7 +72,7 @@ class CardStackTransitioner extends Component<DefaultProps, Props, void> {
|
||||
// props for the new screen
|
||||
transitionProps: NavigationTransitionProps,
|
||||
// props for the old screen
|
||||
prevTransitionProps: NavigationTransitionProps,
|
||||
prevTransitionProps: NavigationTransitionProps
|
||||
) => {
|
||||
const isModal = this.props.mode === 'modal';
|
||||
// Copy the object so we can assign useNativeDriver below
|
||||
@@ -78,7 +82,7 @@ class CardStackTransitioner extends Component<DefaultProps, Props, void> {
|
||||
this.props.transitionConfig,
|
||||
transitionProps,
|
||||
prevTransitionProps,
|
||||
isModal,
|
||||
isModal
|
||||
).transitionSpec,
|
||||
};
|
||||
if (
|
||||
|
||||
@@ -28,19 +28,17 @@ type Props = {
|
||||
/**
|
||||
* Component that renders the navigation list in the drawer.
|
||||
*/
|
||||
const DrawerNavigatorItems = (
|
||||
{
|
||||
navigation,
|
||||
activeTintColor,
|
||||
activeBackgroundColor,
|
||||
inactiveTintColor,
|
||||
inactiveBackgroundColor,
|
||||
getLabel,
|
||||
renderIcon,
|
||||
style,
|
||||
labelStyle,
|
||||
}: Props,
|
||||
) => (
|
||||
const DrawerNavigatorItems = ({
|
||||
navigation,
|
||||
activeTintColor,
|
||||
activeBackgroundColor,
|
||||
inactiveTintColor,
|
||||
inactiveBackgroundColor,
|
||||
getLabel,
|
||||
renderIcon,
|
||||
style,
|
||||
labelStyle,
|
||||
}: Props) => (
|
||||
<View style={[styles.container, style]}>
|
||||
{navigation.state.routes.map((route: *, index: number) => {
|
||||
const focused = navigation.state.index === index;
|
||||
|
||||
@@ -16,7 +16,11 @@ import type {
|
||||
|
||||
type Props = {
|
||||
screenProps?: {},
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationDrawerScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationDrawerScreenOptions
|
||||
>,
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
childNavigationProps: {
|
||||
[key: string]: NavigationScreenProp<NavigationRoute, NavigationAction>,
|
||||
|
||||
@@ -20,7 +20,11 @@ import type { DrawerScene } from './DrawerView';
|
||||
type Navigation = NavigationScreenProp<NavigationRoute, NavigationAction>;
|
||||
|
||||
type Props = {
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationDrawerScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationDrawerScreenOptions
|
||||
>,
|
||||
navigation: Navigation,
|
||||
childNavigationProps: { [key: string]: Navigation },
|
||||
contentComponent: ReactClass<*>,
|
||||
@@ -37,11 +41,11 @@ class DrawerSidebar extends PureComponent<void, Props, void> {
|
||||
|
||||
_getScreenOptions = (routeKey: string) => {
|
||||
const DrawerScreen = this.props.router.getComponentForRouteName(
|
||||
'DrawerClose',
|
||||
'DrawerClose'
|
||||
);
|
||||
return DrawerScreen.router.getScreenOptions(
|
||||
this.props.childNavigationProps[routeKey],
|
||||
this.props.screenProps,
|
||||
this.props.screenProps
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -33,7 +33,11 @@ export type DrawerViewConfig = {
|
||||
|
||||
type Props = DrawerViewConfig & {
|
||||
screenProps?: {},
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationDrawerScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationDrawerScreenOptions
|
||||
>,
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
};
|
||||
|
||||
@@ -80,10 +84,10 @@ export default class DrawerView<T: *> extends PureComponent<void, Props, void> {
|
||||
};
|
||||
|
||||
_updateScreenNavigation = (
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>
|
||||
) => {
|
||||
const navigationState = navigation.state.routes.find(
|
||||
(route: *) => route.routeName === 'DrawerClose',
|
||||
(route: *) => route.routeName === 'DrawerClose'
|
||||
);
|
||||
if (
|
||||
this._screenNavigationProp &&
|
||||
@@ -98,10 +102,10 @@ export default class DrawerView<T: *> extends PureComponent<void, Props, void> {
|
||||
};
|
||||
|
||||
_getNavigationState = (
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>
|
||||
) => {
|
||||
const navigationState = navigation.state.routes.find(
|
||||
(route: *) => route.routeName === 'DrawerClose',
|
||||
(route: *) => route.routeName === 'DrawerClose'
|
||||
);
|
||||
return navigationState;
|
||||
};
|
||||
@@ -121,7 +125,7 @@ export default class DrawerView<T: *> extends PureComponent<void, Props, void> {
|
||||
|
||||
render() {
|
||||
const DrawerScreen = this.props.router.getComponentForRouteName(
|
||||
'DrawerClose',
|
||||
'DrawerClose'
|
||||
);
|
||||
return (
|
||||
<DrawerLayout
|
||||
|
||||
39
packages/react-navigation/src/views/Header.js
vendored
39
packages/react-navigation/src/views/Header.js
vendored
@@ -73,9 +73,8 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
if (!lastScene) {
|
||||
return null;
|
||||
}
|
||||
return this.props.getScreenDetails(
|
||||
lastScene,
|
||||
).options.headerTruncatedBackTitle;
|
||||
return this.props.getScreenDetails(lastScene).options
|
||||
.headerTruncatedBackTitle;
|
||||
}
|
||||
|
||||
_renderTitleComponent = (props: SceneProps) => {
|
||||
@@ -122,7 +121,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
}
|
||||
const backButtonTitle = this._getBackButtonTitleString(props.scene);
|
||||
const truncatedBackButtonTitle = this._getTruncatedBackButtonTitle(
|
||||
props.scene,
|
||||
props.scene
|
||||
);
|
||||
const width = this.state.widths[props.scene.key]
|
||||
? (this.props.layout.initWidth - this.state.widths[props.scene.key]) / 2
|
||||
@@ -153,7 +152,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
props,
|
||||
'left',
|
||||
this._renderLeftComponent,
|
||||
HeaderStyleInterpolator.forLeft,
|
||||
HeaderStyleInterpolator.forLeft
|
||||
);
|
||||
}
|
||||
|
||||
@@ -173,7 +172,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
{ ...props, style },
|
||||
'title',
|
||||
this._renderTitleComponent,
|
||||
HeaderStyleInterpolator.forCenter,
|
||||
HeaderStyleInterpolator.forCenter
|
||||
);
|
||||
}
|
||||
|
||||
@@ -182,7 +181,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
props,
|
||||
'right',
|
||||
this._renderRightComponent,
|
||||
HeaderStyleInterpolator.forRight,
|
||||
HeaderStyleInterpolator.forRight
|
||||
);
|
||||
}
|
||||
|
||||
@@ -190,16 +189,10 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
props: SceneProps,
|
||||
name: SubViewName,
|
||||
renderer: SubViewRenderer,
|
||||
styleInterpolator: NavigationStyleInterpolator,
|
||||
styleInterpolator: NavigationStyleInterpolator
|
||||
): ?React.Element<*> {
|
||||
const {
|
||||
scene,
|
||||
} = props;
|
||||
const {
|
||||
index,
|
||||
isStale,
|
||||
key,
|
||||
} = scene;
|
||||
const { scene } = props;
|
||||
const { index, isStale, key } = scene;
|
||||
|
||||
const offset = this.props.navigation.state.index - index;
|
||||
|
||||
@@ -261,13 +254,13 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
|
||||
let appBar;
|
||||
|
||||
if (this.props.mode === 'float') {
|
||||
const scenesProps: Array<SceneProps> = this.props.scenes.map(
|
||||
(scene: NavigationScene) => ({
|
||||
position: this.props.position,
|
||||
progress: this.props.progress,
|
||||
scene,
|
||||
}),
|
||||
);
|
||||
const scenesProps: Array<
|
||||
SceneProps
|
||||
> = this.props.scenes.map((scene: NavigationScene) => ({
|
||||
position: this.props.position,
|
||||
progress: this.props.progress,
|
||||
scene,
|
||||
}));
|
||||
appBar = scenesProps.map(this._renderHeader, this);
|
||||
} else {
|
||||
appBar = this._renderHeader({
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function create(Component: ReactClass<*>): ReactClass<*> {
|
||||
if (component) {
|
||||
invariant(
|
||||
typeof component.setNativeProps === 'function',
|
||||
'component must implement method `setNativeProps`',
|
||||
'component must implement method `setNativeProps`'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ export default function create(Component: ReactClass<*>): ReactClass<*> {
|
||||
this._positionListener && this._positionListener.remove();
|
||||
this._positionListener = new AnimatedValueSubscription(
|
||||
props.position,
|
||||
this._onPositionChange,
|
||||
this._onPositionChange
|
||||
);
|
||||
}
|
||||
|
||||
@@ -89,11 +89,7 @@ export default function create(Component: ReactClass<*>): ReactClass<*> {
|
||||
}
|
||||
|
||||
_computePointerEvents(): string {
|
||||
const {
|
||||
navigation,
|
||||
position,
|
||||
scene,
|
||||
} = this.props;
|
||||
const { navigation, position, scene } = this.props;
|
||||
|
||||
if (scene.isStale || navigation.state.index !== scene.index) {
|
||||
// The scene isn't focused.
|
||||
|
||||
@@ -30,11 +30,7 @@ export default class SceneView extends PureComponent<void, Props, void> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
screenProps,
|
||||
navigation,
|
||||
component: Component,
|
||||
} = this.props;
|
||||
const { screenProps, navigation, component: Component } = this.props;
|
||||
|
||||
return <Component screenProps={screenProps} navigation={navigation} />;
|
||||
}
|
||||
|
||||
@@ -44,13 +44,15 @@ function compareScenes(one: NavigationScene, two: NavigationScene): number {
|
||||
*/
|
||||
function areScenesShallowEqual(
|
||||
one: NavigationScene,
|
||||
two: NavigationScene,
|
||||
two: NavigationScene
|
||||
): boolean {
|
||||
return one.key === two.key &&
|
||||
return (
|
||||
one.key === two.key &&
|
||||
one.index === two.index &&
|
||||
one.isStale === two.isStale &&
|
||||
one.isActive === two.isActive &&
|
||||
areRoutesShallowEqual(one.route, two.route);
|
||||
areRoutesShallowEqual(one.route, two.route)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +60,7 @@ function areScenesShallowEqual(
|
||||
*/
|
||||
function areRoutesShallowEqual(
|
||||
one: ?NavigationRoute,
|
||||
two: ?NavigationRoute,
|
||||
two: ?NavigationRoute
|
||||
): boolean {
|
||||
if (!one || !two) {
|
||||
return one === two;
|
||||
@@ -74,7 +76,7 @@ function areRoutesShallowEqual(
|
||||
export default function ScenesReducer(
|
||||
scenes: Array<NavigationScene>,
|
||||
nextState: NavigationState,
|
||||
prevState: ?NavigationState,
|
||||
prevState: ?NavigationState
|
||||
): Array<NavigationScene> {
|
||||
if (prevState === nextState) {
|
||||
return scenes;
|
||||
@@ -106,7 +108,7 @@ export default function ScenesReducer(
|
||||
invariant(
|
||||
!nextKeys.has(key),
|
||||
`navigation.state.routes[${index}].key "${key}" conflicts with ` +
|
||||
'another route!',
|
||||
'another route!'
|
||||
);
|
||||
nextKeys.add(key);
|
||||
|
||||
@@ -171,7 +173,7 @@ export default function ScenesReducer(
|
||||
invariant(
|
||||
activeScenesCount === 1,
|
||||
'there should always be only one scene active, not %s.',
|
||||
activeScenesCount,
|
||||
activeScenesCount
|
||||
);
|
||||
|
||||
if (nextScenes.length !== scenes.length) {
|
||||
@@ -180,7 +182,7 @@ export default function ScenesReducer(
|
||||
|
||||
if (
|
||||
nextScenes.some(
|
||||
(scene: *, index: *) => !areScenesShallowEqual(scenes[index], scene),
|
||||
(scene: *, index: *) => !areScenesShallowEqual(scenes[index], scene)
|
||||
)
|
||||
) {
|
||||
return nextScenes;
|
||||
|
||||
@@ -70,7 +70,7 @@ export default class TabBarBottom
|
||||
const inputRange = [-1, ...routes.map((x: *, i: number) => i)];
|
||||
const outputRange = inputRange.map(
|
||||
(inputIndex: number) =>
|
||||
inputIndex === index ? activeTintColor : inactiveTintColor,
|
||||
inputIndex === index ? activeTintColor : inactiveTintColor
|
||||
);
|
||||
const color = position.interpolate({
|
||||
inputRange,
|
||||
@@ -140,7 +140,7 @@ export default class TabBarBottom
|
||||
(inputIndex: number) =>
|
||||
inputIndex === index
|
||||
? activeBackgroundColor
|
||||
: inactiveBackgroundColor,
|
||||
: inactiveBackgroundColor
|
||||
);
|
||||
const backgroundColor = position.interpolate({
|
||||
inputRange,
|
||||
|
||||
@@ -40,11 +40,11 @@ export default class TabBarIcon extends PureComponent<void, Props, void> {
|
||||
const inputRange = [-1, ...routes.map((x: *, i: number) => i)];
|
||||
const activeOpacity = position.interpolate({
|
||||
inputRange,
|
||||
outputRange: inputRange.map((i: number) => i === index ? 1 : 0),
|
||||
outputRange: inputRange.map((i: number) => (i === index ? 1 : 0)),
|
||||
});
|
||||
const inactiveOpacity = position.interpolate({
|
||||
inputRange,
|
||||
outputRange: inputRange.map((i: number) => i === index ? 0 : 1),
|
||||
outputRange: inputRange.map((i: number) => (i === index ? 0 : 1)),
|
||||
});
|
||||
// We render the icon twice at the same position on top of each other:
|
||||
// active and inactive one, so we can fade between them.
|
||||
|
||||
@@ -67,7 +67,7 @@ export default class TabBarTop
|
||||
const inputRange = [-1, ...routes.map((x: *, i: number) => i)];
|
||||
const outputRange = inputRange.map(
|
||||
(inputIndex: number) =>
|
||||
inputIndex === index ? activeTintColor : inactiveTintColor,
|
||||
inputIndex === index ? activeTintColor : inactiveTintColor
|
||||
);
|
||||
const color = position.interpolate({
|
||||
inputRange,
|
||||
|
||||
@@ -41,7 +41,11 @@ type Props = {
|
||||
|
||||
screenProps?: {},
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
router: NavigationRouter<NavigationState, NavigationAction, NavigationTabScreenOptions>,
|
||||
router: NavigationRouter<
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
NavigationTabScreenOptions
|
||||
>,
|
||||
childNavigationProps: {
|
||||
[key: string]: NavigationScreenProp<NavigationRoute, NavigationAction>,
|
||||
},
|
||||
@@ -59,7 +63,7 @@ class TabView extends PureComponent<void, Props, void> {
|
||||
const { screenProps } = this.props;
|
||||
const childNavigation = this.props.childNavigationProps[route.key];
|
||||
const TabComponent = this.props.router.getComponentForRouteName(
|
||||
route.routeName,
|
||||
route.routeName
|
||||
);
|
||||
return (
|
||||
<View style={styles.page}>
|
||||
@@ -75,7 +79,7 @@ class TabView extends PureComponent<void, Props, void> {
|
||||
_getLabel = ({ route, tintColor, focused }: TabScene) => {
|
||||
const options = this.props.router.getScreenOptions(
|
||||
this.props.childNavigationProps[route.key],
|
||||
this.props.screenProps || {},
|
||||
this.props.screenProps || {}
|
||||
);
|
||||
|
||||
if (options.tabBarLabel) {
|
||||
@@ -94,7 +98,7 @@ class TabView extends PureComponent<void, Props, void> {
|
||||
_renderIcon = ({ focused, route, tintColor }: TabScene) => {
|
||||
const options = this.props.router.getScreenOptions(
|
||||
this.props.childNavigationProps[route.key],
|
||||
this.props.screenProps || {},
|
||||
this.props.screenProps || {}
|
||||
);
|
||||
if (options.tabBarIcon) {
|
||||
return typeof options.tabBarIcon === 'function'
|
||||
@@ -145,7 +149,7 @@ class TabView extends PureComponent<void, Props, void> {
|
||||
const { state } = this.props.navigation;
|
||||
const options = router.getScreenOptions(
|
||||
this.props.childNavigationProps[state.routes[state.index].key],
|
||||
screenProps || {},
|
||||
screenProps || {}
|
||||
);
|
||||
|
||||
const tabBarVisible = options.tabBarVisible == null
|
||||
|
||||
@@ -50,7 +50,8 @@ export default class TouchableItem
|
||||
* We need to pass the background prop to specify a borderless ripple effect.
|
||||
*/
|
||||
if (
|
||||
Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_LOLLIPOP
|
||||
Platform.OS === 'android' &&
|
||||
Platform.Version >= ANDROID_VERSION_LOLLIPOP
|
||||
) {
|
||||
const { style, ...rest } = this.props; // eslint-disable-line no-unused-vars
|
||||
|
||||
@@ -60,7 +61,7 @@ export default class TouchableItem
|
||||
style={null}
|
||||
background={TouchableNativeFeedback.Ripple(
|
||||
this.props.pressColor,
|
||||
this.props.borderless,
|
||||
this.props.borderless
|
||||
)}
|
||||
>
|
||||
<View style={this.props.style}>
|
||||
|
||||
@@ -55,13 +55,14 @@ function defaultTransitionConfig(
|
||||
// props for the old screen
|
||||
prevTransitionProps: NavigationTransitionProps,
|
||||
// whether we're animating in/out a modal screen
|
||||
isModal: boolean,
|
||||
isModal: boolean
|
||||
): TransitionConfig {
|
||||
if (Platform.OS === 'android') {
|
||||
// Use the default Android animation no matter if the screen is a modal.
|
||||
// Android doesn't have full-screen modals like iOS does, it has dialogs.
|
||||
if (
|
||||
prevTransitionProps && transitionProps.index < prevTransitionProps.index
|
||||
prevTransitionProps &&
|
||||
transitionProps.index < prevTransitionProps.index
|
||||
) {
|
||||
// Navigating back to the previous screen
|
||||
return FadeOutToBottomAndroid;
|
||||
@@ -81,12 +82,12 @@ function getTransitionConfig(
|
||||
transitionProps: NavigationTransitionProps,
|
||||
// props for the old screen
|
||||
prevTransitionProps: NavigationTransitionProps,
|
||||
isModal: boolean,
|
||||
isModal: boolean
|
||||
): TransitionConfig {
|
||||
const defaultConfig = defaultTransitionConfig(
|
||||
transitionProps,
|
||||
prevTransitionProps,
|
||||
isModal,
|
||||
isModal
|
||||
);
|
||||
if (transitionConfigurer) {
|
||||
return {
|
||||
|
||||
@@ -22,14 +22,14 @@ import type {
|
||||
type Props = {
|
||||
configureTransition: (
|
||||
transitionProps: NavigationTransitionProps,
|
||||
prevTransitionProps: ?NavigationTransitionProps,
|
||||
prevTransitionProps: ?NavigationTransitionProps
|
||||
) => NavigationTransitionSpec,
|
||||
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
|
||||
onTransitionEnd?: () => void,
|
||||
onTransitionStart?: () => void,
|
||||
render: (
|
||||
transitionProps: NavigationTransitionProps,
|
||||
prevTransitionProps: ?NavigationTransitionProps,
|
||||
prevTransitionProps: ?NavigationTransitionProps
|
||||
) => any,
|
||||
style?: any,
|
||||
};
|
||||
@@ -103,15 +103,15 @@ class Transitioner extends React.Component<*, Props, State> {
|
||||
const nextScenes = NavigationScenesReducer(
|
||||
this.state.scenes,
|
||||
nextProps.navigation.state,
|
||||
this.props.navigation.state,
|
||||
this.props.navigation.state
|
||||
);
|
||||
|
||||
if (nextScenes === this.state.scenes) {
|
||||
return;
|
||||
}
|
||||
|
||||
const indexHasChanged = nextProps.navigation.state.index !==
|
||||
this.props.navigation.state.index;
|
||||
const indexHasChanged =
|
||||
nextProps.navigation.state.index !== this.props.navigation.state.index;
|
||||
if (this._isTransitionRunning) {
|
||||
this._queuedTransition = { nextProps, nextScenes, indexHasChanged };
|
||||
return;
|
||||
@@ -123,17 +123,14 @@ class Transitioner extends React.Component<*, Props, State> {
|
||||
_startTransition(
|
||||
nextProps: Props,
|
||||
nextScenes: Array<NavigationScene>,
|
||||
indexHasChanged: boolean,
|
||||
indexHasChanged: boolean
|
||||
) {
|
||||
const nextState = {
|
||||
...this.state,
|
||||
scenes: nextScenes,
|
||||
};
|
||||
|
||||
const {
|
||||
position,
|
||||
progress,
|
||||
} = nextState;
|
||||
const { position, progress } = nextState;
|
||||
|
||||
progress.setValue(0);
|
||||
|
||||
@@ -144,7 +141,7 @@ class Transitioner extends React.Component<*, Props, State> {
|
||||
const transitionUserSpec = nextProps.configureTransition
|
||||
? nextProps.configureTransition(
|
||||
this._transitionProps,
|
||||
this._prevTransitionProps,
|
||||
this._prevTransitionProps
|
||||
)
|
||||
: null;
|
||||
|
||||
@@ -179,7 +176,7 @@ class Transitioner extends React.Component<*, Props, State> {
|
||||
nextProps.onTransitionStart &&
|
||||
nextProps.onTransitionStart(
|
||||
this._transitionProps,
|
||||
this._prevTransitionProps,
|
||||
this._prevTransitionProps
|
||||
);
|
||||
Animated.parallel(animations).start(this._onTransitionEnd);
|
||||
});
|
||||
@@ -241,7 +238,7 @@ class Transitioner extends React.Component<*, Props, State> {
|
||||
this._startTransition(
|
||||
this._queuedTransition.nextProps,
|
||||
this._queuedTransition.nextScenes,
|
||||
this._queuedTransition.indexHasChanged,
|
||||
this._queuedTransition.indexHasChanged
|
||||
);
|
||||
this._queuedTransition = null;
|
||||
} else {
|
||||
@@ -253,18 +250,11 @@ class Transitioner extends React.Component<*, Props, State> {
|
||||
|
||||
function buildTransitionProps(
|
||||
props: Props,
|
||||
state: State,
|
||||
state: State
|
||||
): NavigationTransitionProps {
|
||||
const {
|
||||
navigation,
|
||||
} = props;
|
||||
const { navigation } = props;
|
||||
|
||||
const {
|
||||
layout,
|
||||
position,
|
||||
progress,
|
||||
scenes,
|
||||
} = state;
|
||||
const { layout, position, progress, scenes } = state;
|
||||
|
||||
const scene = scenes.find(isSceneActive);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ type InjectedProps = {
|
||||
};
|
||||
|
||||
export default function withNavigation<T: *>(
|
||||
Component: ReactClass<T & InjectedProps>,
|
||||
Component: ReactClass<T & InjectedProps>
|
||||
) {
|
||||
const componentWithNavigation = (props: T, { navigation }: Context) => (
|
||||
<Component {...props} navigation={navigation} />
|
||||
|
||||
@@ -16,7 +16,7 @@ type InjectedProps<N> = {
|
||||
* HOC which caches the child navigation items.
|
||||
*/
|
||||
export default function withCachedChildNavigation<T: *, N: *>(
|
||||
Comp: ReactClass<T & InjectedProps<N>>,
|
||||
Comp: ReactClass<T & InjectedProps<N>>
|
||||
): ReactClass<T> {
|
||||
return class extends PureComponent {
|
||||
static displayName = `withCachedChildNavigation(${Comp.displayName || Comp.name})`;
|
||||
@@ -36,7 +36,7 @@ export default function withCachedChildNavigation<T: *, N: *>(
|
||||
};
|
||||
|
||||
_updateNavigationProps = (
|
||||
navigation: NavigationScreenProp<N, NavigationAction>,
|
||||
navigation: NavigationScreenProp<N, NavigationAction>
|
||||
) => {
|
||||
// Update props for each child route
|
||||
if (!this._childNavigationProps) {
|
||||
|
||||
36
packages/react-navigation/website/config/env.js
vendored
36
packages/react-navigation/website/config/env.js
vendored
@@ -4,25 +4,25 @@
|
||||
var REACT_APP = /^REACT_APP_/i;
|
||||
|
||||
function getClientEnvironment(publicUrl) {
|
||||
var processEnv = Object
|
||||
.keys(process.env)
|
||||
var processEnv = Object.keys(process.env)
|
||||
.filter(key => REACT_APP.test(key))
|
||||
.reduce((env, key) => {
|
||||
env[key] = JSON.stringify(process.env[key]);
|
||||
return env;
|
||||
}, {
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
'NODE_ENV': JSON.stringify(
|
||||
process.env.NODE_ENV || 'development'
|
||||
),
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
'PUBLIC_URL': JSON.stringify(publicUrl)
|
||||
});
|
||||
return {'process.env': processEnv};
|
||||
.reduce(
|
||||
(env, key) => {
|
||||
env[key] = JSON.stringify(process.env[key]);
|
||||
return env;
|
||||
},
|
||||
{
|
||||
// Useful for determining whether we’re running in production mode.
|
||||
// Most importantly, it switches React into the correct mode.
|
||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
|
||||
// Useful for resolving the correct path to static assets in `public`.
|
||||
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
|
||||
// This should only be used as an escape hatch. Normally you would put
|
||||
// images into the `src` and `import` them in code to get their paths.
|
||||
PUBLIC_URL: JSON.stringify(publicUrl),
|
||||
}
|
||||
);
|
||||
return { 'process.env': processEnv };
|
||||
}
|
||||
|
||||
module.exports = getClientEnvironment;
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = "test-file-stub";
|
||||
module.exports = 'test-file-stub';
|
||||
|
||||
@@ -39,13 +39,13 @@ module.exports = {
|
||||
testsSetup: resolveApp('src/setupTests.js'),
|
||||
appNodeModules: resolveApp('node_modules'),
|
||||
ownNodeModules: resolveApp('node_modules'),
|
||||
nodePaths: nodePaths
|
||||
nodePaths: nodePaths,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// config before publish: we're in ./packages/react-scripts/config/
|
||||
if (__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1) {
|
||||
if (
|
||||
__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1
|
||||
) {
|
||||
module.exports = {
|
||||
appRoot: resolveOwn(''),
|
||||
appBuild: resolveOwn('../../../build'),
|
||||
@@ -59,6 +59,6 @@ if (__dirname.indexOf(path.join('packages', 'react-scripts', 'config')) !== -1)
|
||||
testsSetup: resolveOwn('../template/src/setupTests.js'),
|
||||
appNodeModules: resolveOwn('../node_modules'),
|
||||
ownNodeModules: resolveOwn('../node_modules'),
|
||||
nodePaths: nodePaths
|
||||
nodePaths: nodePaths,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ const publicUrl = '';
|
||||
// Get environment variables to inject into our app.
|
||||
const env = getClientEnvironment(publicUrl);
|
||||
|
||||
console.log(paths.nodePaths.concat([path.resolve(__dirname, '../node_modules')]));
|
||||
console.log(
|
||||
paths.nodePaths.concat([path.resolve(__dirname, '../node_modules')])
|
||||
);
|
||||
|
||||
// This is the development configuration.
|
||||
// It is focused on developer experience and fast rebuilds.
|
||||
@@ -71,7 +73,9 @@ module.exports = {
|
||||
// We use `fallback` instead of `root` because we want `node_modules` to "win"
|
||||
// if there any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
fallback: paths.nodePaths.concat([path.resolve(__dirname, '../node_modules')]),
|
||||
fallback: paths.nodePaths.concat([
|
||||
path.resolve(__dirname, '../node_modules'),
|
||||
]),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
@@ -103,7 +107,6 @@ module.exports = {
|
||||
include: paths.appSrc,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
|
||||
// This is a feature of `babel-loader` for webpack (not Babel itself).
|
||||
// It enables caching results in ./node_modules/.cache/react-scripts/
|
||||
// directory for faster rebuilds. We use findCacheDir() because of:
|
||||
|
||||
@@ -53,10 +53,7 @@ module.exports = {
|
||||
// You can exclude the *.map files from the build during deployment.
|
||||
devtool: 'source-map',
|
||||
// In production, we only want to load the polyfills and the app code.
|
||||
entry: [
|
||||
require.resolve('./polyfills'),
|
||||
paths.appIndexJs,
|
||||
],
|
||||
entry: [require.resolve('./polyfills'), paths.appIndexJs],
|
||||
output: {
|
||||
// The build folder.
|
||||
path: paths.appBuildPublic,
|
||||
@@ -74,7 +71,9 @@ module.exports = {
|
||||
// We use `fallback` instead of `root` because we want `node_modules` to "win"
|
||||
// if there any conflicts. This matches Node resolution mechanism.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/253
|
||||
fallback: paths.nodePaths.concat([path.resolve(__dirname, '../node_modules')]),
|
||||
fallback: paths.nodePaths.concat([
|
||||
path.resolve(__dirname, '../node_modules'),
|
||||
]),
|
||||
// These are the reasonable defaults supported by the Node ecosystem.
|
||||
// We also include JSX as a common component filename extension to support
|
||||
// some tools, although we do not recommend using it, see:
|
||||
@@ -105,7 +104,6 @@ module.exports = {
|
||||
test: /\.(js|jsx)$/,
|
||||
include: paths.appSrc,
|
||||
loader: 'babel',
|
||||
|
||||
},
|
||||
// The notation here is somewhat confusing.
|
||||
// "postcss" loader applies autoprefixer to our CSS.
|
||||
@@ -129,7 +127,10 @@ module.exports = {
|
||||
// Webpack 1.x uses Uglify plugin as a signal to minify *all* the assets
|
||||
// including CSS. This is confusing and will be removed in Webpack 2:
|
||||
// https://github.com/webpack/webpack/issues/283
|
||||
loader: ExtractTextPlugin.extract('style', 'css?importLoaders=1&-autoprefixer!postcss'),
|
||||
loader: ExtractTextPlugin.extract(
|
||||
'style',
|
||||
'css?importLoaders=1&-autoprefixer!postcss'
|
||||
),
|
||||
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
|
||||
},
|
||||
// JSON is not enabled by default in Webpack but both Node and Browserify
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"autoprefixer": "6.5.1",
|
||||
"babel-cli": "^6.18.0",
|
||||
"babel-core": "6.17.0",
|
||||
"babel-eslint": "7.0.0",
|
||||
"babel-jest": "16.0.0",
|
||||
"babel-loader": "6.2.5",
|
||||
"babel-plugin-flow-react-proptypes": "grabbou/babel-plugin-flow-react-proptypes#release",
|
||||
@@ -18,13 +17,6 @@
|
||||
"css-loader": "0.25.0",
|
||||
"detect-port": "1.0.1",
|
||||
"dotenv": "2.0.0",
|
||||
"eslint": "3.8.1",
|
||||
"eslint-config-react-app": "^0.3.0",
|
||||
"eslint-loader": "1.6.0",
|
||||
"eslint-plugin-flowtype": "2.21.0",
|
||||
"eslint-plugin-import": "2.0.1",
|
||||
"eslint-plugin-jsx-a11y": "2.2.3",
|
||||
"eslint-plugin-react": "6.4.1",
|
||||
"extract-text-webpack-plugin": "1.0.1",
|
||||
"file-loader": "0.9.0",
|
||||
"filesize": "3.3.0",
|
||||
@@ -54,6 +46,7 @@
|
||||
"dependencies": {
|
||||
"@blueprintjs/core": "^1.0.1",
|
||||
"prismjs": "^1.6.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "~15.3.2",
|
||||
"react-addons-css-transition-group": "~15.3.2",
|
||||
"react-dom": "~15.3.2",
|
||||
@@ -102,8 +95,5 @@
|
||||
"presets": [
|
||||
"react-app"
|
||||
]
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
}
|
||||
}
|
||||
|
||||
113
packages/react-navigation/website/scripts/build.js
vendored
113
packages/react-navigation/website/scripts/build.js
vendored
@@ -83,46 +83,65 @@ recursive(paths.appBuild, (err, fileNames) => {
|
||||
|
||||
const navLibPackageJson = require(libPkgPath);
|
||||
|
||||
exec('babel', ['src', '--out-dir', paths.appBuildLib], {
|
||||
cwd: paths.appRoot,
|
||||
});
|
||||
|
||||
exec('babel', [ 'src', '--out-dir', paths.appBuildLib], {cwd: paths.appRoot});
|
||||
|
||||
fs.readdirSync(paths.appBuildLib).forEach((module) => {
|
||||
fs.readdirSync(paths.appBuildLib).forEach(module => {
|
||||
const modulePath = path.join(paths.appBuildLib, module);
|
||||
let moduleData = fs.readFileSync(modulePath, {encoding: 'utf8'});
|
||||
let moduleData = fs.readFileSync(modulePath, { encoding: 'utf8' });
|
||||
// This is a dangerous shameful hack but it allows the website source to use a standard-looking import:
|
||||
moduleData = moduleData.split("require('react-navigation'").join("require('../react-navigation/react-navigation.web'");
|
||||
moduleData = moduleData
|
||||
.split("require('react-navigation'")
|
||||
.join("require('../react-navigation/react-navigation.web'");
|
||||
fs.writeFileSync(modulePath, moduleData);
|
||||
});
|
||||
|
||||
const libPath = path.join(paths.appBuild, 'react-navigation');
|
||||
fs.mkdirSync(libPath);
|
||||
|
||||
fs.copySync(
|
||||
path.join(paths.libRoot, 'lib'),
|
||||
libPath
|
||||
);
|
||||
fs.copySync(path.join(paths.libRoot, 'lib'), libPath);
|
||||
|
||||
// fs.writeFileSync(path.join(libPath, 'package.json'), JSON.stringify(Object.assign({}, navLibPackageJson, {
|
||||
// main: 'lib/react-navigation',
|
||||
// }), null, 2));
|
||||
|
||||
fs.writeFileSync(path.join(paths.appBuild, 'package.json'), JSON.stringify(Object.assign({
|
||||
version: '1.0.0',
|
||||
name: 'web-build',
|
||||
}, appPackageJson.server, {
|
||||
dependencies: Object.assign({}, appPackageJson.dependencies, navLibPackageJson.dependencies, appPackageJson.server.dependencies, {
|
||||
'react-navigation': '',
|
||||
}),
|
||||
}), null, 2));
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(paths.appBuild, 'package.json'),
|
||||
JSON.stringify(
|
||||
Object.assign(
|
||||
{
|
||||
version: '1.0.0',
|
||||
name: 'web-build',
|
||||
},
|
||||
appPackageJson.server,
|
||||
{
|
||||
dependencies: Object.assign(
|
||||
{},
|
||||
appPackageJson.dependencies,
|
||||
navLibPackageJson.dependencies,
|
||||
appPackageJson.server.dependencies,
|
||||
{
|
||||
'react-navigation': '',
|
||||
}
|
||||
),
|
||||
}
|
||||
),
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// Print a detailed summary of build files.
|
||||
function printFileSizes(stats, previousSizeMap) {
|
||||
const assets = stats.toJson().assets
|
||||
.filter(asset => /\.(js|css)$/.test(asset.name))
|
||||
.map((asset) => {
|
||||
const fileContents = fs.readFileSync(`${paths.appBuildPublic}/${asset.name}`);
|
||||
const assets = stats
|
||||
.toJson()
|
||||
.assets.filter(asset => /\.(js|css)$/.test(asset.name))
|
||||
.map(asset => {
|
||||
const fileContents = fs.readFileSync(
|
||||
`${paths.appBuildPublic}/${asset.name}`
|
||||
);
|
||||
const size = gzipSize(fileContents);
|
||||
const previousSize = previousSizeMap[removeFileNameHash(asset.name)];
|
||||
const difference = getDifferenceLabel(size, previousSize);
|
||||
@@ -134,10 +153,11 @@ function printFileSizes(stats, previousSizeMap) {
|
||||
};
|
||||
});
|
||||
assets.sort((a, b) => b.size - a.size);
|
||||
const longestSizeLabelLength = Math.max.apply(null,
|
||||
const longestSizeLabelLength = Math.max.apply(
|
||||
null,
|
||||
assets.map(a => stripAnsi(a.sizeLabel).length)
|
||||
);
|
||||
assets.forEach((asset) => {
|
||||
assets.forEach(asset => {
|
||||
let sizeLabel = asset.sizeLabel;
|
||||
const sizeLength = stripAnsi(sizeLabel).length;
|
||||
if (sizeLength < longestSizeLabelLength) {
|
||||
@@ -145,8 +165,7 @@ function printFileSizes(stats, previousSizeMap) {
|
||||
sizeLabel += rightPadding;
|
||||
}
|
||||
console.log(
|
||||
` ${sizeLabel
|
||||
} ${chalk.dim(asset.folder + path.sep)}${chalk.cyan(asset.name)}`
|
||||
` ${sizeLabel} ${chalk.dim(asset.folder + path.sep)}${chalk.cyan(asset.name)}`
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -155,7 +174,7 @@ function printFileSizes(stats, previousSizeMap) {
|
||||
function printErrors(summary, errors) {
|
||||
console.log(chalk.red(summary));
|
||||
console.log();
|
||||
errors.forEach((err) => {
|
||||
errors.forEach(err => {
|
||||
console.log(err.message || err);
|
||||
console.log(err.stack);
|
||||
console.log();
|
||||
@@ -191,20 +210,28 @@ function build(previousSizeMap) {
|
||||
const publicPath = config.output.publicPath;
|
||||
if (homepagePath && homepagePath.indexOf('.github.io/') !== -1) {
|
||||
// "homepage": "http://user.github.io/project"
|
||||
console.log(`The project was built assuming it is hosted at ${chalk.green(publicPath)}.`);
|
||||
console.log(`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`);
|
||||
console.log(
|
||||
`The project was built assuming it is hosted at ${chalk.green(publicPath)}.`
|
||||
);
|
||||
console.log(
|
||||
`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`
|
||||
);
|
||||
console.log();
|
||||
console.log(`The ${chalk.cyan('build')} folder is ready to be deployed.`);
|
||||
console.log(`To publish it at ${chalk.green(homepagePath)}, run:`);
|
||||
console.log();
|
||||
console.log(` ${chalk.cyan('npm')} install --save-dev gh-pages`);
|
||||
console.log();
|
||||
console.log(`Add the following script in your ${chalk.cyan('package.json')}.`);
|
||||
console.log(
|
||||
`Add the following script in your ${chalk.cyan('package.json')}.`
|
||||
);
|
||||
console.log();
|
||||
console.log(` ${chalk.dim('// ...')}`);
|
||||
console.log(` ${chalk.yellow('"scripts"')}: {`);
|
||||
console.log(` ${chalk.dim('// ...')}`);
|
||||
console.log(` ${chalk.yellow('"deploy"')}: ${chalk.yellow('"gh-pages -d build"')}`);
|
||||
console.log(
|
||||
` ${chalk.yellow('"deploy"')}: ${chalk.yellow('"gh-pages -d build"')}`
|
||||
);
|
||||
console.log(' }');
|
||||
console.log();
|
||||
console.log('Then run:');
|
||||
@@ -213,24 +240,36 @@ function build(previousSizeMap) {
|
||||
console.log();
|
||||
} else if (publicPath !== '/') {
|
||||
// "homepage": "http://mywebsite.com/project"
|
||||
console.log(`The project was built assuming it is hosted at ${chalk.green(publicPath)}.`);
|
||||
console.log(`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`);
|
||||
console.log(
|
||||
`The project was built assuming it is hosted at ${chalk.green(publicPath)}.`
|
||||
);
|
||||
console.log(
|
||||
`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`
|
||||
);
|
||||
console.log();
|
||||
console.log(`The ${chalk.cyan('build')} folder is ready to be deployed.`);
|
||||
console.log();
|
||||
} else {
|
||||
// no homepage or "homepage": "http://mywebsite.com"
|
||||
console.log('The project was built assuming it is hosted at the server root.');
|
||||
console.log(
|
||||
'The project was built assuming it is hosted at the server root.'
|
||||
);
|
||||
if (homepagePath) {
|
||||
// "homepage": "http://mywebsite.com"
|
||||
console.log(`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`);
|
||||
console.log(
|
||||
`You can control this with the ${chalk.green('homepage')} field in your ${chalk.cyan('package.json')}.`
|
||||
);
|
||||
console.log();
|
||||
} else {
|
||||
// no homepage
|
||||
console.log(`To override this, specify the ${chalk.green('homepage')} in your ${chalk.cyan('package.json')}.`);
|
||||
console.log(
|
||||
`To override this, specify the ${chalk.green('homepage')} in your ${chalk.cyan('package.json')}.`
|
||||
);
|
||||
console.log('For example, add this to build it for GitHub Pages:');
|
||||
console.log();
|
||||
console.log(` ${chalk.green('"homepage"')}${chalk.cyan(': ')}${chalk.green('"http://myname.github.io/myapp"')}${chalk.cyan(',')}`);
|
||||
console.log(
|
||||
` ${chalk.green('"homepage"')}${chalk.cyan(': ')}${chalk.green('"http://myname.github.io/myapp"')}${chalk.cyan(',')}`
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
console.log(`The ${chalk.cyan('build')} folder is ready to be deployed.`);
|
||||
|
||||
112
packages/react-navigation/website/scripts/start.js
vendored
112
packages/react-navigation/website/scripts/start.js
vendored
@@ -4,7 +4,7 @@ process.env.NODE_ENV = 'development';
|
||||
// if this file is missing. dotenv will never modify any environment variables
|
||||
// that have already been set.
|
||||
// https://github.com/motdotla/dotenv
|
||||
require('dotenv').config({silent: true});
|
||||
require('dotenv').config({ silent: true });
|
||||
|
||||
var chalk = require('chalk');
|
||||
var webpack = require('webpack');
|
||||
@@ -34,7 +34,7 @@ var handleCompile;
|
||||
// We only use this block for testing of Create React App itself:
|
||||
var isSmokeTest = process.argv.some(arg => arg.indexOf('--smoke-test') > -1);
|
||||
if (isSmokeTest) {
|
||||
handleCompile = function (err, stats) {
|
||||
handleCompile = function(err, stats) {
|
||||
if (err || stats.hasErrors() || stats.hasWarnings()) {
|
||||
process.exit(1);
|
||||
} else {
|
||||
@@ -71,10 +71,14 @@ function setupCompiler(host, port, protocol) {
|
||||
console.log();
|
||||
console.log('The app is running at:');
|
||||
console.log();
|
||||
console.log(' ' + chalk.cyan(protocol + '://' + host + ':' + port + '/'));
|
||||
console.log(
|
||||
' ' + chalk.cyan(protocol + '://' + host + ':' + port + '/')
|
||||
);
|
||||
console.log();
|
||||
console.log('Note that the development build is not optimized.');
|
||||
console.log('To create a production build, use ' + chalk.cyan('npm run build') + '.');
|
||||
console.log(
|
||||
'To create a production build, use ' + chalk.cyan('npm run build') + '.'
|
||||
);
|
||||
console.log();
|
||||
}
|
||||
|
||||
@@ -99,8 +103,16 @@ function setupCompiler(host, port, protocol) {
|
||||
});
|
||||
// Teach some ESLint tricks.
|
||||
console.log('You may use special comments to disable some warnings.');
|
||||
console.log('Use ' + chalk.yellow('// eslint-disable-next-line') + ' to ignore the next line.');
|
||||
console.log('Use ' + chalk.yellow('/* eslint-disable */') + ' to ignore all warnings in a file.');
|
||||
console.log(
|
||||
'Use ' +
|
||||
chalk.yellow('// eslint-disable-next-line') +
|
||||
' to ignore the next line.'
|
||||
);
|
||||
console.log(
|
||||
'Use ' +
|
||||
chalk.yellow('/* eslint-disable */') +
|
||||
' to ignore all warnings in a file.'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -108,53 +120,76 @@ function setupCompiler(host, port, protocol) {
|
||||
// We need to provide a custom onError function for httpProxyMiddleware.
|
||||
// It allows us to log custom error messages on the console.
|
||||
function onProxyError(proxy) {
|
||||
return function(err, req, res){
|
||||
return function(err, req, res) {
|
||||
var host = req.headers && req.headers.host;
|
||||
console.log(
|
||||
chalk.red('Proxy error:') + ' Could not proxy request ' + chalk.cyan(req.url) +
|
||||
' from ' + chalk.cyan(host) + ' to ' + chalk.cyan(proxy) + '.'
|
||||
chalk.red('Proxy error:') +
|
||||
' Could not proxy request ' +
|
||||
chalk.cyan(req.url) +
|
||||
' from ' +
|
||||
chalk.cyan(host) +
|
||||
' to ' +
|
||||
chalk.cyan(proxy) +
|
||||
'.'
|
||||
);
|
||||
console.log(
|
||||
'See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (' +
|
||||
chalk.cyan(err.code) + ').'
|
||||
chalk.cyan(err.code) +
|
||||
').'
|
||||
);
|
||||
console.log();
|
||||
|
||||
// And immediately send the proper error response to the client.
|
||||
// Otherwise, the request will eventually timeout with ERR_EMPTY_RESPONSE on the client side.
|
||||
if (res.writeHead && !res.headersSent) {
|
||||
res.writeHead(500);
|
||||
res.writeHead(500);
|
||||
}
|
||||
res.end('Proxy error: Could not proxy request ' + req.url + ' from ' +
|
||||
host + ' to ' + proxy + ' (' + err.code + ').'
|
||||
res.end(
|
||||
'Proxy error: Could not proxy request ' +
|
||||
req.url +
|
||||
' from ' +
|
||||
host +
|
||||
' to ' +
|
||||
proxy +
|
||||
' (' +
|
||||
err.code +
|
||||
').'
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function addMiddleware(devServer) {
|
||||
// `proxy` lets you to specify a fallback server during development.
|
||||
// Every unrecognized request will be forwarded to it.
|
||||
var proxy = require(paths.appPackageJson).proxy;
|
||||
devServer.use(historyApiFallback({
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
// For single page apps, we generally want to fallback to /index.html.
|
||||
// However we also want to respect `proxy` for API calls.
|
||||
// So if `proxy` is specified, we need to decide which fallback to use.
|
||||
// We use a heuristic: if request `accept`s text/html, we pick /index.html.
|
||||
// Modern browsers include text/html into `accept` header when navigating.
|
||||
// However API calls like `fetch()` won’t generally accept text/html.
|
||||
// If this heuristic doesn’t work well for you, don’t use `proxy`.
|
||||
htmlAcceptHeaders: proxy ?
|
||||
['text/html'] :
|
||||
['text/html', '*/*']
|
||||
}));
|
||||
devServer.use(
|
||||
historyApiFallback({
|
||||
// Paths with dots should still use the history fallback.
|
||||
// See https://github.com/facebookincubator/create-react-app/issues/387.
|
||||
disableDotRule: true,
|
||||
// For single page apps, we generally want to fallback to /index.html.
|
||||
// However we also want to respect `proxy` for API calls.
|
||||
// So if `proxy` is specified, we need to decide which fallback to use.
|
||||
// We use a heuristic: if request `accept`s text/html, we pick /index.html.
|
||||
// Modern browsers include text/html into `accept` header when navigating.
|
||||
// However API calls like `fetch()` won’t generally accept text/html.
|
||||
// If this heuristic doesn’t work well for you, don’t use `proxy`.
|
||||
htmlAcceptHeaders: proxy ? ['text/html'] : ['text/html', '*/*'],
|
||||
})
|
||||
);
|
||||
if (proxy) {
|
||||
if (typeof proxy !== 'string') {
|
||||
console.log(chalk.red('When specified, "proxy" in package.json must be a string.'));
|
||||
console.log(chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".'));
|
||||
console.log(chalk.red('Either remove "proxy" from package.json, or make it a string.'));
|
||||
console.log(
|
||||
chalk.red('When specified, "proxy" in package.json must be a string.')
|
||||
);
|
||||
console.log(
|
||||
chalk.red('Instead, the type of "proxy" was "' + typeof proxy + '".')
|
||||
);
|
||||
console.log(
|
||||
chalk.red(
|
||||
'Either remove "proxy" from package.json, or make it a string.'
|
||||
)
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -165,7 +200,8 @@ function addMiddleware(devServer) {
|
||||
// - /sockjs-node/* (WebpackDevServer uses this for hot reloading)
|
||||
// Tip: use https://jex.im/regulex/ to visualize the regex
|
||||
var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/;
|
||||
devServer.use(mayProxy,
|
||||
devServer.use(
|
||||
mayProxy,
|
||||
// Pass the scope regex both to Express and to the middleware for proxying
|
||||
// of both HTTP and WebSockets to work without false positives.
|
||||
httpProxyMiddleware(pathname => mayProxy.test(pathname), {
|
||||
@@ -173,7 +209,7 @@ function addMiddleware(devServer) {
|
||||
logLevel: 'silent',
|
||||
onError: onProxyError(proxy),
|
||||
secure: false,
|
||||
changeOrigin: true
|
||||
changeOrigin: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -217,11 +253,11 @@ function runDevServer(host, port, protocol) {
|
||||
// Reportedly, this avoids CPU overload on some systems.
|
||||
// https://github.com/facebookincubator/create-react-app/issues/293
|
||||
watchOptions: {
|
||||
ignored: /node_modules/
|
||||
ignored: /node_modules/,
|
||||
},
|
||||
// Enable HTTPS if the HTTPS environment variable is set to 'true'
|
||||
https: protocol === "https",
|
||||
host: host
|
||||
https: protocol === 'https',
|
||||
host: host,
|
||||
});
|
||||
|
||||
// Our custom middleware proxies requests to /index.html or a remote API.
|
||||
@@ -241,7 +277,7 @@ function runDevServer(host, port, protocol) {
|
||||
}
|
||||
|
||||
function run(port) {
|
||||
var protocol = process.env.HTTPS === 'true' ? "https" : "http";
|
||||
var protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
var host = process.env.HOST || 'localhost';
|
||||
setupCompiler(host, port, protocol);
|
||||
runDevServer(host, port, protocol);
|
||||
|
||||
@@ -5,7 +5,7 @@ process.env.PUBLIC_URL = '';
|
||||
// if this file is missing. dotenv will never modify any environment variables
|
||||
// that have already been set.
|
||||
// https://github.com/motdotla/dotenv
|
||||
require('dotenv').config({silent: true});
|
||||
require('dotenv').config({ silent: true });
|
||||
|
||||
const jest = require('jest');
|
||||
const argv = process.argv.slice(2);
|
||||
@@ -15,5 +15,4 @@ if (!process.env.CI) {
|
||||
argv.push('--watch');
|
||||
}
|
||||
|
||||
|
||||
jest.run(argv);
|
||||
|
||||
549
packages/react-navigation/website/src/App.js
vendored
549
packages/react-navigation/website/src/App.js
vendored
@@ -15,9 +15,7 @@ import {
|
||||
createNavigator,
|
||||
} from 'react-navigation';
|
||||
|
||||
import type {
|
||||
NavigationScreenComponent,
|
||||
} from 'react-navigation';
|
||||
import type { NavigationScreenComponent } from 'react-navigation';
|
||||
|
||||
type ScreenOptions = {
|
||||
linkName: string,
|
||||
@@ -25,8 +23,8 @@ type ScreenOptions = {
|
||||
title: string,
|
||||
};
|
||||
|
||||
const NavView = ({navigation, router}) => {
|
||||
const {state} = navigation;
|
||||
const NavView = ({ navigation, router }: { navigation: any, router: any }) => {
|
||||
const { state } = navigation;
|
||||
const Component = router.getComponentForState(state);
|
||||
return (
|
||||
<Component
|
||||
@@ -45,260 +43,275 @@ type DocPageConfig = {
|
||||
};
|
||||
|
||||
const createDocPage = (
|
||||
config: DocPageConfig,
|
||||
config: DocPageConfig
|
||||
): (() => NavigationScreenComponent<*, ScreenOptions>) => {
|
||||
const Page: NavigationScreenComponent<*, ScreenOptions> = ({ navigation }) => (
|
||||
<MDPage
|
||||
docPath={config.doc}
|
||||
navigation={navigation}
|
||||
/>
|
||||
);
|
||||
const Page: NavigationScreenComponent<*, ScreenOptions> = ({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: any,
|
||||
}) => <MDPage docPath={config.doc} navigation={navigation} />;
|
||||
Page.navigationOptions = {
|
||||
doc: config.doc,
|
||||
title: config.title,
|
||||
linkName: config.linkName,
|
||||
};
|
||||
return Page;
|
||||
}
|
||||
};
|
||||
|
||||
const GuideDocs = createNavigator(TabRouter({
|
||||
GettingStarted: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Guide-Intro',
|
||||
title: 'Hello Mobile Navigation',
|
||||
linkName: 'Hello Mobile Navigation',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
NestedNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Guide-Nested',
|
||||
title: 'Nesting Navigators',
|
||||
linkName: 'Nesting Navigators',
|
||||
}),
|
||||
path: 'nesting',
|
||||
},
|
||||
ConfiguringHeaders: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Guide-Headers',
|
||||
title: 'Configuring Headers',
|
||||
linkName: 'Configuring Headers',
|
||||
}),
|
||||
path: 'headers',
|
||||
},
|
||||
}))(NavView);
|
||||
const GuideDocs = createNavigator(
|
||||
TabRouter({
|
||||
GettingStarted: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Guide-Intro',
|
||||
title: 'Hello Mobile Navigation',
|
||||
linkName: 'Hello Mobile Navigation',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
NestedNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Guide-Nested',
|
||||
title: 'Nesting Navigators',
|
||||
linkName: 'Nesting Navigators',
|
||||
}),
|
||||
path: 'nesting',
|
||||
},
|
||||
ConfiguringHeaders: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Guide-Headers',
|
||||
title: 'Configuring Headers',
|
||||
linkName: 'Configuring Headers',
|
||||
}),
|
||||
path: 'headers',
|
||||
},
|
||||
})
|
||||
)(NavView);
|
||||
|
||||
GuideDocs.navigationOptions = {
|
||||
linkName: 'Getting Started',
|
||||
icon: 'pt-icon-flows',
|
||||
};
|
||||
|
||||
const GuidesDocs = createNavigator(TabRouter({
|
||||
ReduxIntegration: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Redux-Integration',
|
||||
title: 'Redux Integration Guide',
|
||||
linkName: 'Redux Integration',
|
||||
}),
|
||||
path: 'redux',
|
||||
},
|
||||
WebIntegration: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Web-Integration',
|
||||
title: 'Web Integration Guide',
|
||||
linkName: 'Web Integration',
|
||||
}),
|
||||
path: 'web',
|
||||
},
|
||||
DeepLinking: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Deep-Linking',
|
||||
title: 'Deep Linking Guide',
|
||||
linkName: 'Deep Linking',
|
||||
}),
|
||||
path: 'linking',
|
||||
},
|
||||
ScreenTracking: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Screen-Tracking',
|
||||
title: 'Screen tracking and analytics',
|
||||
linkName: 'Screen Tracking',
|
||||
}),
|
||||
path: 'screen-tracking',
|
||||
},
|
||||
Contributors: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Contributors',
|
||||
title: 'Contributors Guide',
|
||||
linkName: 'Contributors',
|
||||
}),
|
||||
path: 'contributors',
|
||||
},
|
||||
}))(NavView);
|
||||
const GuidesDocs = createNavigator(
|
||||
TabRouter({
|
||||
ReduxIntegration: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Redux-Integration',
|
||||
title: 'Redux Integration Guide',
|
||||
linkName: 'Redux Integration',
|
||||
}),
|
||||
path: 'redux',
|
||||
},
|
||||
WebIntegration: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Web-Integration',
|
||||
title: 'Web Integration Guide',
|
||||
linkName: 'Web Integration',
|
||||
}),
|
||||
path: 'web',
|
||||
},
|
||||
DeepLinking: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Deep-Linking',
|
||||
title: 'Deep Linking Guide',
|
||||
linkName: 'Deep Linking',
|
||||
}),
|
||||
path: 'linking',
|
||||
},
|
||||
ScreenTracking: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Screen-Tracking',
|
||||
title: 'Screen tracking and analytics',
|
||||
linkName: 'Screen Tracking',
|
||||
}),
|
||||
path: 'screen-tracking',
|
||||
},
|
||||
Contributors: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Contributors',
|
||||
title: 'Contributors Guide',
|
||||
linkName: 'Contributors',
|
||||
}),
|
||||
path: 'contributors',
|
||||
},
|
||||
})
|
||||
)(NavView);
|
||||
|
||||
GuidesDocs.navigationOptions = {
|
||||
linkName: 'Advanced Guides',
|
||||
icon: 'pt-icon-manual',
|
||||
};
|
||||
|
||||
const NavigatorsDocs = createNavigator(TabRouter({
|
||||
Navigators: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/Navigators',
|
||||
title: 'Intro to Navigators',
|
||||
linkName: 'Intro to Navigators',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
StackNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/StackNavigator',
|
||||
title: 'StackNavigator',
|
||||
linkName: 'StackNavigator',
|
||||
}),
|
||||
path: 'stack',
|
||||
},
|
||||
TabNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/TabNavigator',
|
||||
title: 'TabNavigator',
|
||||
linkName: 'TabNavigator',
|
||||
}),
|
||||
path: 'tab',
|
||||
},
|
||||
DrawerNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/DrawerNavigator',
|
||||
title: 'DrawerNavigator',
|
||||
linkName: 'DrawerNavigator',
|
||||
}),
|
||||
path: 'drawer',
|
||||
},
|
||||
NavigationProp: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Screen-Navigation-Prop',
|
||||
title: 'The Navigation Prop',
|
||||
linkName: 'The Navigation Prop',
|
||||
}),
|
||||
path: 'navigation-prop',
|
||||
},
|
||||
NavigationActions: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Navigation-Actions',
|
||||
title: 'Navigation Actions',
|
||||
linkName: 'Navigation Actions',
|
||||
}),
|
||||
path: 'navigation-actions',
|
||||
},
|
||||
NavigationOptions: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Screen-Nav-Options',
|
||||
title: 'Screen Nav Options',
|
||||
linkName: 'Screen Nav Options',
|
||||
}),
|
||||
path: 'navigation-options',
|
||||
},
|
||||
Custom: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Custom-Navigators',
|
||||
title: 'Custom Navigators',
|
||||
linkName: 'Custom Navigators',
|
||||
}),
|
||||
path: 'custom',
|
||||
},
|
||||
}))(NavView);
|
||||
const NavigatorsDocs = createNavigator(
|
||||
TabRouter({
|
||||
Navigators: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/Navigators',
|
||||
title: 'Intro to Navigators',
|
||||
linkName: 'Intro to Navigators',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
StackNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/StackNavigator',
|
||||
title: 'StackNavigator',
|
||||
linkName: 'StackNavigator',
|
||||
}),
|
||||
path: 'stack',
|
||||
},
|
||||
TabNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/TabNavigator',
|
||||
title: 'TabNavigator',
|
||||
linkName: 'TabNavigator',
|
||||
}),
|
||||
path: 'tab',
|
||||
},
|
||||
DrawerNavigator: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/navigators/DrawerNavigator',
|
||||
title: 'DrawerNavigator',
|
||||
linkName: 'DrawerNavigator',
|
||||
}),
|
||||
path: 'drawer',
|
||||
},
|
||||
NavigationProp: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Screen-Navigation-Prop',
|
||||
title: 'The Navigation Prop',
|
||||
linkName: 'The Navigation Prop',
|
||||
}),
|
||||
path: 'navigation-prop',
|
||||
},
|
||||
NavigationActions: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Navigation-Actions',
|
||||
title: 'Navigation Actions',
|
||||
linkName: 'Navigation Actions',
|
||||
}),
|
||||
path: 'navigation-actions',
|
||||
},
|
||||
NavigationOptions: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Screen-Nav-Options',
|
||||
title: 'Screen Nav Options',
|
||||
linkName: 'Screen Nav Options',
|
||||
}),
|
||||
path: 'navigation-options',
|
||||
},
|
||||
Custom: {
|
||||
screen: createDocPage({
|
||||
doc: 'guides/Custom-Navigators',
|
||||
title: 'Custom Navigators',
|
||||
linkName: 'Custom Navigators',
|
||||
}),
|
||||
path: 'custom',
|
||||
},
|
||||
})
|
||||
)(NavView);
|
||||
|
||||
NavigatorsDocs.navigationOptions = {
|
||||
linkName: 'Navigators',
|
||||
icon: 'pt-icon-briefcase',
|
||||
};
|
||||
|
||||
const RoutersDocs = createNavigator(TabRouter({
|
||||
Routers: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/Routers',
|
||||
title: 'Routers',
|
||||
linkName: 'Routers',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
RoutersAPI: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/RoutersAPI',
|
||||
title: 'Router API',
|
||||
linkName: 'Custom Router API',
|
||||
}),
|
||||
path: 'api',
|
||||
},
|
||||
StackRouter: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/StackRouter',
|
||||
title: 'StackRouter',
|
||||
linkName: 'StackRouter',
|
||||
}),
|
||||
path: 'stack',
|
||||
},
|
||||
TabRouter: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/TabRouter',
|
||||
title: 'TabRouter',
|
||||
linkName: 'TabRouter',
|
||||
}),
|
||||
path: 'tab',
|
||||
},
|
||||
}))(NavView);
|
||||
const RoutersDocs = createNavigator(
|
||||
TabRouter({
|
||||
Routers: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/Routers',
|
||||
title: 'Routers',
|
||||
linkName: 'Routers',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
RoutersAPI: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/RoutersAPI',
|
||||
title: 'Router API',
|
||||
linkName: 'Custom Router API',
|
||||
}),
|
||||
path: 'api',
|
||||
},
|
||||
StackRouter: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/StackRouter',
|
||||
title: 'StackRouter',
|
||||
linkName: 'StackRouter',
|
||||
}),
|
||||
path: 'stack',
|
||||
},
|
||||
TabRouter: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/routers/TabRouter',
|
||||
title: 'TabRouter',
|
||||
linkName: 'TabRouter',
|
||||
}),
|
||||
path: 'tab',
|
||||
},
|
||||
})
|
||||
)(NavView);
|
||||
|
||||
RoutersDocs.navigationOptions = {
|
||||
linkName: 'Routers',
|
||||
icon: 'pt-icon-fork',
|
||||
};
|
||||
|
||||
const ViewsDocs = createNavigator(TabRouter({
|
||||
Views: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/views/Views',
|
||||
title: 'Views',
|
||||
linkName: 'Navigation Views',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
TransitionerView: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/views/Transitioner',
|
||||
title: 'Transitioner',
|
||||
linkName: 'Transitioner',
|
||||
}),
|
||||
path: 'transitioner',
|
||||
},
|
||||
}))(NavView);
|
||||
const ViewsDocs = createNavigator(
|
||||
TabRouter({
|
||||
Views: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/views/Views',
|
||||
title: 'Views',
|
||||
linkName: 'Navigation Views',
|
||||
}),
|
||||
path: '',
|
||||
},
|
||||
TransitionerView: {
|
||||
screen: createDocPage({
|
||||
doc: 'api/views/Transitioner',
|
||||
title: 'Transitioner',
|
||||
linkName: 'Transitioner',
|
||||
}),
|
||||
path: 'transitioner',
|
||||
},
|
||||
})
|
||||
)(NavView);
|
||||
ViewsDocs.navigationOptions = {
|
||||
linkName: 'Views',
|
||||
icon: 'pt-icon-eye-open',
|
||||
};
|
||||
|
||||
const DocsPage = createNavigator(TabRouter({
|
||||
GuideDocs: {
|
||||
screen: GuideDocs,
|
||||
path: 'intro',
|
||||
},
|
||||
NavigatorsTab: {
|
||||
screen: NavigatorsDocs,
|
||||
path: 'navigators',
|
||||
},
|
||||
GuidesTab: {
|
||||
screen: GuidesDocs,
|
||||
path: 'guides',
|
||||
},
|
||||
RoutersTab: {
|
||||
screen: RoutersDocs,
|
||||
path: 'routers',
|
||||
},
|
||||
ViewsTab: {
|
||||
screen: ViewsDocs,
|
||||
path: 'views',
|
||||
},
|
||||
}))(PageWithSidebar);
|
||||
DocsPage.navigationOptions = ({ navigationOptions }) => ({
|
||||
const DocsPage = createNavigator(
|
||||
TabRouter({
|
||||
GuideDocs: {
|
||||
screen: GuideDocs,
|
||||
path: 'intro',
|
||||
},
|
||||
NavigatorsTab: {
|
||||
screen: NavigatorsDocs,
|
||||
path: 'navigators',
|
||||
},
|
||||
GuidesTab: {
|
||||
screen: GuidesDocs,
|
||||
path: 'guides',
|
||||
},
|
||||
RoutersTab: {
|
||||
screen: RoutersDocs,
|
||||
path: 'routers',
|
||||
},
|
||||
ViewsTab: {
|
||||
screen: ViewsDocs,
|
||||
path: 'views',
|
||||
},
|
||||
})
|
||||
)(PageWithSidebar);
|
||||
DocsPage.navigationOptions = ({
|
||||
navigationOptions,
|
||||
}: {
|
||||
navigationOptions: any,
|
||||
}) => ({
|
||||
title: `${navigationOptions.title} | React Navigation`,
|
||||
});
|
||||
|
||||
@@ -308,35 +321,39 @@ IntroPost.navigationOptions = {
|
||||
linkName: 'Introduction',
|
||||
};
|
||||
|
||||
const BlogHistoryPage = createNavigator(TabRouter({
|
||||
RoadToV1: {
|
||||
screen: createDocPage({
|
||||
doc: 'blog/2017-04-On-the-path-to-v1',
|
||||
title: 'On the path to v1',
|
||||
linkName: 'On the path to v1',
|
||||
}),
|
||||
path: '2017/4/On-the-path-to-v1',
|
||||
},
|
||||
IntroPost: {
|
||||
screen: createDocPage({
|
||||
doc: 'blog/2017-01-Introducing-React-Navigation',
|
||||
title: 'Introducing React Navigation for React Native',
|
||||
linkName: 'React Navigation Intro',
|
||||
}),
|
||||
path: '2017/1/Introducing-React-Navigation',
|
||||
},
|
||||
}))(PageWithSidebar);
|
||||
const BlogHistoryPage = createNavigator(
|
||||
TabRouter({
|
||||
RoadToV1: {
|
||||
screen: createDocPage({
|
||||
doc: 'blog/2017-04-On-the-path-to-v1',
|
||||
title: 'On the path to v1',
|
||||
linkName: 'On the path to v1',
|
||||
}),
|
||||
path: '2017/4/On-the-path-to-v1',
|
||||
},
|
||||
IntroPost: {
|
||||
screen: createDocPage({
|
||||
doc: 'blog/2017-01-Introducing-React-Navigation',
|
||||
title: 'Introducing React Navigation for React Native',
|
||||
linkName: 'React Navigation Intro',
|
||||
}),
|
||||
path: '2017/1/Introducing-React-Navigation',
|
||||
},
|
||||
})
|
||||
)(PageWithSidebar);
|
||||
BlogHistoryPage.navigationOptions = {
|
||||
linkName: 'Recent Posts',
|
||||
icon: 'pt-icon-history',
|
||||
};
|
||||
|
||||
const BlogPage = createNavigator(TabRouter({
|
||||
HistoryTab: {
|
||||
screen: BlogHistoryPage,
|
||||
path: '',
|
||||
},
|
||||
}))(PageWithSidebar);
|
||||
const BlogPage = createNavigator(
|
||||
TabRouter({
|
||||
HistoryTab: {
|
||||
screen: BlogHistoryPage,
|
||||
path: '',
|
||||
},
|
||||
})
|
||||
)(PageWithSidebar);
|
||||
|
||||
const NotFoundError = () => (
|
||||
<div className="errorScreen">
|
||||
@@ -344,25 +361,27 @@ const NotFoundError = () => (
|
||||
</div>
|
||||
);
|
||||
|
||||
const App = createNavigator(TabRouter({
|
||||
Home: {
|
||||
screen: HomePage,
|
||||
path: '',
|
||||
},
|
||||
Docs: {
|
||||
screen: DocsPage,
|
||||
path: 'docs',
|
||||
},
|
||||
Blog: {
|
||||
screen: BlogPage,
|
||||
path: 'blog',
|
||||
},
|
||||
NotFound: {
|
||||
screen: NotFoundError,
|
||||
navigationOptions: {
|
||||
title: 'Page Not Found | React Navigation',
|
||||
const App = createNavigator(
|
||||
TabRouter({
|
||||
Home: {
|
||||
screen: HomePage,
|
||||
path: '',
|
||||
},
|
||||
},
|
||||
}))(AppFrame);
|
||||
Docs: {
|
||||
screen: DocsPage,
|
||||
path: 'docs',
|
||||
},
|
||||
Blog: {
|
||||
screen: BlogPage,
|
||||
path: 'blog',
|
||||
},
|
||||
NotFound: {
|
||||
screen: NotFoundError,
|
||||
navigationOptions: {
|
||||
title: 'Page Not Found | React Navigation',
|
||||
},
|
||||
},
|
||||
})
|
||||
)(AppFrame);
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -2,11 +2,9 @@ import React from 'react';
|
||||
|
||||
import Link from './Link';
|
||||
import Footer from './Footer';
|
||||
import {
|
||||
addNavigationHelpers,
|
||||
} from 'react-navigation';
|
||||
import { addNavigationHelpers } from 'react-navigation';
|
||||
|
||||
const NavigationLinks = ({navigation, className, reverse}) => {
|
||||
const NavigationLinks = ({ navigation, className, reverse }) => {
|
||||
let links = [
|
||||
...navigation.state.routes.map((route, i) => {
|
||||
if (route.routeName === 'Home' || route.routeName === 'NotFound') {
|
||||
@@ -15,8 +13,9 @@ const NavigationLinks = ({navigation, className, reverse}) => {
|
||||
return (
|
||||
<Link
|
||||
to={route.routeName}
|
||||
className={i === navigation.state.index ? 'active':''}
|
||||
key={route.routeName}>
|
||||
className={i === navigation.state.index ? 'active' : ''}
|
||||
key={route.routeName}
|
||||
>
|
||||
{route.routeName}
|
||||
</Link>
|
||||
);
|
||||
@@ -34,55 +33,71 @@ const NavigationLinks = ({navigation, className, reverse}) => {
|
||||
{links}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class AppFrame extends React.Component {
|
||||
state = {isMobileMenuOpen: false};
|
||||
state = { isMobileMenuOpen: false };
|
||||
componentWillReceiveProps(props) {
|
||||
if (this.props.navigation.state !== props.navigation.state) {
|
||||
this.setState({isMobileMenuOpen: false});
|
||||
window.scrollTo(0,0);
|
||||
this.setState({ isMobileMenuOpen: false });
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const {navigation, router} = this.props;
|
||||
const {isMobileMenuOpen} = this.state;
|
||||
const { navigation, router } = this.props;
|
||||
const { isMobileMenuOpen } = this.state;
|
||||
const childNavigation = addNavigationHelpers({
|
||||
...navigation,
|
||||
state: navigation.state.routes[navigation.state.index],
|
||||
});
|
||||
const {state} = navigation;
|
||||
const ScreenView = router.getComponentForRouteName(state.routes[state.index].routeName);
|
||||
const {routes, index} = state;
|
||||
const { state } = navigation;
|
||||
const ScreenView = router.getComponentForRouteName(
|
||||
state.routes[state.index].routeName
|
||||
);
|
||||
const { routes, index } = state;
|
||||
const route = routes[index];
|
||||
const hasChildNavigation = !!route.routes;
|
||||
return (
|
||||
<div className={`main-app ${isMobileMenuOpen ? 'mobileMenuActive' : ''}`}>
|
||||
|
||||
<nav className="pt-navbar" id="navbar"><div className="inner-navbar">
|
||||
<nav className="pt-navbar" id="navbar">
|
||||
<div className="inner-navbar">
|
||||
|
||||
<Link className="pt-navbar-group pt-align-left project-title" to="Home">
|
||||
<img src="/assets/react-nav-logo.svg" role="presentation" className="logo" />
|
||||
<h1 className="pt-navbar-heading">
|
||||
React Navigation
|
||||
</h1>
|
||||
</Link>
|
||||
<Link
|
||||
className="pt-navbar-group pt-align-left project-title"
|
||||
to="Home"
|
||||
>
|
||||
<img
|
||||
src="/assets/react-nav-logo.svg"
|
||||
role="presentation"
|
||||
className="logo"
|
||||
/>
|
||||
<h1 className="pt-navbar-heading">
|
||||
React Navigation
|
||||
</h1>
|
||||
</Link>
|
||||
|
||||
<NavigationLinks navigation={navigation} className="navbuttons" />
|
||||
<NavigationLinks navigation={navigation} className="navbuttons" />
|
||||
|
||||
{hasChildNavigation && (
|
||||
<span
|
||||
className={`pt-icon-properties openMenuButton ${isMobileMenuOpen ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
this.setState(s => ({ isMobileMenuOpen: !s.isMobileMenuOpen}));
|
||||
window.scrollTo(0,0);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{hasChildNavigation &&
|
||||
<span
|
||||
className={`pt-icon-properties openMenuButton ${isMobileMenuOpen ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
this.setState(s => ({
|
||||
isMobileMenuOpen: !s.isMobileMenuOpen,
|
||||
}));
|
||||
window.scrollTo(0, 0);
|
||||
}}
|
||||
/>}
|
||||
|
||||
</div></nav>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<NavigationLinks navigation={navigation} className="mobile-navbuttons" reverse />
|
||||
<NavigationLinks
|
||||
navigation={navigation}
|
||||
className="mobile-navbuttons"
|
||||
reverse
|
||||
/>
|
||||
|
||||
<ScreenView navigation={childNavigation} />
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { NavigationActions, addNavigationHelpers } from 'react-navigation';
|
||||
|
||||
@@ -14,43 +14,69 @@ function getAction(router, path, params) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = (NavigationAwareView) => {
|
||||
const initialAction = getAction(NavigationAwareView.router, window.location.pathname.substr(1));
|
||||
const initialState = NavigationAwareView.router.getStateForAction(initialAction);
|
||||
console.log({initialAction, initialState});
|
||||
export default NavigationAwareView => {
|
||||
const initialAction = getAction(
|
||||
NavigationAwareView.router,
|
||||
window.location.pathname.substr(1)
|
||||
);
|
||||
const initialState = NavigationAwareView.router.getStateForAction(
|
||||
initialAction
|
||||
);
|
||||
console.log({ initialAction, initialState });
|
||||
|
||||
class NavigationContainer extends React.Component {
|
||||
state = initialState;
|
||||
componentDidMount() {
|
||||
const navigation = addNavigationHelpers({state: this.state.routes[this.state.index], dispatch: this.dispatch});
|
||||
document.title = NavigationAwareView.router.getScreenOptions(navigation).title;
|
||||
window.onpopstate = (e) => {
|
||||
const navigation = addNavigationHelpers({
|
||||
state: this.state.routes[this.state.index],
|
||||
dispatch: this.dispatch,
|
||||
});
|
||||
document.title = NavigationAwareView.router.getScreenOptions(
|
||||
navigation
|
||||
).title;
|
||||
window.onpopstate = e => {
|
||||
e.preventDefault();
|
||||
const action = getAction(NavigationAwareView.router, window.location.pathname.substr(1));
|
||||
const action = getAction(
|
||||
NavigationAwareView.router,
|
||||
window.location.pathname.substr(1)
|
||||
);
|
||||
if (action) this.dispatch(action);
|
||||
};
|
||||
}
|
||||
componentWillUpdate(props, state) {
|
||||
const {path, params} = NavigationAwareView.router.getPathAndParamsForState(state);
|
||||
const {
|
||||
path,
|
||||
params,
|
||||
} = NavigationAwareView.router.getPathAndParamsForState(state);
|
||||
const maybeHash = params && params.hash ? `#${params.hash}` : '';
|
||||
const uri = `/${path}${maybeHash}`;
|
||||
if (window.location.pathname !== uri) {
|
||||
window.history.pushState({}, state.title, uri);
|
||||
}
|
||||
const navigation = addNavigationHelpers({state: state.routes[state.index], dispatch: this.dispatch});
|
||||
document.title = NavigationAwareView.router.getScreenOptions(navigation).title;
|
||||
const navigation = addNavigationHelpers({
|
||||
state: state.routes[state.index],
|
||||
dispatch: this.dispatch,
|
||||
});
|
||||
document.title = NavigationAwareView.router.getScreenOptions(
|
||||
navigation
|
||||
).title;
|
||||
}
|
||||
componentDidUpdate() {
|
||||
const {params} = NavigationAwareView.router.getPathAndParamsForState(this.state);
|
||||
const { params } = NavigationAwareView.router.getPathAndParamsForState(
|
||||
this.state
|
||||
);
|
||||
if (params && params.hash) {
|
||||
document.getElementById(params.hash).scrollIntoView();
|
||||
}
|
||||
}
|
||||
dispatch = (action) => {
|
||||
const state = NavigationAwareView.router.getStateForAction(action, this.state);
|
||||
dispatch = action => {
|
||||
const state = NavigationAwareView.router.getStateForAction(
|
||||
action,
|
||||
this.state
|
||||
);
|
||||
|
||||
if (!state) {
|
||||
console.log('Dispatched action did not change state: ', {action});
|
||||
console.log('Dispatched action did not change state: ', { action });
|
||||
} else if (console.group) {
|
||||
console.group('Navigation Dispatch: ');
|
||||
console.log('Action: ', action);
|
||||
@@ -58,7 +84,11 @@ module.exports = (NavigationAwareView) => {
|
||||
console.log('Last State: ', this.state);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.log('Navigation Dispatch: ', {action, newState: state, lastState: this.state});
|
||||
console.log('Navigation Dispatch: ', {
|
||||
action,
|
||||
newState: state,
|
||||
lastState: this.state,
|
||||
});
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
@@ -72,20 +102,31 @@ module.exports = (NavigationAwareView) => {
|
||||
return false;
|
||||
};
|
||||
render() {
|
||||
return <NavigationAwareView navigation={addNavigationHelpers({state: this.state, dispatch: this.dispatch})} />
|
||||
return (
|
||||
<NavigationAwareView
|
||||
navigation={addNavigationHelpers({
|
||||
state: this.state,
|
||||
dispatch: this.dispatch,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
getURIForAction = (action) => {
|
||||
const state = NavigationAwareView.router.getStateForAction(action, this.state) || this.state;
|
||||
const {path} = NavigationAwareView.router.getPathAndParamsForState(state);
|
||||
getURIForAction = action => {
|
||||
const state =
|
||||
NavigationAwareView.router.getStateForAction(action, this.state) ||
|
||||
this.state;
|
||||
const { path } = NavigationAwareView.router.getPathAndParamsForState(
|
||||
state
|
||||
);
|
||||
return `/${path}`;
|
||||
}
|
||||
};
|
||||
getActionForPathAndParams = (path, params) => {
|
||||
return NavigationAwareView.router.getActionForPathAndParams(path, params);
|
||||
}
|
||||
};
|
||||
static childContextTypes = {
|
||||
getActionForPathAndParams: React.PropTypes.func.isRequired,
|
||||
getURIForAction: React.PropTypes.func.isRequired,
|
||||
dispatch: React.PropTypes.func.isRequired,
|
||||
getActionForPathAndParams: PropTypes.func.isRequired,
|
||||
getURIForAction: PropTypes.func.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
};
|
||||
getChildContext() {
|
||||
return {
|
||||
|
||||
24
packages/react-navigation/website/src/Footer.js
vendored
24
packages/react-navigation/website/src/Footer.js
vendored
@@ -1,19 +1,21 @@
|
||||
import React from 'react';
|
||||
|
||||
const Footer = () => (
|
||||
<div className="footer"><div className="inner-footer">
|
||||
<div className="footer">
|
||||
<div className="inner-footer">
|
||||
|
||||
<section className="copyright">
|
||||
<a href="https://github.com/react-community/react-navigation">
|
||||
React Navigation
|
||||
</a>
|
||||
·
|
||||
<a href="https://github.com/react-community/react-navigation/blob/master/LICENSE">
|
||||
Distributed under BSD License
|
||||
</a>
|
||||
</section>
|
||||
<section className="copyright">
|
||||
<a href="https://github.com/react-community/react-navigation">
|
||||
React Navigation
|
||||
</a>
|
||||
·
|
||||
<a href="https://github.com/react-community/react-navigation/blob/master/LICENSE">
|
||||
Distributed under BSD License
|
||||
</a>
|
||||
</section>
|
||||
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Footer;
|
||||
|
||||
102
packages/react-navigation/website/src/HomePage.js
vendored
102
packages/react-navigation/website/src/HomePage.js
vendored
@@ -10,7 +10,7 @@ const GettingStartedButton = () => (
|
||||
<div className="cta-row">
|
||||
<Link className="cta" to="GettingStarted">
|
||||
<span className="label">Get Started</span>
|
||||
<span className="icon pt-icon-arrow-right"></span>
|
||||
<span className="icon pt-icon-arrow-right" />
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
@@ -20,7 +20,7 @@ const ExampleCodeBrowser = (config, ExampleFiles) => {
|
||||
class CodeBrowser extends Component {
|
||||
state = { index: 0 };
|
||||
render() {
|
||||
const {index} = this.state;
|
||||
const { index } = this.state;
|
||||
return (
|
||||
<div className={this.props.alt ? 'code-example alt' : 'code-example'}>
|
||||
<div className="code-example-section">
|
||||
@@ -31,7 +31,8 @@ const ExampleCodeBrowser = (config, ExampleFiles) => {
|
||||
<a
|
||||
key={fileName}
|
||||
className={index === i ? 'active' : ''}
|
||||
onClick={() => this.setState({ index: i })}>
|
||||
onClick={() => this.setState({ index: i })}
|
||||
>
|
||||
{fileName}
|
||||
</a>
|
||||
);
|
||||
@@ -39,10 +40,7 @@ const ExampleCodeBrowser = (config, ExampleFiles) => {
|
||||
</div>
|
||||
<CodeBlock code={ExampleFiles[fileNames[index]]} />
|
||||
</div>
|
||||
<PhoneGraphic
|
||||
sources={config.examples}
|
||||
alt={this.props.alt}
|
||||
/>
|
||||
<PhoneGraphic sources={config.examples} alt={this.props.alt} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -51,14 +49,16 @@ const ExampleCodeBrowser = (config, ExampleFiles) => {
|
||||
return CodeBrowser;
|
||||
};
|
||||
|
||||
const StackExampleBrowser = ExampleCodeBrowser({
|
||||
title: 'Stack Navigator',
|
||||
examples: {
|
||||
iphone: '/assets/iphone-stack.gif',
|
||||
android: '/assets/android-stack.gif',
|
||||
const StackExampleBrowser = ExampleCodeBrowser(
|
||||
{
|
||||
title: 'Stack Navigator',
|
||||
examples: {
|
||||
iphone: '/assets/iphone-stack.gif',
|
||||
android: '/assets/android-stack.gif',
|
||||
},
|
||||
},
|
||||
}, {
|
||||
'BasicApp.js': `\
|
||||
{
|
||||
'BasicApp.js': `\
|
||||
import {
|
||||
StackNavigator,
|
||||
} from 'react-navigation';
|
||||
@@ -68,7 +68,7 @@ const BasicApp = StackNavigator({
|
||||
Profile: {screen: ProfileScreen},
|
||||
});
|
||||
`,
|
||||
'MainScreen.js': `\
|
||||
'MainScreen.js': `\
|
||||
class MainScreen extends React.Component {
|
||||
static navigationOptions = {
|
||||
title: 'Welcome',
|
||||
@@ -85,7 +85,7 @@ class MainScreen extends React.Component {
|
||||
);
|
||||
}
|
||||
}`,
|
||||
'ProfileScreen.js': `\
|
||||
'ProfileScreen.js': `\
|
||||
class ProfileScreen extends React.Component {
|
||||
static navigationOptions = ({navigation}) => ({
|
||||
title: navigation.state.params.name,
|
||||
@@ -100,16 +100,19 @@ class ProfileScreen extends React.Component {
|
||||
);
|
||||
}
|
||||
}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const TabExampleBrowser = ExampleCodeBrowser({
|
||||
title: 'Tab Navigator',
|
||||
examples: {
|
||||
iphone: '/assets/iphone-tabs.gif',
|
||||
android: '/assets/android-tabs.gif',
|
||||
const TabExampleBrowser = ExampleCodeBrowser(
|
||||
{
|
||||
title: 'Tab Navigator',
|
||||
examples: {
|
||||
iphone: '/assets/iphone-tabs.gif',
|
||||
android: '/assets/android-tabs.gif',
|
||||
},
|
||||
},
|
||||
}, {
|
||||
'BasicApp.js': `\
|
||||
{
|
||||
'BasicApp.js': `\
|
||||
import {
|
||||
TabNavigator,
|
||||
} from 'react-navigation';
|
||||
@@ -119,7 +122,7 @@ const BasicApp = TabNavigator({
|
||||
Setup: {screen: SetupScreen},
|
||||
});
|
||||
`,
|
||||
'MainScreen.js': `\
|
||||
'MainScreen.js': `\
|
||||
class MainScreen extends React.Component {
|
||||
static navigationOptions = {
|
||||
tabBarLabel: 'Home',
|
||||
@@ -134,7 +137,7 @@ class MainScreen extends React.Component {
|
||||
);
|
||||
}
|
||||
}`,
|
||||
'SetupScreen.js': `\
|
||||
'SetupScreen.js': `\
|
||||
class SetupScreen extends React.Component {
|
||||
static navigationOptions = {
|
||||
tabBarLabel: 'Setup',
|
||||
@@ -149,7 +152,8 @@ class SetupScreen extends React.Component {
|
||||
);
|
||||
}
|
||||
}`,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
class HomePage extends Component {
|
||||
static navigationOptions = {
|
||||
@@ -164,35 +168,47 @@ class HomePage extends Component {
|
||||
<div className="hero">
|
||||
<h1>Navigation for React Native</h1>
|
||||
<div className="video">
|
||||
<iframe src="https://player.vimeo.com/video/201061589" width="720" height="410" frameBorder="0" allowFullScreen></iframe>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/201061589"
|
||||
width="720"
|
||||
height="410"
|
||||
frameBorder="0"
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
<GettingStartedButton />
|
||||
</div>
|
||||
|
||||
<div className="section">
|
||||
<div className="section-inner">
|
||||
<h1>Easy-to-Use Navigators</h1>
|
||||
<h3>Start quickly with built-in navigators that deliver a seamless out-of-the box experience.</h3>
|
||||
<div className="section-inner">
|
||||
<h1>Easy-to-Use Navigators</h1>
|
||||
<h3>
|
||||
Start quickly with built-in navigators that deliver a seamless out-of-the box experience.
|
||||
</h3>
|
||||
|
||||
<StackExampleBrowser />
|
||||
</div>
|
||||
<StackExampleBrowser />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="section alt">
|
||||
<div className="section-inner">
|
||||
<h1>Components built for iOS and Android</h1>
|
||||
<h3>Navigation views that deliver 60fps animations, and utilize native components to deliver a great look and feel.</h3>
|
||||
<div className="section-inner">
|
||||
<h1>Components built for iOS and Android</h1>
|
||||
<h3>
|
||||
Navigation views that deliver 60fps animations, and utilize native components to deliver a great look and feel.
|
||||
</h3>
|
||||
|
||||
<TabExampleBrowser alt />
|
||||
</div>
|
||||
<TabExampleBrowser alt />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="section">
|
||||
<div className="section-inner">
|
||||
<h1>Routers built for the future</h1>
|
||||
<h3>Routers define the relationship between URIs, actions, and navigation state. Share navigation logic between mobile apps, web apps, and server rendering.</h3>
|
||||
<GettingStartedButton />
|
||||
</div>
|
||||
<div className="section-inner">
|
||||
<h1>Routers built for the future</h1>
|
||||
<h3>
|
||||
Routers define the relationship between URIs, actions, and navigation state. Share navigation logic between mobile apps, web apps, and server rendering.
|
||||
</h3>
|
||||
<GettingStartedButton />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Footer />
|
||||
|
||||
21
packages/react-navigation/website/src/Link.js
vendored
21
packages/react-navigation/website/src/Link.js
vendored
@@ -1,22 +1,19 @@
|
||||
import React, { PropTypes, Component } from 'react';
|
||||
import { NavigationActions } from 'react-navigation'
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { NavigationActions } from 'react-navigation';
|
||||
|
||||
const isModifiedEvent = (event) =>
|
||||
const isModifiedEvent = event =>
|
||||
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
||||
|
||||
const Linkable = (Inner) => {
|
||||
const Linkable = Inner => {
|
||||
class LinkableWrapped extends Component {
|
||||
render() {
|
||||
return (
|
||||
<Inner
|
||||
href={this.getURL()}
|
||||
onClick={this.onClick}
|
||||
{...this.props}
|
||||
/>
|
||||
<Inner href={this.getURL()} onClick={this.onClick} {...this.props} />
|
||||
);
|
||||
}
|
||||
getAction = () => {
|
||||
const {to, href} = this.props;
|
||||
const { to, href } = this.props;
|
||||
if (typeof to === 'string') {
|
||||
return NavigationActions.navigate({ routeName: to });
|
||||
} else if (typeof to === 'object' && typeof to.type === 'string') {
|
||||
@@ -35,7 +32,7 @@ const Linkable = (Inner) => {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
onClick = e => {
|
||||
const action = this.getAction();
|
||||
if (!isModifiedEvent(e) && action) {
|
||||
@@ -55,7 +52,7 @@ const Linkable = (Inner) => {
|
||||
};
|
||||
}
|
||||
return LinkableWrapped;
|
||||
}
|
||||
};
|
||||
|
||||
const Link = Linkable(props => <a {...props} />);
|
||||
|
||||
|
||||
46
packages/react-navigation/website/src/MDPage.js
vendored
46
packages/react-navigation/website/src/MDPage.js
vendored
@@ -1,4 +1,3 @@
|
||||
|
||||
import React from 'react';
|
||||
const Markdown = require('react-markdown');
|
||||
const DocsMD = require('../docs-dist.json');
|
||||
@@ -7,9 +6,14 @@ import PhoneGraphic from './PhoneGraphic';
|
||||
const slugify = require('slugify');
|
||||
import CodeBlock from './CodeBlock';
|
||||
|
||||
const safeString = s => slugify(s).replace(/\)/g, '-').replace(/\(/g, '-').replace(/^-/,'').replace(/-$/,'');
|
||||
const safeString = s =>
|
||||
slugify(s)
|
||||
.replace(/\)/g, '-')
|
||||
.replace(/\(/g, '-')
|
||||
.replace(/^-/, '')
|
||||
.replace(/-$/, '');
|
||||
|
||||
const getHeadingForLevel = (level) => {
|
||||
const getHeadingForLevel = level => {
|
||||
switch (level) {
|
||||
case 2:
|
||||
return 'h2';
|
||||
@@ -29,12 +33,12 @@ const getHeadingForLevel = (level) => {
|
||||
}
|
||||
};
|
||||
|
||||
const MDPage = ({navigation, docPath}) => (
|
||||
const MDPage = ({ navigation, docPath }) => (
|
||||
<Markdown
|
||||
source={DocsMD[docPath]}
|
||||
className="md-section"
|
||||
renderers={{
|
||||
CodeBlock: ({literal, language}) => {
|
||||
CodeBlock: function CodeBlock({ literal, language }) {
|
||||
if (language === 'phone-example') {
|
||||
const graphicName = literal.trim();
|
||||
return (
|
||||
@@ -47,18 +51,18 @@ const MDPage = ({navigation, docPath}) => (
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<CodeBlock code={literal} />
|
||||
);
|
||||
return <CodeBlock code={literal} />;
|
||||
},
|
||||
Heading: ({level, children}) => {
|
||||
let id = React.Children.map(children, (child) => {
|
||||
if (typeof child === 'string') {
|
||||
return safeString(child);
|
||||
} else if (typeof child.props.children === 'string') {
|
||||
return safeString(child.props.children);
|
||||
}
|
||||
}).join('-');
|
||||
Heading: function Heading({ level, children }) {
|
||||
let id = React.Children
|
||||
.map(children, child => {
|
||||
if (typeof child === 'string') {
|
||||
return safeString(child);
|
||||
} else if (typeof child.props.children === 'string') {
|
||||
return safeString(child.props.children);
|
||||
}
|
||||
})
|
||||
.join('-');
|
||||
const Header = getHeadingForLevel(level);
|
||||
return (
|
||||
<Header id={id} className="md-header">
|
||||
@@ -66,17 +70,11 @@ const MDPage = ({navigation, docPath}) => (
|
||||
</Header>
|
||||
);
|
||||
},
|
||||
link: ({children, href}) => {
|
||||
link: function link({ children, href }) {
|
||||
if (href.indexOf('PhoneGraphic:') === 0) {
|
||||
const graphicName = href.split('PhoneGraphic:')[1];
|
||||
|
||||
}
|
||||
return (
|
||||
<Link
|
||||
children={children}
|
||||
href={href}
|
||||
/>
|
||||
);
|
||||
return <Link href={href}>{children}</Link>;
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
import Link from "./Link";
|
||||
import Link from './Link';
|
||||
|
||||
import { NavigationActions, addNavigationHelpers } from 'react-navigation';
|
||||
|
||||
@@ -16,8 +16,8 @@ function getConfig(router, state, action, configName) {
|
||||
|
||||
class PageWithSidebar extends Component {
|
||||
render() {
|
||||
const {router, navigation} = this.props;
|
||||
const {dispatch, state} = navigation;
|
||||
const { router, navigation } = this.props;
|
||||
const { dispatch, state } = navigation;
|
||||
const ActiveScreen = router.getComponentForState(state);
|
||||
let prevAction = null;
|
||||
if (state.routes[state.index].index > 0) {
|
||||
@@ -31,12 +31,17 @@ class PageWithSidebar extends Component {
|
||||
prevAction = NavigationActions.navigate({
|
||||
routeName: state.routes[prev].routeName,
|
||||
action: NavigationActions.navigate({
|
||||
routeName: state.routes[prev].routes[state.routes[prev].routes.length - 1].routeName,
|
||||
})
|
||||
routeName: state.routes[prev].routes[
|
||||
state.routes[prev].routes.length - 1
|
||||
].routeName,
|
||||
}),
|
||||
});
|
||||
}
|
||||
let nextAction = null;
|
||||
if (state.routes[state.index].index < state.routes[state.index].routes.length - 1) {
|
||||
if (
|
||||
state.routes[state.index].index <
|
||||
state.routes[state.index].routes.length - 1
|
||||
) {
|
||||
const next = state.routes[state.index].index + 1;
|
||||
nextAction = NavigationActions.navigate({
|
||||
routeName: state.routes[state.index].routes[next].routeName,
|
||||
@@ -48,64 +53,96 @@ class PageWithSidebar extends Component {
|
||||
routeName: state.routes[next].routeName,
|
||||
});
|
||||
}
|
||||
let prevName = prevAction && getConfig(router, state, prevAction, 'linkName');
|
||||
let nextName = nextAction && getConfig(router, state, nextAction, 'linkName');
|
||||
const docPath = getConfig(router, state, null, 'doc')+'.md';
|
||||
let prevName =
|
||||
prevAction && getConfig(router, state, prevAction, 'linkName');
|
||||
let nextName =
|
||||
nextAction && getConfig(router, state, nextAction, 'linkName');
|
||||
const docPath = getConfig(router, state, null, 'doc') + '.md';
|
||||
return (
|
||||
<div className="page-body"><div className="inner-page-body">
|
||||
<div className="page-body">
|
||||
<div className="inner-page-body">
|
||||
|
||||
<div className="left-sidebar">
|
||||
<ul className="pt-menu pt-elevation-1 navmenu">
|
||||
{state.routes &&
|
||||
state.routes.map((route, i) => {
|
||||
const DocComponent = router.getComponentForRouteName(
|
||||
route.routeName
|
||||
);
|
||||
const childNavigation = addNavigationHelpers({
|
||||
state: route,
|
||||
dispatch,
|
||||
});
|
||||
const options = router.getScreenOptions(childNavigation, {});
|
||||
const isActive = state.index === i;
|
||||
return (
|
||||
<span key={i}>
|
||||
<LinkableLi
|
||||
to={route.routeName}
|
||||
className={
|
||||
'pt-menu-header ' +
|
||||
options.icon +
|
||||
' ' +
|
||||
(isActive ? 'active' : '')
|
||||
}
|
||||
>
|
||||
<h6>{options.linkName}</h6>
|
||||
</LinkableLi>
|
||||
<div>
|
||||
{route.routes &&
|
||||
route.routes.map((childRoute, childI) => {
|
||||
const isChildActive =
|
||||
isActive && route.index === childI;
|
||||
const secondChildNavigation = addNavigationHelpers({
|
||||
state: childRoute,
|
||||
dispatch,
|
||||
});
|
||||
const secondOptions =
|
||||
DocComponent.router &&
|
||||
DocComponent.router.getScreenOptions(
|
||||
secondChildNavigation,
|
||||
{}
|
||||
);
|
||||
const routerLinkName =
|
||||
secondOptions && secondOptions.linkName;
|
||||
const linkName =
|
||||
routerLinkName || childRoute.routeName;
|
||||
return (
|
||||
<Link
|
||||
to={childRoute.routeName}
|
||||
className={`pt-menu-item page ${isChildActive ? 'active' : ''}`}
|
||||
key={childI}
|
||||
>
|
||||
{linkName}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="main-section">
|
||||
<ActiveScreen navigation={this.props.navigation} />
|
||||
<hr />
|
||||
{state.routeName === 'Docs' &&
|
||||
<Link
|
||||
href={`https://github.com/react-community/react-navigation/tree/master/docs/${docPath}`}
|
||||
className="editLink"
|
||||
>
|
||||
{' '}Edit on GitHub
|
||||
</Link>}
|
||||
{prevAction && <Link to={prevAction}>Previous: {prevName}</Link>}
|
||||
{nextAction &&
|
||||
<Link to={nextAction} className="nextLink">
|
||||
Next: {nextName}
|
||||
</Link>}
|
||||
</div>
|
||||
|
||||
<div className="left-sidebar">
|
||||
<ul className="pt-menu pt-elevation-1 navmenu">
|
||||
{state.routes && state.routes.map((route, i) => {
|
||||
const DocComponent = router.getComponentForRouteName(route.routeName);
|
||||
const childNavigation = addNavigationHelpers({
|
||||
state: route,
|
||||
dispatch,
|
||||
});
|
||||
const options = router.getScreenOptions(childNavigation, {});
|
||||
const isActive = state.index === i;
|
||||
return (
|
||||
<span key={i}>
|
||||
<LinkableLi
|
||||
to={route.routeName}
|
||||
className={"pt-menu-header "+options.icon+' '+(isActive?'active':'')}>
|
||||
<h6>{options.linkName}</h6>
|
||||
</LinkableLi>
|
||||
<div>
|
||||
{route.routes && route.routes.map((childRoute, childI) => {
|
||||
const isChildActive = isActive && route.index === childI;
|
||||
const secondChildNavigation = addNavigationHelpers({
|
||||
state: childRoute,
|
||||
dispatch,
|
||||
});
|
||||
const secondOptions = DocComponent.router && DocComponent.router.getScreenOptions(secondChildNavigation, {});
|
||||
const routerLinkName = secondOptions && secondOptions.linkName;
|
||||
const linkName = routerLinkName || childRoute.routeName;
|
||||
return (
|
||||
<Link
|
||||
to={childRoute.routeName}
|
||||
className={`pt-menu-item page ${(isChildActive) ? 'active' : ''}`}
|
||||
key={childI}>
|
||||
{linkName}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="main-section">
|
||||
<ActiveScreen navigation={this.props.navigation} />
|
||||
<hr />
|
||||
{state.routeName === 'Docs' && <Link href={`https://github.com/react-community/react-navigation/tree/master/docs/${docPath}`} className="editLink"> Edit on GitHub</Link>}
|
||||
{prevAction && <Link to={prevAction}>Previous: {prevName}</Link>}
|
||||
{nextAction && <Link to={nextAction} className="nextLink">Next: {nextName}</Link>}
|
||||
</div>
|
||||
|
||||
</div></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,36 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class PhoneGraphic extends Component {
|
||||
props: { sources: { android: string, iphone: string } };
|
||||
state = { activeExample: this.props.alt ? 'android' : 'iphone' };
|
||||
render() {
|
||||
const {activeExample} = this.state;
|
||||
const { activeExample } = this.state;
|
||||
return (
|
||||
<div className="example-section">
|
||||
<div className="buttonbar">
|
||||
<a
|
||||
className={activeExample === 'android'}
|
||||
onClick={() => this.setState({ activeExample: 'android' })}>
|
||||
onClick={() => this.setState({ activeExample: 'android' })}
|
||||
>
|
||||
Android
|
||||
</a>
|
||||
<a
|
||||
className={activeExample === 'iphone'}
|
||||
onClick={() => this.setState({ activeExample: 'iphone' })}>
|
||||
onClick={() => this.setState({ activeExample: 'iphone' })}
|
||||
>
|
||||
iPhone
|
||||
</a>
|
||||
</div>
|
||||
<div className="phone">
|
||||
<div className={`android ${activeExample === 'android'}`}>
|
||||
<div className={`android ${String(activeExample === 'android')}`}>
|
||||
<img src={this.props.sources.android} role="presentation" />
|
||||
</div>
|
||||
<div className="phone-example-spacer" />
|
||||
<div className={`iphone ${activeExample === 'iphone'}`}>
|
||||
<div className={`iphone ${String(activeExample === 'iphone')}`}>
|
||||
<img src={this.props.sources.iphone} role="presentation" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
27
packages/react-navigation/website/src/Server.js
vendored
27
packages/react-navigation/website/src/Server.js
vendored
@@ -1,8 +1,8 @@
|
||||
|
||||
const path = require('path');
|
||||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const join = require('path').join;
|
||||
const basicAuth = require('basic-auth-connect');
|
||||
const server = require('express');
|
||||
@@ -14,14 +14,14 @@ import { NavigationActions, addNavigationHelpers } from 'react-navigation';
|
||||
|
||||
class ServerApp extends React.Component {
|
||||
static childContextTypes = {
|
||||
getURIForAction: React.PropTypes.func.isRequired,
|
||||
getActionForPathAndParams: React.PropTypes.func.isRequired,
|
||||
dispatch: React.PropTypes.func.isRequired,
|
||||
getURIForAction: PropTypes.func.isRequired,
|
||||
getActionForPathAndParams: PropTypes.func.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
};
|
||||
getChildContext() {
|
||||
return {
|
||||
dispatch: this.props.navigation.dispatch,
|
||||
getURIForAction: (action) => {
|
||||
getURIForAction: action => {
|
||||
const state = App.router.getStateForAction(action);
|
||||
let { path } = App.router.getPathAndParamsForState(state);
|
||||
return `/${path}`;
|
||||
@@ -34,19 +34,24 @@ class ServerApp extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
const indexHtml = fs.readFileSync(join(__dirname, '../public/index.html'), { encoding: 'utf8' });
|
||||
const indexHtml = fs.readFileSync(join(__dirname, '../public/index.html'), {
|
||||
encoding: 'utf8',
|
||||
});
|
||||
|
||||
function AppHandler(req, res) {
|
||||
let status = 200;
|
||||
const path = req.url.substr(1)
|
||||
const path = req.url.substr(1);
|
||||
let initAction = App.router.getActionForPathAndParams(path);
|
||||
if (!initAction) {
|
||||
initAction = NavigationActions.navigate({ routeName: 'NotFound', params: { path } });
|
||||
initAction = NavigationActions.navigate({
|
||||
routeName: 'NotFound',
|
||||
params: { path },
|
||||
});
|
||||
status = 404;
|
||||
}
|
||||
const topNavigation = addNavigationHelpers({
|
||||
state: App.router.getStateForAction(initAction),
|
||||
dispatch: (action) => false,
|
||||
dispatch: action => false,
|
||||
});
|
||||
const screenNavigation = addNavigationHelpers({
|
||||
state: topNavigation.state.routes[topNavigation.state.index],
|
||||
@@ -58,7 +63,9 @@ function AppHandler(req, res) {
|
||||
const app = <ServerApp navigation={topNavigation} />;
|
||||
const body = ReactDOMServer.renderToString(app);
|
||||
let html = indexHtml;
|
||||
html = html.split('<div id="root"></div>').join(`<div id="root">${body}</div>`)
|
||||
html = html
|
||||
.split('<div id="root"></div>')
|
||||
.join(`<div id="root">${body}</div>`);
|
||||
if (title) {
|
||||
html = html.split('<title></title>').join(`<title>${title}</title>`);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,4 @@ import '@blueprintjs/core/dist/blueprint.css';
|
||||
|
||||
const ClientApp = BrowserAppContainer(App);
|
||||
|
||||
ReactDOM.render(
|
||||
<ClientApp />,
|
||||
document.getElementById('root')
|
||||
);
|
||||
ReactDOM.render(<ClientApp />, document.getElementById('root'));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user