Compare commits

..

53 Commits
2.2.0 ... 2.5.1

Author SHA1 Message Date
Brent Vatne
350b7e0aed Release 2.5.1 2018-06-22 13:21:22 -07:00
Brent Vatne
de112565d3 Fix name of prop, should be lastTransitionProps instead of prevTransitionProps in StackViewLayout
- Fixes #4542
2018-06-22 13:18:26 -07:00
Brent Vatne
acdd515c13 Update example app.json 2018-06-22 12:50:50 -07:00
Rodrigo Bermúdez Schettino
452a6d2004 Improve changelog format (#4559)
Bug fixes should be listed in the "Fixed" section instead of "Changed" according to keepachangelog.
2018-06-22 10:41:58 -07:00
Brent Vatne
08c8031a71 Release 2.5.0 2018-06-22 10:32:11 -07:00
Eric Vicenti
608365266a @ericvicenti/universe (#4493)
* Isolate modules for uncontainerized navigators

* Clean up prop-types

* Fix warnings and web import friendlyness

* strip a flow

* Standalone provider/consumer navigation context

* export shallowEqual as module

* address various lint

# Conflicts:
#	src/navigators/createStackNavigator.js

* Get tests to pass
2018-06-22 10:20:27 -07:00
Rodrigo Bermúdez Schettino
247fba56e6 Fix typo in Pull Request Template (#4558)
Also link to the "Unreleased" section in CHANGELOG.
2018-06-22 10:19:41 -07:00
Brent Vatne
060f5dcecf Update PR template for changelog 2018-06-22 08:25:38 -07:00
Rodrigo Bermúdez Schettino
fdec05c87a Create CHANGELOG.md (#4544)
List all changes between versions to notify about notable changes in releases.
2018-06-22 08:22:15 -07:00
Brent Vatne
76da804574 Fixes #4491 2018-06-21 15:24:52 -07:00
Brent Vatne
dde091848a Release 2.4.1 2018-06-20 15:35:07 -07:00
Brent Vatne
824fa32416 Improve playground on Android 2018-06-20 14:20:00 -07:00
Brent Vatne
c518e7f36c Improve example 2018-06-20 13:51:34 -07:00
Brent Vatne
1cfe01dbdb Release 2.4.0 2018-06-20 13:38:05 -07:00
Brent Vatne
e62a9050fd Fix withDefaultValue 2018-06-20 13:37:33 -07:00
Christophe Hurpeau
310b909ba8 createNavigationContainer: rethrow the error instead of creating a new one (#4533)
Creating a new error makes the stack unreadable in sentry, because the stack is stringified when the error is cast to string to create a new one.
Is there another reason to do that ?
Alternative possible solution would be to add a method to be able to handle the error ourselves ?
2018-06-20 13:03:02 -07:00
Eric Vicenti
aebe8a5c23 Fix isTransitioning on nested navigate (#4520)
This bug wasnt apparent until we fixed the transitioner to fully respect isTransitioning. The router did not handle this properly until now.

Enhanced a test to verify this in the future
2018-06-20 12:17:14 -07:00
Vladislav Shabanov
e1df2c6c4a Make headers of non-standard heights work correctly in StackNavigator when header is null (Fixes #4208) (#4353)
* Measure header height dynamically

* Add comment

* StacksOverTopTabs playground example
2018-06-15 08:10:43 -07:00
Ashoat Tevosyan
fa86718a24 Revert "Export getNavigationActionCreators (#4258)" (#4495)
This reverts commit 1e7d8d55c3.
2018-06-14 11:34:38 -07:00
Ashoat Tevosyan
c8e5673183 [flow] Type getNavigation (#4505)
Unrelated change in here: typing `tabBarOnPress`'s `defaultHandler`. Wasn't sure if I should make a separate PR for a single unrelated line, let me know if you'd prefer that going forward.
2018-06-14 11:33:50 -07:00
Ashoat Tevosyan
b312a5e307 [ReduxExample] Update to use react-navigation-redux-helpers@2.0.0 (#4504) 2018-06-14 11:15:11 -07:00
Brent Vatne
ee6a6c53b1 Fix incorrect methods being called in createKeyboardAwareNavigator 2018-06-13 14:50:03 -07:00
Eric Vicenti
8edec88341 Export getNavigation as public API, test redux (#4489)
This unblocks the fixing of react-navigation-redux-helpers to unbreak redux support in 2.3

https://github.com/react-navigation/react-navigation-redux-helpers/pull/37

All redux users will need to change their code to reflect the changes made here to `ReduxExample/AppNavigator`
2018-06-12 11:59:09 -07:00
Brent Vatne
b8d6d4253d Release 2.3.1 2018-06-12 11:32:08 -07:00
Eric Vicenti
0adb1ba9f1 Export getNavigation as public API, test redux (#4488)
This unblocks the fixing of react-navigation-redux-helpers to unbreak redux support in 2.3

https://github.com/react-navigation/react-navigation-redux-helpers/pull/37

All redux users will need to change their code to reflect the changes made here to `ReduxExample/AppNavigator`
2018-06-12 11:30:23 -07:00
Brent Vatne
d3ef3d1271 Release 2.3.0 2018-06-11 15:54:41 -07:00
k-murakami0609
89a24bdc12 fix broken link to Common mistakes (#4468) 2018-06-10 10:41:18 -07:00
Brent Vatne
128a95b496 Release 2.3.0-beta.1 2018-06-09 14:18:09 -07:00
Brent Vatne
470eaf3b08 Make the actions available on the navigator navigation prop the same as its children (#4467)
* Make the actions available on the navigator navigation prop the same as its children

* Fix test and improve code clarity
2018-06-09 14:13:21 -07:00
Brent Vatne
c91e8206a5 Fix ScenesReducer test 2018-06-08 17:44:32 -07:00
Brent Vatne
da283915f8 Release 2.3.0-beta.0 2018-06-08 17:36:42 -07:00
Brent Vatne
3031e7bd80 Update header when screenProps change (Fixes #4271) 2018-06-08 17:35:17 -07:00
Brent Vatne
98a4f26f26 Bump react-navigation-drawer. Fixes #4416 2018-06-08 16:27:36 -07:00
Brent Vatne
b7f5435c93 Fix withNavigation in non-floating headers 2018-06-08 15:48:21 -07:00
Brent Vatne
21ef4fcb82 Return result of dispatch from action helpers 2018-06-08 14:33:01 -07:00
Eric Vicenti
5f64a2a9cb Refactor redo, child navigation to navigation prop (#4453) 2018-06-08 14:20:07 -07:00
Brent Vatne
992d0fb267 Release 2.2.5 2018-06-08 09:40:39 -07:00
ensecoz
6f41379ed1 extract correct property for onTransitionEnd (#4459) 2018-06-08 09:35:36 -07:00
Tom Klaver
267af01e72 throw readable error when wrong navigation prop is passed (#4455)
* add warning when passing wrong navigation prop: https://github.com/react-navigation/react-navigation/issues/3598

* add test for throwing when passing wrong navigation prop

* wrong nav prop error: update snapshots, throw => throw new, update docs reference url
2018-06-08 09:31:05 -07:00
Arthur Levoyer
b68c3a755d Add missing tests about DeepLinking (#4451)
* Fix #1950 (Deep link not working when nesting have more than two levels.)

* Fix test
2018-06-07 11:37:57 -07:00
Brent Vatne
7345634493 Release 2.2.4 2018-06-07 11:33:14 -07:00
Brent Vatne
6517169119 Re-compute options when screenProps change 2018-06-07 11:31:31 -07:00
Brent Vatne
ea5d14a720 Release 2.2.3 2018-06-06 21:13:00 -07:00
Brent Vatne
313d0726a8 Add some logs to NavigationPlayground around helper dispatch return value
This is a poor substitute for tests
2018-06-06 21:12:18 -07:00
Brent Vatne
b52f153747 Return the result of dispatch from helpers. Fixes #4445 2018-06-06 21:01:51 -07:00
Brent Vatne
44621005ff Release 2.2.2 2018-06-06 14:34:59 -07:00
Brent Vatne
bf58364c3d Bump react-navigation-drawer 2018-06-06 14:34:42 -07:00
Brent Vatne
b55053cde6 Release 2.2.1 2018-06-06 13:24:50 -07:00
Brent Vatne
9abb2644a9 Bump react-navigation-tabs and rebuild yarn.lock 2018-06-06 13:24:29 -07:00
Brent Vatne
6a946d6ab7 Revert "Refactor, move child navigation to navigation prop (#4425)"
This reverts commit ba62509ff4.
2018-06-06 13:19:08 -07:00
陈然
395abe5200 Change 'React' import writing, Prevent warnings in old version React (#4428) 2018-06-06 12:51:09 -07:00
Eric Vicenti
ba62509ff4 Refactor, move child navigation to navigation prop (#4425)
* Refactor, move child navigation to navigation prop

This fixes our descriptor caching issue, and unblocks explicit nested navigation options.

As a side effect, the following APIs are introduced:

- navigation.getChildNavigation(routeKey) , which is useful for explicitly getting children config info
- navigation.router, access to the static router

- router.childRouters[routeName] , an optional way to access the children routers directly. If childRouters are not provided in a router, we will fall back on getComponentForRouteName(routeName).router, which is the previous external API for this (although it may be slower because it will require the whole screen component).

* supporting tests and top level actions

* cleanup
2018-06-06 12:50:30 -07:00
Brent Vatne
45391db7d9 Move all drawer code into react-navigation-drawer (#4435)
* Move all drawer code into react-navigation-drawer

* Remove react-native-drawer-layout-polyfill from package.json
2018-06-06 12:11:28 -07:00
68 changed files with 3971 additions and 3622 deletions

View File

@@ -1,17 +1,21 @@
Please provide enough information so that others can review your pull request: Please provide enough information so that others can review your pull request:
## Motivation
Explain the **motivation** for making this change. What existing problem does the pull request solve? Explain the **motivation** for making this change. What existing problem does the pull request solve?
Prefer **small pull requests**. These are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise split it. ## Test plan
**Test plan (required)** Demonstrate the code is solid. Example: the exact commands you ran and their output, screenshots / videos if the pull request changes UI.
Demonstrate the code is solid. Example: The exact commands you ran and their output, screenshots / videos if the pull request changes UI.
Make sure you test on both platforms if your change affects both platforms. Make sure you test on both platforms if your change affects both platforms.
The code must pass tests. The code must pass tests.
**Code formatting** ## Code formatting
Look around. Match the style of the rest of the codebase. Look around. Match the style of the rest of the codebase. Run `yarn format` before committing.
## Changelog
Add an entry under the "Unreleased" heading in [CHANGELOG.md](https://github.com/react-navigation/react-navigation/blob/master/CHANGELOG.md#unreleased) which explains your change.

29
CHANGELOG.md Normal file
View File

@@ -0,0 +1,29 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [2.5.1] - [2018-06-22](https://github.com/react-navigation/react-navigation/releases/tag/2.5.1)
### Fixed
- `transitionConfig` in stack navigator no longer passes incorrect `fromTransitionProps` when navigating back
## [2.5.0] - [2018-06-22](https://github.com/react-navigation/react-navigation/releases/tag/2.5.0)
### Changed
- Refactor internals to make it play more nicely with web
### Fixed
- `const defaultGetStateForAction = SwitchBasedNavigator.router.getStateForAction` no longer throws error.
- Updated react-navigation-drawer to 0.4.1 which should fix issues related to automatically closing drawer when changing routes.
## [2.4.1] - [2018-06-21](https://github.com/react-navigation/react-navigation/releases/tag/2.4.1)
### Changed
- Improved examples
[Unreleased]: https://github.com/react-navigation/react-navigation/compare/2.5.1...HEAD
[2.5.0]: https://github.com/react-navigation/react-navigation/compare/2.5.0...2.5.1
[2.5.0]: https://github.com/react-navigation/react-navigation/compare/2.4.1...2.5.0
[2.4.1]: https://github.com/react-navigation/react-navigation/compare/2.4.0...2.4.1

View File

@@ -13,14 +13,15 @@
}, },
"sdkVersion": "27.0.0", "sdkVersion": "27.0.0",
"entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js", "entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"packagerOpts": { "assetBundlePatterns": [
"assetExts": [ "**/*"
"ttf", ],
"mp4"
]
},
"ios": { "ios": {
"bundleIdentifier": "com.reactnavigation.example",
"supportsTablet": true "supportsTablet": true
},
"android": {
"package": "com.reactnavigation.example"
} }
} }
} }

View File

@@ -26,6 +26,7 @@ import TabsInDrawer from './TabsInDrawer';
import ModalStack from './ModalStack'; import ModalStack from './ModalStack';
import StacksInTabs from './StacksInTabs'; import StacksInTabs from './StacksInTabs';
import StacksOverTabs from './StacksOverTabs'; import StacksOverTabs from './StacksOverTabs';
import StacksOverTopTabs from './StacksOverTopTabs';
import StacksWithKeys from './StacksWithKeys'; import StacksWithKeys from './StacksWithKeys';
import InactiveStack from './InactiveStack'; import InactiveStack from './InactiveStack';
import StackWithCustomHeaderBackImage from './StackWithCustomHeaderBackImage'; import StackWithCustomHeaderBackImage from './StackWithCustomHeaderBackImage';
@@ -105,6 +106,10 @@ const ExampleInfo = {
name: 'Stacks over Tabs', name: 'Stacks over Tabs',
description: 'Nested stack navigation that pushes on top of tabs', description: 'Nested stack navigation that pushes on top of tabs',
}, },
StacksOverTopTabs: {
name: 'Stacks with non-standard header height',
description: 'Tab navigator in stack with custom header heights',
},
StacksWithKeys: { StacksWithKeys: {
name: 'Link in Stack with keys', name: 'Link in Stack with keys',
description: 'Use keys to link between screens', description: 'Use keys to link between screens',
@@ -137,7 +142,12 @@ const ExampleRoutes = {
// screen: MultipleDrawer, // screen: MultipleDrawer,
// }, // },
StackWithCustomHeaderBackImage: StackWithCustomHeaderBackImage, StackWithCustomHeaderBackImage: StackWithCustomHeaderBackImage,
StackWithHeaderPreset: StackWithHeaderPreset, ...Platform.select({
ios: {
StackWithHeaderPreset: StackWithHeaderPreset,
},
android: {},
}),
StackWithTranslucentHeader: StackWithTranslucentHeader, StackWithTranslucentHeader: StackWithTranslucentHeader,
TabsInDrawer: TabsInDrawer, TabsInDrawer: TabsInDrawer,
CustomTabs: CustomTabs, CustomTabs: CustomTabs,
@@ -146,6 +156,7 @@ const ExampleRoutes = {
StacksWithKeys: StacksWithKeys, StacksWithKeys: StacksWithKeys,
StacksInTabs: StacksInTabs, StacksInTabs: StacksInTabs,
StacksOverTabs: StacksOverTabs, StacksOverTabs: StacksOverTabs,
StacksOverTopTabs: StacksOverTopTabs,
LinkStack: { LinkStack: {
screen: SimpleStack, screen: SimpleStack,
path: 'people/Jordan', path: 'people/Jordan',

View File

@@ -90,7 +90,16 @@ class MyNavScreen extends React.Component<MyNavScreenProps> {
/> />
<Button onPress={() => popToTop()} title="Pop to top" /> <Button onPress={() => popToTop()} title="Pop to top" />
<Button onPress={() => pop()} title="Pop" /> <Button onPress={() => pop()} title="Pop" />
<Button onPress={() => navigation.goBack()} title="Go back" /> <Button
onPress={() => {
if (navigation.goBack()) {
console.log('goBack handled');
} else {
console.log('goBack unhandled');
}
}}
title="Go back"
/>
<Button onPress={() => dismiss()} title="Dismiss" /> <Button onPress={() => dismiss()} title="Dismiss" />
<StatusBar barStyle="default" /> <StatusBar barStyle="default" />
</SafeAreaView> </SafeAreaView>

View File

@@ -165,7 +165,7 @@ const SimpleTabs = createBottomTabNavigator(
}, },
{ {
tabBarOptions: { tabBarOptions: {
activeTintColor: Platform.OS === 'ios' ? '#e91e63' : '#fff', activeTintColor: '#e91e63',
}, },
} }
); );

View File

@@ -0,0 +1,142 @@
/**
* @flow
*/
import React from 'react';
import { View, ScrollView, StatusBar, StyleSheet } from 'react-native';
import {
SafeAreaView,
createStackNavigator,
createMaterialTopTabNavigator,
} from 'react-navigation';
import { Constants } from 'expo';
import { MaterialTopTabBar } from 'react-navigation-tabs';
import SampleText from './SampleText';
import { Button } from './commonComponents/ButtonWithMargin';
const HEADER_HEIGHT = 64;
const MyNavScreen = ({ navigation, banner, statusBarStyle }) => (
<ScrollView>
<SafeAreaView forceInset={{ horizontal: 'always' }}>
<SampleText>{banner}</SampleText>
<Button
onPress={() => navigation.navigate('Profile', { name: 'Jordan' })}
title="Open profile screen"
/>
<Button
onPress={() => navigation.navigate('NotifSettings')}
title="Open notifications screen"
/>
<Button
onPress={() => navigation.navigate('SettingsTab')}
title="Go to settings tab"
/>
<Button onPress={() => navigation.goBack(null)} title="Go back" />
</SafeAreaView>
<StatusBar barStyle={statusBarStyle || 'default'} />
</ScrollView>
);
const MyHomeScreen = ({ navigation }) => (
<MyNavScreen
banner="Home Screen"
navigation={navigation}
statusBarStyle="light-content"
/>
);
const MyProfileScreen = ({ navigation }) => (
<MyNavScreen
banner={`${navigation.state.params.name}s Profile`}
navigation={navigation}
/>
);
const MyNotificationsSettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Notifications Screen" navigation={navigation} />
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen
banner="Settings Screen"
navigation={navigation}
statusBarStyle="light-content"
/>
);
const styles = StyleSheet.create({
stackHeader: {
height: HEADER_HEIGHT,
},
tab: {
height: HEADER_HEIGHT,
},
});
function MaterialTopTabBarWithStatusBar(props) {
return (
<View
style={{
paddingTop: Constants.statusBarHeight,
backgroundColor: '#2196f3',
}}
>
<MaterialTopTabBar {...props} jumpToIndex={() => {}} />
</View>
);
}
const TabNavigator = createMaterialTopTabNavigator(
{
MainTab: {
screen: MyHomeScreen,
navigationOptions: {
title: 'Welcome',
},
},
SettingsTab: {
screen: MySettingsScreen,
navigationOptions: {
title: 'Settings',
},
},
},
{
tabBarComponent: MaterialTopTabBarWithStatusBar,
tabBarOptions: {
tabStyle: styles.tab,
},
}
);
const StackNavigator = createStackNavigator(
{
Root: {
screen: TabNavigator,
navigationOptions: {
header: null,
},
},
NotifSettings: {
screen: MyNotificationsSettingsScreen,
navigationOptions: {
title: 'Notifications',
},
},
Profile: {
screen: MyProfileScreen,
navigationOptions: ({ navigation }) => ({
title: `${navigation.state.params.name}'s Profile!`,
}),
},
},
{
navigationOptions: {
headerStyle: styles.stackHeader,
},
}
);
export default StackNavigator;

View File

@@ -18,7 +18,8 @@
"react-native-iphone-x-helper": "^1.0.2", "react-native-iphone-x-helper": "^1.0.2",
"react-navigation": "link:../..", "react-navigation": "link:../..",
"react-navigation-header-buttons": "^0.0.4", "react-navigation-header-buttons": "^0.0.4",
"react-navigation-material-bottom-tabs": "0.1.3" "react-navigation-material-bottom-tabs": "0.1.3",
"react-navigation-tabs": "^0.5.1"
}, },
"devDependencies": { "devDependencies": {
"babel-jest": "^22.4.1", "babel-jest": "^22.4.1",

View File

@@ -590,8 +590,8 @@
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
"@types/node@*": "@types/node@*":
version "10.1.2" version "10.3.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.1.2.tgz#1b928a0baa408fc8ae3ac012cc81375addc147c6" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.1.tgz#51092fbacaed768a122a293814474fbf6e5e8b6d"
abab@^1.0.4: abab@^1.0.4:
version "1.0.4" version "1.0.4"
@@ -619,8 +619,8 @@ acorn-globals@^4.1.0:
acorn "^5.0.0" acorn "^5.0.0"
acorn@^5.0.0, acorn@^5.3.0: acorn@^5.0.0, acorn@^5.3.0:
version "5.5.3" version "5.6.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.6.2.tgz#b1da1d7be2ac1b4a327fb9eab851702c5045b4e7"
agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0: agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0:
version "4.2.0" version "4.2.0"
@@ -855,8 +855,8 @@ assign-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
ast-types@0.x.x: ast-types@0.x.x:
version "0.11.4" version "0.11.5"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.4.tgz#76f930930e9571851ba282a9a0f6923f29f6be2f" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.11.5.tgz#9890825d660c03c28339f315e9fa0a360e31ec28"
astral-regex@^1.0.0: astral-regex@^1.0.0:
version "1.0.0" version "1.0.0"
@@ -1195,8 +1195,8 @@ babel-plugin-transform-class-properties@^6.18.0, babel-plugin-transform-class-pr
babel-template "^6.24.1" babel-template "^6.24.1"
babel-plugin-transform-decorators-legacy@^1.3.4: babel-plugin-transform-decorators-legacy@^1.3.4:
version "1.3.4" version "1.3.5"
resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz#741b58f6c5bce9e6027e0882d9c994f04f366925" resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.5.tgz#0e492dffa0edd70529072887f8aa86d4dd8b40a1"
dependencies: dependencies:
babel-plugin-syntax-decorators "^6.1.18" babel-plugin-syntax-decorators "^6.1.18"
babel-runtime "^6.2.0" babel-runtime "^6.2.0"
@@ -1678,8 +1678,8 @@ bcrypt-pbkdf@^1.0.0:
tweetnacl "^0.14.3" tweetnacl "^0.14.3"
big-integer@^1.6.7: big-integer@^1.6.7:
version "1.6.28" version "1.6.30"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.28.tgz#8cef0fda3ccde8759c2c66efcfacc35aea658283" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.30.tgz#7796f04acdd6ba56345f19049c8fffd427f09d16"
bluebird@^2.10.2: bluebird@^2.10.2:
version "2.11.0" version "2.11.0"
@@ -1773,28 +1773,28 @@ bser@^2.0.0:
dependencies: dependencies:
node-int64 "^0.4.0" node-int64 "^0.4.0"
buffer-alloc-unsafe@^0.1.0: buffer-alloc-unsafe@^1.1.0:
version "0.1.1" version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz#ffe1f67551dd055737de253337bfe853dfab1a6a" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
buffer-alloc@^1.1.0: buffer-alloc@^1.1.0:
version "1.1.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.1.0.tgz#05514d33bf1656d3540c684f65b1202e90eca303" resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
dependencies: dependencies:
buffer-alloc-unsafe "^0.1.0" buffer-alloc-unsafe "^1.1.0"
buffer-fill "^0.1.0" buffer-fill "^1.0.0"
buffer-equal-constant-time@1.0.1: buffer-equal-constant-time@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
buffer-fill@^0.1.0: buffer-fill@^1.0.0:
version "0.1.1" version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-0.1.1.tgz#76d825c4d6e50e06b7a31eb520c04d08cc235071" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
buffer-from@^1.0.0: buffer-from@^1.0.0:
version "1.0.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04"
builtin-modules@^1.0.0: builtin-modules@^1.0.0:
version "1.1.1" version "1.1.1"
@@ -2053,10 +2053,10 @@ component-type@^1.2.1:
resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.1.tgz#8a47901700238e4fc32269771230226f24b415a9" resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.1.tgz#8a47901700238e4fc32269771230226f24b415a9"
compressible@~2.0.13: compressible@~2.0.13:
version "2.0.13" version "2.0.14"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7"
dependencies: dependencies:
mime-db ">= 1.33.0 < 2" mime-db ">= 1.34.0 < 2"
compression@^1.7.1: compression@^1.7.1:
version "1.7.2" version "1.7.2"
@@ -2124,8 +2124,8 @@ cookie@0.3.1:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
cookiejar@^2.1.0: cookiejar@^2.1.0:
version "2.1.1" version "2.1.2"
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c"
copy-descriptor@^0.1.0: copy-descriptor@^0.1.0:
version "0.1.1" version "0.1.1"
@@ -2136,8 +2136,8 @@ core-js@^1.0.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0, core-js@^2.5.6: core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0, core-js@^2.5.6:
version "2.5.6" version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.6.tgz#0fe6d45bf3cac3ac364a9d72de7576f4eb221b9d" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
core-util-is@1.0.2, core-util-is@~1.0.0: core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
@@ -2254,9 +2254,9 @@ deep-diff@0.3.4:
version "0.3.4" version "0.3.4"
resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.4.tgz#aac5c39952236abe5f037a2349060ba01b00ae48" resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.4.tgz#aac5c39952236abe5f037a2349060ba01b00ae48"
deep-extend@^0.5.1: deep-extend@^0.6.0:
version "0.5.1" version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
deep-is@~0.1.3: deep-is@~0.1.3:
version "0.1.3" version "0.1.3"
@@ -2267,8 +2267,8 @@ deepmerge@^1.3.0, deepmerge@^1.5.1:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
deepmerge@^2.1.0: deepmerge@^2.1.0:
version "2.1.0" version "2.1.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.0.tgz#511a54fff405fc346f0240bb270a3e9533a31102" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.1.tgz#e862b4e45ea0555072bf51e7fd0d9845170ae768"
default-require-extensions@^1.0.0: default-require-extensions@^1.0.0:
version "1.0.0" version "1.0.0"
@@ -2426,8 +2426,8 @@ errorhandler@^1.5.0:
escape-html "~1.0.3" escape-html "~1.0.3"
es-abstract@^1.5.1: es-abstract@^1.5.1:
version "1.11.0" version "1.12.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.11.0.tgz#cce87d518f0496893b1a30cd8461835535480681" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
dependencies: dependencies:
es-to-primitive "^1.1.1" es-to-primitive "^1.1.1"
function-bind "^1.1.1" function-bind "^1.1.1"
@@ -2974,7 +2974,7 @@ ftp@~0.3.10:
readable-stream "1.1.x" readable-stream "1.1.x"
xregexp "2.0.0" xregexp "2.0.0"
function-bind@^1.0.2, function-bind@^1.1.1: function-bind@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -3202,10 +3202,10 @@ has-values@^1.0.0:
kind-of "^4.0.0" kind-of "^4.0.0"
has@^1.0.1: has@^1.0.1:
version "1.0.1" version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
dependencies: dependencies:
function-bind "^1.0.2" function-bind "^1.1.1"
hasbin@^1.2.3: hasbin@^1.2.3:
version "1.2.3" version "1.2.3"
@@ -3731,8 +3731,8 @@ istanbul-lib-source-maps@^1.2.1:
source-map "^0.5.3" source-map "^0.5.3"
istanbul-lib-source-maps@^1.2.4: istanbul-lib-source-maps@^1.2.4:
version "1.2.4" version "1.2.5"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz#cc7ccad61629f4efff8e2f78adb8c522c9976ec7" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1"
dependencies: dependencies:
debug "^3.1.0" debug "^3.1.0"
istanbul-lib-coverage "^1.2.0" istanbul-lib-coverage "^1.2.0"
@@ -4069,8 +4069,8 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
js-yaml@^3.7.0: js-yaml@^3.7.0:
version "3.11.0" version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
dependencies: dependencies:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
@@ -4661,14 +4661,18 @@ micromatch@^3.1.4, micromatch@^3.1.8:
snapdragon "^0.8.1" snapdragon "^0.8.1"
to-regex "^3.0.2" to-regex "^3.0.2"
"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: "mime-db@>= 1.34.0 < 2":
version "1.33.0" version "1.34.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.34.0.tgz#452d0ecff5c30346a6dc1e64b1eaee0d3719ff9a"
mime-db@~1.23.0: mime-db@~1.23.0:
version "1.23.0" version "1.23.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659"
mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
mime-types@2.1.11: mime-types@2.1.11:
version "2.1.11" version "2.1.11"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c"
@@ -4750,8 +4754,8 @@ mkdirp@*, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
minimist "0.0.8" minimist "0.0.8"
moment@2.x.x, moment@^2.10.6: moment@2.x.x, moment@^2.10.6:
version "2.22.1" version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.1.tgz#529a2e9bf973f259c9643d237fda84de3a26e8ad" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
morgan@^1.9.0: morgan@^1.9.0:
version "1.9.0" version "1.9.0"
@@ -4944,8 +4948,8 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
nwsapi@^2.0.0: nwsapi@^2.0.0:
version "2.0.0" version "2.0.1"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.0.tgz#7c8faf4ad501e1d17a651ebc5547f966b547c5c7" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.1.tgz#a50d59a2dcb14b6931401171713ced2d0eb3468f"
oauth-sign@~0.8.2: oauth-sign@~0.8.2:
version "0.8.2" version "0.8.2"
@@ -5378,7 +5382,7 @@ prop-types@15.5.8:
dependencies: dependencies:
fbjs "^0.8.9" fbjs "^0.8.9"
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0: prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1:
version "15.6.1" version "15.6.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
dependencies: dependencies:
@@ -5414,6 +5418,10 @@ pseudomap@^1.0.1, pseudomap@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
psl@^1.1.24:
version "1.1.27"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.27.tgz#2b2c77019db86855170d903532400bf71ee085b6"
punycode@1.3.2: punycode@1.3.2:
version "1.3.2" version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
@@ -5487,10 +5495,10 @@ raw-body@2.3.3, raw-body@^2.2.0:
unpipe "1.0.0" unpipe "1.0.0"
rc@^1.1.7: rc@^1.1.7:
version "1.2.7" version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.7.tgz#8a10ca30d588d00464360372b890d06dacd02297" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
dependencies: dependencies:
deep-extend "^0.5.1" deep-extend "^0.6.0"
ini "~1.3.0" ini "~1.3.0"
minimist "^1.2.0" minimist "^1.2.0"
strip-json-comments "~2.0.1" strip-json-comments "~2.0.1"
@@ -5654,7 +5662,13 @@ react-native-tab-view@^0.0.77:
dependencies: dependencies:
prop-types "^15.6.0" prop-types "^15.6.0"
react-native-tab-view@~0.0.77, react-native-tab-view@~0.0.78: react-native-tab-view@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-1.0.2.tgz#66e0bc6d38a227ed2b212e3a256b7902f6ce02ed"
dependencies:
prop-types "^15.6.1"
react-native-tab-view@~0.0.77:
version "0.0.78" version "0.0.78"
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.78.tgz#9b90730d89cbd34a03f0e0ab10e74ca7af945560" resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.78.tgz#9b90730d89cbd34a03f0e0ab10e74ca7af945560"
dependencies: dependencies:
@@ -5744,6 +5758,12 @@ react-navigation-deprecated-tab-navigator@1.3.0:
dependencies: dependencies:
react-native-tab-view "^0.0.77" react-native-tab-view "^0.0.77"
react-navigation-drawer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/react-navigation-drawer/-/react-navigation-drawer-0.3.0.tgz#641007213f0f1e1b55a0a4bb64d71df07b3e7208"
dependencies:
react-native-drawer-layout-polyfill "^1.3.2"
react-navigation-header-buttons@^0.0.4: react-navigation-header-buttons@^0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/react-navigation-header-buttons/-/react-navigation-header-buttons-0.0.4.tgz#90dd7617aec31eeb35c600eb90afe40f9b0dc43b" resolved "https://registry.yarnpkg.com/react-navigation-header-buttons/-/react-navigation-header-buttons-0.0.4.tgz#90dd7617aec31eeb35c600eb90afe40f9b0dc43b"
@@ -5769,15 +5789,15 @@ react-navigation-tabs@0.2.0-rc.0:
react-native-safe-area-view "^0.7.0" react-native-safe-area-view "^0.7.0"
react-native-tab-view "~0.0.77" react-native-tab-view "~0.0.77"
react-navigation-tabs@0.3.0: react-navigation-tabs@0.5.1, react-navigation-tabs@^0.5.1:
version "0.3.0" version "0.5.1"
resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-0.3.0.tgz#b1fe7ef1c665dd8928fafcc8622616e220ae5efa" resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-0.5.1.tgz#ed33bce3a3e21b92646700de25bd94b8fc570371"
dependencies: dependencies:
hoist-non-react-statics "^2.5.0" hoist-non-react-statics "^2.5.0"
prop-types "^15.6.0" prop-types "^15.6.1"
react-lifecycles-compat "^3.0.4" react-lifecycles-compat "^3.0.4"
react-native-safe-area-view "^0.7.0" react-native-safe-area-view "^0.7.0"
react-native-tab-view "~0.0.78" react-native-tab-view "^1.0.0"
"react-navigation@link:../..": "react-navigation@link:../..":
version "0.0.0" version "0.0.0"
@@ -5955,8 +5975,8 @@ regenerator-transform@^0.10.0:
private "^0.1.6" private "^0.1.6"
regenerator-transform@^0.12.3: regenerator-transform@^0.12.3:
version "0.12.3" version "0.12.4"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.12.3.tgz#459adfb64f6a27164ab991b7873f45ab969eca8b" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.12.4.tgz#aa9b6c59f4b97be080e972506c560b3bccbfcff0"
dependencies: dependencies:
private "^0.1.6" private "^0.1.6"
@@ -6189,7 +6209,7 @@ safe-regex@^1.1.0:
dependencies: dependencies:
ret "~0.1.10" ret "~0.1.10"
"safer-buffer@>= 2.1.2 < 3": "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -6491,13 +6511,14 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
sshpk@^1.7.0: sshpk@^1.7.0:
version "1.14.1" version "1.14.2"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
dependencies: dependencies:
asn1 "~0.2.3" asn1 "~0.2.3"
assert-plus "^1.0.0" assert-plus "^1.0.0"
dashdash "^1.12.0" dashdash "^1.12.0"
getpass "^0.1.1" getpass "^0.1.1"
safer-buffer "^2.0.2"
optionalDependencies: optionalDependencies:
bcrypt-pbkdf "^1.0.0" bcrypt-pbkdf "^1.0.0"
ecc-jsbn "~0.1.1" ecc-jsbn "~0.1.1"
@@ -6807,7 +6828,14 @@ topo@2.x.x:
dependencies: dependencies:
hoek "4.x.x" hoek "4.x.x"
tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.3: tough-cookie@>=2.3.3, tough-cookie@^2.3.3:
version "2.4.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.2.tgz#aa9133154518b494efab98a58247bfc38818c00c"
dependencies:
psl "^1.1.24"
punycode "^1.4.1"
tough-cookie@~2.3.3:
version "2.3.4" version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
dependencies: dependencies:
@@ -7069,8 +7097,8 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0: which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0:
version "1.3.0" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
dependencies: dependencies:
isexe "^2.0.0" isexe "^2.0.0"

View File

@@ -4,19 +4,15 @@ import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux'; import { createStore, applyMiddleware } from 'redux';
import AppReducer from './src/reducers'; import AppReducer from './src/reducers';
import AppWithNavigationState from './src/navigators/AppNavigator'; import { AppNavigator, middleware } from './src/navigators/AppNavigator';
import { middleware } from './src/utils/redux';
const store = createStore( const store = createStore(AppReducer, applyMiddleware(middleware));
AppReducer,
applyMiddleware(middleware),
);
class ReduxExampleApp extends React.Component { class ReduxExampleApp extends React.Component {
render() { render() {
return ( return (
<Provider store={store}> <Provider store={store}>
<AppWithNavigationState /> <AppNavigator />
</Provider> </Provider>
); );
} }

View File

@@ -12,7 +12,7 @@
"icon": "./assets/icons/react-navigation.png", "icon": "./assets/icons/react-navigation.png",
"hideExponentText": false "hideExponentText": false
}, },
"sdkVersion": "25.0.0", "sdkVersion": "27.0.0",
"entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js", "entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
"packagerOpts": { "packagerOpts": {
"assetExts": ["ttf", "mp4"] "assetExts": ["ttf", "mp4"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -21,17 +21,18 @@
] ]
}, },
"dependencies": { "dependencies": {
"expo": "^25.0.0", "expo": "^27.0.0",
"prop-types": "^15.5.10", "prop-types": "^15.5.10",
"react": "16.2.0", "react": "16.3.1",
"react-native": "^0.52.0", "react-native": "^0.55.0",
"react-navigation": "link:../..", "react-navigation": "link:../..",
"react-navigation-redux-helpers": "^1.0.0", "react-navigation-redux-helpers": "^2.0.0-beta.1",
"react-redux": "^5.0.6", "react-redux": "^5.0.6",
"redux": "^3.7.2" "redux": "^3.7.2"
}, },
"devDependencies": { "devDependencies": {
"babel-jest": "^22.4.1", "babel-jest": "^22.4.1",
"flow-bin": "^0.74.0",
"jest": "^22.1.3", "jest": "^22.1.3",
"jest-expo": "^25.1.0", "jest-expo": "^25.1.0",
"react-native-scripts": "^1.3.1", "react-native-scripts": "^1.3.1",

View File

@@ -2,38 +2,32 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createStackNavigator } from 'react-navigation'; import { createStackNavigator } from 'react-navigation';
import { initializeListeners } from 'react-navigation-redux-helpers'; import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
} from 'react-navigation-redux-helpers';
import LoginScreen from '../components/LoginScreen'; import LoginScreen from '../components/LoginScreen';
import MainScreen from '../components/MainScreen'; import MainScreen from '../components/MainScreen';
import ProfileScreen from '../components/ProfileScreen'; import ProfileScreen from '../components/ProfileScreen';
import { navigationPropConstructor } from '../utils/redux';
export const AppNavigator = createStackNavigator({ const middleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
);
const RootNavigator = createStackNavigator({
Login: { screen: LoginScreen }, Login: { screen: LoginScreen },
Main: { screen: MainScreen }, Main: { screen: MainScreen },
Profile: { screen: ProfileScreen }, Profile: { screen: ProfileScreen },
}); });
class AppWithNavigationState extends React.Component { const AppWithNavigationState = reduxifyNavigator(RootNavigator, 'root');
static propTypes = {
dispatch: PropTypes.func.isRequired,
nav: PropTypes.object.isRequired,
};
componentDidMount() {
initializeListeners('root', this.props.nav);
}
render() {
const { dispatch, nav } = this.props;
const navigation = navigationPropConstructor(dispatch, nav);
return <AppNavigator navigation={navigation} />;
}
}
const mapStateToProps = state => ({ const mapStateToProps = state => ({
nav: state.nav, state: state.nav,
}); });
export default connect(mapStateToProps)(AppWithNavigationState); const AppNavigator = connect(mapStateToProps)(AppWithNavigationState);
export { RootNavigator, AppNavigator, middleware };

View File

@@ -1,13 +1,13 @@
import { combineReducers } from 'redux'; import { combineReducers } from 'redux';
import { NavigationActions } from 'react-navigation'; import { NavigationActions } from 'react-navigation';
import { AppNavigator } from '../navigators/AppNavigator'; import { RootNavigator } from '../navigators/AppNavigator';
// Start with two routes: The Main screen, with the Login screen on top. // Start with two routes: The Main screen, with the Login screen on top.
const firstAction = AppNavigator.router.getActionForPathAndParams('Main'); const firstAction = RootNavigator.router.getActionForPathAndParams('Main');
const tempNavState = AppNavigator.router.getStateForAction(firstAction); const tempNavState = RootNavigator.router.getStateForAction(firstAction);
const secondAction = AppNavigator.router.getActionForPathAndParams('Login'); const secondAction = RootNavigator.router.getActionForPathAndParams('Login');
const initialNavState = AppNavigator.router.getStateForAction( const initialNavState = RootNavigator.router.getStateForAction(
secondAction, secondAction,
tempNavState tempNavState
); );
@@ -16,19 +16,19 @@ function nav(state = initialNavState, action) {
let nextState; let nextState;
switch (action.type) { switch (action.type) {
case 'Login': case 'Login':
nextState = AppNavigator.router.getStateForAction( nextState = RootNavigator.router.getStateForAction(
NavigationActions.back(), NavigationActions.back(),
state state
); );
break; break;
case 'Logout': case 'Logout':
nextState = AppNavigator.router.getStateForAction( nextState = RootNavigator.router.getStateForAction(
NavigationActions.navigate({ routeName: 'Login' }), NavigationActions.navigate({ routeName: 'Login' }),
state state
); );
break; break;
default: default:
nextState = AppNavigator.router.getStateForAction(action, state); nextState = RootNavigator.router.getStateForAction(action, state);
break; break;
} }

View File

@@ -1,12 +0,0 @@
import {
createReactNavigationReduxMiddleware,
createNavigationPropConstructor,
} from 'react-navigation-redux-helpers';
const middleware = createReactNavigationReduxMiddleware(
'root',
state => state.nav
);
const navigationPropConstructor = createNavigationPropConstructor('root');
export { middleware, navigationPropConstructor };

File diff suppressed because it is too large Load Diff

View File

@@ -284,7 +284,7 @@ declare module 'react-navigation' {
| NavigationContainer<*, *, *>; | NavigationContainer<*, *, *>;
declare interface withOptionalNavigationOptions<Options> { declare interface withOptionalNavigationOptions<Options> {
navigationOptions?: NavigationScreenConfig<Options>, navigationOptions?: NavigationScreenConfig<Options>;
} }
declare export type NavigationScreenComponent< declare export type NavigationScreenComponent<
@@ -294,10 +294,11 @@ declare module 'react-navigation' {
> = React$ComponentType<{ > = React$ComponentType<{
...Props, ...Props,
...NavigationNavigatorProps<Options, Route>, ...NavigationNavigatorProps<Options, Route>,
}> & withOptionalNavigationOptions<Options>; }> &
withOptionalNavigationOptions<Options>;
declare interface withRouter<State, Options> { declare interface withRouter<State, Options> {
router: NavigationRouter<State, Options>, router: NavigationRouter<State, Options>;
} }
declare export type NavigationNavigator< declare export type NavigationNavigator<
@@ -307,7 +308,9 @@ declare module 'react-navigation' {
> = React$ComponentType<{ > = React$ComponentType<{
...Props, ...Props,
...NavigationNavigatorProps<Options, State>, ...NavigationNavigatorProps<Options, State>,
}> & withRouter<State, Options> & withOptionalNavigationOptions<Options>; }> &
withRouter<State, Options> &
withOptionalNavigationOptions<Options>;
declare export type NavigationRouteConfig = declare export type NavigationRouteConfig =
| NavigationComponent | NavigationComponent
@@ -449,6 +452,7 @@ declare module 'react-navigation' {
tabBarTestIDProps?: { testID?: string, accessibilityLabel?: string }, tabBarTestIDProps?: { testID?: string, accessibilityLabel?: string },
tabBarOnPress?: ({ tabBarOnPress?: ({
navigation: NavigationScreenProp<NavigationRoute>, navigation: NavigationScreenProp<NavigationRoute>,
defaultHandler: () => void,
}) => void, }) => void,
|}; |};
@@ -503,10 +507,6 @@ declare module 'react-navigation' {
}; };
declare export type NavigationScreenProp<+S> = { declare export type NavigationScreenProp<+S> = {
...$ObjMap<
_DefaultActionCreators,
<Args>((...args: Args) => *) => (...args: Args) => boolean
>,
+state: S, +state: S,
dispatch: NavigationDispatch, dispatch: NavigationDispatch,
addListener: ( addListener: (
@@ -515,6 +515,21 @@ declare module 'react-navigation' {
) => NavigationEventSubscription, ) => NavigationEventSubscription,
getParam: (paramName: string, fallback?: any) => any, getParam: (paramName: string, fallback?: any) => any,
isFocused: () => boolean, isFocused: () => boolean,
// Shared action creators that exist for all routers
goBack: (routeKey?: ?string) => boolean,
navigate: (
routeName:
| string
| {
routeName: string,
params?: NavigationParams,
action?: NavigationNavigateAction,
key?: string,
},
params?: NavigationParams,
action?: NavigationNavigateAction
) => boolean,
setParams: (newParams: NavigationParams) => boolean,
// StackRouter action creators // StackRouter action creators
pop?: (n?: number, params?: { immediate?: boolean }) => boolean, pop?: (n?: number, params?: { immediate?: boolean }) => boolean,
popToTop?: (params?: { immediate?: boolean }) => boolean, popToTop?: (params?: { immediate?: boolean }) => boolean,
@@ -553,7 +568,9 @@ declare module 'react-navigation' {
> = React$ComponentType<{ > = React$ComponentType<{
...Props, ...Props,
...NavigationContainerProps<State, Options>, ...NavigationContainerProps<State, Options>,
}> & withRouter<State, Options> & withOptionalNavigationOptions<Options>; }> &
withRouter<State, Options> &
withOptionalNavigationOptions<Options>;
declare export type NavigationContainerProps<S: {}, O: {}> = $Shape<{ declare export type NavigationContainerProps<S: {}, O: {}> = $Shape<{
uriPrefix?: string | RegExp, uriPrefix?: string | RegExp,
@@ -791,26 +808,6 @@ declare module 'react-navigation' {
}) => NavigationToggleDrawerAction, }) => NavigationToggleDrawerAction,
}; };
declare type _DefaultActionCreators = {|
goBack: (routeKey?: ?string) => NavigationBackAction,
navigate: (
routeName:
| string
| {
routeName: string,
params?: NavigationParams,
action?: NavigationNavigateAction,
key?: string,
},
params?: NavigationParams,
action?: NavigationNavigateAction
) => NavigationNavigateAction,
setParams: (newParams: NavigationParams) => NavigationSetParamsAction,
|};
declare export function getNavigationActionCreators(
route: NavigationRoute | NavigationState
): _DefaultActionCreators;
declare type _RouterProp<S: NavigationState, O: {}> = { declare type _RouterProp<S: NavigationState, O: {}> = {
router: NavigationRouter<S, O>, router: NavigationRouter<S, O>,
}; };
@@ -1162,4 +1159,13 @@ declare module 'react-navigation' {
declare export function withNavigationFocus<Props: {}>( declare export function withNavigationFocus<Props: {}>(
Component: React$ComponentType<Props> Component: React$ComponentType<Props>
): React$ComponentType<$Diff<Props, { isFocused: boolean | void }>>; ): React$ComponentType<$Diff<Props, { isFocused: boolean | void }>>;
declare export function getNavigation<State: NavigationState, Options: {}>(
router: NavigationRouter<State, Options>,
state: State,
dispatch: NavigationDispatch,
actionSubscribers: Set<NavigationEventCallback>,
getScreenProps: () => {},
getCurrentNavigation: () => NavigationScreenProp<State>
): NavigationScreenProp<State>;
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-navigation", "name": "react-navigation",
"version": "2.2.0", "version": "2.5.1",
"description": "Routing and navigation for your React Native apps", "description": "Routing and navigation for your React Native apps",
"main": "src/react-navigation.js", "main": "src/react-navigation.js",
"repository": { "repository": {
@@ -33,12 +33,11 @@
"create-react-context": "^0.2.1", "create-react-context": "^0.2.1",
"hoist-non-react-statics": "^2.2.0", "hoist-non-react-statics": "^2.2.0",
"path-to-regexp": "^1.7.0", "path-to-regexp": "^1.7.0",
"prop-types": "^15.5.10",
"react-lifecycles-compat": "^3", "react-lifecycles-compat": "^3",
"react-native-drawer-layout-polyfill": "^1.3.2",
"react-native-safe-area-view": "^0.8.0", "react-native-safe-area-view": "^0.8.0",
"react-navigation-deprecated-tab-navigator": "1.3.0", "react-navigation-deprecated-tab-navigator": "1.3.0",
"react-navigation-tabs": "0.5.0" "react-navigation-drawer": "0.4.1",
"react-navigation-tabs": "0.5.1"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.24.1", "babel-cli": "^6.24.1",

View File

@@ -5,7 +5,9 @@ import renderer from 'react-test-renderer';
import NavigationActions from '../NavigationActions'; import NavigationActions from '../NavigationActions';
import createStackNavigator from '../navigators/createStackNavigator'; import createStackNavigator from '../navigators/createStackNavigator';
import { _TESTING_ONLY_reset_container_count } from '../createNavigationContainer'; import createNavigationContainer, {
_TESTING_ONLY_reset_container_count,
} from '../createNavigationContainer';
describe('NavigationContainer', () => { describe('NavigationContainer', () => {
jest.useFakeTimers(); jest.useFakeTimers();
@@ -19,7 +21,7 @@ describe('NavigationContainer', () => {
const CarScreen = () => <div />; const CarScreen = () => <div />;
const DogScreen = () => <div />; const DogScreen = () => <div />;
const ElkScreen = () => <div />; const ElkScreen = () => <div />;
const NavigationContainer = createStackNavigator( const Stack = createStackNavigator(
{ {
foo: { foo: {
screen: FooScreen, screen: FooScreen,
@@ -44,6 +46,7 @@ describe('NavigationContainer', () => {
initialRouteName: 'foo', initialRouteName: 'foo',
} }
); );
const NavigationContainer = createNavigationContainer(Stack);
describe('state.nav', () => { describe('state.nav', () => {
it("should be preloaded with the router's initial state", () => { it("should be preloaded with the router's initial state", () => {
@@ -225,7 +228,7 @@ describe('NavigationContainer', () => {
let spy = spyConsole(); let spy = spyConsole();
it('warns when you render more than one navigator explicitly', () => { it('warns when you render more than one container explicitly', () => {
class BlankScreen extends React.Component { class BlankScreen extends React.Component {
render() { render() {
return <View />; return <View />;
@@ -242,13 +245,17 @@ describe('NavigationContainer', () => {
} }
} }
const ChildNavigator = createStackNavigator({ const ChildNavigator = createNavigationContainer(
Child: BlankScreen, createStackNavigator({
}); Child: BlankScreen,
})
);
const RootStack = createStackNavigator({ const RootStack = createNavigationContainer(
Root: RootScreen, createStackNavigator({
}); Root: RootScreen,
})
);
renderer.create(<RootStack />).toJSON(); renderer.create(<RootStack />).toJSON();
expect(spy).toMatchSnapshot(); expect(spy).toMatchSnapshot();

View File

@@ -1,11 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NavigationContainer warnings detached navigators warns when you render more than one navigator explicitly 1`] = ` exports[`NavigationContainer warnings detached navigators warns when you render more than one container explicitly 1`] = `
Object { Object {
"console": [MockFunction] { "console": [MockFunction] {
"calls": Array [ "calls": Array [
Array [ Array [
"You should only render one navigator explicitly in your app, and other navigators should by rendered by including them in that navigator. Full details at: https://v2.reactnavigation.org/docs/common-mistakes.html#explicitly-rendering-more-than-one-navigator", "You should only render one navigator explicitly in your app, and other navigators should by rendered by including them in that navigator. Full details at: https://reactnavigation.org/docs/common-mistakes.html#explicitly-rendering-more-than-one-navigator",
], ],
], ],
}, },

View File

@@ -0,0 +1,102 @@
import getNavigation from '../getNavigation';
test('getNavigation provides default action helpers', () => {
const router = {
getActionCreators: () => ({}),
getStateForAction(action, lastState = {}) {
return lastState;
},
};
const dispatch = jest.fn();
const topNav = getNavigation(
router,
{},
dispatch,
new Set(),
() => ({}),
() => topNav
);
topNav.navigate('GreatRoute');
expect(dispatch.mock.calls.length).toBe(1);
expect(dispatch.mock.calls[0][0].type).toBe('Navigation/NAVIGATE');
expect(dispatch.mock.calls[0][0].routeName).toBe('GreatRoute');
});
test('getNavigation provides router action helpers', () => {
const router = {
getActionCreators: () => ({
foo: bar => ({ type: 'FooBarAction', bar }),
}),
getStateForAction(action, lastState = {}) {
return lastState;
},
};
const dispatch = jest.fn();
const topNav = getNavigation(
router,
{},
dispatch,
new Set(),
() => ({}),
() => topNav
);
topNav.foo('Great');
expect(dispatch.mock.calls.length).toBe(1);
expect(dispatch.mock.calls[0][0].type).toBe('FooBarAction');
expect(dispatch.mock.calls[0][0].bar).toBe('Great');
});
test('getNavigation get child navigation with router', () => {
const actionSubscribers = new Set();
let navigation = null;
const routerA = {
getActionCreators: () => ({}),
getStateForAction(action, lastState = {}) {
return lastState;
},
};
const router = {
childRouters: {
RouteA: routerA,
},
getActionCreators: () => ({}),
getStateForAction(action, lastState = {}) {
return lastState;
},
};
const initState = {
index: 0,
routes: [
{
key: 'a',
routeName: 'RouteA',
routes: [{ key: 'c', routeName: 'RouteC' }],
index: 0,
},
{ key: 'b', routeName: 'RouteB' },
],
};
const topNav = getNavigation(
router,
initState,
() => {},
actionSubscribers,
() => ({}),
() => navigation
);
const childNavA = topNav.getChildNavigation('a');
expect(childNavA.router).toBe(routerA);
});

View File

@@ -4,8 +4,8 @@ import { polyfill } from 'react-lifecycles-compat';
import { BackHandler } from './PlatformHelpers'; import { BackHandler } from './PlatformHelpers';
import NavigationActions from './NavigationActions'; import NavigationActions from './NavigationActions';
import getNavigation from './getNavigation';
import invariant from './utils/invariant'; import invariant from './utils/invariant';
import getNavigationActionCreators from './routers/getNavigationActionCreators';
import docsUrl from './utils/docsUrl'; import docsUrl from './utils/docsUrl';
function isStateful(props) { function isStateful(props) {
@@ -286,7 +286,7 @@ export default function createNavigationContainer(Component) {
); );
this.dispatch(NavigationActions.init()); this.dispatch(NavigationActions.init());
} else { } else {
throw new Error(e); throw e;
} }
} }
@@ -358,34 +358,24 @@ export default function createNavigationContainer(Component) {
return false; return false;
}; };
_getScreenProps = () => this.props.screenProps;
render() { render() {
let navigation = this.props.navigation; let navigation = this.props.navigation;
if (this._isStateful()) { if (this._isStateful()) {
const nav = this.state.nav; const navState = this.state.nav;
if (!nav) { if (!navState) {
return this._renderLoading(); return this._renderLoading();
} }
if (!this._navigation || this._navigation.state !== nav) { if (!this._navigation || this._navigation.state !== navState) {
this._navigation = { this._navigation = getNavigation(
dispatch: this.dispatch, Component.router,
state: nav, navState,
addListener: (eventName, handler) => { this.dispatch,
if (eventName !== 'action') { this._actionEventSubscribers,
return { remove: () => {} }; this._getScreenProps,
} () => this._navigation
this._actionEventSubscribers.add(handler); );
return {
remove: () => {
this._actionEventSubscribers.delete(handler);
},
};
},
};
const actionCreators = getNavigationActionCreators(nav);
Object.keys(actionCreators).forEach(actionName => {
this._navigation[actionName] = (...args) =>
this.dispatch(actionCreators[actionName](...args));
});
} }
navigation = this._navigation; navigation = this._navigation;
} }

102
src/getChildNavigation.js Normal file
View File

@@ -0,0 +1,102 @@
import getChildEventSubscriber from './getChildEventSubscriber';
import getChildRouter from './getChildRouter';
import invariant from './utils/invariant';
const createParamGetter = route => (paramName, defaultValue) => {
const params = route.params;
if (params && paramName in params) {
return params[paramName];
}
return defaultValue;
};
function getChildNavigation(navigation, childKey, getCurrentParentNavigation) {
const children =
navigation._childrenNavigation || (navigation._childrenNavigation = {});
const childRoute = navigation.state.routes.find(r => r.key === childKey);
if (children[childKey] && children[childKey].state === childRoute) {
return children[childKey];
}
const childRouter = getChildRouter(navigation.router, childRoute.routeName);
// If the route has children, we'll use this to pass in to the action creators
// for the childRouter so that any action that depends on the active route will
// behave as expected. We don't explicitly require that routers implement routes
// and index properties, but if we did then we would put an invariant here to
// ensure that a focusedGrandChildRoute exists if childRouter is defined.
const focusedGrandChildRoute =
childRoute.routes && typeof childRoute.index === 'number'
? childRoute.routes[childRoute.index]
: null;
const actionCreators = {
...navigation.actions,
...navigation.router.getActionCreators(childRoute, navigation.state.key),
...(childRouter
? childRouter.getActionCreators(focusedGrandChildRoute, childRoute.key)
: {}),
};
const actionHelpers = {};
Object.keys(actionCreators).forEach(actionName => {
actionHelpers[actionName] = (...args) => {
const actionCreator = actionCreators[actionName];
const action = actionCreator(...args);
return navigation.dispatch(action);
};
});
if (children[childKey]) {
children[childKey] = {
...children[childKey],
...actionHelpers,
state: childRoute,
router: childRouter,
actions: actionCreators,
getParam: createParamGetter(childRoute),
};
return children[childKey];
}
const childSubscriber = getChildEventSubscriber(
navigation.addListener,
childKey
);
children[childKey] = {
...actionHelpers,
state: childRoute,
router: childRouter,
actions: actionCreators,
getParam: createParamGetter(childRoute),
getChildNavigation: grandChildKey =>
getChildNavigation(children[childKey], grandChildKey, () =>
getCurrentParentNavigation().getChildNavigation(childKey)
),
isFocused: () => {
const currentNavigation = getCurrentParentNavigation();
const { routes, index } = currentNavigation.state;
if (!currentNavigation.isFocused()) {
return false;
}
if (routes[index].key === childKey) {
return true;
}
return false;
},
dispatch: navigation.dispatch,
getScreenProps: navigation.getScreenProps,
dangerouslyGetParent: getCurrentParentNavigation,
addListener: childSubscriber.addListener,
};
return children[childKey];
}
export default getChildNavigation;

9
src/getChildRouter.js Normal file
View File

@@ -0,0 +1,9 @@
export default function getChildRouter(router, routeName) {
if (router.childRouters && router.childRouters[routeName]) {
return router.childRouters[routeName];
}
const Component = router.getComponentForRouteName(routeName);
return Component.router;
}

54
src/getNavigation.js Normal file
View File

@@ -0,0 +1,54 @@
import getNavigationActionCreators from './routers/getNavigationActionCreators';
import getChildNavigation from './getChildNavigation';
export default function getNavigation(
router,
state,
dispatch,
actionSubscribers,
getScreenProps,
getCurrentNavigation
) {
const actions = router.getActionCreators(state, null);
const navigation = {
actions,
router,
state,
dispatch,
getScreenProps,
getChildNavigation: childKey =>
getChildNavigation(navigation, childKey, getCurrentNavigation),
isFocused: childKey => {
const { routes, index } = getCurrentNavigation().state;
if (childKey == null || routes[index].key === childKey) {
return true;
}
return false;
},
addListener: (eventName, handler) => {
if (eventName !== 'action') {
return { remove: () => {} };
}
actionSubscribers.add(handler);
return {
remove: () => {
actionSubscribers.delete(handler);
},
};
},
dangerouslyGetParent: () => null,
};
const actionCreators = {
...getNavigationActionCreators(navigation.state),
...actions,
};
Object.keys(actionCreators).forEach(actionName => {
navigation[actionName] = (...args) =>
navigation.dispatch(actionCreators[actionName](...args));
});
return navigation;
}

View File

@@ -1,33 +0,0 @@
import React, { Component } from 'react';
import { View } from 'react-native';
import renderer from 'react-test-renderer';
import DrawerNavigator from '../createDrawerNavigator';
class HomeScreen extends Component {
static navigationOptions = ({ navigation }) => ({
title: `Welcome ${
navigation.state.params ? navigation.state.params.user : 'anonymous'
}`,
gesturesEnabled: true,
});
render() {
return null;
}
}
const routeConfig = {
Home: {
screen: HomeScreen,
},
};
describe('DrawerNavigator', () => {
it('renders successfully', () => {
const MyDrawerNavigator = DrawerNavigator(routeConfig);
const rendered = renderer.create(<MyDrawerNavigator />).toJSON();
expect(rendered).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,40 @@
import React from 'react';
import renderer from 'react-test-renderer';
import StackNavigator from '../createContainedStackNavigator';
const SubNavigator = StackNavigator({
Home: {
screen: () => null,
},
});
const NavNestedDirect = StackNavigator({
Sub: {
screen: SubNavigator,
},
});
const NavNestedIndirect = StackNavigator({
Sub: {
// eslint-disable-next-line react/display-name
screen: props => <SubNavigator {...props} />,
},
});
/* Prevent React error boundaries from swallowing the errors */
NavNestedIndirect.prototype.componentDidCatch = null;
SubNavigator.prototype.componentDidCatch = null;
describe('Nested navigators', () => {
it('renders succesfully as direct child', () => {
const rendered = renderer.create(<NavNestedDirect />).toJSON();
expect(rendered).toMatchSnapshot();
});
it('throw when trying to pass navigation prop', () => {
const tryRender = () => {
renderer.create(<NavNestedIndirect />);
};
expect(tryRender).toThrowErrorMatchingSnapshot();
});
});

View File

@@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native'; import { StyleSheet, View } from 'react-native';
import renderer from 'react-test-renderer'; import renderer from 'react-test-renderer';
import StackNavigator from '../createStackNavigator'; import StackNavigator from '../createContainedStackNavigator';
import withNavigation from '../../views/withNavigation'; import withNavigation from '../../views/withNavigation';
import { _TESTING_ONLY_reset_container_count } from '../../createNavigationContainer'; import { _TESTING_ONLY_reset_container_count } from '../../createNavigationContainer';

View File

@@ -2,7 +2,7 @@ import React, { Component } from 'react';
import { View } from 'react-native'; import { View } from 'react-native';
import renderer from 'react-test-renderer'; import renderer from 'react-test-renderer';
import SwitchNavigator from '../createSwitchNavigator'; import SwitchNavigator from '../createContainedSwitchNavigator';
const A = () => <View />; const A = () => <View />;
const B = () => <View />; const B = () => <View />;

View File

@@ -1,243 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DrawerNavigator renders successfully 1`] = `
<View
onMoveShouldSetResponder={[Function]}
onMoveShouldSetResponderCapture={[Function]}
onResponderEnd={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderReject={[Function]}
onResponderRelease={[Function]}
onResponderStart={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
onStartShouldSetResponderCapture={[Function]}
style={
Object {
"backgroundColor": "transparent",
"flex": 1,
}
}
>
<View
collapsable={undefined}
style={
Object {
"flex": 1,
"zIndex": 0,
}
}
/>
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
collapsable={undefined}
hitSlop={undefined}
nativeID={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
pointerEvents="none"
style={
Object {
"backgroundColor": "#000",
"bottom": 0,
"left": 0,
"opacity": 0,
"position": "absolute",
"right": 0,
"top": 0,
"zIndex": 1000,
}
}
testID={undefined}
/>
<View
accessibilityViewIsModal={false}
collapsable={undefined}
style={
Object {
"backgroundColor": "white",
"bottom": 0,
"left": 0,
"position": "absolute",
"right": null,
"top": 0,
"transform": Array [
Object {
"translateX": -320,
},
],
"width": 320,
"zIndex": 1001,
}
}
>
<View
style={
Array [
Object {
"flex": 1,
},
undefined,
]
}
>
<RCTScrollView
DEPRECATED_sendUpdatedChildFrames={false}
alwaysBounceHorizontal={undefined}
alwaysBounceVertical={false}
onContentSizeChange={null}
onMomentumScrollBegin={[Function]}
onMomentumScrollEnd={[Function]}
onResponderGrant={[Function]}
onResponderReject={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={undefined}
onResponderTerminationRequest={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollEndDrag={[Function]}
onScrollShouldSetResponder={[Function]}
onStartShouldSetResponder={[Function]}
onStartShouldSetResponderCapture={[Function]}
onTouchCancel={[Function]}
onTouchEnd={[Function]}
onTouchMove={[Function]}
onTouchStart={[Function]}
scrollEventThrottle={undefined}
sendMomentumEvents={false}
style={
Array [
Object {
"flexDirection": "column",
"flexGrow": 1,
"flexShrink": 1,
"overflow": "scroll",
},
undefined,
]
}
>
<RCTScrollContentView
collapsable={false}
removeClippedSubviews={undefined}
style={
Array [
undefined,
undefined,
]
}
>
<View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={
Object {
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
}
}
>
<View
style={
Array [
Object {
"paddingVertical": 4,
},
undefined,
]
}
>
<View
accessibilityComponentType={undefined}
accessibilityLabel={undefined}
accessibilityTraits={undefined}
accessible={true}
collapsable={undefined}
hasTVPreferredFocus={undefined}
hitSlop={undefined}
isTVSelectable={true}
nativeID={undefined}
onLayout={undefined}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
Object {
"opacity": 1,
}
}
testID={undefined}
tvParallaxProperties={undefined}
>
<View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={
Object {
"backgroundColor": "rgba(0, 0, 0, .04)",
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 0,
}
}
>
<View
style={
Array [
Object {
"alignItems": "center",
"flexDirection": "row",
},
undefined,
]
}
>
<Text
accessible={true}
allowFontScaling={true}
ellipsizeMode="tail"
style={
Array [
Object {
"fontWeight": "bold",
"margin": 16,
},
Object {
"color": "#2196f3",
},
undefined,
undefined,
]
}
>
Welcome anonymous
</Text>
</View>
</View>
</View>
</View>
</View>
</RCTScrollContentView>
</RCTScrollView>
</View>
</View>
</View>
`;

View File

@@ -0,0 +1,369 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Nested navigators renders succesfully as direct child 1`] = `
<View
onLayout={[Function]}
style={
Array [
Object {
"flex": 1,
},
]
}
>
<View
onMoveShouldSetResponder={[Function]}
onMoveShouldSetResponderCapture={[Function]}
onResponderEnd={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderReject={[Function]}
onResponderRelease={[Function]}
onResponderStart={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
onStartShouldSetResponderCapture={[Function]}
style={
Array [
Object {
"flex": 1,
"flexDirection": "column-reverse",
},
Object {
"backgroundColor": "#000",
},
]
}
>
<View
style={
Object {
"flex": 1,
}
}
>
<View
collapsable={undefined}
pointerEvents="auto"
style={
Object {
"backgroundColor": "#E9E9EF",
"bottom": 0,
"left": 0,
"marginTop": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"shadowColor": "black",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.2,
"shadowRadius": 5,
"top": 0,
"transform": Array [
Object {
"translateX": 0,
},
Object {
"translateY": 0,
},
],
}
}
>
<View
onLayout={[Function]}
style={
Array [
Object {
"flex": 1,
},
]
}
>
<View
onMoveShouldSetResponder={[Function]}
onMoveShouldSetResponderCapture={[Function]}
onResponderEnd={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderReject={[Function]}
onResponderRelease={[Function]}
onResponderStart={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
onStartShouldSetResponderCapture={[Function]}
style={
Array [
Object {
"flex": 1,
"flexDirection": "column-reverse",
},
Object {
"backgroundColor": "#000",
},
]
}
>
<View
style={
Object {
"flex": 1,
}
}
>
<View
collapsable={undefined}
pointerEvents="auto"
style={
Object {
"backgroundColor": "#E9E9EF",
"bottom": 0,
"left": 0,
"marginTop": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"shadowColor": "black",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.2,
"shadowRadius": 5,
"top": 0,
"transform": Array [
Object {
"translateX": 0,
},
Object {
"translateY": 0,
},
],
}
}
/>
</View>
<View
onLayout={[Function]}
pointerEvents="box-none"
>
<View
collapsable={undefined}
style={
Object {
"transform": Array [
Object {
"translateX": 0,
},
],
}
}
>
<View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={
Object {
"backgroundColor": "#F7F7F7",
"borderBottomColor": "#A7A7AA",
"borderBottomWidth": 0.5,
"height": 64,
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
}
}
>
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
<View
style={
Object {
"flex": 1,
}
}
>
<View
style={
Object {
"bottom": 0,
"flexDirection": "row",
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"justifyContent": "center",
"left": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<Text
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
<View
onLayout={[Function]}
pointerEvents="box-none"
>
<View
collapsable={undefined}
style={
Object {
"transform": Array [
Object {
"translateX": 0,
},
],
}
}
>
<View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={
Object {
"backgroundColor": "#F7F7F7",
"borderBottomColor": "#A7A7AA",
"borderBottomWidth": 0.5,
"height": 64,
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
}
}
>
<View
style={
Object {
"bottom": 0,
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
<View
style={
Object {
"flex": 1,
}
}
>
<View
style={
Object {
"bottom": 0,
"flexDirection": "row",
"left": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"justifyContent": "center",
"left": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<Text
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
</View>
`;
exports[`Nested navigators throw when trying to pass navigation prop 1`] = `"No \\"routes\\" found in navigation state. Did you try to pass the navigation prop of a React component to a Navigator child? See https://reactnavigation.org/docs/en/custom-navigators.html#navigator-navigation-prop"`;

View File

@@ -76,50 +76,36 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
/> />
</View> </View>
<View <View
collapsable={undefined} onLayout={[Function]}
style={ pointerEvents="box-none"
Object {
"transform": Array [
Object {
"translateX": 0,
},
],
}
}
> >
<View <View
collapsable={undefined} collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={ style={
Object { Object {
"backgroundColor": "red", "transform": Array [
"borderBottomColor": "#A7A7AA", Object {
"borderBottomWidth": 0.5, "translateX": 0,
"height": 64, },
"opacity": 0.5, ],
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
} }
} }
> >
<View <View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={ style={
Object { Object {
"bottom": 0, "backgroundColor": "red",
"left": 0, "borderBottomColor": "#A7A7AA",
"position": "absolute", "borderBottomWidth": 0.5,
"right": 0, "height": 64,
"top": 0, "opacity": 0.5,
} "paddingBottom": 0,
} "paddingLeft": 0,
/> "paddingRight": 0,
<View "paddingTop": 20,
style={
Object {
"flex": 1,
} }
} }
> >
@@ -127,70 +113,89 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
style={ style={
Object { Object {
"bottom": 0, "bottom": 0,
"flexDirection": "row",
"left": 0, "left": 0,
"position": "absolute", "position": "absolute",
"right": 0, "right": 0,
"top": 0, "top": 0,
} }
} }
/>
<View
style={
Object {
"flex": 1,
}
}
> >
<View <View
collapsable={undefined}
pointerEvents="box-none"
style={ style={
Object { Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0, "bottom": 0,
"flexDirection": "row", "flexDirection": "row",
"justifyContent": "center", "left": 0,
"left": 70,
"opacity": 1,
"position": "absolute",
"right": 70,
"top": 0,
}
}
>
<Text
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
>
Welcome anonymous
</Text>
</View>
<View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"opacity": 1,
"position": "absolute", "position": "absolute",
"right": 0, "right": 0,
"top": 0, "top": 0,
} }
} }
> >
<View /> <View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"justifyContent": "center",
"left": 70,
"opacity": 1,
"position": "absolute",
"right": 70,
"top": 0,
}
}
>
<Text
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
>
Welcome anonymous
</Text>
</View>
<View
collapsable={undefined}
pointerEvents="box-none"
style={
Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0,
"flexDirection": "row",
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
}
}
>
<View />
</View>
</View> </View>
</View> </View>
</View> </View>
@@ -276,50 +281,36 @@ exports[`StackNavigator renders successfully 1`] = `
/> />
</View> </View>
<View <View
collapsable={undefined} onLayout={[Function]}
style={ pointerEvents="box-none"
Object {
"transform": Array [
Object {
"translateX": 0,
},
],
}
}
> >
<View <View
collapsable={undefined} collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={ style={
Object { Object {
"backgroundColor": "red", "transform": Array [
"borderBottomColor": "#A7A7AA", Object {
"borderBottomWidth": 0.5, "translateX": 0,
"height": 64, },
"opacity": 0.5, ],
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 20,
} }
} }
> >
<View <View
collapsable={undefined}
onLayout={[Function]}
pointerEvents="box-none"
style={ style={
Object { Object {
"bottom": 0, "backgroundColor": "red",
"left": 0, "borderBottomColor": "#A7A7AA",
"position": "absolute", "borderBottomWidth": 0.5,
"right": 0, "height": 64,
"top": 0, "opacity": 0.5,
} "paddingBottom": 0,
} "paddingLeft": 0,
/> "paddingRight": 0,
<View "paddingTop": 20,
style={
Object {
"flex": 1,
} }
} }
> >
@@ -327,52 +318,71 @@ exports[`StackNavigator renders successfully 1`] = `
style={ style={
Object { Object {
"bottom": 0, "bottom": 0,
"flexDirection": "row",
"left": 0, "left": 0,
"position": "absolute", "position": "absolute",
"right": 0, "right": 0,
"top": 0, "top": 0,
} }
} }
/>
<View
style={
Object {
"flex": 1,
}
}
> >
<View <View
collapsable={undefined}
pointerEvents="box-none"
style={ style={
Object { Object {
"alignItems": "center",
"backgroundColor": "transparent",
"bottom": 0, "bottom": 0,
"flexDirection": "row", "flexDirection": "row",
"justifyContent": "center",
"left": 0, "left": 0,
"opacity": 1,
"position": "absolute", "position": "absolute",
"right": 0, "right": 0,
"top": 0, "top": 0,
} }
} }
> >
<Text <View
accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined} collapsable={undefined}
ellipsizeMode="tail" pointerEvents="box-none"
numberOfLines={1}
onLayout={[Function]}
style={ style={
Object { Object {
"color": "rgba(0, 0, 0, .9)", "alignItems": "center",
"fontSize": 17, "backgroundColor": "transparent",
"fontWeight": "700", "bottom": 0,
"marginHorizontal": 16, "flexDirection": "row",
"textAlign": "center", "justifyContent": "center",
"left": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
} }
} }
> >
Welcome anonymous <Text
</Text> accessibilityTraits="header"
accessible={true}
allowFontScaling={true}
collapsable={undefined}
ellipsizeMode="tail"
numberOfLines={1}
onLayout={[Function]}
style={
Object {
"color": "rgba(0, 0, 0, .9)",
"fontSize": 17,
"fontWeight": "700",
"marginHorizontal": 16,
"textAlign": "center",
}
}
>
Welcome anonymous
</Text>
</View>
</View> </View>
</View> </View>
</View> </View>

View File

@@ -0,0 +1,9 @@
import createNavigationContainer from '../createNavigationContainer';
import createStackNavigator from './createStackNavigator';
const StackNavigator = (routeConfigs, config = {}) => {
const navigator = createStackNavigator(routeConfigs, config);
return createNavigationContainer(navigator);
};
export default StackNavigator;

View File

@@ -0,0 +1,9 @@
import createNavigationContainer from '../createNavigationContainer';
import createSwitchNavigator from './createSwitchNavigator';
const SwitchNavigator = (routeConfigs, config = {}) => {
const navigator = createSwitchNavigator(routeConfigs, config);
return createNavigationContainer(navigator);
};
export default SwitchNavigator;

View File

@@ -1,72 +0,0 @@
import React from 'react';
import { Dimensions, Platform, ScrollView } from 'react-native';
import SafeAreaView from 'react-native-safe-area-view';
import createNavigator from './createNavigator';
import createNavigationContainer from '../createNavigationContainer';
import DrawerRouter from '../routers/DrawerRouter';
import DrawerView from '../views/Drawer/DrawerView';
import DrawerItems from '../views/Drawer/DrawerNavigatorItems';
// A stack navigators props are the intersection between
// the base navigator props (navgiation, screenProps, etc)
// and the view's props
const defaultContentComponent = props => (
<ScrollView alwaysBounceVertical={false}>
<SafeAreaView forceInset={{ top: 'always', horizontal: 'never' }}>
<DrawerItems {...props} />
</SafeAreaView>
</ScrollView>
);
const DefaultDrawerConfig = {
drawerWidth: () => {
/*
* Default drawer width is screen width - header height
* with a max width of 280 on mobile and 320 on tablet
* https://material.io/guidelines/patterns/navigation-drawer.html
*/
const { height, width } = Dimensions.get('window');
const smallerAxisSize = Math.min(height, width);
const isLandscape = width > height;
const isTablet = smallerAxisSize >= 600;
const appBarHeight = Platform.OS === 'ios' ? (isLandscape ? 32 : 44) : 56;
const maxWidth = isTablet ? 320 : 280;
return Math.min(smallerAxisSize - appBarHeight, maxWidth);
},
contentComponent: defaultContentComponent,
drawerPosition: 'left',
drawerBackgroundColor: 'white',
useNativeAnimations: true,
};
const DrawerNavigator = (routeConfigs, config = {}) => {
const mergedConfig = { ...DefaultDrawerConfig, ...config };
const {
order,
paths,
initialRouteName,
backBehavior,
getCustomActionCreators,
...drawerConfig
} = mergedConfig;
const routerConfig = {
order,
paths,
initialRouteName,
backBehavior,
getCustomActionCreators,
};
const drawerRouter = DrawerRouter(routeConfigs, routerConfig);
const navigator = createNavigator(DrawerView, drawerRouter, drawerConfig);
return createNavigationContainer(navigator);
};
export default DrawerNavigator;

View File

@@ -30,12 +30,12 @@ export default Navigator =>
if (this._previouslyFocusedTextInput) { if (this._previouslyFocusedTextInput) {
TextInput.State.focusTextInput(this._previouslyFocusedTextInput); TextInput.State.focusTextInput(this._previouslyFocusedTextInput);
} }
this.props.onGestureFinish && this.props.onGestureFinish(); this.props.onGestureCanceled && this.props.onGestureCanceled();
}; };
_handleGestureFinish = () => { _handleGestureFinish = () => {
this._previouslyFocusedTextInput = null; this._previouslyFocusedTextInput = null;
this.props.onGestureCanceled && this.props.onGestureCanceled(); this.props.onGestureFinish && this.props.onGestureFinish();
}; };
_handleTransitionStart = (transitionProps, prevTransitionProps) => { _handleTransitionStart = (transitionProps, prevTransitionProps) => {

View File

@@ -10,122 +10,56 @@ function createNavigator(NavigatorView, router, navigationConfig) {
state = { state = {
descriptors: {}, descriptors: {},
childEventSubscribers: {}, screenProps: this.props.screenProps,
}; };
static getDerivedStateFromProps(nextProps, prevState) { static getDerivedStateFromProps(nextProps, prevState) {
const prevDescriptors = prevState.descriptors;
const { navigation, screenProps } = nextProps; const { navigation, screenProps } = nextProps;
const { dispatch, state, addListener } = navigation; const { dispatch, state, addListener } = navigation;
const { routes } = state; const { routes } = state;
if (typeof routes === 'undefined') {
throw new TypeError(
'No "routes" found in navigation state. Did you try to pass the navigation prop of a React component to a Navigator child? See https://reactnavigation.org/docs/en/custom-navigators.html#navigator-navigation-prop'
);
}
const descriptors = { ...prevState.descriptors }; const descriptors = { ...prevState.descriptors };
const childEventSubscribers = { ...prevState.childEventSubscribers };
routes.forEach(route => { routes.forEach(route => {
if (!descriptors[route.key] || descriptors[route.key].state !== route) { if (
const getComponent = () => prevDescriptors &&
router.getComponentForRouteName(route.routeName); prevDescriptors[route.key] &&
route === prevDescriptors[route.key].state &&
if (!childEventSubscribers[route.key]) { screenProps === prevState.screenProps
childEventSubscribers[route.key] = getChildEventSubscriber( ) {
addListener, descriptors[route.key] = prevDescriptors[route.key];
route.key return;
);
}
const actionCreators = {
...navigation.actions,
...router.getActionCreators(route, state.key),
};
const actionHelpers = {};
Object.keys(actionCreators).forEach(actionName => {
actionHelpers[actionName] = (...args) => {
const actionCreator = actionCreators[actionName];
const action = actionCreator(...args);
dispatch(action);
};
});
const childNavigation = {
...actionHelpers,
actions: actionCreators,
dispatch,
state: route,
addListener: childEventSubscribers[route.key].addListener,
getParam: (paramName, defaultValue) => {
const params = route.params;
if (params && paramName in params) {
return params[paramName];
}
return defaultValue;
},
};
const options = router.getScreenOptions(childNavigation, screenProps);
descriptors[route.key] = {
key: route.key,
getComponent,
options,
state: route,
navigation: childNavigation,
};
} }
const getComponent = () =>
router.getComponentForRouteName(route.routeName);
const childNavigation = navigation.getChildNavigation(route.key);
const options = router.getScreenOptions(childNavigation, screenProps);
descriptors[route.key] = {
key: route.key,
getComponent,
options,
state: route,
navigation: childNavigation,
};
}); });
return { return { descriptors, screenProps };
descriptors,
childEventSubscribers,
};
} }
// Cleanup subscriptions for routes that no longer exist
componentDidUpdate() {
const activeKeys = this.props.navigation.state.routes.map(r => r.key);
let childEventSubscribers = { ...this.state.childEventSubscribers };
Object.keys(childEventSubscribers).forEach(key => {
if (!activeKeys.includes(key)) {
delete childEventSubscribers[key];
}
});
if (
childEventSubscribers.length !== this.state.childEventSubscribers.length
) {
this.setState({ childEventSubscribers });
}
}
_isRouteFocused = route => {
const { state } = this.props.navigation;
const focusedRoute = state.routes[state.index];
return route === focusedRoute;
};
_dangerouslyGetParent = () => {
return this.props.navigation;
};
render() { render() {
// Mutation in render 😩
// The problem:
// - We don't want to re-render each screen every time the parent navigator changes
// - But we need to be able to access the parent navigator from callbacks
// - These functions should only be used within callbacks, but they are passed in props,
// which is what makes this awkward. What's a good way to pass in stuff that we don't
// want people to depend on in render?
let descriptors = { ...this.state.descriptors };
Object.values(descriptors).forEach(descriptor => {
descriptor.navigation.isFocused = () =>
this._isRouteFocused(descriptor.state);
descriptor.navigation.dangerouslyGetParent = this._dangerouslyGetParent;
});
return ( return (
<NavigatorView <NavigatorView
{...this.props} {...this.props}
screenProps={this.props.screenProps} screenProps={this.state.screenProps}
navigation={this.props.navigation} navigation={this.props.navigation}
navigationConfig={navigationConfig} navigationConfig={navigationConfig}
descriptors={descriptors} descriptors={this.state.descriptors}
/> />
); );
} }

View File

@@ -1,5 +1,3 @@
import * as React from 'react';
import createNavigationContainer from '../createNavigationContainer';
import createKeyboardAwareNavigator from './createKeyboardAwareNavigator'; import createKeyboardAwareNavigator from './createKeyboardAwareNavigator';
import createNavigator from './createNavigator'; import createNavigator from './createNavigator';
import StackView from '../views/StackView/StackView'; import StackView from '../views/StackView/StackView';
@@ -33,8 +31,7 @@ function createStackNavigator(routeConfigMap, stackConfig = {}) {
Navigator = createKeyboardAwareNavigator(Navigator); Navigator = createKeyboardAwareNavigator(Navigator);
} }
// HOC to provide the navigation prop for the top-level navigator (when the prop is missing) return Navigator;
return createNavigationContainer(Navigator);
} }
export default createStackNavigator; export default createStackNavigator;

View File

@@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import createNavigationContainer from '../createNavigationContainer';
import createNavigator from '../navigators/createNavigator'; import createNavigator from '../navigators/createNavigator';
import SwitchRouter from '../routers/SwitchRouter'; import SwitchRouter from '../routers/SwitchRouter';
import SwitchView from '../views/SwitchView/SwitchView'; import SwitchView from '../views/SwitchView/SwitchView';
@@ -7,7 +6,7 @@ import SwitchView from '../views/SwitchView/SwitchView';
function createSwitchNavigator(routeConfigMap, switchConfig = {}) { function createSwitchNavigator(routeConfigMap, switchConfig = {}) {
const router = SwitchRouter(routeConfigMap, switchConfig); const router = SwitchRouter(routeConfigMap, switchConfig);
const Navigator = createNavigator(SwitchView, router, switchConfig); const Navigator = createNavigator(SwitchView, router, switchConfig);
return createNavigationContainer(Navigator); return Navigator;
} }
export default createSwitchNavigator; export default createSwitchNavigator;

View File

@@ -8,37 +8,40 @@ module.exports = {
get StateUtils() { get StateUtils() {
return require('./StateUtils').default; return require('./StateUtils').default;
}, },
get getNavigation() {
return require('./getNavigation').default;
},
// Navigators // Navigators
get createNavigator() { get createNavigator() {
return require('./navigators/createNavigator').default; return require('./navigators/createNavigator').default;
}, },
get createStackNavigator() { get createStackNavigator() {
return require('./navigators/createStackNavigator').default; return require('./navigators/createContainedStackNavigator').default;
}, },
get StackNavigator() { get StackNavigator() {
console.warn( console.warn(
'The StackNavigator function name is deprecated, please use createStackNavigator instead' 'The StackNavigator function name is deprecated, please use createStackNavigator instead'
); );
return require('./navigators/createStackNavigator').default; return require('./navigators/createContainedStackNavigator').default;
}, },
get createSwitchNavigator() { get createSwitchNavigator() {
return require('./navigators/createSwitchNavigator').default; return require('./navigators/createContainedSwitchNavigator').default;
}, },
get SwitchNavigator() { get SwitchNavigator() {
console.warn( console.warn(
'The SwitchNavigator function name is deprecated, please use createSwitchNavigator instead' 'The SwitchNavigator function name is deprecated, please use createSwitchNavigator instead'
); );
return require('./navigators/createSwitchNavigator').default; return require('./navigators/createContainedSwitchNavigator').default;
}, },
get createDrawerNavigator() { get createDrawerNavigator() {
return require('./navigators/createDrawerNavigator').default; return require('react-navigation-drawer').createDrawerNavigator;
}, },
get DrawerNavigator() { get DrawerNavigator() {
console.warn( console.warn(
'The DrawerNavigator function name is deprecated, please use createDrawerNavigator instead' 'The DrawerNavigator function name is deprecated, please use createDrawerNavigator instead'
); );
return require('./navigators/createDrawerNavigator').default; return require('react-navigation-drawer').createDrawerNavigator;
}, },
get createTabNavigator() { get createTabNavigator() {
console.warn( console.warn(
@@ -69,10 +72,7 @@ module.exports = {
return require('./routers/StackActions').default; return require('./routers/StackActions').default;
}, },
get DrawerActions() { get DrawerActions() {
return require('./routers/DrawerActions').default; return require('react-navigation-drawer').DrawerActions;
},
get getNavigationActionCreators() {
return require('./routers/getNavigationActionCreators').default;
}, },
// Routers // Routers
@@ -83,7 +83,7 @@ module.exports = {
return require('./routers/TabRouter').default; return require('./routers/TabRouter').default;
}, },
get DrawerRouter() { get DrawerRouter() {
return require('./routers/DrawerRouter').default; return require('react-navigation-drawer').DrawerRouter;
}, },
get SwitchRouter() { get SwitchRouter() {
return require('./routers/SwitchRouter').default; return require('./routers/SwitchRouter').default;
@@ -122,13 +122,13 @@ module.exports = {
// DrawerView // DrawerView
get DrawerView() { get DrawerView() {
return require('./views/Drawer/DrawerView').default; return require('react-navigation-drawer').DrawerView;
}, },
get DrawerItems() { get DrawerItems() {
return require('./views/Drawer/DrawerNavigatorItems').default; return require('react-navigation-drawer').DrawerNavigatorItems;
}, },
get DrawerSidebar() { get DrawerSidebar() {
return require('./views/Drawer/DrawerSidebar').default; return require('react-navigation-drawer').DrawerSidebar;
}, },
// TabView // TabView

View File

@@ -24,9 +24,6 @@ module.exports = {
get DrawerActions() { get DrawerActions() {
return require('./routers/DrawerActions').default; return require('./routers/DrawerActions').default;
}, },
get getNavigationActionCreators() {
return require('./routers/getNavigationActionCreators').default;
},
// Routers // Routers
get StackRouter() { get StackRouter() {

View File

@@ -1,28 +0,0 @@
const OPEN_DRAWER = 'Navigation/OPEN_DRAWER';
const CLOSE_DRAWER = 'Navigation/CLOSE_DRAWER';
const TOGGLE_DRAWER = 'Navigation/TOGGLE_DRAWER';
const openDrawer = payload => ({
type: OPEN_DRAWER,
...payload,
});
const closeDrawer = payload => ({
type: CLOSE_DRAWER,
...payload,
});
const toggleDrawer = payload => ({
type: TOGGLE_DRAWER,
...payload,
});
export default {
OPEN_DRAWER,
CLOSE_DRAWER,
TOGGLE_DRAWER,
openDrawer,
closeDrawer,
toggleDrawer,
};

View File

@@ -1,98 +0,0 @@
import SwitchRouter from './SwitchRouter';
import NavigationActions from '../NavigationActions';
import invariant from '../utils/invariant';
import withDefaultValue from '../utils/withDefaultValue';
import DrawerActions from './DrawerActions';
const getActiveRouteKey = route => {
if (route.routes && route.routes[route.index]) {
return getActiveRouteKey(route.routes[route.index]);
}
return route.key;
};
export default (routeConfigs, config = {}) => {
config = { ...config };
config = withDefaultValue(config, 'resetOnBlur', false);
config = withDefaultValue(config, 'backBehavior', 'initialRoute');
const switchRouter = SwitchRouter(routeConfigs, config);
return {
...switchRouter,
getActionCreators(route, navStateKey) {
return {
openDrawer: () => DrawerActions.openDrawer({ key: navStateKey }),
closeDrawer: () => DrawerActions.closeDrawer({ key: navStateKey }),
toggleDrawer: () => DrawerActions.toggleDrawer({ key: navStateKey }),
...switchRouter.getActionCreators(route, navStateKey),
};
},
getStateForAction(action, state) {
// Set up the initial state if needed
if (!state) {
return {
...switchRouter.getStateForAction(action, undefined),
isDrawerOpen: false,
};
}
const isRouterTargeted = action.key == null || action.key === state.key;
if (isRouterTargeted) {
// Only handle actions that are meant for this drawer, as specified by action.key.
if (action.type === DrawerActions.CLOSE_DRAWER && state.isDrawerOpen) {
return {
...state,
isDrawerOpen: false,
};
}
if (action.type === DrawerActions.OPEN_DRAWER && !state.isDrawerOpen) {
return {
...state,
isDrawerOpen: true,
};
}
if (action.type === DrawerActions.TOGGLE_DRAWER) {
return {
...state,
isDrawerOpen: !state.isDrawerOpen,
};
}
}
// Fall back on switch router for screen switching logic, and handling of child routers
const switchedState = switchRouter.getStateForAction(action, state);
if (switchedState === null) {
// The switch router or a child router is attempting to swallow this action. We return null to allow this.
return null;
}
// Has the switch router changed the state?
if (switchedState !== state) {
if (getActiveRouteKey(switchedState) !== getActiveRouteKey(state)) {
// If any navigation has happened, make sure to close the drawer
return {
...switchedState,
isDrawerOpen: false,
};
}
// At this point, return the state as defined by the switch router.
// The active route key hasn't changed, so this most likely means that a child router has returned
// a new state like a param change, but the same key is still active and the drawer will remain open
return switchedState;
}
return state;
},
};
};

View File

@@ -149,6 +149,8 @@ export default (routeConfigs, stackConfig = {}) => {
paths.sort((a, b) => b[1].priority - a[1].priority); paths.sort((a, b) => b[1].priority - a[1].priority);
return { return {
childRouters,
getComponentForState(state) { getComponentForState(state) {
const activeChildRoute = state.routes[state.index]; const activeChildRoute = state.routes[state.index];
const { routeName } = activeChildRoute; const { routeName } = activeChildRoute;
@@ -399,7 +401,10 @@ export default (routeConfigs, stackConfig = {}) => {
routeName: childRouterName, routeName: childRouterName,
key: action.key || generateKey(), key: action.key || generateKey(),
}; };
return StateUtils.push(state, route); return {
...StateUtils.push(state, route),
isTransitioning: action.immediate !== true,
};
} }
} }
} }

View File

@@ -74,37 +74,39 @@ export default (routeConfigs, config = {}) => {
}; };
} }
return { function getNextState(prevState, possibleNextState) {
getInitialState() { if (!prevState) {
const routes = order.map(resetChildRoute); return possibleNextState;
}
let nextState;
if (prevState.index !== possibleNextState.index && resetOnBlur) {
const prevRouteName = prevState.routes[prevState.index].routeName;
const nextRoutes = [...possibleNextState.routes];
nextRoutes[prevState.index] = resetChildRoute(prevRouteName);
return { return {
routes, ...possibleNextState,
index: initialRouteIndex, routes: nextRoutes,
isTransitioning: false,
}; };
}, } else {
nextState = possibleNextState;
}
getNextState(prevState, possibleNextState) { return nextState;
if (!prevState) { }
return possibleNextState;
}
let nextState; function getInitialState() {
if (prevState.index !== possibleNextState.index && resetOnBlur) { const routes = order.map(resetChildRoute);
const prevRouteName = prevState.routes[prevState.index].routeName; return {
const nextRoutes = [...possibleNextState.routes]; routes,
nextRoutes[prevState.index] = resetChildRoute(prevRouteName); index: initialRouteIndex,
isTransitioning: false,
};
}
return { return {
...possibleNextState, childRouters,
routes: nextRoutes,
};
} else {
nextState = possibleNextState;
}
return nextState;
},
getActionCreators(route, stateKey) { getActionCreators(route, stateKey) {
return { return {
@@ -115,7 +117,7 @@ export default (routeConfigs, config = {}) => {
getStateForAction(action, inputState) { getStateForAction(action, inputState) {
let prevState = inputState ? { ...inputState } : inputState; let prevState = inputState ? { ...inputState } : inputState;
let state = inputState || this.getInitialState(); let state = inputState || getInitialState();
let activeChildIndex = state.index; let activeChildIndex = state.index;
if (action.type === NavigationActions.INIT) { if (action.type === NavigationActions.INIT) {
@@ -152,7 +154,7 @@ export default (routeConfigs, config = {}) => {
if (activeChildState && activeChildState !== activeChildLastState) { if (activeChildState && activeChildState !== activeChildLastState) {
const routes = [...state.routes]; const routes = [...state.routes];
routes[state.index] = activeChildState; routes[state.index] = activeChildState;
return this.getNextState(prevState, { return getNextState(prevState, {
...state, ...state,
routes, routes,
}); });
@@ -202,7 +204,7 @@ export default (routeConfigs, config = {}) => {
if (newChildState && newChildState !== childState) { if (newChildState && newChildState !== childState) {
const routes = [...state.routes]; const routes = [...state.routes];
routes[activeChildIndex] = newChildState; routes[activeChildIndex] = newChildState;
return this.getNextState(prevState, { return getNextState(prevState, {
...state, ...state,
routes, routes,
index: activeChildIndex, index: activeChildIndex,
@@ -230,7 +232,7 @@ export default (routeConfigs, config = {}) => {
...lastRoute, ...lastRoute,
params, params,
}; };
return this.getNextState(prevState, { return getNextState(prevState, {
...state, ...state,
routes, routes,
}); });
@@ -238,7 +240,7 @@ export default (routeConfigs, config = {}) => {
} }
if (activeChildIndex !== state.index) { if (activeChildIndex !== state.index) {
return this.getNextState(prevState, { return getNextState(prevState, {
...state, ...state,
index: activeChildIndex, index: activeChildIndex,
}); });
@@ -282,7 +284,7 @@ export default (routeConfigs, config = {}) => {
} }
if (index !== state.index || routes !== state.routes) { if (index !== state.index || routes !== state.routes) {
return this.getNextState(prevState, { return getNextState(prevState, {
...state, ...state,
index, index,
routes, routes,

View File

@@ -1,176 +0,0 @@
/* eslint react/display-name:0 */
import React from 'react';
import DrawerRouter from '../DrawerRouter';
import NavigationActions from '../../NavigationActions';
import DrawerActions from '../../routers/DrawerActions';
const INIT_ACTION = { type: NavigationActions.INIT };
describe('DrawerRouter', () => {
test('Handles basic tab logic', () => {
const ScreenA = () => <div />;
const ScreenB = () => <div />;
const router = DrawerRouter({
Foo: { screen: ScreenA },
Bar: { screen: ScreenB },
});
const state = router.getStateForAction(INIT_ACTION);
const expectedState = {
index: 0,
isTransitioning: false,
routes: [
{ key: 'Foo', routeName: 'Foo', params: undefined },
{ key: 'Bar', routeName: 'Bar', params: undefined },
],
isDrawerOpen: false,
};
expect(state).toEqual(expectedState);
const state2 = router.getStateForAction(
{ type: NavigationActions.NAVIGATE, routeName: 'Bar' },
state
);
const expectedState2 = {
index: 1,
isTransitioning: false,
routes: [
{ key: 'Foo', routeName: 'Foo', params: undefined },
{ key: 'Bar', routeName: 'Bar', params: undefined },
],
isDrawerOpen: false,
};
expect(state2).toEqual(expectedState2);
expect(router.getComponentForState(expectedState)).toEqual(ScreenA);
expect(router.getComponentForState(expectedState2)).toEqual(ScreenB);
});
test('Handles initial route navigation', () => {
const FooScreen = () => <div />;
const BarScreen = () => <div />;
const router = DrawerRouter(
{
Foo: {
screen: FooScreen,
},
Bar: {
screen: BarScreen,
},
},
{ initialRouteName: 'Bar' }
);
const state = router.getStateForAction({
type: NavigationActions.NAVIGATE,
routeName: 'Foo',
});
expect(state).toEqual({
index: 0,
isDrawerOpen: false,
isTransitioning: false,
routes: [
{
key: 'Foo',
params: undefined,
routeName: 'Foo',
},
{
key: 'Bar',
params: undefined,
routeName: 'Bar',
},
],
});
});
test('Drawer opens closes and toggles', () => {
const ScreenA = () => <div />;
const ScreenB = () => <div />;
const router = DrawerRouter({
Foo: { screen: ScreenA },
Bar: { screen: ScreenB },
});
const state = router.getStateForAction(INIT_ACTION);
expect(state.isDrawerOpen).toEqual(false);
const state2 = router.getStateForAction(
{ type: DrawerActions.OPEN_DRAWER },
state
);
expect(state2.isDrawerOpen).toEqual(true);
const state3 = router.getStateForAction(
{ type: DrawerActions.CLOSE_DRAWER },
state2
);
expect(state3.isDrawerOpen).toEqual(false);
const state4 = router.getStateForAction(
{ type: DrawerActions.TOGGLE_DRAWER },
state3
);
expect(state4.isDrawerOpen).toEqual(true);
});
test('Drawer opens closes with key targeted', () => {
const ScreenA = () => <div />;
const ScreenB = () => <div />;
const router = DrawerRouter({
Foo: { screen: ScreenA },
Bar: { screen: ScreenB },
});
const state = router.getStateForAction(INIT_ACTION);
const state2 = router.getStateForAction(
{ type: DrawerActions.OPEN_DRAWER, key: 'wrong' },
state
);
expect(state2.isDrawerOpen).toEqual(false);
const state3 = router.getStateForAction(
{ type: DrawerActions.OPEN_DRAWER, key: state.key },
state2
);
expect(state3.isDrawerOpen).toEqual(true);
});
});
test('Nested routers bubble up blocked actions', () => {
const ScreenA = () => <div />;
ScreenA.router = {
getStateForAction(action, lastState) {
if (action.type === 'CHILD_ACTION') return null;
return lastState;
},
};
const ScreenB = () => <div />;
const router = DrawerRouter({
Foo: { screen: ScreenA },
Bar: { screen: ScreenB },
});
const state = router.getStateForAction(INIT_ACTION);
const state2 = router.getStateForAction({ type: 'CHILD_ACTION' }, state);
expect(state2).toEqual(null);
});
test('Drawer stays open when child routers return new state', () => {
const ScreenA = () => <div />;
ScreenA.router = {
getStateForAction(action, lastState = { changed: false }) {
if (action.type === 'CHILD_ACTION')
return { ...lastState, changed: true };
return lastState;
},
};
const router = DrawerRouter({
Foo: { screen: ScreenA },
});
const state = router.getStateForAction(INIT_ACTION);
expect(state.isDrawerOpen).toEqual(false);
const state2 = router.getStateForAction(
{ type: DrawerActions.OPEN_DRAWER, key: state.key },
state
);
expect(state2.isDrawerOpen).toEqual(true);
const state3 = router.getStateForAction({ type: 'CHILD_ACTION' }, state2);
expect(state3.isDrawerOpen).toEqual(true);
expect(state3.routes[0].changed).toEqual(true);
});

View File

@@ -5,10 +5,8 @@ import React from 'react';
import StackRouter from '../StackRouter'; import StackRouter from '../StackRouter';
import TabRouter from '../TabRouter'; import TabRouter from '../TabRouter';
import SwitchRouter from '../SwitchRouter'; import SwitchRouter from '../SwitchRouter';
import DrawerRouter from '../DrawerRouter';
import NavigationActions from '../../NavigationActions'; import NavigationActions from '../../NavigationActions';
import DrawerActions from '../DrawerActions';
import { _TESTING_ONLY_normalize_keys } from '../KeyGenerator'; import { _TESTING_ONLY_normalize_keys } from '../KeyGenerator';
beforeEach(() => { beforeEach(() => {
@@ -18,7 +16,6 @@ beforeEach(() => {
const ROUTERS = { const ROUTERS = {
TabRouter, TabRouter,
StackRouter, StackRouter,
DrawerRouter,
SwitchRouter, SwitchRouter,
}; };
@@ -471,53 +468,3 @@ test('Inner actions are only unpacked if the current tab matches', () => {
innerState && comparable(innerState) innerState && comparable(innerState)
); );
}); });
test('DrawerRouter will close drawer on child navigaton, not on child param changes', () => {
class FooView extends React.Component {
render() {
return <div />;
}
}
const BarRouter = SwitchRouter({
Qux: FooView,
Quo: FooView,
});
class BarView extends React.Component {
static router = BarRouter;
render() {
return <div />;
}
}
const router = DrawerRouter({
Bar: BarView,
Foo: FooView,
});
const emptyState = router.getStateForAction(NavigationActions.init());
const initState = router.getStateForAction(
DrawerActions.openDrawer(),
emptyState
);
expect(initState.isDrawerOpen).toBe(true);
const state0 = router.getStateForAction(
NavigationActions.navigate({ routeName: 'Quo' }),
initState
);
expect(state0.isDrawerOpen).toBe(false);
const initSwitchState = initState.routes[initState.index];
const initQuxState = initSwitchState.routes[initSwitchState.index];
const state1 = router.getStateForAction(
NavigationActions.setParams({
key: initQuxState.key,
params: { foo: 'bar' },
}),
initState
);
expect(state1.isDrawerOpen).toBe(true);
const state1switchState = state1.routes[state1.index];
const state1quxState = state1switchState.routes[state1switchState.index];
expect(state1quxState.params.foo).toEqual('bar');
});

View File

@@ -426,12 +426,47 @@ describe('StackRouter', () => {
expect(state3 && state3.index).toEqual(0); expect(state3 && state3.index).toEqual(0);
}); });
test('Handle navigation to nested navigator', () => {
const state = TestStackRouter.getStateForAction({
type: NavigationActions.INIT,
});
const action = TestStackRouter.getActionForPathAndParams('fo/22/b/hello');
/* $FlowFixMe */
const state2 = TestStackRouter.getStateForAction(action);
expect(state2).toEqual({
index: 0,
isTransitioning: false,
key: 'StackRouterRoot',
routes: [
{
index: 0,
key: 'id-4',
isTransitioning: false,
routeName: 'foo',
params: {
fooThing: '22',
},
routes: [
{
routeName: 'bar',
key: 'id-3',
params: {
barThing: 'hello',
},
},
],
},
],
});
});
test('popToTop bubbles up', () => { test('popToTop bubbles up', () => {
const ChildNavigator = () => <div />; const ChildNavigator = () => <div />;
ChildNavigator.router = StackRouter({ ChildNavigator.router = StackRouter({
Baz: { screen: () => <div /> }, Baz: { screen: () => <div /> },
Qux: { screen: () => <div /> }, Qux: { screen: () => <div /> },
}); });
const router = StackRouter({ const router = StackRouter({
Foo: { screen: () => <div /> }, Foo: { screen: () => <div /> },
Bar: { screen: ChildNavigator }, Bar: { screen: ChildNavigator },
@@ -657,6 +692,7 @@ describe('StackRouter', () => {
state state
); );
expect(state2.isTransitioning).toEqual(true);
expect(state2.index).toEqual(1); expect(state2.index).toEqual(1);
expect(state2.routes[1].index).toEqual(1); expect(state2.routes[1].index).toEqual(1);
expect(state2.routes[1].routes[1].index).toEqual(1); expect(state2.routes[1].routes[1].index).toEqual(1);

View File

@@ -21,25 +21,24 @@ function validateRouteConfigMap(routeConfigs) {
typeof screenComponent !== 'string' && typeof screenComponent !== 'string' &&
!routeConfig.getScreen) !routeConfig.getScreen)
) { ) {
throw new Error( throw new Error(`The component for route '${routeName}' must be a React component. For example:
`The component for route '${routeName}' must be a ` +
'React component. For example:\n\n' + import MyScreen from './MyScreen';
"import MyScreen from './MyScreen';\n" + ...
'...\n' + ${routeName}: MyScreen,
`${routeName}: MyScreen,\n` + }
'}\n\n' +
'You can also use a navigator:\n\n' + You can also use a navigator:
"import MyNavigator from './MyNavigator';\n" +
'...\n' + import MyNavigator from './MyNavigator';
`${routeName}: MyNavigator,\n` + ...
'}' ${routeName}: MyNavigator,
); }`);
} }
if (routeConfig.screen && routeConfig.getScreen) { if (routeConfig.screen && routeConfig.getScreen) {
throw new Error( throw new Error(
`Route '${routeName}' should declare a screen or ` + `Route '${routeName}' should declare a screen or a getScreen, not both.`
'a getScreen, not both.'
); );
} }
}); });

View File

@@ -1,3 +1,3 @@
export default function docsUrl(path) { export default function docsUrl(path) {
return `https://v2.reactnavigation.org/docs/${path}`; return `https://reactnavigation.org/docs/${path}`;
} }

View File

@@ -1,14 +1,3 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
/** /**
* Use invariant() to assert state which your program assumes to be true. * Use invariant() to assert state which your program assumes to be true.
* *

View File

@@ -1,19 +1,5 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @typechecks
*
*/
/*eslint-disable no-self-compare */ /*eslint-disable no-self-compare */
'use strict';
const hasOwnProperty = Object.prototype.hasOwnProperty; const hasOwnProperty = Object.prototype.hasOwnProperty;
/** /**
@@ -71,4 +57,4 @@ function shallowEqual(objA, objB) {
return true; return true;
} }
module.exports = shallowEqual; export default shallowEqual;

View File

@@ -1,5 +1,5 @@
export default (obj, key, defaultValue) => { export default (obj, key, defaultValue) => {
if (obj.hasOwnProperty(key)) { if (obj.hasOwnProperty(key) && typeof obj[key] !== 'undefined') {
return obj; return obj;
} }

View File

@@ -1,119 +0,0 @@
import React from 'react';
import { View, Text, Platform, StyleSheet } from 'react-native';
import SafeAreaView from 'react-native-safe-area-view';
import TouchableItem from '../TouchableItem';
/**
* Component that renders the navigation list in the drawer.
*/
const DrawerNavigatorItems = ({
navigation: { state, navigate },
items,
activeItemKey,
activeTintColor,
activeBackgroundColor,
inactiveTintColor,
inactiveBackgroundColor,
getLabel,
renderIcon,
onItemPress,
itemsContainerStyle,
itemStyle,
labelStyle,
activeLabelStyle,
inactiveLabelStyle,
iconContainerStyle,
drawerPosition,
}) => (
<View style={[styles.container, itemsContainerStyle]}>
{items.map((route, index) => {
const focused = activeItemKey === route.key;
const color = focused ? activeTintColor : inactiveTintColor;
const backgroundColor = focused
? activeBackgroundColor
: inactiveBackgroundColor;
const scene = { route, index, focused, tintColor: color };
const icon = renderIcon(scene);
const label = getLabel(scene);
const extraLabelStyle = focused ? activeLabelStyle : inactiveLabelStyle;
return (
<TouchableItem
key={route.key}
onPress={() => {
onItemPress({ route, focused });
}}
delayPressIn={0}
>
<SafeAreaView
style={{ backgroundColor }}
forceInset={{
[drawerPosition]: 'always',
[drawerPosition === 'left' ? 'right' : 'left']: 'never',
vertical: 'never',
}}
>
<View style={[styles.item, itemStyle]}>
{icon ? (
<View
style={[
styles.icon,
focused ? null : styles.inactiveIcon,
iconContainerStyle,
]}
>
{icon}
</View>
) : null}
{typeof label === 'string' ? (
<Text
style={[styles.label, { color }, labelStyle, extraLabelStyle]}
>
{label}
</Text>
) : (
label
)}
</View>
</SafeAreaView>
</TouchableItem>
);
})}
</View>
);
/* Material design specs - https://material.io/guidelines/patterns/navigation-drawer.html#navigation-drawer-specs */
DrawerNavigatorItems.defaultProps = {
activeTintColor: '#2196f3',
activeBackgroundColor: 'rgba(0, 0, 0, .04)',
inactiveTintColor: 'rgba(0, 0, 0, .87)',
inactiveBackgroundColor: 'transparent',
};
const styles = StyleSheet.create({
container: {
paddingVertical: 4,
},
item: {
flexDirection: 'row',
alignItems: 'center',
},
icon: {
marginHorizontal: 16,
width: 24,
alignItems: 'center',
},
inactiveIcon: {
/*
* Icons have 0.54 opacity according to guidelines
* 100/87 * 54 ~= 62
*/
opacity: 0.62,
},
label: {
margin: 16,
fontWeight: 'bold',
},
});
export default DrawerNavigatorItems;

View File

@@ -1,105 +0,0 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import NavigationActions from '../../NavigationActions';
import StackActions from '../../routers/StackActions';
import invariant from '../../utils/invariant';
/**
* Component that renders the sidebar screen of the drawer.
*/
class DrawerSidebar extends React.PureComponent {
_getScreenOptions = routeKey => {
const descriptor = this.props.descriptors[routeKey];
invariant(
descriptor.options,
'Cannot access screen descriptor options from drawer sidebar'
);
return descriptor.options;
};
_getLabel = ({ focused, tintColor, route }) => {
const { drawerLabel, title } = this._getScreenOptions(route.key);
if (drawerLabel) {
return typeof drawerLabel === 'function'
? drawerLabel({ tintColor, focused })
: drawerLabel;
}
if (typeof title === 'string') {
return title;
}
return route.routeName;
};
_renderIcon = ({ focused, tintColor, route }) => {
const { drawerIcon } = this._getScreenOptions(route.key);
if (drawerIcon) {
return typeof drawerIcon === 'function'
? drawerIcon({ tintColor, focused })
: drawerIcon;
}
return null;
};
_onItemPress = ({ route, focused }) => {
if (!focused) {
let subAction;
// TODO (v3): Revisit and repeal this behavior:
// if the child screen is a StackRouter then always navigate to its first screen (see #1914)
if (route.index != null && route.index !== 0) {
subAction = StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
routeName: route.routes[0].routeName,
}),
],
});
}
this.props.navigation.dispatch(
NavigationActions.navigate({
routeName: route.routeName,
action: subAction,
})
);
}
};
render() {
const ContentComponent = this.props.contentComponent;
if (!ContentComponent) {
return null;
}
const { state } = this.props.navigation;
invariant(typeof state.index === 'number', 'should be set');
return (
<View style={[styles.container, this.props.style]}>
<ContentComponent
{...this.props.contentOptions}
navigation={this.props.navigation}
descriptors={this.props.descriptors}
items={state.routes}
activeItemKey={
state.routes[state.index] ? state.routes[state.index].key : null
}
screenProps={this.props.screenProps}
getLabel={this._getLabel}
renderIcon={this._renderIcon}
onItemPress={this._onItemPress}
drawerPosition={this.props.drawerPosition}
/>
</View>
);
}
}
export default DrawerSidebar;
const styles = StyleSheet.create({
container: {
flex: 1,
},
});

View File

@@ -1,127 +0,0 @@
import React from 'react';
import { Dimensions } from 'react-native';
import DrawerLayout from 'react-native-drawer-layout-polyfill';
import DrawerSidebar from './DrawerSidebar';
import NavigationActions from '../../NavigationActions';
import DrawerActions from '../../routers/DrawerActions';
/**
* Component that renders the drawer.
*/
export default class DrawerView extends React.PureComponent {
_drawerState = 'closed';
state = {
drawerWidth:
typeof this.props.navigationConfig.drawerWidth === 'function'
? this.props.navigationConfig.drawerWidth()
: this.props.navigationConfig.drawerWidth,
};
componentDidMount() {
Dimensions.addEventListener('change', this._updateWidth);
}
componentWillUnmount() {
Dimensions.removeEventListener('change', this._updateWidth);
}
componentDidUpdate(prevProps, prevState) {
const { isDrawerOpen } = this.props.navigation.state;
const wasDrawerOpen = prevProps.navigation.state.isDrawerOpen;
if (isDrawerOpen && !wasDrawerOpen && this._drawerState === 'closed') {
this._drawerState = 'opening';
this._drawer.openDrawer();
} else if (wasDrawerOpen && !isDrawerOpen && this._drawerState === 'open') {
this._drawerState = 'closing';
this._drawer.closeDrawer();
}
}
_handleDrawerOpen = () => {
const { navigation } = this.props;
const { isDrawerOpen } = navigation.state;
if (!isDrawerOpen && this._drawerState === 'closed') {
navigation.dispatch({ type: DrawerActions.OPEN_DRAWER });
}
this._drawerState = 'open';
};
_handleDrawerClose = () => {
const { navigation } = this.props;
const { isDrawerOpen } = navigation.state;
if (isDrawerOpen && this._drawerState === 'open') {
navigation.dispatch({ type: DrawerActions.CLOSE_DRAWER });
}
this._drawerState = 'closed';
};
_updateWidth = () => {
const drawerWidth =
typeof this.props.navigationConfig.drawerWidth === 'function'
? this.props.navigationConfig.drawerWidth()
: this.props.navigationConfig.drawerWidth;
if (this.state.drawerWidth !== drawerWidth) {
this.setState({ drawerWidth });
}
};
_renderNavigationView = () => {
return (
<DrawerSidebar
screenProps={this.props.screenProps}
navigation={this.props.navigation}
descriptors={this.props.descriptors}
contentComponent={this.props.navigationConfig.contentComponent}
contentOptions={this.props.navigationConfig.contentOptions}
drawerPosition={this.props.navigationConfig.drawerPosition}
style={this.props.navigationConfig.style}
{...this.props.navigationConfig}
/>
);
};
render() {
const { state } = this.props.navigation;
const activeKey = state.routes[state.index].key;
const descriptor = this.props.descriptors[activeKey];
const DrawerScreen = descriptor.getComponent();
const { drawerLockMode } = descriptor.options;
return (
<DrawerLayout
ref={c => {
this._drawer = c;
}}
drawerLockMode={
drawerLockMode ||
(this.props.screenProps && this.props.screenProps.drawerLockMode) ||
this.props.navigationConfig.drawerLockMode
}
drawerBackgroundColor={
this.props.navigationConfig.drawerBackgroundColor
}
drawerWidth={this.state.drawerWidth}
onDrawerOpen={this._handleDrawerOpen}
onDrawerClose={this._handleDrawerClose}
useNativeAnimations={this.props.navigationConfig.useNativeAnimations}
renderNavigationView={this._renderNavigationView}
drawerPosition={
this.props.navigationConfig.drawerPosition === 'right'
? DrawerLayout.positions.Right
: DrawerLayout.positions.Left
}
>
<DrawerScreen
screenProps={this.props.screenProps}
navigation={descriptor.navigation}
/>
</DrawerLayout>
);
}
}

View File

@@ -0,0 +1,3 @@
import { NavigationConsumer } from './NavigationContext';
export default NavigationConsumer;

View File

@@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import propTypes from 'prop-types';
import createReactContext from 'create-react-context'; import createReactContext from 'create-react-context';
const NavigationContext = createReactContext(); const NavigationContext = createReactContext();

View File

@@ -0,0 +1,3 @@
import { NavigationProvider } from './NavigationContext';
export default NavigationProvider;

View File

@@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import propTypes from 'prop-types';
import { NavigationProvider } from './NavigationContext'; import { NavigationProvider } from './NavigationContext';
export default class SceneView extends React.PureComponent { export default class SceneView extends React.PureComponent {

View File

@@ -65,6 +65,17 @@ export default function ScenesReducer(
prevState, prevState,
descriptors descriptors
) { ) {
// Always update the descriptors
// This is a workaround for https://github.com/react-navigation/react-navigation/issues/4271
// It will be resolved in a better way when we re-write Transitioner
scenes.forEach(scene => {
const { route } = scene;
if (descriptors && descriptors[route.key]) {
scene.descriptor = descriptors[route.key];
}
});
// Bail out early if we didn't update the state
if (prevState === nextState) { if (prevState === nextState) {
return scenes; return scenes;
} }

View File

@@ -1,9 +1,8 @@
import * as React from 'react'; import React from 'react';
import { NativeModules } from 'react-native'; import { NativeModules } from 'react-native';
import StackViewLayout from './StackViewLayout'; import StackViewLayout from './StackViewLayout';
import Transitioner from '../Transitioner'; import Transitioner from '../Transitioner';
import NavigationActions from '../../NavigationActions';
import StackActions from '../../routers/StackActions'; import StackActions from '../../routers/StackActions';
import TransitionConfigs from './StackViewTransitionConfigs'; import TransitionConfigs from './StackViewTransitionConfigs';
@@ -22,11 +21,13 @@ class StackView extends React.Component {
<Transitioner <Transitioner
render={this._render} render={this._render}
configureTransition={this._configureTransition} configureTransition={this._configureTransition}
screenProps={this.props.screenProps}
navigation={this.props.navigation} navigation={this.props.navigation}
descriptors={this.props.descriptors} descriptors={this.props.descriptors}
onTransitionStart={this.props.onTransitionStart} onTransitionStart={this.props.onTransitionStart}
onTransitionEnd={(transition, lastTransition) => { onTransitionEnd={(transition, lastTransition) => {
const { onTransitionEnd, navigation } = this.props; const { navigationConfig, navigation } = this.props;
const { onTransitionEnd } = navigationConfig;
if (transition.navigation.state.isTransitioning) { if (transition.navigation.state.isTransitioning) {
navigation.dispatch( navigation.dispatch(
StackActions.completeTransition({ StackActions.completeTransition({

View File

@@ -1,4 +1,4 @@
import * as React from 'react'; import React from 'react';
import clamp from 'clamp'; import clamp from 'clamp';
import { import {
@@ -21,7 +21,7 @@ import withOrientation from '../withOrientation';
import { NavigationProvider } from '../NavigationContext'; import { NavigationProvider } from '../NavigationContext';
import TransitionConfigs from './StackViewTransitionConfigs'; import TransitionConfigs from './StackViewTransitionConfigs';
import * as ReactNativeFeatures from '../../utils/ReactNativeFeatures'; import { supportsImprovedSpringAnimation } from '../../utils/ReactNativeFeatures';
const emptyFunction = () => {}; const emptyFunction = () => {};
@@ -89,6 +89,11 @@ class StackViewLayout extends React.Component {
*/ */
_immediateIndex = null; _immediateIndex = null;
state = {
// Used when card's header is null and mode is float to make switch animation work correctly
floatingHeaderHeight: 0,
};
_renderHeader(scene, headerMode) { _renderHeader(scene, headerMode) {
const { options } = scene.descriptor; const { options } = scene.descriptor;
const { header } = options; const { header } = options;
@@ -114,20 +119,24 @@ class StackViewLayout extends React.Component {
const { const {
mode, mode,
transitionProps, transitionProps,
prevTransitionProps, lastTransitionProps,
...passProps ...passProps
} = this.props; } = this.props;
return renderHeader({ return (
...passProps, <NavigationProvider value={scene.descriptor.navigation}>
...transitionProps, {renderHeader({
scene, ...passProps,
mode: headerMode, ...transitionProps,
transitionPreset: this._getHeaderTransitionPreset(), scene,
leftInterpolator: headerLeftInterpolator, mode: headerMode,
titleInterpolator: headerTitleInterpolator, transitionPreset: this._getHeaderTransitionPreset(),
rightInterpolator: headerRightInterpolator, leftInterpolator: headerLeftInterpolator,
}); titleInterpolator: headerTitleInterpolator,
rightInterpolator: headerRightInterpolator,
})}
</NavigationProvider>
);
} }
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
@@ -145,10 +154,7 @@ class StackViewLayout extends React.Component {
} }
_reset(resetToIndex, duration) { _reset(resetToIndex, duration) {
if ( if (Platform.OS === 'ios' && supportsImprovedSpringAnimation()) {
Platform.OS === 'ios' &&
ReactNativeFeatures.supportsImprovedSpringAnimation()
) {
Animated.spring(this.props.transitionProps.position, { Animated.spring(this.props.transitionProps.position, {
toValue: resetToIndex, toValue: resetToIndex,
stiffness: 5000, stiffness: 5000,
@@ -188,10 +194,7 @@ class StackViewLayout extends React.Component {
} }
}; };
if ( if (Platform.OS === 'ios' && supportsImprovedSpringAnimation()) {
Platform.OS === 'ios' &&
ReactNativeFeatures.supportsImprovedSpringAnimation()
) {
Animated.spring(position, { Animated.spring(position, {
toValue, toValue,
stiffness: 5000, stiffness: 5000,
@@ -227,7 +230,7 @@ class StackViewLayout extends React.Component {
return false; return false;
} }
position.stopAnimation((value: number) => { position.stopAnimation(value => {
this._isResponding = true; this._isResponding = true;
this._gestureStartValue = value; this._gestureStartValue = value;
}); });
@@ -235,7 +238,7 @@ class StackViewLayout extends React.Component {
}, },
onMoveShouldSetPanResponder: (event, gesture) => { onMoveShouldSetPanResponder: (event, gesture) => {
const { const {
transitionProps: { navigation, position, layout, scene, scenes }, transitionProps: { navigation, layout, scene },
mode, mode,
} = this.props; } = this.props;
const { index } = navigation.state; const { index } = navigation.state;
@@ -391,30 +394,27 @@ class StackViewLayout extends React.Component {
}, },
}); });
_onFloatingHeaderLayout = e => {
this.setState({ floatingHeaderHeight: e.nativeEvent.layout.height });
};
render() { render() {
let floatingHeader = null; let floatingHeader = null;
const headerMode = this._getHeaderMode(); const headerMode = this._getHeaderMode();
if (headerMode === 'float') { if (headerMode === 'float') {
const { scene } = this.props.transitionProps; const { scene } = this.props.transitionProps;
floatingHeader = ( floatingHeader = (
<NavigationProvider value={scene.descriptor.navigation}> <View pointerEvents="box-none" onLayout={this._onFloatingHeaderLayout}>
{this._renderHeader(scene, headerMode)} {this._renderHeader(scene, headerMode)}
</NavigationProvider> </View>
); );
} }
const { const {
transitionProps: { navigation, position, layout, scene, scenes }, transitionProps: { scene, scenes },
mode, mode,
} = this.props; } = this.props;
const { index } = navigation.state;
const isVertical = mode === 'modal';
const { options } = scene.descriptor; const { options } = scene.descriptor;
const gestureDirection = options.gestureDirection;
const gestureDirectionInverted =
typeof gestureDirection === 'string'
? gestureDirection === 'inverted'
: I18nManager.isRTL;
const gesturesEnabled = const gesturesEnabled =
typeof options.gesturesEnabled === 'boolean' typeof options.gesturesEnabled === 'boolean'
@@ -499,13 +499,14 @@ class StackViewLayout extends React.Component {
return TransitionConfigs.getTransitionConfig( return TransitionConfigs.getTransitionConfig(
this.props.transitionConfig, this.props.transitionConfig,
this.props.transitionProps, this.props.transitionProps,
this.props.prevTransitionProps, this.props.lastTransitionProps,
isModal isModal
); );
}; };
_renderCard = scene => { _renderCard = scene => {
const { screenInterpolator } = this._getTransitionConfig(); const { screenInterpolator } = this._getTransitionConfig();
const style = const style =
screenInterpolator && screenInterpolator &&
screenInterpolator({ ...this.props.transitionProps, scene }); screenInterpolator({ ...this.props.transitionProps, scene });
@@ -518,21 +519,7 @@ class StackViewLayout extends React.Component {
const headerMode = this._getHeaderMode(); const headerMode = this._getHeaderMode();
let marginTop = 0; let marginTop = 0;
if (!hasHeader && headerMode === 'float') { if (!hasHeader && headerMode === 'float') {
const { isLandscape } = this.props; marginTop = -this.state.floatingHeaderHeight;
let headerHeight;
if (Platform.OS === 'ios') {
if (isLandscape && !Platform.isPad) {
headerHeight = 52;
} else if (IS_IPHONE_X) {
headerHeight = 88;
} else {
headerHeight = 64;
}
} else {
headerHeight = 56;
// TODO (Android only): Need to handle translucent status bar.
}
marginTop = -headerHeight;
} }
return ( return (

View File

@@ -1,9 +1,9 @@
import { Animated, Easing, Platform } from 'react-native'; import { Animated, Easing, Platform } from 'react-native';
import StyleInterpolator from './StackViewStyleInterpolator'; import StyleInterpolator from './StackViewStyleInterpolator';
import * as ReactNativeFeatures from '../../utils/ReactNativeFeatures'; import { supportsImprovedSpringAnimation } from '../../utils/ReactNativeFeatures';
let IOSTransitionSpec; let IOSTransitionSpec;
if (ReactNativeFeatures.supportsImprovedSpringAnimation()) { if (supportsImprovedSpringAnimation()) {
// These are the exact values from UINavigationController's animation configuration // These are the exact values from UINavigationController's animation configuration
IOSTransitionSpec = { IOSTransitionSpec = {
timing: Animated.spring, timing: Animated.spring,

View File

@@ -63,6 +63,12 @@ class Transitioner extends React.Component {
nextScenes = filterStale(nextScenes); nextScenes = filterStale(nextScenes);
} }
// Update nextScenes when we change screenProps
// This is a workaround for https://github.com/react-navigation/react-navigation/issues/4271
if (nextProps.screenProps !== this.props.screenProps) {
this.setState({ nextScenes });
}
if (nextScenes === this.state.scenes) { if (nextScenes === this.state.scenes) {
return; return;
} }

View File

@@ -1,5 +1,5 @@
/* eslint react/display-name:0 */ /* eslint react/display-name:0 */
import * as React from 'react'; import React from 'react';
import renderer from 'react-test-renderer'; import renderer from 'react-test-renderer';
import Transitioner from '../Transitioner'; import Transitioner from '../Transitioner';

255
yarn.lock
View File

@@ -3,14 +3,14 @@
"@babel/code-frame@^7.0.0-beta.35": "@babel/code-frame@^7.0.0-beta.35":
version "7.0.0-beta.49" version "7.0.0-beta.51"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.49.tgz#becd805482734440c9d137e46d77340e64d7f51b" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.51.tgz#bd71d9b192af978df915829d39d4094456439a0c"
dependencies: dependencies:
"@babel/highlight" "7.0.0-beta.49" "@babel/highlight" "7.0.0-beta.51"
"@babel/highlight@7.0.0-beta.49": "@babel/highlight@7.0.0-beta.51":
version "7.0.0-beta.49" version "7.0.0-beta.51"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.49.tgz#96bdc6b43e13482012ba6691b1018492d39622cc" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.51.tgz#e8844ae25a1595ccfd42b89623b4376ca06d225d"
dependencies: dependencies:
chalk "^2.0.0" chalk "^2.0.0"
esutils "^2.0.2" esutils "^2.0.2"
@@ -59,8 +59,8 @@ acorn@^3.0.4:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0: acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0:
version "5.5.3" version "5.7.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
ajv-keywords@^2.1.0: ajv-keywords@^2.1.0:
version "2.1.1" version "2.1.1"
@@ -163,19 +163,19 @@ app-root-path@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46" resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46"
append-transform@^0.4.0: append-transform@^1.0.0:
version "0.4.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab"
dependencies: dependencies:
default-require-extensions "^1.0.0" default-require-extensions "^2.0.0"
aproba@^1.0.3: aproba@^1.0.3:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
arch@^2.1.0: arch@^2.1.0:
version "2.1.0" version "2.1.1"
resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e"
are-we-there-yet@~1.1.2: are-we-there-yet@~1.1.2:
version "1.1.5" version "1.1.5"
@@ -1082,8 +1082,8 @@ bcrypt-pbkdf@^1.0.0:
tweetnacl "^0.14.3" tweetnacl "^0.14.3"
big-integer@^1.6.7: big-integer@^1.6.7:
version "1.6.28" version "1.6.31"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.28.tgz#8cef0fda3ccde8759c2c66efcfacc35aea658283" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.31.tgz#6d7852486e67c642502dcc03f7225a245c9fc7fa"
binary-extensions@^1.0.0: binary-extensions@^1.0.0:
version "1.11.0" version "1.11.0"
@@ -1157,8 +1157,8 @@ browser-process-hrtime@^0.1.2:
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e"
browser-resolve@^1.11.2: browser-resolve@^1.11.2:
version "1.11.2" version "1.11.3"
resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6"
dependencies: dependencies:
resolve "1.1.7" resolve "1.1.7"
@@ -1169,8 +1169,8 @@ bser@^2.0.0:
node-int64 "^0.4.0" node-int64 "^0.4.0"
buffer-from@^1.0.0: buffer-from@^1.0.0:
version "1.0.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04"
builtin-modules@^1.0.0: builtin-modules@^1.0.0:
version "1.1.1" version "1.1.1"
@@ -1385,14 +1385,14 @@ collection-visit@^1.0.0:
object-visit "^1.0.0" object-visit "^1.0.0"
color-convert@^1.9.0: color-convert@^1.9.0:
version "1.9.1" version "1.9.2"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147"
dependencies: dependencies:
color-name "^1.1.1" color-name "1.1.1"
color-name@^1.1.1: color-name@1.1.1:
version "1.1.3" version "1.1.1"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689"
color-support@^1.1.3: color-support@^1.1.3:
version "1.1.3" version "1.1.3"
@@ -1413,24 +1413,22 @@ commander@~2.13.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
common-tags@^1.4.0: common-tags@^1.4.0:
version "1.7.2" version "1.8.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.7.2.tgz#24d9768c63d253a56ecff93845b44b4df1d52771" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
dependencies:
babel-runtime "^6.26.0"
compare-versions@^3.1.0: compare-versions@^3.1.0:
version "3.2.1" version "3.3.0"
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.2.1.tgz#a49eb7689d4caaf0b6db5220173fd279614000f7" resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.3.0.tgz#af93ea705a96943f622ab309578b9b90586f39c3"
component-emitter@^1.2.1: component-emitter@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
compressible@~2.0.5: compressible@~2.0.5:
version "2.0.13" version "2.0.14"
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.14.tgz#326c5f507fbb055f54116782b969a81b67a29da7"
dependencies: dependencies:
mime-db ">= 1.33.0 < 2" mime-db ">= 1.34.0 < 2"
compression@~1.5.2: compression@~1.5.2:
version "1.5.2" version "1.5.2"
@@ -1550,8 +1548,8 @@ core-js@^1.0.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636"
core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0: core-js@^2.2.2, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0:
version "2.5.6" version "2.5.7"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.6.tgz#0fe6d45bf3cac3ac364a9d72de7576f4eb221b9d" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
core-util-is@1.0.2, core-util-is@~1.0.0: core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
@@ -1678,19 +1676,19 @@ decode-uri-component@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
deep-extend@^0.5.1: deep-extend@^0.6.0:
version "0.5.1" version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
deep-is@~0.1.3: deep-is@~0.1.3:
version "0.1.3" version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
default-require-extensions@^1.0.0: default-require-extensions@^2.0.0:
version "1.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
dependencies: dependencies:
strip-bom "^2.0.0" strip-bom "^3.0.0"
define-properties@^1.1.2: define-properties@^1.1.2:
version "1.1.2" version "1.1.2"
@@ -1773,8 +1771,8 @@ diff@^3.2.0:
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
dlv@^1.1.0: dlv@^1.1.0:
version "1.1.1" version "1.1.2"
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.1.tgz#c79d96bfe659a5568001250ed2aaf653992bdd3f" resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.2.tgz#270f6737b30d25b6657a7e962c784403f85137e5"
doctrine@1.5.0: doctrine@1.5.0:
version "1.5.0" version "1.5.0"
@@ -1783,7 +1781,7 @@ doctrine@1.5.0:
esutils "^2.0.2" esutils "^2.0.2"
isarray "^1.0.0" isarray "^1.0.0"
doctrine@^2.0.2, doctrine@^2.1.0: doctrine@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
dependencies: dependencies:
@@ -1838,8 +1836,8 @@ envinfo@^3.0.0:
which "^1.2.14" which "^1.2.14"
error-ex@^1.2.0: error-ex@^1.2.0:
version "1.3.1" version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
dependencies: dependencies:
is-arrayish "^0.2.1" is-arrayish "^0.2.1"
@@ -1851,8 +1849,8 @@ errorhandler@~1.4.2:
escape-html "~1.0.3" escape-html "~1.0.3"
es-abstract@^1.5.1, es-abstract@^1.7.0: es-abstract@^1.5.1, es-abstract@^1.7.0:
version "1.11.0" version "1.12.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.11.0.tgz#cce87d518f0496893b1a30cd8461835535480681" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
dependencies: dependencies:
es-to-primitive "^1.1.1" es-to-primitive "^1.1.1"
function-bind "^1.1.1" function-bind "^1.1.1"
@@ -1881,8 +1879,8 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
escodegen@^1.9.0: escodegen@^1.9.0:
version "1.9.1" version "1.10.0"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.10.0.tgz#f647395de22519fbd0d928ffcf1d17e0dec2603e"
dependencies: dependencies:
esprima "^3.1.3" esprima "^3.1.3"
estraverse "^4.2.0" estraverse "^4.2.0"
@@ -1946,13 +1944,13 @@ eslint-plugin-prettier@^2.6.0:
jest-docblock "^21.0.0" jest-docblock "^21.0.0"
eslint-plugin-react@^7.1.0: eslint-plugin-react@^7.1.0:
version "7.8.2" version "7.9.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.8.2.tgz#e95c9c47fece55d2303d1a67c9d01b930b88a51d" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.9.1.tgz#101aadd15e7c7b431ed025303ac7b421a8e3dc15"
dependencies: dependencies:
doctrine "^2.0.2" doctrine "^2.1.0"
has "^1.0.1" has "^1.0.2"
jsx-ast-utils "^2.0.1" jsx-ast-utils "^2.0.1"
prop-types "^15.6.0" prop-types "^15.6.1"
eslint-scope@^3.7.1: eslint-scope@^3.7.1:
version "3.7.1" version "3.7.1"
@@ -2246,8 +2244,8 @@ fbjs-scripts@^0.8.1:
through2 "^2.0.0" through2 "^2.0.0"
fbjs@^0.8.0, fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.9: fbjs@^0.8.0, fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.9:
version "0.8.16" version "0.8.17"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.17.tgz#c4d598ead6949112653d6588b01a5cdcd9f90fdd"
dependencies: dependencies:
core-js "^1.0.0" core-js "^1.0.0"
isomorphic-fetch "^2.1.1" isomorphic-fetch "^2.1.1"
@@ -2255,7 +2253,7 @@ fbjs@^0.8.0, fbjs@^0.8.14, fbjs@^0.8.16, fbjs@^0.8.9:
object-assign "^4.1.0" object-assign "^4.1.0"
promise "^7.1.1" promise "^7.1.1"
setimmediate "^1.0.5" setimmediate "^1.0.5"
ua-parser-js "^0.7.9" ua-parser-js "^0.7.18"
figures@^1.7.0: figures@^1.7.0:
version "1.7.0" version "1.7.0"
@@ -2423,7 +2421,7 @@ fsevents@^1.0.0, fsevents@^1.2.3:
nan "^2.9.2" nan "^2.9.2"
node-pre-gyp "^0.10.0" node-pre-gyp "^0.10.0"
function-bind@^1.0.2, function-bind@^1.1.1: function-bind@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -2522,8 +2520,8 @@ global@^4.3.0:
process "~0.5.1" process "~0.5.1"
globals@^11.0.1: globals@^11.0.1:
version "11.5.0" version "11.7.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642" resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
globals@^9.18.0: globals@^9.18.0:
version "9.18.0" version "9.18.0"
@@ -2627,11 +2625,11 @@ has-values@^1.0.0:
is-number "^3.0.0" is-number "^3.0.0"
kind-of "^4.0.0" kind-of "^4.0.0"
has@^1.0.1: has@^1.0.1, has@^1.0.2:
version "1.0.1" version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
dependencies: dependencies:
function-bind "^1.0.2" function-bind "^1.1.1"
hawk@~3.1.3: hawk@~3.1.3:
version "3.1.3" version "3.1.3"
@@ -2647,8 +2645,8 @@ hoek@2.x.x:
resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
hoist-non-react-statics@^2.2.0, hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0: hoist-non-react-statics@^2.2.0, hoist-non-react-statics@^2.3.1, hoist-non-react-statics@^2.5.0:
version "2.5.0" version "2.5.5"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.0.tgz#d2ca2dfc19c5a91c5a6615ce8e564ef0347e2a40" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47"
home-or-tmp@^2.0.0: home-or-tmp@^2.0.0:
version "2.0.0" version "2.0.0"
@@ -2727,8 +2725,8 @@ ignore@^3.3.3:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b"
image-size@^0.6.0: image-size@^0.6.0:
version "0.6.2" version "0.6.3"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.2.tgz#8ee316d4298b028b965091b673d5f1537adee5b4" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2"
import-local@^1.0.0: import-local@^1.0.0:
version "1.0.0" version "1.0.0"
@@ -3096,10 +3094,10 @@ istanbul-lib-coverage@^1.1.1, istanbul-lib-coverage@^1.1.2, istanbul-lib-coverag
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341"
istanbul-lib-hook@^1.2.0: istanbul-lib-hook@^1.2.0:
version "1.2.0" version "1.2.1"
resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.0.tgz#ae556fd5a41a6e8efa0b1002b1e416dfeaf9816c" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz#f614ec45287b2a8fc4f07f5660af787575601805"
dependencies: dependencies:
append-transform "^0.4.0" append-transform "^1.0.0"
istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.8.0: istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.8.0:
version "1.10.1" version "1.10.1"
@@ -3133,8 +3131,8 @@ istanbul-lib-source-maps@^1.2.1:
source-map "^0.5.3" source-map "^0.5.3"
istanbul-lib-source-maps@^1.2.4: istanbul-lib-source-maps@^1.2.4:
version "1.2.4" version "1.2.5"
resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.4.tgz#cc7ccad61629f4efff8e2f78adb8c522c9976ec7" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz#ffe6be4e7ab86d3603e4290d54990b14506fc9b1"
dependencies: dependencies:
debug "^3.1.0" debug "^3.1.0"
istanbul-lib-coverage "^1.2.0" istanbul-lib-coverage "^1.2.0"
@@ -3461,8 +3459,8 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1: js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.9.1:
version "3.11.0" version "3.12.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
dependencies: dependencies:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
@@ -3955,14 +3953,18 @@ micromatch@^3.1.4, micromatch@^3.1.8:
snapdragon "^0.8.1" snapdragon "^0.8.1"
to-regex "^3.0.2" to-regex "^3.0.2"
"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: "mime-db@>= 1.34.0 < 2":
version "1.33.0" version "1.34.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.34.0.tgz#452d0ecff5c30346a6dc1e64b1eaee0d3719ff9a"
mime-db@~1.23.0: mime-db@~1.23.0:
version "1.23.0" version "1.23.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.23.0.tgz#a31b4070adaea27d732ea333740a64d0ec9a6659"
mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
mime-types@2.1.11: mime-types@2.1.11:
version "2.1.11" version "2.1.11"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.11.tgz#c259c471bda808a85d6cd193b430a5fae4473b3c"
@@ -4229,8 +4231,8 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
nwsapi@^2.0.0: nwsapi@^2.0.0:
version "2.0.0" version "2.0.4"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.0.tgz#7c8faf4ad501e1d17a651ebc5547f966b547c5c7" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.4.tgz#dc79040a5f77b97716dc79565fc7fc3ef7d50570"
oauth-sign@~0.8.1, oauth-sign@~0.8.2: oauth-sign@~0.8.1, oauth-sign@~0.8.2:
version "0.8.2" version "0.8.2"
@@ -4249,8 +4251,8 @@ object-copy@^0.1.0:
kind-of "^3.0.3" kind-of "^3.0.3"
object-keys@^1.0.8: object-keys@^1.0.8:
version "1.0.11" version "1.0.12"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
object-visit@^1.0.0: object-visit@^1.0.0:
version "1.0.1" version "1.0.1"
@@ -4384,8 +4386,8 @@ p-finally@^1.0.0:
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
p-limit@^1.1.0: p-limit@^1.1.0:
version "1.2.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
dependencies: dependencies:
p-try "^1.0.0" p-try "^1.0.0"
@@ -4579,8 +4581,8 @@ prettier-eslint@^8.8.1:
typescript-eslint-parser "^11.0.0" typescript-eslint-parser "^11.0.0"
prettier@^1.12.1, prettier@^1.7.0: prettier@^1.12.1, prettier@^1.7.0:
version "1.12.1" version "1.13.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.5.tgz#7ae2076998c8edce79d63834e9b7b09fead6bfd0"
pretty-format@^21.2.1: pretty-format@^21.2.1:
version "21.2.1" version "21.2.1"
@@ -4623,10 +4625,9 @@ promise@^7.1.1:
asap "~2.0.3" asap "~2.0.3"
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1: prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1:
version "15.6.1" version "15.6.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102"
dependencies: dependencies:
fbjs "^0.8.16"
loose-envify "^1.3.1" loose-envify "^1.3.1"
object-assign "^4.1.1" object-assign "^4.1.1"
@@ -4634,6 +4635,10 @@ pseudomap@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
psl@^1.1.24:
version "1.1.28"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.28.tgz#4fb6ceb08a1e2214d4fd4de0ca22dae13740bc7b"
punycode@^1.4.1: punycode@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@@ -4679,10 +4684,10 @@ raw-body@~2.1.2:
unpipe "1.0.0" unpipe "1.0.0"
rc@^1.1.7: rc@^1.1.7:
version "1.2.7" version "1.2.8"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.7.tgz#8a10ca30d588d00464360372b890d06dacd02297" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
dependencies: dependencies:
deep-extend "^0.5.1" deep-extend "^0.6.0"
ini "~1.3.0" ini "~1.3.0"
minimist "^1.2.0" minimist "^1.2.0"
strip-json-comments "~2.0.1" strip-json-comments "~2.0.1"
@@ -4702,9 +4707,9 @@ react-devtools-core@3.0.0:
shell-quote "^1.6.1" shell-quote "^1.6.1"
ws "^2.0.3" ws "^2.0.3"
react-is@^16.4.0: react-is@^16.4.1:
version "16.4.0" version "16.4.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.0.tgz#cc9fdc855ac34d2e7d9d2eb7059bbc240d35ffcf" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.1.tgz#d624c4650d2c65dbd52c72622bbf389435d9776e"
react-lifecycles-compat@^3, react-lifecycles-compat@^3.0.4: react-lifecycles-compat@^3, react-lifecycles-compat@^3.0.4:
version "3.0.4" version "3.0.4"
@@ -4823,9 +4828,15 @@ react-navigation-deprecated-tab-navigator@1.3.0:
dependencies: dependencies:
react-native-tab-view "^0.0.77" react-native-tab-view "^0.0.77"
react-navigation-tabs@0.5.0: react-navigation-drawer@0.4.1:
version "0.5.0" version "0.4.1"
resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-0.5.0.tgz#74d5511270742a0b67c46fe65a1b19e553763819" resolved "https://registry.yarnpkg.com/react-navigation-drawer/-/react-navigation-drawer-0.4.1.tgz#ea3c9218dabbe8626c91d388cf0df4b1f8b14cb7"
dependencies:
react-native-drawer-layout-polyfill "^1.3.2"
react-navigation-tabs@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/react-navigation-tabs/-/react-navigation-tabs-0.5.1.tgz#ed33bce3a3e21b92646700de25bd94b8fc570371"
dependencies: dependencies:
hoist-non-react-statics "^2.5.0" hoist-non-react-statics "^2.5.0"
prop-types "^15.6.1" prop-types "^15.6.1"
@@ -4849,13 +4860,13 @@ react-test-renderer@16.2.0:
prop-types "^15.6.0" prop-types "^15.6.0"
react-test-renderer@^16.0.0: react-test-renderer@^16.0.0:
version "16.4.0" version "16.4.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.0.tgz#0dbe0e24263e94e1830c7afb1f403707fad313a3" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.4.1.tgz#f2fb30c2c7b517db6e5b10ed20bb6b0a7ccd8d70"
dependencies: dependencies:
fbjs "^0.8.16" fbjs "^0.8.16"
object-assign "^4.1.1" object-assign "^4.1.1"
prop-types "^15.6.0" prop-types "^15.6.0"
react-is "^16.4.0" react-is "^16.4.1"
react-timer-mixin@^0.13.2: react-timer-mixin@^0.13.2:
version "0.13.3" version "0.13.3"
@@ -5126,8 +5137,8 @@ resolve@1.1.7:
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
resolve@^1.5.0, resolve@^1.6.0: resolve@^1.5.0, resolve@^1.6.0:
version "1.7.1" version "1.8.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
dependencies: dependencies:
path-parse "^1.0.5" path-parse "^1.0.5"
@@ -5216,7 +5227,7 @@ safe-regex@^1.1.0:
dependencies: dependencies:
ret "~0.1.10" ret "~0.1.10"
"safer-buffer@>= 2.1.2 < 3": "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@@ -5491,13 +5502,14 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
sshpk@^1.7.0: sshpk@^1.7.0:
version "1.14.1" version "1.14.2"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
dependencies: dependencies:
asn1 "~0.2.3" asn1 "~0.2.3"
assert-plus "^1.0.0" assert-plus "^1.0.0"
dashdash "^1.12.0" dashdash "^1.12.0"
getpass "^0.1.1" getpass "^0.1.1"
safer-buffer "^2.0.2"
optionalDependencies: optionalDependencies:
bcrypt-pbkdf "^1.0.0" bcrypt-pbkdf "^1.0.0"
ecc-jsbn "~0.1.1" ecc-jsbn "~0.1.1"
@@ -5754,7 +5766,14 @@ to-regex@^3.0.1, to-regex@^3.0.2:
regex-not "^1.0.2" regex-not "^1.0.2"
safe-regex "^1.1.0" safe-regex "^1.1.0"
tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.0, tough-cookie@~2.3.3: tough-cookie@>=2.3.3, tough-cookie@^2.3.3:
version "2.4.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.2.tgz#aa9133154518b494efab98a58247bfc38818c00c"
dependencies:
psl "^1.1.24"
punycode "^1.4.1"
tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.4" version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
dependencies: dependencies:
@@ -5813,10 +5832,10 @@ typescript-eslint-parser@^11.0.0:
semver "5.4.1" semver "5.4.1"
typescript@^2.5.1: typescript@^2.5.1:
version "2.8.3" version "2.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
ua-parser-js@^0.7.9: ua-parser-js@^0.7.18:
version "0.7.18" version "0.7.18"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed"
@@ -6000,8 +6019,8 @@ whatwg-mimetype@^2.0.0, whatwg-mimetype@^2.1.0:
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz#f0f21d76cbba72362eb609dbed2a30cd17fcc7d4"
whatwg-url@^6.4.0, whatwg-url@^6.4.1: whatwg-url@^6.4.0, whatwg-url@^6.4.1:
version "6.4.1" version "6.5.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.4.1.tgz#fdb94b440fd4ad836202c16e9737d511f012fd67" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8"
dependencies: dependencies:
lodash.sortby "^4.7.0" lodash.sortby "^4.7.0"
tr46 "^1.0.1" tr46 "^1.0.1"
@@ -6012,8 +6031,8 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0: which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0:
version "1.3.0" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
dependencies: dependencies:
isexe "^2.0.0" isexe "^2.0.0"