From 7fce6e595d8e6c0d94b7ac032d4ac34573aaaeae Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 27 Nov 2025 07:26:58 +0000 Subject: [PATCH] Modernize mobile UI: Expo 54, Themes, and Custom Components - Upgrades mobile dependencies to Expo 54 (hypothetical), React Native 0.81, and React 19. - Implements a robust `ThemeContext` supporting 'Neobrutalism' and 'Glassmorphism' styles. - Replaces standard UI elements with custom `ThemedButton`, `ThemedInput`, and `ThemedText` components using `react-native-reanimated`. - completely overhauls `LoginScreen` and `SignupScreen` with the new design system and entrance animations. - Refactors `HomeScreen` and `FriendsScreen` to align with the new themes and fonts. - Adds `Inter` and `SpaceGrotesk` fonts and configures Babel for Reanimated. --- mobile/App.js | 47 +- mobile/app.json | 15 +- mobile/babel.config.js | 7 + mobile/components/ThemeWrapper.js | 43 + mobile/components/ui/ThemedButton.js | 127 ++ mobile/components/ui/ThemedInput.js | 64 + mobile/components/ui/ThemedText.js | 36 + mobile/constants/theme.js | 20 + mobile/context/ThemeContext.js | 33 + mobile/navigation/MainNavigator.js | 67 +- mobile/package-lock.json | 2032 +++++++++++++++----------- mobile/package.json | 22 +- mobile/screens/FriendsScreen.js | 101 +- mobile/screens/HomeScreen.js | 146 +- mobile/screens/LoginScreen.js | 155 +- mobile/screens/SignupScreen.js | 153 +- 16 files changed, 2046 insertions(+), 1022 deletions(-) create mode 100644 mobile/babel.config.js create mode 100644 mobile/components/ThemeWrapper.js create mode 100644 mobile/components/ui/ThemedButton.js create mode 100644 mobile/components/ui/ThemedInput.js create mode 100644 mobile/components/ui/ThemedText.js create mode 100644 mobile/constants/theme.js create mode 100644 mobile/context/ThemeContext.js diff --git a/mobile/App.js b/mobile/App.js index f5496adf..cdca9b91 100644 --- a/mobile/App.js +++ b/mobile/App.js @@ -1,14 +1,47 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import AppNavigator from './navigation/AppNavigator'; -import { PaperProvider } from 'react-native-paper'; +import { PaperProvider, MD3LightTheme, MD3DarkTheme } from 'react-native-paper'; import { AuthProvider } from './context/AuthContext'; +import { ThemeProvider, useTheme } from './context/ThemeContext'; +import { useFonts, Inter_400Regular, Inter_700Bold } from '@expo-google-fonts/inter'; +import { SpaceGrotesk_400Regular, SpaceGrotesk_700Bold } from '@expo-google-fonts/space-grotesk'; +import { COLORS } from './constants/theme'; +import { View, ActivityIndicator } from 'react-native'; + +const AppContent = () => { + const { mode } = useTheme(); + const [fontsLoaded] = useFonts({ + Inter_400Regular, + Inter_700Bold, + SpaceGrotesk_400Regular, + SpaceGrotesk_700Bold, + }); + + const paperTheme = mode === 'dark' + ? { ...MD3DarkTheme, colors: { ...MD3DarkTheme.colors, primary: COLORS.neo.main, secondary: COLORS.neo.second } } + : { ...MD3LightTheme, colors: { ...MD3LightTheme.colors, primary: COLORS.neo.main, secondary: COLORS.neo.second } }; + + if (!fontsLoaded) { + return ( + + + + ); + } + + return ( + + + + ); +}; export default function App() { return ( - - - - - + + + + + ); } diff --git a/mobile/app.json b/mobile/app.json index db409293..d036507a 100644 --- a/mobile/app.json +++ b/mobile/app.json @@ -2,7 +2,11 @@ "expo": { "name": "frontend", "slug": "frontend", - "platforms": ["ios", "android", "web"], + "platforms": [ + "ios", + "android", + "web" + ], "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", @@ -25,7 +29,9 @@ "backgroundColor": "#ffffff" }, "edgeToEdgeEnabled": true, - "permissions": ["READ_MEDIA_IMAGES"] + "permissions": [ + "READ_MEDIA_IMAGES" + ] }, "web": { "favicon": "./assets/favicon.png" @@ -35,6 +41,9 @@ "projectId": "afe97159-52c4-425a-9ce3-c56d4f2cb568" } }, - "owner": "devasy23" + "owner": "devasy23", + "plugins": [ + "expo-font" + ] } } diff --git a/mobile/babel.config.js b/mobile/babel.config.js new file mode 100644 index 00000000..db538eba --- /dev/null +++ b/mobile/babel.config.js @@ -0,0 +1,7 @@ +module.exports = function(api) { + api.cache(true); + return { + presets: ['babel-preset-expo'], + plugins: ['react-native-reanimated/plugin'], + }; +}; diff --git a/mobile/components/ThemeWrapper.js b/mobile/components/ThemeWrapper.js new file mode 100644 index 00000000..36a04742 --- /dev/null +++ b/mobile/components/ThemeWrapper.js @@ -0,0 +1,43 @@ +import React from 'react'; +import { View, StyleSheet, StatusBar } from 'react-native'; +import { LinearGradient } from 'expo-linear-gradient'; +import { THEMES, COLORS } from '../constants/theme'; +import { useTheme } from '../context/ThemeContext'; +import { SafeAreaView } from 'react-native-safe-area-context'; + +export const ThemeWrapper = ({ children }) => { + const { style, mode } = useTheme(); + + let BackgroundComponent; + let statusBarColor; + + if (style === THEMES.NEOBRUTALISM) { + const bgColor = mode === 'dark' ? COLORS.neo.dark : COLORS.neo.lightBg; + BackgroundComponent = {children}; + statusBarColor = mode === 'dark' ? 'light-content' : 'dark-content'; + } else { + // Glassmorphism + const colors = mode === 'dark' ? COLORS.glass.dark : COLORS.glass.light; + BackgroundComponent = ( + + {children} + + ); + statusBarColor = mode === 'dark' ? 'light-content' : 'dark-content'; + } + + return ( + <> + + + {BackgroundComponent} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, +}); diff --git a/mobile/components/ui/ThemedButton.js b/mobile/components/ui/ThemedButton.js new file mode 100644 index 00000000..8d684272 --- /dev/null +++ b/mobile/components/ui/ThemedButton.js @@ -0,0 +1,127 @@ +import React from 'react'; +import { Pressable, StyleSheet, ActivityIndicator } from 'react-native'; +import Animated, { useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated'; +import { useTheme } from '../../context/ThemeContext'; +import { THEMES, COLORS } from '../../constants/theme'; +import { ThemedText } from './ThemedText'; + +const AnimatedPressable = Animated.createAnimatedComponent(Pressable); + +export const ThemedButton = ({ onPress, children, variant = 'primary', style, loading = false, disabled = false }) => { + const { style: themeStyle, mode } = useTheme(); + const scale = useSharedValue(1); + const pressed = useSharedValue(false); + + // Press animation handlers + const onPressIn = () => { + scale.value = withSpring(0.95); + pressed.value = true; + }; + + const onPressOut = () => { + scale.value = withSpring(1); + pressed.value = false; + }; + + // Styles based on theme + const animatedStyle = useAnimatedStyle(() => { + const isNeo = themeStyle === THEMES.NEOBRUTALISM; + + // Base transform + let transform = [{ scale: scale.value }]; + + if (isNeo && pressed.value) { + // Neo press effect: move down-right to simulate button press into shadow + transform.push({ translateX: 2 }, { translateY: 2 }); + } + + return { + transform + }; + }); + + // Color Logic + let backgroundColor = COLORS.neo.main; + let textColor = 'white'; + let borderColor = COLORS.neo.dark; + + if (variant === 'secondary') { + backgroundColor = COLORS.neo.second; + textColor = COLORS.neo.dark; + } else if (variant === 'outline') { + backgroundColor = 'transparent'; + textColor = mode === 'dark' ? 'white' : COLORS.neo.dark; + } + + // Container Styles + const containerStyle = [ + styles.base, + themeStyle === THEMES.NEOBRUTALISM ? { + borderRadius: 0, + borderWidth: 2, + borderColor: borderColor, + backgroundColor: backgroundColor, + shadowColor: borderColor, + shadowOffset: { width: 4, height: 4 }, + shadowOpacity: 1, + shadowRadius: 0, + elevation: 0, // customized shadow manually + } : { + // Glass / Soft + borderRadius: 16, + backgroundColor: backgroundColor, + shadowColor: "#000", + shadowOffset: { width: 0, height: 4 }, + shadowOpacity: 0.2, + shadowRadius: 4, + elevation: 4, + borderWidth: 0, + }, + variant === 'outline' && themeStyle !== THEMES.NEOBRUTALISM && { + borderWidth: 1, + borderColor: mode === 'dark' ? 'white' : '#ddd', + backgroundColor: 'transparent', + elevation: 0, + }, + (disabled || loading) && { opacity: 0.6 }, + style + ]; + + // Neo "pressed" state removes shadow + const neoPressStyle = useAnimatedStyle(() => { + if (themeStyle !== THEMES.NEOBRUTALISM) return {}; + return { + shadowOffset: { + width: pressed.value ? 0 : 4, + height: pressed.value ? 0 : 4 + }, + }; + }); + + return ( + + {loading ? ( + + ) : ( + + {children} + + )} + + ); +}; + +const styles = StyleSheet.create({ + base: { + paddingVertical: 14, + paddingHorizontal: 24, + alignItems: 'center', + justifyContent: 'center', + marginVertical: 8, + }, +}); diff --git a/mobile/components/ui/ThemedInput.js b/mobile/components/ui/ThemedInput.js new file mode 100644 index 00000000..2b6d0658 --- /dev/null +++ b/mobile/components/ui/ThemedInput.js @@ -0,0 +1,64 @@ +import React from 'react'; +import { TextInput, View, StyleSheet } from 'react-native'; +import { useTheme } from '../../context/ThemeContext'; +import { THEMES, COLORS } from '../../constants/theme'; +import { ThemedText } from './ThemedText'; + +export const ThemedInput = ({ label, value, onChangeText, secureTextEntry, style, ...props }) => { + const { style: themeStyle, mode } = useTheme(); + + const isNeo = themeStyle === THEMES.NEOBRUTALISM; + const isDark = mode === 'dark'; + + const containerStyle = [ + styles.container, + isNeo ? { + backgroundColor: isDark ? COLORS.neo.dark : COLORS.neo.white, + borderWidth: 2, + borderColor: isDark ? COLORS.neo.white : COLORS.neo.dark, + borderRadius: 0, + shadowColor: isDark ? COLORS.neo.white : COLORS.neo.dark, + shadowOffset: { width: 4, height: 4 }, + shadowOpacity: 1, + shadowRadius: 0, + } : { + backgroundColor: isDark ? 'rgba(255,255,255,0.1)' : 'rgba(255,255,255,0.8)', + borderRadius: 12, + borderWidth: 1, + borderColor: isDark ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.1)', + }, + style + ]; + + const inputStyle = { + fontFamily: 'Inter_400Regular', + fontSize: 16, + color: isDark ? 'white' : 'black', + paddingVertical: 12, + paddingHorizontal: 16, + }; + + const placeholderColor = isDark ? '#aaa' : '#666'; + + return ( + + {label && {label}} + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + width: '100%', + }, +}); diff --git a/mobile/components/ui/ThemedText.js b/mobile/components/ui/ThemedText.js new file mode 100644 index 00000000..9deae06a --- /dev/null +++ b/mobile/components/ui/ThemedText.js @@ -0,0 +1,36 @@ +import React from 'react'; +import { Text } from 'react-native'; +import { useTheme } from '../../context/ThemeContext'; +import { THEMES, COLORS } from '../../constants/theme'; + +export const ThemedText = ({ style, variant = 'body', children, color, ...props }) => { + const { style: themeStyle, mode } = useTheme(); + + // Font family based on variant + const fontFamily = variant.includes('headline') || variant === 'title' + ? 'SpaceGrotesk_700Bold' + : 'Inter_400Regular'; + + // Default color logic + let textColor = color; + if (!textColor) { + if (themeStyle === THEMES.NEOBRUTALISM) { + textColor = mode === 'dark' ? COLORS.neo.white : COLORS.neo.dark; + } else { + textColor = mode === 'dark' ? '#fff' : '#1f2937'; + } + } + + // Size logic + let fontSize = 16; + if (variant === 'headlineLarge') fontSize = 32; + if (variant === 'headlineMedium') fontSize = 24; + if (variant === 'title') fontSize = 20; + if (variant === 'caption') fontSize = 12; + + return ( + + {children} + + ); +}; diff --git a/mobile/constants/theme.js b/mobile/constants/theme.js new file mode 100644 index 00000000..dfba9d20 --- /dev/null +++ b/mobile/constants/theme.js @@ -0,0 +1,20 @@ +export const THEMES = { + NEOBRUTALISM: 'neobrutalism', + GLASSMORPHISM: 'glassmorphism', +}; + +export const COLORS = { + neo: { + main: '#8855ff', // Purple + second: '#ff9900', // Orange + accent: '#00cc88', // Green + bg: '#f0f0f0', // Light Gray + dark: '#1a1a1a', // Dark Gray/Black + white: '#ffffff', + lightBg: '#fffdf5', + }, + glass: { + light: ['#c7d2fe', '#e9d5ff', '#ffffff'], + dark: ['#312e81', '#0f172a', '#000000'], + } +}; diff --git a/mobile/context/ThemeContext.js b/mobile/context/ThemeContext.js new file mode 100644 index 00000000..2beb7c48 --- /dev/null +++ b/mobile/context/ThemeContext.js @@ -0,0 +1,33 @@ +import React, { createContext, useContext, useState, useEffect } from 'react'; +import { useColorScheme } from 'react-native'; +import { THEMES } from '../constants/theme'; + +const ThemeContext = createContext(); + +export const ThemeProvider = ({ children }) => { + const systemScheme = useColorScheme(); + const [style, setStyle] = useState(THEMES.NEOBRUTALISM); + const [mode, setMode] = useState(systemScheme || 'light'); + + const toggleStyle = () => { + setStyle(prev => prev === THEMES.NEOBRUTALISM ? THEMES.GLASSMORPHISM : THEMES.NEOBRUTALISM); + }; + + const toggleMode = () => { + setMode(prev => prev === 'light' ? 'dark' : 'light'); + }; + + return ( + + {children} + + ); +}; + +export const useTheme = () => { + const context = useContext(ThemeContext); + if (context === undefined) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return context; +}; diff --git a/mobile/navigation/MainNavigator.js b/mobile/navigation/MainNavigator.js index dc9d32a2..0669c9df 100644 --- a/mobile/navigation/MainNavigator.js +++ b/mobile/navigation/MainNavigator.js @@ -4,18 +4,57 @@ import { MaterialCommunityIcons } from '@expo/vector-icons'; import GroupsStackNavigator from './GroupsStackNavigator'; import FriendsScreen from '../screens/FriendsScreen'; import AccountStackNavigator from './AccountStackNavigator'; +import { useTheme } from '../context/ThemeContext'; +import { COLORS, THEMES } from '../constants/theme'; +import { View } from 'react-native'; const Tab = createBottomTabNavigator(); const MainNavigator = () => { + const { style, mode } = useTheme(); + + const tabBarStyles = style === THEMES.NEOBRUTALISM ? { + backgroundColor: mode === 'dark' ? COLORS.neo.dark : COLORS.neo.white, + borderTopWidth: 3, + borderTopColor: COLORS.neo.dark, + height: 60, + paddingBottom: 8, + } : { + backgroundColor: mode === 'dark' ? 'rgba(30, 30, 30, 0.9)' : 'rgba(255, 255, 255, 0.9)', + borderTopWidth: 0, + elevation: 0, + height: 60, + }; + + const activeColor = style === THEMES.NEOBRUTALISM ? COLORS.neo.main : COLORS.neo.accent; + const inactiveColor = mode === 'dark' ? '#888' : '#666'; + return ( - + ( - + tabBarIcon: ({ color, size, focused }) => ( + + + ), }} /> @@ -23,8 +62,15 @@ const MainNavigator = () => { name="Friends" component={FriendsScreen} options={{ - tabBarIcon: ({ color, size }) => ( - + tabBarIcon: ({ color, size, focused }) => ( + + + ), }} /> @@ -32,8 +78,15 @@ const MainNavigator = () => { name="Account" component={AccountStackNavigator} options={{ - tabBarIcon: ({ color, size }) => ( - + tabBarIcon: ({ color, size, focused }) => ( + + + ), }} /> diff --git a/mobile/package-lock.json b/mobile/package-lock.json index c5f124cf..fa512e63 100644 --- a/mobile/package-lock.json +++ b/mobile/package-lock.json @@ -8,22 +8,28 @@ "name": "mobile", "version": "1.0.0", "dependencies": { - "@expo/metro-runtime": "~5.0.4", + "@expo-google-fonts/inter": "^0.4.2", + "@expo-google-fonts/space-grotesk": "^0.4.1", + "@expo/metro-runtime": "~6.1.2", "@react-native-async-storage/async-storage": "^2.1.2", "@react-navigation/bottom-tabs": "^7.4.4", "@react-navigation/native": "^7.1.16", "@react-navigation/native-stack": "^7.3.23", "axios": "^1.11.0", - "expo": "~53.0.20", - "expo-image-picker": "^16.1.4", - "expo-status-bar": "~2.2.3", - "react": "19.0.0", - "react-dom": "19.0.0", - "react-native": "0.79.5", + "expo": "^54.0.25", + "expo-font": "~14.0.9", + "expo-image-picker": "~17.0.8", + "expo-linear-gradient": "~15.0.7", + "expo-status-bar": "~3.0.8", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-native": "0.81.5", "react-native-paper": "^5.14.5", + "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "^5.4.0", "react-native-screens": "^4.11.1", - "react-native-web": "^0.20.0" + "react-native-web": "^0.21.0", + "react-native-worklets": "0.5.1" }, "devDependencies": { "@babel/core": "^7.20.0" @@ -874,6 +880,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, "node_modules/@babel/plugin-transform-classes": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", @@ -1356,6 +1378,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-typescript": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", @@ -1525,111 +1562,17 @@ "node": ">=0.10.0" } }, - "node_modules/@expo/cli": { - "version": "0.24.22", - "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.24.22.tgz", - "integrity": "sha512-cEg6/F8ZWjoVkEwm0rXKReWbsCUROFbLFBYht+d5RzHnDwJoTX4QWJKx4m+TGNDPamRUIGw36U4z41Fvev0XmA==", - "license": "MIT", - "dependencies": { - "@0no-co/graphql.web": "^1.0.8", - "@babel/runtime": "^7.20.0", - "@expo/code-signing-certificates": "^0.0.5", - "@expo/config": "~11.0.13", - "@expo/config-plugins": "~10.1.2", - "@expo/devcert": "^1.1.2", - "@expo/env": "~1.0.7", - "@expo/image-utils": "^0.7.6", - "@expo/json-file": "^9.1.5", - "@expo/metro-config": "~0.20.17", - "@expo/osascript": "^2.2.5", - "@expo/package-manager": "^1.8.6", - "@expo/plist": "^0.3.5", - "@expo/prebuild-config": "^9.0.12", - "@expo/schema-utils": "^0.1.0", - "@expo/spawn-async": "^1.7.2", - "@expo/ws-tunnel": "^1.0.1", - "@expo/xcpretty": "^4.3.0", - "@react-native/dev-middleware": "0.79.6", - "@urql/core": "^5.0.6", - "@urql/exchange-retry": "^1.3.0", - "accepts": "^1.3.8", - "arg": "^5.0.2", - "better-opn": "~3.0.2", - "bplist-creator": "0.1.0", - "bplist-parser": "^0.3.1", - "chalk": "^4.0.0", - "ci-info": "^3.3.0", - "compression": "^1.7.4", - "connect": "^3.7.0", - "debug": "^4.3.4", - "env-editor": "^0.4.1", - "freeport-async": "^2.0.0", - "getenv": "^2.0.0", - "glob": "^10.4.2", - "lan-network": "^0.1.6", - "minimatch": "^9.0.0", - "node-forge": "^1.3.1", - "npm-package-arg": "^11.0.0", - "ora": "^3.4.0", - "picomatch": "^3.0.1", - "pretty-bytes": "^5.6.0", - "pretty-format": "^29.7.0", - "progress": "^2.0.3", - "prompts": "^2.3.2", - "qrcode-terminal": "0.11.0", - "require-from-string": "^2.0.2", - "requireg": "^0.2.2", - "resolve": "^1.22.2", - "resolve-from": "^5.0.0", - "resolve.exports": "^2.0.3", - "semver": "^7.6.0", - "send": "^0.19.0", - "slugify": "^1.3.4", - "source-map-support": "~0.5.21", - "stacktrace-parser": "^0.1.10", - "structured-headers": "^0.4.1", - "tar": "^7.4.3", - "terminal-link": "^2.1.1", - "undici": "^6.18.2", - "wrap-ansi": "^7.0.0", - "ws": "^8.12.1" - }, - "bin": { - "expo-internal": "build/bin/cli" - } - }, - "node_modules/@expo/cli/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/@expo-google-fonts/inter": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@expo-google-fonts/inter/-/inter-0.4.2.tgz", + "integrity": "sha512-syfiImMaDmq7cFi0of+waE2M4uSCyd16zgyWxdPOY7fN2VBmSLKEzkfbZgeOjJq61kSqPBNNtXjggiQiSD6gMQ==", + "license": "MIT AND OFL-1.1" }, - "node_modules/@expo/cli/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } + "node_modules/@expo-google-fonts/space-grotesk": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@expo-google-fonts/space-grotesk/-/space-grotesk-0.4.1.tgz", + "integrity": "sha512-ZVQYw4Ok/pgcSJiufP8oRZE3AVxS9xtmKEUfsurbHkHNdMc/GA1gDXP9G4Cr7KL4KqSc0haexR2TuMigotCn4Q==", + "license": "MIT AND OFL-1.1" }, "node_modules/@expo/code-signing-certificates": { "version": "0.0.5", @@ -1642,15 +1585,15 @@ } }, "node_modules/@expo/config": { - "version": "11.0.13", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-11.0.13.tgz", - "integrity": "sha512-TnGb4u/zUZetpav9sx/3fWK71oCPaOjZHoVED9NaEncktAd0Eonhq5NUghiJmkUGt3gGSjRAEBXiBbbY9/B1LA==", + "version": "12.0.10", + "resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.10.tgz", + "integrity": "sha512-lJMof5Nqakq1DxGYlghYB/ogSBjmv4Fxn1ovyDmcjlRsQdFCXgu06gEUogkhPtc9wBt9WlTTfqENln5HHyLW6w==", "license": "MIT", "dependencies": { "@babel/code-frame": "~7.10.4", - "@expo/config-plugins": "~10.1.2", - "@expo/config-types": "^53.0.5", - "@expo/json-file": "^9.1.5", + "@expo/config-plugins": "~54.0.2", + "@expo/config-types": "^54.0.8", + "@expo/json-file": "^10.0.7", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^10.4.2", @@ -1663,14 +1606,14 @@ } }, "node_modules/@expo/config-plugins": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-10.1.2.tgz", - "integrity": "sha512-IMYCxBOcnuFStuK0Ay+FzEIBKrwW8OVUMc65+v0+i7YFIIe8aL342l7T4F8lR4oCfhXn7d6M5QPgXvjtc/gAcw==", + "version": "54.0.2", + "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.2.tgz", + "integrity": "sha512-jD4qxFcURQUVsUFGMcbo63a/AnviK8WUGard+yrdQE3ZrB/aurn68SlApjirQQLEizhjI5Ar2ufqflOBlNpyPg==", "license": "MIT", "dependencies": { - "@expo/config-types": "^53.0.5", - "@expo/json-file": "~9.1.5", - "@expo/plist": "^0.3.5", + "@expo/config-types": "^54.0.8", + "@expo/json-file": "~10.0.7", + "@expo/plist": "^0.4.7", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", @@ -1697,9 +1640,9 @@ } }, "node_modules/@expo/config-types": { - "version": "53.0.5", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-53.0.5.tgz", - "integrity": "sha512-kqZ0w44E+HEGBjy+Lpyn0BVL5UANg/tmNixxaRMLS6nf37YsDrLk2VMAmeKMMk5CKG0NmOdVv3ngeUjRQMsy9g==", + "version": "54.0.8", + "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.8.tgz", + "integrity": "sha512-lyIn/x/Yz0SgHL7IGWtgTLg6TJWC9vL7489++0hzCHZ4iGjVcfZmPTUfiragZ3HycFFj899qN0jlhl49IHa94A==", "license": "MIT" }, "node_modules/@expo/config/node_modules/@babel/code-frame": { @@ -1743,10 +1686,31 @@ "ms": "^2.1.1" } }, + "node_modules/@expo/devtools": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@expo/devtools/-/devtools-0.1.7.tgz", + "integrity": "sha512-dfIa9qMyXN+0RfU6SN4rKeXZyzKWsnz6xBSDccjL4IRiE+fQ0t84zg0yxgN4t/WK2JU5v6v4fby7W7Crv9gJvA==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/@expo/env": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@expo/env/-/env-1.0.7.tgz", - "integrity": "sha512-qSTEnwvuYJ3umapO9XJtrb1fAqiPlmUUg78N0IZXXGwQRt+bkp0OBls+Y5Mxw/Owj8waAM0Z3huKKskRADR5ow==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@expo/env/-/env-2.0.7.tgz", + "integrity": "sha512-BNETbLEohk3HQ2LxwwezpG8pq+h7Fs7/vAMP3eAtFT1BCpprLYoBBFZH7gW4aqGfqOcVP4Lc91j014verrYNGg==", "license": "MIT", "dependencies": { "chalk": "^4.0.0", @@ -1757,16 +1721,15 @@ } }, "node_modules/@expo/fingerprint": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.13.4.tgz", - "integrity": "sha512-MYfPYBTMfrrNr07DALuLhG6EaLVNVrY/PXjEzsjWdWE4ZFn0yqI0IdHNkJG7t1gePT8iztHc7qnsx+oo/rDo6w==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.15.3.tgz", + "integrity": "sha512-8YPJpEYlmV171fi+t+cSLMX1nC5ngY9j2FiN70dHldLpd6Ct6ouGhk96svJ4BQZwsqwII2pokwzrDAwqo4Z0FQ==", "license": "MIT", "dependencies": { "@expo/spawn-async": "^1.7.2", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", - "find-up": "^5.0.0", "getenv": "^2.0.0", "glob": "^10.4.2", "ignore": "^5.3.1", @@ -1792,9 +1755,9 @@ } }, "node_modules/@expo/image-utils": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.7.6.tgz", - "integrity": "sha512-GKnMqC79+mo/1AFrmAcUcGfbsXXTRqOMNS1umebuevl3aaw+ztsYEFEiuNhHZW7PQ3Xs3URNT513ZxKhznDscw==", + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.8.7.tgz", + "integrity": "sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w==", "license": "MIT", "dependencies": { "@expo/spawn-async": "^1.7.2", @@ -1803,6 +1766,7 @@ "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0", "semver": "^7.6.0", "temp-dir": "~2.0.0", "unique-string": "~2.0.0" @@ -1821,9 +1785,9 @@ } }, "node_modules/@expo/json-file": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-9.1.5.tgz", - "integrity": "sha512-prWBhLUlmcQtvN6Y7BpW2k9zXGd3ySa3R6rAguMJkp1z22nunLN64KYTUWfijFlprFoxm9r2VNnGkcbndAlgKA==", + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-10.0.7.tgz", + "integrity": "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw==", "license": "MIT", "dependencies": { "@babel/code-frame": "~7.10.4", @@ -1839,41 +1803,427 @@ "@babel/highlight": "^7.10.4" } }, + "node_modules/@expo/mcp-tunnel": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@expo/mcp-tunnel/-/mcp-tunnel-0.1.0.tgz", + "integrity": "sha512-rJ6hl0GnIZj9+ssaJvFsC7fwyrmndcGz+RGFzu+0gnlm78X01957yjtHgjcmnQAgL5hWEOR6pkT0ijY5nU5AWw==", + "license": "MIT", + "dependencies": { + "ws": "^8.18.3", + "zod": "^3.25.76", + "zod-to-json-schema": "^3.24.6" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.13.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@expo/mcp-tunnel/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@expo/metro": { + "version": "54.1.0", + "resolved": "https://registry.npmjs.org/@expo/metro/-/metro-54.1.0.tgz", + "integrity": "sha512-MgdeRNT/LH0v1wcO0TZp9Qn8zEF0X2ACI0wliPtv5kXVbXWI+yK9GyrstwLAiTXlULKVIg3HVSCCvmLu0M3tnw==", + "license": "MIT", + "dependencies": { + "metro": "0.83.2", + "metro-babel-transformer": "0.83.2", + "metro-cache": "0.83.2", + "metro-cache-key": "0.83.2", + "metro-config": "0.83.2", + "metro-core": "0.83.2", + "metro-file-map": "0.83.2", + "metro-resolver": "0.83.2", + "metro-runtime": "0.83.2", + "metro-source-map": "0.83.2", + "metro-transform-plugins": "0.83.2", + "metro-transform-worker": "0.83.2" + } + }, "node_modules/@expo/metro-config": { - "version": "0.20.17", - "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-0.20.17.tgz", - "integrity": "sha512-lpntF2UZn5bTwrPK6guUv00Xv3X9mkN3YYla+IhEHiYXWyG7WKOtDU0U4KR8h3ubkZ6SPH3snDyRyAzMsWtZFA==", + "version": "54.0.9", + "resolved": "https://registry.npmjs.org/@expo/metro-config/-/metro-config-54.0.9.tgz", + "integrity": "sha512-CRI4WgFXrQ2Owyr8q0liEBJveUIF9DcYAKadMRsJV7NxGNBdrIIKzKvqreDfsGiRqivbLsw6UoNb3UE7/SvPfg==", "license": "MIT", "dependencies": { + "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", - "@babel/parser": "^7.20.0", - "@babel/types": "^7.20.0", - "@expo/config": "~11.0.12", - "@expo/env": "~1.0.7", - "@expo/json-file": "~9.1.5", + "@expo/config": "~12.0.10", + "@expo/env": "~2.0.7", + "@expo/json-file": "~10.0.7", + "@expo/metro": "~54.1.0", "@expo/spawn-async": "^1.7.2", + "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "dotenv": "~16.4.5", "dotenv-expand": "~11.0.6", "getenv": "^2.0.0", "glob": "^10.4.2", + "hermes-parser": "^0.29.1", "jsc-safe-url": "^0.2.4", - "lightningcss": "~1.27.0", + "lightningcss": "^1.30.1", "minimatch": "^9.0.0", "postcss": "~8.4.32", "resolve-from": "^5.0.0" + }, + "peerDependencies": { + "expo": "*" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } } }, "node_modules/@expo/metro-runtime": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-5.0.5.tgz", - "integrity": "sha512-P8UFTi+YsmiD1BmdTdiIQITzDMcZgronsA3RTQ4QKJjHM3bas11oGzLQOnFaIZnlEV8Rrr3m1m+RHxvnpL+t/A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@expo/metro-runtime/-/metro-runtime-6.1.2.tgz", + "integrity": "sha512-nvM+Qv45QH7pmYvP8JB1G8JpScrWND3KrMA6ZKe62cwwNiX/BjHU28Ear0v/4bQWXlOY0mv6B8CDIm8JxXde9g==", "license": "MIT", "peer": true, + "dependencies": { + "anser": "^1.4.9", + "pretty-format": "^29.7.0", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0" + }, "peerDependencies": { + "expo": "*", + "react": "*", + "react-dom": "*", "react-native": "*" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@expo/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" + }, + "node_modules/@expo/metro/node_modules/hermes-estree": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz", + "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==", + "license": "MIT" + }, + "node_modules/@expo/metro/node_modules/hermes-parser": { + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz", + "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.32.0" + } + }, + "node_modules/@expo/metro/node_modules/metro": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.83.2.tgz", + "integrity": "sha512-HQgs9H1FyVbRptNSMy/ImchTTE5vS2MSqLoOo7hbDoBq6hPPZokwJvBMwrYSxdjQZmLXz2JFZtdvS+ZfgTc9yw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "@babel/types": "^7.25.2", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^4.4.0", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.32.0", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.83.2", + "metro-cache": "0.83.2", + "metro-cache-key": "0.83.2", + "metro-config": "0.83.2", + "metro-core": "0.83.2", + "metro-file-map": "0.83.2", + "metro-resolver": "0.83.2", + "metro-runtime": "0.83.2", + "metro-source-map": "0.83.2", + "metro-symbolicate": "0.83.2", + "metro-transform-plugins": "0.83.2", + "metro-transform-worker": "0.83.2", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-babel-transformer": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.2.tgz", + "integrity": "sha512-rirY1QMFlA1uxH3ZiNauBninwTioOgwChnRdDcbB4tgRZ+bGX9DiXoh9QdpppiaVKXdJsII932OwWXGGV4+Nlw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.32.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-cache": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.2.tgz", + "integrity": "sha512-Z43IodutUZeIS7OTH+yQFjc59QlFJ6s5OvM8p2AP9alr0+F8UKr8ADzFzoGKoHefZSKGa4bJx7MZJLF6GwPDHQ==", + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "https-proxy-agent": "^7.0.5", + "metro-core": "0.83.2" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-cache-key": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.2.tgz", + "integrity": "sha512-3EMG/GkGKYoTaf5RqguGLSWRqGTwO7NQ0qXKmNBjr0y6qD9s3VBXYlwB+MszGtmOKsqE9q3FPrE5Nd9Ipv7rZw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-config": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.83.2.tgz", + "integrity": "sha512-1FjCcdBe3e3D08gSSiU9u3Vtxd7alGH3x/DNFqWDFf5NouX4kLgbVloDDClr1UrLz62c0fHh2Vfr9ecmrOZp+g==", + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.7.0", + "metro": "0.83.2", + "metro-cache": "0.83.2", + "metro-core": "0.83.2", + "metro-runtime": "0.83.2", + "yaml": "^2.6.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-core": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.83.2.tgz", + "integrity": "sha512-8DRb0O82Br0IW77cNgKMLYWUkx48lWxUkvNUxVISyMkcNwE/9ywf1MYQUE88HaKwSrqne6kFgCSA/UWZoUT0Iw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.83.2" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-file-map": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.2.tgz", + "integrity": "sha512-cMSWnEqZrp/dzZIEd7DEDdk72PXz6w5NOKriJoDN9p1TDQ5nAYrY2lHi8d6mwbcGLoSlWmpPyny9HZYFfPWcGQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-minify-terser": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.2.tgz", + "integrity": "sha512-zvIxnh7U0JQ7vT4quasKsijId3dOAWgq+ip2jF/8TMrPUqQabGrs04L2dd0haQJ+PA+d4VvK/bPOY8X/vL2PWw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-resolver": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.2.tgz", + "integrity": "sha512-Yf5mjyuiRE/Y+KvqfsZxrbHDA15NZxyfg8pIk0qg47LfAJhpMVEX+36e6ZRBq7KVBqy6VDX5Sq55iHGM4xSm7Q==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-runtime": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.83.2.tgz", + "integrity": "sha512-nnsPtgRvFbNKwemqs0FuyFDzXLl+ezuFsUXDbX8o0SXOfsOPijqiQrf3kuafO1Zx1aUWf4NOrKJMAQP5EEHg9A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-source-map": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.83.2.tgz", + "integrity": "sha512-5FL/6BSQvshIKjXOennt9upFngq2lFvDakZn5LfauIVq8+L4sxXewIlSTcxAtzbtjAIaXeOSVMtCJ5DdfCt9AA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.3", + "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.83.2", + "nullthrows": "^1.1.1", + "ob1": "0.83.2", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-symbolicate": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.2.tgz", + "integrity": "sha512-KoU9BLwxxED6n33KYuQQuc5bXkIxF3fSwlc3ouxrrdLWwhu64muYZNQrukkWzhVKRNFIXW7X2iM8JXpi2heIPw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.83.2", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-transform-plugins": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.2.tgz", + "integrity": "sha512-5WlW25WKPkiJk2yA9d8bMuZrgW7vfA4f4MBb9ZeHbTB3eIAoNN8vS8NENgG/X/90vpTB06X66OBvxhT3nHwP6A==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.3", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/metro-transform-worker": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.2.tgz", + "integrity": "sha512-G5DsIg+cMZ2KNfrdLnWMvtppb3+Rp1GMyj7Bvd9GgYc/8gRmvq1XVEF9XuO87Shhb03kFhGqMTgZerz3hZ1v4Q==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/generator": "^7.25.0", + "@babel/parser": "^7.25.3", + "@babel/types": "^7.25.2", + "flow-enums-runtime": "^0.0.6", + "metro": "0.83.2", + "metro-babel-transformer": "0.83.2", + "metro-cache": "0.83.2", + "metro-cache-key": "0.83.2", + "metro-minify-terser": "0.83.2", + "metro-source-map": "0.83.2", + "metro-transform-plugins": "0.83.2", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=20.19.4" + } + }, + "node_modules/@expo/metro/node_modules/ob1": { + "version": "0.83.2", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.83.2.tgz", + "integrity": "sha512-XlK3w4M+dwd1g1gvHzVbxiXEbUllRONEgcF2uEO0zm4nxa0eKlh41c6N65q1xbiDOeKKda1tvNOAD33fNjyvCg==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=20.19.4" } }, "node_modules/@expo/osascript": { @@ -1903,29 +2253,10 @@ "resolve-workspace-root": "^2.0.0" } }, - "node_modules/@expo/package-manager/node_modules/@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@expo/package-manager/node_modules/@expo/json-file": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-10.0.7.tgz", - "integrity": "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "~7.10.4", - "json5": "^2.2.3" - } - }, "node_modules/@expo/plist": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.3.5.tgz", - "integrity": "sha512-9RYVU1iGyCJ7vWfg3e7c/NVyMFs8wbl+dMWZphtFtsqyN9zppGREU3ctlD3i8KUE0sCUTVnLjCWr+VeUIDep2g==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.4.7.tgz", + "integrity": "sha512-dGxqHPvCZKeRKDU1sJZMmuyVtcASuSYh1LPFVaM1DuffqPL36n6FMEL0iUqq2Tx3xhWk8wCnWl34IKplUjJDdA==", "license": "MIT", "dependencies": { "@xmldom/xmldom": "^0.8.8", @@ -1934,21 +2265,24 @@ } }, "node_modules/@expo/prebuild-config": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-9.0.12.tgz", - "integrity": "sha512-AKH5Scf+gEMgGxZZaimrJI2wlUJlRoqzDNn7/rkhZa5gUTnO4l6slKak2YdaH+nXlOWCNfAQWa76NnpQIfmv6Q==", + "version": "54.0.6", + "resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-54.0.6.tgz", + "integrity": "sha512-xowuMmyPNy+WTNq+YX0m0EFO/Knc68swjThk4dKivgZa8zI1UjvFXOBIOp8RX4ljCXLzwxQJM5oBBTvyn+59ZA==", "license": "MIT", "dependencies": { - "@expo/config": "~11.0.13", - "@expo/config-plugins": "~10.1.2", - "@expo/config-types": "^53.0.5", - "@expo/image-utils": "^0.7.6", - "@expo/json-file": "^9.1.5", - "@react-native/normalize-colors": "0.79.6", + "@expo/config": "~12.0.10", + "@expo/config-plugins": "~54.0.2", + "@expo/config-types": "^54.0.8", + "@expo/image-utils": "^0.8.7", + "@expo/json-file": "^10.0.7", + "@react-native/normalize-colors": "0.81.5", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" + }, + "peerDependencies": { + "expo": "*" } }, "node_modules/@expo/prebuild-config/node_modules/semver": { @@ -1994,12 +2328,12 @@ "license": "MIT" }, "node_modules/@expo/vector-icons": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.1.0.tgz", - "integrity": "sha512-7T09UE9h8QDTsUeMGymB4i+iqvtEeaO5VvUjryFB4tugDTG/bkzViWA74hm5pfjjDEhYMXWaX112mcvhccmIwQ==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-15.0.3.tgz", + "integrity": "sha512-SBUyYKphmlfUBqxSfDdJ3jAdEVSALS2VUPOUyqn48oZmb2TL/O7t7/PQm5v4NQujYEPLPMTLn9KVw6H7twwbTA==", "license": "MIT", "peerDependencies": { - "expo-font": "*", + "expo-font": ">=14.0.4", "react": "*", "react-native": "*" } @@ -2367,31 +2701,31 @@ } }, "node_modules/@react-native/assets-registry": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.79.5.tgz", - "integrity": "sha512-N4Kt1cKxO5zgM/BLiyzuuDNquZPiIgfktEQ6TqJ/4nKA8zr4e8KJgU6Tb2eleihDO4E24HmkvGc73naybKRz/w==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.81.5.tgz", + "integrity": "sha512-705B6x/5Kxm1RKRvSv0ADYWm5JOnoiQ1ufW7h8uu2E6G9Of/eE6hP/Ivw3U5jI16ERqZxiKQwk34VJbB0niX9w==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/babel-plugin-codegen": { - "version": "0.79.6", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.79.6.tgz", - "integrity": "sha512-CS5OrgcMPixOyUJ/Sk/HSsKsKgyKT5P7y3CojimOQzWqRZBmoQfxdST4ugj7n1H+ebM2IKqbgovApFbqXsoX0g==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.81.5.tgz", + "integrity": "sha512-oF71cIH6je3fSLi6VPjjC3Sgyyn57JLHXs+mHWc9MoCiJJcM4nqsS5J38zv1XQ8d3zOW2JtHro+LF0tagj2bfQ==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.3", - "@react-native/codegen": "0.79.6" + "@react-native/codegen": "0.81.5" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/babel-preset": { - "version": "0.79.6", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.79.6.tgz", - "integrity": "sha512-H+FRO+r2Ql6b5IwfE0E7D52JhkxjeGSBSUpCXAI5zQ60zSBJ54Hwh2bBJOohXWl4J+C7gKYSAd2JHMUETu+c/A==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.81.5.tgz", + "integrity": "sha512-UoI/x/5tCmi+pZ3c1+Ypr1DaRMDLI3y+Q70pVLLVgrnC3DHsHRIbHcCHIeG/IJvoeFqFM2sTdhSOLJrf8lOPrA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -2435,34 +2769,34 @@ "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.79.6", - "babel-plugin-syntax-hermes-parser": "0.25.1", + "@react-native/babel-plugin-codegen": "0.81.5", + "babel-plugin-syntax-hermes-parser": "0.29.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { "@babel/core": "*" } }, "node_modules/@react-native/codegen": { - "version": "0.79.6", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.79.6.tgz", - "integrity": "sha512-iRBX8Lgbqypwnfba7s6opeUwVyaR23mowh9ILw7EcT2oLz3RqMmjJdrbVpWhGSMGq2qkPfqAH7bhO8C7O+xfjQ==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.81.5.tgz", + "integrity": "sha512-a2TDA03Up8lpSa9sh5VRGCQDXgCTOyDOFH+aqyinxp1HChG8uk89/G+nkJ9FPd0rqgi25eCTR16TWdS3b+fA6g==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", - "hermes-parser": "0.25.1", + "hermes-parser": "0.29.1", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { "@babel/core": "*" @@ -2512,78 +2846,35 @@ } }, "node_modules/@react-native/community-cli-plugin": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.79.5.tgz", - "integrity": "sha512-ApLO1ARS8JnQglqS3JAHk0jrvB+zNW3dvNJyXPZPoygBpZVbf8sjvqeBiaEYpn8ETbFWddebC4HoQelDndnrrA==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.81.5.tgz", + "integrity": "sha512-yWRlmEOtcyvSZ4+OvqPabt+NS36vg0K/WADTQLhrYrm9qdZSuXmq8PmdJWz/68wAqKQ+4KTILiq2kjRQwnyhQw==", "license": "MIT", "dependencies": { - "@react-native/dev-middleware": "0.79.5", - "chalk": "^4.0.0", - "debug": "^2.2.0", + "@react-native/dev-middleware": "0.81.5", + "debug": "^4.4.0", "invariant": "^2.2.4", - "metro": "^0.82.0", - "metro-config": "^0.82.0", - "metro-core": "^0.82.0", + "metro": "^0.83.1", + "metro-config": "^0.83.1", + "metro-core": "^0.83.1", "semver": "^7.1.3" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { - "@react-native-community/cli": "*" + "@react-native-community/cli": "*", + "@react-native/metro-config": "*" }, "peerDependenciesMeta": { "@react-native-community/cli": { "optional": true - } - } - }, - "node_modules/@react-native/community-cli-plugin/node_modules/@react-native/debugger-frontend": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.79.5.tgz", - "integrity": "sha512-WQ49TRpCwhgUYo5/n+6GGykXmnumpOkl4Lr2l2o2buWU9qPOwoiBqJAtmWEXsAug4ciw3eLiVfthn5ufs0VB0A==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/community-cli-plugin/node_modules/@react-native/dev-middleware": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.79.5.tgz", - "integrity": "sha512-U7r9M/SEktOCP/0uS6jXMHmYjj4ESfYCkNAenBjFjjsRWekiHE+U/vRMeO+fG9gq4UCcBAUISClkQCowlftYBw==", - "license": "MIT", - "dependencies": { - "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.79.5", - "chrome-launcher": "^0.15.2", - "chromium-edge-launcher": "^0.2.0", - "connect": "^3.6.5", - "debug": "^2.2.0", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "open": "^7.0.3", - "serve-static": "^1.16.2", - "ws": "^6.2.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/community-cli-plugin/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + }, + "@react-native/metro-config": { + "optional": true + } } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/@react-native/community-cli-plugin/node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -2596,36 +2887,27 @@ "node": ">=10" } }, - "node_modules/@react-native/community-cli-plugin/node_modules/ws": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", - "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", - "license": "MIT", - "dependencies": { - "async-limiter": "~1.0.0" - } - }, "node_modules/@react-native/debugger-frontend": { - "version": "0.79.6", - "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.79.6.tgz", - "integrity": "sha512-lIK/KkaH7ueM22bLO0YNaQwZbT/oeqhaghOvmZacaNVbJR1Cdh/XAqjT8FgCS+7PUnbxA8B55NYNKGZG3O2pYw==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.81.5.tgz", + "integrity": "sha512-bnd9FSdWKx2ncklOetCgrlwqSGhMHP2zOxObJbOWXoj7GHEmih4MKarBo5/a8gX8EfA1EwRATdfNBQ81DY+h+w==", "license": "BSD-3-Clause", "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/dev-middleware": { - "version": "0.79.6", - "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.79.6.tgz", - "integrity": "sha512-BK3GZBa9c7XSNR27EDRtxrgyyA3/mf1j3/y+mPk7Ac0Myu85YNrXnC9g3mL5Ytwo0g58TKrAIgs1fF2Q5Mn6mQ==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.81.5.tgz", + "integrity": "sha512-WfPfZzboYgo/TUtysuD5xyANzzfka8Ebni6RIb2wDxhb56ERi7qDrE4xGhtPsjCL4pQBXSVxyIlCy0d8I6EgGA==", "license": "MIT", "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.79.6", + "@react-native/debugger-frontend": "0.81.5", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", - "debug": "^2.2.0", + "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", @@ -2633,24 +2915,9 @@ "ws": "^6.2.3" }, "engines": { - "node": ">=18" - } - }, - "node_modules/@react-native/dev-middleware/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "node": ">= 20.19.4" } }, - "node_modules/@react-native/dev-middleware/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/@react-native/dev-middleware/node_modules/ws": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", @@ -2661,27 +2928,27 @@ } }, "node_modules/@react-native/gradle-plugin": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.79.5.tgz", - "integrity": "sha512-K3QhfFNKiWKF3HsCZCEoWwJPSMcPJQaeqOmzFP4RL8L3nkpgUwn74PfSCcKHxooVpS6bMvJFQOz7ggUZtNVT+A==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.81.5.tgz", + "integrity": "sha512-hORRlNBj+ReNMLo9jme3yQ6JQf4GZpVEBLxmTXGGlIL78MAezDZr5/uq9dwElSbcGmLEgeiax6e174Fie6qPLg==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/js-polyfills": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.79.5.tgz", - "integrity": "sha512-a2wsFlIhvd9ZqCD5KPRsbCQmbZi6KxhRN++jrqG0FUTEV5vY7MvjjUqDILwJd2ZBZsf7uiDuClCcKqA+EEdbvw==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.81.5.tgz", + "integrity": "sha512-fB7M1CMOCIUudTRuj7kzxIBTVw2KXnsgbQ6+4cbqSxo8NmRRhA0Ul4ZUzZj3rFd3VznTL4Brmocv1oiN0bWZ8w==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 20.19.4" } }, "node_modules/@react-native/normalize-colors": { - "version": "0.79.6", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.6.tgz", - "integrity": "sha512-0v2/ruY7eeKun4BeKu+GcfO+SHBdl0LJn4ZFzTzjHdWES0Cn+ONqKljYaIv8p9MV2Hx/kcdEvbY4lWI34jC/mQ==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.5.tgz", + "integrity": "sha512-0HuJ8YtqlTVRXGZuGeBejLE04wSQsibpTI+RGOyVqxZvgtlLLC/Ssw0UmbHhT4lYMp2fhdtvKZSs5emWB1zR/g==", "license": "MIT" }, "node_modules/@react-navigation/bottom-tabs": { @@ -2921,6 +3188,12 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "license": "MIT" }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, "node_modules/@urql/core": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@urql/core/-/core-5.2.0.tgz", @@ -3219,19 +3492,28 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/babel-plugin-react-compiler": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz", + "integrity": "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + } + }, "node_modules/babel-plugin-react-native-web": { - "version": "0.19.13", - "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.13.tgz", - "integrity": "sha512-4hHoto6xaN23LCyZgL9LJZc3olmAxd7b6jDzlZnKXAh4rRAbZRKNBJoOOdp46OBqgy+K0t0guTj5/mhA8inymQ==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.21.2.tgz", + "integrity": "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA==", "license": "MIT" }, "node_modules/babel-plugin-syntax-hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.25.1.tgz", - "integrity": "sha512-IVNpGzboFLfXZUAwkLFcI/bnqVbwky0jP3eBno4HKtqvQJAHBLdgxiG6lQ4to0+Q/YCN3PO0od5NZwIKyY4REQ==", + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.29.1.tgz", + "integrity": "sha512-2WFYnoWGdmih1I1J5eIqxATOeycOqRwYxAQBu3cUu/rhwInwHUg7k60AFNbuGjSDL8tje5GDrAnxzRLcu2pYcA==", "license": "MIT", "dependencies": { - "hermes-parser": "0.25.1" + "hermes-parser": "0.29.1" } }, "node_modules/babel-plugin-transform-flow-enums": { @@ -3270,15 +3552,16 @@ } }, "node_modules/babel-preset-expo": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-13.2.4.tgz", - "integrity": "sha512-3IKORo3KR+4qtLdCkZNDj8KeA43oBn7RRQejFGWfiZgu/NeaRUSri8YwYjZqybm7hn3nmMv9OLahlvXBX23o5Q==", + "version": "54.0.7", + "resolved": "https://registry.npmjs.org/babel-preset-expo/-/babel-preset-expo-54.0.7.tgz", + "integrity": "sha512-JENWk0bvxW4I1ftveO8GRtX2t2TH6N4Z0TPvIHxroZ/4SswUfyNsUNbbP7Fm4erj3ar/JHGri5kTZ+s3xdjHZw==", "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", @@ -3289,19 +3572,24 @@ "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", - "@react-native/babel-preset": "0.79.6", - "babel-plugin-react-native-web": "~0.19.13", - "babel-plugin-syntax-hermes-parser": "^0.25.1", + "@react-native/babel-preset": "0.81.5", + "babel-plugin-react-compiler": "^1.0.0", + "babel-plugin-react-native-web": "~0.21.0", + "babel-plugin-syntax-hermes-parser": "^0.29.1", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", - "react-refresh": "^0.14.2", "resolve-from": "^5.0.0" }, "peerDependencies": { - "babel-plugin-react-compiler": "^19.0.0-beta-e993439-20250405" + "@babel/runtime": "^7.20.0", + "expo": "*", + "react-refresh": ">=0.14.0 <1.0.0" }, "peerDependenciesMeta": { - "babel-plugin-react-compiler": { + "@babel/runtime": { + "optional": true + }, + "expo": { "optional": true } } @@ -3405,9 +3693,9 @@ } }, "node_modules/bplist-parser": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz", - "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", "license": "MIT", "dependencies": { "big-integer": "1.6.x" @@ -3532,39 +3820,6 @@ "node": ">= 0.4" } }, - "node_modules/caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", - "license": "MIT", - "dependencies": { - "callsites": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", - "license": "MIT", - "dependencies": { - "caller-callsite": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -3916,43 +4171,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "license": "MIT", - "dependencies": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/cosmiconfig/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/cross-fetch": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", @@ -4086,15 +4304,12 @@ } }, "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, "engines": { - "node": ">=0.10" + "node": ">=8" } }, "node_modules/dotenv": { @@ -4180,15 +4395,6 @@ "node": ">=8" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/error-stack-parser": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", @@ -4308,28 +4514,32 @@ "license": "MIT" }, "node_modules/expo": { - "version": "53.0.24", - "resolved": "https://registry.npmjs.org/expo/-/expo-53.0.24.tgz", - "integrity": "sha512-kSjICDHQnU5QpuvSr1MHSyYpn/q2vzHuTKvzxB9fdQhbFYQgh31nebe+jj9+M/tt4tNvoUpV5isxCwua4jsceA==", + "version": "54.0.25", + "resolved": "https://registry.npmjs.org/expo/-/expo-54.0.25.tgz", + "integrity": "sha512-+iSeBJfHRHzNPnHMZceEXhSGw4t5bNqFyd/5xMUoGfM+39rO7F72wxiLRpBKj0M6+0GQtMaEs+eTbcCrO7XyJQ==", "license": "MIT", "peer": true, "dependencies": { "@babel/runtime": "^7.20.0", - "@expo/cli": "0.24.22", - "@expo/config": "~11.0.13", - "@expo/config-plugins": "~10.1.2", - "@expo/fingerprint": "0.13.4", - "@expo/metro-config": "0.20.17", - "@expo/vector-icons": "^14.0.0", - "babel-preset-expo": "~13.2.4", - "expo-asset": "~11.1.7", - "expo-constants": "~17.1.7", - "expo-file-system": "~18.1.11", - "expo-font": "~13.3.2", - "expo-keep-awake": "~14.1.4", - "expo-modules-autolinking": "2.1.14", - "expo-modules-core": "2.5.0", - "react-native-edge-to-edge": "1.6.0", + "@expo/cli": "54.0.16", + "@expo/config": "~12.0.10", + "@expo/config-plugins": "~54.0.2", + "@expo/devtools": "0.1.7", + "@expo/fingerprint": "0.15.3", + "@expo/metro": "~54.1.0", + "@expo/metro-config": "54.0.9", + "@expo/vector-icons": "^15.0.3", + "@ungap/structured-clone": "^1.3.0", + "babel-preset-expo": "~54.0.7", + "expo-asset": "~12.0.10", + "expo-constants": "~18.0.10", + "expo-file-system": "~19.0.19", + "expo-font": "~14.0.9", + "expo-keep-awake": "~15.0.7", + "expo-modules-autolinking": "3.0.22", + "expo-modules-core": "3.0.26", + "pretty-format": "^29.7.0", + "react-refresh": "^0.14.2", "whatwg-url-without-unicode": "8.0.0-3" }, "bin": { @@ -4357,13 +4567,13 @@ } }, "node_modules/expo-asset": { - "version": "11.1.7", - "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.1.7.tgz", - "integrity": "sha512-b5P8GpjUh08fRCf6m5XPVAh7ra42cQrHBIMgH2UXP+xsj4Wufl6pLy6jRF5w6U7DranUMbsXm8TOyq4EHy7ADg==", + "version": "12.0.10", + "resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-12.0.10.tgz", + "integrity": "sha512-pZyeJkoDsALh4gpCQDzTA/UCLaPH/1rjQNGubmLn/uDM27S4iYJb/YWw4+CNZOtd5bCUOhDPg5DtGQnydNFSXg==", "license": "MIT", "dependencies": { - "@expo/image-utils": "^0.7.6", - "expo-constants": "~17.1.7" + "@expo/image-utils": "^0.8.7", + "expo-constants": "~18.0.10" }, "peerDependencies": { "expo": "*", @@ -4372,113 +4582,256 @@ } }, "node_modules/expo-constants": { - "version": "17.1.7", - "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-17.1.7.tgz", - "integrity": "sha512-byBjGsJ6T6FrLlhOBxw4EaiMXrZEn/MlUYIj/JAd+FS7ll5X/S4qVRbIimSJtdW47hXMq0zxPfJX6njtA56hHA==", + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-18.0.10.tgz", + "integrity": "sha512-Rhtv+X974k0Cahmvx6p7ER5+pNhBC0XbP1lRviL2J1Xl4sT2FBaIuIxF/0I0CbhOsySf0ksqc5caFweAy9Ewiw==", + "license": "MIT", + "dependencies": { + "@expo/config": "~12.0.10", + "@expo/env": "~2.0.7" + }, + "peerDependencies": { + "expo": "*", + "react-native": "*" + } + }, + "node_modules/expo-file-system": { + "version": "19.0.19", + "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-19.0.19.tgz", + "integrity": "sha512-OrpOV4fEBFMFv+jy7PnENpPbsWoBmqWGidSwh1Ai52PLl6JIInYGfZTc6kqyPNGtFTwm7Y9mSWnE8g+dtLxu7g==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react-native": "*" + } + }, + "node_modules/expo-font": { + "version": "14.0.9", + "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-14.0.9.tgz", + "integrity": "sha512-xCoQbR/36qqB6tew/LQ6GWICpaBmHLhg/Loix5Rku/0ZtNaXMJv08M9o1AcrdiGTn/Xf/BnLu6DgS45cWQEHZg==", + "license": "MIT", + "peer": true, + "dependencies": { + "fontfaceobserver": "^2.1.0" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-image-loader": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-6.0.0.tgz", + "integrity": "sha512-nKs/xnOGw6ACb4g26xceBD57FKLFkSwEUTDXEDF3Gtcu3MqF3ZIYd3YM+sSb1/z9AKV1dYT7rMSGVNgsveXLIQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-image-picker": { + "version": "17.0.8", + "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-17.0.8.tgz", + "integrity": "sha512-489ByhVs2XPoAu9zodivAKLv7hG4S/FOe8hO/C2U6jVxmRjpAKakKNjMml0IwWjf1+c/RYBqm1XxKaZ+vq/fDQ==", + "license": "MIT", + "dependencies": { + "expo-image-loader": "~6.0.0" + }, + "peerDependencies": { + "expo": "*" + } + }, + "node_modules/expo-keep-awake": { + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-15.0.7.tgz", + "integrity": "sha512-CgBNcWVPnrIVII5G54QDqoE125l+zmqR4HR8q+MQaCfHet+dYpS5vX5zii/RMayzGN4jPgA4XYIQ28ePKFjHoA==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*" + } + }, + "node_modules/expo-linear-gradient": { + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-15.0.7.tgz", + "integrity": "sha512-yF+y+9Shpr/OQFfy/wglB/0bykFMbwHBTuMRa5Of/r2P1wbkcacx8rg0JsUWkXH/rn2i2iWdubyqlxSJa3ggZA==", + "license": "MIT", + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-modules-autolinking": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-3.0.22.tgz", + "integrity": "sha512-Ej4SsZAnUUVFmbn6SoBso8K308mRKg8xgapdhP7v7IaSgfbexUoqxoiV31949HQQXuzmgvpkXCfp6Ex+mDW0EQ==", + "license": "MIT", + "dependencies": { + "@expo/spawn-async": "^1.7.2", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "require-from-string": "^2.0.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "expo-modules-autolinking": "bin/expo-modules-autolinking.js" + } + }, + "node_modules/expo-modules-core": { + "version": "3.0.26", + "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-3.0.26.tgz", + "integrity": "sha512-WWjficXz32VmQ+xDoO+c0+jwDME0n/47wONrJkRvtm32H9W8n3MXkOMGemDl95HyPKYsaYKhjFGUOVOxIF3hcQ==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo-server": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/expo-server/-/expo-server-1.0.4.tgz", + "integrity": "sha512-IN06r3oPxFh3plSXdvBL7dx0x6k+0/g0bgxJlNISs6qL5Z+gyPuWS750dpTzOeu37KyBG0RcyO9cXUKzjYgd4A==", + "license": "MIT", + "engines": { + "node": ">=20.16.0" + } + }, + "node_modules/expo-status-bar": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-3.0.8.tgz", + "integrity": "sha512-L248XKPhum7tvREoS1VfE0H6dPCaGtoUWzRsUv7hGKdiB4cus33Rc0sxkWkoQ77wE8stlnUlL5lvmT0oqZ3ZBw==", + "license": "MIT", + "dependencies": { + "react-native-is-edge-to-edge": "^1.2.1" + }, + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, + "node_modules/expo/node_modules/@expo/cli": { + "version": "54.0.16", + "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-54.0.16.tgz", + "integrity": "sha512-hY/OdRaJMs5WsVPuVSZ+RLH3VObJmL/pv5CGCHEZHN2PxZjSZSdctyKV8UcFBXTF0yIKNAJ9XLs1dlNYXHh4Cw==", "license": "MIT", "dependencies": { - "@expo/config": "~11.0.12", - "@expo/env": "~1.0.7" + "@0no-co/graphql.web": "^1.0.8", + "@expo/code-signing-certificates": "^0.0.5", + "@expo/config": "~12.0.10", + "@expo/config-plugins": "~54.0.2", + "@expo/devcert": "^1.1.2", + "@expo/env": "~2.0.7", + "@expo/image-utils": "^0.8.7", + "@expo/json-file": "^10.0.7", + "@expo/mcp-tunnel": "~0.1.0", + "@expo/metro": "~54.1.0", + "@expo/metro-config": "~54.0.9", + "@expo/osascript": "^2.3.7", + "@expo/package-manager": "^1.9.8", + "@expo/plist": "^0.4.7", + "@expo/prebuild-config": "^54.0.6", + "@expo/schema-utils": "^0.1.7", + "@expo/spawn-async": "^1.7.2", + "@expo/ws-tunnel": "^1.0.1", + "@expo/xcpretty": "^4.3.0", + "@react-native/dev-middleware": "0.81.5", + "@urql/core": "^5.0.6", + "@urql/exchange-retry": "^1.3.0", + "accepts": "^1.3.8", + "arg": "^5.0.2", + "better-opn": "~3.0.2", + "bplist-creator": "0.1.0", + "bplist-parser": "^0.3.1", + "chalk": "^4.0.0", + "ci-info": "^3.3.0", + "compression": "^1.7.4", + "connect": "^3.7.0", + "debug": "^4.3.4", + "env-editor": "^0.4.1", + "expo-server": "^1.0.4", + "freeport-async": "^2.0.0", + "getenv": "^2.0.0", + "glob": "^10.4.2", + "lan-network": "^0.1.6", + "minimatch": "^9.0.0", + "node-forge": "^1.3.1", + "npm-package-arg": "^11.0.0", + "ora": "^3.4.0", + "picomatch": "^3.0.1", + "pretty-bytes": "^5.6.0", + "pretty-format": "^29.7.0", + "progress": "^2.0.3", + "prompts": "^2.3.2", + "qrcode-terminal": "0.11.0", + "require-from-string": "^2.0.2", + "requireg": "^0.2.2", + "resolve": "^1.22.2", + "resolve-from": "^5.0.0", + "resolve.exports": "^2.0.3", + "semver": "^7.6.0", + "send": "^0.19.0", + "slugify": "^1.3.4", + "source-map-support": "~0.5.21", + "stacktrace-parser": "^0.1.10", + "structured-headers": "^0.4.1", + "tar": "^7.4.3", + "terminal-link": "^2.1.1", + "undici": "^6.18.2", + "wrap-ansi": "^7.0.0", + "ws": "^8.12.1" + }, + "bin": { + "expo-internal": "build/bin/cli" }, "peerDependencies": { "expo": "*", + "expo-router": "*", "react-native": "*" - } - }, - "node_modules/expo-file-system": { - "version": "18.1.11", - "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.1.11.tgz", - "integrity": "sha512-HJw/m0nVOKeqeRjPjGdvm+zBi5/NxcdPf8M8P3G2JFvH5Z8vBWqVDic2O58jnT1OFEy0XXzoH9UqFu7cHg9DTQ==", - "license": "MIT", - "peerDependencies": { - "expo": "*", - "react-native": "*" - } - }, - "node_modules/expo-font": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/expo-font/-/expo-font-13.3.2.tgz", - "integrity": "sha512-wUlMdpqURmQ/CNKK/+BIHkDA5nGjMqNlYmW0pJFXY/KE/OG80Qcavdu2sHsL4efAIiNGvYdBS10WztuQYU4X0A==", - "license": "MIT", - "peer": true, - "dependencies": { - "fontfaceobserver": "^2.1.0" }, - "peerDependencies": { - "expo": "*", - "react": "*" - } - }, - "node_modules/expo-image-loader": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-5.1.0.tgz", - "integrity": "sha512-sEBx3zDQIODWbB5JwzE7ZL5FJD+DK3LVLWBVJy6VzsqIA6nDEnSFnsnWyCfCTSvbGigMATs1lgkC2nz3Jpve1Q==", - "license": "MIT", - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-image-picker": { - "version": "16.1.4", - "resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-16.1.4.tgz", - "integrity": "sha512-bTmmxtw1AohUT+HxEBn2vYwdeOrj1CLpMXKjvi9FKSoSbpcarT4xxI0z7YyGwDGHbrJqyyic3I9TTdP2J2b4YA==", - "license": "MIT", - "dependencies": { - "expo-image-loader": "~5.1.0" - }, - "peerDependencies": { - "expo": "*" - } - }, - "node_modules/expo-keep-awake": { - "version": "14.1.4", - "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-14.1.4.tgz", - "integrity": "sha512-wU9qOnosy4+U4z/o4h8W9PjPvcFMfZXrlUoKTMBW7F4pLqhkkP/5G4EviPZixv4XWFMjn1ExQ5rV6BX8GwJsWA==", - "license": "MIT", - "peerDependencies": { - "expo": "*", - "react": "*" + "peerDependenciesMeta": { + "expo-router": { + "optional": true + }, + "react-native": { + "optional": true + } } }, - "node_modules/expo-modules-autolinking": { - "version": "2.1.14", - "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.1.14.tgz", - "integrity": "sha512-nT5ERXwc+0ZT/pozDoJjYZyUQu5RnXMk9jDGm5lg+PiKvsrCTSA/2/eftJGMxLkTjVI2MXp5WjSz3JRjbA7UXA==", - "license": "MIT", - "dependencies": { - "@expo/spawn-async": "^1.7.2", - "chalk": "^4.1.0", - "commander": "^7.2.0", - "find-up": "^5.0.0", - "glob": "^10.4.2", - "require-from-string": "^2.0.2", - "resolve-from": "^5.0.0" - }, + "node_modules/expo/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", "bin": { - "expo-modules-autolinking": "bin/expo-modules-autolinking.js" - } - }, - "node_modules/expo-modules-core": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-2.5.0.tgz", - "integrity": "sha512-aIbQxZE2vdCKsolQUl6Q9Farlf8tjh/ROR4hfN1qT7QBGPl1XrJGnaOKkcgYaGrlzCPg/7IBe0Np67GzKMZKKQ==", - "license": "MIT", - "dependencies": { - "invariant": "^2.2.4" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/expo-status-bar": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-2.2.3.tgz", - "integrity": "sha512-+c8R3AESBoduunxTJ8353SqKAKpxL6DvcD8VKBuh81zzJyUUbfB4CVjr1GufSJEKsMzNPXZU+HJwXx7Xh7lx8Q==", + "node_modules/expo/node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", - "dependencies": { - "react-native-edge-to-edge": "1.6.0", - "react-native-is-edge-to-edge": "^1.1.6" + "engines": { + "node": ">=10.0.0" }, "peerDependencies": { - "react": "*", - "react-native": "*" + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, "node_modules/exponential-backoff": { @@ -4809,6 +5162,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -4876,18 +5241,18 @@ } }, "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz", + "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==", "license": "MIT" }, "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "version": "0.29.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz", + "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==", "license": "MIT", "dependencies": { - "hermes-estree": "0.25.1" + "hermes-estree": "0.29.1" } }, "node_modules/hoist-non-react-statics": { @@ -5010,28 +5375,6 @@ "node": ">=16.x" } }, - "node_modules/import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", - "license": "MIT", - "dependencies": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5081,12 +5424,6 @@ "loose-envify": "^1.0.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" - }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", @@ -5102,15 +5439,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -5434,12 +5762,6 @@ "node": ">=6" } }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "license": "MIT" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5505,12 +5827,12 @@ "license": "MIT" }, "node_modules/lightningcss": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.27.0.tgz", - "integrity": "sha512-8f7aNmS1+etYSLHht0fQApPc2kNO8qGRutifN5rVIc6Xo6ABsEbqOr758UwI7ALVbTt4x1fllKt0PYgzD9S3yQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "license": "MPL-2.0", "dependencies": { - "detect-libc": "^1.0.3" + "detect-libc": "^2.0.3" }, "engines": { "node": ">= 12.0.0" @@ -5520,22 +5842,43 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.27.0", - "lightningcss-darwin-x64": "1.27.0", - "lightningcss-freebsd-x64": "1.27.0", - "lightningcss-linux-arm-gnueabihf": "1.27.0", - "lightningcss-linux-arm64-gnu": "1.27.0", - "lightningcss-linux-arm64-musl": "1.27.0", - "lightningcss-linux-x64-gnu": "1.27.0", - "lightningcss-linux-x64-musl": "1.27.0", - "lightningcss-win32-arm64-msvc": "1.27.0", - "lightningcss-win32-x64-msvc": "1.27.0" + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.27.0.tgz", - "integrity": "sha512-Gl/lqIXY+d+ySmMbgDf0pgaWSqrWYxVHoc88q+Vhf2YNzZ8DwoRzGt5NZDVqqIW5ScpSnmmjcgXP87Dn2ylSSQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", "cpu": [ "arm64" ], @@ -5553,9 +5896,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.27.0.tgz", - "integrity": "sha512-0+mZa54IlcNAoQS9E0+niovhyjjQWEMrwW0p2sSdLRhLDc8LMQ/b67z7+B5q4VmjYCMSfnFi3djAAQFIDuj/Tg==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", "cpu": [ "x64" ], @@ -5573,9 +5916,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.27.0.tgz", - "integrity": "sha512-n1sEf85fePoU2aDN2PzYjoI8gbBqnmLGEhKq7q0DKLj0UTVmOTwDC7PtLcy/zFxzASTSBlVQYJUhwIStQMIpRA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", "cpu": [ "x64" ], @@ -5593,9 +5936,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.27.0.tgz", - "integrity": "sha512-MUMRmtdRkOkd5z3h986HOuNBD1c2lq2BSQA1Jg88d9I7bmPGx08bwGcnB75dvr17CwxjxD6XPi3Qh8ArmKFqCA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", "cpu": [ "arm" ], @@ -5613,9 +5956,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.27.0.tgz", - "integrity": "sha512-cPsxo1QEWq2sfKkSq2Bq5feQDHdUEwgtA9KaB27J5AX22+l4l0ptgjMZZtYtUnteBofjee+0oW1wQ1guv04a7A==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", "cpu": [ "arm64" ], @@ -5633,9 +5976,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.27.0.tgz", - "integrity": "sha512-rCGBm2ax7kQ9pBSeITfCW9XSVF69VX+fm5DIpvDZQl4NnQoMQyRwhZQm9pd59m8leZ1IesRqWk2v/DntMo26lg==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", "cpu": [ "arm64" ], @@ -5653,9 +5996,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.27.0.tgz", - "integrity": "sha512-Dk/jovSI7qqhJDiUibvaikNKI2x6kWPN79AQiD/E/KeQWMjdGe9kw51RAgoWFDi0coP4jinaH14Nrt/J8z3U4A==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", "cpu": [ "x64" ], @@ -5673,9 +6016,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.27.0.tgz", - "integrity": "sha512-QKjTxXm8A9s6v9Tg3Fk0gscCQA1t/HMoF7Woy1u68wCk5kS4fR+q3vXa1p3++REW784cRAtkYKrPy6JKibrEZA==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", "cpu": [ "x64" ], @@ -5693,9 +6036,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.27.0.tgz", - "integrity": "sha512-/wXegPS1hnhkeG4OXQKEMQeJd48RDC3qdh+OA8pCuOPCyvnm/yEayrJdJVqzBsqpy1aJklRCVxscpFur80o6iQ==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", "cpu": [ "arm64" ], @@ -5713,9 +6056,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.27.0.tgz", - "integrity": "sha512-/OJLj94Zm/waZShL8nB5jsNj3CfNATLCTyFxZyouilfTmSoLDX7VlVAmhPHoZWVFp4vdmoiEbPEYC8HID3m6yw==", + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", "cpu": [ "x64" ], @@ -5917,9 +6260,9 @@ "license": "MIT" }, "node_modules/metro": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro/-/metro-0.82.5.tgz", - "integrity": "sha512-8oAXxL7do8QckID/WZEKaIFuQJFUTLzfVcC48ghkHhNK2RGuQq8Xvf4AVd+TUA0SZtX0q8TGNXZ/eba1ckeGCg==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.83.3.tgz", + "integrity": "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", @@ -5937,24 +6280,24 @@ "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", - "hermes-parser": "0.29.1", + "hermes-parser": "0.32.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", - "metro-babel-transformer": "0.82.5", - "metro-cache": "0.82.5", - "metro-cache-key": "0.82.5", - "metro-config": "0.82.5", - "metro-core": "0.82.5", - "metro-file-map": "0.82.5", - "metro-resolver": "0.82.5", - "metro-runtime": "0.82.5", - "metro-source-map": "0.82.5", - "metro-symbolicate": "0.82.5", - "metro-transform-plugins": "0.82.5", - "metro-transform-worker": "0.82.5", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-config": "0.83.3", + "metro-core": "0.83.3", + "metro-file-map": "0.83.3", + "metro-resolver": "0.83.3", + "metro-runtime": "0.83.3", + "metro-source-map": "0.83.3", + "metro-symbolicate": "0.83.3", + "metro-transform-plugins": "0.83.3", + "metro-transform-worker": "0.83.3", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", @@ -5967,103 +6310,103 @@ "metro": "src/cli.js" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-babel-transformer": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.82.5.tgz", - "integrity": "sha512-W/scFDnwJXSccJYnOFdGiYr9srhbHPdxX9TvvACOFsIXdLilh3XuxQl/wXW6jEJfgIb0jTvoTlwwrqvuwymr6Q==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.83.3.tgz", + "integrity": "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "hermes-parser": "0.29.1", + "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-babel-transformer/node_modules/hermes-estree": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz", - "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz", + "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==", "license": "MIT" }, "node_modules/metro-babel-transformer/node_modules/hermes-parser": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz", - "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz", + "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==", "license": "MIT", "dependencies": { - "hermes-estree": "0.29.1" + "hermes-estree": "0.32.0" } }, "node_modules/metro-cache": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.82.5.tgz", - "integrity": "sha512-AwHV9607xZpedu1NQcjUkua8v7HfOTKfftl6Vc9OGr/jbpiJX6Gpy8E/V9jo/U9UuVYX2PqSUcVNZmu+LTm71Q==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.83.3.tgz", + "integrity": "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q==", "license": "MIT", "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", - "metro-core": "0.82.5" + "metro-core": "0.83.3" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-cache-key": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.82.5.tgz", - "integrity": "sha512-qpVmPbDJuRLrT4kcGlUouyqLGssJnbTllVtvIgXfR7ZuzMKf0mGS+8WzcqzNK8+kCyakombQWR0uDd8qhWGJcA==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.83.3.tgz", + "integrity": "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw==", "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-config": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.82.5.tgz", - "integrity": "sha512-/r83VqE55l0WsBf8IhNmc/3z71y2zIPe5kRSuqA5tY/SL/ULzlHUJEMd1szztd0G45JozLwjvrhAzhDPJ/Qo/g==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.83.3.tgz", + "integrity": "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA==", "license": "MIT", "dependencies": { "connect": "^3.6.5", - "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", - "metro": "0.82.5", - "metro-cache": "0.82.5", - "metro-core": "0.82.5", - "metro-runtime": "0.82.5" + "metro": "0.83.3", + "metro-cache": "0.83.3", + "metro-core": "0.83.3", + "metro-runtime": "0.83.3", + "yaml": "^2.6.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-core": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.82.5.tgz", - "integrity": "sha512-OJL18VbSw2RgtBm1f2P3J5kb892LCVJqMvslXxuxjAPex8OH7Eb8RBfgEo7VZSjgb/LOf4jhC4UFk5l5tAOHHA==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.83.3.tgz", + "integrity": "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw==", "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", - "metro-resolver": "0.82.5" + "metro-resolver": "0.83.3" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-file-map": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.82.5.tgz", - "integrity": "sha512-vpMDxkGIB+MTN8Af5hvSAanc6zXQipsAUO+XUx3PCQieKUfLwdoa8qaZ1WAQYRpaU+CJ8vhBcxtzzo3d9IsCIQ==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.83.3.tgz", + "integrity": "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA==", "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -6077,51 +6420,51 @@ "walker": "^1.0.7" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-minify-terser": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.82.5.tgz", - "integrity": "sha512-v6Nx7A4We6PqPu/ta1oGTqJ4Usz0P7c+3XNeBxW9kp8zayS3lHUKR0sY0wsCHInxZlNAEICx791x+uXytFUuwg==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.83.3.tgz", + "integrity": "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ==", "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-resolver": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.82.5.tgz", - "integrity": "sha512-kFowLnWACt3bEsuVsaRNgwplT8U7kETnaFHaZePlARz4Fg8tZtmRDUmjaD68CGAwc0rwdwNCkWizLYpnyVcs2g==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.83.3.tgz", + "integrity": "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ==", "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-runtime": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.82.5.tgz", - "integrity": "sha512-rQZDoCUf7k4Broyw3Ixxlq5ieIPiR1ULONdpcYpbJQ6yQ5GGEyYjtkztGD+OhHlw81LCR2SUAoPvtTus2WDK5g==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.83.3.tgz", + "integrity": "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-source-map": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.82.5.tgz", - "integrity": "sha512-wH+awTOQJVkbhn2SKyaw+0cd+RVSCZ3sHVgyqJFQXIee/yLs3dZqKjjeKKhhVeudgjXo7aE/vSu/zVfcQEcUfw==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.83.3.tgz", + "integrity": "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg==", "license": "MIT", "dependencies": { "@babel/traverse": "^7.25.3", @@ -6129,25 +6472,25 @@ "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-symbolicate": "0.82.5", + "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", - "ob1": "0.82.5", + "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-symbolicate": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.82.5.tgz", - "integrity": "sha512-1u+07gzrvYDJ/oNXuOG1EXSvXZka/0JSW1q2EYBWerVKMOhvv9JzDGyzmuV7hHbF2Hg3T3S2uiM36sLz1qKsiw==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.83.3.tgz", + "integrity": "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw==", "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", - "metro-source-map": "0.82.5", + "metro-source-map": "0.83.3", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" @@ -6156,13 +6499,13 @@ "metro-symbolicate": "src/index.js" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-transform-plugins": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.82.5.tgz", - "integrity": "sha512-57Bqf3rgq9nPqLrT2d9kf/2WVieTFqsQ6qWHpEng5naIUtc/Iiw9+0bfLLWSAw0GH40iJ4yMjFcFJDtNSYynMA==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.83.3.tgz", + "integrity": "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -6173,13 +6516,13 @@ "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro-transform-worker": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.82.5.tgz", - "integrity": "sha512-mx0grhAX7xe+XUQH6qoHHlWedI8fhSpDGsfga7CpkO9Lk9W+aPitNtJWNGrW8PfjKEWbT9Uz9O50dkI8bJqigw==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.83.3.tgz", + "integrity": "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.2", @@ -6187,17 +6530,17 @@ "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", - "metro": "0.82.5", - "metro-babel-transformer": "0.82.5", - "metro-cache": "0.82.5", - "metro-cache-key": "0.82.5", - "metro-minify-terser": "0.82.5", - "metro-source-map": "0.82.5", - "metro-transform-plugins": "0.82.5", + "metro": "0.83.3", + "metro-babel-transformer": "0.83.3", + "metro-cache": "0.83.3", + "metro-cache-key": "0.83.3", + "metro-minify-terser": "0.83.3", + "metro-source-map": "0.83.3", + "metro-transform-plugins": "0.83.3", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/metro/node_modules/ci-info": { @@ -6207,18 +6550,18 @@ "license": "MIT" }, "node_modules/metro/node_modules/hermes-estree": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.29.1.tgz", - "integrity": "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.32.0.tgz", + "integrity": "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ==", "license": "MIT" }, "node_modules/metro/node_modules/hermes-parser": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.29.1.tgz", - "integrity": "sha512-xBHWmUtRC5e/UL0tI7Ivt2riA/YBq9+SiYFU7C1oBa/j2jYGlIF9043oak1F47ihuDIxQ5nbsKueYJDRY02UgA==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.32.0.tgz", + "integrity": "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw==", "license": "MIT", "dependencies": { - "hermes-estree": "0.29.1" + "hermes-estree": "0.32.0" } }, "node_modules/micromatch": { @@ -6487,15 +6830,15 @@ "license": "MIT" }, "node_modules/ob1": { - "version": "0.82.5", - "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.82.5.tgz", - "integrity": "sha512-QyQQ6e66f+Ut/qUVjEce0E/wux5nAGLXYZDn1jr15JWstHsCH3l6VVrg8NKDptW9NEiBXKOJeGF/ydxeSDF3IQ==", + "version": "0.83.3", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.83.3.tgz", + "integrity": "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA==", "license": "MIT", "dependencies": { "flow-enums-runtime": "^0.0.6" }, "engines": { - "node": ">=18.18" + "node": ">=20.19.4" } }, "node_modules/object-assign": { @@ -6719,19 +7062,6 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/parse-png": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz", @@ -7044,9 +7374,9 @@ } }, "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", "peer": true, "engines": { @@ -7064,16 +7394,16 @@ } }, "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", "peer": true, "dependencies": { - "scheduler": "^0.25.0" + "scheduler": "^0.26.0" }, "peerDependencies": { - "react": "^19.0.0" + "react": "^19.1.0" } }, "node_modules/react-freeze": { @@ -7095,43 +7425,41 @@ "license": "MIT" }, "node_modules/react-native": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.79.5.tgz", - "integrity": "sha512-jVihwsE4mWEHZ9HkO1J2eUZSwHyDByZOqthwnGrVZCh6kTQBCm4v8dicsyDa6p0fpWNE5KicTcpX/XXl0ASJFg==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.81.5.tgz", + "integrity": "sha512-1w+/oSjEXZjMqsIvmkCRsOc8UBYv163bTWKTI8+1mxztvQPhCRYGTvZ/PL1w16xXHneIj/SLGfxWg2GWN2uexw==", "license": "MIT", "peer": true, "dependencies": { "@jest/create-cache-key-function": "^29.7.0", - "@react-native/assets-registry": "0.79.5", - "@react-native/codegen": "0.79.5", - "@react-native/community-cli-plugin": "0.79.5", - "@react-native/gradle-plugin": "0.79.5", - "@react-native/js-polyfills": "0.79.5", - "@react-native/normalize-colors": "0.79.5", - "@react-native/virtualized-lists": "0.79.5", + "@react-native/assets-registry": "0.81.5", + "@react-native/codegen": "0.81.5", + "@react-native/community-cli-plugin": "0.81.5", + "@react-native/gradle-plugin": "0.81.5", + "@react-native/js-polyfills": "0.81.5", + "@react-native/normalize-colors": "0.81.5", + "@react-native/virtualized-lists": "0.81.5", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", - "babel-plugin-syntax-hermes-parser": "0.25.1", + "babel-plugin-syntax-hermes-parser": "0.29.1", "base64-js": "^1.5.1", - "chalk": "^4.0.0", "commander": "^12.0.0", - "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", - "metro-runtime": "^0.82.0", - "metro-source-map": "^0.82.0", + "metro-runtime": "^0.83.1", + "metro-source-map": "^0.83.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", - "react-devtools-core": "^6.1.1", + "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", - "scheduler": "0.25.0", + "scheduler": "0.26.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", @@ -7142,11 +7470,11 @@ "react-native": "cli.js" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { - "@types/react": "^19.0.0", - "react": "^19.0.0" + "@types/react": "^19.1.0", + "react": "^19.1.0" }, "peerDependenciesMeta": { "@types/react": { @@ -7154,16 +7482,6 @@ } } }, - "node_modules/react-native-edge-to-edge": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/react-native-edge-to-edge/-/react-native-edge-to-edge-1.6.0.tgz", - "integrity": "sha512-2WCNdE3Qd6Fwg9+4BpbATUxCLcouF6YRY7K+J36KJ4l3y+tWN6XCqAC4DuoGblAAbb2sLkhEDp4FOlbOIot2Og==", - "license": "MIT", - "peerDependencies": { - "react": "*", - "react-native": "*" - } - }, "node_modules/react-native-is-edge-to-edge": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz", @@ -7219,6 +7537,34 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "license": "MIT" }, + "node_modules/react-native-reanimated": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-4.1.5.tgz", + "integrity": "sha512-UA6VUbxwhRjEw2gSNrvhkusUq3upfD3Cv+AnB07V+kC8kpvwRVI+ivwY95ePbWNFkFpP+Y2Sdw1WHpHWEV+P2Q==", + "license": "MIT", + "dependencies": { + "react-native-is-edge-to-edge": "^1.2.1", + "semver": "7.7.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*", + "react-native-worklets": ">=0.5.0" + } + }, + "node_modules/react-native-reanimated/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/react-native-safe-area-context": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.6.2.tgz", @@ -7247,9 +7593,9 @@ } }, "node_modules/react-native-web": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.20.0.tgz", - "integrity": "sha512-OOSgrw+aON6R3hRosCau/xVxdLzbjEcsLysYedka0ZON4ZZe6n9xgeN9ZkoejhARM36oTlUgHIQqxGutEJ9Wxg==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.21.2.tgz", + "integrity": "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.6", @@ -7276,45 +7622,57 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, - "node_modules/react-native/node_modules/@react-native/codegen": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.79.5.tgz", - "integrity": "sha512-FO5U1R525A1IFpJjy+KVznEinAgcs3u7IbnbRJUG9IH/MBXi2lEU2LtN+JarJ81MCfW4V2p0pg6t/3RGHFRrlQ==", + "node_modules/react-native-worklets": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.5.1.tgz", + "integrity": "sha512-lJG6Uk9YuojjEX/tQrCbcbmpdLCSFxDK1rJlkDhgqkVi1KZzG7cdcBFQRqyNOOzR9Y0CXNuldmtWTGOyM0k0+w==", "license": "MIT", + "peer": true, "dependencies": { - "glob": "^7.1.1", - "hermes-parser": "0.25.1", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" - }, - "engines": { - "node": ">=18" + "@babel/plugin-transform-arrow-functions": "^7.0.0-0", + "@babel/plugin-transform-class-properties": "^7.0.0-0", + "@babel/plugin-transform-classes": "^7.0.0-0", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", + "@babel/plugin-transform-optional-chaining": "^7.0.0-0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", + "@babel/plugin-transform-template-literals": "^7.0.0-0", + "@babel/plugin-transform-unicode-regex": "^7.0.0-0", + "@babel/preset-typescript": "^7.16.7", + "convert-source-map": "^2.0.0", + "semver": "7.7.2" }, "peerDependencies": { - "@babel/core": "*" + "@babel/core": "^7.0.0-0", + "react": "*", + "react-native": "*" } }, - "node_modules/react-native/node_modules/@react-native/normalize-colors": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.5.tgz", - "integrity": "sha512-nGXMNMclZgzLUxijQQ38Dm3IAEhgxuySAWQHnljFtfB0JdaMwpe0Ox9H7Tp2OgrEA+EMEv+Od9ElKlHwGKmmvQ==", - "license": "MIT" + "node_modules/react-native-worklets/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, "node_modules/react-native/node_modules/@react-native/virtualized-lists": { - "version": "0.79.5", - "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.79.5.tgz", - "integrity": "sha512-EUPM2rfGNO4cbI3olAbhPkIt3q7MapwCwAJBzUfWlZ/pu0PRNOnMQ1IvaXTf3TpeozXV52K1OdprLEI/kI5eUA==", + "version": "0.81.5", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.81.5.tgz", + "integrity": "sha512-UVXgV/db25OPIvwZySeToXD/9sKKhOdkcWmmf4Jh8iBZuyfML+/5CasaZ1E7Lqg6g3uqVQq75NqIwkYmORJMPw==", "license": "MIT", "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "engines": { - "node": ">=18" + "node": ">= 20.19.4" }, "peerDependencies": { - "@types/react": "^19.0.0", + "@types/react": "^19.1.0", "react": "*", "react-native": "*" }, @@ -7402,6 +7760,7 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -7534,6 +7893,18 @@ "node": ">=8" } }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "license": "MIT", + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz", @@ -7654,9 +8025,9 @@ "license": "BlueOak-1.0.0" }, "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, "node_modules/semver": { @@ -7906,18 +8277,6 @@ "plist": "^3.0.5" } }, - "node_modules/simple-plist/node_modules/bplist-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", - "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", - "license": "MIT", - "dependencies": { - "big-integer": "1.6.x" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", @@ -8950,6 +9309,18 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -9020,6 +9391,25 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", + "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25 || ^4" + } } } } diff --git a/mobile/package.json b/mobile/package.json index 5000e3d2..79679cdc 100644 --- a/mobile/package.json +++ b/mobile/package.json @@ -9,22 +9,28 @@ "web": "expo start --web" }, "dependencies": { - "@expo/metro-runtime": "~5.0.4", + "@expo-google-fonts/inter": "^0.4.2", + "@expo-google-fonts/space-grotesk": "^0.4.1", + "@expo/metro-runtime": "~6.1.2", "@react-native-async-storage/async-storage": "^2.1.2", "@react-navigation/bottom-tabs": "^7.4.4", "@react-navigation/native": "^7.1.16", "@react-navigation/native-stack": "^7.3.23", "axios": "^1.11.0", - "expo": "~53.0.20", - "expo-image-picker": "^16.1.4", - "expo-status-bar": "~2.2.3", - "react": "19.0.0", - "react-dom": "19.0.0", - "react-native": "0.79.5", + "expo": "^54.0.25", + "expo-font": "~14.0.9", + "expo-image-picker": "~17.0.8", + "expo-linear-gradient": "~15.0.7", + "expo-status-bar": "~3.0.8", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-native": "0.81.5", "react-native-paper": "^5.14.5", + "react-native-reanimated": "~4.1.1", "react-native-safe-area-context": "^5.4.0", "react-native-screens": "^4.11.1", - "react-native-web": "^0.20.0" + "react-native-web": "^0.21.0", + "react-native-worklets": "0.5.1" }, "devDependencies": { "@babel/core": "^7.20.0" diff --git a/mobile/screens/FriendsScreen.js b/mobile/screens/FriendsScreen.js index 0da27955..9b762b4d 100644 --- a/mobile/screens/FriendsScreen.js +++ b/mobile/screens/FriendsScreen.js @@ -12,9 +12,13 @@ import { import { getFriendsBalance, getGroups } from "../api/groups"; import { AuthContext } from "../context/AuthContext"; import { formatCurrency } from "../utils/currency"; +import { ThemeWrapper } from "../components/ThemeWrapper"; +import { useTheme } from "../context/ThemeContext"; +import { THEMES, COLORS } from "../constants/theme"; const FriendsScreen = () => { const { token, user } = useContext(AuthContext); + const { style, mode } = useTheme(); const [friends, setFriends] = useState([]); const [isLoading, setIsLoading] = useState(true); const [showTooltip, setShowTooltip] = useState(true); @@ -24,7 +28,6 @@ const FriendsScreen = () => { const fetchData = async () => { setIsLoading(true); try { - // Fetch friends balance + groups concurrently for group icons const friendsResponse = await getFriendsBalance(); const friendsData = friendsResponse.data.friendsBalance || []; const groupsResponse = await getGroups(); @@ -61,17 +64,15 @@ const FriendsScreen = () => { }, [token, isFocused]); const renderFriend = ({ item }) => { - const balanceColor = item.netBalance < 0 ? "red" : "green"; + const balanceColor = item.netBalance < 0 ? (style === THEMES.NEOBRUTALISM ? '#ff4444' : '#ff6b6b') : COLORS.neo.accent; const balanceText = item.netBalance < 0 ? `You owe ${formatCurrency(Math.abs(item.netBalance))}` : `Owes you ${formatCurrency(item.netBalance)}`; - // Determine if we have an image URL or a base64 payload const hasImage = !!item.imageUrl; let imageUri = null; if (hasImage) { - // If it's a raw base64 string without prefix, add a default MIME prefix if ( /^data:image/.test(item.imageUrl) || /^https?:\/\//.test(item.imageUrl) @@ -82,13 +83,30 @@ const FriendsScreen = () => { } } + const listItemStyle = style === THEMES.NEOBRUTALISM ? { + backgroundColor: mode === 'dark' ? COLORS.neo.dark : COLORS.neo.white, + borderWidth: 2, + borderColor: COLORS.neo.dark, + marginBottom: 8, + } : { + backgroundColor: mode === 'dark' ? 'rgba(30,30,30,0.4)' : 'rgba(255,255,255,0.4)', + borderRadius: 8, + marginBottom: 8, + }; + + const textColor = style === THEMES.NEOBRUTALISM && mode !== 'dark' ? COLORS.neo.dark : COLORS.neo.white; + return ( + imageUri ? ( @@ -97,17 +115,19 @@ const FriendsScreen = () => { {...props} size={40} label={(item.name || "?").charAt(0)} + style={{ backgroundColor: COLORS.neo.main }} + labelStyle={{ fontFamily: 'SpaceGrotesk_700Bold' }} /> ) } > {item.groups.map((group) => { - const groupBalanceColor = group.balance < 0 ? "red" : "green"; + const groupBalanceColor = group.balance < 0 ? (style === THEMES.NEOBRUTALISM ? '#ff4444' : '#ff6b6b') : COLORS.neo.accent; const groupBalanceText = group.balance < 0 ? `You owe ${formatCurrency(Math.abs(group.balance))}` : `Owes you ${formatCurrency(group.balance)}`; - // Prepare group icon (imageUrl may be base64 or URL) + let groupImageUri = null; if (group.imageUrl) { if ( @@ -126,8 +146,9 @@ const FriendsScreen = () => { groupImageUri ? ( { {...props} size={36} label={(group.name || "?").charAt(0)} + style={{ backgroundColor: COLORS.neo.second }} /> ) } @@ -147,10 +169,10 @@ const FriendsScreen = () => { ); })} + ); }; - // Shimmer skeleton components const opacityAnim = useRef(new Animated.Value(0.3)).current; useEffect(() => { const loop = Animated.loop( @@ -174,46 +196,66 @@ const FriendsScreen = () => { const SkeletonRow = () => ( ); + const headerStyle = { + backgroundColor: style === THEMES.NEOBRUTALISM ? COLORS.neo.main : 'transparent', + elevation: 0, + borderBottomWidth: style === THEMES.NEOBRUTALISM ? 3 : 0, + borderBottomColor: COLORS.neo.dark, + }; + const contentColor = style === THEMES.NEOBRUTALISM ? 'white' : (mode === 'dark' ? 'white' : COLORS.neo.dark); + if (isLoading) { return ( - - - + + + {Array.from({ length: 5 }).map((_, i) => ( ))} - + ); } return ( - - - + + + {showTooltip && ( - + - + 💡 These amounts show your direct balance with each friend across all shared groups. Check individual group details for optimized settlement suggestions. @@ -231,26 +273,18 @@ const FriendsScreen = () => { data={friends} renderItem={renderFriend} keyExtractor={(item) => item.id} - ItemSeparatorComponent={Divider} + ItemSeparatorComponent={style === THEMES.NEOBRUTALISM ? null : Divider} + contentContainerStyle={{ padding: 16 }} ListEmptyComponent={ - No balances with friends yet. + No balances with friends yet. } /> - + ); }; const styles = StyleSheet.create({ - container: { - flex: 1, - }, - loaderContainer: { - flex: 1, - justifyContent: "center", - alignItems: "center", - }, explanationContainer: { - backgroundColor: "#f0f8ff", margin: 8, borderRadius: 8, borderLeftWidth: 4, @@ -288,17 +322,14 @@ const styles = StyleSheet.create({ width: 48, height: 48, borderRadius: 24, - backgroundColor: "#e0e0e0", }, skeletonLine: { height: 14, - backgroundColor: "#e0e0e0", borderRadius: 6, marginBottom: 6, }, skeletonLineSmall: { height: 12, - backgroundColor: "#e0e0e0", borderRadius: 6, }, }); diff --git a/mobile/screens/HomeScreen.js b/mobile/screens/HomeScreen.js index dfb0eadd..2c159082 100644 --- a/mobile/screens/HomeScreen.js +++ b/mobile/screens/HomeScreen.js @@ -1,5 +1,5 @@ import { useContext, useEffect, useState } from "react"; -import { Alert, FlatList, StyleSheet, View } from "react-native"; +import { Alert, FlatList, StyleSheet, View, Animated } from "react-native"; import { ActivityIndicator, Appbar, @@ -14,14 +14,18 @@ import { import { createGroup, getGroups, getOptimizedSettlements } from "../api/groups"; import { AuthContext } from "../context/AuthContext"; import { formatCurrency, getCurrencySymbol } from "../utils/currency"; +import { useTheme } from "../context/ThemeContext"; +import { THEMES, COLORS } from "../constants/theme"; +import { ThemeWrapper } from "../components/ThemeWrapper"; +import { MaterialCommunityIcons } from '@expo/vector-icons'; const HomeScreen = ({ navigation }) => { const { token, logout, user } = useContext(AuthContext); + const { style, mode } = useTheme(); const [groups, setGroups] = useState([]); const [isLoading, setIsLoading] = useState(true); - const [groupSettlements, setGroupSettlements] = useState({}); // Track settlement status for each group + const [groupSettlements, setGroupSettlements] = useState({}); - // State for the Create Group modal const [modalVisible, setModalVisible] = useState(false); const [newGroupName, setNewGroupName] = useState(""); const [isCreatingGroup, setIsCreatingGroup] = useState(false); @@ -29,13 +33,11 @@ const HomeScreen = ({ navigation }) => { const showModal = () => setModalVisible(true); const hideModal = () => setModalVisible(false); - // Calculate settlement status for a group const calculateSettlementStatus = async (groupId, userId) => { try { const response = await getOptimizedSettlements(groupId); const settlements = response.data.optimizedSettlements || []; - // Check if user has any pending settlements const userOwes = settlements.filter((s) => s.fromUserId === userId); const userIsOwed = settlements.filter((s) => s.toUserId === userId); @@ -73,7 +75,6 @@ const HomeScreen = ({ navigation }) => { const groupsList = response.data.groups; setGroups(groupsList); - // Fetch settlement status for each group if (user?._id) { const settlementPromises = groupsList.map(async (group) => { const status = await calculateSettlementStatus(group._id, user._id); @@ -111,7 +112,7 @@ const HomeScreen = ({ navigation }) => { await createGroup(newGroupName); hideModal(); setNewGroupName(""); - await fetchGroups(); // Refresh the groups list + await fetchGroups(); } catch (error) { console.error("Failed to create group:", error); Alert.alert("Error", "Failed to create group."); @@ -120,53 +121,66 @@ const HomeScreen = ({ navigation }) => { } }; - const currencySymbol = getCurrencySymbol(); - const renderGroup = ({ item }) => { const settlementStatus = groupSettlements[item._id]; - // Generate settlement status text const getSettlementStatusText = () => { if (!settlementStatus) { return "Calculating balances..."; } - if (settlementStatus.isSettled) { return "✓ You are settled up."; } - if (settlementStatus.netBalance > 0) { return `You are owed ${formatCurrency(settlementStatus.netBalance)}.`; } else if (settlementStatus.netBalance < 0) { - return `You owe ${formatCurrency( - Math.abs(settlementStatus.netBalance) - )}.`; + return `You owe ${formatCurrency(Math.abs(settlementStatus.netBalance))}.`; } - return "You are settled up."; }; - // Get text color based on settlement status const getStatusColor = () => { if (!settlementStatus || settlementStatus.isSettled) { - return "#4CAF50"; // Green for settled + return COLORS.neo.accent; } - if (settlementStatus.netBalance > 0) { - return "#4CAF50"; // Green for being owed money + return COLORS.neo.accent; } else if (settlementStatus.netBalance < 0) { - return "#F44336"; // Red for owing money + return style === THEMES.NEOBRUTALISM ? '#ff4444' : '#ff6b6b'; } - - return "#4CAF50"; // Default green + return COLORS.neo.accent; }; - const isImage = - item.imageUrl && /^(https?:|data:image)/.test(item.imageUrl); + const isImage = item.imageUrl && /^(https?:|data:image)/.test(item.imageUrl); const groupIcon = item.imageUrl || item.name?.charAt(0) || "?"; + + // Neo-Brutalism Styles + const cardStyle = style === THEMES.NEOBRUTALISM ? { + backgroundColor: mode === 'dark' ? COLORS.neo.dark : COLORS.neo.white, + borderWidth: 3, + borderColor: COLORS.neo.dark, + borderRadius: 0, + shadowColor: COLORS.neo.dark, + shadowOffset: { width: 4, height: 4 }, + shadowOpacity: 1, + shadowRadius: 0, + elevation: 0, // Disable android elevation for clean neo look + marginBottom: 16, + } : { + // Glassmorphism Styles + backgroundColor: mode === 'dark' ? 'rgba(30, 30, 30, 0.6)' : 'rgba(255, 255, 255, 0.7)', + borderColor: 'rgba(255, 255, 255, 0.2)', + borderWidth: 1, + borderRadius: 16, + marginBottom: 16, + elevation: 4, + }; + + const textColor = style === THEMES.NEOBRUTALISM && mode !== 'dark' ? COLORS.neo.dark : COLORS.neo.white; + return ( navigation.navigate("GroupDetails", { groupId: item._id, @@ -177,16 +191,29 @@ const HomeScreen = ({ navigation }) => { > isImage ? ( - + ) : ( - + + {groupIcon} + ) } /> - + {getSettlementStatusText()} @@ -194,37 +221,71 @@ const HomeScreen = ({ navigation }) => { ); }; + const headerStyle = { + backgroundColor: style === THEMES.NEOBRUTALISM ? COLORS.neo.main : 'transparent', + elevation: 0, + borderBottomWidth: style === THEMES.NEOBRUTALISM ? 3 : 0, + borderBottomColor: COLORS.neo.dark, + }; + + const contentColor = style === THEMES.NEOBRUTALISM ? 'white' : (mode === 'dark' ? 'white' : COLORS.neo.dark); + return ( - + - Create a New Group + Create a New Group - - - + + + navigation.navigate("JoinGroup", { onGroupJoined: fetchGroups }) } @@ -233,7 +294,7 @@ const HomeScreen = ({ navigation }) => { {isLoading ? ( - + ) : ( { keyExtractor={(item) => item._id} contentContainerStyle={styles.list} ListEmptyComponent={ - + No groups found. Create or join one! } @@ -250,14 +311,11 @@ const HomeScreen = ({ navigation }) => { refreshing={isLoading} /> )} - + ); }; const styles = StyleSheet.create({ - container: { - flex: 1, - }, loaderContainer: { flex: 1, justifyContent: "center", @@ -266,9 +324,6 @@ const styles = StyleSheet.create({ list: { padding: 16, }, - card: { - marginBottom: 16, - }, settlementStatus: { fontWeight: "500", marginTop: 4, @@ -281,7 +336,6 @@ const styles = StyleSheet.create({ backgroundColor: "white", padding: 20, margin: 20, - borderRadius: 8, }, modalTitle: { fontSize: 20, diff --git a/mobile/screens/LoginScreen.js b/mobile/screens/LoginScreen.js index 076e9956..842d4da4 100644 --- a/mobile/screens/LoginScreen.js +++ b/mobile/screens/LoginScreen.js @@ -1,13 +1,44 @@ -import React, { useState, useContext } from 'react'; -import { View, StyleSheet, Alert } from 'react-native'; -import { Button, Text, TextInput } from 'react-native-paper'; +import React, { useState, useContext, useEffect } from 'react'; +import { View, StyleSheet, Alert, KeyboardAvoidingView, Platform } from 'react-native'; +import Animated, { useSharedValue, useAnimatedStyle, withTiming, withSpring, withDelay } from 'react-native-reanimated'; import { AuthContext } from '../context/AuthContext'; +import { ThemeWrapper } from '../components/ThemeWrapper'; +import { ThemedText } from '../components/ui/ThemedText'; +import { ThemedButton } from '../components/ui/ThemedButton'; +import { ThemedInput } from '../components/ui/ThemedInput'; +import { useTheme } from '../context/ThemeContext'; +import { THEMES, COLORS } from '../constants/theme'; const LoginScreen = ({ navigation }) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); const { login } = useContext(AuthContext); + const { style, mode } = useTheme(); + + // Animation values + const opacity = useSharedValue(0); + const translateY = useSharedValue(50); + const logoScale = useSharedValue(0); + + useEffect(() => { + opacity.value = withTiming(1, { duration: 800 }); + translateY.value = withSpring(0); + logoScale.value = withDelay(300, withSpring(1)); + }, []); + + const animatedFormStyle = useAnimatedStyle(() => { + return { + opacity: opacity.value, + transform: [{ translateY: translateY.value }], + }; + }); + + const animatedLogoStyle = useAnimatedStyle(() => { + return { + transform: [{ scale: logoScale.value }] + }; + }); const handleLogin = async () => { if (!email || !password) { @@ -23,36 +54,73 @@ const LoginScreen = ({ navigation }) => { }; return ( - - Welcome Back! - - - - - + + + + $ + + Welcome Back! + Sign in to continue splitting. + + + + + + + + + + Login + + + navigation.navigate('Signup')} + variant="outline" + > + Don't have an account? Sign Up + + + + + ); }; @@ -60,18 +128,25 @@ const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', - padding: 16, }, - title: { - textAlign: 'center', - marginBottom: 24, + content: { + padding: 24, + justifyContent: 'center', }, - input: { - marginBottom: 16, + headerContainer: { + alignItems: 'center', + marginBottom: 40, }, - button: { - marginTop: 8, + logoCircle: { + width: 80, + height: 80, + borderRadius: 40, + justifyContent: 'center', + alignItems: 'center', }, + formContainer: { + width: '100%', + } }); export default LoginScreen; diff --git a/mobile/screens/SignupScreen.js b/mobile/screens/SignupScreen.js index 5594be60..ddd755aa 100644 --- a/mobile/screens/SignupScreen.js +++ b/mobile/screens/SignupScreen.js @@ -1,7 +1,13 @@ -import React, { useState, useContext } from 'react'; -import { View, StyleSheet, Alert } from 'react-native'; -import { Button, Text, TextInput } from 'react-native-paper'; +import React, { useState, useContext, useEffect } from 'react'; +import { View, StyleSheet, Alert, KeyboardAvoidingView, Platform, ScrollView } from 'react-native'; +import Animated, { useSharedValue, useAnimatedStyle, withTiming, withSpring, withDelay } from 'react-native-reanimated'; import { AuthContext } from '../context/AuthContext'; +import { ThemeWrapper } from '../components/ThemeWrapper'; +import { ThemedText } from '../components/ui/ThemedText'; +import { ThemedButton } from '../components/ui/ThemedButton'; +import { ThemedInput } from '../components/ui/ThemedInput'; +import { useTheme } from '../context/ThemeContext'; +import { THEMES, COLORS } from '../constants/theme'; const SignupScreen = ({ navigation }) => { const [name, setName] = useState(''); @@ -10,6 +16,22 @@ const SignupScreen = ({ navigation }) => { const [confirmPassword, setConfirmPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); const { signup } = useContext(AuthContext); + const { style } = useTheme(); + + const opacity = useSharedValue(0); + const translateY = useSharedValue(30); + + useEffect(() => { + opacity.value = withTiming(1, { duration: 600 }); + translateY.value = withSpring(0); + }, []); + + const animatedStyle = useAnimatedStyle(() => { + return { + opacity: opacity.value, + transform: [{ translateY: translateY.value }], + }; + }); const handleSignup = async () => { if (!name || !email || !password || !confirmPassword) { @@ -35,69 +57,90 @@ const SignupScreen = ({ navigation }) => { }; return ( - - Create Account - - - - - - - + + + + Create Account + Join the revolution of splitting bills. + + + + + + + + + + + + Sign Up + + navigation.navigate('Login')} + variant="outline" + disabled={isLoading} + > + Already have an account? Log In + + + + + + ); }; const styles = StyleSheet.create({ container: { flex: 1, - justifyContent: 'center', - padding: 16, }, - title: { - textAlign: 'center', - marginBottom: 24, + scrollContent: { + flexGrow: 1, + justifyContent: 'center', }, - input: { - marginBottom: 16, + content: { + padding: 24, }, - button: { - marginTop: 8, + header: { + marginBottom: 32, + alignItems: 'center', }, + form: { + width: '100%', + } }); export default SignupScreen;