mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-26 13:35:32 +08:00
Compare commits
32 Commits
v1.0.0-bet
...
v1.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ac3bb90ed | ||
|
|
627c487936 | ||
|
|
f46bdff703 | ||
|
|
bc75a5b7b9 | ||
|
|
50d5c8bc0a | ||
|
|
c7b73cd8b4 | ||
|
|
e2e540c32d | ||
|
|
7a57c4e779 | ||
|
|
4373544257 | ||
|
|
8329e269b6 | ||
|
|
450a1e3ba5 | ||
|
|
a83220b511 | ||
|
|
6af770d644 | ||
|
|
ef63b230b2 | ||
|
|
41b587ca65 | ||
|
|
faed4731bc | ||
|
|
7fe76fb7c6 | ||
|
|
89a6668595 | ||
|
|
9cf9e25661 | ||
|
|
363f93fc4d | ||
|
|
928f632c89 | ||
|
|
950d0c6877 | ||
|
|
5a26506595 | ||
|
|
5cb42bdf5d | ||
|
|
d5618ebd41 | ||
|
|
368bc615c1 | ||
|
|
f332b6bdf7 | ||
|
|
b5700b9277 | ||
|
|
ad59d161db | ||
|
|
cc355dcee9 | ||
|
|
04c075c1bb | ||
|
|
7ae6908428 |
10
.github/ISSUE_TEMPLATE.md
vendored
10
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,10 +1,10 @@
|
||||
## The issue list is reserved for bugs and feature requests, not for questions.
|
||||
## The issue tracker is reserved for bug reports only.
|
||||
|
||||
For usage questions, try to:
|
||||
If you have a question or feature request, please try one of the following resources:
|
||||
|
||||
- [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)
|
||||
- [Read the documentation](https://reactnavigation.org/)
|
||||
- [Post a feature request to Canny](https://react-navigation.canny.io/feature-requests)
|
||||
- [Get help on Discord chat (#react-navigation on Reactiflux)](https://discord.gg/4xEK3nD) or [on StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation)
|
||||
- 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.
|
||||
|
||||
---
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# React Navigation [](https://circleci.com/gh/react-community/react-navigation/tree/master) [](https://badge.fury.io/js/react-navigation) [](https://codecov.io/gh/react-community/react-navigation) [](https://reactnavigation.org/docs/guides/contributors)
|
||||
# React Navigation
|
||||
|
||||
[](https://badge.fury.io/js/react-navigation) [](https://codecov.io/gh/react-community/react-navigation) [](https://reactnavigation.org/docs/guides/contributors)
|
||||
|
||||
*Learn once, navigate anywhere.*
|
||||
|
||||
|
||||
@@ -158,6 +158,10 @@ Object to override the distance of touch start from the edge of the screen to re
|
||||
- `horizontal` - *number* - Distance for horizontal direction. Defaults to 25.
|
||||
- `vertical` - *number* - Distance for vertical direction. Defaults to 135.
|
||||
|
||||
#### `gestureDirection`
|
||||
|
||||
String to override the direction for dismiss gesture. `default` for normal behaviour or `inverted` for right-to-left swipes.
|
||||
|
||||
### Navigator Props
|
||||
|
||||
The navigator component created by `StackNavigator(...)` takes the following props:
|
||||
@@ -222,3 +226,5 @@ const ModalNavigator = StackNavigator(
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
Header transitions can also be configured using `headerLeftInterpolator`, `headerTitleInterpolator` and `headerRightInterpolator` fields under `transitionConfig`.
|
||||
|
||||
@@ -88,7 +88,6 @@ The route configs object is a mapping from route name to a route config, which t
|
||||
- `swipeEnabled` - Whether to allow swiping between tabs.
|
||||
- `animationEnabled` - Whether to animate when changing tabs.
|
||||
- `configureTransition` - a function that, given `currentTransitionProps` and `nextTransitionProps`, returns a configuration object that describes the animation between tabs.
|
||||
- `lazy` - Whether to lazily render tabs as needed as opposed to rendering them upfront.
|
||||
- `initialLayout` - Optional object containing the initial `height` and `width`, can be passed to prevent the one frame delay in [react-native-tab-view](https://github.com/react-native-community/react-native-tab-view#avoid-one-frame-delay) rendering.
|
||||
- `tabBarOptions` - Configure the tab bar, see below.
|
||||
|
||||
@@ -168,6 +167,10 @@ Generic title that can be used as a fallback for `headerTitle` and `tabBarLabel`
|
||||
|
||||
True or false to show or hide the tab bar, if not set then defaults to true.
|
||||
|
||||
#### `swipeEnabled`
|
||||
|
||||
True or false to enable or disable swiping between tabs, if not set then defaults to TabNavigatorConfig option swipeEnabled.
|
||||
|
||||
#### `tabBarIcon`
|
||||
|
||||
React Element or a function that given `{ focused: boolean, tintColor: string }` returns a React.Node, to display in tab bar.
|
||||
|
||||
@@ -166,20 +166,24 @@ render: (transitionProps: NavigationTransitionProps, prevTransitionProps: ?Navig
|
||||
### `onTransitionStart` function
|
||||
Invoked when the transition animation is about to start.
|
||||
|
||||
If you return a promise from `onTransitionStart`, the transition animation will begin after the promise is resolved.
|
||||
|
||||
#### Flow definition
|
||||
```js
|
||||
onTransitionStart: (transitionProps: NavigationTransitionProps, prevTransitionProps: ?NavigationTransitionProps) => void,
|
||||
onTransitionStart: (transitionProps: NavigationTransitionProps, prevTransitionProps: ?NavigationTransitionProps) => (Promise | void),
|
||||
```
|
||||
#### Parameters
|
||||
- `transitionProps`: the current [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the current state and props
|
||||
- `prevTransitionProps`: the previous [NavigationTransitionProps](https://github.com/react-community/react-navigation/blob/master/src/TypeDefinition.js#L273) created from the previous state and props
|
||||
|
||||
#### Returns
|
||||
- none.
|
||||
- `Promise` to delay the start of the transition animation, or none to begin the transition animation immediately.
|
||||
|
||||
### `onTransitionEnd` function
|
||||
Invoked once the transition animation completes.
|
||||
|
||||
If you return a promise from `onTransitionEnd`, any queued transition animations will begin after the promise is resolved.
|
||||
|
||||
#### Flow definition
|
||||
```js
|
||||
onTransitionEnd: () => void
|
||||
|
||||
@@ -17,7 +17,7 @@ Quickly get a grasp on the React Navigation API with demonstrations of the Stack
|
||||
Dive into the basics of React Navigation by creating a new React Native project, installing React Navigation, creating your first navigator, and learning how to interact with it.
|
||||
|
||||
3. [Navigation Playground](https://github.com/react-community/react-navigation/tree/master/examples/NavigationPlayground)
|
||||
Curious of the various capabilities of React Navigation? Browse the official example app, which will demonstrates various patterns with React Navigation.
|
||||
Curious of the various capabilities of React Navigation? Browse the official example app, which will demonstrate various patterns with React Navigation.
|
||||
|
||||
4. [Community Contributions](https://github.com/react-community/react-navigation#community-contributions)
|
||||
With the flexibility of React Navigation we won't be able to cover every possible situation, but another developer may have! Browse our list of community contributions to find topics that may answer your questions.
|
||||
|
||||
@@ -88,7 +88,7 @@ const RootNavigator = StackNavigator({
|
||||
export default RootNavigator;
|
||||
```
|
||||
|
||||
Finally, we should be able to navigate from the home screen to the details screen. When you register a component with a navigator that component will then have a `navigation` prop added to it. This `navigation` prop drives how we use move between different screens.
|
||||
Finally, we should be able to navigate from the home screen to the details screen. When you register a component with a navigator that component will then have a `navigation` prop added to it. This `navigation` prop drives how we move between different screens.
|
||||
|
||||
To move from the home screen to the details screen we'll want to use `navigation.navigate`, like so:
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Note that if you want to dispatch react-navigation actions you should use the ac
|
||||
|
||||
The following actions are supported:
|
||||
* [Navigate](#Navigate) - Navigate to another route
|
||||
* [Reset](#Reset) - Replace current state with a new state
|
||||
* [Reset](#reset) - Replace current state with a new state
|
||||
* [Back](#Back) - Go back to previous state
|
||||
* [Set Params](#SetParams) - Set Params for given route
|
||||
* [Init](#Init) - Used to initialize first state if state is undefined
|
||||
|
||||
@@ -61,7 +61,7 @@ class Root extends React.Component {
|
||||
|
||||
Once you do this, your navigation state is stored within your redux store, at which point you can fire navigation actions using your redux dispatch function.
|
||||
|
||||
Keep in mind that when a navigator is given a `navigation` prop, it relinquishes control of its internal state. That means you are now responsible for persisting its state, handling any deep linking, [Handling the Hardware Back Button in Android](#handling-the-hardware-back-button-in-android), etc.
|
||||
Keep in mind that when a navigator is given a `navigation` prop, it relinquishes control of its internal state. That means you are now responsible for persisting its state, handling any deep linking, [Handling the Hardware Back Button in Android](#Handling-the-Hardware-Back-Button-in-Android), etc.
|
||||
|
||||
Navigation state is automatically passed down from one navigator to another when you nest them. Note that in order for a child navigator to receive the state from a parent navigator, it should be defined as a `screen`.
|
||||
|
||||
|
||||
@@ -4,6 +4,6 @@ A playground for experimenting with react-navigation in a pure-JS React Native a
|
||||
|
||||
## Usage
|
||||
|
||||
Please see the [Contributors Guide](https://github.com/react-community/react-navigation/blob/master/docs/guides/Contributors.md#development) for instructions on running these example apps.
|
||||
Please see the [Contributors Guide](https://reactnavigation.org/docs/guides/contributors#Run-the-Example-App) for instructions on running these example apps.
|
||||
|
||||
You can view this example application directly on your phone by visiting [our expo demo](https://exp.host/@react-navigation/NavigationPlayground).
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"icon": "./assets/icons/react-navigation.png",
|
||||
"hideExponentText": false
|
||||
},
|
||||
"sdkVersion": "23.0.0",
|
||||
"sdkVersion": "24.0.0",
|
||||
"entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
|
||||
"packagerOpts": {
|
||||
"assetExts": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import { ScreenOrientation } from 'expo';
|
||||
import { Constants, ScreenOrientation } from 'expo';
|
||||
|
||||
ScreenOrientation.allow(ScreenOrientation.Orientation.ALL);
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
StyleSheet,
|
||||
TouchableOpacity,
|
||||
Text,
|
||||
StatusBar,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { SafeAreaView, StackNavigator } from 'react-navigation';
|
||||
@@ -19,6 +20,7 @@ import Banner from './Banner';
|
||||
import CustomTabs from './CustomTabs';
|
||||
import CustomTransitioner from './CustomTransitioner';
|
||||
import Drawer from './Drawer';
|
||||
import MultipleDrawer from './MultipleDrawer';
|
||||
import TabsInDrawer from './TabsInDrawer';
|
||||
import ModalStack from './ModalStack';
|
||||
import StacksInTabs from './StacksInTabs';
|
||||
@@ -43,6 +45,11 @@ const ExampleRoutes = {
|
||||
description: 'Android-style drawer navigation',
|
||||
screen: Drawer,
|
||||
},
|
||||
// MultipleDrawer: {
|
||||
// name: 'Multiple Drawer Example',
|
||||
// description: 'Add any drawer you need',
|
||||
// screen: MultipleDrawer,
|
||||
// },
|
||||
TabsInDrawer: {
|
||||
name: 'Drawer + Tabs Example',
|
||||
description: 'A drawer combined with tabs',
|
||||
@@ -98,34 +105,47 @@ const ExampleRoutes = {
|
||||
},
|
||||
};
|
||||
|
||||
const MainScreen = ({ navigation }) => (
|
||||
<ScrollView style={{ flex: 1 }} contentInsetAdjustmentBehavior="automatic">
|
||||
<Banner />
|
||||
{Object.keys(ExampleRoutes).map((routeName: string) => (
|
||||
<TouchableOpacity
|
||||
key={routeName}
|
||||
onPress={() => {
|
||||
const { path, params, screen } = ExampleRoutes[routeName];
|
||||
const { router } = screen;
|
||||
const action = path && router.getActionForPathAndParams(path, params);
|
||||
navigation.navigate(routeName, {}, action);
|
||||
}}
|
||||
>
|
||||
<SafeAreaView
|
||||
style={styles.itemContainer}
|
||||
forceInset={{ vertical: 'never' }}
|
||||
>
|
||||
<View style={styles.item}>
|
||||
<Text style={styles.title}>{ExampleRoutes[routeName].name}</Text>
|
||||
<Text style={styles.description}>
|
||||
{ExampleRoutes[routeName].description}
|
||||
</Text>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
);
|
||||
class MainScreen extends React.Component<*> {
|
||||
render() {
|
||||
const { navigation } = this.props;
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<ScrollView style={{ flex: 1 }}>
|
||||
<Banner />
|
||||
{Object.keys(ExampleRoutes).map((routeName: string) => (
|
||||
<TouchableOpacity
|
||||
key={routeName}
|
||||
onPress={() => {
|
||||
const { path, params, screen } = ExampleRoutes[routeName];
|
||||
const { router } = screen;
|
||||
const action =
|
||||
path && router.getActionForPathAndParams(path, params);
|
||||
navigation.navigate(routeName, {}, action);
|
||||
}}
|
||||
>
|
||||
<SafeAreaView
|
||||
style={styles.itemContainer}
|
||||
forceInset={{ vertical: 'never' }}
|
||||
>
|
||||
<View style={styles.item}>
|
||||
<Text style={styles.title}>
|
||||
{ExampleRoutes[routeName].name}
|
||||
</Text>
|
||||
<Text style={styles.description}>
|
||||
{ExampleRoutes[routeName].description}
|
||||
</Text>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
</TouchableOpacity>
|
||||
))}
|
||||
</ScrollView>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<View style={styles.statusBarUnderlay} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const AppNavigator = StackNavigator(
|
||||
{
|
||||
@@ -165,6 +185,14 @@ const styles = StyleSheet.create({
|
||||
marginBottom: 20,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
statusBarUnderlay: {
|
||||
backgroundColor: '#673ab7',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
height: Constants.statusBarHeight,
|
||||
},
|
||||
title: {
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
|
||||
@@ -22,6 +22,7 @@ export default Banner;
|
||||
const styles = StyleSheet.create({
|
||||
bannerContainer: {
|
||||
backgroundColor: '#673ab7',
|
||||
paddingTop: 20,
|
||||
},
|
||||
banner: {
|
||||
flexDirection: 'row',
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
StatusBar,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
@@ -32,6 +33,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
title="Go back"
|
||||
/>
|
||||
</SafeAreaView>
|
||||
<StatusBar barStyle="default" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Platform,
|
||||
Easing,
|
||||
View,
|
||||
Animated,
|
||||
Image,
|
||||
Button,
|
||||
Easing,
|
||||
Image,
|
||||
Platform,
|
||||
StatusBar,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {
|
||||
Transitioner,
|
||||
@@ -30,6 +31,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
)}
|
||||
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
<StatusBar barStyle="default" />
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, Platform, ScrollView } from 'react-native';
|
||||
import { Button, Platform, ScrollView, StatusBar } from 'react-native';
|
||||
import { DrawerNavigator, SafeAreaView } from 'react-navigation';
|
||||
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
||||
import SampleText from './SampleText';
|
||||
@@ -18,6 +18,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</SafeAreaView>
|
||||
<StatusBar barStyle="default" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
@@ -57,6 +58,9 @@ const DrawerExample = DrawerNavigator(
|
||||
},
|
||||
},
|
||||
{
|
||||
drawerOpenRoute: 'DrawerOpen',
|
||||
drawerCloseRoute: 'DrawerClose',
|
||||
drawerToggleRoute: 'DrawerToggle',
|
||||
initialRouteName: 'Drafts',
|
||||
contentOptions: {
|
||||
activeTintColor: '#e91e63',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, ScrollView, Text } from 'react-native';
|
||||
import { Button, ScrollView, StatusBar, Text } from 'react-native';
|
||||
import { SafeAreaView, StackNavigator } from 'react-navigation';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
@@ -36,6 +36,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
)}
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</SafeAreaView>
|
||||
<StatusBar barStyle="default" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
84
examples/NavigationPlayground/js/MultipleDrawer.js
Normal file
84
examples/NavigationPlayground/js/MultipleDrawer.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, Platform, ScrollView, StyleSheet } from 'react-native';
|
||||
import { DrawerNavigator } from 'react-navigation';
|
||||
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
const MyNavScreen = ({ navigation, banner }) => (
|
||||
<ScrollView style={styles.container}>
|
||||
<SampleText>{banner}</SampleText>
|
||||
<Button
|
||||
onPress={() => navigation.navigate('DrawerOpen')}
|
||||
title="Open drawer"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const InboxScreen = ({ navigation }) => (
|
||||
<MyNavScreen banner={'Inbox Screen'} navigation={navigation} />
|
||||
);
|
||||
InboxScreen.navigationOptions = {
|
||||
drawerLabel: 'Inbox',
|
||||
drawerIcon: ({ tintColor }) => (
|
||||
<MaterialIcons
|
||||
name="move-to-inbox"
|
||||
size={24}
|
||||
style={{ color: tintColor }}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
const DraftsScreen = ({ navigation }) => (
|
||||
<MyNavScreen banner={'Drafts Screen'} navigation={navigation} />
|
||||
);
|
||||
DraftsScreen.navigationOptions = {
|
||||
drawerLabel: 'Drafts',
|
||||
drawerIcon: ({ tintColor }) => (
|
||||
<MaterialIcons name="drafts" size={24} style={{ color: tintColor }} />
|
||||
),
|
||||
};
|
||||
|
||||
const DrawerExample = DrawerNavigator(
|
||||
{
|
||||
Inbox: {
|
||||
path: '/',
|
||||
screen: InboxScreen,
|
||||
},
|
||||
Drafts: {
|
||||
path: '/sent',
|
||||
screen: DraftsScreen,
|
||||
},
|
||||
},
|
||||
{
|
||||
drawerOpenRoute: 'DrawerOpen',
|
||||
drawerCloseRoute: 'DrawerClose',
|
||||
drawerToggleRoute: 'DrawerToggle',
|
||||
initialRouteName: 'Drafts',
|
||||
contentOptions: {
|
||||
activeTintColor: '#e91e63',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const MainDrawerExample = DrawerNavigator({
|
||||
Drafts: {
|
||||
screen: DrawerExample,
|
||||
},
|
||||
}, {
|
||||
drawerOpenRoute: 'DrawerOpen',
|
||||
drawerCloseRoute: 'DrawerClose',
|
||||
drawerToggleRoute: 'DrawerToggle',
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
marginTop: Platform.OS === 'ios' ? 20 : 0,
|
||||
},
|
||||
});
|
||||
|
||||
export default MainDrawerExample;
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, ScrollView } from 'react-native';
|
||||
import { Button, ScrollView, StatusBar } from 'react-native';
|
||||
import { StackNavigator, SafeAreaView } from 'react-navigation';
|
||||
import SampleText from './SampleText';
|
||||
|
||||
@@ -19,6 +19,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
title="Go to a photos screen"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
<StatusBar barStyle="default" />
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, Platform, ScrollView, View } from 'react-native';
|
||||
import { Button, Platform, ScrollView, StatusBar, View } from 'react-native';
|
||||
import { SafeAreaView, TabNavigator } from 'react-navigation';
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
import SampleText from './SampleText';
|
||||
@@ -20,6 +20,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
title="Go to settings tab"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
<StatusBar barStyle="default" />
|
||||
</SafeAreaView>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, ScrollView } from 'react-native';
|
||||
import { Button, ScrollView, StatusBar } from 'react-native';
|
||||
import { SafeAreaView, StackNavigator, TabNavigator } from 'react-navigation';
|
||||
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
@@ -27,6 +27,8 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</SafeAreaView>
|
||||
|
||||
<StatusBar barStyle="default" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, ScrollView } from 'react-native';
|
||||
import { Button, ScrollView, StatusBar } from 'react-native';
|
||||
import { SafeAreaView, StackNavigator, TabNavigator } from 'react-navigation';
|
||||
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
@@ -27,6 +27,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
</SafeAreaView>
|
||||
<StatusBar barStyle="default" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Button, ScrollView, Animated } from 'react-native';
|
||||
import { Animated, Button, ScrollView, StatusBar } from 'react-native';
|
||||
import { StackNavigator, TabNavigator } from 'react-navigation';
|
||||
|
||||
import Ionicons from 'react-native-vector-icons/Ionicons';
|
||||
@@ -25,6 +25,7 @@ const MyNavScreen = ({ navigation, banner }) => (
|
||||
title="Go to settings tab"
|
||||
/>
|
||||
<Button onPress={() => navigation.goBack(null)} title="Go back" />
|
||||
<StatusBar barStyle="default" />
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"private": true,
|
||||
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
|
||||
"scripts": {
|
||||
"postinstall": "rm -rf node_modules/react-navigation/{node_modules,examples}",
|
||||
"postinstall":
|
||||
"rm -rf node_modules/react-navigation/{node_modules,examples}",
|
||||
"start": "react-native-scripts start",
|
||||
"eject": "react-native-scripts eject",
|
||||
"android": "react-native-scripts android",
|
||||
@@ -12,29 +13,22 @@
|
||||
"test": "node node_modules/jest/bin/jest.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"expo": "^23.0.0",
|
||||
"expo": "^24.0.2",
|
||||
"react": "16.0.0",
|
||||
"react-native": "^0.50.3",
|
||||
"react-native": "^0.51.0",
|
||||
"react-navigation": "file:../.."
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-jest": "^21.0.0",
|
||||
"flow-bin": "^0.56.0",
|
||||
"jest": "^21.0.1",
|
||||
"jest-expo": "^23.0.0",
|
||||
"react-addons-test-utils": "16.0.0-alpha.3",
|
||||
"jest-expo": "^24.0.0",
|
||||
"react-native-scripts": "^1.5.0",
|
||||
"react-test-renderer": "16.0.0-alpha.12"
|
||||
"react-test-renderer": "16.0.0"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "jest-expo",
|
||||
"moduleFileExtensions": [
|
||||
"web.js",
|
||||
"js",
|
||||
"json",
|
||||
"jsx",
|
||||
"node"
|
||||
],
|
||||
"moduleFileExtensions": ["web.js", "js", "json", "jsx", "node"],
|
||||
"modulePathIgnorePatterns": [
|
||||
"/node_modules/.*/react-native/",
|
||||
"/node_modules/.*/react/"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,4 @@
|
||||
|
||||
## Usage
|
||||
|
||||
Please see the [Contributors Guide](https://github.com/react-community/react-navigation/blob/master/docs/guides/Contributors.md#development) for instructions on running these example apps.
|
||||
Please see the [Contributors Guide](https://reactnavigation.org/docs/guides/contributors#Run-the-Example-App) for instructions on running these example apps.
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
## Usage
|
||||
|
||||
Please see the [Contributors Guide](https://github.com/react-community/react-navigation/blob/master/docs/guides/Contributors.md#development) for instructions on running these example apps.
|
||||
Please see the [Contributors Guide](https://reactnavigation.org/docs/guides/contributors#Run-the-Example-App) for instructions on running these example apps.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"icon": "./assets/icons/react-navigation.png",
|
||||
"hideExponentText": false
|
||||
},
|
||||
"sdkVersion": "22.0.0",
|
||||
"sdkVersion": "23.0.0",
|
||||
"entryPoint": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
|
||||
"packagerOpts": {
|
||||
"assetExts": [
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
"private": true,
|
||||
"main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
|
||||
"scripts": {
|
||||
"postinstall": "rm -rf node_modules/react-navigation/{node_modules,examples}",
|
||||
"postinstall":
|
||||
"rm -rf node_modules/react-navigation/{node_modules,examples}",
|
||||
"start": "react-native-scripts start",
|
||||
"eject": "react-native-scripts eject",
|
||||
"android": "react-native-scripts android",
|
||||
@@ -35,6 +36,6 @@
|
||||
"jest-expo": "^23.0.0",
|
||||
"react-native-scripts": "^1.3.1",
|
||||
"react-navigation": "file:../..",
|
||||
"react-test-renderer": "16.0.0-alpha.12"
|
||||
"react-test-renderer": "16.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-navigation",
|
||||
"version": "1.0.0-beta.20",
|
||||
"version": "1.0.0-beta.25",
|
||||
"description": "React Navigation",
|
||||
"main": "src/react-navigation.js",
|
||||
"sources": {
|
||||
@@ -55,7 +55,7 @@
|
||||
"path-to-regexp": "^1.7.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-native-drawer-layout-polyfill": "^1.3.2",
|
||||
"react-native-tab-view": "^0.0.70"
|
||||
"react-native-tab-view": "^0.0.74"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.24.1",
|
||||
|
||||
@@ -228,9 +228,9 @@ export type NavigationScreenDetails<T> = {
|
||||
navigation: NavigationScreenProp<NavigationRoute>,
|
||||
};
|
||||
|
||||
export type NavigationScreenOptions = {|
|
||||
export type NavigationScreenOptions = {
|
||||
title?: string,
|
||||
|};
|
||||
};
|
||||
|
||||
export type NavigationScreenConfigProps = {
|
||||
navigation: NavigationScreenProp<NavigationRoute>,
|
||||
@@ -300,6 +300,9 @@ export type HeaderProps = NavigationSceneRendererProps & {
|
||||
getScreenDetails: NavigationScene => NavigationScreenDetails<
|
||||
NavigationStackScreenOptions
|
||||
>,
|
||||
leftInterpolator: (props: NavigationSceneRendererProps) => {},
|
||||
titleInterpolator: (props: NavigationSceneRendererProps) => {},
|
||||
rightInterpolator: (props: NavigationSceneRendererProps) => {},
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -321,6 +324,7 @@ export type NavigationStackScreenOptions = NavigationScreenOptions & {
|
||||
headerStyle?: ViewStyleProp,
|
||||
gesturesEnabled?: boolean,
|
||||
gestureResponseDistance?: { vertical?: number, horizontal?: number },
|
||||
gestureDirection?: 'default' | 'inverted',
|
||||
};
|
||||
|
||||
export type NavigationStackRouterConfig = {
|
||||
@@ -421,6 +425,31 @@ export type NavigationNavigatorProps<O: {}, S: {}> = {
|
||||
navigationOptions?: O,
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigation container
|
||||
*/
|
||||
|
||||
export type NavigationContainer<
|
||||
State: NavigationState,
|
||||
Options: {},
|
||||
Props: {}
|
||||
> = React.ComponentType<NavigationContainerProps<State, Options> & Props> & {
|
||||
router: NavigationRouter<State, Options>,
|
||||
navigationOptions?: ?NavigationScreenConfig<Options>,
|
||||
};
|
||||
|
||||
export type NavigationContainerProps<S: {}, O: {}> = {
|
||||
uriPrefix?: string | RegExp,
|
||||
onNavigationStateChange?: (
|
||||
NavigationState,
|
||||
NavigationState,
|
||||
NavigationAction
|
||||
) => void,
|
||||
navigation?: NavigationScreenProp<S>,
|
||||
screenProps?: *,
|
||||
navigationOptions?: O,
|
||||
};
|
||||
|
||||
/**
|
||||
* Gestures, Animations, and Interpolators
|
||||
*/
|
||||
@@ -496,6 +525,11 @@ export type TransitionConfig = {
|
||||
// How to animate position and opacity of the screen
|
||||
// based on the value generated by the transitionSpec
|
||||
screenInterpolator?: (props: NavigationSceneRendererProps) => {},
|
||||
// How to animate position and opacity of the header componetns
|
||||
// based on the value generated by the transitionSpec
|
||||
headerLeftInterpolator?: (props: NavigationSceneRendererProps) => {},
|
||||
headerTitleInterpolator?: (props: NavigationSceneRendererProps) => {},
|
||||
headerRightInterpolator?: (props: NavigationSceneRendererProps) => {},
|
||||
// The style of the container. Useful when a scene doesn't have
|
||||
// 100% opacity and the underlying container is visible.
|
||||
containerStyle?: ViewStyleProp,
|
||||
|
||||
@@ -13,20 +13,10 @@ import type {
|
||||
NavigationNavigator,
|
||||
PossiblyDeprecatedNavigationAction,
|
||||
NavigationInitAction,
|
||||
NavigationContainerProps,
|
||||
NavigationContainer,
|
||||
} from './TypeDefinition';
|
||||
|
||||
type Props<S, O> = {
|
||||
uriPrefix?: string | RegExp,
|
||||
onNavigationStateChange?: (
|
||||
NavigationState,
|
||||
NavigationState,
|
||||
NavigationAction
|
||||
) => void,
|
||||
navigation?: NavigationScreenProp<S>,
|
||||
screenProps?: *,
|
||||
navigationOptions?: O,
|
||||
};
|
||||
|
||||
type State<NavState> = {
|
||||
nav: ?NavState,
|
||||
};
|
||||
@@ -40,15 +30,19 @@ type State<NavState> = {
|
||||
export default function createNavigationContainer<S: NavigationState, O: {}>(
|
||||
// Let the NavigationNavigator props flowwwww
|
||||
Component: NavigationNavigator<S, O, *>
|
||||
) {
|
||||
class NavigationContainer extends React.Component<Props<S, O>, State<S>> {
|
||||
): NavigationContainer<S, O, *> {
|
||||
class NavigationContainer extends React.Component<
|
||||
NavigationContainerProps<S, O>,
|
||||
State<S>
|
||||
> {
|
||||
subs: ?{
|
||||
remove: () => void,
|
||||
} = null;
|
||||
|
||||
static router = Component.router;
|
||||
static navigationOptions = null;
|
||||
|
||||
constructor(props: Props<S, O>) {
|
||||
constructor(props: NavigationContainerProps<S, O>) {
|
||||
super(props);
|
||||
|
||||
this._validateProps(props);
|
||||
@@ -64,7 +58,7 @@ export default function createNavigationContainer<S: NavigationState, O: {}>(
|
||||
return !this.props.navigation;
|
||||
}
|
||||
|
||||
_validateProps(props: Props<S, O>) {
|
||||
_validateProps(props: NavigationContainerProps<S, O>) {
|
||||
if (this._isStateful()) {
|
||||
return;
|
||||
}
|
||||
@@ -91,6 +85,8 @@ export default function createNavigationContainer<S: NavigationState, O: {}>(
|
||||
let path = url.split(delimiter)[1];
|
||||
if (typeof path === 'undefined') {
|
||||
path = url;
|
||||
} else if (path === '') {
|
||||
path = '/';
|
||||
}
|
||||
return {
|
||||
path,
|
||||
@@ -142,7 +138,7 @@ export default function createNavigationContainer<S: NavigationState, O: {}>(
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: Props<S, O>) {
|
||||
componentWillReceiveProps(nextProps: NavigationContainerProps<S, O>) {
|
||||
this._validateProps(nextProps);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ const DefaultDrawerConfig = {
|
||||
return Math.min(smallerAxisSize - appBarHeight, maxWidth);
|
||||
},
|
||||
contentComponent: defaultContentComponent,
|
||||
drawerOpenRoute: 'DrawerOpen',
|
||||
drawerCloseRoute: 'DrawerClose',
|
||||
drawerToggleRoute: 'DrawerToggle',
|
||||
drawerPosition: 'left',
|
||||
drawerBackgroundColor: 'white',
|
||||
useNativeAnimations: true,
|
||||
@@ -82,6 +85,9 @@ const DrawerNavigator = (
|
||||
drawerPosition,
|
||||
useNativeAnimations,
|
||||
drawerBackgroundColor,
|
||||
drawerOpenRoute,
|
||||
drawerCloseRoute,
|
||||
drawerToggleRoute,
|
||||
...tabsConfig
|
||||
} = mergedConfig;
|
||||
|
||||
@@ -89,7 +95,7 @@ const DrawerNavigator = (
|
||||
|
||||
const drawerRouter = TabRouter(
|
||||
{
|
||||
DrawerClose: {
|
||||
[drawerCloseRoute]: {
|
||||
screen: createNavigator(
|
||||
contentRouter,
|
||||
routeConfigs,
|
||||
@@ -99,15 +105,15 @@ const DrawerNavigator = (
|
||||
<DrawerScreen {...props} />
|
||||
)),
|
||||
},
|
||||
DrawerOpen: {
|
||||
[drawerOpenRoute]: {
|
||||
screen: () => null,
|
||||
},
|
||||
DrawerToggle: {
|
||||
[drawerToggleRoute]: {
|
||||
screen: () => null,
|
||||
},
|
||||
},
|
||||
{
|
||||
initialRouteName: 'DrawerClose',
|
||||
initialRouteName: drawerCloseRoute,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -126,6 +132,9 @@ const DrawerNavigator = (
|
||||
contentComponent={contentComponent}
|
||||
contentOptions={contentOptions}
|
||||
drawerPosition={drawerPosition}
|
||||
drawerOpenRoute={drawerOpenRoute}
|
||||
drawerCloseRoute={drawerCloseRoute}
|
||||
drawerToggleRoute={drawerToggleRoute}
|
||||
/>
|
||||
));
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ const TabNavigator = (
|
||||
swipeEnabled,
|
||||
animationEnabled,
|
||||
configureTransition,
|
||||
lazy,
|
||||
initialLayout,
|
||||
...tabsConfig
|
||||
} = mergedConfig;
|
||||
@@ -70,7 +69,6 @@ const TabNavigator = (
|
||||
swipeEnabled={swipeEnabled}
|
||||
animationEnabled={animationEnabled}
|
||||
configureTransition={configureTransition}
|
||||
lazy={lazy}
|
||||
initialLayout={initialLayout}
|
||||
/>
|
||||
));
|
||||
@@ -84,7 +82,6 @@ const Presets = {
|
||||
tabBarPosition: 'bottom',
|
||||
swipeEnabled: false,
|
||||
animationEnabled: false,
|
||||
lazy: false,
|
||||
initialLayout: undefined,
|
||||
},
|
||||
AndroidTopTabs: {
|
||||
@@ -92,7 +89,6 @@ const Presets = {
|
||||
tabBarPosition: 'top',
|
||||
swipeEnabled: true,
|
||||
animationEnabled: true,
|
||||
lazy: false,
|
||||
initialLayout: undefined,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -137,6 +137,7 @@ exports[`DrawerNavigator renders successfully 1`] = `
|
||||
}
|
||||
>
|
||||
<View
|
||||
collapsable={undefined}
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -182,6 +183,7 @@ exports[`DrawerNavigator renders successfully 1`] = `
|
||||
tvParallaxProperties={undefined}
|
||||
>
|
||||
<View
|
||||
collapsable={undefined}
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
|
||||
@@ -89,6 +89,7 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
leftInterpolator={[Function]}
|
||||
mode="float"
|
||||
navigation={
|
||||
Object {
|
||||
@@ -107,6 +108,7 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
|
||||
},
|
||||
}
|
||||
}
|
||||
rightInterpolator={[Function]}
|
||||
router={
|
||||
Object {
|
||||
"getActionForPathAndParams": [Function],
|
||||
@@ -118,9 +120,11 @@ exports[`StackNavigator applies correct values when headerRight is present 1`] =
|
||||
"getStateForAction": [Function],
|
||||
}
|
||||
}
|
||||
titleInterpolator={[Function]}
|
||||
transitionConfig={undefined}
|
||||
>
|
||||
<View
|
||||
collapsable={undefined}
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -316,6 +320,7 @@ exports[`StackNavigator renders successfully 1`] = `
|
||||
"width": 0,
|
||||
}
|
||||
}
|
||||
leftInterpolator={[Function]}
|
||||
mode="float"
|
||||
navigation={
|
||||
Object {
|
||||
@@ -334,6 +339,7 @@ exports[`StackNavigator renders successfully 1`] = `
|
||||
},
|
||||
}
|
||||
}
|
||||
rightInterpolator={[Function]}
|
||||
router={
|
||||
Object {
|
||||
"getActionForPathAndParams": [Function],
|
||||
@@ -345,9 +351,11 @@ exports[`StackNavigator renders successfully 1`] = `
|
||||
"getStateForAction": [Function],
|
||||
}
|
||||
}
|
||||
titleInterpolator={[Function]}
|
||||
transitionConfig={undefined}
|
||||
>
|
||||
<View
|
||||
collapsable={undefined}
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
|
||||
@@ -69,6 +69,7 @@ exports[`TabNavigator renders successfully 1`] = `
|
||||
style={undefined}
|
||||
>
|
||||
<View
|
||||
collapsable={undefined}
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
|
||||
@@ -61,11 +61,7 @@ export default (
|
||||
const routes = order.map((routeName: string) => {
|
||||
const tabRouter = tabRouters[routeName];
|
||||
if (tabRouter) {
|
||||
const childAction =
|
||||
action.action ||
|
||||
NavigationActions.init({
|
||||
...(action.params ? { params: action.params } : {}),
|
||||
});
|
||||
const childAction = NavigationActions.init();
|
||||
return {
|
||||
...tabRouter.getStateForAction(childAction),
|
||||
key: routeName,
|
||||
@@ -106,7 +102,7 @@ export default (
|
||||
const activeTabRouter = tabRouters[order[state.index]];
|
||||
if (activeTabRouter) {
|
||||
const activeTabState = activeTabRouter.getStateForAction(
|
||||
action.action || action,
|
||||
action,
|
||||
activeTabLastState
|
||||
);
|
||||
if (!activeTabState && inputState) {
|
||||
|
||||
@@ -3,9 +3,12 @@
|
||||
|
||||
import React from 'react';
|
||||
import TabRouter from '../TabRouter';
|
||||
import StackRouter from '../StackRouter';
|
||||
|
||||
import NavigationActions from '../../NavigationActions';
|
||||
|
||||
import type { NavigationRoute, NavigationState } from '../../TypeDefinition';
|
||||
|
||||
const INIT_ACTION = { type: NavigationActions.INIT };
|
||||
|
||||
const BareLeafRouteConfig = {
|
||||
@@ -212,7 +215,6 @@ describe('TabRouter', () => {
|
||||
const navAction = {
|
||||
type: NavigationActions.NAVIGATE,
|
||||
routeName: 'Baz',
|
||||
params: { foo: '42', bar: '43' },
|
||||
};
|
||||
let state = router.getStateForAction(navAction);
|
||||
expect(state).toEqual({
|
||||
@@ -224,8 +226,8 @@ describe('TabRouter', () => {
|
||||
key: 'Baz',
|
||||
routeName: 'Baz',
|
||||
routes: [
|
||||
{ key: 'Boo', routeName: 'Boo', params: { foo: '42', bar: '43' } },
|
||||
{ key: 'Bar', routeName: 'Bar', params: { foo: '42', bar: '43' } },
|
||||
{ key: 'Boo', routeName: 'Boo' },
|
||||
{ key: 'Bar', routeName: 'Bar' },
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -245,8 +247,8 @@ describe('TabRouter', () => {
|
||||
key: 'Baz',
|
||||
routeName: 'Baz',
|
||||
routes: [
|
||||
{ key: 'Boo', routeName: 'Boo', params: { foo: '42', bar: '43' } },
|
||||
{ key: 'Bar', routeName: 'Bar', params: { foo: '42', bar: '43' } },
|
||||
{ key: 'Boo', routeName: 'Boo' },
|
||||
{ key: 'Bar', routeName: 'Bar' },
|
||||
],
|
||||
});
|
||||
});
|
||||
@@ -604,4 +606,71 @@ describe('TabRouter', () => {
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test('Inner actions are only unpacked if the current tab matches', () => {
|
||||
const PlainScreen = () => <div />;
|
||||
const ScreenA = () => <div />;
|
||||
const ScreenB = () => <div />;
|
||||
ScreenB.router = StackRouter({
|
||||
Baz: { screen: PlainScreen },
|
||||
Zoo: { screen: PlainScreen },
|
||||
});
|
||||
ScreenA.router = StackRouter({
|
||||
Bar: { screen: PlainScreen },
|
||||
Boo: { screen: ScreenB },
|
||||
});
|
||||
const router = TabRouter({
|
||||
Foo: { screen: ScreenA },
|
||||
});
|
||||
const screenApreState = {
|
||||
index: 0,
|
||||
key: 'Init',
|
||||
routeName: 'Foo',
|
||||
routes: [{ key: 'Init', routeName: 'Bar' }],
|
||||
};
|
||||
const preState = {
|
||||
index: 0,
|
||||
routes: [screenApreState],
|
||||
};
|
||||
|
||||
type ComparableRoute = {
|
||||
routeName?: string,
|
||||
routes?: Array<ComparableRoute>,
|
||||
};
|
||||
|
||||
type RouteOrState =
|
||||
| NavigationRoute
|
||||
| NavigationState
|
||||
| (NavigationRoute & NavigationState);
|
||||
|
||||
const comparable = (state: RouteOrState): ComparableRoute => {
|
||||
let result = {};
|
||||
if (typeof state.routeName === 'string') {
|
||||
result = { ...result, routeName: state.routeName };
|
||||
}
|
||||
if (state.routes instanceof Array) {
|
||||
result = {
|
||||
...result,
|
||||
routes: state.routes.map(comparable),
|
||||
};
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const action = NavigationActions.navigate({
|
||||
routeName: 'Boo',
|
||||
action: NavigationActions.navigate({ routeName: 'Zoo' }),
|
||||
});
|
||||
|
||||
const expectedState = ScreenA.router.getStateForAction(
|
||||
action,
|
||||
screenApreState
|
||||
);
|
||||
const state = router.getStateForAction(action, preState);
|
||||
const innerState = state ? state.routes[0] : state;
|
||||
|
||||
expect(expectedState && comparable(expectedState)).toEqual(
|
||||
innerState && comparable(innerState)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
12
src/utils/ReactNativeFeatures.js
Normal file
12
src/utils/ReactNativeFeatures.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/* @flow */
|
||||
|
||||
import { NativeModules } from 'react-native';
|
||||
const { PlatformConstants } = NativeModules;
|
||||
|
||||
export const supportsImprovedSpringAnimation = () => {
|
||||
if (PlatformConstants && PlatformConstants.reactNativeVersion) {
|
||||
const { major, minor } = PlatformConstants.reactNativeVersion;
|
||||
return minor >= 50 || (major === 0 && minor === 0); // `master` has major + minor set to 0
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -163,6 +163,11 @@ class CardStack extends React.Component<Props> {
|
||||
}
|
||||
|
||||
const renderHeader = header || ((props: *) => <Header {...props} />);
|
||||
const {
|
||||
headerLeftInterpolator,
|
||||
headerTitleInterpolator,
|
||||
headerRightInterpolator,
|
||||
} = this._getTransitionConfig();
|
||||
|
||||
// We need to explicitly exclude `mode` since Flow doesn't see
|
||||
// mode: headerMode override below and reports prop mismatch
|
||||
@@ -173,6 +178,9 @@ class CardStack extends React.Component<Props> {
|
||||
scene,
|
||||
mode: headerMode,
|
||||
getScreenDetails: this._getScreenDetails,
|
||||
leftInterpolator: headerLeftInterpolator,
|
||||
titleInterpolator: headerTitleInterpolator,
|
||||
rightInterpolator: headerRightInterpolator,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -232,6 +240,8 @@ class CardStack extends React.Component<Props> {
|
||||
const { navigation, position, layout, scene, scenes, mode } = this.props;
|
||||
const { index } = navigation.state;
|
||||
const isVertical = mode === 'modal';
|
||||
const { options } = this._getScreenDetails(scene);
|
||||
const gestureDirectionInverted = options.gestureDirection === 'inverted';
|
||||
|
||||
const responder = PanResponder.create({
|
||||
onPanResponderTerminate: () => {
|
||||
@@ -262,7 +272,9 @@ class CardStack extends React.Component<Props> {
|
||||
const axisHasBeenMeasured = !!axisLength;
|
||||
|
||||
// Measure the distance from the touch to the edge of the screen
|
||||
const screenEdgeDistance = currentDragPosition - currentDragDistance;
|
||||
const screenEdgeDistance = gestureDirectionInverted
|
||||
? axisLength - (currentDragPosition - currentDragDistance)
|
||||
: currentDragPosition - currentDragDistance;
|
||||
// Compare to the gesture distance relavant to card or modal
|
||||
const {
|
||||
gestureResponseDistance: userGestureResponseDistance = {},
|
||||
@@ -294,7 +306,7 @@ class CardStack extends React.Component<Props> {
|
||||
? layout.height.__getValue()
|
||||
: layout.width.__getValue();
|
||||
const currentValue =
|
||||
I18nManager.isRTL && axis === 'dx'
|
||||
(I18nManager.isRTL && axis === 'dx') !== gestureDirectionInverted
|
||||
? startValue + gesture[axis] / axisDistance
|
||||
: startValue - gesture[axis] / axisDistance;
|
||||
const value = clamp(index - 1, currentValue, index);
|
||||
@@ -317,12 +329,19 @@ class CardStack extends React.Component<Props> {
|
||||
const axisDistance = isVertical
|
||||
? layout.height.__getValue()
|
||||
: layout.width.__getValue();
|
||||
const movedDistance = gesture[isVertical ? 'dy' : 'dx'];
|
||||
const gestureVelocity = gesture[isVertical ? 'vy' : 'vx'];
|
||||
const movementDirection = gestureDirectionInverted ? -1 : 1;
|
||||
const movedDistance =
|
||||
movementDirection * gesture[isVertical ? 'dy' : 'dx'];
|
||||
const gestureVelocity =
|
||||
movementDirection * gesture[isVertical ? 'vy' : 'vx'];
|
||||
const defaultVelocity = axisDistance / ANIMATION_DURATION;
|
||||
const velocity = Math.max(Math.abs(gestureVelocity), defaultVelocity);
|
||||
const resetDuration = movedDistance / velocity;
|
||||
const goBackDuration = (axisDistance - movedDistance) / velocity;
|
||||
const resetDuration = gestureDirectionInverted
|
||||
? (axisDistance - movedDistance) / velocity
|
||||
: movedDistance / velocity;
|
||||
const goBackDuration = gestureDirectionInverted
|
||||
? movedDistance / velocity
|
||||
: (axisDistance - movedDistance) / velocity;
|
||||
|
||||
// To asyncronously get the current animated value, we need to run stopAnimation:
|
||||
position.stopAnimation((value: number) => {
|
||||
@@ -348,7 +367,6 @@ class CardStack extends React.Component<Props> {
|
||||
},
|
||||
});
|
||||
|
||||
const { options } = this._getScreenDetails(scene);
|
||||
const gesturesEnabled =
|
||||
typeof options.gesturesEnabled === 'boolean'
|
||||
? options.gesturesEnabled
|
||||
|
||||
@@ -9,12 +9,25 @@ import type {
|
||||
} from '../../TypeDefinition';
|
||||
|
||||
import CardStackStyleInterpolator from './CardStackStyleInterpolator';
|
||||
import * as ReactNativeFeatures from '../../utils/ReactNativeFeatures';
|
||||
|
||||
const IOSTransitionSpec = ({
|
||||
duration: 500,
|
||||
easing: Easing.bezier(0.2833, 0.99, 0.31833, 0.99),
|
||||
timing: Animated.timing,
|
||||
}: NavigationTransitionSpec);
|
||||
let IOSTransitionSpec;
|
||||
if (ReactNativeFeatures.supportsImprovedSpringAnimation()) {
|
||||
// These are the exact values from UINavigationController's animation configuration
|
||||
IOSTransitionSpec = ({
|
||||
timing: Animated.spring,
|
||||
stiffness: 1000,
|
||||
damping: 500,
|
||||
mass: 3,
|
||||
}: NavigationTransitionSpec);
|
||||
} else {
|
||||
// This is an approximation of the IOS spring animation using a derived bezier curve
|
||||
IOSTransitionSpec = ({
|
||||
duration: 500,
|
||||
easing: Easing.bezier(0.2833, 0.99, 0.31833, 0.99),
|
||||
timing: Animated.timing,
|
||||
}: NavigationTransitionSpec);
|
||||
}
|
||||
|
||||
// Standard iOS navigation transition
|
||||
const SlideFromRightIOS = ({
|
||||
|
||||
@@ -33,6 +33,9 @@ export type DrawerViewConfig = {
|
||||
drawerLockMode?: 'unlocked' | 'locked-closed' | 'locked-open',
|
||||
drawerWidth?: number | (() => number),
|
||||
drawerPosition?: 'left' | 'right',
|
||||
drawerOpenRoute?: string,
|
||||
drawerCloseRoute?: string,
|
||||
drawerToggleRoute?: string,
|
||||
contentComponent?: React.ComponentType<*>,
|
||||
contentOptions?: {},
|
||||
style?: ViewStyleProp,
|
||||
@@ -41,11 +44,21 @@ export type DrawerViewConfig = {
|
||||
screenProps?: {},
|
||||
};
|
||||
|
||||
export type DrawerViewPropsExceptRouter = DrawerViewConfig & {
|
||||
navigation: NavigationScreenProp<NavigationState>,
|
||||
};
|
||||
export type DrawerViewProps = {
|
||||
drawerLockMode?: 'unlocked' | 'locked-closed' | 'locked-open',
|
||||
drawerWidth: number | (() => number),
|
||||
drawerPosition: 'left' | 'right',
|
||||
drawerOpenRoute: string,
|
||||
drawerCloseRoute: string,
|
||||
drawerToggleRoute: string,
|
||||
contentComponent: React.ComponentType<*>,
|
||||
contentOptions?: {},
|
||||
style?: ViewStyleProp,
|
||||
useNativeAnimations: boolean,
|
||||
drawerBackgroundColor: string,
|
||||
screenProps?: {},
|
||||
|
||||
export type DrawerViewProps = DrawerViewPropsExceptRouter & {
|
||||
navigation: NavigationScreenProp<NavigationState>,
|
||||
router: NavigationRouter<NavigationState, NavigationDrawerScreenOptions>,
|
||||
};
|
||||
|
||||
@@ -81,14 +94,19 @@ export default class DrawerView extends React.PureComponent<
|
||||
if (
|
||||
this.props.navigation.state.index !== nextProps.navigation.state.index
|
||||
) {
|
||||
const {
|
||||
drawerOpenRoute,
|
||||
drawerCloseRoute,
|
||||
drawerToggleRoute,
|
||||
} = this.props;
|
||||
const { routes, index } = nextProps.navigation.state;
|
||||
if (routes[index].routeName === 'DrawerOpen') {
|
||||
if (routes[index].routeName === drawerOpenRoute) {
|
||||
this._drawer.openDrawer();
|
||||
} else if (routes[index].routeName === 'DrawerToggle') {
|
||||
if (this._drawer.state.drawerShown) {
|
||||
this.props.navigation.navigate('DrawerClose');
|
||||
} else if (routes[index].routeName === drawerToggleRoute) {
|
||||
if (this.props.navigation.state.index === 0) {
|
||||
this.props.navigation.navigate(drawerOpenRoute);
|
||||
} else {
|
||||
this.props.navigation.navigate('DrawerOpen');
|
||||
this.props.navigation.navigate(drawerCloseRoute);
|
||||
}
|
||||
} else {
|
||||
this._drawer.closeDrawer();
|
||||
@@ -100,27 +118,28 @@ export default class DrawerView extends React.PureComponent<
|
||||
_screenNavigationProp: NavigationScreenProp<NavigationStateRoute>;
|
||||
|
||||
_handleDrawerOpen = () => {
|
||||
const { navigation } = this.props;
|
||||
const { navigation, drawerOpenRoute } = this.props;
|
||||
const { routes, index } = navigation.state;
|
||||
if (routes[index].routeName !== 'DrawerOpen') {
|
||||
this.props.navigation.navigate('DrawerOpen');
|
||||
if (routes[index].routeName !== drawerOpenRoute) {
|
||||
this.props.navigation.navigate(drawerOpenRoute);
|
||||
}
|
||||
};
|
||||
|
||||
_handleDrawerClose = () => {
|
||||
const { navigation } = this.props;
|
||||
const { navigation, drawerCloseRoute } = this.props;
|
||||
const { routes, index } = navigation.state;
|
||||
if (routes[index].routeName !== 'DrawerClose') {
|
||||
this.props.navigation.navigate('DrawerClose');
|
||||
if (routes[index].routeName !== drawerCloseRoute) {
|
||||
this.props.navigation.navigate(drawerCloseRoute);
|
||||
}
|
||||
};
|
||||
|
||||
_updateScreenNavigation = (
|
||||
navigation: NavigationScreenProp<NavigationState>
|
||||
) => {
|
||||
const { drawerCloseRoute } = this.props;
|
||||
// $FlowFixMe there's no way type the specific shape of the nav state
|
||||
const navigationState: NavigationStateRoute = navigation.state.routes.find(
|
||||
(route: *) => route.routeName === 'DrawerClose'
|
||||
(route: *) => route.routeName === drawerCloseRoute
|
||||
);
|
||||
if (
|
||||
this._screenNavigationProp &&
|
||||
@@ -146,8 +165,9 @@ export default class DrawerView extends React.PureComponent<
|
||||
};
|
||||
|
||||
_getNavigationState = (navigation: NavigationScreenProp<NavigationState>) => {
|
||||
const { drawerCloseRoute } = this.props;
|
||||
const navigationState = navigation.state.routes.find(
|
||||
(route: *) => route.routeName === 'DrawerClose'
|
||||
(route: *) => route.routeName === drawerCloseRoute
|
||||
);
|
||||
return navigationState;
|
||||
};
|
||||
@@ -168,7 +188,7 @@ export default class DrawerView extends React.PureComponent<
|
||||
|
||||
render() {
|
||||
const DrawerScreen = this.props.router.getComponentForRouteName(
|
||||
'DrawerClose'
|
||||
this.props.drawerCloseRoute
|
||||
);
|
||||
|
||||
const screenNavigation = addNavigationHelpers({
|
||||
|
||||
@@ -49,6 +49,12 @@ const TITLE_OFFSET = Platform.OS === 'ios' ? 70 : 56;
|
||||
|
||||
type Props = HeaderProps & { isLandscape: boolean };
|
||||
class Header extends React.PureComponent<Props, State> {
|
||||
static defaultProps = {
|
||||
leftInterpolator: HeaderStyleInterpolator.forLeft,
|
||||
titleInterpolator: HeaderStyleInterpolator.forCenter,
|
||||
rightInterpolator: HeaderStyleInterpolator.forRight,
|
||||
};
|
||||
|
||||
static get HEIGHT() {
|
||||
console.warn(
|
||||
'Header.HEIGHT is deprecated and will be removed before react-navigation comes out of beta.'
|
||||
@@ -142,7 +148,10 @@ class Header extends React.PureComponent<Props, State> {
|
||||
_renderLeftComponent = (props: SceneProps): ?React.Node => {
|
||||
// $FlowFixMe
|
||||
const { options } = this.props.getScreenDetails(props.scene);
|
||||
if (React.isValidElement(options.headerLeft)) {
|
||||
if (
|
||||
React.isValidElement(options.headerLeft) ||
|
||||
options.headerLeft === null
|
||||
) {
|
||||
return options.headerLeft;
|
||||
}
|
||||
if (props.scene.index === 0) {
|
||||
@@ -180,7 +189,7 @@ class Header extends React.PureComponent<Props, State> {
|
||||
props,
|
||||
'left',
|
||||
this._renderLeftComponent,
|
||||
HeaderStyleInterpolator.forLeft
|
||||
this.props.leftInterpolator
|
||||
);
|
||||
}
|
||||
|
||||
@@ -207,7 +216,7 @@ class Header extends React.PureComponent<Props, State> {
|
||||
{ ...props, style },
|
||||
'title',
|
||||
this._renderTitleComponent,
|
||||
HeaderStyleInterpolator.forCenter
|
||||
this.props.titleInterpolator
|
||||
);
|
||||
}
|
||||
|
||||
@@ -216,7 +225,7 @@ class Header extends React.PureComponent<Props, State> {
|
||||
props,
|
||||
'right',
|
||||
this._renderRightComponent,
|
||||
HeaderStyleInterpolator.forRight
|
||||
this.props.rightInterpolator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
Platform,
|
||||
SafeAreaView,
|
||||
StyleSheet,
|
||||
View,
|
||||
Animated,
|
||||
} from 'react-native';
|
||||
import withOrientation from './withOrientation';
|
||||
|
||||
@@ -101,19 +101,19 @@ class SafeView extends Component {
|
||||
const { forceInset = false, isLandscape, children, style } = this.props;
|
||||
|
||||
if (Platform.OS !== 'ios') {
|
||||
return <View style={style}>{this.props.children}</View>;
|
||||
return <Animated.View style={style}>{this.props.children}</Animated.View>;
|
||||
}
|
||||
|
||||
const safeAreaStyle = this._getSafeAreaStyle();
|
||||
|
||||
return (
|
||||
<View
|
||||
<Animated.View
|
||||
ref={c => (this.view = c)}
|
||||
onLayout={this._onLayout}
|
||||
style={safeAreaStyle}
|
||||
>
|
||||
{this.props.children}
|
||||
</View>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class SafeView extends Component {
|
||||
const WIDTH = isLandscape ? X_HEIGHT : X_WIDTH;
|
||||
const HEIGHT = isLandscape ? X_WIDTH : X_HEIGHT;
|
||||
|
||||
this.view.measureInWindow((winX, winY, winWidth, winHeight) => {
|
||||
this.view._component.measureInWindow((winX, winY, winWidth, winHeight) => {
|
||||
let realY = winY;
|
||||
let realX = winX;
|
||||
|
||||
|
||||
@@ -122,8 +122,9 @@ export default class TabBarTop extends React.PureComponent<Props> {
|
||||
);
|
||||
};
|
||||
|
||||
_handleOnPress = (previousScene: NavigationRoute, scene: TabScene) => {
|
||||
const { getOnPress, jumpToIndex }: Props = this.props;
|
||||
_handleOnPress = (scene: TabScene) => {
|
||||
const { getOnPress, jumpToIndex, navigation }: Props = this.props;
|
||||
const previousScene = navigation.state.routes[navigation.state.index];
|
||||
const onPress = getOnPress(previousScene, scene);
|
||||
|
||||
if (onPress) {
|
||||
@@ -136,8 +137,6 @@ export default class TabBarTop extends React.PureComponent<Props> {
|
||||
render() {
|
||||
// TODO: Define full proptypes
|
||||
const props: any = this.props;
|
||||
const { state } = props.navigation;
|
||||
const previousScene = state.routes[state.index];
|
||||
|
||||
return (
|
||||
<TabBar
|
||||
|
||||
@@ -26,7 +26,6 @@ export type TabViewConfig = {
|
||||
currentTransitionProps: Object,
|
||||
nextTransitionProps: Object
|
||||
) => Object,
|
||||
lazy?: boolean,
|
||||
initialLayout?: Layout,
|
||||
};
|
||||
|
||||
@@ -47,7 +46,6 @@ type Props = {
|
||||
currentTransitionProps: Object,
|
||||
nextTransitionProps: Object
|
||||
) => Object,
|
||||
lazy?: boolean,
|
||||
initialLayout: Layout,
|
||||
|
||||
screenProps?: {},
|
||||
@@ -171,8 +169,6 @@ class TabView extends React.PureComponent<Props> {
|
||||
tabBarPosition,
|
||||
animationEnabled,
|
||||
configureTransition,
|
||||
swipeEnabled,
|
||||
lazy,
|
||||
initialLayout,
|
||||
screenProps,
|
||||
} = this.props;
|
||||
@@ -190,6 +186,11 @@ class TabView extends React.PureComponent<Props> {
|
||||
const tabBarVisible =
|
||||
options.tabBarVisible == null ? true : options.tabBarVisible;
|
||||
|
||||
const swipeEnabled =
|
||||
options.swipeEnabled == null
|
||||
? this.props.swipeEnabled
|
||||
: options.swipeEnabled;
|
||||
|
||||
if (tabBarComponent !== undefined && tabBarVisible) {
|
||||
if (tabBarPosition === 'bottom') {
|
||||
renderFooter = this._renderTabBar;
|
||||
@@ -206,7 +207,6 @@ class TabView extends React.PureComponent<Props> {
|
||||
}
|
||||
|
||||
const props = {
|
||||
lazy,
|
||||
initialLayout,
|
||||
animationEnabled,
|
||||
configureTransition,
|
||||
@@ -221,7 +221,6 @@ class TabView extends React.PureComponent<Props> {
|
||||
style: styles.container,
|
||||
};
|
||||
|
||||
// $FlowFixMe: mismatch with react-native-tab-view type
|
||||
return <TabViewAnimated {...props} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,12 +172,17 @@ class Transitioner extends React.Component<Props, State> {
|
||||
|
||||
// update scenes and play the transition
|
||||
this._isTransitionRunning = true;
|
||||
this.setState(nextState, () => {
|
||||
nextProps.onTransitionStart &&
|
||||
nextProps.onTransitionStart(
|
||||
this.setState(nextState, async () => {
|
||||
if (nextProps.onTransitionStart) {
|
||||
const result = nextProps.onTransitionStart(
|
||||
this._transitionProps,
|
||||
this._prevTransitionProps
|
||||
);
|
||||
|
||||
if (result instanceof Promise) {
|
||||
await result;
|
||||
}
|
||||
}
|
||||
Animated.parallel(animations).start(this._onTransitionEnd);
|
||||
});
|
||||
}
|
||||
@@ -231,9 +236,18 @@ class Transitioner extends React.Component<Props, State> {
|
||||
|
||||
this._transitionProps = buildTransitionProps(this.props, nextState);
|
||||
|
||||
this.setState(nextState, () => {
|
||||
this.props.onTransitionEnd &&
|
||||
this.props.onTransitionEnd(this._transitionProps, prevTransitionProps);
|
||||
this.setState(nextState, async () => {
|
||||
if (this.props.onTransitionEnd) {
|
||||
const result = this.props.onTransitionEnd(
|
||||
this._transitionProps,
|
||||
prevTransitionProps
|
||||
);
|
||||
|
||||
if (result instanceof Promise) {
|
||||
await result;
|
||||
}
|
||||
}
|
||||
|
||||
if (this._queuedTransition) {
|
||||
this._startTransition(
|
||||
this._queuedTransition.nextProps,
|
||||
|
||||
@@ -25,6 +25,7 @@ exports[`TabBarBottom renders successfully 1`] = `
|
||||
style={undefined}
|
||||
>
|
||||
<View
|
||||
collapsable={undefined}
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
@@ -133,7 +134,7 @@ exports[`TabBarBottom renders successfully 1`] = `
|
||||
bounces={false}
|
||||
contentContainerStyle={
|
||||
Object {
|
||||
"flexGrow": 1,
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
contentOffset={
|
||||
@@ -163,9 +164,10 @@ exports[`TabBarBottom renders successfully 1`] = `
|
||||
onTouchEnd={[Function]}
|
||||
onTouchMove={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
overScrollMode="never"
|
||||
pagingEnabled={true}
|
||||
scrollEnabled={undefined}
|
||||
scrollEventThrottle={16}
|
||||
scrollEventThrottle={1}
|
||||
scrollsToTop={false}
|
||||
sendMomentumEvents={true}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
@@ -178,7 +180,7 @@ exports[`TabBarBottom renders successfully 1`] = `
|
||||
"overflow": "scroll",
|
||||
},
|
||||
Object {
|
||||
"flexGrow": 1,
|
||||
"flex": 1,
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -192,7 +194,7 @@ exports[`TabBarBottom renders successfully 1`] = `
|
||||
"flexDirection": "row",
|
||||
},
|
||||
Object {
|
||||
"flexGrow": 1,
|
||||
"flex": 1,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4488,11 +4488,11 @@ react-native-drawer-layout@1.3.2:
|
||||
dependencies:
|
||||
react-native-dismiss-keyboard "1.0.0"
|
||||
|
||||
react-native-tab-view@^0.0.70:
|
||||
version "0.0.70"
|
||||
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.70.tgz#1dd2ded32acd0cb6bfef38d26e53675db733b37b"
|
||||
react-native-tab-view@^0.0.74:
|
||||
version "0.0.74"
|
||||
resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-0.0.74.tgz#62c0c882d9232b461ce181d440d683b4f99d1bd8"
|
||||
dependencies:
|
||||
prop-types "^15.5.10"
|
||||
prop-types "^15.6.0"
|
||||
|
||||
react-native-vector-icons@^4.2.0:
|
||||
version "4.4.2"
|
||||
|
||||
Reference in New Issue
Block a user