Compare commits

...

20 Commits

Author SHA1 Message Date
Spencer Carli
29e451193d 1.0.0-beta.14 2017-10-17 11:11:45 -05:00
Spencer Carli
36ffc4f31a [iOS 11] Handle landscape tabbar correctly. (#2676)
* Handle the ios11 tabbar correctly

* Fix an issue when showLabel is false

* Add a basic test for the tabbarbottom

* Add check for ios version number

* Tests shall pass

* make things work for all the versions

* Again, fix the tests
2017-10-16 10:01:30 +01:00
robertkongsvmx
82c2cdbe09 Issue-2662: Add support for testID and accessibilityLabel for tab bar items (#2684) 2017-10-15 19:45:22 -05:00
Lorenzo Sciandra
3ae4b31a9d Updating the README (#2752)
* update the README

* Fixing a couple formats

* rephrase intro

* reordering and relinking

* small reorder

* typo

* couple more changes

* couple tweaks

* libraries section
2017-10-15 16:20:01 -05:00
Finian
f84fe15272 Add allowFontScaling option for TabView and headerTitleAllowFontScaling for HeaderTitle (#2377) (#2721) 2017-10-15 09:57:09 +01:00
Chid Gilovitz
5576b84d8a Update Routers.md (#2750)
Added import line to code example.
2017-10-14 12:31:46 +01:00
Lucas Padilha
09e396002f added drawerBackgroundColor for documentation (#2723)
* added property inside drawerConfig to backgroundColor (drawerBackgroundColor)

* Adjusting documentation for PR deployment (# 2698)

* add example in the doc
2017-10-11 14:04:22 +01:00
Akshay Kadam
2dca5b2135 Typo: 'create' was written twice 😂 (#2727) 2017-10-11 14:00:49 +01:00
Pat Needham
27d496c268 Fix Querystring params not set for nested URI (issue #2251) (#2695)
* fix issue #2251 by including queryString to get nested action

* only use nested query string when original queryString exists, and include test cases
2017-10-09 21:21:39 -05:00
Lucas Padilha
df788fd9ac added property inside drawerConfig to backgroundColor (drawerBackgroundColor) (#2698) 2017-10-08 10:40:08 +01:00
Vojtech Novak
e4a7b7e073 remove ineffective invariant usages, fixes #2258 (#2693)
* remove ineffective invariant usages

* fix flow err

* fix tests

* fix tests

* use throw
2017-10-05 11:59:13 +01:00
David Lewis
c08be7fb43 Suggest flex: 1 for embedded navigator (#2639) 2017-10-03 17:01:52 -05:00
Neo
81d8d91085 add doc for transitionConfig (#1827)
* add doc for transitionConfig

* address review
2017-10-03 16:54:19 -05:00
Dan Gurney
5e001155fb Fix "drawerLockMode" terminology for screenProps (#2667)
Should be "drawerLockMode" instead of "lockMode"
2017-10-03 17:21:49 +01:00
Lorenzo Sciandra
c1d181eccd Fixing Intro Guide (#2679)
* Fixing Intro Guide

Fixes #832 - the code in this page was wrong, that export default was causing errors.

I've also modified a few phrases here and there to help the comprehension.

* more fixes, for CRNA
2017-10-03 09:05:39 -05:00
Spencer Carli
a8556b0df2 Improve StatusBar/Header Behavior (#2669)
* Track orientation change

* Add tests for withOrientation

* Better variable naming
2017-09-29 16:11:30 -05:00
Dave Pack
c4541f44af Updates examples to react-native 0.48.4 and expo sdk 21. (#2675) 2017-09-29 16:06:56 -05:00
Vojtech Novak
ef82f1b5ff Update ISSUE_TEMPLATE.md (#2668)
the problem I see with many bug reports in this repo is that people write a very vague description of what their problem is and expect to get some help. I tried to:

1 . emphasise how important it is to include a runnable reproduction
2 . cut down on some extra words at the beginning of the template so it's more to the point
2017-09-29 15:51:06 -05:00
Spencer Carli
1a62bf7955 Remove RelativeImageStub providesModule 2017-09-28 14:57:17 -05:00
Ashoat Tevosyan
a79d86b152 Remove @providesModule declarations in src/utils to avoid Flow conflicts with fbjs package (#2665) 2017-09-28 14:42:14 -05:00
41 changed files with 965 additions and 262 deletions

View File

@@ -1,17 +1,16 @@
## Before You Start...
The issue list is reserved exclusively for bug reports and feature requests. That means we do not accept usage questions.
## The issue list is reserved for bugs and feature requests, not for questions.
For usage questions, please use the following resources:
For usage questions, try to:
- [Read the docs](https://reactnavigation.org/)
- [Ask on the Reactiflux (#react-navigation)](https://discord.gg/reactiflux)
- [Look for / ask questions on StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation)
- Also try to search for your issue - it may have already been answered or even fixed in the development branch. However, if you find that an old, closed issue still persists in the latest version, you should open a new issue.
- Search for your issue - it may have already been answered or even fixed in the development branch. However, if you find that an old, closed issue still persists in the latest version, you should open a new issue.
---
### Current Behavior
- _If describing a bug, tell us what happens. Provide a screenshot when possible and full code sample_
- _If describing a bug, tell us what happens. Please provide a repository with code and steps to reproduce the bug. **Not providing code that other people can run makes is significantly harder to fix your bug.** Provide a screenshot when possible_
- _If suggesting a change/improvement, explain the difference from current behavior_
### Expected Behavior
@@ -19,7 +18,6 @@ For usage questions, please use the following resources:
- _If you're suggesting a change/improvement, tell us how it should work_
### Your Environment
- _Include as many relevant details about the environment you experienced the bug in_
| software | version
| ---------------- | -------

162
README.md
View File

@@ -1,63 +1,143 @@
# React Navigation [![CircleCI](https://circleci.com/gh/react-community/react-navigation/tree/master.svg?style=shield&circle-token=622fcb1d78413084c2f44699ed2104246a177485)](https://circleci.com/gh/react-community/react-navigation/tree/master) [![npm version](https://badge.fury.io/js/react-navigation.svg)](https://badge.fury.io/js/react-navigation) [![codecov](https://codecov.io/gh/react-community/react-navigation/branch/master/graph/badge.svg)](https://codecov.io/gh/react-community/react-navigation)
# React Navigation [![CircleCI](https://circleci.com/gh/react-community/react-navigation/tree/master.svg?style=shield&circle-token=622fcb1d78413084c2f44699ed2104246a177485)](https://circleci.com/gh/react-community/react-navigation/tree/master) [![npm version](https://badge.fury.io/js/react-navigation.svg)](https://badge.fury.io/js/react-navigation) [![codecov](https://codecov.io/gh/react-community/react-navigation/branch/master/graph/badge.svg)](https://codecov.io/gh/react-community/react-navigation) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactnavigation.org/docs/guides/contributors)
*Learn once, navigate anywhere.*
Browse the docs on [reactnavigation.org](https://reactnavigation.org/) or try it out on [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
React Navigation is born from the React Native community's need for an extensible yet easy-to-use navigation solution based on Javascript.
## Motivation
React Navigation is the result of a collaboration between developers from Facebook, Expo and the React community at large: it replaces and improves upon several navigation libraries in the ecosystem, including Ex-Navigation, React Native's Navigator and NavigationExperimental components.
React Navigation is born from the React Native community's need for an
extensible yet easy-to-use navigation solution. It replaces and improves
upon several navigation libraries in the ecosystem, including Ex-Navigation,
React Native's Navigator and NavigationExperimental components. React
Navigation can also be used across React and React Native projects allowing
for a higher degree of shared code.
* [Installation](#installation)
* [Community contributions](#community-contributions)
* [Introduction to the library](#introduction-to-the-library)
* [Basic Tutorials](#basic-tutorials)
* [Intermediate Concepts](#intermediate-concepts)
* [Advanced Topics](#advanced-topics)
* [Comparisons and Discussion](##comparisons-and-discussion)
* [Example Projects](#example-projects)
* [Libraries](#libraries)
* [FAQs](#faqs)
* [When is version 1.0.0 going to be released?](#when-is-version-100-going-to-be-released)
* [I'm having troubles using the library, what can I do?](#im-having-troubles-using-the-library-what-can-i-do)
* [How can I help?](#how-can-i-help)
* [Is this the only library available for navigation?](#is-this-the-only-library-available-for-navigation)
* [Can I use this library for web?](#can-i-use-this-library-for-web)
* [Code of conduct](#code-of-conduct)
* [License](#license)
Once stable, NavigationExperimental will be deprecated in favor of React
Navigation. React Navigation is a collaboration between people from
Facebook, Exponent and the React community at large.
## Installation
## [Getting started](https://reactnavigation.org/docs/intro/)
Since the library is a JS-based solution, to install the latest version of react-navigation you only need to run:
1. Create a new React Native App
```
react-native init SimpleApp
cd SimpleApp
```
2. Install the latest version of react-navigation from npm
```
```bash
yarn add react-navigation
```
or
```
```bash
npm install --save react-navigation
```
3. Run the new app
```
react-native run-android # or:
react-native run-ios
```
## Get Started
## Community
To learn how the library work, head to the [introduction](https://reactnavigation.org/docs/intro/) on the website for a quick tutorial that will cover all the basics - or try it out [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
We have an active channel on the [Reactiflux](https://www.reactiflux.com/) community. It's the best place to show off things you've made with the library, ask for help, or just hang out and discuss the project. This also helps keep the [issues](https://github.com/react-community/react-navigation/issues) manageable.
#### Advanced guides
## Advanced guide
* [Redux integration](https://reactnavigation.org/docs/guides/redux)
* [Deep linking](https://reactnavigation.org/docs/guides/linking)
- [Redux integration](https://reactnavigation.org/docs/guides/redux)
- [Web integration](https://reactnavigation.org/docs/guides/web)
- [Deep linking](https://reactnavigation.org/docs/guides/linking)
- [Contributors guide](https://reactnavigation.org/docs/guides/contributors)
#### React Navigation API
## React Navigation API
* [Navigators](https://reactnavigation.org/docs/navigators/)
* [Routers](https://reactnavigation.org/docs/routers/)
* [Views](https://reactnavigation.org/docs/views/)
- [Navigators](https://reactnavigation.org/docs/navigators/)
- [Routers](https://reactnavigation.org/docs/routers/)
- [Views](https://reactnavigation.org/docs/views/)
## Community contributions
## Helpful Resources
A lot of developers poured their knowledge in blog posts, and other repos - we will try to keep here a list of tutorials and resources to help someone who wants to learn about React Navigation and techniques to handle navigation effectively.
- [React Navigation Links](https://github.com/react-navigation/react-navigation-links)
#### Introduction to the library
* [Getting Started with React Navigation](https://hackernoon.com/getting-started-with-react-navigation-the-navigation-solution-for-react-native-ea3f4bd786a4)
#### Basic Tutorials
* [Basic ReactNavigation Example App and Tutorial](http://docs.nativebase.io/docs/examples/navigation/StackNavigationExample.html)
* [Understanding Navigation in React Native](https://www.codementor.io/blessingoraz/understanding-navigation-in-react-native-a3wlcxmzu?published=1#.WXfDlvk_ooE.twitter)
* [Comprehensive routing and navigation in React Native made easy](https://medium.com/@kevinle/comprehensive-routing-and-navigation-in-react-native-made-easy-6383e6cdc293)
* [Replace a Screen Using React Navigation](https://medium.com/handlebar-labs/replace-a-screen-using-react-navigation-a503eab207eb)
#### Intermediate Concepts
* [Using React Navigation and Redux in your React Native Application](https://medium.com/modus-create-front-end-development/using-react-navigation-and-redux-in-your-react-native-application-efac33265138)
* [React-Navigation, complete Redux state management, tab-bar, and multiple navigators](https://medium.com/@parkerdan/react-navigation-with-complete-redux-state-management-tab-bar-and-multiple-navigators-ed30a69d9a4d)
* [Custom Drawer with React-Navigation in React-Native](http://www.skywardsoftwares.co.in/react-native/custom-drawer-with-react-navigation-in-react-native/)
* [React Navigation Drawer - a tutorial series](https://shift.infinite.red/react-navigation-drawer-tutorial-a802fc3ee6dc)
#### Advanced Topics
* [Full Stack React Native Development using GraphCool and Apollo Subscriptions + React Navigation](https://medium.com/react-native-training/full-stack-react-native-development-using-graphcool-and-apollo-subscriptions-react-navigation-cdb3e1374c05)
#### Comparisons and Discussion
* [Migrate from ExNavigation to React Navigation](https://hackernoon.com/migrate-from-exnavigation-to-react-navigation-1af661ec5082)
* [Playing with React Navigation and Airbnb's Native Navigation](https://medium.com/@ericvicenti/playing-with-react-navigation-and-airbnbs-native-navigation-4e49fc765489)
* [How we restructured our app with React Navigation](https://m.oursky.com/how-we-restructured-our-app-with-react-navigation-98a89e219c26)
* [Whats Happening with Navigation in React Native?](https://blog.revisify.com/whats-happening-with-navigation-in-react-native-c193535888c3)
#### Example Projects
* [Yaba-Social](https://github.com/allpwrfulroot/yaba-social)
* [React Native Boilerplate with React Navigation and Redux integration](https://github.com/verybluebot/react-native-boilerplate)
#### Libraries
* [react-navigation-addons](https://github.com/satya164/react-navigation-addons)
* [react-navigation-props-mapper](https://github.com/vonovak/react-navigation-props-mapper)
## FAQs
#### When is version 1.0.0 going to be released?
As soon as all the tasks [here](https://github.com/react-community/react-navigation/issues/2585) have been completed. You can read more about it in the [blog](https://reactnavigation.org/blog/2017/9/Renewed-v1).
(in the meantime, you can find the changelog for every release [here](https://github.com/react-community/react-navigation/releases))
#### I'm having troubles using the library, what can I do?
Head to the [issues](https://github.com/react-community/react-navigation/issues) and do a quick search: if you think you are experiencing a bug chances are somebody already opened an issue for it. If instead you are having more general problems, use [Stack Overflow](https://stackoverflow.com/search?q=react-navigation) - which is better suited and helps keeping the Issues section of the repo clean. Alternatively you could join the [Reactiflux](https://www.reactiflux.com/) community on Discord where there are React Native and React Navigation channels with helpful people who might be able to answer you.
You should **only** open a new issue if you believe that you are experiencing a bug or have a feature request, and please **follow** the dedicated template - it will help everyone helping you (and may get closed if it doesn't).
#### How can I help?
Glad you ask! This library is a community effort: it can only be great if we all help out in one way or another 😄 . If you feel like you aren't experienced enough using react navigation to contribute, you can still make an impact by:
1. Responding to one of the open [issues](https://github.com/react-community/react-navigation/issues). Even if you can't resolve or fully answer a question, asking for more information or clarity on an issue is extremely beneficial for someone to come after you to resolve the issue.
1. Creating public example repos of navigation problems you have solved.
1. Answering questions on [Stack Overflow](https://stackoverflow.com/search?q=react-navigation). Alternatively, asking questions on Stack Overflow instead of opening an issue.
1. Answering questions in our [Reactiflux](https://www.reactiflux.com/) channel.
1. Providing feedback on the open [PRs](https://github.com/react-community/react-navigation/pulls).
If you feel brave enough you can submit a PR: follow the [Contributors guide](https://reactnavigation.org/docs/guides/contributors) to find out how. If you don't know where to start, check the ones with the label [`Type: Good First Task`](https://github.com/react-community/react-navigation/labels/Type%3A%20Good%20First%20Task) - even [fixing a typo in the documentation](https://github.com/react-community/react-navigation/pull/2727) is a worthy contribution!
#### Is this the only library available for navigation?
No: there are some other libraries - which, depending on your project, can be better or worse suited for your project. They differ in the approach and implementation from `react-navigation`, but share the common goal of helping you create a good React Native application; you can find a general round up in the [React Native docs](http://facebook.github.io/react-native/docs/navigation.html).
#### Can I use this library for web?
This library originally planned to support web too - but at the moment [it is not a priority](https://github.com/react-community/react-navigation/issues/2585#issuecomment-330338793) for v1.0; a lot of work is necessary to reach it as-is and we had to freeze this support (consider it ["experimental"](https://reactnavigation.org/docs/guides/web)).
## Code of conduct
This library has adopted a Code of Conduct that we expect project participants to adhere to. Please read the [full text](https://github.com/react-community/react-navigation/blob/master/CODE_OF_CONDUCT.md) so that you can understand what actions will and will not be tolerated.
## License
React-navigation is licensed under the [BSD 2-clause "Simplified" License](https://github.com/react-community/react-navigation/blob/master/LICENSE).

View File

@@ -87,11 +87,12 @@ The route configs object is a mapping from route name to a route config, which t
### DrawerNavigatorConfig
- `drawerWidth` - Width of the drawer
- `drawerWidth` - Width of the drawer.
- `drawerPosition` - Options are `left` or `right`. Default is `left` position.
- `contentComponent` - Component used to render the content of the drawer, for example, navigation items. Receives the `navigation` prop for the drawer. Defaults to `DrawerItems`. For more information, see below.
- `contentOptions` - Configure the drawer content, see below.
- `useNativeAnimations` - Enable native animations. Default is `true`.
- `drawerBackgroundColor` - Use the Drawer background for some color. The Default is `white`.
#### Example:
@@ -103,7 +104,8 @@ as you can see in the example below.
{
drawerWidth: 200,
drawerPosition: 'right',
contentComponent: props => <ScrollView><DrawerItems {...props} /></ScrollView>
contentComponent: props => <ScrollView><DrawerItems {...props} /></ScrollView>,
drawerBackgroundColor: 'transparent'
}
```
@@ -173,7 +175,7 @@ React Element or a function, that given `{ focused: boolean, tintColor: string }
#### `drawerLockMode`
Specifies the [lock mode](https://facebook.github.io/react-native/docs/drawerlayoutandroid.html#drawerlockmode) of the drawer. This can also update dynamically by using screenProps.lockMode on your top level router.
Specifies the [lock mode](https://facebook.github.io/react-native/docs/drawerlayoutandroid.html#drawerlockmode) of the drawer. This can also update dynamically by using screenProps.drawerLockMode on your top level router.
### Navigator Props

View File

@@ -104,6 +104,10 @@ React Element or a function that given `HeaderProps` returns a React Element, to
String or React Element used by the header. Defaults to scene `title`
#### `headerTitleAllowFontScaling`
Whether header title font should scale to respect Text Size accessibility settings. Defaults to true
#### `headerBackTitle`
Title string used by the back button on iOS, or `null` to disable label. Defaults to the previous scene's `headerTitle`
@@ -173,3 +177,45 @@ The navigator component created by `StackNavigator(...)` takes the following pro
See the examples [SimpleStack.js](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground/js/SimpleStack.js) and [ModalStack.js](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground/js/ModalStack.js) which you can run locally as part of the [NavigationPlayground](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground) app.
You can view these examples directly on your phone by visiting [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
#### Modal StackNavigator with Custom Screen Transitions
```js
const ModalNavigator = StackNavigator(
{
Main: { screen: Main },
Login: { screen: Login },
},
{
headerMode: 'none',
mode: 'modal',
navigationOptions: {
gesturesEnabled: false,
},
transitionConfig: () => ({
transitionSpec: {
duration: 300,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
},
screenInterpolator: sceneProps => {
const { layout, position, scene } = sceneProps;
const { index } = scene;
const height = layout.initHeight;
const translateY = position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [height, 0, 0],
});
const opacity = position.interpolate({
inputRange: [index - 1, index - 0.99, index],
outputRange: [0, 1, 1],
});
return { opacity, transform: [{ translateY }] };
},
}),
}
);
```

View File

@@ -107,6 +107,7 @@ Several options get passed to the underlying router to modify navigation logic:
- `style` - style object for the tab bar
- `labelStyle` - style object for the tab label
- `tabStyle` - style object for the tab
- `allowFontScaling` - whether label font should scale to respect Text Size accessibility settings, default is true
Example:
@@ -137,6 +138,7 @@ tabBarOptions: {
- `labelStyle` - style object for the tab label
- `iconStyle` - style object for the tab icon
- `style` - style object for the tab bar
- `allowFontScaling` - whether label font should scale to respect Text Size accessibility settings, default is true
Example:

View File

@@ -65,6 +65,8 @@ MyApp.router.getStateForAction = (action, state) => {
Sometimes you may want to prevent some navigation activity, depending on your route.
```js
import { NavigationActions } from 'react-navigation'
const MyStackRouter = StackRouter({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },

View File

@@ -6,7 +6,6 @@ Let's use React Navigation to build a simple chat application for Android and iO
First, make sure you're [all set up to use React Native](http://facebook.github.io/react-native/docs/getting-started.html). Next, create a new project and add `react-navigation`:
```sh
# Create a new React Native App
react-native init SimpleApp
@@ -16,11 +15,13 @@ cd SimpleApp
npm install --save react-navigation
# Run the new app
react-native run-android # or:
react-native run-android
# or:
react-native run-ios
```
If you are using `create-react-native-app` instead of `react-native init`, then:
```sh
# Create a new React Native App
create-react-native-app SimpleApp
@@ -41,13 +42,11 @@ Verify that you can successfully see the bare sample app run on iOS and/or Andro
bare-project
```
We want to share code on iOS and Android, so lets delete the contents of `index.ios.js` and `index.android.js` and replace it with `import './App';`.
Now lets create the new file for our app implementation, `App.js`.
We want to share code on iOS and Android, so let's delete the contents of `index.ios.js` and `index.android.js` and replace it with `import './App';` - after which, we need to create the new file for our app implementation, `App.js` (if you used `create-react-native-app` this has been already done)
## Introducing Stack Navigator
For our app, we want to use the `StackNavigator` because we want a conceptual 'stack' navigation, where each new screen is put on the top of the stack and going back removes a screen from the top of the stack. Let's start with just one screen:
For our app, we want to use the `StackNavigator` because conceptually we want to obtain a 'card stack' effect of movement, where each new screen is put on the top of the stack and going back removes a screen from the top of the stack. Let's start with just one screen:
```js
import React from 'react';
@@ -66,14 +65,50 @@ class HomeScreen extends React.Component {
}
}
export default const SimpleApp = StackNavigator({
export const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
});
// if you are using create-react-native-app you don't need this line
AppRegistry.registerComponent('SimpleApp', () => SimpleApp);
```
If you used `create-react-native-app` the already existing `App.js` will be modified to
```js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome'
};
render() {
return <Text>Hello, Navigation!</Text>;
}
}
const SimpleApp = StackNavigator({
Home: { screen: HomeScreen }
});
export default class App extends React.Component {
render() {
return <SimpleApp />;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
});
```
The `title` of the screen is configurable on the [static `navigationOptions`](/docs/navigators/navigation-options), where many options can be set to configure the presentation of the screen in the navigator.
Now the same screen should appear on both iPhone and Android apps:
@@ -84,9 +119,15 @@ first-screen
## Adding a New Screen
In our `App.js` file, let's add a new screen called `ChatScreen`:
In our `App.js` file, let's add a new screen called `ChatScreen`, defining it under `HomeScreen`:
```js
// ...
class HomeScreen extends React.Component {
//...
}
class ChatScreen extends React.Component {
static navigationOptions = {
title: 'Chat with Lucy',
@@ -99,9 +140,10 @@ class ChatScreen extends React.Component {
);
}
}
```
We can then add a button to our `HomeScreen` component that links to `ChatScreen` using the `routeName` `Chat`.
We can then add a button to our `HomeScreen` component that links to `ChatScreen`: we need to use the provided method `navigate` (from the [screen navigation prop](/docs/navigators/navigation-prop)) by giving it the `routeName` of the screen we want to reach, in this case `Chat`.
```js
class HomeScreen extends React.Component {
@@ -123,10 +165,12 @@ class HomeScreen extends React.Component {
}
```
We're using the navigate function from the [screen navigation prop](/docs/navigators/navigation-prop) to go to `ChatScreen`. But that won't work until we add this to our `StackNavigator` like so:
(*don't forget to import View and Button from react-native: * `import { AppRegistry, Text, View, Button } from 'react-native';`)
But that won't work until we say to our `StackNavigator` of the existence of the `Chat` screen, like so:
```js
export default const SimpleApp = StackNavigator({
export const SimpleApp = StackNavigator({
Home: { screen: HomeScreen },
Chat: { screen: ChatScreen },
});

View File

@@ -90,6 +90,8 @@ const SimpleApp = StackNavigator({
```
In this case, the NavigatorWrappingScreen is not a navigator, but it renders a navigator as part of its output.
If this navigator renders blank then change `<View>` to `<View style={{flex: 1}}>`.
```js
class NavigatorWrappingScreen extends React.Component {
render() {

View File

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

View File

@@ -28,6 +28,10 @@ const MyHomeScreen = ({ navigation }) => (
);
MyHomeScreen.navigationOptions = {
tabBarTestIDProps: {
testID: 'TEST_ID_HOME',
accessibilityLabel: 'TEST_ID_HOME_ACLBL',
},
tabBarLabel: 'Home',
tabBarIcon: ({ tintColor, focused }) => (
<Ionicons

View File

@@ -12,7 +12,7 @@
"test": "node node_modules/jest/bin/jest.js"
},
"dependencies": {
"expo": "^20.1.2",
"expo": "^21.0.1",
"react": "16.0.0-alpha.12",
"react-native": "~0.48.4",
"react-navigation": "file:../.."
@@ -21,7 +21,7 @@
"babel-jest": "^21.0.0",
"flow-bin": "^0.51.0",
"jest": "^21.0.1",
"jest-expo": "^20.0.0",
"jest-expo": "^21.0.0",
"react-addons-test-utils": "16.0.0-alpha.3",
"react-native-scripts": "^1.3.1",
"react-test-renderer": "16.0.0-alpha.12"

View File

@@ -1904,25 +1904,26 @@ expect@^21.0.0:
jest-message-util "^21.0.0"
jest-regex-util "^21.0.0"
expo@^20.1.2:
version "20.1.2"
resolved "https://registry.yarnpkg.com/expo/-/expo-20.1.2.tgz#bac5723693bdfdd30aa003df7b05d06ee5459d5f"
expo@^21.0.1:
version "21.0.2"
resolved "https://registry.yarnpkg.com/expo/-/expo-21.0.2.tgz#8420b9f4b95503c464575a31fd9c820363caef9d"
dependencies:
"@expo/vector-icons" "^5.0.0"
babel-preset-expo "^3.0.0"
fbemitter "^2.1.1"
lodash.map "^4.6.0"
lodash.zipobject "^4.1.3"
lottie-react-native "1.1.1"
lottie-react-native "2.2.0"
md5-file "^3.1.1"
pretty-format "^20.0.3"
prop-types "^15.5.10"
qs "^6.5.0"
react-native-branch "2.0.0-beta.3"
react-native-gesture-handler "^1.0.0-alpha.14"
react-native-gesture-handler "1.0.0-alpha.22"
react-native-maps "0.15.3"
react-native-svg "5.3.0"
uuid-js "^0.7.5"
websql expo/node-websql#18.0.0
websql "https://github.com/expo/node-websql/archive/18.0.0.tar.gz"
express-session@~1.11.3:
version "1.11.3"
@@ -3066,9 +3067,9 @@ jest-environment-node@^21.0.0:
jest-mock "^21.0.0"
jest-util "^21.0.0"
jest-expo@^20.0.0:
version "20.0.0"
resolved "https://registry.yarnpkg.com/jest-expo/-/jest-expo-20.0.0.tgz#fc925bb8ecca56b410b5129d70407aa743e311b6"
jest-expo@^21.0.0:
version "21.0.2"
resolved "https://registry.yarnpkg.com/jest-expo/-/jest-expo-21.0.2.tgz#87c60deda29a9c67d5c59f24e7104aff6ce0aaee"
dependencies:
babel-jest "^20.0.3"
jest "^20.0.4"
@@ -3720,16 +3721,17 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
dependencies:
js-tokens "^3.0.0"
lottie-ios@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/lottie-ios/-/lottie-ios-1.5.2.tgz#c188f1baa1c308a291538fc585a76e0cfc060711"
lottie-ios@^2.0.5:
version "2.1.3"
resolved "https://registry.yarnpkg.com/lottie-ios/-/lottie-ios-2.1.3.tgz#57b2328511a26606dc6de7a74bbdbf77f92c6aa0"
lottie-react-native@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/lottie-react-native/-/lottie-react-native-1.1.1.tgz#1c87a3afca96edfa0869227140a2cff9bcc62c9b"
lottie-react-native@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/lottie-react-native/-/lottie-react-native-2.2.0.tgz#18196806ef6546cd3e01b24fc5a5974f02e4f017"
dependencies:
invariant "^2.2.2"
lottie-ios "^1.5.2"
lottie-ios "^2.0.5"
prop-types "^15.5.10"
react-native-safe-module "^1.1.0"
lower-case-first@^1.0.0:
@@ -4534,6 +4536,10 @@ qs@6.5.0, qs@^6.2.1, qs@^6.4.0:
version "6.5.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
qs@^6.5.0:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
querystring@0.2.0, querystring@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@@ -4648,9 +4654,11 @@ react-native-drawer-layout@1.3.2:
dependencies:
react-native-dismiss-keyboard "1.0.0"
react-native-gesture-handler@^1.0.0-alpha.14:
version "1.0.0-alpha.17"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.0-alpha.17.tgz#1ae4412e1b208d175b34a14931d0635064a92e7b"
react-native-gesture-handler@1.0.0-alpha.22:
version "1.0.0-alpha.22"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.0-alpha.22.tgz#96e5ae08b26a9e99d115f6e16f63d7487ef995fc"
dependencies:
prop-types "^15.5.10"
react-native-maps@0.15.3:
version "0.15.3"
@@ -4791,7 +4799,7 @@ react-native@~0.48.4:
yargs "^6.4.0"
"react-navigation@file:../..":
version "1.0.0-beta.12"
version "1.0.0-beta.13"
dependencies:
babel-plugin-transform-define "^1.3.0"
clamp "^1.0.1"
@@ -5914,9 +5922,9 @@ webidl-conversions@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
websql@expo/node-websql#18.0.0:
"websql@https://github.com/expo/node-websql/archive/18.0.0.tar.gz":
version "0.4.4"
resolved "https://codeload.github.com/expo/node-websql/tar.gz/e364fa65146a9e2157a19e5c719e7702c2b6b87a"
resolved "https://github.com/expo/node-websql/archive/18.0.0.tar.gz#39b12a08b0180495de1412d8a64a529e21ad554e"
dependencies:
argsarray "^0.0.1"
immediate "^3.2.2"

View File

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

View File

@@ -22,17 +22,17 @@
]
},
"dependencies": {
"expo": "^20.1.2",
"expo": "^21.0.1",
"prop-types": "^15.5.10",
"react": "16.0.0-alpha.12",
"react-native": "~0.47.2",
"react-native": "~0.48.4",
"react-redux": "^5.0.6",
"redux": "^3.7.2"
},
"devDependencies": {
"babel-jest": "^21.0.0",
"jest": "^21.0.1",
"jest-expo": "^20.0.0",
"jest-expo": "^21.0.0",
"react-native-scripts": "^1.3.1",
"react-navigation": "file:../..",
"react-test-renderer": "16.0.0-alpha.12"

View File

@@ -898,7 +898,7 @@ babel-preset-fbjs@^1.0.0:
babel-plugin-transform-object-rest-spread "^6.6.5"
object-assign "^4.0.1"
babel-preset-fbjs@^2.1.0, babel-preset-fbjs@^2.1.4:
babel-preset-fbjs@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-2.1.4.tgz#22f358e6654073acf61e47a052a777d7bccf03af"
dependencies:
@@ -949,40 +949,6 @@ babel-preset-jest@^21.0.0:
dependencies:
babel-plugin-jest-hoist "^21.0.0"
babel-preset-react-native@^1.9.1:
version "1.9.2"
resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-1.9.2.tgz#b22addd2e355ff3b39671b79be807e52dfa145f2"
dependencies:
babel-plugin-check-es2015-constants "^6.5.0"
babel-plugin-react-transform "2.0.2"
babel-plugin-syntax-async-functions "^6.5.0"
babel-plugin-syntax-class-properties "^6.5.0"
babel-plugin-syntax-flow "^6.5.0"
babel-plugin-syntax-jsx "^6.5.0"
babel-plugin-syntax-trailing-function-commas "^6.5.0"
babel-plugin-transform-class-properties "^6.5.0"
babel-plugin-transform-es2015-arrow-functions "^6.5.0"
babel-plugin-transform-es2015-block-scoping "^6.5.0"
babel-plugin-transform-es2015-classes "^6.5.0"
babel-plugin-transform-es2015-computed-properties "^6.5.0"
babel-plugin-transform-es2015-destructuring "^6.5.0"
babel-plugin-transform-es2015-for-of "^6.5.0"
babel-plugin-transform-es2015-function-name "^6.5.0"
babel-plugin-transform-es2015-literals "^6.5.0"
babel-plugin-transform-es2015-modules-commonjs "^6.5.0"
babel-plugin-transform-es2015-parameters "^6.5.0"
babel-plugin-transform-es2015-shorthand-properties "^6.5.0"
babel-plugin-transform-es2015-spread "^6.5.0"
babel-plugin-transform-es2015-template-literals "^6.5.0"
babel-plugin-transform-flow-strip-types "^6.5.0"
babel-plugin-transform-object-assign "^6.5.0"
babel-plugin-transform-object-rest-spread "^6.5.0"
babel-plugin-transform-react-display-name "^6.5.0"
babel-plugin-transform-react-jsx "^6.5.0"
babel-plugin-transform-react-jsx-source "^6.5.0"
babel-plugin-transform-regenerator "^6.5.0"
react-transform-hmr "^1.0.4"
babel-preset-react-native@^2.0.0, babel-preset-react-native@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/babel-preset-react-native/-/babel-preset-react-native-2.1.0.tgz#9013ebd82da1c88102bf588810ff59e209ca2b8a"
@@ -1805,6 +1771,14 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"
envinfo@^3.0.0:
version "3.4.1"
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-3.4.1.tgz#8c80e9f2eec2cd4e2adb2c5d0127ce07a2aaa2ae"
dependencies:
minimist "^1.2.0"
os-name "^2.0.1"
which "^1.2.14"
"errno@>=0.1.1 <0.2.0-0", errno@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
@@ -1930,25 +1904,26 @@ expect@^21.0.0:
jest-message-util "^21.0.0"
jest-regex-util "^21.0.0"
expo@^20.1.2:
version "20.1.2"
resolved "https://registry.yarnpkg.com/expo/-/expo-20.1.2.tgz#bac5723693bdfdd30aa003df7b05d06ee5459d5f"
expo@^21.0.1:
version "21.0.1"
resolved "https://registry.yarnpkg.com/expo/-/expo-21.0.1.tgz#c0e9da91041cf974a9157db6a4d9e8ac95755bc7"
dependencies:
"@expo/vector-icons" "^5.0.0"
babel-preset-expo "^3.0.0"
fbemitter "^2.1.1"
lodash.map "^4.6.0"
lodash.zipobject "^4.1.3"
lottie-react-native "1.1.1"
lottie-react-native "2.2.0"
md5-file "^3.1.1"
pretty-format "^20.0.3"
prop-types "^15.5.10"
qs "^6.5.0"
react-native-branch "2.0.0-beta.3"
react-native-gesture-handler "^1.0.0-alpha.14"
react-native-gesture-handler "1.0.0-alpha.22"
react-native-maps "0.15.3"
react-native-svg "5.3.0"
uuid-js "^0.7.5"
websql expo/node-websql#18.0.0
websql "https://github.com/expo/node-websql/archive/18.0.0.tar.gz"
express-session@~1.11.3:
version "1.11.3"
@@ -2603,9 +2578,9 @@ iconv-lite@0.4.18, iconv-lite@^0.4.17, iconv-lite@~0.4.13:
version "0.4.18"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2"
image-size@^0.3.5:
version "0.3.5"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.3.5.tgz#83240eab2fb5b00b04aab8c74b0471e9cba7ad8c"
image-size@^0.6.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.6.1.tgz#98122a562d59dcc097ef1b2c8191866eb8f5d663"
immediate@^3.2.2:
version "3.2.3"
@@ -3038,11 +3013,19 @@ jest-diff@^21.0.0:
jest-get-type "^21.0.0"
pretty-format "^21.0.0"
jest-docblock@20.1.0-chi.1:
version "20.1.0-chi.1"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.1.0-chi.1.tgz#06981ab0e59498a2492333b0c5502a82e4603207"
jest-docblock@20.1.0-delta.4:
version "20.1.0-delta.4"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.1.0-delta.4.tgz#360d4f5fb702730c4136c4e71e5706188a694682"
jest-docblock@^20.0.3:
version "20.0.3"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712"
jest-docblock@^20.1.0-alpha.3:
jest-docblock@^20.1.0-chi.1:
version "20.1.0-echo.1"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.1.0-echo.1.tgz#be02f43ee019f97e6b83267c746ac7b40d290fe8"
@@ -3080,9 +3063,9 @@ jest-environment-node@^21.0.0:
jest-mock "^21.0.0"
jest-util "^21.0.0"
jest-expo@^20.0.0:
version "20.0.0"
resolved "https://registry.yarnpkg.com/jest-expo/-/jest-expo-20.0.0.tgz#fc925bb8ecca56b410b5129d70407aa743e311b6"
jest-expo@^21.0.0:
version "21.0.2"
resolved "https://registry.yarnpkg.com/jest-expo/-/jest-expo-21.0.2.tgz#87c60deda29a9c67d5c59f24e7104aff6ce0aaee"
dependencies:
babel-jest "^20.0.3"
jest "^20.0.4"
@@ -3092,13 +3075,24 @@ jest-get-type@^21.0.0:
version "21.0.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.0.0.tgz#ed8667533c0a24a4feebbf492661f23abac3620b"
jest-haste-map@20.1.0-alpha.3:
version "20.1.0-alpha.3"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.1.0-alpha.3.tgz#37a1eea267cd770b99114a39c049a287501edf72"
jest-haste-map@20.1.0-chi.1:
version "20.1.0-chi.1"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.1.0-chi.1.tgz#db5f5f31362c76e242b40ea9a3ccfa364719cee3"
dependencies:
fb-watchman "^2.0.0"
graceful-fs "^4.1.11"
jest-docblock "^20.1.0-alpha.3"
jest-docblock "^20.1.0-chi.1"
micromatch "^2.3.11"
sane "^2.0.0"
worker-farm "^1.3.1"
jest-haste-map@20.1.0-delta.4:
version "20.1.0-delta.4"
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-20.1.0-delta.4.tgz#12e32b297a6dd49705cacde938029fc158834006"
dependencies:
fb-watchman "^2.0.0"
graceful-fs "^4.1.11"
jest-docblock "20.1.0-delta.4"
micromatch "^2.3.11"
sane "^2.0.0"
worker-farm "^1.3.1"
@@ -3723,16 +3717,17 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
dependencies:
js-tokens "^3.0.0"
lottie-ios@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/lottie-ios/-/lottie-ios-1.5.2.tgz#c188f1baa1c308a291538fc585a76e0cfc060711"
lottie-ios@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/lottie-ios/-/lottie-ios-2.0.5.tgz#3da0871e981f5621c633296eab0d9cf2340c0bcd"
lottie-react-native@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/lottie-react-native/-/lottie-react-native-1.1.1.tgz#1c87a3afca96edfa0869227140a2cff9bcc62c9b"
lottie-react-native@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/lottie-react-native/-/lottie-react-native-2.2.0.tgz#18196806ef6546cd3e01b24fc5a5974f02e4f017"
dependencies:
invariant "^2.2.2"
lottie-ios "^1.5.2"
lottie-ios "^2.0.5"
prop-types "^15.5.10"
react-native-safe-module "^1.1.0"
lower-case-first@^1.0.0:
@@ -3764,6 +3759,10 @@ lsmod@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lsmod/-/lsmod-1.0.0.tgz#9a00f76dca36eb23fa05350afe1b585d4299e64b"
macos-release@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-1.1.0.tgz#831945e29365b470aa8724b0ab36c8f8959d10fb"
makeerror@1.0.x:
version "1.0.11"
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c"
@@ -3817,9 +3816,9 @@ methods@^1.1.1, methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
metro-bundler@^0.9.0:
version "0.9.2"
resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.9.2.tgz#a23c1e0c28fc920f4280980dc7c3bb54e51d0240"
metro-bundler@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/metro-bundler/-/metro-bundler-0.11.0.tgz#ba5d2ae34943da28a37c2098047ad265c16fddf4"
dependencies:
absolute-path "^0.0.0"
async "^2.4.0"
@@ -3827,8 +3826,8 @@ metro-bundler@^0.9.0:
babel-generator "^6.24.1"
babel-plugin-external-helpers "^6.18.0"
babel-preset-es2015-node "^6.1.1"
babel-preset-fbjs "^2.1.0"
babel-preset-react-native "^1.9.1"
babel-preset-fbjs "^2.1.4"
babel-preset-react-native "^2.0.0"
babel-register "^6.24.1"
babylon "^6.17.0"
chalk "^1.1.1"
@@ -3838,8 +3837,9 @@ metro-bundler@^0.9.0:
denodeify "^1.2.1"
fbjs "0.8.12"
graceful-fs "^4.1.3"
image-size "^0.3.5"
jest-haste-map "^20.0.4"
image-size "^0.6.0"
jest-docblock "20.1.0-chi.1"
jest-haste-map "20.1.0-chi.1"
json-stable-stringify "^1.0.1"
json5 "^0.4.0"
left-pad "^1.1.3"
@@ -3851,7 +3851,7 @@ metro-bundler@^0.9.0:
rimraf "^2.5.4"
source-map "^0.5.6"
temp "0.8.3"
throat "^3.0.0"
throat "^4.1.0"
uglify-js "2.7.5"
write-file-atomic "^1.2.0"
xpipe "^1.0.5"
@@ -4212,6 +4212,13 @@ os-locale@^1.4.0:
dependencies:
lcid "^1.0.0"
os-name@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/os-name/-/os-name-2.0.1.tgz#b9a386361c17ae3a21736ef0599405c9a8c5dc5e"
dependencies:
macos-release "^1.0.0"
win-release "^1.0.0"
os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
@@ -4525,6 +4532,10 @@ qs@6.5.0, qs@^6.2.1, qs@^6.4.0:
version "6.5.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
qs@^6.5.0:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
querystring@0.2.0, querystring@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
@@ -4605,9 +4616,9 @@ react-deep-force-update@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/react-deep-force-update/-/react-deep-force-update-1.1.1.tgz#bcd31478027b64b3339f108921ab520b4313dc2c"
react-devtools-core@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-2.3.1.tgz#dc83aba85735effe5e1dc386a1614cb5e8d0047d"
react-devtools-core@^2.5.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-2.5.1.tgz#81ef30e0ac35c670d96b436d1f7510eaebe6c08b"
dependencies:
shell-quote "^1.6.1"
ws "^2.0.3"
@@ -4632,9 +4643,11 @@ react-native-drawer-layout@1.3.2:
dependencies:
react-native-dismiss-keyboard "1.0.0"
react-native-gesture-handler@^1.0.0-alpha.14:
version "1.0.0-alpha.17"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.0-alpha.17.tgz#1ae4412e1b208d175b34a14931d0635064a92e7b"
react-native-gesture-handler@1.0.0-alpha.22:
version "1.0.0-alpha.22"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.0.0-alpha.22.tgz#96e5ae08b26a9e99d115f6e16f63d7487ef995fc"
dependencies:
prop-types "^15.5.10"
react-native-maps@0.15.3:
version "0.15.3"
@@ -4686,9 +4699,9 @@ react-native-vector-icons@4.1.1:
prop-types "^15.5.8"
yargs "^6.3.0"
react-native@~0.47.2:
version "0.47.2"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.47.2.tgz#5e55cd84e4947123c86d36ea6f95ab9ed2d0cb19"
react-native@~0.48.4:
version "0.48.4"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.48.4.tgz#f305e9fef069a5b3f6a7250ddd50f603cf30ab2d"
dependencies:
absolute-path "^0.0.0"
art "^0.10.0"
@@ -4720,6 +4733,7 @@ react-native@~0.47.2:
create-react-class "^15.5.2"
debug "^2.2.0"
denodeify "^1.2.1"
envinfo "^3.0.0"
errno ">=0.1.1 <0.2.0-0"
event-target-shim "^1.0.5"
fbjs "0.8.12"
@@ -4729,13 +4743,13 @@ react-native@~0.47.2:
glob "^7.1.1"
graceful-fs "^4.1.3"
inquirer "^3.0.6"
jest-haste-map "20.1.0-alpha.3"
jest-haste-map "20.1.0-delta.4"
json-stable-stringify "^1.0.1"
json5 "^0.4.0"
left-pad "^1.1.3"
lodash "^4.16.6"
merge-stream "^1.0.1"
metro-bundler "^0.9.0"
metro-bundler "^0.11.0"
mime "^1.3.4"
mime-types "2.1.11"
minimist "^1.2.0"
@@ -4749,7 +4763,7 @@ react-native@~0.47.2:
promise "^7.1.1"
prop-types "^15.5.8"
react-clone-referenced-element "^1.0.1"
react-devtools-core "2.3.1"
react-devtools-core "^2.5.0"
react-timer-mixin "^0.13.2"
react-transform-hmr "^1.0.4"
rebound "^0.0.13"
@@ -4762,7 +4776,7 @@ react-native@~0.47.2:
source-map "^0.5.6"
stacktrace-parser "^0.1.3"
temp "0.8.3"
throat "^3.0.0"
throat "^4.1.0"
whatwg-fetch "^1.0.0"
wordwrap "^1.0.0"
write-file-atomic "^1.2.0"
@@ -4774,7 +4788,7 @@ react-native@~0.47.2:
yargs "^6.4.0"
"react-navigation@file:../..":
version "1.0.0-beta.12"
version "1.0.0-beta.13"
dependencies:
babel-plugin-transform-define "^1.3.0"
clamp "^1.0.1"
@@ -5144,7 +5158,7 @@ sax@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240"
"semver@2 || 3 || 4 || 5", semver@5.x, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0:
"semver@2 || 3 || 4 || 5", semver@5.x, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
@@ -5606,7 +5620,7 @@ throat@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836"
throat@^4.0.0:
throat@^4.0.0, throat@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a"
@@ -5897,9 +5911,9 @@ webidl-conversions@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
websql@expo/node-websql#18.0.0:
"websql@https://github.com/expo/node-websql/archive/18.0.0.tar.gz":
version "0.4.4"
resolved "https://codeload.github.com/expo/node-websql/tar.gz/e364fa65146a9e2157a19e5c719e7702c2b6b87a"
resolved "https://github.com/expo/node-websql/archive/18.0.0.tar.gz#39b12a08b0180495de1412d8a64a529e21ad554e"
dependencies:
argsarray "^0.0.1"
immediate "^3.2.2"
@@ -5932,7 +5946,7 @@ which-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
which@^1.2.12, which@^1.2.9:
which@^1.2.12, which@^1.2.14, which@^1.2.9:
version "1.3.0"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
dependencies:
@@ -5944,6 +5958,12 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2"
win-release@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/win-release/-/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
dependencies:
semver "^5.0.1"
winchan@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/winchan/-/winchan-0.1.4.tgz#88fa12411cd542eb626018c38a196bcbb17993bb"

View File

@@ -1,6 +1,6 @@
{
"name": "react-navigation",
"version": "1.0.0-beta.13",
"version": "1.0.0-beta.14",
"description": "React Navigation",
"main": "src/react-navigation.js",
"sources": {
@@ -83,7 +83,7 @@
"react": "16.0.0-alpha.12",
"react-native": "^0.48.4",
"react-native-vector-icons": "^4.2.0",
"react-test-renderer": "^15.6.1"
"react-test-renderer": "^16.0.0"
},
"jest": {
"notify": true,

View File

@@ -262,6 +262,7 @@ export type HeaderProps = {
NavigationStackScreenOptions
>,
style: ViewStyleProp,
isLandscape?: boolean,
};
/**
@@ -273,6 +274,7 @@ export type NavigationStackScreenOptions = {
header?: ?(React.Element<*> | (HeaderProps => React.Element<*>)),
headerTitle?: string | React.Element<*>,
headerTitleStyle?: AnimatedTextStyleProp,
headerTitleAllowFontScaling?: boolean,
headerTintColor?: string,
headerLeft?: React.Element<*>,
headerBackTitle?: string,
@@ -334,6 +336,7 @@ export type NavigationTabScreenOptions = {
*
>),
tabBarVisible?: boolean,
tabBarTestIDProps?: { testID?: string, accessibilityLabel?: string },
tabBarOnPress?: (
scene: TabScene,
jumpToIndex: (index: number) => void

View File

@@ -1,7 +1,6 @@
/* @flow */
import React from 'react';
import invariant from './utils/invariant';
import { BackHandler, Linking } from './PlatformHelpers';
import NavigationActions from './NavigationActions';
import addNavigationHelpers from './addNavigationHelpers';
@@ -74,15 +73,16 @@ export default function createNavigationContainer<S: *, O>(
const keys = Object.keys(containerProps);
invariant(
keys.length === 0,
'This navigator has both navigation and container props, so it is ' +
`unclear if it should own its own state. Remove props: "${keys.join(
', '
)}" ` +
'if the navigator should get its state from the navigation prop. If the ' +
'navigator should maintain its own state, do not pass a navigation prop.'
);
if (keys.length !== 0) {
throw new Error(
'This navigator has both navigation and container props, so it is ' +
`unclear if it should own its own state. Remove props: "${keys.join(
', '
)}" ` +
'if the navigator should get its state from the navigation prop. If the ' +
'navigator should maintain its own state, do not pass a navigation prop.'
);
}
}
_urlToPathAndParams(url: string) {

View File

@@ -32,6 +32,7 @@ const DefaultDrawerConfig = {
Dimensions.get('window').width - (Platform.OS === 'android' ? 56 : 64),
contentComponent: DrawerItems,
drawerPosition: 'left',
drawerBackgroundColor: 'white',
useNativeAnimations: true,
};
@@ -48,6 +49,7 @@ const DrawerNavigator = (
contentOptions,
drawerPosition,
useNativeAnimations,
drawerBackgroundColor,
...tabsConfig
} = mergedConfig;
@@ -83,6 +85,7 @@ const DrawerNavigator = (
)((props: *) => (
<DrawerView
{...props}
drawerBackgroundColor={drawerBackgroundColor}
drawerLockMode={drawerLockMode}
useNativeAnimations={useNativeAnimations}
drawerWidth={drawerWidth}

View File

@@ -357,10 +357,11 @@ export default (
// get the action for the path AFTER the matched path for this
// router
let nestedAction;
let nestedQueryString = queryString ? '?' + queryString : '';
if (childRouters[matchedRouteName]) {
nestedAction = childRouters[matchedRouteName].getActionForPathAndParams(
/* $FlowFixMe */
pathMatch.slice(pathMatchKeys.length).join('/')
pathMatch.slice(pathMatchKeys.length).join('/') + nestedQueryString
);
}

View File

@@ -45,11 +45,12 @@ export default (
tabRouters[routeName] = routeConfig.screen.router;
}
});
invariant(
initialRouteIndex !== -1,
`Invalid initialRouteName '${initialRouteName}' for TabRouter. ` +
`Should be one of ${order.map((n: *) => `"${n}"`).join(', ')}`
);
if (initialRouteIndex === -1) {
throw new Error(
`Invalid initialRouteName '${initialRouteName}' for TabRouter. ` +
`Should be one of ${order.map((n: *) => `"${n}"`).join(', ')}`
);
}
return {
getStateForAction(
action: NavigationAction | { action: NavigationAction },

View File

@@ -902,4 +902,66 @@ describe('StackRouter', () => {
)
);
});
test('Querystring params get passed to nested deep link', () => {
// uri with two non-empty query param values
const uri = 'main/p/4/list/10259959195?code=test&foo=bar';
const action = TestStackRouter.getActionForPathAndParams(uri);
expect(action).toEqual({
type: NavigationActions.NAVIGATE,
routeName: 'main',
params: {
code: 'test',
foo: 'bar',
},
action: {
type: NavigationActions.NAVIGATE,
routeName: 'profile',
params: {
id: '4',
code: 'test',
foo: 'bar',
},
action: {
type: NavigationActions.NAVIGATE,
routeName: 'list',
params: {
id: '10259959195',
code: 'test',
foo: 'bar',
},
},
},
});
// uri with one empty and one non-empty query param value
const uri2 = 'main/p/4/list/10259959195?code=&foo=bar';
const action2 = TestStackRouter.getActionForPathAndParams(uri2);
expect(action2).toEqual({
type: NavigationActions.NAVIGATE,
routeName: 'main',
params: {
code: '',
foo: 'bar',
},
action: {
type: NavigationActions.NAVIGATE,
routeName: 'profile',
params: {
id: '4',
code: '',
foo: 'bar',
},
action: {
type: NavigationActions.NAVIGATE,
routeName: 'list',
params: {
id: '10259959195',
code: '',
foo: 'bar',
},
},
},
});
});
});

View File

@@ -63,10 +63,11 @@ export default (
let outputConfig = {};
if (Component.router) {
invariant(
route && routes && index != null,
`Expect nav state to have routes and index, ${JSON.stringify(route)}`
);
if (!route || !routes || index == null) {
throw new Error(
`Expect nav state to have routes and index, ${JSON.stringify(route)}`
);
}
const childRoute = routes[index];
const childNavigation = addNavigationHelpers({
state: childRoute,

View File

@@ -17,13 +17,14 @@ export default function getScreenForRouteName( // eslint-disable-line consistent
): NavigationComponent {
const routeConfig = routeConfigs[routeName];
invariant(
routeConfig,
`There is no route defined for key ${routeName}.\n` +
`Must be one of: ${Object.keys(routeConfigs)
.map((a: string) => `'${a}'`)
.join(',')}`
);
if (!routeConfig) {
throw new Error(
`There is no route defined for key ${routeName}.\n` +
`Must be one of: ${Object.keys(routeConfigs)
.map((a: string) => `'${a}'`)
.join(',')}`
);
}
if (routeConfig.screen) {
return routeConfig.screen;
@@ -41,5 +42,5 @@ export default function getScreenForRouteName( // eslint-disable-line consistent
return screen;
}
invariant(false, `Route ${routeName} must define a screen or a getScreen.`);
throw new Error(`Route ${routeName} must define a screen or a getScreen.`);
}

View File

@@ -18,28 +18,25 @@ function validateRouteConfigMap(routeConfigs: NavigationRouteConfigMap) {
routeNames.forEach((routeName: string) => {
const routeConfig = routeConfigs[routeName];
invariant(
routeConfig.screen || routeConfig.getScreen,
`Route '${routeName}' should declare a screen. ` +
'For example:\n\n' +
"import MyScreen from './MyScreen';\n" +
'...\n' +
`${routeName}: {\n` +
' screen: MyScreen,\n' +
'}'
);
if (routeConfig.screen && routeConfig.getScreen) {
invariant(
false,
if (!routeConfig.screen && !routeConfig.getScreen) {
throw new Error(
`Route '${routeName}' should declare a screen. ` +
'For example:\n\n' +
"import MyScreen from './MyScreen';\n" +
'...\n' +
`${routeName}: {\n` +
' screen: MyScreen,\n' +
'}'
);
} else if (routeConfig.screen && routeConfig.getScreen) {
throw new Error(
`Route '${routeName}' should declare a screen or ` +
'a getScreen, not both.'
);
}
if (routeConfig.screen) {
invariant(
typeof routeConfig.screen === 'function',
if (routeConfig.screen && typeof routeConfig.screen !== 'function') {
throw new Error(
`The component for route '${routeName}' must be a ` +
'React component. For example:\n\n' +
"import MyScreen from './MyScreen';\n" +

View File

@@ -1,5 +1,4 @@
/* @flow */
import invariant from '../utils/invariant';
import type { NavigationRoute } from '../TypeDefinition';
@@ -15,8 +14,7 @@ export default (screenOptions: *, route: NavigationRoute) => {
const deprecatedKey = keys.find((key: *) => deprecatedKeys.includes(key));
if (typeof screenOptions.title === 'function') {
invariant(
false,
throw new Error(
[
`\`title\` cannot be defined as a function in navigation options for \`${route.routeName}\` screen. \n`,
'Try replacing the following:',
@@ -33,8 +31,7 @@ export default (screenOptions: *, route: NavigationRoute) => {
}
if (deprecatedKey && typeof screenOptions[deprecatedKey] === 'function') {
invariant(
false,
throw new Error(
[
`\`${deprecatedKey}\` cannot be defined as a function in navigation options for \`${route.routeName}\` screen. \n`,
'Try replacing the following:',
@@ -53,8 +50,7 @@ export default (screenOptions: *, route: NavigationRoute) => {
}
if (deprecatedKey && typeof screenOptions[deprecatedKey] === 'object') {
invariant(
false,
throw new Error(
[
`Invalid key \`${deprecatedKey}\` defined in navigation options for \`${route.routeName}\` screen.`,
'\n',

View File

@@ -5,8 +5,6 @@
* 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.
*
* @providesModule invariant
*/
'use strict';

View File

@@ -6,7 +6,6 @@
* 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.
*
* @providesModule shallowEqual
* @typechecks
* @flow
*/

View File

@@ -125,6 +125,5 @@ export default withCachedChildNavigation(DrawerSidebar);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
},
});

View File

@@ -36,6 +36,7 @@ export type DrawerViewConfig = {
contentOptions?: {},
style?: ViewStyleProp,
useNativeAnimations?: boolean,
drawerBackgroundColor?: String,
};
type Props = DrawerViewConfig & {
@@ -160,6 +161,7 @@ export default class DrawerView<T: *> extends PureComponent<void, Props, void> {
(this.props.screenProps && this.props.screenProps.drawerLockMode) ||
(config && config.drawerLockMode)
}
drawerBackgroundColor={this.props.drawerBackgroundColor}
drawerWidth={this.props.drawerWidth}
onDrawerOpen={this._handleDrawerOpen}
onDrawerClose={this._handleDrawerClose}

View File

@@ -9,6 +9,7 @@ import { Animated, Platform, StyleSheet, View } from 'react-native';
import HeaderTitle from './HeaderTitle';
import HeaderBackButton from './HeaderBackButton';
import HeaderStyleInterpolator from './HeaderStyleInterpolator';
import withOrientation from '../withOrientation';
import type {
NavigationScene,
@@ -91,6 +92,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
const titleStyle = details.options.headerTitleStyle;
const color = details.options.headerTintColor;
const allowFontScaling = details.options.headerTitleAllowFontScaling;
// On iOS, width of left/right components depends on the calculated
// size of the title.
@@ -109,6 +111,7 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
return (
<HeaderTitle
onLayout={onLayoutIOS}
allowFontScaling={allowFontScaling == null ? true : allowFontScaling}
style={[color ? { color } : null, titleStyle]}
>
{titleString}
@@ -281,14 +284,25 @@ class Header extends React.PureComponent<void, HeaderProps, HeaderState> {
screenProps,
progress,
style,
isLandscape,
...rest
} = this.props;
const { options } = this.props.getScreenDetails(scene);
const headerStyle = options.headerStyle;
const landscapeAwareStatusBarHeight = isLandscape ? 0 : STATUSBAR_HEIGHT;
const containerStyles = [
styles.container,
{
paddingTop: landscapeAwareStatusBarHeight,
height: APPBAR_HEIGHT + landscapeAwareStatusBarHeight,
},
headerStyle,
style,
];
return (
<Animated.View {...rest} style={[styles.container, headerStyle, style]}>
<Animated.View {...rest} style={containerStyles}>
<View style={styles.appBar}>{appBar}</View>
</Animated.View>
);
@@ -315,9 +329,7 @@ if (Platform.OS === 'ios') {
const styles = StyleSheet.create({
container: {
paddingTop: STATUSBAR_HEIGHT,
backgroundColor: Platform.OS === 'ios' ? '#F7F7F7' : '#FFF',
height: STATUSBAR_HEIGHT + APPBAR_HEIGHT,
...platformContainerStyles,
},
appBar: {
@@ -353,4 +365,4 @@ const styles = StyleSheet.create({
},
});
export default Header;
export default withOrientation(Header);

View File

@@ -1,8 +1,15 @@
/* @flow */
import React, { PureComponent } from 'react';
import { Animated, TouchableWithoutFeedback, StyleSheet } from 'react-native';
import {
Animated,
TouchableWithoutFeedback,
StyleSheet,
View,
Platform,
} from 'react-native';
import TabBarIcon from './TabBarIcon';
import withOrientation from '../withOrientation';
import type {
NavigationAction,
@@ -21,6 +28,8 @@ type DefaultProps = {
inactiveTintColor: string,
inactiveBackgroundColor: string,
showLabel: boolean,
showIcon: boolean,
allowFontScaling: boolean,
};
type Props = {
@@ -28,6 +37,9 @@ type Props = {
activeBackgroundColor: string,
inactiveTintColor: string,
inactiveBackgroundColor: string,
showLabel: boolean,
showIcon: boolean,
allowFontScaling: boolean,
position: Animated.Value,
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
jumpToIndex: (index: number) => void,
@@ -35,27 +47,27 @@ type Props = {
getOnPress: (
scene: TabScene
) => (scene: TabScene, jumpToIndex: (index: number) => void) => void,
getTestIDProps: (scene: TabScene) => (scene: TabScene) => any,
renderIcon: (scene: TabScene) => React.Element<*>,
showLabel: boolean,
style?: ViewStyleProp,
labelStyle?: TextStyleProp,
tabStyle?: ViewStyleProp,
showIcon: boolean,
showIcon?: boolean,
isLandscape?: boolean,
};
export default class TabBarBottom extends PureComponent<
DefaultProps,
Props,
void
> {
const majorVersionIOS = parseInt(Platform.Version, 10);
class TabBarBottom extends PureComponent<DefaultProps, Props, void> {
// See https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/UIKitUICatalog/UITabBar.html
static defaultProps = {
static defaultProps: DefaultProps = {
activeTintColor: '#3478f6', // Default active tint color in iOS 10
activeBackgroundColor: 'transparent',
inactiveTintColor: '#929292', // Default inactive tint color in iOS 10
inactiveBackgroundColor: 'transparent',
showLabel: true,
showIcon: true,
allowFontScaling: true,
};
props: Props;
@@ -68,6 +80,9 @@ export default class TabBarBottom extends PureComponent<
inactiveTintColor,
labelStyle,
showLabel,
showIcon,
isLandscape,
allowFontScaling,
} = this.props;
if (showLabel === false) {
return null;
@@ -87,9 +102,21 @@ export default class TabBarBottom extends PureComponent<
const tintColor = scene.focused ? activeTintColor : inactiveTintColor;
const label = this.props.getLabel({ ...scene, tintColor });
let marginLeft = 0;
if (isLandscape && showIcon && majorVersionIOS >= 11) {
marginLeft = LABEL_LEFT_MARGIN;
}
let marginTop = 0;
if (!isLandscape && showIcon && majorVersionIOS >= 11) {
marginTop = LABEL_TOP_MARGIN;
}
if (typeof label === 'string') {
return (
<Animated.Text style={[styles.label, { color }, labelStyle]}>
<Animated.Text
style={[styles.label, { color, marginLeft, marginTop }, labelStyle]}
allowFontScaling={allowFontScaling}
>
{label}
</Animated.Text>
);
@@ -110,6 +137,7 @@ export default class TabBarBottom extends PureComponent<
inactiveTintColor,
renderIcon,
showIcon,
showLabel,
} = this.props;
if (showIcon === false) {
return null;
@@ -122,21 +150,29 @@ export default class TabBarBottom extends PureComponent<
inactiveTintColor={inactiveTintColor}
renderIcon={renderIcon}
scene={scene}
style={styles.icon}
style={showLabel && majorVersionIOS >= 11 ? {} : styles.icon}
/>
);
};
_renderTestIDProps = (scene: TabScene) => {
const testIDProps =
this.props.getTestIDProps && this.props.getTestIDProps(scene);
return testIDProps;
};
render() {
const {
position,
navigation,
jumpToIndex,
getOnPress,
getTestIDProps,
activeBackgroundColor,
inactiveBackgroundColor,
style,
tabStyle,
isLandscape,
} = this.props;
const { routes } = navigation.state;
// Prepend '-1', so there are always at least 2 items in inputRange
@@ -157,17 +193,25 @@ export default class TabBarBottom extends PureComponent<
inputRange,
outputRange: (outputRange: Array<string>),
});
const justifyContent = this.props.showIcon ? 'flex-end' : 'center';
const extraProps = this._renderTestIDProps(scene) || {};
const { testID, accessibilityLabel } = extraProps;
return (
<TouchableWithoutFeedback
key={route.key}
testID={testID}
accessibilityLabel={accessibilityLabel}
onPress={() =>
onPress ? onPress(scene, jumpToIndex) : jumpToIndex(index)}
>
<Animated.View
style={[
styles.tab,
{ backgroundColor, justifyContent },
isLandscape && majorVersionIOS >= 11 && styles.tabLandscape,
!isLandscape && majorVersionIOS >= 11 && styles.tabPortrait,
{ backgroundColor },
tabStyle,
]}
>
@@ -182,19 +226,29 @@ export default class TabBarBottom extends PureComponent<
}
}
const LABEL_LEFT_MARGIN = 20;
const LABEL_TOP_MARGIN = 15;
const styles = StyleSheet.create({
tabBar: {
height: 49, // Default tab bar height in iOS 10
height: 49, // Default tab bar height in iOS 10+
flexDirection: 'row',
borderTopWidth: StyleSheet.hairlineWidth,
borderTopColor: 'rgba(0, 0, 0, .3)',
backgroundColor: '#F7F7F7', // Default background color in iOS 10
backgroundColor: '#F7F7F7', // Default background color in iOS 10+
},
tab: {
flex: 1,
alignItems: 'stretch',
alignItems: 'center',
justifyContent: 'flex-end',
},
tabPortrait: {
justifyContent: 'flex-end',
flexDirection: 'column',
},
tabLandscape: {
justifyContent: 'center',
flexDirection: 'row',
},
icon: {
flexGrow: 1,
},
@@ -205,3 +259,5 @@ const styles = StyleSheet.create({
backgroundColor: 'transparent',
},
});
export default withOrientation(TabBarBottom);

View File

@@ -21,6 +21,7 @@ type DefaultProps = {
showIcon: boolean,
showLabel: boolean,
upperCaseLabel: boolean,
allowFontScaling: boolean,
};
type Props = {
@@ -29,6 +30,7 @@ type Props = {
showIcon: boolean,
showLabel: boolean,
upperCaseLabel: boolean,
allowFontScaling: boolean,
position: Animated.Value,
navigation: NavigationScreenProp<NavigationState, NavigationAction>,
jumpToIndex: (index: number) => void,
@@ -46,12 +48,13 @@ export default class TabBarTop extends PureComponent<
Props,
void
> {
static defaultProps = {
static defaultProps: DefaultProps = {
activeTintColor: '#fff',
inactiveTintColor: '#fff',
showIcon: false,
showLabel: true,
upperCaseLabel: true,
allowFontScaling: true,
};
props: Props;
@@ -65,6 +68,7 @@ export default class TabBarTop extends PureComponent<
showLabel,
upperCaseLabel,
labelStyle,
allowFontScaling,
} = this.props;
if (showLabel === false) {
return null;
@@ -86,7 +90,10 @@ export default class TabBarTop extends PureComponent<
const label = this.props.getLabel({ ...scene, tintColor });
if (typeof label === 'string') {
return (
<Animated.Text style={[styles.label, { color }, labelStyle]}>
<Animated.Text
style={[styles.label, { color }, labelStyle]}
allowFontScaling={allowFontScaling}
>
{upperCaseLabel ? label.toUpperCase() : label}
</Animated.Text>
);

View File

@@ -104,6 +104,15 @@ class TabView extends PureComponent<void, Props, void> {
return options.tabBarOnPress;
};
_getTestIDProps = ({ route }: TabScene) => {
const options = this.props.router.getScreenOptions(
this.props.childNavigationProps[route.key],
this.props.screenProps || {}
);
return options.tabBarTestIDProps;
};
_renderIcon = ({ focused, route, tintColor }: TabScene) => {
const options = this.props.router.getScreenOptions(
this.props.childNavigationProps[route.key],
@@ -133,6 +142,7 @@ class TabView extends PureComponent<void, Props, void> {
screenProps={this.props.screenProps}
navigation={this.props.navigation}
getLabel={this._getLabel}
getTestIDProps={this._getTestIDProps}
getOnPress={this._getOnPress}
renderIcon={this._renderIcon}
animationEnabled={animationEnabled}

View File

@@ -0,0 +1,31 @@
import React from 'react';
import { View } from 'react-native';
import renderer from 'react-test-renderer';
import TabRouter from '../../routers/TabRouter';
import TabView from '../TabView/TabView';
import TabBarBottom from '../TabView/TabBarBottom';
describe('TabBarBottom', () => {
it('renders successfully', () => {
const navigation = {
state: {
index: 0,
routes: [{ key: 's1', routeName: 's1' }],
},
};
const router = TabRouter({ s1: { screen: View } });
const rendered = renderer
.create(
<TabView
tabBarComponent={TabBarBottom}
navigation={navigation}
router={router}
/>
)
.toJSON();
expect(rendered).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,228 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TabBarBottom renders successfully 1`] = `
<View
loaded={
Array [
0,
]
}
onLayout={[Function]}
style={
Array [
Object {
"flex": 1,
"overflow": "hidden",
},
Object {
"flex": 1,
},
]
}
>
<View
collapsable={undefined}
style={
Object {
"backgroundColor": "#F7F7F7",
"borderTopColor": "rgba(0, 0, 0, .3)",
"borderTopWidth": 0.5,
"flexDirection": "row",
"height": 49,
}
}
>
<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]}
style={
Object {
"alignItems": "center",
"backgroundColor": "rgba(0, 0, 0, 0)",
"flex": 1,
"justifyContent": "flex-end",
}
}
testID={undefined}
>
<View
style={
Object {
"flexGrow": 1,
}
}
>
<View
collapsable={undefined}
style={
Object {
"alignItems": "center",
"bottom": 0,
"justifyContent": "center",
"left": 0,
"opacity": 1,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
<View
collapsable={undefined}
style={
Object {
"alignItems": "center",
"bottom": 0,
"justifyContent": "center",
"left": 0,
"opacity": 0,
"position": "absolute",
"right": 0,
"top": 0,
}
}
/>
</View>
<Text
accessible={true}
allowFontScaling={true}
collapsable={undefined}
disabled={false}
ellipsizeMode="tail"
style={
Object {
"backgroundColor": "transparent",
"color": "rgba(52, 120, 246, 1)",
"fontSize": 10,
"marginBottom": 1.5,
"marginLeft": 0,
"marginTop": 0,
"textAlign": "center",
}
}
>
s1
</Text>
</View>
</View>
<RCTScrollView
DEPRECATED_sendUpdatedChildFrames={false}
alwaysBounceHorizontal={false}
alwaysBounceVertical={false}
automaticallyAdjustContentInsets={false}
bounces={false}
contentContainerStyle={
Object {
"flexGrow": 1,
}
}
contentOffset={
Object {
"x": 0,
"y": 0,
}
}
directionalLockEnabled={true}
horizontal={true}
keyboardDismissMode="on-drag"
keyboardShouldPersistTaps="always"
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]}
onTouchEnd={[Function]}
onTouchMove={[Function]}
onTouchStart={[Function]}
pagingEnabled={true}
scrollEnabled={undefined}
scrollEventThrottle={16}
scrollsToTop={false}
sendMomentumEvents={true}
showsHorizontalScrollIndicator={false}
style={
Array [
Object {
"flexDirection": "row",
"flexGrow": 1,
"flexShrink": 1,
"overflow": "scroll",
},
Object {
"flexGrow": 1,
},
]
}
>
<RCTScrollContentView
collapsable={false}
removeClippedSubviews={undefined}
style={
Array [
Object {
"flexDirection": "row",
},
Object {
"flexGrow": 1,
},
]
}
>
<View
style={
Object {
"flex": 1,
"overflow": "hidden",
}
}
testID={undefined}
>
<View
style={
Object {
"flex": 1,
"overflow": "hidden",
}
}
>
<View
navigation={
Object {
"goBack": [Function],
"navigate": [Function],
"setParams": [Function],
"state": Object {
"key": "s1",
"routeName": "s1",
},
}
}
screenProps={undefined}
/>
</View>
</View>
</RCTScrollContentView>
</RCTScrollView>
</View>
`;

View File

@@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it adds isLandscape to props 1`] = `
<View
isLandscape={false}
/>
`;

View File

@@ -0,0 +1,15 @@
import React from 'react';
import { View } from 'react-native';
import renderer from 'react-test-renderer';
import withOrientation, { isOrientationLandscape } from '../withOrientation';
test('it adds isLandscape to props', () => {
const WrappedComponent = withOrientation(View);
const rendered = renderer.create(<WrappedComponent />).toJSON();
expect(rendered).toMatchSnapshot();
});
test('calculates orientation correctly', () => {
const isLandscape = isOrientationLandscape({ width: 10, height: 1 });
expect(isLandscape).toBeTruthy();
});

View File

@@ -0,0 +1,55 @@
// @flow
import React from 'react';
import { Dimensions } from 'react-native';
import hoistNonReactStatic from 'hoist-non-react-statics';
type WindowDimensions = {
width: number,
height: number,
};
type InjectedProps = {
isLandscape: boolean,
};
type State = {
isLandscape: boolean,
};
export const isOrientationLandscape = ({
width,
height,
}: WindowDimensions): boolean => width > height;
export default function<T: *>(WrappedComponent: ReactClass<T & InjectedProps>) {
class withOrientation extends React.Component<void, T, State> {
state: State;
constructor() {
super();
const isLandscape = isOrientationLandscape(Dimensions.get('window'));
this.state = { isLandscape };
}
componentDidMount() {
Dimensions.addEventListener('change', this.handleOrientationChange);
}
componentWillUnmount() {
Dimensions.removeEventListener('change', this.handleOrientationChange);
}
handleOrientationChange = ({ window }: { window: WindowDimensions }) => {
const isLandscape = isOrientationLandscape(window);
this.setState({ isLandscape });
};
render() {
return <WrappedComponent {...this.props} {...this.state} />;
}
}
return hoistNonReactStatic(withOrientation, WrappedComponent);
}

View File

@@ -6,7 +6,6 @@
* 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.
*
* @providesModule RelativeImageStub
* @flow
*/
'use strict';

View File

@@ -2287,6 +2287,18 @@ fbjs@0.8.12:
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fbjs@^0.8.16:
version "0.8.16"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fbjs@^0.8.9:
version "0.8.15"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.15.tgz#4f0695fdfcc16c37c0b07facec8cb4c4091685b9"
@@ -4587,12 +4599,12 @@ react-proxy@^1.1.7:
lodash "^4.6.1"
react-deep-force-update "^1.0.0"
react-test-renderer@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.6.1.tgz#026f4a5bb5552661fd2cc4bbcd0d4bc8a35ebf7e"
react-test-renderer@^16.0.0:
version "16.0.0"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.0.0.tgz#9fe7b8308f2f71f29fc356d4102086f131c9cb15"
dependencies:
fbjs "^0.8.9"
object-assign "^4.1.0"
fbjs "^0.8.16"
object-assign "^4.1.1"
react-timer-mixin@^0.13.2:
version "0.13.3"