expo-template-default 51.0.7 → 51.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/(tabs)/_layout.tsx +11 -18
- package/app/(tabs)/explore.tsx +51 -60
- package/app/(tabs)/index.tsx +22 -25
- package/app/+html.tsx +4 -7
- package/app/+not-found.tsx +7 -7
- package/app/_layout.tsx +8 -12
- package/components/Collapsible.tsx +40 -0
- package/components/ExternalLink.tsx +6 -6
- package/components/HelloWave.tsx +19 -24
- package/components/ParallaxScrollView.tsx +12 -17
- package/components/ThemedText.tsx +14 -20
- package/components/ThemedView.tsx +5 -8
- package/components/navigation/TabBarIcon.tsx +3 -3
- package/constants/Colors.ts +12 -12
- package/expo-env.d.ts +3 -0
- package/hooks/useColorScheme.ts +1 -1
- package/hooks/useColorScheme.web.ts +1 -1
- package/hooks/useThemeColor.ts +5 -5
- package/package.json +3 -3
- package/babel.config.js +0 -6
- package/components/Drawer.tsx +0 -54
package/app/(tabs)/_layout.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Tabs } from
|
|
2
|
-
import React from
|
|
1
|
+
import { Tabs } from 'expo-router';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
|
-
import { TabBarIcon } from
|
|
5
|
-
import { Colors } from
|
|
6
|
-
import { useColorScheme } from
|
|
4
|
+
import { TabBarIcon } from '@/components/navigation/TabBarIcon';
|
|
5
|
+
import { Colors } from '@/constants/Colors';
|
|
6
|
+
import { useColorScheme } from '@/hooks/useColorScheme';
|
|
7
7
|
|
|
8
8
|
export default function TabLayout() {
|
|
9
9
|
const colorScheme = useColorScheme();
|
|
@@ -11,31 +11,24 @@ export default function TabLayout() {
|
|
|
11
11
|
return (
|
|
12
12
|
<Tabs
|
|
13
13
|
screenOptions={{
|
|
14
|
-
tabBarActiveTintColor: Colors[colorScheme ??
|
|
14
|
+
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
|
15
15
|
headerShown: false,
|
|
16
|
-
}}
|
|
17
|
-
>
|
|
16
|
+
}}>
|
|
18
17
|
<Tabs.Screen
|
|
19
18
|
name="index"
|
|
20
19
|
options={{
|
|
21
|
-
title:
|
|
20
|
+
title: 'Home',
|
|
22
21
|
tabBarIcon: ({ color, focused }) => (
|
|
23
|
-
<TabBarIcon
|
|
24
|
-
name={focused ? "home" : "home-outline"}
|
|
25
|
-
color={color}
|
|
26
|
-
/>
|
|
22
|
+
<TabBarIcon name={focused ? 'home' : 'home-outline'} color={color} />
|
|
27
23
|
),
|
|
28
24
|
}}
|
|
29
25
|
/>
|
|
30
26
|
<Tabs.Screen
|
|
31
27
|
name="explore"
|
|
32
28
|
options={{
|
|
33
|
-
title:
|
|
29
|
+
title: 'Explore',
|
|
34
30
|
tabBarIcon: ({ color, focused }) => (
|
|
35
|
-
<TabBarIcon
|
|
36
|
-
name={focused ? "code-slash" : "code-slash-outline"}
|
|
37
|
-
color={color}
|
|
38
|
-
/>
|
|
31
|
+
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
|
|
39
32
|
),
|
|
40
33
|
}}
|
|
41
34
|
/>
|
package/app/(tabs)/explore.tsx
CHANGED
|
@@ -1,111 +1,102 @@
|
|
|
1
|
-
import Ionicons from
|
|
2
|
-
import { StyleSheet, Image, Platform } from
|
|
1
|
+
import Ionicons from '@expo/vector-icons/Ionicons';
|
|
2
|
+
import { StyleSheet, Image, Platform } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { ExternalLink } from
|
|
6
|
-
import ParallaxScrollView from
|
|
7
|
-
import { ThemedText } from
|
|
8
|
-
import { ThemedView } from
|
|
4
|
+
import { Collapsible } from '@/components/Collapsible';
|
|
5
|
+
import { ExternalLink } from '@/components/ExternalLink';
|
|
6
|
+
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
|
7
|
+
import { ThemedText } from '@/components/ThemedText';
|
|
8
|
+
import { ThemedView } from '@/components/ThemedView';
|
|
9
9
|
|
|
10
10
|
export default function TabTwoScreen() {
|
|
11
11
|
return (
|
|
12
12
|
<ParallaxScrollView
|
|
13
|
-
headerBackgroundColor={{ light:
|
|
14
|
-
headerImage={
|
|
15
|
-
<Ionicons size={310} name="code-slash" style={styles.headerImage} />
|
|
16
|
-
}
|
|
17
|
-
>
|
|
13
|
+
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
|
|
14
|
+
headerImage={<Ionicons size={310} name="code-slash" style={styles.headerImage} />}>
|
|
18
15
|
<ThemedView style={styles.titleContainer}>
|
|
19
16
|
<ThemedText type="title">Explore</ThemedText>
|
|
20
17
|
</ThemedView>
|
|
21
|
-
<ThemedText>
|
|
22
|
-
|
|
23
|
-
</ThemedText>
|
|
24
|
-
<Drawer title="File-based routing">
|
|
18
|
+
<ThemedText>This app includes example code to help you get started.</ThemedText>
|
|
19
|
+
<Collapsible title="File-based routing">
|
|
25
20
|
<ThemedText>
|
|
26
|
-
This app has two screens:{
|
|
27
|
-
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText>{
|
|
28
|
-
and{" "}
|
|
21
|
+
This app has two screens:{' '}
|
|
22
|
+
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> and{' '}
|
|
29
23
|
<ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText>
|
|
30
24
|
</ThemedText>
|
|
31
25
|
<ThemedText>
|
|
32
|
-
The layout file in{
|
|
33
|
-
<ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{" "}
|
|
26
|
+
The layout file in <ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{' '}
|
|
34
27
|
sets up the tab navigator.
|
|
35
28
|
</ThemedText>
|
|
36
29
|
<ExternalLink href="https://docs.expo.dev/router/introduction">
|
|
37
30
|
<ThemedText type="link">Learn more</ThemedText>
|
|
38
31
|
</ExternalLink>
|
|
39
|
-
</
|
|
40
|
-
<
|
|
32
|
+
</Collapsible>
|
|
33
|
+
<Collapsible title="Android, iOS, and web support">
|
|
41
34
|
<ThemedText>
|
|
42
|
-
You can open this project on Android, iOS, and the web. To open the web version, press
|
|
35
|
+
You can open this project on Android, iOS, and the web. To open the web version, press{' '}
|
|
36
|
+
<ThemedText type="defaultSemiBold">w</ThemedText> in the terminal running this project.
|
|
43
37
|
</ThemedText>
|
|
44
|
-
</
|
|
45
|
-
<
|
|
38
|
+
</Collapsible>
|
|
39
|
+
<Collapsible title="Images">
|
|
46
40
|
<ThemedText>
|
|
47
|
-
For static images, you can use the
|
|
48
|
-
<ThemedText type="defaultSemiBold">@
|
|
49
|
-
|
|
50
|
-
provide files for different screen densities
|
|
41
|
+
For static images, you can use the <ThemedText type="defaultSemiBold">@2x</ThemedText> and{' '}
|
|
42
|
+
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
|
43
|
+
different screen densities
|
|
51
44
|
</ThemedText>
|
|
52
|
-
<Image
|
|
53
|
-
source={require("@/assets/images/react-logo.png")}
|
|
54
|
-
style={{ alignSelf: "center" }}
|
|
55
|
-
/>
|
|
45
|
+
<Image source={require('@/assets/images/react-logo.png')} style={{ alignSelf: 'center' }} />
|
|
56
46
|
<ExternalLink href="https://reactnative.dev/docs/images">
|
|
57
47
|
<ThemedText type="link">Learn more</ThemedText>
|
|
58
48
|
</ExternalLink>
|
|
59
|
-
</
|
|
60
|
-
<
|
|
49
|
+
</Collapsible>
|
|
50
|
+
<Collapsible title="Custom fonts">
|
|
61
51
|
<ThemedText>
|
|
62
|
-
Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText>{
|
|
63
|
-
|
|
64
|
-
<ThemedText style={{ fontFamily: "SpaceMono" }}>
|
|
52
|
+
Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText> to see how to load{' '}
|
|
53
|
+
<ThemedText style={{ fontFamily: 'SpaceMono' }}>
|
|
65
54
|
custom fonts such as this one.
|
|
66
55
|
</ThemedText>
|
|
67
56
|
</ThemedText>
|
|
68
57
|
<ExternalLink href="https://docs.expo.dev/versions/latest/sdk/font">
|
|
69
58
|
<ThemedText type="link">Learn more</ThemedText>
|
|
70
59
|
</ExternalLink>
|
|
71
|
-
</
|
|
72
|
-
<
|
|
60
|
+
</Collapsible>
|
|
61
|
+
<Collapsible title="Light and dark mode components">
|
|
73
62
|
<ThemedText>
|
|
74
|
-
This template has light and dark mode support. The{
|
|
75
|
-
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook
|
|
76
|
-
|
|
77
|
-
can adjust UI colors accordingly.
|
|
63
|
+
This template has light and dark mode support. The{' '}
|
|
64
|
+
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook lets you inspect
|
|
65
|
+
what the user's current color scheme is, and so you can adjust UI colors accordingly.
|
|
78
66
|
</ThemedText>
|
|
79
67
|
<ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/">
|
|
80
68
|
<ThemedText type="link">Learn more</ThemedText>
|
|
81
69
|
</ExternalLink>
|
|
82
|
-
</
|
|
83
|
-
<
|
|
70
|
+
</Collapsible>
|
|
71
|
+
<Collapsible title="Animations">
|
|
84
72
|
<ThemedText>
|
|
85
|
-
This template includes an example of an animated component. The{
|
|
86
|
-
<ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component
|
|
87
|
-
|
|
88
|
-
|
|
73
|
+
This template includes an example of an animated component. The{' '}
|
|
74
|
+
<ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component uses
|
|
75
|
+
the <ThemedText type="defaultSemiBold">Animated</ThemedText> API to create a waving hand
|
|
76
|
+
animation.
|
|
89
77
|
</ThemedText>
|
|
90
|
-
{Platform.select({
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
78
|
+
{Platform.select({
|
|
79
|
+
ios: (
|
|
80
|
+
<ThemedText>
|
|
81
|
+
The <ThemedText type="defaultSemiBold">components/ParallaxScrollView.tsx</ThemedText>{' '}
|
|
82
|
+
component provides a parallax effect for the header image.
|
|
83
|
+
</ThemedText>
|
|
84
|
+
),
|
|
85
|
+
})}
|
|
86
|
+
</Collapsible>
|
|
96
87
|
</ParallaxScrollView>
|
|
97
88
|
);
|
|
98
89
|
}
|
|
99
90
|
|
|
100
91
|
const styles = StyleSheet.create({
|
|
101
92
|
headerImage: {
|
|
102
|
-
color:
|
|
93
|
+
color: '#808080',
|
|
103
94
|
bottom: -90,
|
|
104
95
|
left: -35,
|
|
105
|
-
position:
|
|
96
|
+
position: 'absolute',
|
|
106
97
|
},
|
|
107
98
|
titleContainer: {
|
|
108
|
-
flexDirection:
|
|
99
|
+
flexDirection: 'row',
|
|
109
100
|
gap: 8,
|
|
110
101
|
},
|
|
111
102
|
});
|
package/app/(tabs)/index.tsx
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
import { Image, StyleSheet, Platform } from
|
|
1
|
+
import { Image, StyleSheet, Platform } from 'react-native';
|
|
2
2
|
|
|
3
|
-
import ParallaxScrollView from
|
|
4
|
-
import { ThemedText } from
|
|
5
|
-
import { ThemedView } from
|
|
6
|
-
import { HelloWave } from
|
|
3
|
+
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
|
4
|
+
import { ThemedText } from '@/components/ThemedText';
|
|
5
|
+
import { ThemedView } from '@/components/ThemedView';
|
|
6
|
+
import { HelloWave } from '@/components/HelloWave';
|
|
7
7
|
|
|
8
8
|
export default function HomeScreen() {
|
|
9
9
|
return (
|
|
10
10
|
<ParallaxScrollView
|
|
11
|
-
headerBackgroundColor={{ light:
|
|
11
|
+
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
|
12
12
|
headerImage={
|
|
13
13
|
<Image
|
|
14
|
-
source={require(
|
|
14
|
+
source={require('@/assets/images/partial-react-logo.png')}
|
|
15
15
|
style={styles.reactLogo}
|
|
16
16
|
/>
|
|
17
|
-
}
|
|
18
|
-
>
|
|
17
|
+
}>
|
|
19
18
|
<ThemedView style={styles.titleContainer}>
|
|
20
19
|
<ThemedText type="title">Welcome!</ThemedText>
|
|
21
20
|
<HelloWave />
|
|
@@ -23,29 +22,27 @@ export default function HomeScreen() {
|
|
|
23
22
|
<ThemedView style={styles.stepContainer}>
|
|
24
23
|
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
|
25
24
|
<ThemedText>
|
|
26
|
-
Edit
|
|
27
|
-
|
|
28
|
-
to see changes. Press{" "}
|
|
25
|
+
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
|
26
|
+
Press{' '}
|
|
29
27
|
<ThemedText type="defaultSemiBold">
|
|
30
|
-
{Platform.select({ ios:
|
|
31
|
-
|
|
28
|
+
{Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
|
|
29
|
+
</ThemedText>{' '}
|
|
30
|
+
to open developer tools.
|
|
32
31
|
</ThemedText>
|
|
33
32
|
</ThemedView>
|
|
34
33
|
<ThemedView style={styles.stepContainer}>
|
|
35
34
|
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
|
36
35
|
<ThemedText>
|
|
37
|
-
Tap the Explore tab to learn more about what's included in this
|
|
38
|
-
starter app.
|
|
36
|
+
Tap the Explore tab to learn more about what's included in this starter app.
|
|
39
37
|
</ThemedText>
|
|
40
38
|
</ThemedView>
|
|
41
39
|
<ThemedView style={styles.stepContainer}>
|
|
42
40
|
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
|
43
41
|
<ThemedText>
|
|
44
|
-
When you're ready, run{
|
|
45
|
-
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText>{
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<ThemedText type="defaultSemiBold">app</ThemedText> to{" "}
|
|
42
|
+
When you're ready, run{' '}
|
|
43
|
+
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
|
44
|
+
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
|
45
|
+
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
|
49
46
|
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
|
50
47
|
</ThemedText>
|
|
51
48
|
</ThemedView>
|
|
@@ -55,8 +52,8 @@ export default function HomeScreen() {
|
|
|
55
52
|
|
|
56
53
|
const styles = StyleSheet.create({
|
|
57
54
|
titleContainer: {
|
|
58
|
-
flexDirection:
|
|
59
|
-
alignItems:
|
|
55
|
+
flexDirection: 'row',
|
|
56
|
+
alignItems: 'center',
|
|
60
57
|
gap: 8,
|
|
61
58
|
},
|
|
62
59
|
stepContainer: {
|
|
@@ -65,8 +62,8 @@ const styles = StyleSheet.create({
|
|
|
65
62
|
reactLogo: {
|
|
66
63
|
height: 178,
|
|
67
64
|
width: 290,
|
|
68
|
-
bottom:0,
|
|
65
|
+
bottom: 0,
|
|
69
66
|
left: 0,
|
|
70
|
-
position:
|
|
67
|
+
position: 'absolute',
|
|
71
68
|
},
|
|
72
69
|
});
|
package/app/+html.tsx
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
import { ScrollViewStyleReset } from
|
|
2
|
-
import { type PropsWithChildren } from
|
|
1
|
+
import { ScrollViewStyleReset } from 'expo-router/html';
|
|
2
|
+
import { type PropsWithChildren } from 'react';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* This file is web-only and used to configure the root HTML for every web page during static rendering.
|
|
6
6
|
* The contents of this function only run in Node.js environments and do not have access to the DOM or browser APIs.
|
|
7
|
-
*/
|
|
7
|
+
*/
|
|
8
8
|
export default function Root({ children }: PropsWithChildren) {
|
|
9
9
|
return (
|
|
10
10
|
<html lang="en">
|
|
11
11
|
<head>
|
|
12
12
|
<meta charSet="utf-8" />
|
|
13
13
|
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
|
14
|
-
<meta
|
|
15
|
-
name="viewport"
|
|
16
|
-
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
|
17
|
-
/>
|
|
14
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
|
18
15
|
|
|
19
16
|
{/*
|
|
20
17
|
Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
|
package/app/+not-found.tsx
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Link, Stack } from
|
|
2
|
-
import { StyleSheet } from
|
|
1
|
+
import { Link, Stack } from 'expo-router';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
3
|
|
|
4
|
-
import { ThemedText } from
|
|
5
|
-
import { ThemedView } from
|
|
4
|
+
import { ThemedText } from '@/components/ThemedText';
|
|
5
|
+
import { ThemedView } from '@/components/ThemedView';
|
|
6
6
|
|
|
7
7
|
export default function NotFoundScreen() {
|
|
8
8
|
return (
|
|
9
9
|
<>
|
|
10
|
-
<Stack.Screen options={{ title:
|
|
10
|
+
<Stack.Screen options={{ title: 'Oops!' }} />
|
|
11
11
|
<ThemedView style={styles.container}>
|
|
12
12
|
<ThemedText type="title">This screen doesn't exist.</ThemedText>
|
|
13
13
|
<Link href="/" style={styles.link}>
|
|
@@ -21,8 +21,8 @@ export default function NotFoundScreen() {
|
|
|
21
21
|
const styles = StyleSheet.create({
|
|
22
22
|
container: {
|
|
23
23
|
flex: 1,
|
|
24
|
-
alignItems:
|
|
25
|
-
justifyContent:
|
|
24
|
+
alignItems: 'center',
|
|
25
|
+
justifyContent: 'center',
|
|
26
26
|
padding: 20,
|
|
27
27
|
},
|
|
28
28
|
link: {
|
package/app/_layout.tsx
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from
|
|
6
|
-
import { useFonts } from "expo-font";
|
|
7
|
-
import { Stack } from "expo-router";
|
|
8
|
-
import * as SplashScreen from "expo-splash-screen";
|
|
9
|
-
import { useEffect } from "react";
|
|
1
|
+
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
|
|
2
|
+
import { useFonts } from 'expo-font';
|
|
3
|
+
import { Stack } from 'expo-router';
|
|
4
|
+
import * as SplashScreen from 'expo-splash-screen';
|
|
5
|
+
import { useEffect } from 'react';
|
|
10
6
|
|
|
11
|
-
import { useColorScheme } from
|
|
7
|
+
import { useColorScheme } from '@/hooks/useColorScheme';
|
|
12
8
|
|
|
13
9
|
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
|
14
10
|
SplashScreen.preventAutoHideAsync();
|
|
@@ -16,7 +12,7 @@ SplashScreen.preventAutoHideAsync();
|
|
|
16
12
|
export default function RootLayout() {
|
|
17
13
|
const colorScheme = useColorScheme();
|
|
18
14
|
const [loaded] = useFonts({
|
|
19
|
-
SpaceMono: require(
|
|
15
|
+
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
|
|
20
16
|
});
|
|
21
17
|
|
|
22
18
|
useEffect(() => {
|
|
@@ -30,7 +26,7 @@ export default function RootLayout() {
|
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
return (
|
|
33
|
-
<ThemeProvider value={colorScheme ===
|
|
29
|
+
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
|
34
30
|
<Stack>
|
|
35
31
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
36
32
|
<Stack.Screen name="+not-found" />
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import Ionicons from '@expo/vector-icons/Ionicons';
|
|
2
|
+
import { PropsWithChildren, useState } from 'react';
|
|
3
|
+
import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { ThemedText } from '@/components/ThemedText';
|
|
6
|
+
import { ThemedView } from '@/components/ThemedView';
|
|
7
|
+
import { Colors } from '@/constants/Colors';
|
|
8
|
+
|
|
9
|
+
export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
|
|
10
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
11
|
+
const theme = useColorScheme() ?? 'light';
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<ThemedView>
|
|
15
|
+
<TouchableOpacity
|
|
16
|
+
style={styles.heading}
|
|
17
|
+
onPress={() => setIsOpen((value) => !value)}
|
|
18
|
+
activeOpacity={0.8}>
|
|
19
|
+
<Ionicons
|
|
20
|
+
name={isOpen ? 'chevron-down' : 'chevron-forward-outline'}
|
|
21
|
+
size={18}
|
|
22
|
+
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon}
|
|
23
|
+
/>
|
|
24
|
+
<ThemedText type="defaultSemiBold">{title}</ThemedText>
|
|
25
|
+
</TouchableOpacity>
|
|
26
|
+
<ThemedView style={styles.content}>{isOpen ? children : null}</ThemedView>
|
|
27
|
+
</ThemedView>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const styles = StyleSheet.create({
|
|
32
|
+
heading: {
|
|
33
|
+
flexDirection: 'row',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
gap: 4,
|
|
36
|
+
},
|
|
37
|
+
content: {
|
|
38
|
+
marginLeft: 24,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Link } from
|
|
2
|
-
import * as WebBrowser from
|
|
3
|
-
import React from
|
|
4
|
-
import { Platform } from
|
|
1
|
+
import { Link } from 'expo-router';
|
|
2
|
+
import * as WebBrowser from 'expo-web-browser';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Platform } from 'react-native';
|
|
5
5
|
|
|
6
6
|
export function ExternalLink(
|
|
7
|
-
props: Omit<React.ComponentProps<typeof Link>,
|
|
7
|
+
props: Omit<React.ComponentProps<typeof Link>, 'href'> & { href: string }
|
|
8
8
|
) {
|
|
9
9
|
return (
|
|
10
10
|
<Link
|
|
@@ -13,7 +13,7 @@ export function ExternalLink(
|
|
|
13
13
|
// @ts-expect-error: External URLs are not typed.
|
|
14
14
|
href={props.href}
|
|
15
15
|
onPress={(e) => {
|
|
16
|
-
if (Platform.OS !==
|
|
16
|
+
if (Platform.OS !== 'web') {
|
|
17
17
|
// Prevent the default behavior of linking to the default browser on native.
|
|
18
18
|
e.preventDefault();
|
|
19
19
|
// Open the link in an in-app browser.
|
package/components/HelloWave.tsx
CHANGED
|
@@ -1,33 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import Animated, {
|
|
3
|
+
useSharedValue,
|
|
4
|
+
useAnimatedStyle,
|
|
5
|
+
withTiming,
|
|
6
|
+
withRepeat,
|
|
7
|
+
withSequence,
|
|
8
|
+
} from 'react-native-reanimated';
|
|
3
9
|
|
|
4
|
-
import { ThemedText } from
|
|
10
|
+
import { ThemedText } from '@/components/ThemedText';
|
|
5
11
|
|
|
6
12
|
export function HelloWave() {
|
|
7
|
-
const
|
|
13
|
+
const rotationAnimation = useSharedValue(0);
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
duration: 150,
|
|
14
|
-
useNativeDriver: true,
|
|
15
|
-
}),
|
|
16
|
-
Animated.timing(rotateAnimation, {
|
|
17
|
-
toValue: 0,
|
|
18
|
-
duration: 150,
|
|
19
|
-
useNativeDriver: true,
|
|
20
|
-
}),
|
|
21
|
-
]), { iterations: 4 }).start();
|
|
22
|
-
}, [rotateAnimation]);
|
|
15
|
+
rotationAnimation.value = withRepeat(
|
|
16
|
+
withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
|
|
17
|
+
4 // Run the animation 4 times
|
|
18
|
+
);
|
|
23
19
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
});
|
|
20
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
21
|
+
transform: [{ rotate: `${rotationAnimation.value}deg` }],
|
|
22
|
+
}));
|
|
28
23
|
|
|
29
24
|
return (
|
|
30
|
-
<Animated.View style={
|
|
25
|
+
<Animated.View style={animatedStyle}>
|
|
31
26
|
<ThemedText style={styles.text}>👋</ThemedText>
|
|
32
27
|
</Animated.View>
|
|
33
28
|
);
|
|
@@ -37,6 +32,6 @@ const styles = StyleSheet.create({
|
|
|
37
32
|
text: {
|
|
38
33
|
fontSize: 28,
|
|
39
34
|
lineHeight: 32,
|
|
40
|
-
marginTop: -6
|
|
35
|
+
marginTop: -6,
|
|
41
36
|
},
|
|
42
37
|
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { PropsWithChildren } from
|
|
2
|
-
import { StyleSheet, useColorScheme } from
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { StyleSheet, useColorScheme } from 'react-native';
|
|
3
3
|
import Animated, {
|
|
4
4
|
interpolate,
|
|
5
5
|
useAnimatedRef,
|
|
6
6
|
useAnimatedStyle,
|
|
7
7
|
useScrollViewOffset,
|
|
8
|
-
} from
|
|
8
|
+
} from 'react-native-reanimated';
|
|
9
9
|
|
|
10
|
-
import { ThemedView } from
|
|
10
|
+
import { ThemedView } from '@/components/ThemedView';
|
|
11
11
|
|
|
12
12
|
const HEADER_HEIGHT = 250;
|
|
13
13
|
|
|
@@ -19,7 +19,7 @@ export default function ParallaxScrollView({
|
|
|
19
19
|
headerImage: React.ReactElement;
|
|
20
20
|
headerBackgroundColor: { dark: string; light: string };
|
|
21
21
|
}>) {
|
|
22
|
-
const colorScheme = useColorScheme() ||
|
|
22
|
+
const colorScheme = useColorScheme() || 'light';
|
|
23
23
|
const scrollRef = useAnimatedRef<Animated.ScrollView>();
|
|
24
24
|
const scrollOffset = useScrollViewOffset(scrollRef);
|
|
25
25
|
|
|
@@ -30,15 +30,11 @@ export default function ParallaxScrollView({
|
|
|
30
30
|
translateY: interpolate(
|
|
31
31
|
scrollOffset.value,
|
|
32
32
|
[-HEADER_HEIGHT, 0, HEADER_HEIGHT],
|
|
33
|
-
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
|
|
33
|
+
[-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
|
|
34
34
|
),
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
|
-
scale: interpolate(
|
|
38
|
-
scrollOffset.value,
|
|
39
|
-
[-HEADER_HEIGHT, 0, HEADER_HEIGHT],
|
|
40
|
-
[2, 1, 1],
|
|
41
|
-
),
|
|
37
|
+
scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
|
|
42
38
|
},
|
|
43
39
|
],
|
|
44
40
|
};
|
|
@@ -52,8 +48,7 @@ export default function ParallaxScrollView({
|
|
|
52
48
|
styles.header,
|
|
53
49
|
{ backgroundColor: headerBackgroundColor[colorScheme] },
|
|
54
50
|
headerAnimatedStyle,
|
|
55
|
-
]}
|
|
56
|
-
>
|
|
51
|
+
]}>
|
|
57
52
|
{headerImage}
|
|
58
53
|
</Animated.View>
|
|
59
54
|
<ThemedView style={styles.content}>{children}</ThemedView>
|
|
@@ -68,14 +63,14 @@ const styles = StyleSheet.create({
|
|
|
68
63
|
},
|
|
69
64
|
header: {
|
|
70
65
|
height: 250,
|
|
71
|
-
overflow:
|
|
66
|
+
overflow: 'hidden',
|
|
72
67
|
},
|
|
73
68
|
content: {
|
|
74
69
|
flex: 1,
|
|
75
70
|
padding: 32,
|
|
76
71
|
gap: 24,
|
|
77
72
|
borderRadius: 16,
|
|
78
|
-
overflow:
|
|
79
|
-
marginTop: -12
|
|
80
|
-
}
|
|
73
|
+
overflow: 'hidden',
|
|
74
|
+
marginTop: -12,
|
|
75
|
+
},
|
|
81
76
|
});
|
|
@@ -1,31 +1,25 @@
|
|
|
1
|
-
import { Text, StyleSheet } from
|
|
1
|
+
import { Text, StyleSheet } from 'react-native';
|
|
2
2
|
|
|
3
|
-
import { useThemeColor } from
|
|
3
|
+
import { useThemeColor } from '@/hooks/useThemeColor';
|
|
4
4
|
|
|
5
5
|
export type TextProps = {
|
|
6
6
|
lightColor?: string;
|
|
7
7
|
darkColor?: string;
|
|
8
|
-
} & { type?:
|
|
8
|
+
} & { type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link' } & Text['props'];
|
|
9
9
|
|
|
10
10
|
export function ThemedText(props: TextProps) {
|
|
11
|
-
const {
|
|
12
|
-
|
|
13
|
-
lightColor,
|
|
14
|
-
darkColor,
|
|
15
|
-
type = "default",
|
|
16
|
-
...otherProps
|
|
17
|
-
} = props;
|
|
18
|
-
const color = useThemeColor({ light: lightColor, dark: darkColor }, "text");
|
|
11
|
+
const { style, lightColor, darkColor, type = 'default', ...otherProps } = props;
|
|
12
|
+
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
|
|
19
13
|
|
|
20
14
|
return (
|
|
21
15
|
<Text
|
|
22
16
|
style={[
|
|
23
17
|
{ color },
|
|
24
|
-
type ===
|
|
25
|
-
type ===
|
|
26
|
-
type ===
|
|
27
|
-
type ===
|
|
28
|
-
type ===
|
|
18
|
+
type === 'default' ? styles.default : undefined,
|
|
19
|
+
type === 'title' ? styles.title : undefined,
|
|
20
|
+
type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined,
|
|
21
|
+
type === 'subtitle' ? styles.subtitle : undefined,
|
|
22
|
+
type === 'link' ? styles.link : undefined,
|
|
29
23
|
style,
|
|
30
24
|
]}
|
|
31
25
|
{...otherProps}
|
|
@@ -41,20 +35,20 @@ const styles = StyleSheet.create({
|
|
|
41
35
|
defaultSemiBold: {
|
|
42
36
|
fontSize: 16,
|
|
43
37
|
lineHeight: 24,
|
|
44
|
-
fontWeight:
|
|
38
|
+
fontWeight: '600',
|
|
45
39
|
},
|
|
46
40
|
title: {
|
|
47
41
|
fontSize: 32,
|
|
48
|
-
fontWeight:
|
|
42
|
+
fontWeight: 'bold',
|
|
49
43
|
lineHeight: 32,
|
|
50
44
|
},
|
|
51
45
|
subtitle: {
|
|
52
46
|
fontSize: 20,
|
|
53
|
-
fontWeight:
|
|
47
|
+
fontWeight: 'bold',
|
|
54
48
|
},
|
|
55
49
|
link: {
|
|
56
50
|
lineHeight: 30,
|
|
57
51
|
fontSize: 16,
|
|
58
|
-
color:
|
|
52
|
+
color: '#2e78b7',
|
|
59
53
|
},
|
|
60
54
|
});
|
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
import { View } from
|
|
1
|
+
import { View } from 'react-native';
|
|
2
2
|
|
|
3
|
-
import { useThemeColor } from
|
|
3
|
+
import { useThemeColor } from '@/hooks/useThemeColor';
|
|
4
4
|
|
|
5
5
|
export type ViewProps = {
|
|
6
6
|
lightColor?: string;
|
|
7
7
|
darkColor?: string;
|
|
8
|
-
} & View[
|
|
8
|
+
} & View['props'];
|
|
9
9
|
|
|
10
10
|
export function ThemedView(props: ViewProps) {
|
|
11
11
|
const { style, lightColor, darkColor, ...otherProps } = props;
|
|
12
|
-
const backgroundColor = useThemeColor(
|
|
13
|
-
{ light: lightColor, dark: darkColor },
|
|
14
|
-
"background",
|
|
15
|
-
);
|
|
12
|
+
const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
|
|
16
13
|
|
|
17
14
|
return <View style={[{ backgroundColor }, style]} {...otherProps} />;
|
|
18
|
-
}
|
|
15
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
|
|
2
2
|
|
|
3
|
-
import Ionicons from
|
|
4
|
-
import { type ComponentProps } from
|
|
3
|
+
import Ionicons from '@expo/vector-icons/Ionicons';
|
|
4
|
+
import { type ComponentProps } from 'react';
|
|
5
5
|
|
|
6
6
|
export function TabBarIcon(props: {
|
|
7
|
-
name: ComponentProps<typeof Ionicons>[
|
|
7
|
+
name: ComponentProps<typeof Ionicons>['name'];
|
|
8
8
|
color: string;
|
|
9
9
|
}) {
|
|
10
10
|
return <Ionicons size={28} style={{ marginBottom: -3 }} {...props} />;
|
package/constants/Colors.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Below are the colors that are used in the app. The colors are defined in the light and dark mode.
|
|
3
3
|
* There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
|
|
4
|
-
*/
|
|
4
|
+
*/
|
|
5
5
|
|
|
6
|
-
const tintColorLight =
|
|
7
|
-
const tintColorDark =
|
|
6
|
+
const tintColorLight = '#0a7ea4';
|
|
7
|
+
const tintColorDark = '#fff';
|
|
8
8
|
|
|
9
|
-
export const Colors =
|
|
9
|
+
export const Colors = {
|
|
10
10
|
light: {
|
|
11
|
-
text:
|
|
12
|
-
background:
|
|
11
|
+
text: '#11181C',
|
|
12
|
+
background: '#fff',
|
|
13
13
|
tint: tintColorLight,
|
|
14
|
-
icon:
|
|
15
|
-
tabIconDefault:
|
|
14
|
+
icon: '#687076',
|
|
15
|
+
tabIconDefault: '#687076',
|
|
16
16
|
tabIconSelected: tintColorLight,
|
|
17
17
|
},
|
|
18
18
|
dark: {
|
|
19
|
-
text:
|
|
20
|
-
background:
|
|
19
|
+
text: '#ECEDEE',
|
|
20
|
+
background: '#151718',
|
|
21
21
|
tint: tintColorDark,
|
|
22
|
-
icon:
|
|
23
|
-
tabIconDefault:
|
|
22
|
+
icon: '#9BA1A6',
|
|
23
|
+
tabIconDefault: '#9BA1A6',
|
|
24
24
|
tabIconSelected: tintColorDark,
|
|
25
25
|
},
|
|
26
26
|
};
|
package/expo-env.d.ts
ADDED
package/hooks/useColorScheme.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { useColorScheme } from
|
|
1
|
+
export { useColorScheme } from 'react-native';
|
package/hooks/useThemeColor.ts
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* https://docs.expo.io/guides/color-schemes/
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useColorScheme } from
|
|
7
|
-
import { Colors } from
|
|
6
|
+
import { useColorScheme } from 'react-native';
|
|
7
|
+
import { Colors } from '@/constants/Colors';
|
|
8
8
|
|
|
9
9
|
export function useThemeColor(
|
|
10
10
|
props: { light?: string; dark?: string },
|
|
11
|
-
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
|
|
11
|
+
colorName: keyof typeof Colors.light & keyof typeof Colors.dark
|
|
12
12
|
) {
|
|
13
|
-
const theme = useColorScheme() ??
|
|
13
|
+
const theme = useColorScheme() ?? 'light';
|
|
14
14
|
const colorFromProps = props[theme];
|
|
15
15
|
|
|
16
16
|
if (colorFromProps) {
|
|
@@ -18,4 +18,4 @@ export function useThemeColor(
|
|
|
18
18
|
} else {
|
|
19
19
|
return Colors[theme][colorName];
|
|
20
20
|
}
|
|
21
|
-
}
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-template-default",
|
|
3
3
|
"main": "expo-router/entry",
|
|
4
|
-
"version": "51.0.
|
|
4
|
+
"version": "51.0.9",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "expo start",
|
|
7
7
|
"reset-project": "./scripts/reset-project.js",
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@expo/vector-icons": "^14.0.0",
|
|
19
19
|
"@react-navigation/native": "^6.0.2",
|
|
20
|
-
"expo": "~51.0.0-preview.
|
|
20
|
+
"expo": "~51.0.0-preview.6",
|
|
21
21
|
"expo-constants": "~16.0.1",
|
|
22
22
|
"expo-font": "~12.0.4",
|
|
23
23
|
"expo-linking": "~6.3.1",
|
|
24
|
-
"expo-router": "~3.5.
|
|
24
|
+
"expo-router": "~3.5.3",
|
|
25
25
|
"expo-splash-screen": "~0.27.2",
|
|
26
26
|
"expo-status-bar": "~1.12.1",
|
|
27
27
|
"expo-system-ui": "~3.0.2",
|
package/babel.config.js
DELETED
package/components/Drawer.tsx
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Ionicons } from "@expo/vector-icons";
|
|
2
|
-
import { PropsWithChildren, useState } from "react";
|
|
3
|
-
import {
|
|
4
|
-
LayoutAnimation,
|
|
5
|
-
StyleSheet,
|
|
6
|
-
TouchableOpacity,
|
|
7
|
-
useColorScheme,
|
|
8
|
-
} from "react-native";
|
|
9
|
-
|
|
10
|
-
import { ThemedText } from "@/components/ThemedText";
|
|
11
|
-
import { ThemedView } from "@/components/ThemedView";
|
|
12
|
-
import { Colors } from "@/constants/Colors";
|
|
13
|
-
|
|
14
|
-
export function Drawer({
|
|
15
|
-
children,
|
|
16
|
-
title,
|
|
17
|
-
}: PropsWithChildren & { title: string }) {
|
|
18
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
19
|
-
const theme = useColorScheme() ?? "light";
|
|
20
|
-
|
|
21
|
-
const toggleOpen = () => {
|
|
22
|
-
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
|
23
|
-
setIsOpen((value) => !value);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<ThemedView>
|
|
28
|
-
<TouchableOpacity
|
|
29
|
-
style={styles.heading}
|
|
30
|
-
onPress={toggleOpen}
|
|
31
|
-
activeOpacity={0.8}
|
|
32
|
-
>
|
|
33
|
-
<Ionicons
|
|
34
|
-
name={isOpen ? "chevron-down" : "chevron-forward-outline"}
|
|
35
|
-
size={18}
|
|
36
|
-
color={theme === "light" ? Colors.light.icon : Colors.dark.icon}
|
|
37
|
-
/>
|
|
38
|
-
<ThemedText type="defaultSemiBold">{title}</ThemedText>
|
|
39
|
-
</TouchableOpacity>
|
|
40
|
-
<ThemedView style={styles.content}>{isOpen ? children : null}</ThemedView>
|
|
41
|
-
</ThemedView>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const styles = StyleSheet.create({
|
|
46
|
-
heading: {
|
|
47
|
-
flexDirection: "row",
|
|
48
|
-
alignItems: "center",
|
|
49
|
-
gap: 4,
|
|
50
|
-
},
|
|
51
|
-
content: {
|
|
52
|
-
marginLeft: 24,
|
|
53
|
-
}
|
|
54
|
-
});
|