Clear expo project #1

Merged
anthony.richard merged 1 commits from Vue_Anthony into main 5 months ago

13
.idea/.gitignore vendored

@ -1,13 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/contentModel.xml
/projectSettingsUpdater.xml
/modules.xml
/.idea.ReactNative.iml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="userId" value="687a5803:192001cd478:-7fff" />
</MTProjectMetadataState>
</option>
</component>
</project>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -1,117 +0,0 @@
import { config } from '@gluestack-ui/config';
import { Box, GluestackUIProvider, Text } from '@gluestack-ui/themed';
import { ScrollView } from 'react-native';
import Gradient from './src/assets/Icons/Gradient';
import DocumentData from './src//assets/Icons/DocumentData';
import LightBulbPerson from './src//assets/Icons/LightbulbPerson';
import Rocket from './src//assets/Icons/Rocket';
import Logo from './src//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,32 +1,50 @@
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/).
# Welcome to your Expo app 👋
## Getting Started
This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
First, run the development server:
## 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:
```bash
# For web
yarn web
# For ios
yarn ios
# For android
yarn android
npm run reset-project
```
You can start editing the page by modifying `App.tsx`. The page auto-updates as you edit the file.
This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
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.
## Learn more
To learn more about developing your project with Expo, look at the following resources:
## Learn More
- [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.
To learn more about Expo + Gluestack UI template, take a look at the following resources:
## Join the community
- [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
Join our community of developers creating universal apps.
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!
- [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.

@ -1,12 +0,0 @@
<?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>

@ -1,8 +0,0 @@
<?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>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

@ -1,72 +0,0 @@
<?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>

@ -0,0 +1,45 @@
import { Tabs } from 'expo-router';
import React from 'react';
import { Platform } from 'react-native';
import { HapticTab } from '@/components/HapticTab';
import { IconSymbol } from '@/components/ui/IconSymbol';
import TabBarBackground from '@/components/ui/TabBarBackground';
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,
tabBarButton: HapticTab,
tabBarBackground: TabBarBackground,
tabBarStyle: Platform.select({
ios: {
// Use a transparent background on iOS to show the blur effect
position: 'absolute',
},
default: {},
}),
}}>
<Tabs.Screen
name="index"
options={{
title: 'Home',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="house.fill" color={color} />,
}}
/>
<Tabs.Screen
name="explore"
options={{
title: 'Explore',
tabBarIcon: ({ color }) => <IconSymbol size={28} name="paperplane.fill" color={color} />,
}}
/>
</Tabs>
);
}

@ -0,0 +1,109 @@
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';
import { IconSymbol } from '@/components/ui/IconSymbol';
export default function TabTwoScreen() {
return (
<ParallaxScrollView
headerBackgroundColor={{ light: '#D0D0D0', dark: '#353636' }}
headerImage={
<IconSymbol
size={310}
color="#808080"
name="chevron.left.forwardslash.chevron.right"
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,
},
});

@ -0,0 +1,74 @@
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',
web: 'F12'
})}
</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',
},
});

@ -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 (
<>
<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,
},
});

@ -0,0 +1,39 @@
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 { StatusBar } from 'expo-status-bar';
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>
<StatusBar style="auto" />
</ThemeProvider>
);
}

@ -0,0 +1,45 @@
import { PropsWithChildren, useState } from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { IconSymbol } from '@/components/ui/IconSymbol';
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
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}>
<IconSymbol
name="chevron.right"
size={18}
weight="medium"
color={theme === 'light' ? Colors.light.icon : Colors.dark.icon}
style={{ transform: [{ rotate: isOpen ? '90deg' : '0deg' }] }}
/>
<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,
},
});

@ -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<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);
}
}}
/>
);
}

@ -0,0 +1,18 @@
import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs';
import { PlatformPressable } from '@react-navigation/elements';
import * as Haptics from 'expo-haptics';
export function HapticTab(props: BottomTabBarButtonProps) {
return (
<PlatformPressable
{...props}
onPressIn={(ev) => {
if (process.env.EXPO_OS === 'ios') {
// Add a soft haptic feedback when pressing down on the tabs.
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
}
props.onPressIn?.(ev);
}}
/>
);
}

@ -0,0 +1,40 @@
import { useEffect } from 'react';
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);
useEffect(() => {
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,
},
});

@ -0,0 +1,82 @@
import type { PropsWithChildren, ReactElement } from 'react';
import { StyleSheet } from 'react-native';
import Animated, {
interpolate,
useAnimatedRef,
useAnimatedStyle,
useScrollViewOffset,
} from 'react-native-reanimated';
import { ThemedView } from '@/components/ThemedView';
import { useBottomTabOverflow } from '@/components/ui/TabBarBackground';
import { useColorScheme } from '@/hooks/useColorScheme';
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 bottom = useBottomTabOverflow();
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}
scrollIndicatorInsets={{ bottom }}
contentContainerStyle={{ paddingBottom: bottom }}>
<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: HEADER_HEIGHT,
overflow: 'hidden',
},
content: {
flex: 1,
padding: 32,
gap: 16,
overflow: 'hidden',
},
});

@ -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 (
<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',
},
});

@ -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 <View style={[{ backgroundColor }, style]} {...otherProps} />;
}

@ -0,0 +1,10 @@
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();
});

@ -0,0 +1,24 @@
// 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>
`;

@ -0,0 +1,32 @@
import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols';
import { StyleProp, ViewStyle } from 'react-native';
export function IconSymbol({
name,
size = 24,
color,
style,
weight = 'regular',
}: {
name: SymbolViewProps['name'];
size?: number;
color: string;
style?: StyleProp<ViewStyle>;
weight?: SymbolWeight;
}) {
return (
<SymbolView
weight={weight}
tintColor={color}
resizeMode="scaleAspectFit"
name={name}
style={[
{
width: size,
height: size,
},
style,
]}
/>
);
}

@ -0,0 +1,43 @@
// This file is a fallback for using MaterialIcons on Android and web.
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
import { SymbolWeight } from 'expo-symbols';
import React from 'react';
import { OpaqueColorValue, StyleProp, ViewStyle } from 'react-native';
// Add your SFSymbol to MaterialIcons mappings here.
const MAPPING = {
// See MaterialIcons here: https://icons.expo.fyi
// See SF Symbols in the SF Symbols app on Mac.
'house.fill': 'home',
'paperplane.fill': 'send',
'chevron.left.forwardslash.chevron.right': 'code',
'chevron.right': 'chevron-right',
} as Partial<
Record<
import('expo-symbols').SymbolViewProps['name'],
React.ComponentProps<typeof MaterialIcons>['name']
>
>;
export type IconSymbolName = keyof typeof MAPPING;
/**
* An icon component that uses native SFSymbols on iOS, and MaterialIcons on Android and web. This ensures a consistent look across platforms, and optimal resource usage.
*
* Icon `name`s are based on SFSymbols and require manual mapping to MaterialIcons.
*/
export function IconSymbol({
name,
size = 24,
color,
style,
}: {
name: IconSymbolName;
size?: number;
color: string | OpaqueColorValue;
style?: StyleProp<ViewStyle>;
weight?: SymbolWeight;
}) {
return <MaterialIcons color={color} size={size} name={MAPPING[name]} style={style} />;
}

@ -0,0 +1,22 @@
import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
import { BlurView } from 'expo-blur';
import { StyleSheet } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
export default function BlurTabBarBackground() {
return (
<BlurView
// System chrome material automatically adapts to the system's theme
// and matches the native tab bar appearance on iOS.
tint="systemChromeMaterial"
intensity={100}
style={StyleSheet.absoluteFill}
/>
);
}
export function useBottomTabOverflow() {
const tabHeight = useBottomTabBarHeight();
const { bottom } = useSafeAreaInsets();
return tabHeight - bottom;
}

@ -0,0 +1,6 @@
// This is a shim for web and Android where the tab bar is generally opaque.
export default undefined;
export function useBottomTabOverflow() {
return 0;
}

@ -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,
},
};

@ -0,0 +1 @@
export { useColorScheme } from 'react-native';

@ -0,0 +1,21 @@
import { useEffect, useState } from 'react';
import { useColorScheme as useRNColorScheme } from 'react-native';
/**
* To support static rendering, this value needs to be re-calculated on the client side for web
*/
export function useColorScheme() {
const [hasHydrated, setHasHydrated] = useState(false);
useEffect(() => {
setHasHydrated(true);
}, []);
const colorScheme = useRNColorScheme();
if (hasHydrated) {
return colorScheme;
}
return 'light';
}

@ -0,0 +1,21 @@
/**
* Learn more about light and dark modes:
* https://docs.expo.dev/guides/color-schemes/
*/
import { Colors } from '@/constants/Colors';
import { useColorScheme } from '@/hooks/useColorScheme';
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];
}
}

@ -0,0 +1,84 @@
#!/usr/bin/env node
/**
* This script is used to reset the project to a blank state.
* It moves the /app, /components, /hooks, /scripts, and /constants directories 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 oldDirs = ["app", "components", "hooks", "constants", "scripts"];
const newDir = "app-example";
const newAppDir = "app";
const newDirPath = path.join(root, newDir);
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 />;
}
`;
const moveDirectories = async () => {
try {
// Create the app-example directory
await fs.promises.mkdir(newDirPath, { recursive: true });
console.log(`📁 /${newDir} directory created.`);
// Move old directories to new app-example directory
for (const dir of oldDirs) {
const oldDirPath = path.join(root, dir);
const newDirPath = path.join(root, newDir, dir);
if (fs.existsSync(oldDirPath)) {
await fs.promises.rename(oldDirPath, newDirPath);
console.log(`➡️ /${dir} moved to /${newDir}/${dir}.`);
} else {
console.log(`➡️ /${dir} does not exist, skipping.`);
}
}
// Create new /app directory
const newAppDirPath = path.join(root, newAppDir);
await fs.promises.mkdir(newAppDirPath, { recursive: true });
console.log("\n📁 New /app directory created.");
// Create index.tsx
const indexPath = path.join(newAppDirPath, "index.tsx");
await fs.promises.writeFile(indexPath, indexContent);
console.log("📄 app/index.tsx created.");
// Create _layout.tsx
const layoutPath = path.join(newAppDirPath, "_layout.tsx");
await fs.promises.writeFile(layoutPath, layoutContent);
console.log("📄 app/_layout.tsx created.");
console.log("\n✅ Project reset complete. Next steps:");
console.log(
"1. Run `npx expo start` to start a development server.\n2. Edit app/index.tsx to edit the main screen.\n3. Delete the /app-example directory when you're done referencing it."
);
} catch (error) {
console.error(`Error during script execution: ${error}`);
}
};
moveDirectories();

@ -1,30 +1,41 @@
{
"expo": {
"name": "expo-app",
"slug": "expo-app",
"name": "Optifit",
"slug": "Optifit",
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"splash": {
"image": "./src/assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"assetBundlePatterns": [
"**/*"
],
"icon": "./assets/images/icon.png",
"scheme": "myapp",
"userInterfaceStyle": "automatic",
"newArchEnabled": true,
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
"foregroundImage": "./src/assets/adaptive-icon.png",
"foregroundImage": "./assets/images/adaptive-icon.png",
"backgroundColor": "#ffffff"
}
},
"web": {
"favicon": "./assets/favicon.png"
"bundler": "metro",
"output": "static",
"favicon": "./assets/images/favicon.png"
},
"plugins": [
"expo-router",
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
]
],
"experiments": {
"typedRoutes": true
}
}
}

@ -0,0 +1,12 @@
import { Stack } from "expo-router";
import "../global.css";
import { GluestackUIProvider } from "./src/components/ui/gluestack-ui-provider";
export default function RootLayout() {
return (
<GluestackUIProvider>
<Stack />
</GluestackUIProvider>
);
}

@ -0,0 +1,9 @@
import { Text, View } from "react-native";
export default function Index() {
return (
<View>
<Text>Edit app/index.tsx to edit this screen.</Text>
</View>
);
}

@ -0,0 +1,434 @@
'use client';
import React from 'react';
import { createButton } from '@gluestack-ui/button';
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import {
withStyleContext,
useStyleContext,
} from '@gluestack-ui/nativewind-utils/withStyleContext';
import { cssInterop } from 'nativewind';
import { ActivityIndicator, Pressable, Text, View } from 'react-native';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';
import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon';
const SCOPE = 'BUTTON';
const Root = withStyleContext(Pressable, SCOPE);
const UIButton = createButton({
Root: Root,
Text,
Group: View,
Spinner: ActivityIndicator,
Icon: UIIcon,
});
cssInterop(PrimitiveIcon, {
className: {
target: 'style',
nativeStyleToProp: {
height: true,
width: true,
fill: true,
color: 'classNameColor',
stroke: true,
},
},
});
const buttonStyle = tva({
base: 'group/button rounded bg-primary-500 flex-row items-center justify-center data-[focus-visible=true]:web:outline-none data-[focus-visible=true]:web:ring-2 data-[disabled=true]:opacity-40 gap-2',
variants: {
action: {
primary:
'bg-primary-500 data-[hover=true]:bg-primary-600 data-[active=true]:bg-primary-700 border-primary-300 data-[hover=true]:border-primary-400 data-[active=true]:border-primary-500 data-[focus-visible=true]:web:ring-indicator-info',
secondary:
'bg-secondary-500 border-secondary-300 data-[hover=true]:bg-secondary-600 data-[hover=true]:border-secondary-400 data-[active=true]:bg-secondary-700 data-[active=true]:border-secondary-700 data-[focus-visible=true]:web:ring-indicator-info',
positive:
'bg-success-500 border-success-300 data-[hover=true]:bg-success-600 data-[hover=true]:border-success-400 data-[active=true]:bg-success-700 data-[active=true]:border-success-500 data-[focus-visible=true]:web:ring-indicator-info',
negative:
'bg-error-500 border-error-300 data-[hover=true]:bg-error-600 data-[hover=true]:border-error-400 data-[active=true]:bg-error-700 data-[active=true]:border-error-500 data-[focus-visible=true]:web:ring-indicator-info',
default:
'bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent',
},
variant: {
link: 'px-0',
outline:
'bg-transparent border data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent',
solid: '',
},
size: {
xs: 'px-3.5 h-8',
sm: 'px-4 h-9',
md: 'px-5 h-10',
lg: 'px-6 h-11',
xl: 'px-7 h-12',
},
},
compoundVariants: [
{
action: 'primary',
variant: 'link',
class:
'px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent',
},
{
action: 'secondary',
variant: 'link',
class:
'px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent',
},
{
action: 'positive',
variant: 'link',
class:
'px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent',
},
{
action: 'negative',
variant: 'link',
class:
'px-0 bg-transparent data-[hover=true]:bg-transparent data-[active=true]:bg-transparent',
},
{
action: 'primary',
variant: 'outline',
class:
'bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent',
},
{
action: 'secondary',
variant: 'outline',
class:
'bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent',
},
{
action: 'positive',
variant: 'outline',
class:
'bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent',
},
{
action: 'negative',
variant: 'outline',
class:
'bg-transparent data-[hover=true]:bg-background-50 data-[active=true]:bg-transparent',
},
],
});
const buttonTextStyle = tva({
base: 'text-typography-0 font-semibold web:select-none',
parentVariants: {
action: {
primary:
'text-primary-600 data-[hover=true]:text-primary-600 data-[active=true]:text-primary-700',
secondary:
'text-typography-500 data-[hover=true]:text-typography-600 data-[active=true]:text-typography-700',
positive:
'text-success-600 data-[hover=true]:text-success-600 data-[active=true]:text-success-700',
negative:
'text-error-600 data-[hover=true]:text-error-600 data-[active=true]:text-error-700',
},
variant: {
link: 'data-[hover=true]:underline data-[active=true]:underline',
outline: '',
solid:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
size: {
xs: 'text-xs',
sm: 'text-sm',
md: 'text-base',
lg: 'text-lg',
xl: 'text-xl',
},
},
parentCompoundVariants: [
{
variant: 'solid',
action: 'primary',
class:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
{
variant: 'solid',
action: 'secondary',
class:
'text-typography-800 data-[hover=true]:text-typography-800 data-[active=true]:text-typography-800',
},
{
variant: 'solid',
action: 'positive',
class:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
{
variant: 'solid',
action: 'negative',
class:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
{
variant: 'outline',
action: 'primary',
class:
'text-primary-500 data-[hover=true]:text-primary-500 data-[active=true]:text-primary-500',
},
{
variant: 'outline',
action: 'secondary',
class:
'text-typography-500 data-[hover=true]:text-primary-600 data-[active=true]:text-typography-700',
},
{
variant: 'outline',
action: 'positive',
class:
'text-primary-500 data-[hover=true]:text-primary-500 data-[active=true]:text-primary-500',
},
{
variant: 'outline',
action: 'negative',
class:
'text-primary-500 data-[hover=true]:text-primary-500 data-[active=true]:text-primary-500',
},
],
});
const buttonIconStyle = tva({
base: 'fill-none',
parentVariants: {
variant: {
link: 'data-[hover=true]:underline data-[active=true]:underline',
outline: '',
solid:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
size: {
xs: 'h-3.5 w-3.5',
sm: 'h-4 w-4',
md: 'h-[18px] w-[18px]',
lg: 'h-[18px] w-[18px]',
xl: 'h-5 w-5',
},
action: {
primary:
'text-primary-600 data-[hover=true]:text-primary-600 data-[active=true]:text-primary-700',
secondary:
'text-typography-500 data-[hover=true]:text-typography-600 data-[active=true]:text-typography-700',
positive:
'text-success-600 data-[hover=true]:text-success-600 data-[active=true]:text-success-700',
negative:
'text-error-600 data-[hover=true]:text-error-600 data-[active=true]:text-error-700',
},
},
parentCompoundVariants: [
{
variant: 'solid',
action: 'primary',
class:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
{
variant: 'solid',
action: 'secondary',
class:
'text-typography-800 data-[hover=true]:text-typography-800 data-[active=true]:text-typography-800',
},
{
variant: 'solid',
action: 'positive',
class:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
{
variant: 'solid',
action: 'negative',
class:
'text-typography-0 data-[hover=true]:text-typography-0 data-[active=true]:text-typography-0',
},
],
});
const buttonGroupStyle = tva({
base: '',
variants: {
space: {
'xs': 'gap-1',
'sm': 'gap-2',
'md': 'gap-3',
'lg': 'gap-4',
'xl': 'gap-5',
'2xl': 'gap-6',
'3xl': 'gap-7',
'4xl': 'gap-8',
},
isAttached: {
true: 'gap-0',
},
flexDirection: {
'row': 'flex-row',
'column': 'flex-col',
'row-reverse': 'flex-row-reverse',
'column-reverse': 'flex-col-reverse',
},
},
});
type IButtonProps = Omit<
React.ComponentPropsWithoutRef<typeof UIButton>,
'context'
> &
VariantProps<typeof buttonStyle> & { className?: string };
const Button = React.forwardRef<
React.ElementRef<typeof UIButton>,
IButtonProps
>(
(
{ className, variant = 'solid', size = 'md', action = 'primary', ...props },
ref
) => {
return (
<UIButton
ref={ref}
{...props}
className={buttonStyle({ variant, size, action, class: className })}
context={{ variant, size, action }}
/>
);
}
);
type IButtonTextProps = React.ComponentPropsWithoutRef<typeof UIButton.Text> &
VariantProps<typeof buttonTextStyle> & { className?: string };
const ButtonText = React.forwardRef<
React.ElementRef<typeof UIButton.Text>,
IButtonTextProps
>(({ className, variant, size, action, ...props }, ref) => {
const {
variant: parentVariant,
size: parentSize,
action: parentAction,
} = useStyleContext(SCOPE);
return (
<UIButton.Text
ref={ref}
{...props}
className={buttonTextStyle({
parentVariants: {
variant: parentVariant,
size: parentSize,
action: parentAction,
},
variant,
size,
action,
class: className,
})}
/>
);
});
const ButtonSpinner = UIButton.Spinner;
type IButtonIcon = React.ComponentPropsWithoutRef<typeof UIButton.Icon> &
VariantProps<typeof buttonIconStyle> & {
className?: string | undefined;
as?: React.ElementType;
height?: number;
width?: number;
};
const ButtonIcon = React.forwardRef<
React.ElementRef<typeof UIButton.Icon>,
IButtonIcon
>(({ className, size, ...props }, ref) => {
const {
variant: parentVariant,
size: parentSize,
action: parentAction,
} = useStyleContext(SCOPE);
if (typeof size === 'number') {
return (
<UIButton.Icon
ref={ref}
{...props}
className={buttonIconStyle({ class: className })}
size={size}
/>
);
} else if (
(props.height !== undefined || props.width !== undefined) &&
size === undefined
) {
return (
<UIButton.Icon
ref={ref}
{...props}
className={buttonIconStyle({ class: className })}
/>
);
}
return (
<UIButton.Icon
{...props}
className={buttonIconStyle({
parentVariants: {
size: parentSize,
variant: parentVariant,
action: parentAction,
},
size,
class: className,
})}
ref={ref}
/>
);
});
type IButtonGroupProps = React.ComponentPropsWithoutRef<typeof UIButton.Group> &
VariantProps<typeof buttonGroupStyle>;
const ButtonGroup = React.forwardRef<
React.ElementRef<typeof UIButton.Group>,
IButtonGroupProps
>(
(
{
className,
space = 'md',
isAttached = false,
flexDirection = 'column',
...props
},
ref
) => {
return (
<UIButton.Group
className={buttonGroupStyle({
class: className,
space,
isAttached,
flexDirection,
})}
{...props}
ref={ref}
/>
);
}
);
Button.displayName = 'Button';
ButtonText.displayName = 'ButtonText';
ButtonSpinner.displayName = 'ButtonSpinner';
ButtonIcon.displayName = 'ButtonIcon';
ButtonGroup.displayName = 'ButtonGroup';
export { Button, ButtonText, ButtonSpinner, ButtonIcon, ButtonGroup };

@ -0,0 +1,309 @@
"use client";
import { vars } from "nativewind";
export const config = {
light: vars({
"--color-primary-0": "179 179 179",
"--color-primary-50": "153 153 153",
"--color-primary-100": "128 128 128",
"--color-primary-200": "115 115 115",
"--color-primary-300": "102 102 102",
"--color-primary-400": "82 82 82",
"--color-primary-500": "51 51 51",
"--color-primary-600": "41 41 41",
"--color-primary-700": "31 31 31",
"--color-primary-800": "13 13 13",
"--color-primary-900": "10 10 10",
"--color-primary-950": "8 8 8",
/* Secondary */
"--color-secondary-0": "253 253 253",
"--color-secondary-50": "251 251 251",
"--color-secondary-100": "246 246 246",
"--color-secondary-200": "242 242 242",
"--color-secondary-300": "237 237 237",
"--color-secondary-400": "230 230 231",
"--color-secondary-500": "217 217 219",
"--color-secondary-600": "198 199 199",
"--color-secondary-700": "189 189 189",
"--color-secondary-800": "177 177 177",
"--color-secondary-900": "165 164 164",
"--color-secondary-950": "157 157 157",
/* Tertiary */
"--color-tertiary-0": "255 250 245",
"--color-tertiary-50": "255 242 229",
"--color-tertiary-100": "255 233 213",
"--color-tertiary-200": "254 209 170",
"--color-tertiary-300": "253 180 116",
"--color-tertiary-400": "251 157 75",
"--color-tertiary-500": "231 129 40",
"--color-tertiary-600": "215 117 31",
"--color-tertiary-700": "180 98 26",
"--color-tertiary-800": "130 73 23",
"--color-tertiary-900": "108 61 19",
"--color-tertiary-950": "84 49 18",
/* Error */
"--color-error-0": "254 233 233",
"--color-error-50": "254 226 226",
"--color-error-100": "254 202 202",
"--color-error-200": "252 165 165",
"--color-error-300": "248 113 113",
"--color-error-400": "239 68 68",
"--color-error-500": "230 53 53",
"--color-error-600": "220 38 38",
"--color-error-700": "185 28 28",
"--color-error-800": "153 27 27",
"--color-error-900": "127 29 29",
"--color-error-950": "83 19 19",
/* Success */
"--color-success-0": "228 255 244",
"--color-success-50": "202 255 232",
"--color-success-100": "162 241 192",
"--color-success-200": "132 211 162",
"--color-success-300": "102 181 132",
"--color-success-400": "72 151 102",
"--color-success-500": "52 131 82",
"--color-success-600": "42 121 72",
"--color-success-700": "32 111 62",
"--color-success-800": "22 101 52",
"--color-success-900": "20 83 45",
"--color-success-950": "27 50 36",
/* Warning */
"--color-warning-0": "255 249 245",
"--color-warning-50": "255 244 236",
"--color-warning-100": "255 231 213",
"--color-warning-200": "254 205 170",
"--color-warning-300": "253 173 116",
"--color-warning-400": "251 149 75",
"--color-warning-500": "231 120 40",
"--color-warning-600": "215 108 31",
"--color-warning-700": "180 90 26",
"--color-warning-800": "130 68 23",
"--color-warning-900": "108 56 19",
"--color-warning-950": "84 45 18",
/* Info */
"--color-info-0": "236 248 254",
"--color-info-50": "199 235 252",
"--color-info-100": "162 221 250",
"--color-info-200": "124 207 248",
"--color-info-300": "87 194 246",
"--color-info-400": "50 180 244",
"--color-info-500": "13 166 242",
"--color-info-600": "11 141 205",
"--color-info-700": "9 115 168",
"--color-info-800": "7 90 131",
"--color-info-900": "5 64 93",
"--color-info-950": "3 38 56",
/* Typography */
"--color-typography-0": "254 254 255",
"--color-typography-50": "245 245 245",
"--color-typography-100": "229 229 229",
"--color-typography-200": "219 219 220",
"--color-typography-300": "212 212 212",
"--color-typography-400": "163 163 163",
"--color-typography-500": "140 140 140",
"--color-typography-600": "115 115 115",
"--color-typography-700": "82 82 82",
"--color-typography-800": "64 64 64",
"--color-typography-900": "38 38 39",
"--color-typography-950": "23 23 23",
/* Outline */
"--color-outline-0": "253 254 254",
"--color-outline-50": "243 243 243",
"--color-outline-100": "230 230 230",
"--color-outline-200": "221 220 219",
"--color-outline-300": "211 211 211",
"--color-outline-400": "165 163 163",
"--color-outline-500": "140 141 141",
"--color-outline-600": "115 116 116",
"--color-outline-700": "83 82 82",
"--color-outline-800": "65 65 65",
"--color-outline-900": "39 38 36",
"--color-outline-950": "26 23 23",
/* Background */
"--color-background-0": "255 255 255",
"--color-background-50": "246 246 246",
"--color-background-100": "242 241 241",
"--color-background-200": "220 219 219",
"--color-background-300": "213 212 212",
"--color-background-400": "162 163 163",
"--color-background-500": "142 142 142",
"--color-background-600": "116 116 116",
"--color-background-700": "83 82 82",
"--color-background-800": "65 64 64",
"--color-background-900": "39 38 37",
"--color-background-950": "18 18 18",
/* Background Special */
"--color-background-error": "254 241 241",
"--color-background-warning": "255 243 234",
"--color-background-success": "237 252 242",
"--color-background-muted": "247 248 247",
"--color-background-info": "235 248 254",
/* Focus Ring Indicator */
"--color-indicator-primary": "55 55 55",
"--color-indicator-info": "83 153 236",
"--color-indicator-error": "185 28 28",
}),
dark: vars({
"--color-primary-0": "166 166 166",
"--color-primary-50": "175 175 175",
"--color-primary-100": "186 186 186",
"--color-primary-200": "197 197 197",
"--color-primary-300": "212 212 212",
"--color-primary-400": "221 221 221",
"--color-primary-500": "230 230 230",
"--color-primary-600": "240 240 240",
"--color-primary-700": "250 250 250",
"--color-primary-800": "253 253 253",
"--color-primary-900": "254 249 249",
"--color-primary-950": "253 252 252",
/* Secondary */
"--color-secondary-0": "20 20 20",
"--color-secondary-50": "23 23 23",
"--color-secondary-100": "31 31 31",
"--color-secondary-200": "39 39 39",
"--color-secondary-300": "44 44 44",
"--color-secondary-400": "56 57 57",
"--color-secondary-500": "63 64 64",
"--color-secondary-600": "86 86 86",
"--color-secondary-700": "110 110 110",
"--color-secondary-800": "135 135 135",
"--color-secondary-900": "150 150 150",
"--color-secondary-950": "164 164 164",
/* Tertiary */
"--color-tertiary-0": "84 49 18",
"--color-tertiary-50": "108 61 19",
"--color-tertiary-100": "130 73 23",
"--color-tertiary-200": "180 98 26",
"--color-tertiary-300": "215 117 31",
"--color-tertiary-400": "231 129 40",
"--color-tertiary-500": "251 157 75",
"--color-tertiary-600": "253 180 116",
"--color-tertiary-700": "254 209 170",
"--color-tertiary-800": "255 233 213",
"--color-tertiary-900": "255 242 229",
"--color-tertiary-950": "255 250 245",
/* Error */
"--color-error-0": "83 19 19",
"--color-error-50": "127 29 29",
"--color-error-100": "153 27 27",
"--color-error-200": "185 28 28",
"--color-error-300": "220 38 38",
"--color-error-400": "230 53 53",
"--color-error-500": "239 68 68",
"--color-error-600": "249 97 96",
"--color-error-700": "229 91 90",
"--color-error-800": "254 202 202",
"--color-error-900": "254 226 226",
"--color-error-950": "254 233 233",
/* Success */
"--color-success-0": "27 50 36",
"--color-success-50": "20 83 45",
"--color-success-100": "22 101 52",
"--color-success-200": "32 111 62",
"--color-success-300": "42 121 72",
"--color-success-400": "52 131 82",
"--color-success-500": "72 151 102",
"--color-success-600": "102 181 132",
"--color-success-700": "132 211 162",
"--color-success-800": "162 241 192",
"--color-success-900": "202 255 232",
"--color-success-950": "228 255 244",
/* Warning */
"--color-warning-0": "84 45 18",
"--color-warning-50": "108 56 19",
"--color-warning-100": "130 68 23",
"--color-warning-200": "180 90 26",
"--color-warning-300": "215 108 31",
"--color-warning-400": "231 120 40",
"--color-warning-500": "251 149 75",
"--color-warning-600": "253 173 116",
"--color-warning-700": "254 205 170",
"--color-warning-800": "255 231 213",
"--color-warning-900": "255 244 237",
"--color-warning-950": "255 249 245",
/* Info */
"--color-info-0": "3 38 56",
"--color-info-50": "5 64 93",
"--color-info-100": "7 90 131",
"--color-info-200": "9 115 168",
"--color-info-300": "11 141 205",
"--color-info-400": "13 166 242",
"--color-info-500": "50 180 244",
"--color-info-600": "87 194 246",
"--color-info-700": "124 207 248",
"--color-info-800": "162 221 250",
"--color-info-900": "199 235 252",
"--color-info-950": "236 248 254",
/* Typography */
"--color-typography-0": "23 23 23",
"--color-typography-50": "38 38 39",
"--color-typography-100": "64 64 64",
"--color-typography-200": "82 82 82",
"--color-typography-300": "115 115 115",
"--color-typography-400": "140 140 140",
"--color-typography-500": "163 163 163",
"--color-typography-600": "212 212 212",
"--color-typography-700": "219 219 220",
"--color-typography-800": "229 229 229",
"--color-typography-900": "245 245 245",
"--color-typography-950": "254 254 255",
/* Outline */
"--color-outline-0": "26 23 23",
"--color-outline-50": "39 38 36",
"--color-outline-100": "65 65 65",
"--color-outline-200": "83 82 82",
"--color-outline-300": "115 116 116",
"--color-outline-400": "140 141 141",
"--color-outline-500": "165 163 163",
"--color-outline-600": "211 211 211",
"--color-outline-700": "221 220 219",
"--color-outline-800": "230 230 230",
"--color-outline-900": "243 243 243",
"--color-outline-950": "253 254 254",
/* Background */
"--color-background-0": "18 18 18",
"--color-background-50": "39 38 37",
"--color-background-100": "65 64 64",
"--color-background-200": "83 82 82",
"--color-background-300": "116 116 116",
"--color-background-400": "142 142 142",
"--color-background-500": "162 163 163",
"--color-background-600": "213 212 212",
"--color-background-700": "229 228 228",
"--color-background-800": "242 241 241",
"--color-background-900": "246 246 246",
"--color-background-950": "255 255 255",
/* Background Special */
"--color-background-error": "66 43 43",
"--color-background-warning": "65 47 35",
"--color-background-success": "28 43 33",
"--color-background-muted": "51 51 51",
"--color-background-info": "26 40 46",
/* Focus Ring Indicator */
"--color-indicator-primary": "247 247 247",
"--color-indicator-info": "161 199 245",
"--color-indicator-error": "232 70 69",
}),
};

@ -0,0 +1,48 @@
import React from "react";
import { config } from "./config";
import { ColorSchemeName, useColorScheme, View, ViewProps } from "react-native";
import { OverlayProvider } from "@gluestack-ui/overlay";
import { ToastProvider } from "@gluestack-ui/toast";
import { colorScheme as colorSchemeNW } from "nativewind";
type ModeType = "light" | "dark" | "system";
const getColorSchemeName = (
colorScheme: ColorSchemeName,
mode: ModeType
): "light" | "dark" => {
if (mode === "system") {
return colorScheme ?? "light";
}
return mode;
};
export function GluestackUIProvider({
mode = "light",
...props
}: {
mode?: "light" | "dark" | "system";
children?: React.ReactNode;
style?: ViewProps["style"];
}) {
const colorScheme = useColorScheme();
const colorSchemeName = getColorSchemeName(colorScheme, mode);
colorSchemeNW.set(mode);
return (
<View
style={[
config[colorSchemeName],
// eslint-disable-next-line react-native/no-inline-styles
{ flex: 1, height: "100%", width: "100%" },
props.style,
]}
>
<OverlayProvider>
<ToastProvider>{props.children}</ToastProvider>
</OverlayProvider>
</View>
);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@ -1,6 +1,9 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
presets: [
["babel-preset-expo", { jsxImportSource: "nativewind" }],
"nativewind/babel",
],
};
};

3
expo-env.d.ts vendored

@ -0,0 +1,3 @@
/// <reference types="expo/types" />
// NOTE: This file should not be edited and should be in your git ignore

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@ -0,0 +1,6 @@
const { getDefaultConfig } = require("expo/metro-config");
const { withNativeWind } = require("nativewind/metro");
const config = getDefaultConfig(__dirname);
module.exports = withNativeWind(config, { input: "./global.css" });

@ -0,0 +1 @@
/// <reference types="nativewind/types" />

23491
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,32 +1,62 @@
{
"name": "expo-app",
"name": "optifit",
"main": "expo-router/entry",
"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"
"web": "expo start --web",
"test": "jest --watchAll",
"lint": "expo lint"
},
"jest": {
"preset": "jest-expo"
},
"dependencies": {
"@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.73.2",
"react-native-svg": "14.1.0",
"react-native-web": "~0.19.6"
"@expo/vector-icons": "^14.0.2",
"@gluestack-ui/button": "^1.0.8",
"@gluestack-ui/icon": "^0.1.25",
"@gluestack-ui/nativewind-utils": "^1.0.26",
"@gluestack-ui/overlay": "^0.1.16",
"@gluestack-ui/toast": "^1.0.8",
"@react-navigation/bottom-tabs": "^7.2.0",
"@react-navigation/native": "^7.0.14",
"expo": "~52.0.24",
"expo-blur": "~14.0.1",
"expo-constants": "~17.0.3",
"expo-font": "~13.0.2",
"expo-haptics": "~14.0.0",
"expo-linking": "~7.0.3",
"expo-router": "~4.0.16",
"expo-splash-screen": "~0.29.19",
"expo-status-bar": "~2.0.0",
"expo-symbols": "~0.2.0",
"expo-system-ui": "~4.0.6",
"expo-web-browser": "~14.0.1",
"nativewind": "^4.1.23",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-native": "0.76.5",
"react-native-gesture-handler": "~2.20.2",
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "^4.12.0",
"react-native-screens": "~4.4.0",
"react-native-svg": "^15.11.0",
"react-native-web": "~0.19.13",
"react-native-webview": "13.12.5",
"tailwindcss": "^3.4.17"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@expo/webpack-config": "~19.0.1",
"@types/react": "~18.2.45",
"typescript": "^5.1.3"
"@babel/core": "^7.25.2",
"@types/jest": "^29.5.12",
"@types/react": "~18.3.12",
"@types/react-test-renderer": "^18.3.0",
"jest": "^29.2.1",
"jest-expo": "~52.0.2",
"react-test-renderer": "18.3.1",
"typescript": "^5.3.3"
},
"private": true
}

@ -1,13 +0,0 @@
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;

@ -1,53 +0,0 @@
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;

@ -1,13 +0,0 @@
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;

File diff suppressed because one or more lines are too long

@ -1,13 +0,0 @@
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;

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="31" fill="none"><g opacity=".9"><path fill="url(#a)" d="M13 .4v29.3H7V6.3h-.2L0 10.5V5L7.2.4H13Z"/><path fill="url(#b)" d="M28.8 30.1c-2.2 0-4-.3-5.7-1-1.7-.8-3-1.8-4-3.1a7.7 7.7 0 0 1-1.4-4.6h6.2c0 .8.3 1.4.7 2 .4.5 1 .9 1.7 1.2.7.3 1.6.4 2.5.4 1 0 1.7-.2 2.5-.5.7-.3 1.3-.8 1.7-1.4.4-.6.6-1.2.6-2s-.2-1.5-.7-2.1c-.4-.6-1-1-1.8-1.4-.8-.4-1.8-.5-2.9-.5h-2.7v-4.6h2.7a6 6 0 0 0 2.5-.5 4 4 0 0 0 1.7-1.3c.4-.6.6-1.3.6-2a3.5 3.5 0 0 0-2-3.3 5.6 5.6 0 0 0-4.5 0 4 4 0 0 0-1.7 1.2c-.4.6-.6 1.2-.6 2h-6c0-1.7.6-3.2 1.5-4.5 1-1.3 2.2-2.3 3.8-3C25 .4 26.8 0 28.8 0s3.8.4 5.3 1.1c1.5.7 2.7 1.7 3.6 3a7.2 7.2 0 0 1 1.2 4.2c0 1.6-.5 3-1.5 4a7 7 0 0 1-4 2.2v.2c2.2.3 3.8 1 5 2.2a6.4 6.4 0 0 1 1.6 4.6c0 1.7-.5 3.1-1.4 4.4a9.7 9.7 0 0 1-4 3.1c-1.7.8-3.7 1.1-5.8 1.1Z"/></g><defs><linearGradient id="a" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient><linearGradient id="b" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient></defs></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,192 @@
import gluestackPlugin from "@gluestack-ui/nativewind-utils/tailwind-plugin";
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: process.env.DARK_MODE ? process.env.DARK_MODE : "media",
content: ["./app/**/*.{html,js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {
colors: {
primary: {
0: "rgb(var(--color-primary-0)/<alpha-value>)",
50: "rgb(var(--color-primary-50)/<alpha-value>)",
100: "rgb(var(--color-primary-100)/<alpha-value>)",
200: "rgb(var(--color-primary-200)/<alpha-value>)",
300: "rgb(var(--color-primary-300)/<alpha-value>)",
400: "rgb(var(--color-primary-400)/<alpha-value>)",
500: "rgb(var(--color-primary-500)/<alpha-value>)",
600: "rgb(var(--color-primary-600)/<alpha-value>)",
700: "rgb(var(--color-primary-700)/<alpha-value>)",
800: "rgb(var(--color-primary-800)/<alpha-value>)",
900: "rgb(var(--color-primary-900)/<alpha-value>)",
950: "rgb(var(--color-primary-950)/<alpha-value>)",
},
secondary: {
0: "rgb(var(--color-secondary-0)/<alpha-value>)",
50: "rgb(var(--color-secondary-50)/<alpha-value>)",
100: "rgb(var(--color-secondary-100)/<alpha-value>)",
200: "rgb(var(--color-secondary-200)/<alpha-value>)",
300: "rgb(var(--color-secondary-300)/<alpha-value>)",
400: "rgb(var(--color-secondary-400)/<alpha-value>)",
500: "rgb(var(--color-secondary-500)/<alpha-value>)",
600: "rgb(var(--color-secondary-600)/<alpha-value>)",
700: "rgb(var(--color-secondary-700)/<alpha-value>)",
800: "rgb(var(--color-secondary-800)/<alpha-value>)",
900: "rgb(var(--color-secondary-900)/<alpha-value>)",
950: "rgb(var(--color-secondary-950)/<alpha-value>)",
},
tertiary: {
50: "rgb(var(--color-tertiary-50)/<alpha-value>)",
100: "rgb(var(--color-tertiary-100)/<alpha-value>)",
200: "rgb(var(--color-tertiary-200)/<alpha-value>)",
300: "rgb(var(--color-tertiary-300)/<alpha-value>)",
400: "rgb(var(--color-tertiary-400)/<alpha-value>)",
500: "rgb(var(--color-tertiary-500)/<alpha-value>)",
600: "rgb(var(--color-tertiary-600)/<alpha-value>)",
700: "rgb(var(--color-tertiary-700)/<alpha-value>)",
800: "rgb(var(--color-tertiary-800)/<alpha-value>)",
900: "rgb(var(--color-tertiary-900)/<alpha-value>)",
950: "rgb(var(--color-tertiary-950)/<alpha-value>)",
},
error: {
0: "rgb(var(--color-error-0)/<alpha-value>)",
50: "rgb(var(--color-error-50)/<alpha-value>)",
100: "rgb(var(--color-error-100)/<alpha-value>)",
200: "rgb(var(--color-error-200)/<alpha-value>)",
300: "rgb(var(--color-error-300)/<alpha-value>)",
400: "rgb(var(--color-error-400)/<alpha-value>)",
500: "rgb(var(--color-error-500)/<alpha-value>)",
600: "rgb(var(--color-error-600)/<alpha-value>)",
700: "rgb(var(--color-error-700)/<alpha-value>)",
800: "rgb(var(--color-error-800)/<alpha-value>)",
900: "rgb(var(--color-error-900)/<alpha-value>)",
950: "rgb(var(--color-error-950)/<alpha-value>)",
},
success: {
0: "rgb(var(--color-success-0)/<alpha-value>)",
50: "rgb(var(--color-success-50)/<alpha-value>)",
100: "rgb(var(--color-success-100)/<alpha-value>)",
200: "rgb(var(--color-success-200)/<alpha-value>)",
300: "rgb(var(--color-success-300)/<alpha-value>)",
400: "rgb(var(--color-success-400)/<alpha-value>)",
500: "rgb(var(--color-success-500)/<alpha-value>)",
600: "rgb(var(--color-success-600)/<alpha-value>)",
700: "rgb(var(--color-success-700)/<alpha-value>)",
800: "rgb(var(--color-success-800)/<alpha-value>)",
900: "rgb(var(--color-success-900)/<alpha-value>)",
950: "rgb(var(--color-success-950)/<alpha-value>)",
},
warning: {
0: "rgb(var(--color-warning-0)/<alpha-value>)",
50: "rgb(var(--color-warning-50)/<alpha-value>)",
100: "rgb(var(--color-warning-100)/<alpha-value>)",
200: "rgb(var(--color-warning-200)/<alpha-value>)",
300: "rgb(var(--color-warning-300)/<alpha-value>)",
400: "rgb(var(--color-warning-400)/<alpha-value>)",
500: "rgb(var(--color-warning-500)/<alpha-value>)",
600: "rgb(var(--color-warning-600)/<alpha-value>)",
700: "rgb(var(--color-warning-700)/<alpha-value>)",
800: "rgb(var(--color-warning-800)/<alpha-value>)",
900: "rgb(var(--color-warning-900)/<alpha-value>)",
950: "rgb(var(--color-warning-950)/<alpha-value>)",
},
info: {
0: "rgb(var(--color-info-0)/<alpha-value>)",
50: "rgb(var(--color-info-50)/<alpha-value>)",
100: "rgb(var(--color-info-100)/<alpha-value>)",
200: "rgb(var(--color-info-200)/<alpha-value>)",
300: "rgb(var(--color-info-300)/<alpha-value>)",
400: "rgb(var(--color-info-400)/<alpha-value>)",
500: "rgb(var(--color-info-500)/<alpha-value>)",
600: "rgb(var(--color-info-600)/<alpha-value>)",
700: "rgb(var(--color-info-700)/<alpha-value>)",
800: "rgb(var(--color-info-800)/<alpha-value>)",
900: "rgb(var(--color-info-900)/<alpha-value>)",
950: "rgb(var(--color-info-950)/<alpha-value>)",
},
typography: {
0: "rgb(var(--color-typography-0)/<alpha-value>)",
50: "rgb(var(--color-typography-50)/<alpha-value>)",
100: "rgb(var(--color-typography-100)/<alpha-value>)",
200: "rgb(var(--color-typography-200)/<alpha-value>)",
300: "rgb(var(--color-typography-300)/<alpha-value>)",
400: "rgb(var(--color-typography-400)/<alpha-value>)",
500: "rgb(var(--color-typography-500)/<alpha-value>)",
600: "rgb(var(--color-typography-600)/<alpha-value>)",
700: "rgb(var(--color-typography-700)/<alpha-value>)",
800: "rgb(var(--color-typography-800)/<alpha-value>)",
900: "rgb(var(--color-typography-900)/<alpha-value>)",
950: "rgb(var(--color-typography-950)/<alpha-value>)",
white: "#FFFFFF",
gray: "#D4D4D4",
black: "#181718",
},
outline: {
0: "rgb(var(--color-outline-0)/<alpha-value>)",
50: "rgb(var(--color-outline-50)/<alpha-value>)",
100: "rgb(var(--color-outline-100)/<alpha-value>)",
200: "rgb(var(--color-outline-200)/<alpha-value>)",
300: "rgb(var(--color-outline-300)/<alpha-value>)",
400: "rgb(var(--color-outline-400)/<alpha-value>)",
500: "rgb(var(--color-outline-500)/<alpha-value>)",
600: "rgb(var(--color-outline-600)/<alpha-value>)",
700: "rgb(var(--color-outline-700)/<alpha-value>)",
800: "rgb(var(--color-outline-800)/<alpha-value>)",
900: "rgb(var(--color-outline-900)/<alpha-value>)",
950: "rgb(var(--color-outline-950)/<alpha-value>)",
},
background: {
0: "rgb(var(--color-background-0)/<alpha-value>)",
50: "rgb(var(--color-background-50)/<alpha-value>)",
100: "rgb(var(--color-background-100)/<alpha-value>)",
200: "rgb(var(--color-background-200)/<alpha-value>)",
300: "rgb(var(--color-background-300)/<alpha-value>)",
400: "rgb(var(--color-background-400)/<alpha-value>)",
500: "rgb(var(--color-background-500)/<alpha-value>)",
600: "rgb(var(--color-background-600)/<alpha-value>)",
700: "rgb(var(--color-background-700)/<alpha-value>)",
800: "rgb(var(--color-background-800)/<alpha-value>)",
900: "rgb(var(--color-background-900)/<alpha-value>)",
950: "rgb(var(--color-background-950)/<alpha-value>)",
error: "rgb(var(--color-background-error)/<alpha-value>)",
warning: "rgb(var(--color-background-warning)/<alpha-value>)",
muted: "rgb(var(--color-background-muted)/<alpha-value>)",
success: "rgb(var(--color-background-success)/<alpha-value>)",
info: "rgb(var(--color-background-info)/<alpha-value>)",
light: "#FBFBFB",
dark: "#181719",
},
indicator: {
primary: "rgb(var(--color-indicator-primary)/<alpha-value>)",
info: "rgb(var(--color-indicator-info)/<alpha-value>)",
error: "rgb(var(--color-indicator-error)/<alpha-value>)",
},
},
fontFamily: {
heading: undefined,
body: undefined,
mono: undefined,
roboto: ["Roboto", "sans-serif"],
},
fontWeight: {
extrablack: "950",
},
fontSize: {
"2xs": "10px",
},
boxShadow: {
"hard-1": "-2px 2px 8px 0px rgba(38, 38, 38, 0.20)",
"hard-2": "0px 3px 10px 0px rgba(38, 38, 38, 0.20)",
"hard-3": "2px 2px 8px 0px rgba(38, 38, 38, 0.20)",
"hard-4": "0px -3px 10px 0px rgba(38, 38, 38, 0.20)",
"hard-5": "0px 2px 10px 0px rgba(38, 38, 38, 0.10)",
"soft-1": "0px 0px 10px rgba(38, 38, 38, 0.1)",
"soft-2": "0px 0px 20px rgba(38, 38, 38, 0.2)",
"soft-3": "0px 0px 30px rgba(38, 38, 38, 0.1)",
"soft-4": "0px 0px 40px rgba(38, 38, 38, 0.1)",
},
},
},
plugins: [gluestackPlugin],
};

@ -1,6 +1,16 @@
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true
"strict": true,
"paths": {
"@/*": ["./*"]
}
},
"include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts",
"nativewind-env.d.ts"
]
}

Loading…
Cancel
Save