docs: add basic example app

This commit is contained in:
osdnk
2019-08-07 21:34:48 +01:00
parent 217f15d925
commit d09f93614c
22 changed files with 820 additions and 170 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@@ -18,7 +18,9 @@
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.1",
"@expo/vector-icons": "10.0.3",
"expo": "^34.0.1",
"expo-asset": "4.0.0",
"react": "16.8.3",
"react-dom": "^16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",

View File

@@ -0,0 +1,62 @@
/* eslint-disable import/namespace, import/default */
import * as React from 'react';
import { MaterialIcons } from '@expo/vector-icons';
import createBottomTabNavigator from '@navigation-ex/bottom-tabs';
// @ts-ignore
import TouchableBounce from 'react-native/Libraries/Components/Touchable/TouchableBounce';
import Albums from '../Shared/Albums';
import Contacts from '../Shared/Contacts';
import Chat from '../Shared/Chat';
const getTabBarIcon = (name: string) => ({
tintColor,
horizontal,
}: {
tintColor: string;
horizontal: boolean;
}) => (
<MaterialIcons name={name} color={tintColor} size={horizontal ? 17 : 24} />
);
type BottomTabParams = {
albums: undefined;
contacts: undefined;
chat: undefined;
};
const BottomTabs = createBottomTabNavigator<BottomTabParams>();
export default function BottomTabsScreen() {
return (
<BottomTabs.Navigator>
<BottomTabs.Screen
name="chat"
component={Chat}
options={{
title: 'Chat',
tabBarIcon: getTabBarIcon('chat-bubble'),
tabBarButtonComponent: TouchableBounce,
}}
/>
<BottomTabs.Screen
name="contacts"
component={Contacts}
options={{
title: 'Contacts',
tabBarIcon: getTabBarIcon('contacts'),
tabBarButtonComponent: TouchableBounce,
}}
/>
<BottomTabs.Screen
name="albums"
component={Albums}
options={{
title: 'Albums',
tabBarIcon: getTabBarIcon('photo-album'),
tabBarButtonComponent: TouchableBounce,
}}
/>
</BottomTabs.Navigator>
);
}

View File

@@ -0,0 +1,54 @@
import * as React from 'react';
import { StyleSheet } from 'react-native';
import createMaterialTopTabNavigator from '@navigation-ex/material-top-tabs';
import Albums from '../Shared/Albums';
import Contacts from '../Shared/Contacts';
import Chat from '../Shared/Chat';
type MaterialTabParams = {
albums: undefined;
contacts: undefined;
chat: undefined;
};
const MaterialTabs = createMaterialTopTabNavigator<MaterialTabParams>();
export default function MaterialTabsScreen() {
return (
<MaterialTabs.Navigator
tabBarOptions={{
style: styles.tabBar,
labelStyle: styles.tabLabel,
indicatorStyle: styles.tabIndicator,
}}
>
<MaterialTabs.Screen
name="chat"
component={Chat}
options={{ title: 'Chat' }}
/>
<MaterialTabs.Screen
name="contacts"
component={Contacts}
options={{ title: 'Contacts' }}
/>
<MaterialTabs.Screen
name="albums"
component={Albums}
options={{ title: 'Albums' }}
/>
</MaterialTabs.Navigator>
);
}
const styles = StyleSheet.create({
tabBar: {
backgroundColor: 'white',
},
tabLabel: {
color: 'black',
},
tabIndicator: {
backgroundColor: 'tomato',
},
});

View File

@@ -0,0 +1,110 @@
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import { Button } from 'react-native-paper';
import { RouteProp, ParamListBase } from '@navigation-ex/core';
import createStackNavigator, {
StackNavigationProp,
} from '@navigation-ex/stack';
import Article from '../Shared/Article';
import Albums from '../Shared/Albums';
type SimpleStackParams = {
article: { author: string };
album: undefined;
};
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
const ArticleScreen = ({
navigation,
route,
}: {
navigation: SimpleStackNavigation;
route: RouteProp<SimpleStackParams, 'article'>;
}) => (
<React.Fragment>
<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>
<Article author={{ name: route.params.author }} />
</React.Fragment>
);
const AlbumsScreen = ({
navigation,
}: {
navigation: SimpleStackNavigation;
}) => (
<React.Fragment>
<View style={styles.buttons}>
<Button
mode="contained"
onPress={() => navigation.push('article', { author: 'Babel fish' })}
style={styles.button}
>
Push article
</Button>
<Button
mode="outlined"
onPress={() => navigation.goBack()}
style={styles.button}
>
Go back
</Button>
</View>
<Albums />
</React.Fragment>
);
const SimpleStack = createStackNavigator<SimpleStackParams>();
export default function SimpleStackScreen({
navigation,
}: {
navigation: StackNavigationProp<ParamListBase>;
}) {
navigation.setOptions({
header: null,
});
return (
<SimpleStack.Navigator>
<SimpleStack.Screen
name="article"
component={ArticleScreen}
options={({ route }) => ({
title: `Article by ${route.params.author}`,
})}
initialParams={{ author: 'Gandalf' }}
/>
<SimpleStack.Screen
name="album"
component={AlbumsScreen}
options={{ title: 'Album' }}
/>
</SimpleStack.Navigator>
);
}
const styles = StyleSheet.create({
buttons: {
flexDirection: 'row',
padding: 8,
},
button: {
margin: 8,
},
});

View File

@@ -0,0 +1,42 @@
import * as React from 'react';
import { Image, Dimensions, ScrollView, StyleSheet } from 'react-native';
const COVERS = [
require('../../assets/album-art-1.jpg'),
require('../../assets/album-art-2.jpg'),
require('../../assets/album-art-3.jpg'),
require('../../assets/album-art-4.jpg'),
require('../../assets/album-art-5.jpg'),
require('../../assets/album-art-6.jpg'),
require('../../assets/album-art-7.jpg'),
require('../../assets/album-art-8.jpg'),
];
export default class Albums extends React.Component {
render() {
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.content}
>
{COVERS.map((source, i) => (
<Image key={i} source={source} style={styles.cover} />
))}
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#343C46',
},
content: {
flexDirection: 'row',
flexWrap: 'wrap',
},
cover: {
width: '50%',
height: Dimensions.get('window').width / 2,
},
});

View File

@@ -0,0 +1,115 @@
import * as React from 'react';
import { View, Text, Image, ScrollView, StyleSheet } from 'react-native';
type Props = {
date: string;
author: {
name: string;
};
};
export default class Article extends React.Component<Props> {
static defaultProps = {
date: '1st Jan 2025',
author: {
name: 'Knowledge Bot',
},
};
render() {
const { date, author } = this.props;
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.content}
>
<View style={styles.author}>
<Image
style={styles.avatar}
source={require('../../assets/avatar-1.png')}
/>
<View style={styles.meta}>
<Text style={styles.name}>{author.name}</Text>
<Text style={styles.timestamp}>{date}</Text>
</View>
</View>
<Text style={styles.title}>Lorem Ipsum</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.
</Text>
<Image style={styles.image} source={require('../../assets/book.jpg')} />
<Text style={styles.paragraph}>
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}>
Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of &quot;de
Finibus Bonorum et Malorum&quot; (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, &quot;Lorem ipsum dolor sit amet..&quot;, comes from a line in
section 1.10.32.
</Text>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
},
content: {
paddingVertical: 16,
},
author: {
flexDirection: 'row',
marginVertical: 8,
marginHorizontal: 16,
},
meta: {
marginHorizontal: 8,
justifyContent: 'center',
},
name: {
color: '#000',
fontWeight: 'bold',
fontSize: 16,
lineHeight: 24,
},
timestamp: {
color: '#999',
fontSize: 14,
lineHeight: 21,
},
avatar: {
height: 48,
width: 48,
borderRadius: 24,
},
title: {
color: '#000',
fontWeight: 'bold',
fontSize: 36,
marginVertical: 8,
marginHorizontal: 16,
},
paragraph: {
color: '#000',
fontSize: 16,
lineHeight: 24,
marginVertical: 8,
marginHorizontal: 16,
},
image: {
width: '100%',
height: 200,
resizeMode: 'cover',
marginVertical: 8,
},
});

View File

@@ -0,0 +1,114 @@
import * as React from 'react';
import {
View,
Image,
Text,
TextInput,
ScrollView,
StyleSheet,
} from 'react-native';
const MESSAGES = [
'okay',
'sudo make me a sandwich',
'what? make it yourself',
'make me a sandwich',
];
export default class Chat extends React.Component {
render() {
return (
<View style={styles.container}>
<ScrollView
style={styles.inverted}
contentContainerStyle={styles.content}
>
{MESSAGES.map((text, i) => {
const odd = i % 2;
return (
<View
key={i}
style={[odd ? styles.odd : styles.even, styles.inverted]}
>
<Image
style={styles.avatar}
source={
odd
? require('../../assets/avatar-2.png')
: require('../../assets/avatar-1.png')
}
/>
<View
style={[styles.bubble, odd ? styles.received : styles.sent]}
>
<Text style={odd ? styles.receivedText : styles.sentText}>
{text}
</Text>
</View>
</View>
);
})}
</ScrollView>
<TextInput
style={styles.input}
placeholder="Write a message"
underlineColorAndroid="transparent"
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#eceff1',
},
inverted: {
transform: [{ scaleY: -1 }],
},
content: {
padding: 16,
},
even: {
flexDirection: 'row',
},
odd: {
flexDirection: 'row-reverse',
},
avatar: {
marginVertical: 8,
marginHorizontal: 6,
height: 40,
width: 40,
borderRadius: 20,
borderColor: 'rgba(0, 0, 0, .16)',
borderWidth: StyleSheet.hairlineWidth,
},
bubble: {
marginVertical: 8,
marginHorizontal: 6,
paddingVertical: 12,
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',
},
});

View File

@@ -0,0 +1,136 @@
import * as React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { FlatList } from 'react-native-gesture-handler';
type Item = { name: string; number: number };
const CONTACTS: Item[] = [
{ name: 'Marissa Castillo', number: 7766398169 },
{ name: 'Denzel Curry', number: 9394378449 },
{ name: 'Miles Ferguson', number: 8966872888 },
{ name: 'Desiree Webster', number: 6818656371 },
{ name: 'Samantha Young', number: 6538288534 },
{ name: 'Irene Hunter', number: 2932176249 },
{ name: 'Annie Ryan', number: 4718456627 },
{ name: 'Sasha Oliver', number: 9743195919 },
{ name: 'Jarrod Avila', number: 8339212305 },
{ name: 'Griffin Weaver', number: 6059349721 },
{ name: 'Emilee Moss', number: 7382905180 },
{ name: 'Angelique Oliver', number: 9689298436 },
{ name: 'Emanuel Little', number: 6673376805 },
{ name: 'Wayne Day', number: 6918839582 },
{ name: 'Lauren Reese', number: 4652613201 },
{ name: 'Kailey Ward', number: 2232609512 },
{ name: 'Gabrielle Newman', number: 2837997127 },
{ name: 'Luke Strickland', number: 8404732322 },
{ name: 'Payton Garza', number: 7916140875 },
{ name: 'Anna Moss', number: 3504954657 },
{ name: 'Kailey Vazquez', number: 3002136330 },
{ name: 'Jennifer Coleman', number: 5469629753 },
{ name: 'Cindy Casey', number: 8446175026 },
{ name: 'Dillon Doyle', number: 5614510703 },
{ name: 'Savannah Garcia', number: 5634775094 },
{ name: 'Kailey Hudson', number: 3289239675 },
{ name: 'Ariel Green', number: 2103492196 },
{ name: 'Weston Perez', number: 2984221823 },
{ name: 'Kari Juarez', number: 9502125065 },
{ name: 'Sara Sanders', number: 7696668206 },
{ name: 'Griffin Le', number: 3396937040 },
{ name: 'Fernando Valdez', number: 9124257306 },
{ name: 'Taylor Marshall', number: 9656072372 },
{ name: 'Elias Dunn', number: 9738536473 },
{ name: 'Diane Barrett', number: 6886824829 },
{ name: 'Samuel Freeman', number: 5523948094 },
{ name: 'Irene Garza', number: 2077694008 },
{ name: 'Devante Alvarez', number: 9897002645 },
{ name: 'Sydney Floyd', number: 6462897254 },
{ name: 'Toni Dixon', number: 3775448213 },
{ name: 'Anastasia Spencer', number: 4548212752 },
{ name: 'Reid Cortez', number: 6668056507 },
{ name: 'Ramon Duncan', number: 8889157751 },
{ name: 'Kenny Moreno', number: 5748219540 },
{ name: 'Shelby Craig', number: 9473708675 },
{ name: 'Jordyn Brewer', number: 7552277991 },
{ name: 'Tanya Walker', number: 4308189657 },
{ name: 'Nolan Figueroa', number: 9173443776 },
{ name: 'Sophia Gibbs', number: 6435942770 },
{ name: 'Vincent Sandoval', number: 2606111495 },
];
class ContactItem extends React.PureComponent<{
item: { name: string; number: number };
}> {
render() {
const { item } = this.props;
return (
<View style={styles.item}>
<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>
</View>
</View>
);
}
}
export default class Contacts extends React.Component {
private renderItem = ({ item }: { item: Item }) => (
<ContactItem item={item} />
);
private ItemSeparator = () => <View style={styles.separator} />;
render() {
return (
<FlatList
data={CONTACTS}
keyExtractor={(_, i) => String(i)}
renderItem={this.renderItem}
ItemSeparatorComponent={this.ItemSeparator}
/>
);
}
}
const styles = StyleSheet.create({
item: {
backgroundColor: 'white',
flexDirection: 'row',
alignItems: 'center',
padding: 8,
},
avatar: {
height: 36,
width: 36,
borderRadius: 18,
backgroundColor: '#e91e63',
alignItems: 'center',
justifyContent: 'center',
},
letter: {
color: 'white',
fontWeight: 'bold',
},
details: {
margin: 8,
},
name: {
fontWeight: 'bold',
fontSize: 14,
color: 'black',
},
number: {
fontSize: 12,
color: '#999',
},
separator: {
height: StyleSheet.hairlineWidth,
backgroundColor: 'rgba(0, 0, 0, .08)',
},
});

View File

@@ -0,0 +1,99 @@
import * as React from 'react';
import { View, Text, Image, ScrollView, StyleSheet } from 'react-native';
export default class Profile extends React.Component {
render() {
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.content}
>
<View style={styles.author}>
<Image
style={styles.avatar}
source={require('../../assets/avatar-1.png')}
/>
<View style={styles.meta}>
<Text style={styles.name}>Knowledge Bot</Text>
<Text style={styles.timestamp}>1st Jan 2025</Text>
</View>
</View>
<Text style={styles.title}>Lorem Ipsum</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.
</Text>
<Image style={styles.image} source={require('../../assets/book.jpg')} />
<Text style={styles.paragraph}>
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}>
Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of &quot;de
Finibus Bonorum et Malorum&quot; (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, &quot;Lorem ipsum dolor sit amet..&quot;, comes from a line in
section 1.10.32.
</Text>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
},
content: {
paddingVertical: 16,
},
author: {
flexDirection: 'row',
marginVertical: 8,
marginHorizontal: 16,
},
meta: {
marginHorizontal: 8,
justifyContent: 'center',
},
name: {
color: '#000',
fontWeight: 'bold',
fontSize: 16,
lineHeight: 24,
},
timestamp: {
color: '#999',
fontSize: 14,
lineHeight: 21,
},
avatar: {
height: 48,
width: 48,
borderRadius: 24,
},
title: {
color: '#000',
fontWeight: 'bold',
fontSize: 36,
marginVertical: 8,
marginHorizontal: 16,
},
paragraph: {
color: '#000',
fontSize: 16,
lineHeight: 24,
marginVertical: 8,
marginHorizontal: 16,
},
image: {
width: '100%',
height: 200,
resizeMode: 'cover',
marginVertical: 8,
},
});

View File

@@ -1,152 +1,45 @@
import * as React from 'react';
import {
View,
Text,
Platform,
AsyncStorage,
YellowBox,
StyleSheet,
} from 'react-native';
import { Button } from 'react-native-paper';
import {
NavigationContainer,
CompositeNavigationProp,
NavigationHelpers,
RouteProp,
InitialState,
useFocusEffect,
} from '@navigation-ex/core';
import { ScrollView, AsyncStorage, YellowBox } from 'react-native';
import { Appbar, List } from 'react-native-paper';
import { Asset } from 'expo-asset';
import { NavigationContainer, InitialState } from '@navigation-ex/core';
import createDrawerNavigator, {
DrawerNavigationProp,
} from '@navigation-ex/drawer';
import createStackNavigator, {
Assets as StackAssets,
StackNavigationProp,
} from '@navigation-ex/stack';
import createMaterialTopTabNavigator, {
MaterialTopTabNavigationProp,
} from '@navigation-ex/material-top-tabs';
type StackParamList = {
first: { author: string };
second: undefined;
third: undefined;
};
type TabParamList = {
fourth: undefined;
fifth: undefined;
};
import SimpleStackScreen from './Screens/SimpleStack';
import BottomTabsScreen from './Screens/BottomTabs';
import MaterialTabsScreen from './Screens/MaterialTabs';
YellowBox.ignoreWarnings(['Require cycle:', 'Warning: Async Storage']);
const Stack = createStackNavigator<StackParamList>();
const Tab = createMaterialTopTabNavigator<TabParamList>();
const First = ({
navigation,
route,
}: {
navigation: CompositeNavigationProp<
StackNavigationProp<StackParamList, 'first'>,
NavigationHelpers<TabParamList>
>;
route: RouteProp<StackParamList, 'first'>;
}) => {
const updateTitle = React.useCallback(() => {
if (Platform.OS !== 'web') {
return;
}
document.title = `${route.name} (${route.params.author})`;
return () => {
document.title = '';
};
}, [route.name, route.params.author]);
useFocusEffect(updateTitle);
return (
<View>
<Text style={styles.title}>First, {route.params.author}</Text>
<Button onPress={() => navigation.push('second')}>Push second</Button>
<Button onPress={() => navigation.push('third')}>Push third</Button>
<Button onPress={() => navigation.navigate('fourth')}>
Navigate to fourth
</Button>
<Button onPress={() => navigation.navigate('first', { author: 'John' })}>
Navigate with params
</Button>
<Button onPress={() => navigation.pop()}>Pop</Button>
</View>
);
type RootDrawerParamList = {
Root: undefined;
};
const Second = ({
navigation,
}: {
navigation: CompositeNavigationProp<
StackNavigationProp<StackParamList, 'second'>,
NavigationHelpers<TabParamList>
>;
}) => {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
const timer = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(timer);
}, []);
navigation.setOptions({
title: `Count ${count}`,
});
return (
<View>
<Text style={styles.title}>Second</Text>
<Button onPress={() => navigation.push('first', { author: 'Joel' })}>
Push first
</Button>
<Button onPress={() => navigation.pop()}>Pop</Button>
</View>
);
type RootStackParamList = {
Home: undefined;
} & {
[P in keyof typeof SCREENS]: undefined;
};
const Fourth = ({
navigation,
}: {
navigation: CompositeNavigationProp<
MaterialTopTabNavigationProp<TabParamList, 'fourth'>,
StackNavigationProp<StackParamList>
>;
}) => (
<View>
<Text style={styles.title}>Fourth</Text>
<Button onPress={() => navigation.jumpTo('fifth')}>Jump to fifth</Button>
<Button onPress={() => navigation.push('first', { author: 'Jake' })}>
Push first
</Button>
<Button onPress={() => navigation.goBack()}>Go back</Button>
</View>
);
const SCREENS = {
SimpleStack: { title: 'Simple Stack', component: SimpleStackScreen },
BottomTabs: { title: 'Bottom Tabs', component: BottomTabsScreen },
MaterialTabs: { title: 'Material Tabs', component: MaterialTabsScreen },
};
const Fifth = ({
navigation,
}: {
navigation: CompositeNavigationProp<
MaterialTopTabNavigationProp<TabParamList, 'fifth'>,
StackNavigationProp<StackParamList>
>;
}) => (
<View>
<Text style={styles.title}>Fifth</Text>
<Button onPress={() => navigation.jumpTo('fourth')}>Jump to fourth</Button>
<Button onPress={() => navigation.push('second')}>Push second</Button>
<Button onPress={() => navigation.pop()}>Pop</Button>
</View>
);
const Drawer = createDrawerNavigator<RootDrawerParamList>();
const Stack = createStackNavigator<RootStackParamList>();
const PERSISTENCE_KEY = 'NAVIGATION_STATE';
Asset.loadAsync(StackAssets);
export default function App() {
const [isReady, setIsReady] = React.useState(false);
const [initialState, setInitialState] = React.useState<
@@ -181,43 +74,58 @@ export default function App() {
AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))
}
>
<Stack.Navigator>
<Stack.Screen
name="first"
component={First}
options={({ route }) => ({
title: `Foo (${route.params ? route.params.author : ''})`,
})}
initialParams={{ author: 'Jane' }}
/>
<Stack.Screen name="second" options={{ title: 'Bar' }}>
{props => <Second {...props} />}
</Stack.Screen>
<Stack.Screen name="third" options={{ title: 'Baz' }}>
{() => (
<Tab.Navigator initialRouteName="fifth">
<Tab.Screen
name="fourth"
component={Fourth}
options={{ title: 'This' }}
/>
<Tab.Screen
name="fifth"
component={Fifth}
options={{ title: 'That' }}
/>
</Tab.Navigator>
<Drawer.Navigator>
<Drawer.Screen name="Root" options={{ title: 'Examples' }}>
{({
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 => (
<List.Item
key={name}
title={SCREENS[name].title}
onPress={() => navigation.push(name)}
/>
)
)}
</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.Navigator>
)}
</Stack.Screen>
</Stack.Navigator>
</Drawer.Screen>
</Drawer.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 8,
},
});

View File

@@ -1300,7 +1300,7 @@
resolved "https://registry.yarnpkg.com/@expo/traveling-fastlane-linux/-/traveling-fastlane-linux-1.9.11.tgz#a26a94c0e4b118130da27a7edb3410d67706b81b"
integrity sha512-xCHnqKfwWYygQfRbi9MGNSG28EHKDtzMB+QDklSH1GeD90TA0beAjlNF+Z+KPxj28s3WZlQr9yw1AqBS7aipcw==
"@expo/vector-icons@^10.0.2":
"@expo/vector-icons@10.0.3", "@expo/vector-icons@^10.0.2":
version "10.0.3"
resolved "https://registry.yarnpkg.com/@expo/vector-icons/-/vector-icons-10.0.3.tgz#9dec25cf6c29871f2bb1fe932029878c221f1f75"
integrity sha512-3iTdjnBlleddgcRGZV9JQXi+WRL3n2BehW48JOFv/mydx8BjHD0QAcYLOXGuwrcRKR0AIRhHxFQwKVyQ4YcYLA==
@@ -5572,6 +5572,14 @@ expo-app-loader-provider@~6.0.0:
resolved "https://registry.yarnpkg.com/expo-app-loader-provider/-/expo-app-loader-provider-6.0.0.tgz#c187a39942ac27cfaec3b394a5c9851d3f39678b"
integrity sha512-GtpztJVxOz+vVwdLyHskpzVzFWMXZPIFC/zczHZPsTwjS+wXj6n8MVaLxX6GaTyhNEtYjp0VIQUw3b7eP+vO6w==
expo-asset@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/expo-asset/-/expo-asset-4.0.0.tgz#41f8de836b0e1426dd4ae461cffbcaad0fdc4e15"
integrity sha512-oFIaq1V3D23wos3Lc1+3ABAAbXTytVDCXF0lTSDNsCEGHk+rt2WUedD0FL+RNw+C4zG7aqxI6cPaDNc+4lyKdA==
dependencies:
path-browserify "^1.0.0"
url-parse "^1.4.4"
expo-asset@~6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/expo-asset/-/expo-asset-6.0.0.tgz#caa3f45e7a27d978f8055fc58df6e33a4e661937"