@ -0,0 +1,117 @@
|
||||
import { config } from '@gluestack-ui/config';
|
||||
import { Box, GluestackUIProvider, Text } from '@gluestack-ui/themed';
|
||||
import { ScrollView } from 'react-native';
|
||||
import Gradient from './assets/Icons/Gradient';
|
||||
import DocumentData from './assets/Icons/DocumentData';
|
||||
import LightBulbPerson from './assets/Icons/LightbulbPerson';
|
||||
import Rocket from './assets/Icons/Rocket';
|
||||
import Logo from './assets/Icons/Logo';
|
||||
export default function App() {
|
||||
return (
|
||||
<GluestackUIProvider config={config}>
|
||||
<Home />
|
||||
</GluestackUIProvider>
|
||||
);
|
||||
}
|
||||
const Home = () => {
|
||||
return <Container />;
|
||||
};
|
||||
const FeatureCard = ({ iconSvg: IconSvg, name, desc }: any) => {
|
||||
return (
|
||||
<Box
|
||||
flexDirection="column"
|
||||
borderWidth={1}
|
||||
borderColor="$borderDark700"
|
||||
$web-flex={1}
|
||||
m="$2"
|
||||
p="$4"
|
||||
rounded="$md"
|
||||
>
|
||||
<Box alignItems="center" display="flex" flexDirection="row">
|
||||
{/* <Image source={iconSvg} alt="document" width={22} height={22} /> */}
|
||||
<Text>
|
||||
<IconSvg />
|
||||
</Text>
|
||||
<Text fontSize={22} color="$white" fontWeight="500" ml="$2">
|
||||
{name}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text color="$textDark400" mt="$2">
|
||||
{desc}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
const Container = () => {
|
||||
return (
|
||||
<Box flex={1} backgroundColor="$black">
|
||||
<ScrollView
|
||||
style={{
|
||||
height: '100%',
|
||||
}}
|
||||
contentContainerStyle={{
|
||||
flexGrow: 1,
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
position="absolute"
|
||||
$base-h={500}
|
||||
$base-w={500}
|
||||
$lg-h={700}
|
||||
$lg-w={700}
|
||||
>
|
||||
<Gradient />
|
||||
</Box>
|
||||
<Box
|
||||
height="60%"
|
||||
$base-my="$16"
|
||||
$base-mx="$5"
|
||||
$base-h="80%"
|
||||
$lg-my="$24"
|
||||
$lg-mx="$32"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
>
|
||||
<Box
|
||||
bg="#64748B33"
|
||||
py="$2"
|
||||
px="$6"
|
||||
rounded="$full"
|
||||
alignItems="center"
|
||||
marginTop={20}
|
||||
$base-flexDirection="column"
|
||||
$sm-flexDirection="row"
|
||||
$md-alignSelf="flex-start"
|
||||
>
|
||||
<Text color="$white" fontWeight="$normal">
|
||||
Get started by editing
|
||||
</Text>
|
||||
<Text color="$white" fontWeight="$medium" ml="$2">
|
||||
App.tsx
|
||||
</Text>
|
||||
</Box>
|
||||
<Box justifyContent="center" alignItems="center">
|
||||
<Logo />
|
||||
</Box>
|
||||
<Box $base-flexDirection="column" $md-flexDirection="row">
|
||||
<FeatureCard
|
||||
iconSvg={DocumentData}
|
||||
name="Docs"
|
||||
desc="Find in-depth information about gluestack features and API."
|
||||
/>
|
||||
<FeatureCard
|
||||
iconSvg={LightBulbPerson}
|
||||
name="Learn"
|
||||
desc="Learn about gluestack in an interactive course with quizzes!"
|
||||
/>
|
||||
<FeatureCard
|
||||
iconSvg={Rocket}
|
||||
name="Deploy"
|
||||
desc="Instantly drop your gluestack site to a shareable URL with vercel."
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</ScrollView>
|
||||
</Box>
|
||||
);
|
||||
};
|
@ -1,50 +1,32 @@
|
||||
# Welcome to your Expo app 👋
|
||||
This is a [Next.js](https://github.com/expo/expo) + [Gluestack-ui](https://ui.gluestack.io/) project template bootstrapped with [`create-expo-app`](https://docs.expo.dev/get-started/create-a-project/).
|
||||
|
||||
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
|
||||
## Getting Started
|
||||
|
||||
## Get started
|
||||
|
||||
1. Install dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Start the app
|
||||
|
||||
```bash
|
||||
npx expo start
|
||||
```
|
||||
|
||||
In the output, you'll find options to open the app in a
|
||||
|
||||
- [development build](https://docs.expo.dev/develop/development-builds/introduction/)
|
||||
- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
|
||||
- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
|
||||
- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
|
||||
|
||||
You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
|
||||
|
||||
## Get a fresh project
|
||||
|
||||
When you're ready, run:
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run reset-project
|
||||
# For web
|
||||
yarn web
|
||||
# For ios
|
||||
yarn ios
|
||||
# For android
|
||||
yarn android
|
||||
```
|
||||
|
||||
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
|
||||
You can start editing the page by modifying `App.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
## Learn more
|
||||
This project uses [`@gluestack-ui`](https://ui.gluestack.io/docs/overview/introduction) library that provides optionally styled and accessible components. These components are designed for easy integration into applications developed with React and React Native.
|
||||
|
||||
To learn more about developing your project with Expo, look at the following resources:
|
||||
|
||||
- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
|
||||
- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
|
||||
## Learn More
|
||||
|
||||
## Join the community
|
||||
To learn more about Expo + Gluestack UI template, take a look at the following resources:
|
||||
|
||||
Join our community of developers creating universal apps.
|
||||
- [Expo Documentation](https://github.com/expo/expo) - learn about Expo features and API.
|
||||
- [Gluestack UI Documenatation](https://ui.gluestack.io/docs/overview/introduction) - learn about core concepts and architecture of gluestack-ui.
|
||||
- [Gluestack Style Documentaion](https://style.gluestack.io/docs/overview/introduction) - learn about the universal styling library that is used in Gluestack-ui
|
||||
|
||||
- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
|
||||
- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
|
||||
You can check out:
|
||||
- [the gluestack-ui GitHub repository](https://github.com/gluestack/gluestack-ui)
|
||||
- [the gluestack-style GitHub repository](https://github.com/gluestack/gluestack-style)
|
||||
Your feedback and contributions are welcome!
|
||||
|
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/ReactNative.iml" filepath="$PROJECT_DIR$/.idea/ReactNative.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="9cf59646-9488-4deb-8601-845f721975aa" name="Changes" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 1
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="2rNmL1yw5JzLAjOwzrLGBZT0Au8" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="autoscrollFromSource" value="true" />
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"git-widget-placeholder": "master",
|
||||
"last_opened_file_path": "/Users/tonyfages/3A/SAE/ReactNative/ReactNative",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"npm.ios.executor": "Run",
|
||||
"ts.external.directory.path": "/Users/tonyfages/3A/SAE/ReactNative/ReactNative/node_modules/typescript/lib",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="RunManager">
|
||||
<configuration name="ios" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
|
||||
<package-json value="$PROJECT_DIR$/package.json" />
|
||||
<command value="run" />
|
||||
<scripts>
|
||||
<script value="ios" />
|
||||
</scripts>
|
||||
<node-interpreter value="project" />
|
||||
<envs />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="npm.ios" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-js-predefined-d6986cc7102b-7c0b70fcd90d-JavaScript-WS-242.21829.149" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="9cf59646-9488-4deb-8601-845f721975aa" name="Changes" comment="" />
|
||||
<created>1736407849500</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1736407849500</updated>
|
||||
<workItem from="1736407850864" duration="149000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
</project>
|
@ -1,36 +1,30 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "Optifit-App",
|
||||
"slug": "Optifit-App",
|
||||
"name": "expo-app",
|
||||
"slug": "expo-app",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"scheme": "myapp",
|
||||
"userInterfaceStyle": "automatic",
|
||||
"icon": "./assets/icon.png",
|
||||
"userInterfaceStyle": "light",
|
||||
"splash": {
|
||||
"image": "./assets/images/splash.png",
|
||||
"image": "./assets/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"assetBundlePatterns": [
|
||||
"**/*"
|
||||
],
|
||||
"ios": {
|
||||
"supportsTablet": true
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"foregroundImage": "./assets/adaptive-icon.png",
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
},
|
||||
"web": {
|
||||
"bundler": "metro",
|
||||
"output": "static",
|
||||
"favicon": "./assets/images/favicon.png"
|
||||
},
|
||||
"plugins": [
|
||||
"expo-router"
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true
|
||||
"favicon": "./assets/favicon.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
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 (
|
||||
<Tabs
|
||||
screenOptions={{
|
||||
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
||||
headerShown: false,
|
||||
}}>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: 'Home',
|
||||
tabBarIcon: ({ color, focused }) => (
|
||||
<TabBarIcon name={focused ? 'home' : 'home-outline'} color={color} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="explore"
|
||||
options={{
|
||||
title: 'Explore',
|
||||
tabBarIcon: ({ color, focused }) => (
|
||||
<TabBarIcon name={focused ? 'code-slash' : 'code-slash-outline'} color={color} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
import Ionicons from '@expo/vector-icons/Ionicons';
|
||||
import { StyleSheet, Image, Platform } from 'react-native';
|
||||
|
||||
import { Collapsible } from '@/components/Collapsible';
|
||||
import { ExternalLink } from '@/components/ExternalLink';
|
||||
import ParallaxScrollView from '@/components/ParallaxScrollView';
|
||||
import { ThemedText } from '@/components/ThemedText';
|
||||
import { ThemedView } from '@/components/ThemedView';
|
||||
|
||||
export default function TabTwoScreen() {
|
||||
return (
|
||||
<ParallaxScrollView
|
||||
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
|
||||
headerImage={<Ionicons size={310} name="code-slash" style={styles.headerImage} />}>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Explore</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedText>This app includes example code to help you get started.</ThemedText>
|
||||
<Collapsible title="File-based routing">
|
||||
<ThemedText>
|
||||
This app has two screens:{' '}
|
||||
<ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> and{' '}
|
||||
<ThemedText type="defaultSemiBold">app/(tabs)/explore.tsx</ThemedText>
|
||||
</ThemedText>
|
||||
<ThemedText>
|
||||
The layout file in <ThemedText type="defaultSemiBold">app/(tabs)/_layout.tsx</ThemedText>{' '}
|
||||
sets up the tab navigator.
|
||||
</ThemedText>
|
||||
<ExternalLink href="https://docs.expo.dev/router/introduction">
|
||||
<ThemedText type="link">Learn more</ThemedText>
|
||||
</ExternalLink>
|
||||
</Collapsible>
|
||||
<Collapsible title="Android, iOS, and web support">
|
||||
<ThemedText>
|
||||
You can open this project on Android, iOS, and the web. To open the web version, press{' '}
|
||||
<ThemedText type="defaultSemiBold">w</ThemedText> in the terminal running this project.
|
||||
</ThemedText>
|
||||
</Collapsible>
|
||||
<Collapsible title="Images">
|
||||
<ThemedText>
|
||||
For static images, you can use the <ThemedText type="defaultSemiBold">@2x</ThemedText> and{' '}
|
||||
<ThemedText type="defaultSemiBold">@3x</ThemedText> suffixes to provide files for
|
||||
different screen densities
|
||||
</ThemedText>
|
||||
<Image source={require('@/assets/images/react-logo.png')} style={{ alignSelf: 'center' }} />
|
||||
<ExternalLink href="https://reactnative.dev/docs/images">
|
||||
<ThemedText type="link">Learn more</ThemedText>
|
||||
</ExternalLink>
|
||||
</Collapsible>
|
||||
<Collapsible title="Custom fonts">
|
||||
<ThemedText>
|
||||
Open <ThemedText type="defaultSemiBold">app/_layout.tsx</ThemedText> to see how to load{' '}
|
||||
<ThemedText style={{ fontFamily: 'SpaceMono' }}>
|
||||
custom fonts such as this one.
|
||||
</ThemedText>
|
||||
</ThemedText>
|
||||
<ExternalLink href="https://docs.expo.dev/versions/latest/sdk/font">
|
||||
<ThemedText type="link">Learn more</ThemedText>
|
||||
</ExternalLink>
|
||||
</Collapsible>
|
||||
<Collapsible title="Light and dark mode components">
|
||||
<ThemedText>
|
||||
This template has light and dark mode support. The{' '}
|
||||
<ThemedText type="defaultSemiBold">useColorScheme()</ThemedText> hook lets you inspect
|
||||
what the user's current color scheme is, and so you can adjust UI colors accordingly.
|
||||
</ThemedText>
|
||||
<ExternalLink href="https://docs.expo.dev/develop/user-interface/color-themes/">
|
||||
<ThemedText type="link">Learn more</ThemedText>
|
||||
</ExternalLink>
|
||||
</Collapsible>
|
||||
<Collapsible title="Animations">
|
||||
<ThemedText>
|
||||
This template includes an example of an animated component. The{' '}
|
||||
<ThemedText type="defaultSemiBold">components/HelloWave.tsx</ThemedText> component uses
|
||||
the powerful <ThemedText type="defaultSemiBold">react-native-reanimated</ThemedText> library
|
||||
to create a waving hand animation.
|
||||
</ThemedText>
|
||||
{Platform.select({
|
||||
ios: (
|
||||
<ThemedText>
|
||||
The <ThemedText type="defaultSemiBold">components/ParallaxScrollView.tsx</ThemedText>{' '}
|
||||
component provides a parallax effect for the header image.
|
||||
</ThemedText>
|
||||
),
|
||||
})}
|
||||
</Collapsible>
|
||||
</ParallaxScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
headerImage: {
|
||||
color: '#808080',
|
||||
bottom: -90,
|
||||
left: -35,
|
||||
position: 'absolute',
|
||||
},
|
||||
titleContainer: {
|
||||
flexDirection: 'row',
|
||||
gap: 8,
|
||||
},
|
||||
});
|
@ -1,70 +0,0 @@
|
||||
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 (
|
||||
<ParallaxScrollView
|
||||
headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
|
||||
headerImage={
|
||||
<Image
|
||||
source={require('@/assets/images/partial-react-logo.png')}
|
||||
style={styles.reactLogo}
|
||||
/>
|
||||
}>
|
||||
<ThemedView style={styles.titleContainer}>
|
||||
<ThemedText type="title">Welcome!</ThemedText>
|
||||
<HelloWave />
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 1: Try it</ThemedText>
|
||||
<ThemedText>
|
||||
Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
|
||||
Press{' '}
|
||||
<ThemedText type="defaultSemiBold">
|
||||
{Platform.select({ ios: 'cmd + d', android: 'cmd + m' })}
|
||||
</ThemedText>{' '}
|
||||
to open developer tools.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 2: Explore</ThemedText>
|
||||
<ThemedText>
|
||||
Tap the Explore tab to learn more about what's included in this starter app.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
<ThemedView style={styles.stepContainer}>
|
||||
<ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
|
||||
<ThemedText>
|
||||
When you're ready, run{' '}
|
||||
<ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
|
||||
<ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
|
||||
<ThemedText type="defaultSemiBold">app-example</ThemedText>.
|
||||
</ThemedText>
|
||||
</ThemedView>
|
||||
</ParallaxScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
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',
|
||||
},
|
||||
});
|
@ -1,39 +0,0 @@
|
||||
import { ScrollViewStyleReset } from 'expo-router/html';
|
||||
import { type PropsWithChildren } from 'react';
|
||||
|
||||
/**
|
||||
* This file is web-only and used to configure the root HTML for every web page during static rendering.
|
||||
* The contents of this function only run in Node.js environments and do not have access to the DOM or browser APIs.
|
||||
*/
|
||||
export default function Root({ children }: PropsWithChildren) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
|
||||
{/*
|
||||
Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
|
||||
However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
|
||||
*/}
|
||||
<ScrollViewStyleReset />
|
||||
|
||||
{/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */}
|
||||
<style dangerouslySetInnerHTML={{ __html: responsiveBackground }} />
|
||||
{/* Add any additional <head> elements that you want globally available on web... */}
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
const responsiveBackground = `
|
||||
body {
|
||||
background-color: #fff;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #000;
|
||||
}
|
||||
}`;
|
@ -1,32 +0,0 @@
|
||||
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 (
|
||||
<>
|
||||
<Stack.Screen options={{ title: 'Oops!' }} />
|
||||
<ThemedView style={styles.container}>
|
||||
<ThemedText type="title">This screen doesn't exist.</ThemedText>
|
||||
<Link href="/" style={styles.link}>
|
||||
<ThemedText type="link">Go to home screen!</ThemedText>
|
||||
</Link>
|
||||
</ThemedView>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
link: {
|
||||
marginTop: 15,
|
||||
paddingVertical: 15,
|
||||
},
|
||||
});
|
@ -1,37 +0,0 @@
|
||||
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 (
|
||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
<Stack>
|
||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="+not-found" />
|
||||
</Stack>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { Svg, Path } from "react-native-svg";
|
||||
const SvgComponent = () => {
|
||||
return (
|
||||
<Svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<Path
|
||||
d="M9.5 16.75C9.5 16.3358 9.16421 16 8.75 16C8.33579 16 8 16.3358 8 16.75V18.25C8 18.6642 8.33579 19 8.75 19C9.16421 19 9.5 18.6642 9.5 18.25V16.75ZM12 12C12.4142 12 12.75 12.3358 12.75 12.75V18.25C12.75 18.6642 12.4142 19 12 19C11.5858 19 11.25 18.6642 11.25 18.25L11.25 12.75C11.25 12.3358 11.5858 12 12 12ZM16 14.75C16 14.3358 15.6642 14 15.25 14C14.8358 14 14.5 14.3358 14.5 14.75V18.25C14.5 18.6642 14.8358 19 15.25 19C15.6642 19 16 18.6642 16 18.25V14.75ZM13.585 2.586L19.414 8.414C19.789 8.789 20 9.298 20 9.828V20C20 21.104 19.104 22 18 22H6C4.896 22 4 21.104 4 20V4C4 2.896 4.896 2 6 2H12.172C12.1999 2 12.2271 2.00371 12.2542 2.00741C12.2738 2.01008 12.2933 2.01274 12.313 2.014C12.528 2.029 12.74 2.07 12.937 2.152C12.9944 2.17648 13.0488 2.20797 13.103 2.23933C13.1197 2.24897 13.1363 2.25859 13.153 2.268C13.1685 2.27647 13.1845 2.28426 13.2005 2.29207C13.2281 2.30548 13.2557 2.31894 13.281 2.336C13.359 2.389 13.429 2.452 13.5 2.516C13.5115 2.5262 13.5238 2.53567 13.5363 2.5452C13.5531 2.55808 13.57 2.57105 13.585 2.586ZM18 20.5C18.276 20.5 18.5 20.275 18.5 20V10H14C12.896 10 12 9.104 12 8V3.5H6C5.724 3.5 5.5 3.725 5.5 4V20C5.5 20.275 5.724 20.5 6 20.5H18ZM17.378 8.5L13.5 4.621V8C13.5 8.275 13.724 8.5 14 8.5H17.378Z"
|
||||
fill="#FAFAFA"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
export default SvgComponent;
|
@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { Svg, G, Ellipse, Defs, RadialGradient, Stop } from "react-native-svg";
|
||||
const SvgComponent = () => {
|
||||
return (
|
||||
<Svg width="965" height="1078" viewBox="0 0 965 1078" fill="none">
|
||||
<G opacity="0.8">
|
||||
<G>
|
||||
<Ellipse
|
||||
cx="222.599"
|
||||
cy="277.706"
|
||||
rx="641.842"
|
||||
ry="699.982"
|
||||
fill="url(#paint0_radial_2913_5676)"
|
||||
/>
|
||||
</G>
|
||||
<G>
|
||||
<Ellipse
|
||||
cx="-82.2838"
|
||||
cy="30.7211"
|
||||
rx="463.716"
|
||||
ry="505.721"
|
||||
fill="url(#paint1_radial_2913_5676)"
|
||||
/>
|
||||
</G>
|
||||
</G>
|
||||
<Defs>
|
||||
<RadialGradient
|
||||
id="paint0_radial_2913_5676"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(222.599 277.706) rotate(90) scale(780.255 715.448)"
|
||||
>
|
||||
<Stop offset="0%" stopColor="#5D4178" />
|
||||
<Stop offset="100%" stopColor="#2D1248" stopOpacity="0" />
|
||||
</RadialGradient>
|
||||
<RadialGradient
|
||||
id="paint1_radial_2913_5676"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-82.2838 30.7211) rotate(90) scale(563.717 516.895)"
|
||||
>
|
||||
<Stop offset="0%" stopColor="#6212B1" />
|
||||
<Stop offset="100%" stopColor="#220044" stopOpacity="0" />
|
||||
</RadialGradient>
|
||||
</Defs>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
export default SvgComponent;
|
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { Svg, Path } from "react-native-svg";
|
||||
const SvgComponent = () => {
|
||||
return (
|
||||
<Svg width="25" height="24" viewBox="0 0 25 24" fill="none">
|
||||
<Path
|
||||
d="M12.666 2.00098C16.6701 2.00098 19.916 5.24691 19.916 9.25098C19.916 11.347 19.0153 13.2707 17.253 14.9929C17.176 15.0681 17.1164 15.1586 17.0779 15.2582L17.0464 15.3605L15.9153 20.2561C15.6926 21.22 14.8695 21.9183 13.8963 21.993L13.7231 21.9996H11.6093C10.6198 21.9996 9.75392 21.3545 9.46231 20.4228L9.4169 20.2555L8.28733 15.3607C8.25505 15.2208 8.18329 15.0931 8.08058 14.9928C6.40117 13.3526 5.5038 11.5297 5.42214 9.54923L5.41602 9.25098L5.41989 9.01166C5.54616 5.11837 8.74203 2.00098 12.666 2.00098ZM14.781 18.499H10.55L10.8785 19.9182C10.9492 20.2245 11.2017 20.4504 11.5061 20.4925L11.6093 20.4996H13.7231C14.0373 20.4996 14.3141 20.3044 14.4237 20.0174L14.4538 19.9184L14.781 18.499ZM12.666 3.50098C9.56423 3.50098 7.03608 5.95699 6.92017 9.03042L6.91602 9.25098L6.92273 9.52799C6.99888 11.0913 7.72323 12.5471 9.12864 13.9197C9.23715 14.0257 9.33415 14.1419 9.41852 14.2662C10.3954 13.776 11.4985 13.5 12.666 13.5C13.834 13.5 14.9375 13.7762 15.9147 14.2668C15.9649 14.1928 16.0195 14.1217 16.0784 14.0539L16.2046 13.9201C17.6092 12.5475 18.3332 11.0916 18.4093 9.52803L18.416 9.25098L18.4118 9.03042C18.2959 5.95699 15.7678 3.50098 12.666 3.50098ZM15.4268 15.7049C14.6074 15.2555 13.6665 15 12.666 15C11.6657 15 10.7251 15.2554 9.90583 15.7046L10.204 16.999H15.127L15.4268 15.7049ZM12.666 7.5C11.6995 7.5 10.916 8.2835 10.916 9.25C10.916 10.2165 11.6995 11 12.666 11C13.6325 11 14.416 10.2165 14.416 9.25C14.416 8.2835 13.6325 7.5 12.666 7.5ZM9.41602 9.25C9.41602 7.45507 10.8711 6 12.666 6C14.4609 6 15.916 7.45507 15.916 9.25C15.916 11.0449 14.4609 12.5 12.666 12.5C10.8711 12.5 9.41602 11.0449 9.41602 9.25Z"
|
||||
fill="#FAFAFA"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
export default SvgComponent;
|
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { Svg, Path } from "react-native-svg";
|
||||
const SvgComponent = () => {
|
||||
return (
|
||||
<Svg width="25" height="24" viewBox="0 0 25 24" fill="none">
|
||||
<Path
|
||||
d="M13.3902 7.43126C14.3665 6.45495 15.9494 6.45495 16.9257 7.43126C17.902 8.40757 17.902 9.99048 16.9257 10.9668C15.9494 11.9431 14.3665 11.9431 13.3902 10.9668C12.4139 9.99048 12.4139 8.40757 13.3902 7.43126ZM15.8651 8.49192C15.4745 8.10139 14.8414 8.10139 14.4508 8.49192C14.0603 8.88244 14.0603 9.51561 14.4508 9.90613C14.8414 10.2967 15.4745 10.2967 15.8651 9.90613C16.2556 9.51561 16.2556 8.88244 15.8651 8.49192ZM21.8416 4.32265C21.5728 3.45785 20.8955 2.78081 20.0306 2.51238L19.3685 2.30692C16.975 1.56409 14.367 2.20851 12.5949 3.98062L11.599 4.9765C10.2292 3.94786 8.27617 4.0567 7.02985 5.30302L5.78732 6.54555C5.49443 6.83844 5.49443 7.31331 5.78732 7.60621L7.3783 9.19718L7.19849 9.37699C6.51507 10.0604 6.51507 11.1684 7.19849 11.8519L7.69383 12.3472L6.29827 13.1432C6.09513 13.259 5.95766 13.463 5.92653 13.6948C5.89539 13.9266 5.97415 14.1596 6.13952 14.325L10.0286 18.2141C10.1939 18.3793 10.4267 18.4581 10.6583 18.4271C10.89 18.3962 11.0939 18.259 11.21 18.0562L12.0079 16.6613L12.5051 17.1584C13.1885 17.8419 14.2965 17.8419 14.9799 17.1584L15.1567 16.9816L16.7463 18.5712C17.0392 18.8641 17.5141 18.8641 17.807 18.5712L19.0495 17.3287C20.2953 16.0829 20.4046 14.1308 19.3772 12.7612L20.3751 11.7632C22.1479 9.99043 22.7921 7.38111 22.048 4.98696L21.8416 4.32265ZM19.586 3.94498C19.9791 4.06699 20.287 4.37473 20.4092 4.76783L20.6156 5.43213C21.1944 7.29426 20.6933 9.32372 19.3145 10.7026L13.9193 16.0978C13.8216 16.1954 13.6633 16.1954 13.5657 16.0978L8.25915 10.7912C8.16152 10.6936 8.16152 10.5353 8.25915 10.4377L13.6555 5.04128C15.0338 3.66297 17.0623 3.16176 18.9239 3.73951L19.586 3.94498ZM18.2971 13.8413C18.7496 14.607 18.6469 15.61 17.9888 16.2681L17.2766 16.9803L16.2174 15.921L18.2971 13.8413ZM8.09051 6.36368C8.74902 5.70516 9.75305 5.60275 10.519 6.05644L8.43896 8.13652L7.37831 7.07588L8.09051 6.36368ZM10.9086 15.562L10.3953 16.4594L7.8951 13.9592L8.79348 13.4469L10.9086 15.562ZM7.02287 18.3947C7.31577 18.1018 7.31577 17.6269 7.02287 17.334C6.72998 17.0411 6.25511 17.0411 5.96221 17.334L3.48734 19.8089C3.19445 20.1018 3.19445 20.5767 3.48734 20.8696C3.78023 21.1625 4.25511 21.1625 4.548 20.8696L7.02287 18.3947ZM5.07829 15.3895C5.37119 15.6824 5.37119 16.1573 5.07829 16.4501L4.01763 17.5108C3.72474 17.8037 3.24987 17.8037 2.95697 17.5108C2.66408 17.2179 2.66408 16.743 2.95697 16.4501L4.01763 15.3895C4.31053 15.0966 4.7854 15.0966 5.07829 15.3895ZM8.96539 20.3413C9.25829 20.0484 9.25829 19.5736 8.9654 19.2807C8.67251 18.9878 8.19764 18.9878 7.90474 19.2807L6.84614 20.3392C6.55324 20.6321 6.55324 21.107 6.84612 21.3999C7.13901 21.6928 7.61389 21.6928 7.90678 21.3999L8.96539 20.3413Z"
|
||||
fill="#FAFAFA"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
};
|
||||
export default SvgComponent;
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 1.1 KiB |
@ -1,41 +0,0 @@
|
||||
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 (
|
||||
<ThemedView>
|
||||
<TouchableOpacity
|
||||
style={styles.heading}
|
||||
onPress={() => setIsOpen((value) => !value)}
|
||||
activeOpacity={0.8}>
|
||||
<Ionicons
|
||||
name={isOpen ? 'chevron-down' : 'chevron-forward-outline'}
|
||||
size={18}
|
||||
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon}
|
||||
/>
|
||||
<ThemedText type="defaultSemiBold">{title}</ThemedText>
|
||||
</TouchableOpacity>
|
||||
{isOpen && <ThemedView style={styles.content}>{children}</ThemedView>}
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
heading: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
},
|
||||
content: {
|
||||
marginTop: 6,
|
||||
marginLeft: 24,
|
||||
},
|
||||
});
|
@ -1,24 +0,0 @@
|
||||
import { Link } from 'expo-router';
|
||||
import { openBrowserAsync } from 'expo-web-browser';
|
||||
import { type ComponentProps } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
type Props = Omit<ComponentProps<typeof Link>, 'href'> & { href: string };
|
||||
|
||||
export function ExternalLink({ href, ...rest }: Props) {
|
||||
return (
|
||||
<Link
|
||||
target="_blank"
|
||||
{...rest}
|
||||
href={href}
|
||||
onPress={async (event) => {
|
||||
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);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
@ -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 (
|
||||
<Animated.View style={animatedStyle}>
|
||||
<ThemedText style={styles.text}>👋</ThemedText>
|
||||
</Animated.View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
text: {
|
||||
fontSize: 28,
|
||||
lineHeight: 32,
|
||||
marginTop: -6,
|
||||
},
|
||||
});
|
@ -1,76 +0,0 @@
|
||||
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<Animated.ScrollView>();
|
||||
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 (
|
||||
<ThemedView style={styles.container}>
|
||||
<Animated.ScrollView ref={scrollRef} scrollEventThrottle={16}>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.header,
|
||||
{ backgroundColor: headerBackgroundColor[colorScheme] },
|
||||
headerAnimatedStyle,
|
||||
]}>
|
||||
{headerImage}
|
||||
</Animated.View>
|
||||
<ThemedView style={styles.content}>{children}</ThemedView>
|
||||
</Animated.ScrollView>
|
||||
</ThemedView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
header: {
|
||||
height: 250,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
padding: 32,
|
||||
gap: 16,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
});
|
@ -1,60 +0,0 @@
|
||||
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 (
|
||||
<Text
|
||||
style={[
|
||||
{ color },
|
||||
type === 'default' ? styles.default : undefined,
|
||||
type === 'title' ? styles.title : undefined,
|
||||
type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined,
|
||||
type === 'subtitle' ? styles.subtitle : undefined,
|
||||
type === 'link' ? styles.link : undefined,
|
||||
style,
|
||||
]}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
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',
|
||||
},
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
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 <View style={[{ backgroundColor }, style]} {...otherProps} />;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
import { ThemedText } from '../ThemedText';
|
||||
|
||||
it(`renders correctly`, () => {
|
||||
const tree = renderer.create(<ThemedText>Snapshot test!</ThemedText>).toJSON();
|
||||
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
@ -1,24 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<Text
|
||||
style={
|
||||
[
|
||||
{
|
||||
"color": "#11181C",
|
||||
},
|
||||
{
|
||||
"fontSize": 16,
|
||||
"lineHeight": 24,
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
]
|
||||
}
|
||||
>
|
||||
Snapshot test!
|
||||
</Text>
|
||||
`;
|
@ -1,9 +0,0 @@
|
||||
// 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<ComponentProps<typeof Ionicons>['name']>) {
|
||||
return <Ionicons size={28} style={[{ marginBottom: -3 }, style]} {...rest} />;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* 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,
|
||||
},
|
||||
};
|
@ -1 +0,0 @@
|
||||
export { useColorScheme } from 'react-native';
|
@ -1,8 +0,0 @@
|
||||
// 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';
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* 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];
|
||||
}
|
||||
}
|
@ -1,49 +1,32 @@
|
||||
{
|
||||
"name": "optifit-app",
|
||||
"main": "expo-router/entry",
|
||||
"name": "expo-app",
|
||||
"version": "1.0.0",
|
||||
"main": "node_modules/expo/AppEntry.js",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"reset-project": "node ./scripts/reset-project.js",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"web": "expo start --web",
|
||||
"test": "jest --watchAll",
|
||||
"lint": "expo lint"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "jest-expo"
|
||||
"web": "expo start --web"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^14.0.2",
|
||||
"@react-navigation/native": "^6.0.2",
|
||||
"expo": "~51.0.28",
|
||||
"expo-constants": "~16.0.2",
|
||||
"expo-font": "~12.0.9",
|
||||
"expo-linking": "~6.3.1",
|
||||
"expo-router": "~3.5.23",
|
||||
"expo-splash-screen": "~0.27.5",
|
||||
"expo-status-bar": "~1.12.1",
|
||||
"expo-system-ui": "~3.0.7",
|
||||
"expo-web-browser": "~13.0.3",
|
||||
"@expo/html-elements": "latest",
|
||||
"@gluestack-style/react": "latest",
|
||||
"@gluestack-ui/config": "^1.1.5",
|
||||
"@gluestack-ui/themed": "latest",
|
||||
"@legendapp/motion": "latest",
|
||||
"expo": "^51.0.8",
|
||||
"expo-status-bar": "~1.11.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native": "0.74.5",
|
||||
"react-native-gesture-handler": "~2.16.1",
|
||||
"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": "0.73.2",
|
||||
"react-native-svg": "14.1.0",
|
||||
"react-native-web": "~0.19.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@expo/webpack-config": "~19.0.1",
|
||||
"@types/react": "~18.2.45",
|
||||
"@types/react-test-renderer": "^18.0.7",
|
||||
"jest": "^29.2.1",
|
||||
"jest-expo": "~51.0.3",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "~5.3.3"
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* This script is used to reset the project to a blank state.
|
||||
* It moves the /app directory to /app-example and creates a new /app directory with an index.tsx and _layout.tsx file.
|
||||
* You can remove the `reset-project` script from package.json and safely delete this file after running it.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const root = process.cwd();
|
||||
const oldDirPath = path.join(root, 'app');
|
||||
const newDirPath = path.join(root, 'app-example');
|
||||
const newAppDirPath = path.join(root, 'app');
|
||||
|
||||
const indexContent = `import { Text, View } from "react-native";
|
||||
|
||||
export default function Index() {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Text>Edit app/index.tsx to edit this screen.</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
const layoutContent = `import { Stack } from "expo-router";
|
||||
|
||||
export default function RootLayout() {
|
||||
return (
|
||||
<Stack>
|
||||
<Stack.Screen name="index" />
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
`;
|
||||
|
||||
fs.rename(oldDirPath, newDirPath, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error renaming directory: ${error}`);
|
||||
}
|
||||
console.log('/app moved to /app-example.');
|
||||
|
||||
fs.mkdir(newAppDirPath, { recursive: true }, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error creating new app directory: ${error}`);
|
||||
}
|
||||
console.log('New /app directory created.');
|
||||
|
||||
const indexPath = path.join(newAppDirPath, 'index.tsx');
|
||||
fs.writeFile(indexPath, indexContent, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error creating index.tsx: ${error}`);
|
||||
}
|
||||
console.log('app/index.tsx created.');
|
||||
|
||||
const layoutPath = path.join(newAppDirPath, '_layout.tsx');
|
||||
fs.writeFile(layoutPath, layoutContent, (error) => {
|
||||
if (error) {
|
||||
return console.error(`Error creating _layout.tsx: ${error}`);
|
||||
}
|
||||
console.log('app/_layout.tsx created.');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,17 +1,6 @@
|
||||
{
|
||||
"extends": "expo/tsconfig.base",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".expo/types/**/*.ts",
|
||||
"expo-env.d.ts"
|
||||
]
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
|