mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-13 22:42:25 +08:00
Compare commits
9 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0e4e1f6fb | ||
|
|
00fc616de0 | ||
|
|
703edb3569 | ||
|
|
38a38b021a | ||
|
|
42bc37d2ff | ||
|
|
75ad2aaae5 | ||
|
|
eef17a801e | ||
|
|
7b8277dae5 | ||
|
|
6cddb5238c |
@@ -35,7 +35,7 @@ Navigators bundle a router and a view which takes the navigation state and decid
|
||||
A simple navigator could look like this:
|
||||
|
||||
```js
|
||||
import { createNavigatorFactory } from '@react-navigation/core';
|
||||
import { createNavigatorFactory } from '@react-navigation/native';
|
||||
|
||||
function StackNavigator({ initialRouteName, children, ...rest }) {
|
||||
// The `navigation` object contains the navigation state and some helpers (e.g. push, pop)
|
||||
@@ -256,7 +256,7 @@ Sometimes we want to run side-effects when a screen is focused. A side effect ma
|
||||
To make this easier, the library exports a `useFocusEffect` hook:
|
||||
|
||||
```js
|
||||
import { useFocusEffect } from '@react-navigation/core';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
|
||||
function Profile({ userId }) {
|
||||
const [user, setUser] = React.useState(null);
|
||||
@@ -285,7 +285,7 @@ The `useFocusEffect` is analogous to React's `useEffect` hook. The only differen
|
||||
We might want to render different content based on the current focus state of the screen. The library exports a `useIsFocused` hook to make this easier:
|
||||
|
||||
```js
|
||||
import { useIsFocused } from '@react-navigation/core';
|
||||
import { useIsFocused } from '@react-navigation/native';
|
||||
|
||||
// ...
|
||||
|
||||
|
||||
@@ -54,6 +54,23 @@ module.exports = {
|
||||
}, {}),
|
||||
},
|
||||
|
||||
server: {
|
||||
enhanceMiddleware: middleware => {
|
||||
return (req, res, next) => {
|
||||
const assets = '/packages/stack/src/views/assets';
|
||||
|
||||
if (req.url.startsWith(assets)) {
|
||||
req.url = req.url.replace(
|
||||
assets,
|
||||
'/assets/../packages/stack/src/views/assets'
|
||||
);
|
||||
}
|
||||
|
||||
return middleware(req, res, next);
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
transformer: {
|
||||
getTransformOptions: async () => ({
|
||||
transform: {
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^10.0.0",
|
||||
"@react-native-community/masked-view": "0.1.5",
|
||||
"color": "^3.1.2",
|
||||
"expo": "^36.0.0",
|
||||
"expo-asset": "~8.0.0",
|
||||
"query-string": "^6.9.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { View, TextInput, ActivityIndicator, StyleSheet } from 'react-native';
|
||||
import { Title, Button } from 'react-native-paper';
|
||||
import { ParamListBase } from '@react-navigation/core';
|
||||
import { ParamListBase } from '@react-navigation/native';
|
||||
import {
|
||||
createStackNavigator,
|
||||
HeaderBackButton,
|
||||
@@ -9,11 +9,27 @@ import {
|
||||
} from '@react-navigation/stack';
|
||||
|
||||
type AuthStackParams = {
|
||||
splash: undefined;
|
||||
home: undefined;
|
||||
'sign-in': undefined;
|
||||
Splash: undefined;
|
||||
Home: undefined;
|
||||
SignIn: undefined;
|
||||
PostSignOut: undefined;
|
||||
};
|
||||
|
||||
const AUTH_CONTEXT_ERROR =
|
||||
'Authentication context not found. Have your wrapped your components with AuthContext.Consumer?';
|
||||
|
||||
const AuthContext = React.createContext<{
|
||||
signIn: () => void;
|
||||
signOut: () => void;
|
||||
}>({
|
||||
signIn: () => {
|
||||
throw new Error(AUTH_CONTEXT_ERROR);
|
||||
},
|
||||
signOut: () => {
|
||||
throw new Error(AUTH_CONTEXT_ERROR);
|
||||
},
|
||||
});
|
||||
|
||||
const SplashScreen = () => {
|
||||
return (
|
||||
<View style={styles.content}>
|
||||
@@ -22,27 +38,27 @@ const SplashScreen = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const SignInScreen = ({ onSignIn }: { onSignIn: (token: string) => void }) => {
|
||||
const SignInScreen = () => {
|
||||
const { signIn } = React.useContext(AuthContext);
|
||||
|
||||
return (
|
||||
<View style={styles.content}>
|
||||
<TextInput placeholder="Username" style={styles.input} />
|
||||
<TextInput placeholder="Password" secureTextEntry style={styles.input} />
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={() => onSignIn('token')}
|
||||
style={styles.button}
|
||||
>
|
||||
<Button mode="contained" onPress={signIn} style={styles.button}>
|
||||
Sign in
|
||||
</Button>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const HomeScreen = ({ onSignOut }: { onSignOut: () => void }) => {
|
||||
const HomeScreen = () => {
|
||||
const { signOut } = React.useContext(AuthContext);
|
||||
|
||||
return (
|
||||
<View style={styles.content}>
|
||||
<Title style={styles.text}>Signed in successfully 🎉</Title>
|
||||
<Button onPress={onSignOut} style={styles.button}>
|
||||
<Button onPress={signOut} style={styles.button}>
|
||||
Sign out
|
||||
</Button>
|
||||
</View>
|
||||
@@ -105,36 +121,44 @@ export default function SimpleStackScreen({ navigation }: Props) {
|
||||
headerShown: false,
|
||||
});
|
||||
|
||||
const authContext = React.useMemo(
|
||||
() => ({
|
||||
signIn: () => dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' }),
|
||||
signOut: () => dispatch({ type: 'SIGN_OUT' }),
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<SimpleStack.Navigator
|
||||
screenOptions={{
|
||||
headerLeft: () => (
|
||||
<HeaderBackButton onPress={() => navigation.goBack()} />
|
||||
),
|
||||
}}
|
||||
>
|
||||
{state.isLoading ? (
|
||||
<SimpleStack.Screen
|
||||
name="splash"
|
||||
component={SplashScreen}
|
||||
options={{ title: `Auth Flow` }}
|
||||
/>
|
||||
) : state.userToken === undefined ? (
|
||||
<SimpleStack.Screen name="sign-in" options={{ title: `Sign in` }}>
|
||||
{() => (
|
||||
<SignInScreen
|
||||
onSignIn={token => dispatch({ type: 'SIGN_IN', token })}
|
||||
/>
|
||||
)}
|
||||
</SimpleStack.Screen>
|
||||
) : (
|
||||
<SimpleStack.Screen name="home" options={{ title: 'Home' }}>
|
||||
{() => (
|
||||
<HomeScreen onSignOut={() => dispatch({ type: 'SIGN_OUT' })} />
|
||||
)}
|
||||
</SimpleStack.Screen>
|
||||
)}
|
||||
</SimpleStack.Navigator>
|
||||
<AuthContext.Provider value={authContext}>
|
||||
<SimpleStack.Navigator
|
||||
screenOptions={{
|
||||
headerLeft: () => (
|
||||
<HeaderBackButton onPress={() => navigation.goBack()} />
|
||||
),
|
||||
}}
|
||||
>
|
||||
{state.isLoading ? (
|
||||
<SimpleStack.Screen
|
||||
name="Splash"
|
||||
component={SplashScreen}
|
||||
options={{ title: 'Auth Flow' }}
|
||||
/>
|
||||
) : state.userToken === undefined ? (
|
||||
<SimpleStack.Screen
|
||||
name="SignIn"
|
||||
options={{ title: 'Sign in' }}
|
||||
component={SignInScreen}
|
||||
/>
|
||||
) : (
|
||||
<SimpleStack.Screen
|
||||
name="Home"
|
||||
options={{ title: 'Home' }}
|
||||
component={HomeScreen}
|
||||
/>
|
||||
)}
|
||||
</SimpleStack.Navigator>
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
|
||||
import Albums from '../Shared/Albums';
|
||||
import Contacts from '../Shared/Contacts';
|
||||
@@ -15,13 +14,7 @@ const MaterialTopTabs = createMaterialTopTabNavigator<MaterialTopTabParams>();
|
||||
|
||||
export default function MaterialTopTabsScreen() {
|
||||
return (
|
||||
<MaterialTopTabs.Navigator
|
||||
tabBarOptions={{
|
||||
style: styles.tabBar,
|
||||
labelStyle: styles.tabLabel,
|
||||
indicatorStyle: styles.tabIndicator,
|
||||
}}
|
||||
>
|
||||
<MaterialTopTabs.Navigator>
|
||||
<MaterialTopTabs.Screen
|
||||
name="chat"
|
||||
component={Chat}
|
||||
@@ -40,15 +33,3 @@ export default function MaterialTopTabsScreen() {
|
||||
</MaterialTopTabs.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
tabBar: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
tabLabel: {
|
||||
color: 'black',
|
||||
},
|
||||
tabIndicator: {
|
||||
backgroundColor: 'tomato',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { Button } from 'react-native-paper';
|
||||
import { useSafeArea } from 'react-native-safe-area-context';
|
||||
import { RouteProp, ParamListBase } from '@react-navigation/core';
|
||||
import { RouteProp, ParamListBase } from '@react-navigation/native';
|
||||
import {
|
||||
createStackNavigator,
|
||||
StackNavigationProp,
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
RouteProp,
|
||||
ParamListBase,
|
||||
useFocusEffect,
|
||||
} from '@react-navigation/core';
|
||||
useTheme,
|
||||
} from '@react-navigation/native';
|
||||
import { DrawerNavigationProp } from '@react-navigation/drawer';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import {
|
||||
@@ -23,90 +24,113 @@ type NativeStackParams = {
|
||||
|
||||
type NativeStackNavigation = NativeStackNavigationProp<NativeStackParams>;
|
||||
|
||||
const Title = ({ children }: { children: React.ReactNode }) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return <Text style={[styles.title, { color: colors.text }]}>{children}</Text>;
|
||||
};
|
||||
|
||||
const Paragraph = ({ children }: { children: React.ReactNode }) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<Text style={[styles.paragraph, { color: colors.text }]}>{children}</Text>
|
||||
);
|
||||
};
|
||||
|
||||
const ArticleScreen = ({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: NativeStackNavigation;
|
||||
route: RouteProp<NativeStackParams, 'article'>;
|
||||
}) => (
|
||||
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
|
||||
<View style={styles.buttons}>
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={() => navigation.push('album')}
|
||||
style={styles.button}
|
||||
>
|
||||
Push album
|
||||
</Button>
|
||||
<Button
|
||||
mode="outlined"
|
||||
onPress={() => navigation.goBack()}
|
||||
style={styles.button}
|
||||
>
|
||||
Go back
|
||||
</Button>
|
||||
</View>
|
||||
<Text style={styles.title}>What is Lorem Ipsum?</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
|
||||
Lorem Ipsum has been the industry's standard dummy text ever since
|
||||
the 1500s, when an unknown printer took a galley of type and scrambled it
|
||||
to make a type specimen book. It has survived not only five centuries, but
|
||||
also the leap into electronic typesetting, remaining essentially
|
||||
unchanged. It was popularised in the 1960s with the release of Letraset
|
||||
sheets containing Lorem Ipsum passages, and more recently with desktop
|
||||
publishing software like Aldus PageMaker including versions of Lorem
|
||||
Ipsum.
|
||||
</Text>
|
||||
<Text style={styles.title}>Where does it come from?</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
Contrary to popular belief, Lorem Ipsum is not simply random text. It has
|
||||
roots in a piece of classical Latin literature from 45 BC, making it over
|
||||
2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney
|
||||
College in Virginia, looked up one of the more obscure Latin words,
|
||||
consectetur, from a Lorem Ipsum passage, and going through the cites of
|
||||
the word in classical literature, discovered the undoubtable source. Lorem
|
||||
Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum
|
||||
et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45
|
||||
BC. This book is a treatise on the theory of ethics, very popular during
|
||||
the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor
|
||||
sit amet..", comes from a line in section 1.10.32.
|
||||
</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below
|
||||
for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus
|
||||
Bonorum et Malorum" by Cicero are also reproduced in their exact
|
||||
original form, accompanied by English versions from the 1914 translation
|
||||
by H. Rackham.
|
||||
</Text>
|
||||
<Text style={styles.title}>Why do we use it?</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout. The point of using
|
||||
Lorem Ipsum is that it has a more-or-less normal distribution of letters,
|
||||
as opposed to using "Content here, content here", making it look
|
||||
like readable English. Many desktop publishing packages and web page
|
||||
editors now use Lorem Ipsum as their default model text, and a search for
|
||||
"lorem ipsum" will uncover many web sites still in their
|
||||
infancy. Various versions have evolved over the years, sometimes by
|
||||
accident, sometimes on purpose (injected humour and the like).
|
||||
</Text>
|
||||
<Text style={styles.title}>Where can I get some?</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
There are many variations of passages of Lorem Ipsum available, but the
|
||||
majority have suffered alteration in some form, by injected humour, or
|
||||
randomised words which don't look even slightly believable. If you
|
||||
are going to use a passage of Lorem Ipsum, you need to be sure there
|
||||
isn't anything embarrassing hidden in the middle of text. All the
|
||||
Lorem Ipsum generators on the Internet tend to repeat predefined chunks as
|
||||
necessary, making this the first true generator on the Internet. It uses a
|
||||
dictionary of over 200 Latin words, combined with a handful of model
|
||||
sentence structures, to generate Lorem Ipsum which looks reasonable. The
|
||||
generated Lorem Ipsum is therefore always free from repetition, injected
|
||||
humour, or non-characteristic words etc.
|
||||
</Text>
|
||||
</ScrollView>
|
||||
);
|
||||
}) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
style={{ backgroundColor: colors.card }}
|
||||
contentContainerStyle={styles.content}
|
||||
>
|
||||
<View style={styles.buttons}>
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={() => navigation.push('album')}
|
||||
style={styles.button}
|
||||
>
|
||||
Push album
|
||||
</Button>
|
||||
<Button
|
||||
mode="outlined"
|
||||
onPress={() => navigation.goBack()}
|
||||
style={styles.button}
|
||||
>
|
||||
Go back
|
||||
</Button>
|
||||
</View>
|
||||
<Title>What is Lorem Ipsum?</Title>
|
||||
<Paragraph>
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting
|
||||
industry. Lorem Ipsum has been the industry's standard dummy text
|
||||
ever since the 1500s, when an unknown printer took a galley of type and
|
||||
scrambled it to make a type specimen book. It has survived not only five
|
||||
centuries, but also the leap into electronic typesetting, remaining
|
||||
essentially unchanged. It was popularised in the 1960s with the release
|
||||
of Letraset sheets containing Lorem Ipsum passages, and more recently
|
||||
with desktop publishing software like Aldus PageMaker including versions
|
||||
of Lorem Ipsum.
|
||||
</Paragraph>
|
||||
<Title>Where does it come from?</Title>
|
||||
<Paragraph>
|
||||
Contrary to popular belief, Lorem Ipsum is not simply random text. It
|
||||
has roots in a piece of classical Latin literature from 45 BC, making it
|
||||
over 2000 years old. Richard McClintock, a Latin professor at
|
||||
Hampden-Sydney College in Virginia, looked up one of the more obscure
|
||||
Latin words, consectetur, from a Lorem Ipsum passage, and going through
|
||||
the cites of the word in classical literature, discovered the
|
||||
undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33
|
||||
of "de Finibus Bonorum et Malorum" (The Extremes of Good and
|
||||
Evil) by Cicero, written in 45 BC. This book is a treatise on the theory
|
||||
of ethics, very popular during the Renaissance. The first line of Lorem
|
||||
Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in
|
||||
section 1.10.32.
|
||||
</Paragraph>
|
||||
<Paragraph>
|
||||
The standard chunk of Lorem Ipsum used since the 1500s is reproduced
|
||||
below for those interested. Sections 1.10.32 and 1.10.33 from "de
|
||||
Finibus Bonorum et Malorum" by Cicero are also reproduced in their
|
||||
exact original form, accompanied by English versions from the 1914
|
||||
translation by H. Rackham.
|
||||
</Paragraph>
|
||||
<Title>Why do we use it?</Title>
|
||||
<Paragraph>
|
||||
It is a long established fact that a reader will be distracted by the
|
||||
readable content of a page when looking at its layout. The point of
|
||||
using Lorem Ipsum is that it has a more-or-less normal distribution of
|
||||
letters, as opposed to using "Content here, content here",
|
||||
making it look like readable English. Many desktop publishing packages
|
||||
and web page editors now use Lorem Ipsum as their default model text,
|
||||
and a search for "lorem ipsum" will uncover many web sites
|
||||
still in their infancy. Various versions have evolved over the years,
|
||||
sometimes by accident, sometimes on purpose (injected humour and the
|
||||
like).
|
||||
</Paragraph>
|
||||
<Title>Where can I get some?</Title>
|
||||
<Paragraph>
|
||||
There are many variations of passages of Lorem Ipsum available, but the
|
||||
majority have suffered alteration in some form, by injected humour, or
|
||||
randomised words which don't look even slightly believable. If you
|
||||
are going to use a passage of Lorem Ipsum, you need to be sure there
|
||||
isn't anything embarrassing hidden in the middle of text. All the
|
||||
Lorem Ipsum generators on the Internet tend to repeat predefined chunks
|
||||
as necessary, making this the first true generator on the Internet. It
|
||||
uses a dictionary of over 200 Latin words, combined with a handful of
|
||||
model sentence structures, to generate Lorem Ipsum which looks
|
||||
reasonable. The generated Lorem Ipsum is therefore always free from
|
||||
repetition, injected humour, or non-characteristic words etc.
|
||||
</Paragraph>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
const AlbumsScreen = ({
|
||||
navigation,
|
||||
@@ -191,21 +215,16 @@ const styles = StyleSheet.create({
|
||||
button: {
|
||||
margin: 8,
|
||||
},
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
content: {
|
||||
paddingVertical: 16,
|
||||
},
|
||||
title: {
|
||||
color: '#000',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 24,
|
||||
marginVertical: 8,
|
||||
marginHorizontal: 16,
|
||||
},
|
||||
paragraph: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
marginVertical: 8,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { Button } from 'react-native-paper';
|
||||
import { RouteProp, ParamListBase } from '@react-navigation/core';
|
||||
import { RouteProp, ParamListBase } from '@react-navigation/native';
|
||||
import {
|
||||
createStackNavigator,
|
||||
StackNavigationProp,
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function Albums() {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: '#343C46',
|
||||
backgroundColor: '#000',
|
||||
},
|
||||
content: {
|
||||
flexDirection: 'row',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { View, Text, Image, ScrollView, StyleSheet } from 'react-native';
|
||||
import { useScrollToTop } from '@react-navigation/native';
|
||||
import { useScrollToTop, useTheme } from '@react-navigation/native';
|
||||
|
||||
type Props = {
|
||||
date?: string;
|
||||
@@ -19,10 +19,12 @@ export default function Article({
|
||||
|
||||
useScrollToTop(ref);
|
||||
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
ref={ref}
|
||||
style={styles.container}
|
||||
style={{ backgroundColor: colors.card }}
|
||||
contentContainerStyle={styles.content}
|
||||
>
|
||||
<View style={styles.author}>
|
||||
@@ -31,24 +33,26 @@ export default function Article({
|
||||
source={require('../../assets/avatar-1.png')}
|
||||
/>
|
||||
<View style={styles.meta}>
|
||||
<Text style={styles.name}>{author.name}</Text>
|
||||
<Text style={styles.timestamp}>{date}</Text>
|
||||
<Text style={[styles.name, { color: colors.text }]}>
|
||||
{author.name}
|
||||
</Text>
|
||||
<Text style={[styles.timestamp, { color: colors.text }]}>{date}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Text style={styles.title}>Lorem Ipsum</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
<Text style={[styles.title, { color: colors.text }]}>Lorem Ipsum</Text>
|
||||
<Text style={[styles.paragraph, { color: colors.text }]}>
|
||||
Contrary to popular belief, Lorem Ipsum is not simply random text. It
|
||||
has roots in a piece of classical Latin literature from 45 BC, making it
|
||||
over 2000 years old.
|
||||
</Text>
|
||||
<Image style={styles.image} source={require('../../assets/book.jpg')} />
|
||||
<Text style={styles.paragraph}>
|
||||
<Text style={[styles.paragraph, { color: colors.text }]}>
|
||||
Richard McClintock, a Latin professor at Hampden-Sydney College in
|
||||
Virginia, looked up one of the more obscure Latin words, consectetur,
|
||||
from a Lorem Ipsum passage, and going through the cites of the word in
|
||||
classical literature, discovered the undoubtable source.
|
||||
</Text>
|
||||
<Text style={styles.paragraph}>
|
||||
<Text style={[styles.paragraph, { color: colors.text }]}>
|
||||
Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus
|
||||
Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero,
|
||||
written in 45 BC. This book is a treatise on the theory of ethics, very
|
||||
@@ -61,9 +65,6 @@ export default function Article({
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
content: {
|
||||
paddingVertical: 16,
|
||||
},
|
||||
@@ -77,13 +78,12 @@ const styles = StyleSheet.create({
|
||||
justifyContent: 'center',
|
||||
},
|
||||
name: {
|
||||
color: '#000',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
},
|
||||
timestamp: {
|
||||
color: '#999',
|
||||
opacity: 0.5,
|
||||
fontSize: 14,
|
||||
lineHeight: 21,
|
||||
},
|
||||
@@ -93,14 +93,12 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 24,
|
||||
},
|
||||
title: {
|
||||
color: '#000',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 36,
|
||||
marginVertical: 8,
|
||||
marginHorizontal: 16,
|
||||
},
|
||||
paragraph: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
lineHeight: 24,
|
||||
marginVertical: 8,
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
} from 'react-native';
|
||||
import { useScrollToTop } from '@react-navigation/native';
|
||||
import { useScrollToTop, useTheme } from '@react-navigation/native';
|
||||
import Color from 'color';
|
||||
|
||||
const MESSAGES = [
|
||||
'okay',
|
||||
@@ -21,6 +22,8 @@ export default function Chat() {
|
||||
|
||||
useScrollToTop(ref);
|
||||
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ScrollView
|
||||
@@ -45,9 +48,12 @@ export default function Chat() {
|
||||
}
|
||||
/>
|
||||
<View
|
||||
style={[styles.bubble, odd ? styles.received : styles.sent]}
|
||||
style={[
|
||||
styles.bubble,
|
||||
{ backgroundColor: odd ? colors.primary : colors.card },
|
||||
]}
|
||||
>
|
||||
<Text style={odd ? styles.receivedText : styles.sentText}>
|
||||
<Text style={{ color: odd ? 'white' : colors.text }}>
|
||||
{text}
|
||||
</Text>
|
||||
</View>
|
||||
@@ -56,7 +62,14 @@ export default function Chat() {
|
||||
})}
|
||||
</ScrollView>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
style={[
|
||||
styles.input,
|
||||
{ backgroundColor: colors.card, color: colors.text },
|
||||
]}
|
||||
placeholderTextColor={Color(colors.text)
|
||||
.alpha(0.5)
|
||||
.rgb()
|
||||
.string()}
|
||||
placeholder="Write a message"
|
||||
underlineColorAndroid="transparent"
|
||||
/>
|
||||
@@ -67,7 +80,6 @@ export default function Chat() {
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#eceff1',
|
||||
},
|
||||
inverted: {
|
||||
transform: [{ scaleY: -1 }],
|
||||
@@ -97,22 +109,9 @@ const styles = StyleSheet.create({
|
||||
paddingHorizontal: 16,
|
||||
borderRadius: 20,
|
||||
},
|
||||
sent: {
|
||||
backgroundColor: '#cfd8dc',
|
||||
},
|
||||
received: {
|
||||
backgroundColor: '#2196F3',
|
||||
},
|
||||
sentText: {
|
||||
color: 'black',
|
||||
},
|
||||
receivedText: {
|
||||
color: 'white',
|
||||
},
|
||||
input: {
|
||||
height: 48,
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 24,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { View, Text, FlatList, StyleSheet } from 'react-native';
|
||||
import { useScrollToTop } from '@react-navigation/native';
|
||||
import { useScrollToTop, useTheme } from '@react-navigation/native';
|
||||
|
||||
type Item = { name: string; number: number };
|
||||
|
||||
@@ -57,27 +57,35 @@ const CONTACTS: Item[] = [
|
||||
{ name: 'Vincent Sandoval', number: 2606111495 },
|
||||
];
|
||||
|
||||
class ContactItem extends React.PureComponent<{
|
||||
item: { name: string; number: number };
|
||||
}> {
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
const ContactItem = React.memo(
|
||||
({ item }: { item: { name: string; number: number } }) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View style={styles.item}>
|
||||
<View style={[styles.item, { backgroundColor: colors.card }]}>
|
||||
<View style={styles.avatar}>
|
||||
<Text style={styles.letter}>
|
||||
{item.name.slice(0, 1).toUpperCase()}
|
||||
</Text>
|
||||
</View>
|
||||
<View style={styles.details}>
|
||||
<Text style={styles.name}>{item.name}</Text>
|
||||
<Text style={styles.number}>{item.number}</Text>
|
||||
<Text style={[styles.name, { color: colors.text }]}>{item.name}</Text>
|
||||
<Text style={[styles.number, { color: colors.text, opacity: 0.5 }]}>
|
||||
{item.number}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const ItemSeparator = () => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View style={[styles.separator, { backgroundColor: colors.border }]} />
|
||||
);
|
||||
};
|
||||
|
||||
export default function Contacts() {
|
||||
const ref = React.useRef<FlatList<Item>>(null);
|
||||
@@ -86,8 +94,6 @@ export default function Contacts() {
|
||||
|
||||
const renderItem = ({ item }: { item: Item }) => <ContactItem item={item} />;
|
||||
|
||||
const ItemSeparator = () => <View style={styles.separator} />;
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
ref={ref}
|
||||
@@ -101,7 +107,6 @@ export default function Contacts() {
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
item: {
|
||||
backgroundColor: 'white',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: 8,
|
||||
@@ -124,14 +129,11 @@ const styles = StyleSheet.create({
|
||||
name: {
|
||||
fontWeight: 'bold',
|
||||
fontSize: 14,
|
||||
color: 'black',
|
||||
},
|
||||
number: {
|
||||
fontSize: 12,
|
||||
color: '#999',
|
||||
},
|
||||
separator: {
|
||||
height: StyleSheet.hairlineWidth,
|
||||
backgroundColor: 'rgba(0, 0, 0, .08)',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
import * as React from 'react';
|
||||
import { ScrollView, AsyncStorage, YellowBox } from 'react-native';
|
||||
import {
|
||||
View,
|
||||
ScrollView,
|
||||
AsyncStorage,
|
||||
YellowBox,
|
||||
Platform,
|
||||
StatusBar,
|
||||
} from 'react-native';
|
||||
import { MaterialIcons } from '@expo/vector-icons';
|
||||
import { Appbar, List } from 'react-native-paper';
|
||||
import {
|
||||
Provider as PaperProvider,
|
||||
DefaultTheme as PaperLightTheme,
|
||||
DarkTheme as PaperDarkTheme,
|
||||
Subheading,
|
||||
Appbar,
|
||||
List,
|
||||
Switch,
|
||||
Divider,
|
||||
} from 'react-native-paper';
|
||||
import { Asset } from 'expo-asset';
|
||||
import {
|
||||
InitialState,
|
||||
getStateFromPath,
|
||||
NavigationContainerRef,
|
||||
} from '@react-navigation/core';
|
||||
import {
|
||||
useLinking,
|
||||
NavigationContainerRef,
|
||||
NavigationNativeContainer,
|
||||
DefaultTheme,
|
||||
DarkTheme,
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
createDrawerNavigator,
|
||||
@@ -74,7 +90,8 @@ const SCREENS = {
|
||||
const Drawer = createDrawerNavigator<RootDrawerParamList>();
|
||||
const Stack = createStackNavigator<RootStackParamList>();
|
||||
|
||||
const PERSISTENCE_KEY = 'NAVIGATION_STATE';
|
||||
const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
|
||||
const THEME_PERSISTENCE_KEY = 'THEME_TYPE';
|
||||
|
||||
Asset.loadAsync(StackAssets);
|
||||
|
||||
@@ -104,6 +121,8 @@ export default function App() {
|
||||
},
|
||||
});
|
||||
|
||||
const [theme, setTheme] = React.useState(DefaultTheme);
|
||||
|
||||
const [isReady, setIsReady] = React.useState(false);
|
||||
const [initialState, setInitialState] = React.useState<
|
||||
InitialState | undefined
|
||||
@@ -115,7 +134,9 @@ export default function App() {
|
||||
let state = await getInitialState();
|
||||
|
||||
if (state === undefined) {
|
||||
const savedState = await AsyncStorage.getItem(PERSISTENCE_KEY);
|
||||
const savedState = await AsyncStorage.getItem(
|
||||
NAVIGATION_PERSISTENCE_KEY
|
||||
);
|
||||
state = savedState ? JSON.parse(savedState) : undefined;
|
||||
}
|
||||
|
||||
@@ -123,6 +144,14 @@ export default function App() {
|
||||
setInitialState(state);
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
const themeName = await AsyncStorage.getItem(THEME_PERSISTENCE_KEY);
|
||||
|
||||
setTheme(themeName === 'dark' ? DarkTheme : DefaultTheme);
|
||||
} catch (e) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
setIsReady(true);
|
||||
}
|
||||
};
|
||||
@@ -130,78 +159,126 @@ export default function App() {
|
||||
restoreState();
|
||||
}, [getInitialState]);
|
||||
|
||||
const paperTheme = React.useMemo(() => {
|
||||
const t = theme.dark ? PaperDarkTheme : PaperLightTheme;
|
||||
|
||||
return {
|
||||
...t,
|
||||
colors: {
|
||||
...t.colors,
|
||||
...theme.colors,
|
||||
surface: theme.colors.card,
|
||||
accent: theme.dark ? 'rgb(255, 55, 95)' : 'rgb(255, 45, 85)',
|
||||
},
|
||||
};
|
||||
}, [theme.colors, theme.dark]);
|
||||
|
||||
if (!isReady) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<NavigationNativeContainer
|
||||
ref={containerRef}
|
||||
initialState={initialState}
|
||||
onStateChange={state =>
|
||||
AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))
|
||||
}
|
||||
>
|
||||
<Drawer.Navigator>
|
||||
<Drawer.Screen
|
||||
name="Root"
|
||||
options={{
|
||||
title: 'Examples',
|
||||
drawerIcon: ({ size, color }) => (
|
||||
<MaterialIcons size={size} color={color} name="folder" />
|
||||
),
|
||||
}}
|
||||
>
|
||||
{({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: DrawerNavigationProp<RootDrawerParamList>;
|
||||
}) => (
|
||||
<Stack.Navigator>
|
||||
<Stack.Screen
|
||||
name="Home"
|
||||
options={{
|
||||
title: 'Examples',
|
||||
headerLeft: () => (
|
||||
<Appbar.Action
|
||||
icon="menu"
|
||||
onPress={() => navigation.toggleDrawer()}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: StackNavigationProp<RootStackParamList>;
|
||||
}) => (
|
||||
<ScrollView>
|
||||
{(Object.keys(SCREENS) as Array<keyof typeof SCREENS>).map(
|
||||
name => (
|
||||
<PaperProvider theme={paperTheme}>
|
||||
{Platform.OS === 'ios' && (
|
||||
<StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />
|
||||
)}
|
||||
<NavigationNativeContainer
|
||||
ref={containerRef}
|
||||
initialState={initialState}
|
||||
onStateChange={state =>
|
||||
AsyncStorage.setItem(
|
||||
NAVIGATION_PERSISTENCE_KEY,
|
||||
JSON.stringify(state)
|
||||
)
|
||||
}
|
||||
theme={theme}
|
||||
>
|
||||
<Drawer.Navigator>
|
||||
<Drawer.Screen
|
||||
name="Root"
|
||||
options={{
|
||||
title: 'Examples',
|
||||
drawerIcon: ({ size, color }) => (
|
||||
<MaterialIcons size={size} color={color} name="folder" />
|
||||
),
|
||||
}}
|
||||
>
|
||||
{({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: DrawerNavigationProp<RootDrawerParamList>;
|
||||
}) => (
|
||||
<Stack.Navigator>
|
||||
<Stack.Screen
|
||||
name="Home"
|
||||
options={{
|
||||
title: 'Examples',
|
||||
headerLeft: () => (
|
||||
<Appbar.Action
|
||||
color={theme.colors.text}
|
||||
icon="menu"
|
||||
onPress={() => navigation.toggleDrawer()}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
>
|
||||
{({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: StackNavigationProp<RootStackParamList>;
|
||||
}) => (
|
||||
<ScrollView
|
||||
style={{ backgroundColor: theme.colors.background }}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
padding: 16,
|
||||
}}
|
||||
>
|
||||
<Subheading>Dark theme</Subheading>
|
||||
<Switch
|
||||
value={theme.dark}
|
||||
onValueChange={() => {
|
||||
AsyncStorage.setItem(
|
||||
THEME_PERSISTENCE_KEY,
|
||||
theme.dark ? 'light' : 'dark'
|
||||
);
|
||||
|
||||
setTheme(t => (t.dark ? DefaultTheme : DarkTheme));
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<Divider />
|
||||
{(Object.keys(SCREENS) as Array<
|
||||
keyof typeof SCREENS
|
||||
>).map(name => (
|
||||
<List.Item
|
||||
key={name}
|
||||
title={SCREENS[name].title}
|
||||
onPress={() => navigation.push(name)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</ScrollView>
|
||||
))}
|
||||
</ScrollView>
|
||||
)}
|
||||
</Stack.Screen>
|
||||
{(Object.keys(SCREENS) as Array<keyof typeof SCREENS>).map(
|
||||
name => (
|
||||
<Stack.Screen
|
||||
key={name}
|
||||
name={name}
|
||||
component={SCREENS[name].component}
|
||||
options={{ title: SCREENS[name].title }}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Stack.Screen>
|
||||
{(Object.keys(SCREENS) as Array<keyof typeof SCREENS>).map(
|
||||
name => (
|
||||
<Stack.Screen
|
||||
key={name}
|
||||
name={name}
|
||||
component={SCREENS[name].component}
|
||||
options={{ title: SCREENS[name].title }}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Stack.Navigator>
|
||||
)}
|
||||
</Drawer.Screen>
|
||||
</Drawer.Navigator>
|
||||
</NavigationNativeContainer>
|
||||
</Stack.Navigator>
|
||||
)}
|
||||
</Drawer.Screen>
|
||||
</Drawer.Navigator>
|
||||
</NavigationNativeContainer>
|
||||
</PaperProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.25...@react-navigation/bottom-tabs@5.0.0-alpha.26) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.25](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.24...@react-navigation/bottom-tabs@5.0.0-alpha.25) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.24](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.23...@react-navigation/bottom-tabs@5.0.0-alpha.24) (2019-12-10)
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Bottom tab navigator for React Navigation following iOS design guidelines.
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/bottom-tabs
|
||||
yarn add @react-navigation/native @react-navigation/bottom-tabs
|
||||
```
|
||||
|
||||
Now we need to install [`react-native-safe-area-context`](https://github.com/th3rdwave/react-native-safe-area-context).
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.24",
|
||||
"version": "5.0.0-alpha.26",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -33,10 +33,12 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16",
|
||||
"color": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
"@types/color": "^3.0.0",
|
||||
"@types/react": "^16.9.11",
|
||||
"@types/react-native": "^0.60.22",
|
||||
"del-cli": "^3.0.0",
|
||||
@@ -46,7 +48,7 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-safe-area-context": "^0.3.6"
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
useNavigationBuilder,
|
||||
createNavigatorFactory,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
TabRouter,
|
||||
TabRouterOptions,
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
Descriptor,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import { TabNavigationState } from '@react-navigation/routers';
|
||||
|
||||
export type BottomTabNavigationEventMap = {
|
||||
|
||||
@@ -10,22 +10,15 @@ import {
|
||||
Dimensions,
|
||||
} from 'react-native';
|
||||
import {
|
||||
Route,
|
||||
NavigationContext,
|
||||
CommonActions,
|
||||
} from '@react-navigation/core';
|
||||
useTheme,
|
||||
} from '@react-navigation/native';
|
||||
import { SafeAreaConsumer } from 'react-native-safe-area-context';
|
||||
|
||||
import BottomTabItem from './BottomTabItem';
|
||||
import { BottomTabBarProps } from '../types';
|
||||
|
||||
type State = {
|
||||
dimensions: { height: number; width: number };
|
||||
layout: { height: number; width: number };
|
||||
keyboard: boolean;
|
||||
visible: Animated.Value;
|
||||
};
|
||||
|
||||
type Props = BottomTabBarProps & {
|
||||
activeTintColor?: string;
|
||||
inactiveTintColor?: string;
|
||||
@@ -34,97 +27,101 @@ type Props = BottomTabBarProps & {
|
||||
const DEFAULT_TABBAR_HEIGHT = 50;
|
||||
const DEFAULT_MAX_TAB_ITEM_WIDTH = 125;
|
||||
|
||||
export default class BottomTabBar extends React.Component<Props, State> {
|
||||
static defaultProps = {
|
||||
keyboardHidesTabBar: false,
|
||||
adaptive: true,
|
||||
};
|
||||
export default function BottomTabBar({
|
||||
state,
|
||||
navigation,
|
||||
descriptors,
|
||||
activeBackgroundColor,
|
||||
activeTintColor,
|
||||
adaptive = true,
|
||||
allowFontScaling,
|
||||
inactiveBackgroundColor,
|
||||
inactiveTintColor,
|
||||
keyboardHidesTabBar = false,
|
||||
labelPosition,
|
||||
labelStyle,
|
||||
showIcon,
|
||||
showLabel,
|
||||
style,
|
||||
tabStyle,
|
||||
}: Props) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
state = {
|
||||
dimensions: Dimensions.get('window'),
|
||||
layout: { height: 0, width: 0 },
|
||||
keyboard: false,
|
||||
visible: new Animated.Value(1),
|
||||
};
|
||||
const [dimensions, setDimensions] = React.useState(Dimensions.get('window'));
|
||||
const [layout, setLayout] = React.useState({ height: 0, width: 0 });
|
||||
const [keyboardShown, setKeyboardShown] = React.useState(false);
|
||||
|
||||
componentDidMount() {
|
||||
Dimensions.addEventListener('change', this.handleOrientationChange);
|
||||
const [visible] = React.useState(() => new Animated.Value(0));
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
Keyboard.addListener('keyboardWillShow', this.handleKeyboardShow);
|
||||
Keyboard.addListener('keyboardWillHide', this.handleKeyboardHide);
|
||||
} else {
|
||||
Keyboard.addListener('keyboardDidShow', this.handleKeyboardShow);
|
||||
Keyboard.addListener('keyboardDidHide', this.handleKeyboardHide);
|
||||
}
|
||||
}
|
||||
const { routes } = state;
|
||||
|
||||
componentWillUnmount() {
|
||||
Dimensions.removeEventListener('change', this.handleOrientationChange);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
Keyboard.removeListener('keyboardWillShow', this.handleKeyboardShow);
|
||||
Keyboard.removeListener('keyboardWillHide', this.handleKeyboardHide);
|
||||
} else {
|
||||
Keyboard.removeListener('keyboardDidShow', this.handleKeyboardShow);
|
||||
Keyboard.removeListener('keyboardDidHide', this.handleKeyboardHide);
|
||||
}
|
||||
}
|
||||
|
||||
private handleOrientationChange = ({ window }: { window: ScaledSize }) => {
|
||||
this.setState({ dimensions: window });
|
||||
};
|
||||
|
||||
private handleKeyboardShow = () =>
|
||||
this.setState({ keyboard: true }, () =>
|
||||
Animated.timing(this.state.visible, {
|
||||
React.useEffect(() => {
|
||||
if (keyboardShown) {
|
||||
Animated.timing(visible, {
|
||||
toValue: 0,
|
||||
duration: 200,
|
||||
useNativeDriver: true,
|
||||
}).start()
|
||||
);
|
||||
}).start();
|
||||
}
|
||||
}, [keyboardShown, visible]);
|
||||
|
||||
private handleKeyboardHide = () =>
|
||||
Animated.timing(this.state.visible, {
|
||||
toValue: 1,
|
||||
duration: 250,
|
||||
useNativeDriver: true,
|
||||
}).start(({ finished }) => {
|
||||
if (finished) {
|
||||
this.setState({ keyboard: false });
|
||||
}
|
||||
});
|
||||
React.useEffect(() => {
|
||||
const handleOrientationChange = ({ window }: { window: ScaledSize }) => {
|
||||
setDimensions(window);
|
||||
};
|
||||
|
||||
private handleLayout = (e: LayoutChangeEvent) => {
|
||||
const { layout } = this.state;
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
const handleKeyboardShow = () => setKeyboardShown(true);
|
||||
|
||||
if (height === layout.height && width === layout.width) {
|
||||
return;
|
||||
const handleKeyboardHide = () =>
|
||||
Animated.timing(visible, {
|
||||
toValue: 1,
|
||||
duration: 250,
|
||||
useNativeDriver: true,
|
||||
}).start(({ finished }) => {
|
||||
if (finished) {
|
||||
setKeyboardShown(false);
|
||||
}
|
||||
});
|
||||
|
||||
Dimensions.addEventListener('change', handleOrientationChange);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
Keyboard.addListener('keyboardWillShow', handleKeyboardShow);
|
||||
Keyboard.addListener('keyboardWillHide', handleKeyboardHide);
|
||||
} else {
|
||||
Keyboard.addListener('keyboardDidShow', handleKeyboardShow);
|
||||
Keyboard.addListener('keyboardDidHide', handleKeyboardHide);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
layout: {
|
||||
height,
|
||||
width,
|
||||
},
|
||||
return () => {
|
||||
Dimensions.removeEventListener('change', handleOrientationChange);
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
Keyboard.removeListener('keyboardWillShow', handleKeyboardShow);
|
||||
Keyboard.removeListener('keyboardWillHide', handleKeyboardHide);
|
||||
} else {
|
||||
Keyboard.removeListener('keyboardDidShow', handleKeyboardShow);
|
||||
Keyboard.removeListener('keyboardDidHide', handleKeyboardHide);
|
||||
}
|
||||
};
|
||||
}, [visible]);
|
||||
|
||||
const handleLayout = (e: LayoutChangeEvent) => {
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
|
||||
setLayout(layout => {
|
||||
if (height === layout.height && width === layout.width) {
|
||||
return layout;
|
||||
} else {
|
||||
return {
|
||||
height,
|
||||
width,
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
private getLabelText = ({ route }: { route: Route<string> }) => {
|
||||
const { options } = this.props.descriptors[route.key];
|
||||
|
||||
return options.tabBarLabel !== undefined
|
||||
? options.tabBarLabel
|
||||
: options.title !== undefined
|
||||
? options.title
|
||||
: route.name;
|
||||
};
|
||||
|
||||
private shouldUseHorizontalLabels = () => {
|
||||
const { state, adaptive, tabStyle, labelPosition } = this.props;
|
||||
const { dimensions } = this.state;
|
||||
const { routes } = state;
|
||||
const shouldUseHorizontalLabels = () => {
|
||||
const isLandscape = dimensions.width > dimensions.height;
|
||||
|
||||
if (labelPosition) {
|
||||
@@ -165,126 +162,114 @@ export default class BottomTabBar extends React.Component<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
state,
|
||||
navigation,
|
||||
descriptors,
|
||||
keyboardHidesTabBar,
|
||||
activeTintColor,
|
||||
inactiveTintColor,
|
||||
activeBackgroundColor,
|
||||
inactiveBackgroundColor,
|
||||
labelStyle,
|
||||
showIcon,
|
||||
showLabel,
|
||||
allowFontScaling,
|
||||
style,
|
||||
tabStyle,
|
||||
} = this.props;
|
||||
const { routes } = state;
|
||||
return (
|
||||
<SafeAreaConsumer>
|
||||
{insets => (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.tabBar,
|
||||
{
|
||||
backgroundColor: colors.card,
|
||||
borderTopColor: colors.border,
|
||||
},
|
||||
keyboardHidesTabBar
|
||||
? {
|
||||
// When the keyboard is shown, slide down the tab bar
|
||||
transform: [
|
||||
{
|
||||
translateY: visible.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [layout.height, 0],
|
||||
}),
|
||||
},
|
||||
],
|
||||
// Absolutely position the tab bar so that the content is below it
|
||||
// This is needed to avoid gap at bottom when the tab bar is hidden
|
||||
position: keyboardShown ? 'absolute' : null,
|
||||
}
|
||||
: null,
|
||||
{
|
||||
height: DEFAULT_TABBAR_HEIGHT + (insets ? insets.bottom : 0),
|
||||
paddingBottom: insets ? insets.bottom : 0,
|
||||
},
|
||||
style,
|
||||
]}
|
||||
pointerEvents={keyboardHidesTabBar && keyboardShown ? 'none' : 'auto'}
|
||||
>
|
||||
<View style={styles.content} onLayout={handleLayout}>
|
||||
{routes.map((route, index) => {
|
||||
const focused = index === state.index;
|
||||
const { options } = descriptors[route.key];
|
||||
|
||||
return (
|
||||
<SafeAreaConsumer>
|
||||
{insets => (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.tabBar,
|
||||
keyboardHidesTabBar
|
||||
? {
|
||||
// When the keyboard is shown, slide down the tab bar
|
||||
transform: [
|
||||
{
|
||||
translateY: this.state.visible.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [this.state.layout.height, 0],
|
||||
}),
|
||||
},
|
||||
],
|
||||
// Absolutely position the tab bar so that the content is below it
|
||||
// This is needed to avoid gap at bottom when the tab bar is hidden
|
||||
position: this.state.keyboard ? 'absolute' : null,
|
||||
}
|
||||
: null,
|
||||
{
|
||||
height: DEFAULT_TABBAR_HEIGHT + (insets ? insets.bottom : 0),
|
||||
paddingBottom: insets ? insets.bottom : 0,
|
||||
},
|
||||
style,
|
||||
]}
|
||||
pointerEvents={
|
||||
keyboardHidesTabBar && this.state.keyboard ? 'none' : 'auto'
|
||||
}
|
||||
>
|
||||
<View style={styles.content} onLayout={this.handleLayout}>
|
||||
{routes.map((route, index) => {
|
||||
const focused = index === state.index;
|
||||
const { options } = descriptors[route.key];
|
||||
const onPress = () => {
|
||||
const event = navigation.emit({
|
||||
type: 'tabPress',
|
||||
target: route.key,
|
||||
});
|
||||
|
||||
const onPress = () => {
|
||||
const event = navigation.emit({
|
||||
type: 'tabPress',
|
||||
target: route.key,
|
||||
if (!focused && !event.defaultPrevented) {
|
||||
navigation.dispatch({
|
||||
...CommonActions.navigate(route.name),
|
||||
target: state.key,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (!focused && !event.defaultPrevented) {
|
||||
navigation.dispatch({
|
||||
...CommonActions.navigate(route.name),
|
||||
target: state.key,
|
||||
});
|
||||
}
|
||||
};
|
||||
const onLongPress = () => {
|
||||
navigation.emit({
|
||||
type: 'tabLongPress',
|
||||
target: route.key,
|
||||
});
|
||||
};
|
||||
|
||||
const onLongPress = () => {
|
||||
navigation.emit({
|
||||
type: 'tabLongPress',
|
||||
target: route.key,
|
||||
});
|
||||
};
|
||||
const label =
|
||||
options.tabBarLabel !== undefined
|
||||
? options.tabBarLabel
|
||||
: options.title !== undefined
|
||||
? options.title
|
||||
: route.name;
|
||||
|
||||
const label = this.getLabelText({ route });
|
||||
const accessibilityLabel =
|
||||
options.tabBarAccessibilityLabel !== undefined
|
||||
? options.tabBarAccessibilityLabel
|
||||
: typeof label === 'string'
|
||||
? `${label}, tab, ${index + 1} of ${routes.length}`
|
||||
: undefined;
|
||||
const accessibilityLabel =
|
||||
options.tabBarAccessibilityLabel !== undefined
|
||||
? options.tabBarAccessibilityLabel
|
||||
: typeof label === 'string'
|
||||
? `${label}, tab, ${index + 1} of ${routes.length}`
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<NavigationContext.Provider
|
||||
key={route.key}
|
||||
value={descriptors[route.key].navigation}
|
||||
>
|
||||
<BottomTabItem
|
||||
route={route}
|
||||
focused={focused}
|
||||
horizontal={this.shouldUseHorizontalLabels()}
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
testID={options.tabBarTestID}
|
||||
allowFontScaling={allowFontScaling}
|
||||
activeTintColor={activeTintColor}
|
||||
inactiveTintColor={inactiveTintColor}
|
||||
activeBackgroundColor={activeBackgroundColor}
|
||||
inactiveBackgroundColor={inactiveBackgroundColor}
|
||||
button={options.tabBarButton}
|
||||
icon={options.tabBarIcon}
|
||||
label={label}
|
||||
showIcon={showIcon}
|
||||
showLabel={showLabel}
|
||||
labelStyle={labelStyle}
|
||||
style={tabStyle}
|
||||
/>
|
||||
</NavigationContext.Provider>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</Animated.View>
|
||||
)}
|
||||
</SafeAreaConsumer>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<NavigationContext.Provider
|
||||
key={route.key}
|
||||
value={descriptors[route.key].navigation}
|
||||
>
|
||||
<BottomTabItem
|
||||
route={route}
|
||||
focused={focused}
|
||||
horizontal={shouldUseHorizontalLabels()}
|
||||
onPress={onPress}
|
||||
onLongPress={onLongPress}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
testID={options.tabBarTestID}
|
||||
allowFontScaling={allowFontScaling}
|
||||
activeTintColor={activeTintColor}
|
||||
inactiveTintColor={inactiveTintColor}
|
||||
activeBackgroundColor={activeBackgroundColor}
|
||||
inactiveBackgroundColor={inactiveBackgroundColor}
|
||||
button={options.tabBarButton}
|
||||
icon={options.tabBarIcon}
|
||||
label={label}
|
||||
showIcon={showIcon}
|
||||
showLabel={showLabel}
|
||||
labelStyle={labelStyle}
|
||||
style={tabStyle}
|
||||
/>
|
||||
</NavigationContext.Provider>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</Animated.View>
|
||||
)}
|
||||
</SafeAreaConsumer>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -292,9 +277,7 @@ const styles = StyleSheet.create({
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
backgroundColor: '#fff',
|
||||
borderTopWidth: StyleSheet.hairlineWidth,
|
||||
borderTopColor: 'rgba(0, 0, 0, .3)',
|
||||
elevation: 8,
|
||||
},
|
||||
content: {
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
ViewStyle,
|
||||
TextStyle,
|
||||
} from 'react-native';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import Color from 'color';
|
||||
|
||||
import TabBarIcon from './TabBarIcon';
|
||||
import { BottomTabBarButtonProps } from '../types';
|
||||
@@ -113,8 +114,8 @@ export default function BottomTabBarItem({
|
||||
onPress,
|
||||
onLongPress,
|
||||
horizontal,
|
||||
activeTintColor = '#007AFF',
|
||||
inactiveTintColor = '#8E8E93',
|
||||
activeTintColor: customActiveTintColor,
|
||||
inactiveTintColor: customInactiveTintColor,
|
||||
activeBackgroundColor = 'transparent',
|
||||
inactiveBackgroundColor = 'transparent',
|
||||
showLabel = true,
|
||||
@@ -123,6 +124,20 @@ export default function BottomTabBarItem({
|
||||
labelStyle,
|
||||
style,
|
||||
}: Props) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
const activeTintColor =
|
||||
customActiveTintColor === undefined
|
||||
? colors.primary
|
||||
: customActiveTintColor;
|
||||
|
||||
const inactiveTintColor =
|
||||
customInactiveTintColor === undefined
|
||||
? Color(colors.text)
|
||||
.mix(Color(colors.card), 0.5)
|
||||
.hex()
|
||||
: customInactiveTintColor;
|
||||
|
||||
const renderLabel = ({ focused }: { focused: boolean }) => {
|
||||
if (showLabel === false) {
|
||||
return null;
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
import { TabNavigationState } from '@react-navigation/routers';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { ScreenContainer } from 'react-native-screens';
|
||||
|
||||
@@ -25,6 +26,26 @@ type State = {
|
||||
loaded: number[];
|
||||
};
|
||||
|
||||
function SceneContent({
|
||||
isFocused,
|
||||
children,
|
||||
}: {
|
||||
isFocused: boolean;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View
|
||||
accessibilityElementsHidden={!isFocused}
|
||||
importantForAccessibility={isFocused ? 'auto' : 'no-hide-descendants'}
|
||||
style={[styles.content, { backgroundColor: colors.background }]}
|
||||
>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export default class BottomTabView extends React.Component<Props, State> {
|
||||
static defaultProps = {
|
||||
lazy: true,
|
||||
@@ -97,15 +118,9 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
style={StyleSheet.absoluteFill}
|
||||
isVisible={isFocused}
|
||||
>
|
||||
<View
|
||||
accessibilityElementsHidden={!isFocused}
|
||||
importantForAccessibility={
|
||||
isFocused ? 'auto' : 'no-hide-descendants'
|
||||
}
|
||||
style={styles.content}
|
||||
>
|
||||
<SceneContent isFocused={isFocused}>
|
||||
{descriptors[route.key].render()}
|
||||
</View>
|
||||
</SceneContent>
|
||||
</ResourceSavingScene>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route } from '@react-navigation/native';
|
||||
|
||||
type Props = {
|
||||
route: Route<string>;
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.16...@react-navigation/compat@5.0.0-alpha.17) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.16](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.15...@react-navigation/compat@5.0.0-alpha.16) (2019-12-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
@@ -7,7 +7,7 @@ Compatibility layer to write navigator definitions in static configuration forma
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/compat
|
||||
yarn add @react-navigation/native @react-navigation/compat
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.0.0-alpha.16",
|
||||
"version": "5.0.0-alpha.17",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -24,7 +24,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.9.11",
|
||||
@@ -32,7 +32,7 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "~16.9.0"
|
||||
},
|
||||
"@react-native-community/bob": {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import ScreenPropsContext from './ScreenPropsContext';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommonActions, NavigationState } from '@react-navigation/core';
|
||||
import { CommonActions, NavigationState } from '@react-navigation/native';
|
||||
|
||||
export function navigate({
|
||||
routeName,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CommonActions } from '@react-navigation/core';
|
||||
import { CommonActions } from '@react-navigation/native';
|
||||
import { StackActions, StackActionType } from '@react-navigation/routers';
|
||||
|
||||
export function reset(): CommonActions.Action {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
ParamListBase,
|
||||
NavigationProp,
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import * as helpers from './helpers';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
TypedNavigator,
|
||||
NavigationProp,
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import CompatScreen from './CompatScreen';
|
||||
import ScreenPropsContext from './ScreenPropsContext';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
useNavigationBuilder,
|
||||
createNavigatorFactory,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
TabRouter,
|
||||
TabRouterOptions,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ParamListBase, NavigationProp, Route } from '@react-navigation/core';
|
||||
import { ParamListBase, NavigationProp, Route } from '@react-navigation/native';
|
||||
import * as helpers from './helpers';
|
||||
|
||||
export type CompatNavigationProp<
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
useRoute,
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { NavigationProp, ParamListBase } from '@react-navigation/core';
|
||||
import { NavigationProp, ParamListBase } from '@react-navigation/native';
|
||||
import useCompatNavigation from './useCompatNavigation';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { useIsFocused } from '@react-navigation/core';
|
||||
import { useIsFocused } from '@react-navigation/native';
|
||||
|
||||
type InjectedProps = {
|
||||
isFocused: boolean;
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.27...@react-navigation/drawer@5.0.0-alpha.28) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.26...@react-navigation/drawer@5.0.0-alpha.27) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.25...@react-navigation/drawer@5.0.0-alpha.26) (2019-12-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
@@ -7,7 +7,7 @@ Bottom tab navigator for React Navigation following iOS design guidelines.
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/drawer
|
||||
yarn add @react-navigation/native @react-navigation/drawer
|
||||
```
|
||||
|
||||
Now we need to install [`react-native-gesture-handler`](https://github.com/kmagiera/react-native-gesture-handler), [`react-native-reanimated`](https://github.com/kmagiera/react-native-reanimated) and [`react-native-safe-area-context`](https://github.com/th3rdwave/react-native-safe-area-context).
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"drawer"
|
||||
],
|
||||
"version": "5.0.0-alpha.26",
|
||||
"version": "5.0.0-alpha.28",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -34,7 +34,8 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16",
|
||||
"color": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
@@ -50,7 +51,7 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-gesture-handler": "^1.0.0",
|
||||
|
||||
@@ -10,6 +10,7 @@ export { default as DrawerView } from './views/DrawerView';
|
||||
export { default as DrawerItem } from './views/DrawerItem';
|
||||
export { default as DrawerItemList } from './views/DrawerItemList';
|
||||
export { default as DrawerContent } from './views/DrawerContent';
|
||||
export { default as DrawerContentScrollView } from './views/DrawerContentScrollView';
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
createNavigatorFactory,
|
||||
useNavigationBuilder,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
DrawerNavigationState,
|
||||
DrawerRouterOptions,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
NavigationProp,
|
||||
Descriptor,
|
||||
NavigationHelpers,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import { DrawerNavigationState } from '@react-navigation/routers';
|
||||
import { PanGestureHandler } from 'react-native-gesture-handler';
|
||||
|
||||
@@ -121,7 +121,7 @@ export type DrawerNavigationOptions = {
|
||||
|
||||
export type DrawerContentComponentProps<T = DrawerContentOptions> = T & {
|
||||
state: DrawerNavigationState;
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
navigation: DrawerNavigationHelpers;
|
||||
descriptors: DrawerDescriptorMap;
|
||||
/**
|
||||
* Animated node which represents the current progress of the drawer's open state.
|
||||
|
||||
@@ -1,36 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import { useSafeArea } from 'react-native-safe-area-context';
|
||||
import DrawerItemList from './DrawerItemList';
|
||||
import { DrawerContentComponentProps } from '../types';
|
||||
import DrawerContentScrollView from './DrawerContentScrollView';
|
||||
|
||||
export default function DrawerContent({
|
||||
contentContainerStyle,
|
||||
style,
|
||||
drawerPosition,
|
||||
...rest
|
||||
}: DrawerContentComponentProps) {
|
||||
const insets = useSafeArea();
|
||||
|
||||
export default function DrawerContent(props: DrawerContentComponentProps) {
|
||||
return (
|
||||
<ScrollView
|
||||
contentContainerStyle={[
|
||||
{
|
||||
paddingTop: insets.top + 4,
|
||||
paddingLeft: drawerPosition === 'left' ? insets.left : 0,
|
||||
paddingRight: drawerPosition === 'right' ? insets.right : 0,
|
||||
},
|
||||
contentContainerStyle,
|
||||
]}
|
||||
style={[styles.container, style]}
|
||||
>
|
||||
<DrawerItemList {...rest} />
|
||||
</ScrollView>
|
||||
<DrawerContentScrollView {...props}>
|
||||
<DrawerItemList {...props} />
|
||||
</DrawerContentScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
43
packages/drawer/src/views/DrawerContentScrollView.tsx
Normal file
43
packages/drawer/src/views/DrawerContentScrollView.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import * as React from 'react';
|
||||
import { ScrollView, StyleSheet, ScrollViewProps } from 'react-native';
|
||||
import { useSafeArea } from 'react-native-safe-area-context';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
type Props = ScrollViewProps & {
|
||||
drawerPosition: 'left' | 'right';
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function DrawerContentScrollView({
|
||||
contentContainerStyle,
|
||||
style,
|
||||
drawerPosition,
|
||||
children,
|
||||
...rest
|
||||
}: Props) {
|
||||
const insets = useSafeArea();
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
{...rest}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
paddingTop: insets.top + 4,
|
||||
paddingLeft: drawerPosition === 'left' ? insets.left : 0,
|
||||
paddingRight: drawerPosition === 'right' ? insets.right : 0,
|
||||
},
|
||||
contentContainerStyle,
|
||||
]}
|
||||
style={[styles.container, { backgroundColor: colors.card }, style]}
|
||||
>
|
||||
{children}
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
ViewStyle,
|
||||
TextStyle,
|
||||
} from 'react-native';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
import Color from 'color';
|
||||
import TouchableItem from './TouchableItem';
|
||||
|
||||
type Props = {
|
||||
@@ -61,19 +63,29 @@ type Props = {
|
||||
/**
|
||||
* A component used to show an action item with an icon and a label in a navigation drawer.
|
||||
*/
|
||||
export default function DrawerItem({
|
||||
icon,
|
||||
label,
|
||||
labelStyle,
|
||||
focused = false,
|
||||
activeTintColor = '#6200ee',
|
||||
inactiveTintColor = 'rgba(0, 0, 0, .68)',
|
||||
activeBackgroundColor = 'rgba(98, 0, 238, 0.12)',
|
||||
inactiveBackgroundColor = 'transparent',
|
||||
style,
|
||||
onPress,
|
||||
...rest
|
||||
}: Props) {
|
||||
export default function DrawerItem(props: Props) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
const {
|
||||
icon,
|
||||
label,
|
||||
labelStyle,
|
||||
focused = false,
|
||||
activeTintColor = colors.primary,
|
||||
inactiveTintColor = Color(colors.text)
|
||||
.alpha(0.68)
|
||||
.rgb()
|
||||
.string(),
|
||||
activeBackgroundColor = Color(activeTintColor)
|
||||
.alpha(0.12)
|
||||
.rgb()
|
||||
.string(),
|
||||
inactiveBackgroundColor = 'transparent',
|
||||
style,
|
||||
onPress,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
const { borderRadius = 4 } = StyleSheet.flatten(style || {});
|
||||
const color = focused ? activeTintColor : inactiveTintColor;
|
||||
const backgroundColor = focused
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { CommonActions } from '@react-navigation/core';
|
||||
import { CommonActions } from '@react-navigation/native';
|
||||
import {
|
||||
DrawerActions,
|
||||
DrawerNavigationState,
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.25](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.24...@react-navigation/material-bottom-tabs@5.0.0-alpha.25) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.24](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.23...@react-navigation/material-bottom-tabs@5.0.0-alpha.24) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.23](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.22...@react-navigation/material-bottom-tabs@5.0.0-alpha.23) (2019-12-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
@@ -7,7 +7,7 @@ React Navigation integration for [bottom navigation](https://material.io/design/
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/material-bottom-tabs
|
||||
yarn add @react-navigation/native @react-navigation/material-bottom-tabs
|
||||
```
|
||||
|
||||
Setup `react-native-paper` following the [Getting Started guide](https://callstack.github.io/react-native-paper/getting-started.html).
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.23",
|
||||
"version": "5.0.0-alpha.25",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -34,7 +34,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
@@ -49,7 +49,7 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-paper": "^3.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
useNavigationBuilder,
|
||||
createNavigatorFactory,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
TabRouter,
|
||||
TabRouterOptions,
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
Descriptor,
|
||||
NavigationProp,
|
||||
NavigationHelpers,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import { TabNavigationState } from '@react-navigation/routers';
|
||||
|
||||
export type MaterialBottomTabNavigationEventMap = {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { BottomNavigation } from 'react-native-paper';
|
||||
import { BottomNavigation, DefaultTheme, DarkTheme } from 'react-native-paper';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import { TabNavigationState, TabActions } from '@react-navigation/routers';
|
||||
|
||||
import {
|
||||
@@ -25,9 +25,25 @@ export default function MaterialBottomTabView({
|
||||
descriptors,
|
||||
...rest
|
||||
}: Props) {
|
||||
const { dark, colors } = useTheme();
|
||||
|
||||
const theme = React.useMemo(() => {
|
||||
const t = dark ? DarkTheme : DefaultTheme;
|
||||
|
||||
return {
|
||||
...t,
|
||||
colors: {
|
||||
...t.colors,
|
||||
...colors,
|
||||
surface: colors.card,
|
||||
},
|
||||
};
|
||||
}, [colors, dark]);
|
||||
|
||||
return (
|
||||
<BottomNavigation
|
||||
{...rest}
|
||||
theme={theme}
|
||||
navigationState={state}
|
||||
onIndexChange={(index: number) =>
|
||||
navigation.dispatch({
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.23](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-top-tabs@5.0.0-alpha.22...@react-navigation/material-top-tabs@5.0.0-alpha.23) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.22](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-top-tabs@5.0.0-alpha.21...@react-navigation/material-top-tabs@5.0.0-alpha.22) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.21](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-top-tabs@5.0.0-alpha.20...@react-navigation/material-top-tabs@5.0.0-alpha.21) (2019-12-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
@@ -7,7 +7,7 @@ React Navigation integration for animated tab view component from [`react-native
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/material-top-tabs react-native-tab-view
|
||||
yarn add @react-navigation/native @react-navigation/material-top-tabs react-native-tab-view
|
||||
```
|
||||
|
||||
Now we need to install [`react-native-gesture-handler`](https://github.com/kmagiera/react-native-gesture-handler) and [`react-native-reanimated`](https://github.com/kmagiera/react-native-reanimated)..
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.21",
|
||||
"version": "5.0.0-alpha.23",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -34,7 +34,8 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16",
|
||||
"color": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
@@ -49,7 +50,7 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-gesture-handler": "^1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
useNavigationBuilder,
|
||||
createNavigatorFactory,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
TabRouter,
|
||||
TabRouterOptions,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
NavigationHelpers,
|
||||
Route,
|
||||
NavigationProp,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import { TabNavigationState } from '@react-navigation/routers';
|
||||
|
||||
export type MaterialTopTabNavigationEventMap = {
|
||||
|
||||
@@ -1,29 +1,46 @@
|
||||
import * as React from 'react';
|
||||
import { View, Text, StyleSheet } from 'react-native';
|
||||
import { TabBar } from 'react-native-tab-view';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import Color from 'color';
|
||||
|
||||
import { MaterialTopTabBarProps } from '../types';
|
||||
|
||||
export default function TabBarTop({
|
||||
state,
|
||||
navigation,
|
||||
descriptors,
|
||||
activeTintColor = 'rgba(255, 255, 255, 1)',
|
||||
inactiveTintColor = 'rgba(255, 255, 255, 0.7)',
|
||||
allowFontScaling = true,
|
||||
iconStyle,
|
||||
labelStyle,
|
||||
showIcon = false,
|
||||
showLabel = true,
|
||||
...rest
|
||||
}: MaterialTopTabBarProps) {
|
||||
export default function TabBarTop(props: MaterialTopTabBarProps) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
const {
|
||||
state,
|
||||
navigation,
|
||||
descriptors,
|
||||
activeTintColor = colors.text,
|
||||
inactiveTintColor = Color(activeTintColor)
|
||||
.alpha(0.5)
|
||||
.rgb()
|
||||
.string(),
|
||||
allowFontScaling = true,
|
||||
showIcon = false,
|
||||
showLabel = true,
|
||||
pressColor = Color(activeTintColor)
|
||||
.alpha(0.08)
|
||||
.rgb()
|
||||
.string(),
|
||||
iconStyle,
|
||||
labelStyle,
|
||||
indicatorStyle,
|
||||
style,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<TabBar
|
||||
{...rest}
|
||||
navigationState={state}
|
||||
activeColor={activeTintColor}
|
||||
inactiveColor={inactiveTintColor}
|
||||
indicatorStyle={[{ backgroundColor: colors.primary }, indicatorStyle]}
|
||||
style={[{ backgroundColor: colors.card }, style]}
|
||||
pressColor={pressColor}
|
||||
getAccessibilityLabel={({ route }) =>
|
||||
descriptors[route.key].options.tabBarAccessibilityLabel
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import { TabView, SceneRendererProps } from 'react-native-tab-view';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import { TabNavigationState, TabActions } from '@react-navigation/routers';
|
||||
|
||||
import MaterialTopTabBar from './MaterialTopTabBar';
|
||||
@@ -18,6 +19,16 @@ type Props = MaterialTopTabNavigationConfig & {
|
||||
tabBarPosition: 'top' | 'bottom';
|
||||
};
|
||||
|
||||
function SceneContent({ children }: { children: React.ReactNode }) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: colors.background }}>
|
||||
{children}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
export default class MaterialTopTabView extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
tabBarPosition: 'top',
|
||||
@@ -93,7 +104,9 @@ export default class MaterialTopTabView extends React.PureComponent<Props> {
|
||||
target: state.key,
|
||||
})
|
||||
}
|
||||
renderScene={({ route }) => descriptors[route.key].render()}
|
||||
renderScene={({ route }) => (
|
||||
<SceneContent>{descriptors[route.key].render()}</SceneContent>
|
||||
)}
|
||||
navigationState={state}
|
||||
renderTabBar={this.renderTabBar}
|
||||
renderLazyPlaceholder={this.renderLazyPlaceholder}
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native-stack@5.0.0-alpha.16...@react-navigation/native-stack@5.0.0-alpha.17) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.16](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native-stack@5.0.0-alpha.15...@react-navigation/native-stack@5.0.0-alpha.16) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native-stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.15](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native-stack@5.0.0-alpha.14...@react-navigation/native-stack@5.0.0-alpha.15) (2019-12-07)
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Expo is currently not supported as it includes an older version of `react-native
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/native-stack
|
||||
yarn add @react-navigation/native @react-navigation/native-stack
|
||||
```
|
||||
|
||||
Now we need to install [`react-native-screens`](https://github.com/kmagiera/react-native-screens).
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.15",
|
||||
"version": "5.0.0-alpha.17",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,7 +29,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
@@ -38,7 +38,7 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-screens": "^2.0.0-alpha.8"
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
createNavigatorFactory,
|
||||
useNavigationBuilder,
|
||||
EventArg,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
|
||||
import {
|
||||
StackRouter,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
NavigationHelpers,
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
StackNavigationState,
|
||||
StackRouterOptions,
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
ScreenStackHeaderRightView,
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
} from 'react-native-screens';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import { NativeStackNavigationOptions } from '../types';
|
||||
|
||||
type Props = NativeStackNavigationOptions & {
|
||||
@@ -14,6 +14,7 @@ type Props = NativeStackNavigationOptions & {
|
||||
};
|
||||
|
||||
export default function HeaderConfig(props: Props) {
|
||||
const { colors } = useTheme();
|
||||
const {
|
||||
route,
|
||||
title,
|
||||
@@ -52,17 +53,23 @@ export default function HeaderConfig(props: Props) {
|
||||
titleColor={
|
||||
headerTitleStyle.color !== undefined
|
||||
? headerTitleStyle.color
|
||||
: headerTintColor
|
||||
: headerTintColor !== undefined
|
||||
? headerTintColor
|
||||
: colors.text
|
||||
}
|
||||
backTitle={headerBackTitleVisible ? headerBackTitle : ''}
|
||||
backTitleFontFamily={headerBackTitleStyle.fontFamily}
|
||||
backTitleFontSize={headerBackTitleStyle.fontSize}
|
||||
color={headerTintColor}
|
||||
color={headerTintColor !== undefined ? headerTintColor : colors.primary}
|
||||
gestureEnabled={gestureEnabled === undefined ? true : gestureEnabled}
|
||||
largeTitle={headerLargeTitle}
|
||||
largeTitleFontFamily={headerLargeTitleStyle.fontFamily}
|
||||
largeTitleFontSize={headerLargeTitleStyle.fontSize}
|
||||
backgroundColor={headerStyle.backgroundColor}
|
||||
backgroundColor={
|
||||
headerStyle.backgroundColor !== undefined
|
||||
? headerStyle.backgroundColor
|
||||
: colors.card
|
||||
}
|
||||
>
|
||||
{headerRight !== undefined ? (
|
||||
<ScreenStackHeaderRightView>{headerRight()}</ScreenStackHeaderRightView>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ScreenProps,
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
} from 'react-native-screens';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
import HeaderConfig from './HeaderConfig';
|
||||
import {
|
||||
NativeStackNavigationHelpers,
|
||||
@@ -34,8 +35,10 @@ export default function NativeStackView({
|
||||
navigation,
|
||||
descriptors,
|
||||
}: Props) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<ScreenStack style={styles.scenes}>
|
||||
<ScreenStack style={styles.container}>
|
||||
{state.routes.map(route => {
|
||||
const { options, render: renderScene } = descriptors[route.key];
|
||||
const { presentation = 'push', animation, contentStyle } = options;
|
||||
@@ -55,7 +58,15 @@ export default function NativeStackView({
|
||||
}}
|
||||
>
|
||||
<HeaderConfig {...options} route={route} />
|
||||
<View style={[styles.content, contentStyle]}>{renderScene()}</View>
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
{ backgroundColor: colors.background },
|
||||
contentStyle,
|
||||
]}
|
||||
>
|
||||
{renderScene()}
|
||||
</View>
|
||||
</Screen>
|
||||
);
|
||||
})}
|
||||
@@ -64,11 +75,7 @@ export default function NativeStackView({
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
content: {
|
||||
flex: 1,
|
||||
backgroundColor: '#eee',
|
||||
},
|
||||
scenes: {
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.19](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native@5.0.0-alpha.18...@react-navigation/native@5.0.0-alpha.19) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.18](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native@5.0.0-alpha.17...@react-navigation/native@5.0.0-alpha.18) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native@5.0.0-alpha.16...@react-navigation/native@5.0.0-alpha.17) (2019-12-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
@@ -7,7 +7,7 @@ React Native integration for React Navigation
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/native
|
||||
yarn add @react-navigation/native
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"ios",
|
||||
"android"
|
||||
],
|
||||
"version": "5.0.0-alpha.17",
|
||||
"version": "5.0.0-alpha.19",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,6 +29,9 @@
|
||||
"prepare": "bob build",
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.27"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
"@types/react": "^16.9.11",
|
||||
@@ -39,7 +42,6 @@
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
},
|
||||
|
||||
@@ -4,7 +4,14 @@ import {
|
||||
NavigationContainerProps,
|
||||
NavigationContainerRef,
|
||||
} from '@react-navigation/core';
|
||||
import ThemeProvider from './theming/ThemeProvider';
|
||||
import DefaultTheme from './theming/DefaultTheme';
|
||||
import useBackButton from './useBackButton';
|
||||
import { Theme } from './types';
|
||||
|
||||
type Props = NavigationContainerProps & {
|
||||
theme?: Theme;
|
||||
};
|
||||
|
||||
/**
|
||||
* Container component which holds the navigation state
|
||||
@@ -13,11 +20,12 @@ import useBackButton from './useBackButton';
|
||||
*
|
||||
* @param props.initialState Initial state object for the navigation tree.
|
||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||
* @param props.theme Theme object for the navigators.
|
||||
* @param props.children Child elements to render the content.
|
||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||
*/
|
||||
const NavigationNativeContainer = React.forwardRef(function NativeContainer(
|
||||
props: NavigationContainerProps,
|
||||
{ theme = DefaultTheme, ...rest }: Props,
|
||||
ref: React.Ref<NavigationContainerRef>
|
||||
) {
|
||||
const refContainer = React.useRef<NavigationContainerRef>(null);
|
||||
@@ -27,11 +35,9 @@ const NavigationNativeContainer = React.forwardRef(function NativeContainer(
|
||||
React.useImperativeHandle(ref, () => refContainer.current);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
{...props}
|
||||
ref={refContainer}
|
||||
children={props.children}
|
||||
/>
|
||||
<ThemeProvider value={theme}>
|
||||
<NavigationContainer {...rest} ref={refContainer} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
export * from '@react-navigation/core';
|
||||
|
||||
export { default as NavigationNativeContainer } from './NavigationNativeContainer';
|
||||
|
||||
export { default as useBackButton } from './useBackButton';
|
||||
export { default as useLinking } from './useLinking';
|
||||
export { default as useScrollToTop } from './useScrollToTop';
|
||||
|
||||
export { default as DefaultTheme } from './theming/DefaultTheme';
|
||||
export { default as DarkTheme } from './theming/DarkTheme';
|
||||
export { default as ThemeProvider } from './theming/ThemeProvider';
|
||||
export { default as useTheme } from './theming/useTheme';
|
||||
|
||||
14
packages/native/src/theming/DarkTheme.tsx
Normal file
14
packages/native/src/theming/DarkTheme.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Theme } from '../types';
|
||||
|
||||
const DarkTheme: Theme = {
|
||||
dark: true,
|
||||
colors: {
|
||||
primary: 'rgb(10, 132, 255)',
|
||||
background: 'rgb(1, 1, 1)',
|
||||
card: 'rgb(18, 18, 18)',
|
||||
text: 'rgb(229, 229, 231)',
|
||||
border: 'rgb(39, 39, 41)',
|
||||
},
|
||||
};
|
||||
|
||||
export default DarkTheme;
|
||||
14
packages/native/src/theming/DefaultTheme.tsx
Normal file
14
packages/native/src/theming/DefaultTheme.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Theme } from '../types';
|
||||
|
||||
const DefaultTheme: Theme = {
|
||||
dark: false,
|
||||
colors: {
|
||||
primary: 'rgb(0, 122, 255)',
|
||||
background: 'rgb(242, 242, 242)',
|
||||
card: 'rgb(255, 255, 255)',
|
||||
text: 'rgb(28, 28, 30)',
|
||||
border: 'rgb(199, 199, 204)',
|
||||
},
|
||||
};
|
||||
|
||||
export default DefaultTheme;
|
||||
7
packages/native/src/theming/ThemeContext.tsx
Normal file
7
packages/native/src/theming/ThemeContext.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import DefaultTheme from './DefaultTheme';
|
||||
import { Theme } from '../types';
|
||||
|
||||
const ThemeContext = React.createContext<Theme>(DefaultTheme);
|
||||
|
||||
export default ThemeContext;
|
||||
14
packages/native/src/theming/ThemeProvider.tsx
Normal file
14
packages/native/src/theming/ThemeProvider.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import * as React from 'react';
|
||||
import ThemeContext from './ThemeContext';
|
||||
import { Theme } from '../types';
|
||||
|
||||
type Props = {
|
||||
value: Theme;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function ThemeProvider({ value, children }: Props) {
|
||||
return (
|
||||
<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
8
packages/native/src/theming/useTheme.tsx
Normal file
8
packages/native/src/theming/useTheme.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import ThemeContext from './ThemeContext';
|
||||
|
||||
export default function useTheme() {
|
||||
const theme = React.useContext(ThemeContext);
|
||||
|
||||
return theme;
|
||||
}
|
||||
10
packages/native/src/types.tsx
Normal file
10
packages/native/src/types.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
export type Theme = {
|
||||
dark: boolean;
|
||||
colors: {
|
||||
primary: string;
|
||||
background: string;
|
||||
card: string;
|
||||
text: string;
|
||||
border: string;
|
||||
};
|
||||
};
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.16](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/routers@5.0.0-alpha.15...@react-navigation/routers@5.0.0-alpha.16) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/routers
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.15](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/routers@5.0.0-alpha.14...@react-navigation/routers@5.0.0-alpha.15) (2019-11-17)
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ You probably don't need to use this package directly if you're not building cust
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/routers
|
||||
yarn add @react-navigation/routers
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -17,7 +17,7 @@ yarn add @react-navigation/core @react-navigation/routers
|
||||
A basic custom navigator bundling a router and a view looks like this:
|
||||
|
||||
```js
|
||||
import { createNavigatorFactory, useNavigationBuilder } from '@react-navigation/core';
|
||||
import { createNavigatorFactory, useNavigationBuilder } from '@react-navigation/native';
|
||||
import { StackRouter } from '@react-navigation/routers';
|
||||
|
||||
function StackNavigator({ initialRouteName, children, ...rest }) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.15",
|
||||
"version": "5.0.0-alpha.16",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,6 +29,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.27",
|
||||
"shortid": "^2.2.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -36,9 +37,6 @@
|
||||
"del-cli": "^3.0.0",
|
||||
"typescript": "^3.7.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/core": "^5.0.0-alpha.0"
|
||||
},
|
||||
"@react-native-community/bob": {
|
||||
"source": "src",
|
||||
"output": "lib",
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.44](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.43...@react-navigation/stack@5.0.0-alpha.44) (2019-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add custom theme support ([#211](https://github.com/react-navigation/navigation-ex/issues/211)) ([00fc616](https://github.com/react-navigation/navigation-ex/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.43](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.42...@react-navigation/stack@5.0.0-alpha.43) (2019-12-11)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.41...@react-navigation/stack@5.0.0-alpha.42) (2019-12-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* expose animation related values in context ([6cddb52](https://github.com/react-navigation/navigation-ex/commit/6cddb5238c0b1e37238c85c76e2ecb1f81517c19))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.40...@react-navigation/stack@5.0.0-alpha.41) (2019-12-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
@@ -7,7 +7,7 @@ Stack navigator for React Navigation.
|
||||
Open a Terminal in your project's folder and run,
|
||||
|
||||
```sh
|
||||
yarn add @react-navigation/core @react-navigation/stack @react-native-community/masked-view
|
||||
yarn add @react-navigation/native @react-navigation/stack @react-native-community/masked-view
|
||||
```
|
||||
|
||||
Now we need to install [`react-native-gesture-handler`](https://github.com/kmagiera/react-native-gesture-handler), [`react-native-reanimated`](https://github.com/kmagiera/react-native-reanimated), [`react-native-screens`](https://github.com/kmagiera/react-native-screens) and [`react-native-safe-area-context`](https://github.com/th3rdwave/react-native-safe-area-context).
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"stack"
|
||||
],
|
||||
"version": "5.0.0-alpha.41",
|
||||
"version": "5.0.0-alpha.44",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -33,7 +33,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.15"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.7.0",
|
||||
@@ -51,7 +51,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/masked-view": "^0.1.1",
|
||||
"@react-navigation/core": "^5.0.0-alpha.0",
|
||||
"@react-navigation/native": "^5.0.0-alpha.0",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-gesture-handler": "^1.0.0",
|
||||
|
||||
@@ -35,6 +35,7 @@ export {
|
||||
* Utilities
|
||||
*/
|
||||
export { default as StackGestureContext } from './utils/StackGestureContext';
|
||||
export { default as StackCardAnimationContext } from './utils/StackCardAnimationContext';
|
||||
|
||||
/**
|
||||
* Types
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
createNavigatorFactory,
|
||||
DefaultNavigatorOptions,
|
||||
EventArg,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import {
|
||||
StackRouter,
|
||||
StackRouterOptions,
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
Descriptor,
|
||||
Route,
|
||||
NavigationHelpers,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
|
||||
export type StackNavigationEventMap = {
|
||||
@@ -406,6 +406,10 @@ export type StackHeaderTitleProps = {
|
||||
* Whether title font should scale to respect Text Size accessibility settings.
|
||||
*/
|
||||
allowFontScaling?: boolean;
|
||||
/**
|
||||
* Tint color for the header.
|
||||
*/
|
||||
tintColor?: string;
|
||||
/**
|
||||
* Content of the title element. Usually the title string.
|
||||
*/
|
||||
@@ -468,6 +472,10 @@ export type StackCardInterpolationProps = {
|
||||
* Animated node representing whether the card is closing.
|
||||
*/
|
||||
closing: Animated.Node<0 | 1>;
|
||||
/**
|
||||
* Animated node representing whether the card is being swiped.
|
||||
*/
|
||||
swiping: Animated.Node<0 | 1>;
|
||||
/**
|
||||
* Animated node representing multiplier when direction is inverted.
|
||||
*/
|
||||
|
||||
6
packages/stack/src/utils/StackCardAnimationContext.tsx
Normal file
6
packages/stack/src/utils/StackCardAnimationContext.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { StackCardInterpolationProps } from '../types';
|
||||
|
||||
export default React.createContext<StackCardInterpolationProps | undefined>(
|
||||
undefined
|
||||
);
|
||||
@@ -8,45 +8,56 @@ import {
|
||||
LayoutChangeEvent,
|
||||
} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
import MaskedView from '../MaskedView';
|
||||
import TouchableItem from '../TouchableItem';
|
||||
import { StackHeaderLeftButtonProps } from '../../types';
|
||||
|
||||
type Props = StackHeaderLeftButtonProps & {
|
||||
tintColor: string;
|
||||
};
|
||||
type Props = StackHeaderLeftButtonProps;
|
||||
|
||||
type State = {
|
||||
fullLabelWidth?: number;
|
||||
};
|
||||
export default function HeaderBackButton({
|
||||
disabled,
|
||||
allowFontScaling,
|
||||
backImage,
|
||||
label,
|
||||
labelStyle,
|
||||
labelVisible = Platform.OS === 'ios',
|
||||
onLabelLayout,
|
||||
onPress,
|
||||
pressColorAndroid: customPressColorAndroid,
|
||||
screenLayout,
|
||||
tintColor: customTintColor,
|
||||
titleLayout,
|
||||
truncatedLabel = 'Back',
|
||||
}: Props) {
|
||||
const { dark, colors } = useTheme();
|
||||
|
||||
class HeaderBackButton extends React.Component<Props, State> {
|
||||
static defaultProps = {
|
||||
pressColorAndroid: 'rgba(0, 0, 0, .32)',
|
||||
tintColor: Platform.select({
|
||||
ios: '#037aff',
|
||||
web: '#5f6368',
|
||||
}),
|
||||
labelVisible: Platform.OS === 'ios',
|
||||
truncatedLabel: 'Back',
|
||||
};
|
||||
const [initialLabelWidth, setInitialLabelWidth] = React.useState<
|
||||
undefined | number
|
||||
>(undefined);
|
||||
|
||||
state: State = {};
|
||||
const tintColor =
|
||||
customTintColor !== undefined
|
||||
? customTintColor
|
||||
: Platform.select({
|
||||
ios: colors.primary,
|
||||
default: colors.text,
|
||||
});
|
||||
|
||||
private handleLabelLayout = (e: LayoutChangeEvent) => {
|
||||
const { onLabelLayout } = this.props;
|
||||
const pressColorAndroid =
|
||||
customPressColorAndroid !== undefined
|
||||
? customPressColorAndroid
|
||||
: dark
|
||||
? 'rgba(255, 255, 255, .32)'
|
||||
: 'rgba(0, 0, 0, .32)';
|
||||
|
||||
const handleLabelLayout = (e: LayoutChangeEvent) => {
|
||||
onLabelLayout && onLabelLayout(e);
|
||||
|
||||
this.setState({
|
||||
fullLabelWidth: e.nativeEvent.layout.x + e.nativeEvent.layout.width,
|
||||
});
|
||||
setInitialLabelWidth(e.nativeEvent.layout.x + e.nativeEvent.layout.width);
|
||||
};
|
||||
|
||||
private shouldTruncateLabel = () => {
|
||||
const { titleLayout, screenLayout, label } = this.props;
|
||||
const { fullLabelWidth: initialLabelWidth } = this.state;
|
||||
|
||||
const shouldTruncateLabel = () => {
|
||||
return (
|
||||
!label ||
|
||||
(initialLabelWidth &&
|
||||
@@ -56,9 +67,7 @@ class HeaderBackButton extends React.Component<Props, State> {
|
||||
);
|
||||
};
|
||||
|
||||
private renderBackImage = () => {
|
||||
const { backImage, labelVisible, tintColor } = this.props;
|
||||
|
||||
const renderBackImage = () => {
|
||||
if (backImage) {
|
||||
return backImage({ tintColor });
|
||||
} else {
|
||||
@@ -76,19 +85,8 @@ class HeaderBackButton extends React.Component<Props, State> {
|
||||
}
|
||||
};
|
||||
|
||||
private renderLabel() {
|
||||
const {
|
||||
label,
|
||||
truncatedLabel,
|
||||
allowFontScaling,
|
||||
labelVisible,
|
||||
backImage,
|
||||
labelStyle,
|
||||
tintColor,
|
||||
screenLayout,
|
||||
} = this.props;
|
||||
|
||||
const leftLabelText = this.shouldTruncateLabel() ? truncatedLabel : label;
|
||||
const renderLabel = () => {
|
||||
const leftLabelText = shouldTruncateLabel() ? truncatedLabel : label;
|
||||
|
||||
if (!labelVisible || leftLabelText === undefined) {
|
||||
return null;
|
||||
@@ -109,7 +107,7 @@ class HeaderBackButton extends React.Component<Props, State> {
|
||||
onLayout={
|
||||
// This measurement is used to determine if we should truncate the label when it doesn't fit
|
||||
// Only measure it when label is not truncated because we want the measurement of full label
|
||||
leftLabelText === label ? this.handleLabelLayout : undefined
|
||||
leftLabelText === label ? handleLabelLayout : undefined
|
||||
}
|
||||
style={[
|
||||
styles.label,
|
||||
@@ -145,42 +143,37 @@ class HeaderBackButton extends React.Component<Props, State> {
|
||||
{labelElement}
|
||||
</MaskedView>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private handlePress = () =>
|
||||
this.props.onPress && requestAnimationFrame(this.props.onPress);
|
||||
const handlePress = () => onPress && requestAnimationFrame(onPress);
|
||||
|
||||
render() {
|
||||
const { pressColorAndroid, label, disabled } = this.props;
|
||||
|
||||
return (
|
||||
<TouchableItem
|
||||
disabled={disabled}
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
accessibilityComponentType="button"
|
||||
accessibilityLabel={
|
||||
label && label !== 'Back' ? `${label}, back` : 'Go back'
|
||||
}
|
||||
accessibilityTraits="button"
|
||||
testID="header-back"
|
||||
delayPressIn={0}
|
||||
onPress={disabled ? undefined : this.handlePress}
|
||||
pressColor={pressColorAndroid}
|
||||
style={[styles.container, disabled && styles.disabled]}
|
||||
hitSlop={Platform.select({
|
||||
ios: undefined,
|
||||
default: { top: 16, right: 16, bottom: 16, left: 16 },
|
||||
})}
|
||||
borderless
|
||||
>
|
||||
<React.Fragment>
|
||||
{this.renderBackImage()}
|
||||
{this.renderLabel()}
|
||||
</React.Fragment>
|
||||
</TouchableItem>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<TouchableItem
|
||||
disabled={disabled}
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
accessibilityComponentType="button"
|
||||
accessibilityLabel={
|
||||
label && label !== 'Back' ? `${label}, back` : 'Go back'
|
||||
}
|
||||
accessibilityTraits="button"
|
||||
testID="header-back"
|
||||
delayPressIn={0}
|
||||
onPress={disabled ? undefined : handlePress}
|
||||
pressColor={pressColorAndroid}
|
||||
style={[styles.container, disabled && styles.disabled]}
|
||||
hitSlop={Platform.select({
|
||||
ios: undefined,
|
||||
default: { top: 16, right: 16, bottom: 16, left: 16 },
|
||||
})}
|
||||
borderless
|
||||
>
|
||||
<React.Fragment>
|
||||
{renderBackImage()}
|
||||
{renderLabel()}
|
||||
</React.Fragment>
|
||||
</TouchableItem>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -253,5 +246,3 @@ const styles = StyleSheet.create({
|
||||
transform: [{ scaleX: I18nManager.isRTL ? -1 : 1 }],
|
||||
},
|
||||
});
|
||||
|
||||
export default HeaderBackButton;
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet, Platform, ViewProps } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
export default function HeaderBackground({ style, ...rest }: ViewProps) {
|
||||
return <Animated.View style={[styles.container, style]} {...rest} />;
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.container,
|
||||
{
|
||||
backgroundColor: colors.card,
|
||||
borderBottomColor: colors.border,
|
||||
shadowColor: colors.border,
|
||||
},
|
||||
style,
|
||||
]}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'white',
|
||||
...Platform.select({
|
||||
android: {
|
||||
elevation: 4,
|
||||
},
|
||||
ios: {
|
||||
shadowColor: 'rgba(0, 0, 0, 0.3)',
|
||||
shadowOpacity: 0.85,
|
||||
shadowRadius: 0,
|
||||
shadowOffset: {
|
||||
@@ -25,7 +39,6 @@ const styles = StyleSheet.create({
|
||||
},
|
||||
default: {
|
||||
borderBottomWidth: StyleSheet.hairlineWidth,
|
||||
borderBottomColor: 'rgba(0, 0, 0, 0.20)',
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
NavigationContext,
|
||||
Route,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
} from '@react-navigation/native';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route } from '@react-navigation/native';
|
||||
import HeaderBackButton from './HeaderBackButton';
|
||||
import HeaderBackground from './HeaderBackground';
|
||||
import memoize from '../../utils/memoize';
|
||||
@@ -339,7 +339,8 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
||||
children: currentTitle,
|
||||
onLayout: this.handleTitleLayout,
|
||||
allowFontScaling: titleAllowFontScaling,
|
||||
style: [{ color: headerTintColor }, customTitleStyle],
|
||||
tintColor: headerTintColor,
|
||||
style: customTitleStyle,
|
||||
})}
|
||||
</Animated.View>
|
||||
{right ? (
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet, Platform, TextProps } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
|
||||
type Props = TextProps & {
|
||||
tintColor?: string;
|
||||
children?: string;
|
||||
};
|
||||
|
||||
export default function HeaderTitle({ style, ...rest }: Props) {
|
||||
export default function HeaderTitle({ tintColor, style, ...rest }: Props) {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<Animated.Text numberOfLines={1} {...rest} style={[styles.title, style]} />
|
||||
<Animated.Text
|
||||
numberOfLines={1}
|
||||
{...rest}
|
||||
style={[
|
||||
styles.title,
|
||||
{ color: tintColor === undefined ? colors.text : tintColor },
|
||||
style,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -17,17 +29,14 @@ const styles = StyleSheet.create({
|
||||
ios: {
|
||||
fontSize: 17,
|
||||
fontWeight: '600',
|
||||
color: 'rgba(0, 0, 0, .9)',
|
||||
},
|
||||
android: {
|
||||
fontSize: 20,
|
||||
fontWeight: '500',
|
||||
color: 'rgba(0, 0, 0, .9)',
|
||||
},
|
||||
default: {
|
||||
fontSize: 18,
|
||||
fontWeight: '500',
|
||||
color: '#3c4043',
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ import animate, { Binary } from './CardAnimation';
|
||||
import PointerEventsView from './PointerEventsView';
|
||||
import memoize from '../../utils/memoize';
|
||||
import StackGestureContext from '../../utils/StackGestureContext';
|
||||
import StackCardAnimationContext from '../../utils/StackCardAnimationContext';
|
||||
import {
|
||||
TransitionSpec,
|
||||
StackCardStyleInterpolator,
|
||||
@@ -645,6 +646,7 @@ export default class Card extends React.Component<Props> {
|
||||
current: { progress: current },
|
||||
next: next && { progress: next },
|
||||
closing: this.isClosing,
|
||||
swiping: this.isSwiping,
|
||||
inverted: this.inverted,
|
||||
layouts: {
|
||||
screen: layout,
|
||||
@@ -674,6 +676,36 @@ export default class Card extends React.Component<Props> {
|
||||
this.props.insets.left
|
||||
);
|
||||
|
||||
// Keep track of the animation context when deps changes.
|
||||
private getCardAnimationContext = memoize(
|
||||
(
|
||||
index: number,
|
||||
current: Animated.Node<number>,
|
||||
next: Animated.Node<number> | undefined,
|
||||
layout: Layout,
|
||||
insetTop: number,
|
||||
insetRight: number,
|
||||
insetBottom: number,
|
||||
insetLeft: number
|
||||
) => ({
|
||||
index,
|
||||
current: { progress: current },
|
||||
next: next && { progress: next },
|
||||
closing: this.isClosing,
|
||||
swiping: this.isSwiping,
|
||||
inverted: this.inverted,
|
||||
layouts: {
|
||||
screen: layout,
|
||||
},
|
||||
insets: {
|
||||
top: insetTop,
|
||||
right: insetRight,
|
||||
bottom: insetBottom,
|
||||
left: insetLeft,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
private gestureActivationCriteria() {
|
||||
const { layout, gestureDirection, gestureResponseDistance } = this.props;
|
||||
|
||||
@@ -757,6 +789,17 @@ export default class Card extends React.Component<Props> {
|
||||
);
|
||||
}
|
||||
|
||||
const animationContext = this.getCardAnimationContext(
|
||||
index,
|
||||
current,
|
||||
next,
|
||||
layout,
|
||||
insets.top,
|
||||
insets.right,
|
||||
insets.bottom,
|
||||
insets.left
|
||||
);
|
||||
|
||||
const {
|
||||
containerStyle,
|
||||
cardStyle,
|
||||
@@ -810,13 +853,11 @@ export default class Card extends React.Component<Props> {
|
||||
<PointerEventsView
|
||||
active={active}
|
||||
progress={this.props.current}
|
||||
style={[
|
||||
styles.content,
|
||||
transparent ? styles.transparent : styles.opaque,
|
||||
contentStyle,
|
||||
]}
|
||||
style={[styles.content, contentStyle]}
|
||||
>
|
||||
{children}
|
||||
<StackCardAnimationContext.Provider value={animationContext}>
|
||||
{children}
|
||||
</StackCardAnimationContext.Provider>
|
||||
</PointerEventsView>
|
||||
</Animated.View>
|
||||
</PanGestureHandler>
|
||||
@@ -860,10 +901,4 @@ const styles = StyleSheet.create({
|
||||
height: 3,
|
||||
shadowOffset: { width: 1, height: -1 },
|
||||
},
|
||||
transparent: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
opaque: {
|
||||
backgroundColor: '#eee',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||
import Card from './Card';
|
||||
import { Scene, Layout, StackHeaderMode, TransitionPreset } from '../../types';
|
||||
@@ -53,30 +53,58 @@ type Props = TransitionPreset & {
|
||||
floatingHeaderHeight: number;
|
||||
};
|
||||
|
||||
export default class CardContainer extends React.PureComponent<Props> {
|
||||
private handleOpen = () => {
|
||||
const { scene, onTransitionEnd, onOpenRoute } = this.props;
|
||||
|
||||
export default function CardContainer({
|
||||
active,
|
||||
cardOverlayEnabled,
|
||||
cardShadowEnabled,
|
||||
cardStyle,
|
||||
cardStyleInterpolator,
|
||||
cardTransparent,
|
||||
closing,
|
||||
current,
|
||||
floatingHeaderHeight,
|
||||
focused,
|
||||
gestureDirection,
|
||||
gestureEnabled,
|
||||
gestureResponseDistance,
|
||||
gestureVelocityImpact,
|
||||
getPreviousRoute,
|
||||
headerMode,
|
||||
headerShown,
|
||||
headerStyleInterpolator,
|
||||
headerTransparent,
|
||||
index,
|
||||
layout,
|
||||
onCloseRoute,
|
||||
onGoBack,
|
||||
onOpenRoute,
|
||||
onPageChangeCancel,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeStart,
|
||||
onTransitionEnd,
|
||||
onTransitionStart,
|
||||
previousScene,
|
||||
renderHeader,
|
||||
renderScene,
|
||||
safeAreaInsetBottom,
|
||||
safeAreaInsetLeft,
|
||||
safeAreaInsetRight,
|
||||
safeAreaInsetTop,
|
||||
scene,
|
||||
state,
|
||||
transitionSpec,
|
||||
}: Props) {
|
||||
const handleOpen = () => {
|
||||
onTransitionEnd && onTransitionEnd({ route: scene.route }, false);
|
||||
onOpenRoute({ route: scene.route });
|
||||
};
|
||||
|
||||
private handleClose = () => {
|
||||
const { scene, onTransitionEnd, onCloseRoute } = this.props;
|
||||
|
||||
const handleClose = () => {
|
||||
onTransitionEnd && onTransitionEnd({ route: scene.route }, true);
|
||||
onCloseRoute({ route: scene.route });
|
||||
};
|
||||
|
||||
private handleTransitionStart = ({ closing }: { closing: boolean }) => {
|
||||
const {
|
||||
scene,
|
||||
onTransitionStart,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeCancel,
|
||||
onGoBack,
|
||||
} = this.props;
|
||||
|
||||
const handleTransitionStart = ({ closing }: { closing: boolean }) => {
|
||||
if (closing) {
|
||||
onPageChangeConfirm && onPageChangeConfirm();
|
||||
} else {
|
||||
@@ -87,103 +115,70 @@ export default class CardContainer extends React.PureComponent<Props> {
|
||||
closing && onGoBack({ route: scene.route });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
index,
|
||||
layout,
|
||||
active,
|
||||
focused,
|
||||
closing,
|
||||
current,
|
||||
state,
|
||||
scene,
|
||||
previousScene,
|
||||
safeAreaInsetTop,
|
||||
safeAreaInsetRight,
|
||||
safeAreaInsetBottom,
|
||||
safeAreaInsetLeft,
|
||||
cardTransparent,
|
||||
cardOverlayEnabled,
|
||||
cardShadowEnabled,
|
||||
cardStyle,
|
||||
onPageChangeStart,
|
||||
onPageChangeCancel,
|
||||
gestureEnabled,
|
||||
gestureResponseDistance,
|
||||
gestureVelocityImpact,
|
||||
floatingHeaderHeight,
|
||||
headerShown,
|
||||
getPreviousRoute,
|
||||
headerMode,
|
||||
headerTransparent,
|
||||
renderHeader,
|
||||
renderScene,
|
||||
gestureDirection,
|
||||
transitionSpec,
|
||||
cardStyleInterpolator,
|
||||
headerStyleInterpolator,
|
||||
} = this.props;
|
||||
const insets = {
|
||||
top: safeAreaInsetTop,
|
||||
right: safeAreaInsetRight,
|
||||
bottom: safeAreaInsetBottom,
|
||||
left: safeAreaInsetLeft,
|
||||
};
|
||||
|
||||
const insets = {
|
||||
top: safeAreaInsetTop,
|
||||
right: safeAreaInsetRight,
|
||||
bottom: safeAreaInsetBottom,
|
||||
left: safeAreaInsetLeft,
|
||||
};
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<Card
|
||||
index={index}
|
||||
active={active}
|
||||
transparent={cardTransparent}
|
||||
gestureDirection={gestureDirection}
|
||||
layout={layout}
|
||||
insets={insets}
|
||||
current={current}
|
||||
next={scene.progress.next}
|
||||
closing={closing}
|
||||
onOpen={this.handleOpen}
|
||||
onClose={this.handleClose}
|
||||
overlayEnabled={cardOverlayEnabled}
|
||||
shadowEnabled={cardShadowEnabled}
|
||||
onTransitionStart={this.handleTransitionStart}
|
||||
onGestureBegin={onPageChangeStart}
|
||||
onGestureCanceled={onPageChangeCancel}
|
||||
gestureEnabled={gestureEnabled}
|
||||
gestureResponseDistance={gestureResponseDistance}
|
||||
gestureVelocityImpact={gestureVelocityImpact}
|
||||
transitionSpec={transitionSpec}
|
||||
styleInterpolator={cardStyleInterpolator}
|
||||
accessibilityElementsHidden={!focused}
|
||||
importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
|
||||
pointerEvents="box-none"
|
||||
containerStyle={
|
||||
headerMode === 'float' && !headerTransparent && headerShown !== false
|
||||
? { marginTop: floatingHeaderHeight }
|
||||
: null
|
||||
}
|
||||
contentStyle={cardStyle}
|
||||
style={StyleSheet.absoluteFill}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.scene}>
|
||||
{renderScene({ route: scene.route })}
|
||||
</View>
|
||||
{headerMode === 'screen'
|
||||
? renderHeader({
|
||||
mode: 'screen',
|
||||
layout,
|
||||
insets,
|
||||
scenes: [previousScene, scene],
|
||||
state,
|
||||
getPreviousRoute,
|
||||
styleInterpolator: headerStyleInterpolator,
|
||||
})
|
||||
: null}
|
||||
</View>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Card
|
||||
index={index}
|
||||
active={active}
|
||||
transparent={cardTransparent}
|
||||
gestureDirection={gestureDirection}
|
||||
layout={layout}
|
||||
insets={insets}
|
||||
current={current}
|
||||
next={scene.progress.next}
|
||||
closing={closing}
|
||||
onOpen={handleOpen}
|
||||
onClose={handleClose}
|
||||
overlayEnabled={cardOverlayEnabled}
|
||||
shadowEnabled={cardShadowEnabled}
|
||||
onTransitionStart={handleTransitionStart}
|
||||
onGestureBegin={onPageChangeStart}
|
||||
onGestureCanceled={onPageChangeCancel}
|
||||
gestureEnabled={gestureEnabled}
|
||||
gestureResponseDistance={gestureResponseDistance}
|
||||
gestureVelocityImpact={gestureVelocityImpact}
|
||||
transitionSpec={transitionSpec}
|
||||
styleInterpolator={cardStyleInterpolator}
|
||||
accessibilityElementsHidden={!focused}
|
||||
importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
|
||||
pointerEvents="box-none"
|
||||
containerStyle={
|
||||
headerMode === 'float' && !headerTransparent && headerShown !== false
|
||||
? { marginTop: floatingHeaderHeight }
|
||||
: null
|
||||
}
|
||||
contentStyle={[
|
||||
{
|
||||
backgroundColor: cardTransparent ? 'transparent' : colors.background,
|
||||
},
|
||||
cardStyle,
|
||||
]}
|
||||
style={StyleSheet.absoluteFill}
|
||||
>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.scene}>{renderScene({ route: scene.route })}</View>
|
||||
{headerMode === 'screen'
|
||||
? renderHeader({
|
||||
mode: 'screen',
|
||||
layout,
|
||||
insets,
|
||||
scenes: [previousScene, scene],
|
||||
state,
|
||||
getPreviousRoute,
|
||||
styleInterpolator: headerStyleInterpolator,
|
||||
})
|
||||
: null}
|
||||
</View>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
||||
@@ -11,7 +11,7 @@ import Animated from 'react-native-reanimated';
|
||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import * as Screens from 'react-native-screens'; // Import with * as to prevent getters being called
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route } from '@react-navigation/native';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
|
||||
import { getDefaultHeaderHeight } from '../Header/HeaderSegment';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
import { SafeAreaConsumer, EdgeInsets } from 'react-native-safe-area-context';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route } from '@react-navigation/native';
|
||||
import { StackActions, StackNavigationState } from '@react-navigation/routers';
|
||||
|
||||
import CardStack from './CardStack';
|
||||
|
||||
19
yarn.lock
19
yarn.lock
@@ -2721,6 +2721,25 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/cli-table/-/cli-table-0.3.0.tgz#f1857156bf5fd115c6a2db260ba0be1f8fc5671c"
|
||||
integrity sha512-QnZUISJJXyhyD6L1e5QwXDV/A5i2W1/gl6D6YMc8u0ncPepbv/B4w3S+izVvtAg60m6h+JP09+Y/0zF2mojlFQ==
|
||||
|
||||
"@types/color-convert@*":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-1.9.0.tgz#bfa8203e41e7c65471e9841d7e306a7cd8b5172d"
|
||||
integrity sha512-OKGEfULrvSL2VRbkl/gnjjgbbF7ycIlpSsX7Nkab4MOWi5XxmgBYvuiQ7lcCFY5cPDz7MUNaKgxte2VRmtr4Fg==
|
||||
dependencies:
|
||||
"@types/color-name" "*"
|
||||
|
||||
"@types/color-name@*":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
|
||||
|
||||
"@types/color@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/color/-/color-3.0.0.tgz#40f8a6bf2fd86e969876b339a837d8ff1b0a6e30"
|
||||
integrity sha512-5qqtNia+m2I0/85+pd2YzAXaTyKO8j+svirO5aN+XaQJ5+eZ8nx0jPtEWZLxCi50xwYsX10xUHetFzfb1WEs4Q==
|
||||
dependencies:
|
||||
"@types/color-convert" "*"
|
||||
|
||||
"@types/eslint-visitor-keys@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||
|
||||
Reference in New Issue
Block a user