diff --git a/.gitignore b/.gitignore
index ec8a36a..6623142 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,9 @@ web-build/
# macOS
.DS_Store
+
+# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
+# The following patterns were generated by expo-cli
+
+expo-env.d.ts
+# @end expo-cli
\ No newline at end of file
diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx
index 22a49b6..0edcba2 100644
--- a/app/(tabs)/_layout.tsx
+++ b/app/(tabs)/_layout.tsx
@@ -1,21 +1,28 @@
-import { Tabs } from 'expo-router';
-import React from 'react';
-
-import { TabBarIcon } from '@/components/navigation/TabBarIcon';
+import { Tabs } from "expo-router";
+import { TabBarIcon } from '@/components/default/navigation/TabBarIcon';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
-export default function TabLayout() {
- const colorScheme = useColorScheme();
+const TabLayout = () => {
+ const scheme = useColorScheme() ?? 'light';
return (
+ headerStyle: {
+ backgroundColor: Colors[scheme].background,
+ },
+ headerShadowVisible: false,
+ headerTintColor: Colors[scheme].tint,
+ tabBarStyle: {
+ backgroundColor: Colors[scheme].background,
+ },
+ }}
+ >
(
@@ -24,14 +31,15 @@ export default function TabLayout() {
}}
/>
(
-
+
),
}}
/>
);
-}
+};
+export default TabLayout;
diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
index 324aeb7..4662e77 100644
--- a/app/(tabs)/index.tsx
+++ b/app/(tabs)/index.tsx
@@ -1,70 +1,34 @@
-import { Image, StyleSheet, Platform } from 'react-native';
+import { StyleSheet } from "react-native";
+import { ThemedText } from "@/components/ThemedText";
+import { ThemedView } from "@/components/ThemedView";
-import { HelloWave } from '@/components/HelloWave';
-import ParallaxScrollView from '@/components/ParallaxScrollView';
-import { ThemedText } from '@/components/ThemedText';
-import { ThemedView } from '@/components/ThemedView';
+import Button from "@/components/buttons/Button";
-export default function HomeScreen() {
+const Index = () => {
return (
-
- }>
-
- Welcome!
-
+
+
+ Home Screen
+
+
+
-
- Step 1: Try it
-
- Edit app/(tabs)/index.tsx to see changes.
- Press{' '}
-
- {Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
- {' '}
- to open developer tools.
-
-
-
- Step 2: Explore
-
- Tap the Explore tab to learn more about what's included in this starter app.
-
-
-
- Step 3: Get a fresh start
-
- When you're ready, run{' '}
- npm run reset-project to get a fresh{' '}
- app directory. This will move the current{' '}
- app to{' '}
- app-example.
-
-
-
+
);
}
+export default Index;
const styles = StyleSheet.create({
- titleContainer: {
- flexDirection: 'row',
+ container: {
+ flex: 1,
alignItems: 'center',
- gap: 8,
+ justifyContent: 'center',
},
- stepContainer: {
- gap: 8,
- marginBottom: 8,
+ text: {
+ fontSize: 24,
},
- reactLogo: {
- height: 178,
- width: 290,
- bottom: 0,
- left: 0,
- position: 'absolute',
+ footerContainer: {
+ flex: 1 / 3,
+ alignItems: 'center',
},
});
diff --git a/app/(tabs)/settings.tsx b/app/(tabs)/settings.tsx
new file mode 100644
index 0000000..de303b2
--- /dev/null
+++ b/app/(tabs)/settings.tsx
@@ -0,0 +1,25 @@
+import { StyleSheet } from "react-native";
+import { ThemedText } from "@/components/ThemedText";
+import { ThemedView } from "@/components/ThemedView";
+
+const Settings = () => {
+ return (
+
+
+ Settings
+
+
+ );
+};
+export default Settings;
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ text: {
+ fontSize: 24,
+ },
+});
diff --git a/app/+not-found.tsx b/app/+not-found.tsx
index 963b04f..166f6b0 100644
--- a/app/+not-found.tsx
+++ b/app/+not-found.tsx
@@ -1,32 +1,32 @@
-import { Link, Stack } from 'expo-router';
-import { StyleSheet } from 'react-native';
+import { StyleSheet } from "react-native";
+import { ThemedText } from "@/components/ThemedText";
+import { ThemedView } from "@/components/ThemedView";
+import { Link, Stack } from "expo-router";
-import { ThemedText } from '@/components/ThemedText';
-import { ThemedView } from '@/components/ThemedView';
-
-export default function NotFoundScreen() {
+const NotFoundScreen = () => {
return (
<>
-
+
- This screen doesn't exist.
-
- Go to home screen!
+
+
+ Go back home.
+
>
);
-}
+};
+export default NotFoundScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: 'center',
justifyContent: 'center',
- padding: 20,
+ alignItems: 'center',
},
- link: {
- marginTop: 15,
- paddingVertical: 15,
+ button: {
+ fontSize: 24,
+ textDecorationLine: 'underline',
},
});
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 2e37cdd..58c1773 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -1,37 +1,10 @@
-import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
-import { useFonts } from 'expo-font';
-import { Stack } from 'expo-router';
-import * as SplashScreen from 'expo-splash-screen';
-import { useEffect } from 'react';
-import 'react-native-reanimated';
-
-import { useColorScheme } from '@/hooks/useColorScheme';
-
-// Prevent the splash screen from auto-hiding before asset loading is complete.
-SplashScreen.preventAutoHideAsync();
+import { Stack } from "expo-router";
export default function RootLayout() {
- const colorScheme = useColorScheme();
- const [loaded] = useFonts({
- SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
- });
-
- useEffect(() => {
- if (loaded) {
- SplashScreen.hideAsync();
- }
- }, [loaded]);
-
- if (!loaded) {
- return null;
- }
-
return (
-
-
-
-
-
-
+
+
+
+
);
}
diff --git a/assets/images/adaptive-icon.png b/assets/images/adaptive-icon.png
index 03d6f6b..fa3c871 100644
Binary files a/assets/images/adaptive-icon.png and b/assets/images/adaptive-icon.png differ
diff --git a/assets/images/favicon.png b/assets/images/favicon.png
index e75f697..11877b6 100644
Binary files a/assets/images/favicon.png and b/assets/images/favicon.png differ
diff --git a/assets/images/icon.png b/assets/images/icon.png
index a0b1526..fa3c871 100644
Binary files a/assets/images/icon.png and b/assets/images/icon.png differ
diff --git a/assets/images/splash.png b/assets/images/splash.png
index 0e89705..3f3dd3a 100644
Binary files a/assets/images/splash.png and b/assets/images/splash.png differ
diff --git a/components/HelloWave.tsx b/components/HelloWave.tsx
deleted file mode 100644
index f4b6ea5..0000000
--- a/components/HelloWave.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { StyleSheet } from 'react-native';
-import Animated, {
- useSharedValue,
- useAnimatedStyle,
- withTiming,
- withRepeat,
- withSequence,
-} from 'react-native-reanimated';
-
-import { ThemedText } from '@/components/ThemedText';
-
-export function HelloWave() {
- const rotationAnimation = useSharedValue(0);
-
- rotationAnimation.value = withRepeat(
- withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
- 4 // Run the animation 4 times
- );
-
- const animatedStyle = useAnimatedStyle(() => ({
- transform: [{ rotate: `${rotationAnimation.value}deg` }],
- }));
-
- return (
-
- 👋
-
- );
-}
-
-const styles = StyleSheet.create({
- text: {
- fontSize: 28,
- lineHeight: 32,
- marginTop: -6,
- },
-});
diff --git a/components/buttons/Button.tsx b/components/buttons/Button.tsx
new file mode 100644
index 0000000..35c4ad6
--- /dev/null
+++ b/components/buttons/Button.tsx
@@ -0,0 +1,85 @@
+import { StyleSheet, Pressable } from "react-native";
+import { ThemedText } from "@/components/ThemedText";
+import { ThemedView } from "@/components/ThemedView";
+import { Colors } from '@/constants/Colors';
+import { useColorScheme } from '@/hooks/useColorScheme';
+import FontAwesome from "@expo/vector-icons/FontAwesome";
+
+type Props = {
+ label: string;
+ theme?: 'primary';
+ onPress?: () => void;
+};
+
+const Button = ({ label, theme, onPress }: Props) => {
+ const scheme = useColorScheme() ?? 'light';
+ if (theme === 'primary') {
+ return (
+
+ alert('You pressed a button.')}
+ >
+
+ {label}
+
+
+
+ );
+ } else {
+ return (
+
+ alert('You pressed a button.')}
+ >
+
+ {label}
+
+
+
+ );
+ }
+};
+export default Button;
+
+const styles = StyleSheet.create({
+ buttonContainer: {
+ width: 320,
+ height: 68,
+ marginHorizontal: 20,
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 3,
+ },
+ button: {
+ borderRadius: 10,
+ width: '100%',
+ height: '100%',
+ alignItems: 'center',
+ justifyContent: 'center',
+ flexDirection: 'row',
+ },
+ buttonIcon: {
+ paddingRight: 8,
+ },
+ buttonLabel: {
+ fontSize: 16,
+ },
+});
diff --git a/components/Collapsible.tsx b/components/default/Collapsible.tsx
similarity index 100%
rename from components/Collapsible.tsx
rename to components/default/Collapsible.tsx
diff --git a/components/ExternalLink.tsx b/components/default/ExternalLink.tsx
similarity index 100%
rename from components/ExternalLink.tsx
rename to components/default/ExternalLink.tsx
diff --git a/components/ParallaxScrollView.tsx b/components/default/ParallaxScrollView.tsx
similarity index 100%
rename from components/ParallaxScrollView.tsx
rename to components/default/ParallaxScrollView.tsx
diff --git a/components/navigation/TabBarIcon.tsx b/components/default/navigation/TabBarIcon.tsx
similarity index 100%
rename from components/navigation/TabBarIcon.tsx
rename to components/default/navigation/TabBarIcon.tsx
diff --git a/constants/Colors.ts b/constants/Colors.ts
index 14e6784..a52bc57 100644
--- a/constants/Colors.ts
+++ b/constants/Colors.ts
@@ -17,7 +17,7 @@ export const Colors = {
},
dark: {
text: '#ECEDEE',
- background: '#151718',
+ background: '#2e2f3d',
tint: tintColorDark,
icon: '#9BA1A6',
tabIconDefault: '#9BA1A6',
diff --git a/example/app/(tabs)/_layout.tsx b/example/app/(tabs)/_layout.tsx
new file mode 100644
index 0000000..22a49b6
--- /dev/null
+++ b/example/app/(tabs)/_layout.tsx
@@ -0,0 +1,37 @@
+import { Tabs } from 'expo-router';
+import React from 'react';
+
+import { TabBarIcon } from '@/components/navigation/TabBarIcon';
+import { Colors } from '@/constants/Colors';
+import { useColorScheme } from '@/hooks/useColorScheme';
+
+export default function TabLayout() {
+ const colorScheme = useColorScheme();
+
+ return (
+
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+
+ );
+}
diff --git a/app/(tabs)/explore.tsx b/example/app/(tabs)/explore.tsx
similarity index 100%
rename from app/(tabs)/explore.tsx
rename to example/app/(tabs)/explore.tsx
diff --git a/example/app/(tabs)/index.tsx b/example/app/(tabs)/index.tsx
new file mode 100644
index 0000000..324aeb7
--- /dev/null
+++ b/example/app/(tabs)/index.tsx
@@ -0,0 +1,70 @@
+import { Image, StyleSheet, Platform } from 'react-native';
+
+import { HelloWave } from '@/components/HelloWave';
+import ParallaxScrollView from '@/components/ParallaxScrollView';
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+
+export default function HomeScreen() {
+ return (
+
+ }>
+
+ Welcome!
+
+
+
+ Step 1: Try it
+
+ Edit app/(tabs)/index.tsx to see changes.
+ Press{' '}
+
+ {Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
+ {' '}
+ to open developer tools.
+
+
+
+ Step 2: Explore
+
+ Tap the Explore tab to learn more about what's included in this starter app.
+
+
+
+ Step 3: Get a fresh start
+
+ When you're ready, run{' '}
+ npm run reset-project to get a fresh{' '}
+ app directory. This will move the current{' '}
+ app to{' '}
+ app-example.
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ titleContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ },
+ stepContainer: {
+ gap: 8,
+ marginBottom: 8,
+ },
+ reactLogo: {
+ height: 178,
+ width: 290,
+ bottom: 0,
+ left: 0,
+ position: 'absolute',
+ },
+});
diff --git a/app/+html.tsx b/example/app/+html.tsx
similarity index 100%
rename from app/+html.tsx
rename to example/app/+html.tsx
diff --git a/example/app/+not-found.tsx b/example/app/+not-found.tsx
new file mode 100644
index 0000000..963b04f
--- /dev/null
+++ b/example/app/+not-found.tsx
@@ -0,0 +1,32 @@
+import { Link, Stack } from 'expo-router';
+import { StyleSheet } from 'react-native';
+
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+
+export default function NotFoundScreen() {
+ return (
+ <>
+
+
+ This screen doesn't exist.
+
+ Go to home screen!
+
+
+ >
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 20,
+ },
+ link: {
+ marginTop: 15,
+ paddingVertical: 15,
+ },
+});
diff --git a/example/app/_layout.tsx b/example/app/_layout.tsx
new file mode 100644
index 0000000..2e37cdd
--- /dev/null
+++ b/example/app/_layout.tsx
@@ -0,0 +1,37 @@
+import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
+import { useFonts } from 'expo-font';
+import { Stack } from 'expo-router';
+import * as SplashScreen from 'expo-splash-screen';
+import { useEffect } from 'react';
+import 'react-native-reanimated';
+
+import { useColorScheme } from '@/hooks/useColorScheme';
+
+// Prevent the splash screen from auto-hiding before asset loading is complete.
+SplashScreen.preventAutoHideAsync();
+
+export default function RootLayout() {
+ const colorScheme = useColorScheme();
+ const [loaded] = useFonts({
+ SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
+ });
+
+ useEffect(() => {
+ if (loaded) {
+ SplashScreen.hideAsync();
+ }
+ }, [loaded]);
+
+ if (!loaded) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/example/assets/fonts/SpaceMono-Regular.ttf b/example/assets/fonts/SpaceMono-Regular.ttf
new file mode 100755
index 0000000..28d7ff7
Binary files /dev/null and b/example/assets/fonts/SpaceMono-Regular.ttf differ
diff --git a/example/assets/images/adaptive-icon.png b/example/assets/images/adaptive-icon.png
new file mode 100644
index 0000000..03d6f6b
Binary files /dev/null and b/example/assets/images/adaptive-icon.png differ
diff --git a/example/assets/images/favicon.png b/example/assets/images/favicon.png
new file mode 100644
index 0000000..e75f697
Binary files /dev/null and b/example/assets/images/favicon.png differ
diff --git a/example/assets/images/icon.png b/example/assets/images/icon.png
new file mode 100644
index 0000000..a0b1526
Binary files /dev/null and b/example/assets/images/icon.png differ
diff --git a/assets/images/partial-react-logo.png b/example/assets/images/partial-react-logo.png
similarity index 100%
rename from assets/images/partial-react-logo.png
rename to example/assets/images/partial-react-logo.png
diff --git a/assets/images/react-logo.png b/example/assets/images/react-logo.png
similarity index 100%
rename from assets/images/react-logo.png
rename to example/assets/images/react-logo.png
diff --git a/assets/images/react-logo@2x.png b/example/assets/images/react-logo@2x.png
similarity index 100%
rename from assets/images/react-logo@2x.png
rename to example/assets/images/react-logo@2x.png
diff --git a/assets/images/react-logo@3x.png b/example/assets/images/react-logo@3x.png
similarity index 100%
rename from assets/images/react-logo@3x.png
rename to example/assets/images/react-logo@3x.png
diff --git a/example/assets/images/splash.png b/example/assets/images/splash.png
new file mode 100644
index 0000000..0e89705
Binary files /dev/null and b/example/assets/images/splash.png differ
diff --git a/example/components/Collapsible.tsx b/example/components/Collapsible.tsx
new file mode 100644
index 0000000..c326473
--- /dev/null
+++ b/example/components/Collapsible.tsx
@@ -0,0 +1,41 @@
+import Ionicons from '@expo/vector-icons/Ionicons';
+import { PropsWithChildren, useState } from 'react';
+import { StyleSheet, TouchableOpacity, useColorScheme } from 'react-native';
+
+import { ThemedText } from '@/components/ThemedText';
+import { ThemedView } from '@/components/ThemedView';
+import { Colors } from '@/constants/Colors';
+
+export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
+ const [isOpen, setIsOpen] = useState(false);
+ const theme = useColorScheme() ?? 'light';
+
+ return (
+
+ setIsOpen((value) => !value)}
+ activeOpacity={0.8}>
+
+ {title}
+
+ {isOpen && {children}}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ heading: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 6,
+ },
+ content: {
+ marginTop: 6,
+ marginLeft: 24,
+ },
+});
diff --git a/example/components/ExternalLink.tsx b/example/components/ExternalLink.tsx
new file mode 100644
index 0000000..8f05675
--- /dev/null
+++ b/example/components/ExternalLink.tsx
@@ -0,0 +1,24 @@
+import { Link } from 'expo-router';
+import { openBrowserAsync } from 'expo-web-browser';
+import { type ComponentProps } from 'react';
+import { Platform } from 'react-native';
+
+type Props = Omit, 'href'> & { href: string };
+
+export function ExternalLink({ href, ...rest }: Props) {
+ return (
+ {
+ if (Platform.OS !== 'web') {
+ // Prevent the default behavior of linking to the default browser on native.
+ event.preventDefault();
+ // Open the link in an in-app browser.
+ await openBrowserAsync(href);
+ }
+ }}
+ />
+ );
+}
diff --git a/example/components/ParallaxScrollView.tsx b/example/components/ParallaxScrollView.tsx
new file mode 100644
index 0000000..0a35419
--- /dev/null
+++ b/example/components/ParallaxScrollView.tsx
@@ -0,0 +1,76 @@
+import type { PropsWithChildren, ReactElement } from 'react';
+import { StyleSheet, useColorScheme } from 'react-native';
+import Animated, {
+ interpolate,
+ useAnimatedRef,
+ useAnimatedStyle,
+ useScrollViewOffset,
+} from 'react-native-reanimated';
+
+import { ThemedView } from '@/components/ThemedView';
+
+const HEADER_HEIGHT = 250;
+
+type Props = PropsWithChildren<{
+ headerImage: ReactElement;
+ headerBackgroundColor: { dark: string; light: string };
+}>;
+
+export default function ParallaxScrollView({
+ children,
+ headerImage,
+ headerBackgroundColor,
+}: Props) {
+ const colorScheme = useColorScheme() ?? 'light';
+ const scrollRef = useAnimatedRef();
+ const scrollOffset = useScrollViewOffset(scrollRef);
+
+ const headerAnimatedStyle = useAnimatedStyle(() => {
+ return {
+ transform: [
+ {
+ translateY: interpolate(
+ scrollOffset.value,
+ [-HEADER_HEIGHT, 0, HEADER_HEIGHT],
+ [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
+ ),
+ },
+ {
+ scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
+ },
+ ],
+ };
+ });
+
+ return (
+
+
+
+ {headerImage}
+
+ {children}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ header: {
+ height: 250,
+ overflow: 'hidden',
+ },
+ content: {
+ flex: 1,
+ padding: 32,
+ gap: 16,
+ overflow: 'hidden',
+ },
+});
diff --git a/example/components/ThemedText.tsx b/example/components/ThemedText.tsx
new file mode 100644
index 0000000..c0e1a78
--- /dev/null
+++ b/example/components/ThemedText.tsx
@@ -0,0 +1,60 @@
+import { Text, type TextProps, StyleSheet } from 'react-native';
+
+import { useThemeColor } from '@/hooks/useThemeColor';
+
+export type ThemedTextProps = TextProps & {
+ lightColor?: string;
+ darkColor?: string;
+ type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
+};
+
+export function ThemedText({
+ style,
+ lightColor,
+ darkColor,
+ type = 'default',
+ ...rest
+}: ThemedTextProps) {
+ const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
+
+ return (
+
+ );
+}
+
+const styles = StyleSheet.create({
+ default: {
+ fontSize: 16,
+ lineHeight: 24,
+ },
+ defaultSemiBold: {
+ fontSize: 16,
+ lineHeight: 24,
+ fontWeight: '600',
+ },
+ title: {
+ fontSize: 32,
+ fontWeight: 'bold',
+ lineHeight: 32,
+ },
+ subtitle: {
+ fontSize: 20,
+ fontWeight: 'bold',
+ },
+ link: {
+ lineHeight: 30,
+ fontSize: 16,
+ color: '#0a7ea4',
+ },
+});
diff --git a/example/components/ThemedView.tsx b/example/components/ThemedView.tsx
new file mode 100644
index 0000000..4d2cb09
--- /dev/null
+++ b/example/components/ThemedView.tsx
@@ -0,0 +1,14 @@
+import { View, type ViewProps } from 'react-native';
+
+import { useThemeColor } from '@/hooks/useThemeColor';
+
+export type ThemedViewProps = ViewProps & {
+ lightColor?: string;
+ darkColor?: string;
+};
+
+export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
+ const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
+
+ return ;
+}
diff --git a/components/__tests__/ThemedText-test.tsx b/example/components/__tests__/ThemedText-test.tsx
similarity index 100%
rename from components/__tests__/ThemedText-test.tsx
rename to example/components/__tests__/ThemedText-test.tsx
diff --git a/components/__tests__/__snapshots__/ThemedText-test.tsx.snap b/example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap
similarity index 100%
rename from components/__tests__/__snapshots__/ThemedText-test.tsx.snap
rename to example/components/__tests__/__snapshots__/ThemedText-test.tsx.snap
diff --git a/example/components/navigation/TabBarIcon.tsx b/example/components/navigation/TabBarIcon.tsx
new file mode 100644
index 0000000..b7302c3
--- /dev/null
+++ b/example/components/navigation/TabBarIcon.tsx
@@ -0,0 +1,9 @@
+// You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
+
+import Ionicons from '@expo/vector-icons/Ionicons';
+import { type IconProps } from '@expo/vector-icons/build/createIconSet';
+import { type ComponentProps } from 'react';
+
+export function TabBarIcon({ style, ...rest }: IconProps['name']>) {
+ return ;
+}
diff --git a/example/constants/Colors.ts b/example/constants/Colors.ts
new file mode 100644
index 0000000..14e6784
--- /dev/null
+++ b/example/constants/Colors.ts
@@ -0,0 +1,26 @@
+/**
+ * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
+ * 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.
+ */
+
+const tintColorLight = '#0a7ea4';
+const tintColorDark = '#fff';
+
+export const Colors = {
+ light: {
+ text: '#11181C',
+ background: '#fff',
+ tint: tintColorLight,
+ icon: '#687076',
+ tabIconDefault: '#687076',
+ tabIconSelected: tintColorLight,
+ },
+ dark: {
+ text: '#ECEDEE',
+ background: '#151718',
+ tint: tintColorDark,
+ icon: '#9BA1A6',
+ tabIconDefault: '#9BA1A6',
+ tabIconSelected: tintColorDark,
+ },
+};
diff --git a/example/hooks/useColorScheme.ts b/example/hooks/useColorScheme.ts
new file mode 100644
index 0000000..17e3c63
--- /dev/null
+++ b/example/hooks/useColorScheme.ts
@@ -0,0 +1 @@
+export { useColorScheme } from 'react-native';
diff --git a/example/hooks/useColorScheme.web.ts b/example/hooks/useColorScheme.web.ts
new file mode 100644
index 0000000..6dcd80d
--- /dev/null
+++ b/example/hooks/useColorScheme.web.ts
@@ -0,0 +1,8 @@
+// NOTE: The default React Native styling doesn't support server rendering.
+// Server rendered styles should not change between the first render of the HTML
+// and the first render on the client. Typically, web developers will use CSS media queries
+// to render different styles on the client and server, these aren't directly supported in React Native
+// but can be achieved using a styling library like Nativewind.
+export function useColorScheme() {
+ return 'light';
+}
diff --git a/example/hooks/useThemeColor.ts b/example/hooks/useThemeColor.ts
new file mode 100644
index 0000000..ae43b47
--- /dev/null
+++ b/example/hooks/useThemeColor.ts
@@ -0,0 +1,22 @@
+/**
+ * Learn more about light and dark modes:
+ * https://docs.expo.dev/guides/color-schemes/
+ */
+
+import { useColorScheme } from 'react-native';
+
+import { Colors } from '@/constants/Colors';
+
+export function useThemeColor(
+ props: { light?: string; dark?: string },
+ colorName: keyof typeof Colors.light & keyof typeof Colors.dark
+) {
+ const theme = useColorScheme() ?? 'light';
+ const colorFromProps = props[theme];
+
+ if (colorFromProps) {
+ return colorFromProps;
+ } else {
+ return Colors[theme][colorName];
+ }
+}
diff --git a/scripts/reset-project.js b/example/scripts/reset-project.js
similarity index 100%
rename from scripts/reset-project.js
rename to example/scripts/reset-project.js
diff --git a/package-lock.json b/package-lock.json
index 4497d4b..de99974 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,6 +13,7 @@
"expo": "~51.0.28",
"expo-constants": "~16.0.2",
"expo-font": "~12.0.9",
+ "expo-image": "~1.13.0",
"expo-linking": "~6.3.1",
"expo-router": "~3.5.23",
"expo-splash-screen": "~0.27.5",
@@ -10102,6 +10103,15 @@
"expo": "*"
}
},
+ "node_modules/expo-image": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-1.13.0.tgz",
+ "integrity": "sha512-0NLDcFmEn4Nh1sXeRvNzDHT+Fl6FXtTol6ki6kYYH0/iDeSFWyIy/Fek6kzDDYAmhipSMR7buPf7VVoHseTbAA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo": "*"
+ }
+ },
"node_modules/expo-keep-awake": {
"version": "13.0.2",
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-13.0.2.tgz",
diff --git a/package.json b/package.json
index fcfbc7a..e972640 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,8 @@
"react-native-reanimated": "~3.10.1",
"react-native-safe-area-context": "4.10.5",
"react-native-screens": "3.31.1",
- "react-native-web": "~0.19.10"
+ "react-native-web": "~0.19.10",
+ "expo-image": "~1.13.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",