From 3d357cbad42323edd9ccfb056c6728d73da74974 Mon Sep 17 00:00:00 2001 From: KM Koushik Date: Wed, 21 Oct 2026 19:41:05 +1100 Subject: [PATCH 1/2] feat: SplitPro React Native app Expo SDK 58 app in mobile/ for splitpro.app with native iOS/Android UI: balances, friends, groups, add/edit expense with every split type, expense detail, settle up, activity, account, Google/Apple/email sign-in and push. Uses the server's AppRouter types and the web's shared split logic. --- mobile/.claude/settings.json | 5 + mobile/.gitignore | 41 + mobile/.npmrc | 1 + mobile/.prettierignore | 7 + mobile/.prettierrc.json | 6 + mobile/AGENTS.md | 41 + mobile/README.md | 342 + mobile/app.config.ts | 75 + mobile/assets/icon.png | Bin 0 -> 58828 bytes mobile/assets/splash-icon.png | Bin 0 -> 14407 bytes mobile/eas.json | 36 + mobile/eslint.config.js | 15 + mobile/metro.config.js | 48 + mobile/package.json | 69 + mobile/pnpm-lock.yaml | 8513 +++++++++++++++++ .../app/(app)/(tabs)/(account)/_layout.tsx | 47 + .../app/(app)/(tabs)/(account)/account.tsx | 241 + .../(app)/(tabs)/(account)/edit-profile.tsx | 105 + .../app/(app)/(tabs)/(account)/feedback.tsx | 94 + .../app/(app)/(tabs)/(activity)/_layout.tsx | 17 + .../app/(app)/(tabs)/(activity)/activity.tsx | 184 + .../app/(app)/(tabs)/(balances)/_layout.tsx | 17 + .../app/(app)/(tabs)/(balances)/balances.tsx | 122 + .../src/app/(app)/(tabs)/(groups)/_layout.tsx | 17 + .../src/app/(app)/(tabs)/(groups)/groups.tsx | 96 + mobile/src/app/(app)/(tabs)/_layout.tsx | 47 + mobile/src/app/(app)/_layout.tsx | 83 + mobile/src/app/(app)/add.tsx | 272 + mobile/src/app/(app)/balances/[friendId].tsx | 317 + mobile/src/app/(app)/expenses/[expenseId].tsx | 155 + mobile/src/app/(app)/groups/[groupId].tsx | 301 + .../(app)/groups/[groupId]/add-members.tsx | 287 + .../(app)/groups/[groupId]/default-split.tsx | 260 + .../src/app/(app)/groups/[groupId]/info.tsx | 160 + mobile/src/app/(app)/groups/new.tsx | 121 + mobile/src/app/(app)/join-group.tsx | 86 + mobile/src/app/(app)/new.tsx | 7 + mobile/src/app/(app)/settle-up.tsx | 82 + mobile/src/app/(auth)/_layout.tsx | 15 + mobile/src/app/(auth)/oauth-callback.tsx | 24 + mobile/src/app/(auth)/sign-in.tsx | 325 + mobile/src/app/(auth)/verify.tsx | 227 + mobile/src/app/_layout.tsx | 91 + mobile/src/app/index.tsx | 12 + .../account/NotificationsSection.tsx | 127 + mobile/src/components/account/XLogo.tsx | 13 + mobile/src/components/account/downloadData.ts | 38 + .../src/components/activity/ActivityItem.tsx | 176 + .../components/add-expense/AddExpenseForm.tsx | 130 + .../components/add-expense/AmountField.tsx | 127 + .../src/components/add-expense/DetailRows.tsx | 255 + .../add-expense/ParticipantsInput.tsx | 191 + .../src/components/add-expense/ReceiptRow.tsx | 210 + .../add-expense/SelectUserOrGroup.tsx | 203 + .../add-expense/SplitEditorSheet.tsx | 298 + .../components/add-expense/addExpense.test.ts | 255 + .../src/components/add-expense/amountInput.ts | 24 + mobile/src/components/add-expense/calendar.ts | 29 + .../src/components/add-expense/categories.ts | 41 + .../src/components/add-expense/formChanges.ts | 26 + .../src/components/add-expense/offerPush.ts | 48 + .../src/components/add-expense/splitStatus.ts | 78 + mobile/src/components/add-expense/timeZone.ts | 5 + .../components/add-expense/useInviteFriend.ts | 27 + .../components/add-expense/useSaveExpense.ts | 103 + .../expense-detail/ExpenseDetails.tsx | 273 + .../expense-detail/ReceiptImage.tsx | 154 + .../expense-detail/RecurringRule.tsx | 162 + .../expense-detail/expenseDetail.test.ts | 126 + .../expense-detail/expenseDetail.ts | 81 + .../components/expense/AddExpenseAction.tsx | 44 + .../components/expense/ExpenseListDate.tsx | 34 + .../components/expense/ExpenseListItem.tsx | 268 + .../src/components/expense/categoryIcons.tsx | 61 + mobile/src/components/expense/index.ts | 6 + .../src/components/expense/useCurrentUser.ts | 10 + .../src/components/friend/BalanceTotals.tsx | 86 + .../components/friend/FriendBalanceRow.tsx | 126 + .../src/components/friend/FriendSummary.tsx | 144 + mobile/src/components/friend/exportCsv.ts | 118 + .../components/group/DefaultSplitSummary.tsx | 103 + .../src/components/group/GroupBalanceRow.tsx | 115 + .../components/group/GroupRecurringRules.tsx | 235 + .../src/components/group/GroupStatsSheet.tsx | 64 + mobile/src/components/group/GroupSummary.tsx | 127 + mobile/src/components/group/NoMembers.tsx | 37 + mobile/src/components/group/invite.ts | 44 + .../src/components/group/useGroupDetails.ts | 30 + mobile/src/components/group/useGroupExit.ts | 86 + .../src/components/settle/FriendSettleUp.tsx | 304 + .../src/components/settle/GroupSettleUp.tsx | 213 + mobile/src/components/settle/PaymentDate.tsx | 89 + .../src/components/settle/SettleUpPayment.tsx | 127 + mobile/src/components/settle/index.ts | 3 + mobile/src/components/settle/shared.tsx | 90 + mobile/src/components/ui/Avatar.tsx | 73 + mobile/src/components/ui/Button.tsx | 160 + mobile/src/components/ui/Card.tsx | 29 + mobile/src/components/ui/CodeInput.tsx | 110 + mobile/src/components/ui/CurrencySheet.tsx | 142 + mobile/src/components/ui/EmptyState.tsx | 62 + mobile/src/components/ui/Fab.tsx | 54 + mobile/src/components/ui/HeaderActions.tsx | 254 + mobile/src/components/ui/Icon.tsx | 117 + mobile/src/components/ui/Input.tsx | 117 + .../src/components/ui/InsetStickyHeader.tsx | 70 + mobile/src/components/ui/ListRow.tsx | 156 + mobile/src/components/ui/ModalHeader.tsx | 77 + mobile/src/components/ui/Money.tsx | 35 + mobile/src/components/ui/PopUpButton.tsx | 57 + mobile/src/components/ui/QuickActions.tsx | 74 + mobile/src/components/ui/Screen.tsx | 129 + mobile/src/components/ui/SearchField.tsx | 47 + mobile/src/components/ui/Section.tsx | 137 + mobile/src/components/ui/SettingsIcon.tsx | 57 + mobile/src/components/ui/Sheet.tsx | 105 + mobile/src/components/ui/SheetHeader.tsx | 102 + mobile/src/components/ui/Skeleton.tsx | 39 + mobile/src/components/ui/Spinner.tsx | 30 + mobile/src/components/ui/SwipeActions.tsx | 149 + mobile/src/components/ui/Text.tsx | 52 + mobile/src/components/ui/Toast.tsx | 158 + mobile/src/components/ui/index.ts | 54 + mobile/src/i18n/i18next.d.ts | 9 + mobile/src/i18n/index.ts | 45 + mobile/src/i18n/locales/en.json | 555 ++ mobile/src/lib/api.ts | 36 + mobile/src/lib/appConfig.ts | 14 + mobile/src/lib/authApi.ts | 124 + mobile/src/lib/config.ts | 5 + mobile/src/lib/dates.ts | 5 + mobile/src/lib/dialogs.ts | 45 + mobile/src/lib/haptics.ts | 27 + mobile/src/lib/money.ts | 42 + mobile/src/lib/navigation.ts | 43 + mobile/src/lib/pendingLink.test.ts | 57 + mobile/src/lib/pendingLink.ts | 60 + mobile/src/lib/pkce.test.mjs | 53 + mobile/src/lib/pkce.ts | 41 + mobile/src/lib/push.ts | 256 + mobile/src/lib/socialAuth.ts | 106 + mobile/src/lib/storage.ts | 12 + mobile/src/lib/storage.web.ts | 6 + mobile/src/providers/ApiProvider.tsx | 70 + mobile/src/providers/usePendingLink.ts | 57 + mobile/src/providers/usePushNotifications.ts | 89 + mobile/src/shims/prisma-client.ts | 35 + mobile/src/store/addExpenseStore.ts | 6 + mobile/src/store/authStore.ts | 84 + mobile/src/store/recentCurrencies.ts | 39 + mobile/src/theme/navigation.ts | 39 + mobile/src/theme/palette.test.ts | 72 + mobile/src/theme/palette.ts | 85 + mobile/src/theme/tokens.ts | 344 + mobile/src/types/expo.d.ts | 3 + mobile/tsconfig.json | 12 + 156 files changed, 23897 insertions(+) create mode 100644 mobile/.claude/settings.json create mode 100644 mobile/.gitignore create mode 100644 mobile/.npmrc create mode 100644 mobile/.prettierignore create mode 100644 mobile/.prettierrc.json create mode 100644 mobile/AGENTS.md create mode 100644 mobile/README.md create mode 100644 mobile/app.config.ts create mode 100644 mobile/assets/icon.png create mode 100644 mobile/assets/splash-icon.png create mode 100644 mobile/eas.json create mode 100644 mobile/eslint.config.js create mode 100644 mobile/metro.config.js create mode 100644 mobile/package.json create mode 100644 mobile/pnpm-lock.yaml create mode 100644 mobile/src/app/(app)/(tabs)/(account)/_layout.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(account)/account.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(account)/edit-profile.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(account)/feedback.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(activity)/_layout.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(activity)/activity.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(balances)/_layout.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(balances)/balances.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(groups)/_layout.tsx create mode 100644 mobile/src/app/(app)/(tabs)/(groups)/groups.tsx create mode 100644 mobile/src/app/(app)/(tabs)/_layout.tsx create mode 100644 mobile/src/app/(app)/_layout.tsx create mode 100644 mobile/src/app/(app)/add.tsx create mode 100644 mobile/src/app/(app)/balances/[friendId].tsx create mode 100644 mobile/src/app/(app)/expenses/[expenseId].tsx create mode 100644 mobile/src/app/(app)/groups/[groupId].tsx create mode 100644 mobile/src/app/(app)/groups/[groupId]/add-members.tsx create mode 100644 mobile/src/app/(app)/groups/[groupId]/default-split.tsx create mode 100644 mobile/src/app/(app)/groups/[groupId]/info.tsx create mode 100644 mobile/src/app/(app)/groups/new.tsx create mode 100644 mobile/src/app/(app)/join-group.tsx create mode 100644 mobile/src/app/(app)/new.tsx create mode 100644 mobile/src/app/(app)/settle-up.tsx create mode 100644 mobile/src/app/(auth)/_layout.tsx create mode 100644 mobile/src/app/(auth)/oauth-callback.tsx create mode 100644 mobile/src/app/(auth)/sign-in.tsx create mode 100644 mobile/src/app/(auth)/verify.tsx create mode 100644 mobile/src/app/_layout.tsx create mode 100644 mobile/src/app/index.tsx create mode 100644 mobile/src/components/account/NotificationsSection.tsx create mode 100644 mobile/src/components/account/XLogo.tsx create mode 100644 mobile/src/components/account/downloadData.ts create mode 100644 mobile/src/components/activity/ActivityItem.tsx create mode 100644 mobile/src/components/add-expense/AddExpenseForm.tsx create mode 100644 mobile/src/components/add-expense/AmountField.tsx create mode 100644 mobile/src/components/add-expense/DetailRows.tsx create mode 100644 mobile/src/components/add-expense/ParticipantsInput.tsx create mode 100644 mobile/src/components/add-expense/ReceiptRow.tsx create mode 100644 mobile/src/components/add-expense/SelectUserOrGroup.tsx create mode 100644 mobile/src/components/add-expense/SplitEditorSheet.tsx create mode 100644 mobile/src/components/add-expense/addExpense.test.ts create mode 100644 mobile/src/components/add-expense/amountInput.ts create mode 100644 mobile/src/components/add-expense/calendar.ts create mode 100644 mobile/src/components/add-expense/categories.ts create mode 100644 mobile/src/components/add-expense/formChanges.ts create mode 100644 mobile/src/components/add-expense/offerPush.ts create mode 100644 mobile/src/components/add-expense/splitStatus.ts create mode 100644 mobile/src/components/add-expense/timeZone.ts create mode 100644 mobile/src/components/add-expense/useInviteFriend.ts create mode 100644 mobile/src/components/add-expense/useSaveExpense.ts create mode 100644 mobile/src/components/expense-detail/ExpenseDetails.tsx create mode 100644 mobile/src/components/expense-detail/ReceiptImage.tsx create mode 100644 mobile/src/components/expense-detail/RecurringRule.tsx create mode 100644 mobile/src/components/expense-detail/expenseDetail.test.ts create mode 100644 mobile/src/components/expense-detail/expenseDetail.ts create mode 100644 mobile/src/components/expense/AddExpenseAction.tsx create mode 100644 mobile/src/components/expense/ExpenseListDate.tsx create mode 100644 mobile/src/components/expense/ExpenseListItem.tsx create mode 100644 mobile/src/components/expense/categoryIcons.tsx create mode 100644 mobile/src/components/expense/index.ts create mode 100644 mobile/src/components/expense/useCurrentUser.ts create mode 100644 mobile/src/components/friend/BalanceTotals.tsx create mode 100644 mobile/src/components/friend/FriendBalanceRow.tsx create mode 100644 mobile/src/components/friend/FriendSummary.tsx create mode 100644 mobile/src/components/friend/exportCsv.ts create mode 100644 mobile/src/components/group/DefaultSplitSummary.tsx create mode 100644 mobile/src/components/group/GroupBalanceRow.tsx create mode 100644 mobile/src/components/group/GroupRecurringRules.tsx create mode 100644 mobile/src/components/group/GroupStatsSheet.tsx create mode 100644 mobile/src/components/group/GroupSummary.tsx create mode 100644 mobile/src/components/group/NoMembers.tsx create mode 100644 mobile/src/components/group/invite.ts create mode 100644 mobile/src/components/group/useGroupDetails.ts create mode 100644 mobile/src/components/group/useGroupExit.ts create mode 100644 mobile/src/components/settle/FriendSettleUp.tsx create mode 100644 mobile/src/components/settle/GroupSettleUp.tsx create mode 100644 mobile/src/components/settle/PaymentDate.tsx create mode 100644 mobile/src/components/settle/SettleUpPayment.tsx create mode 100644 mobile/src/components/settle/index.ts create mode 100644 mobile/src/components/settle/shared.tsx create mode 100644 mobile/src/components/ui/Avatar.tsx create mode 100644 mobile/src/components/ui/Button.tsx create mode 100644 mobile/src/components/ui/Card.tsx create mode 100644 mobile/src/components/ui/CodeInput.tsx create mode 100644 mobile/src/components/ui/CurrencySheet.tsx create mode 100644 mobile/src/components/ui/EmptyState.tsx create mode 100644 mobile/src/components/ui/Fab.tsx create mode 100644 mobile/src/components/ui/HeaderActions.tsx create mode 100644 mobile/src/components/ui/Icon.tsx create mode 100644 mobile/src/components/ui/Input.tsx create mode 100644 mobile/src/components/ui/InsetStickyHeader.tsx create mode 100644 mobile/src/components/ui/ListRow.tsx create mode 100644 mobile/src/components/ui/ModalHeader.tsx create mode 100644 mobile/src/components/ui/Money.tsx create mode 100644 mobile/src/components/ui/PopUpButton.tsx create mode 100644 mobile/src/components/ui/QuickActions.tsx create mode 100644 mobile/src/components/ui/Screen.tsx create mode 100644 mobile/src/components/ui/SearchField.tsx create mode 100644 mobile/src/components/ui/Section.tsx create mode 100644 mobile/src/components/ui/SettingsIcon.tsx create mode 100644 mobile/src/components/ui/Sheet.tsx create mode 100644 mobile/src/components/ui/SheetHeader.tsx create mode 100644 mobile/src/components/ui/Skeleton.tsx create mode 100644 mobile/src/components/ui/Spinner.tsx create mode 100644 mobile/src/components/ui/SwipeActions.tsx create mode 100644 mobile/src/components/ui/Text.tsx create mode 100644 mobile/src/components/ui/Toast.tsx create mode 100644 mobile/src/components/ui/index.ts create mode 100644 mobile/src/i18n/i18next.d.ts create mode 100644 mobile/src/i18n/index.ts create mode 100644 mobile/src/i18n/locales/en.json create mode 100644 mobile/src/lib/api.ts create mode 100644 mobile/src/lib/appConfig.ts create mode 100644 mobile/src/lib/authApi.ts create mode 100644 mobile/src/lib/config.ts create mode 100644 mobile/src/lib/dates.ts create mode 100644 mobile/src/lib/dialogs.ts create mode 100644 mobile/src/lib/haptics.ts create mode 100644 mobile/src/lib/money.ts create mode 100644 mobile/src/lib/navigation.ts create mode 100644 mobile/src/lib/pendingLink.test.ts create mode 100644 mobile/src/lib/pendingLink.ts create mode 100644 mobile/src/lib/pkce.test.mjs create mode 100644 mobile/src/lib/pkce.ts create mode 100644 mobile/src/lib/push.ts create mode 100644 mobile/src/lib/socialAuth.ts create mode 100644 mobile/src/lib/storage.ts create mode 100644 mobile/src/lib/storage.web.ts create mode 100644 mobile/src/providers/ApiProvider.tsx create mode 100644 mobile/src/providers/usePendingLink.ts create mode 100644 mobile/src/providers/usePushNotifications.ts create mode 100644 mobile/src/shims/prisma-client.ts create mode 100644 mobile/src/store/addExpenseStore.ts create mode 100644 mobile/src/store/authStore.ts create mode 100644 mobile/src/store/recentCurrencies.ts create mode 100644 mobile/src/theme/navigation.ts create mode 100644 mobile/src/theme/palette.test.ts create mode 100644 mobile/src/theme/palette.ts create mode 100644 mobile/src/theme/tokens.ts create mode 100644 mobile/src/types/expo.d.ts create mode 100644 mobile/tsconfig.json diff --git a/mobile/.claude/settings.json b/mobile/.claude/settings.json new file mode 100644 index 0000000..176e6a5 --- /dev/null +++ b/mobile/.claude/settings.json @@ -0,0 +1,5 @@ +{ + "enabledPlugins": { + "expo@claude-plugins-official": true + } +} diff --git a/mobile/.gitignore b/mobile/.gitignore new file mode 100644 index 0000000..d914c32 --- /dev/null +++ b/mobile/.gitignore @@ -0,0 +1,41 @@ +# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files + +# dependencies +node_modules/ + +# Expo +.expo/ +dist/ +web-build/ +expo-env.d.ts + +# Native +.kotlin/ +*.orig.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision + +# Metro +.metro-health-check* + +# debug +npm-debug.* +yarn-debug.* +yarn-error.* + +# macOS +.DS_Store +*.pem + +# local env files +.env*.local + +# typescript +*.tsbuildinfo + +# generated native folders +/ios +/android diff --git a/mobile/.npmrc b/mobile/.npmrc new file mode 100644 index 0000000..d67f374 --- /dev/null +++ b/mobile/.npmrc @@ -0,0 +1 @@ +node-linker=hoisted diff --git a/mobile/.prettierignore b/mobile/.prettierignore new file mode 100644 index 0000000..0892780 --- /dev/null +++ b/mobile/.prettierignore @@ -0,0 +1,7 @@ +node_modules +.expo +dist +ios +android +pnpm-lock.yaml +expo-env.d.ts diff --git a/mobile/.prettierrc.json b/mobile/.prettierrc.json new file mode 100644 index 0000000..47174e4 --- /dev/null +++ b/mobile/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100 +} diff --git a/mobile/AGENTS.md b/mobile/AGENTS.md new file mode 100644 index 0000000..be05e77 --- /dev/null +++ b/mobile/AGENTS.md @@ -0,0 +1,41 @@ +This is an Expo/React Native mobile application. Prioritize mobile-first patterns, performance, and cross-platform compatibility. + +## Expo has changed — do not trust your training data + +Expo ships breaking changes every SDK release. APIs you remember are likely renamed, moved, or removed. Before writing any code that touches an Expo, EAS, or React Native API: + +1. Read the major version of the `expo` package in `package.json`. +2. Fetch the matching versioned docs: `https://docs.expo.dev/versions/v.0.0/` +3. For anything else, fetch https://docs.expo.dev/llms.txt — an index of all Expo docs with corrections to common LLM misconceptions. Follow its links to the specific page you need; never answer from memory. + +## Commands + +Use `bunx` instead of `npx` if the project uses bun (`bun.lock` present). + +```bash +npx expo install # ALWAYS use instead of npm/yarn/pnpm/bun add — resolves SDK-compatible versions +npx expo start # start the dev server +npx expo lint # lint +npx tsc --noEmit # typecheck +npx expo-doctor # diagnose dependency and config issues +npx expo install --fix # fix incompatible package versions +``` + +Run lint and typecheck before declaring any task done. + +## Navigation & Routing + +- Use **Expo Router** for all navigation. Routes live in `src/app/` — every file there is a screen, `_layout.tsx` files define navigators. Keep non-route code (components, hooks, utils) outside `src/app/`. +- Import `Link`, `router`, and `useLocalSearchParams` from `expo-router`. +- Docs: https://docs.expo.dev/router/introduction.md + +## Building with EAS + +Use EAS to build, sign, and submit the app in the cloud (`eas build`, `eas submit`) and to ship over-the-air updates (`eas update`) — no local Xcode or Android Studio required. Run EAS CLI as `bunx eas-cli ` in Bun projects, or `npx eas-cli@latest ` otherwise; substitute that for bare `eas` in docs examples. +Docs: https://docs.expo.dev/eas/index.md + +## Rules + +- If `ios/` and `android/` directories do not exist, they are generated (Continuous Native Generation). Never create or edit them by hand — configure native behavior in `app.json` and config plugins. +- Expo Go only includes its bundled native modules. After adding a library with native code, the app needs a development build: `npx expo run:ios|android` locally, or `eas build --profile development`. +- Prefer recommended Expo modules over third-party libraries, and check your available skills before adding dependencies. Docs: https://docs.expo.dev/versions/latest/index.md diff --git a/mobile/README.md b/mobile/README.md new file mode 100644 index 0000000..0ffe075 --- /dev/null +++ b/mobile/README.md @@ -0,0 +1,342 @@ +# SplitPro mobile + +The iOS and Android app for [SplitPro](https://splitpro.app), built with Expo (SDK 58) and Expo Router. It +talks to the same tRPC API as the web app and reuses the web's pure logic from `../src`. + +## Run it + +```sh +cd mobile +pnpm install +pnpm start # then press i / a, or scan with a development build +pnpm ios # same as `expo start --ios` +``` + +The app uses native modules (Apple sign-in, secure store, SF Symbols, `@expo/ui`, haptics, glass +effect), so build a development client with `npx expo run:ios` / `npx expo run:android` (or +`eas build --profile development`), and rebuild it whenever a native dependency is added. Expo Go +can't run it. + +Point it at a local server with `EXPO_PUBLIC_API_URL=http://:3000 pnpm start`. The +default is `https://splitpro.app`. + +Checks: `pnpm typecheck`, `pnpm lint`, `pnpm format:check`, `pnpm test`. + +`pnpm test` runs the pure-logic tests (`src/**/*.test.ts` with Node's test runner through the +root's `tsx`, plus `node --test src/lib/pkce.test.mjs`). Run some with +`../node_modules/.bin/tsx --tsconfig tsconfig.json --test `. Tests can only import modules +that don't pull in React Native or Expo, so keep logic you want to test in plain `.ts` files. + +## Layout + +``` +src/ + app/ Expo Router routes (file = screen) + _layout.tsx splash, providers, navigation theme, auth guard (Stack.Protected) + (auth)/ sign-in, verify (email code) + (app)/_layout.tsx signed-in stack: tabs + detail screens + modals + (app)/(tabs)/ native tab bar; each tab is a group with its own stack: + (balances)/balances, (groups)/groups, (activity)/activity, + (account)/account + (app)/new.tsx old /new link, redirects to /add + (app)/balances/[friendId].tsx, groups/[groupId].tsx, expenses/[expenseId].tsx + (app)/add.tsx add/edit expense modal + (app)/settle-up.tsx settle-up form sheet + components/ui/ primitives, see "Native UI conventions" + i18n/ i18next setup + locales/en.json + lib/ + api.ts tRPC client: `api`, RouterInputs/RouterOutputs + authApi.ts all native-auth HTTP calls (/api/mobile/auth/*) + appConfig.ts useAppConfig(): server settings (invites on, receipt storage URL) + socialAuth.ts Apple (native) and Google (browser + PKCE) sign-in + storage.ts key-value storage: SecureStore on devices, localStorage on web + dialogs.ts confirmAction / showMessage (native Alert, browser dialogs on web) + navigation.ts goBackOr(fallback) + pendingLink.ts the link opened while signed out, opened after sign-in + push.ts push notifications + money.ts formatMoney / parseMoneyInput + config.ts API_URL + providers/ApiProvider.tsx React Query + tRPC, 401 handling, refetch on foreground + providers/usePendingLink.ts, usePushNotifications.ts + shims/prisma-client.ts Prisma enums for the shared code (see below) + store/authStore.ts session token (zustand over lib/storage) + store/recentCurrencies.ts recently used currencies, persisted + theme/tokens.ts semantic colors (light/dark), text styles, spacing, radii, layout + theme/navigation.ts native stack screen options shared by the layouts + lib/haptics.ts haptics.success / warning / error / selection / light +``` + +## Conventions + +- **Code style** follows the root `AGENTS.md`: arrow functions, Yoda comparisons + (`'signedIn' === status`, enforced by lint), early returns, `type` imports. +- **Imports**: `@/…` is `mobile/src`, `~/…` is the web's `../src`. Only import _pure_ modules from + `~/` (`~/utils/*`, `~/lib/currency`), plus `import type` from anywhere (e.g. + `~/server/api/root`). Never value-import server code: it would end up in the bundle. +- **Data**: use the typed hooks, e.g. `api.user.getBalances.useQuery()` and + `RouterOutputs['user']['getBalances']`. Don't call `fetch` for app data. A 401 anywhere signs the + user out automatically. +- **Money**: amounts are integer cents (the API's `number`), never floats. Display with `` or + `formatMoney`, parse user input with `parseMoneyInput`, split with `~/utils/splits`. +- **Styling**: `StyleSheet.create` + `@/theme/tokens`. No raw hex values or font names in + screens. Build on `components/ui`; see "Native UI conventions" below. +- **Strings**: every user-facing string goes through `t('…')`. Add English keys to + `src/i18n/locales/en.json` only; keys are type-checked. +- **Routes**: add a file under `src/app/(app)/`. Give it a title in `(app)/_layout.tsx`. Use + `presentation: 'modal' | 'fullScreenModal' | 'formSheet'` for flows, `` for quick picks. +- **Toasts**: `toast.success(…)` / `toast.error(…)` from `@/components/ui` (they also play the + success/error haptic). Log handled failures with `console.warn`: in development + `console.error` opens Expo's error overlay. +- **Storage**: use `storage` from `@/lib/storage` (never `expo-secure-store` directly, it does + nothing on web). For zustand, `persist` with `createJSONStorage(() => storage)`. Keys look like + `splitpro.somePref` (letters, digits, `.`, `-`, `_` only). +- **Server settings** the web reads in `getServerSideProps` (e.g. `ENABLE_SENDING_INVITES`) come + from `useAppConfig()`, backed by `user.getAppConfig`. Add fields there, not `EXPO_PUBLIC_*` vars. +- **Dialogs and back**: `confirmAction` / `showMessage` from `@/lib/dialogs`; close a screen with + `goBackOr()` from `@/lib/navigation`, which also works when the screen was opened from a link. + +## Native UI conventions + +The app should feel like it was built with UIKit / SwiftUI on iOS and Jetpack Compose on Android, not +like the website in a web view. Match what the system apps (Settings, Contacts, Wallet, Mail, Gmail, +Google Contacts) do; only reach for custom UI when there is no system equivalent. The reference +screens are sign-in / verify (`app/(auth)`), the Balances tab +(`app/(app)/(tabs)/(balances)/balances.tsx`) and the friend screen +(`app/(app)/balances/[friendId].tsx`). Copy them. + +### Theme: colors + +`colors` in `@/theme/tokens` are **semantic roles**, never brand hex values. On iOS they are system +colors (`PlatformColor`), so light/dark mode and Increased Contrast just work; on Android they are +Material 3 dynamic colors from the wallpaper; on web they are the iOS values for the scheme at +launch. The app follows the system appearance (`userInterfaceStyle: 'automatic'`). + +| Role | Use for | +| --------------------------------------------------------- | ------------------------------------------------------------------- | +| `background` / `secondaryBackground` | plain lists and free-form screens / tiles on them | +| `groupedBackground` / `secondaryGroupedBackground` | inset-grouped screens (forms, settings, detail) / the cells on them | +| `label`, `secondaryLabel`, `tertiaryLabel`, `placeholder` | text, in decreasing importance | +| `separator` | hairlines between rows | +| `fill`, `secondaryFill`, `tertiaryFill` | behind controls: search fields, gray buttons, code cells, skeletons | +| `highlight` | pressed row (iOS) / ripple (Android) | +| `tint` | brand cyan for text and icons: links, plain buttons, active tab | +| `tintFill`, `onTint` | brand cyan behind white: filled buttons, prominent header buttons | +| `tintStrong` | tint text on a tint wash (tinted buttons) | +| `positive`, `negative` | money you get back / money you owe | +| `destructive` | delete, remove, errors | + +Brand cyan is **only** the tint. Don't paint backgrounds, cards or headers with it. + +The tint is split because iOS always draws white on prominent bar buttons: white needs cyan-700 +(`tintFill`) for 4.5:1, which is too dark to read as text on black, so dark mode uses the bright +cyan for `tint`. The hex values live in `theme/palette.ts`, and `palette.test.ts` fails if a pair +drops below WCAG AA. Never put `onTint` on `tint`. + +### Theme: type + +`` uses the iOS text styles: `largeTitle`, `title1`–`title3`, `headline`, `body` +(default), `callout`, `subheadline`, `footnote`, `caption1`, `caption2`. Android gets the matching +Material 3 sizes. The font is the system font (SF Pro / Roboto); there is no custom font. Text scales +with Dynamic Type / font size, so never hardcode `fontSize` in screens; pick a variant. Use +`weight` for emphasis (`headline` is already semibold) and `tabular` for amounts that line up. +`footnote` and the captions default to `secondaryLabel`. + +```tsx +{name} +{t('auth.code_sent', { email })} + +``` + +Other tokens: `spacing` (4pt grid), `radii.section` (26 on iOS 26 Liquid Glass, 10 before, 16 on +Android), `layout.rowMinHeight` (44 iOS / 56 Android), `layout.rowAvatar`, `layout.sectionMargin`. + +### Navigation and headers + +- **Tabs** are the system tab bar (`NativeTabs` from `expo-router/native-tabs`): `UITabBar` with + Liquid Glass on iOS 26, the Material navigation bar on Android. Each tab is a route group with + its own `Stack` (`(tabs)/(balances)/_layout.tsx` …), so detail screens push inside the native stack + with the system back button and swipe-back. +- **Every screen has a native header.** Never draw a title or a back button in JS. Tab roots use + `tabRootOptions` (large title that collapses on scroll); detail screens use a normal title. + Set the title with `` or in the layout. +- **iOS 26 headers are transparent**: the root scroll view must have + `contentInsetAdjustmentBehavior="automatic"` and no top safe-area padding (`Screen edges={[]}`), + so content scrolls under the glass and the large title collapses. Every screen does this now. + `opaqueHeaderOptions` is only for page-sheet modals whose content starts with a large picture + (edit profile, feedback): a transparent header in a sheet covers the top of the content. +- Inset-grouped screens take `groupedScreenOptions` in their layout (the grouped background). +- **The large title only follows the list if the list is the screen's first view.** UIKit walks + the first-subview chain when the screen appears. So: no wrapping `` (return a fragment with + the list first, then `HeaderActions` / `AddExpenseAction`; put the background on the list's + `style`), and keep the list mounted while loading or failing: show the spinner or error through + `ListEmptyComponent`, not an early `return`. See `(tabs)/(balances)/balances.tsx`. +- **Back buttons are a chevron only** (`headerBackButtonDisplayMode: 'minimal'` in + `stackScreenOptions`), like iOS 26 system apps. Titles use `label`; the tint only colors buttons. +- **Header buttons**: `` anywhere in the screen. It renders + `Stack.Toolbar` items on iOS (glass buttons, SF Symbols, native `UIMenu`) and Material icon + buttons with a dropdown menu on Android. Use one icon button per action, an `icons.more` menu + for the rest; destructive items go in the menu, never as a bare header button, in their own + section at the end (`{ items: [...] }`), which draws a divider above them. An action without + `icon` is a text button. +- **Menu items must be direct children of `Stack.Toolbar.Menu`.** It filters its children by type, + so wrapping a `Stack.Toolbar.MenuAction` in your own component makes the menu silently not open. + `HeaderActions` renders items with a plain function for this reason. +- **Add expense** on tab roots: ``. It is the + prominent "+" in the iOS navigation bar and an extended FAB on Android. Render one per screen. +- **Modals**: flows with their own route (add expense, new group, add members, default split, + edit profile, feedback, settle up) use ``: + glass ✕ / tinted ✓ on iOS 26, "Cancel" / bold "Done"-style text before iOS 26, ✕ and a text button + (Material full-screen dialog) on Android. `onBack` swaps Cancel for a back chevron for a later + step (settle up's amount step). `presentation: 'modal'` for flows, `'formSheet'` + + `sheetAllowedDetents` for quick tasks with a few fields. +- **Sheets with a confirm button** (`Sheet` content, e.g. the split editor) use `SheetHeader`, drawn + to match `ModalHeader`. Sheets with `size="medium" | "large"` don't pad the bottom; give the list a + bottom content inset of `useSafeAreaInsets().bottom` so it scrolls to the sheet's edge. + +```tsx + + +``` + +### Which component + +| Need | Use | +| ------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| Plain list (balances, activity) | `FlatList`/`SectionList` + `ListRow`, `ItemSeparatorComponent={() => }` | +| Settings-style / form / detail screen | `Screen background="grouped"` + `Section header footer` containing `ListRow`s or `Input inline` | +| Long grouped list | `SectionList` + `SectionHeader` + `SectionCell first last` (see the friend screen) | +| Row that opens a screen | `ListRow accessory="chevron"` (chevron shows on iOS only, as on Material) | +| Pick one of a few options | `ListRow accessory="checkmark"` in a `Section`, or a menu (`HeaderActions` `menu`) | +| Pick from a long list (currency) | `Sheet size="large"` + `SearchField` + list (see `CurrencySheet`) | +| 2–4 mutually exclusive views | `SegmentedControl` from `@expo/ui/community/segmented-control` (+ `haptics.selection()`) | +| Dropdown-style picker | `Picker` from `@expo/ui/community/picker` | +| Date / time | `@expo/ui/community/datetime-picker` (inline or compact on iOS, Material dialog on Android) | +| On/off | RN `Switch` with `trackColor={{ true: colors.tint }}`, nothing else | +| Menu from a button | `HeaderActions` `menu` in the header, `MenuView` from `@expo/ui/community/menu` elsewhere | +| Pick a value from a menu in a row | `PopUpButton` (iOS pop-up button: value + ⌃⌄, opens a `MenuView`) | +| Row actions on swipe | `SwipeActions` around the row (UIKit-style buttons from the trailing edge); keep a menu too | +| Settings-style row icon | `SettingsIcon` (white symbol on a colored tile on iOS, plain Material symbol on Android) | +| Sticky section headers under a header | `StickyHeaderComponent={InsetStickyHeader}`; turn sticky headers off while a search bar is active | +| Long-press menu + peek on a row (iOS) | `Link` with `Link.Trigger` / `Link.Preview` / `Link.Menu` (see `FriendBalanceRow`) | +| Confirm a destructive action | `confirmAction({ destructive: true, … })` from `@/lib/dialogs` (native alert) | +| Quick in-screen task | `Sheet` (`@expo/ui` bottom sheet: SwiftUI sheet / Material modal sheet) | +| Buttons in content | `Button` `filled` (one primary per screen), `tinted`, `gray`, `plain`, `destructive` | +| Actions under a profile header | `QuickActions` (Contacts-card tiles) | +| Summary numbers | tiles like `BalanceTotals`, or a `Card` on a grouped screen | +| Search on a screen with a header | `Stack.SearchBar` / `headerSearchBarOptions`; `SearchField` only inside sheets | +| Empty / error state | `EmptyState` with an `icons.*` symbol (ContentUnavailableView) | +| Loading | `FullScreenSpinner` (system `ActivityIndicator`); `RefreshControl` without a custom tint | +| Feedback after an action | `toast.success/error` (glass capsule above modals, plays the haptic) | +| Text field | `Input` (filled field on iOS, outlined on Android); `Input inline` inside a `Section` | +| A date shown to the user | `formatDate` from `@/lib/dates` (device locale, medium style, like the date picker) | + +### Icons + +`` renders an SF Symbol on iOS and a Material Symbol on Android via +`expo-symbols`. Add every new icon to the `icons` map in `components/ui/Icon.tsx` with both names, so +the platforms stay paired (SF Symbols app / fonts.google.com/icons). Header and tab icons take the +same names (`icon.ios` for `sf`, `icon.android` for `md`). There is no icon font or Lucide; brand +marks (Google "G", X logo) are SVGs (`react-native-svg`). + +Don't keep local icon maps in feature folders; `icons` is the only table (settings tiles, form rows, +menus all use it). Common pairs: add `plus`/`add`, more `ellipsis`/`more_vert`, share `square.and.arrow.up`/`share`, +delete `trash`/`delete`, edit `pencil`/`edit`, settle `arrow.left.arrow.right`/`handshake`, receipt +`list.bullet.rectangle`/`receipt_long`, error `exclamationmark.triangle`/`error`. + +### Haptics + +`haptics` from `@/lib/haptics`: `selection()` when a picker/segment/checkmark value changes, +`light()` for a long press, `warning()` before a destructive confirmation, `success()`/`error()` +only when there's no toast (`toast.success/error` already play them). Don't add haptics to plain +taps or navigation. + +### Gotchas learned in the conversion + +- `MenuView` (`@expo/ui/community/menu`) sizes itself to its child: give the child an explicit size + or `alignSelf`, or the tap target collapses. +- `ActionSheetIOS` crashes when given the app's dynamic tint (`tintColor: colors.tint`, a + `DynamicColorIOS`). Leave `tintColor` out; the sheet takes the window tint (see `ReceiptRow`). +- `@expo/ui`'s `DateTimePicker` types `accentColor` as a string; the dynamic `colors.tint` needs a + cast (`colors.tint as string`). It still resolves per mode at runtime. +- In dark mode the date picker's selected day is drawn by iOS in white on `accentColor` (the bright + `tint`), about 2.4:1. Passing `tintFill` instead would fix the day but make the month heading + and arrows fail on the dark popover, and no single cyan passes both. Left as the system draws it. +- Changing the simulator's appearance closes open menus; when screenshotting a menu in both modes, + switch the mode first, then open it. + +### Platform differences worth keeping + +- iOS: chevrons on push rows, highlight on press, primary action in the navigation bar, inset-grouped + sections with continuous corners, swipe-back. +- Android: ripples (`android_ripple`), no chevrons, extended FAB for the primary action, overflow + menu `more_vert`, 56dp rows, outlined text fields, system back. +- Branch with `Platform.OS` / `Platform.select` inside components in `components/ui`; screens should + rarely need to. + +### Do / don't + +- Do use system controls (`Switch`, `ActivityIndicator`, `Alert`, menus, sheets, pickers) instead of + drawing look-alikes. +- Do let lists fill the screen edge to edge; use `Section` for grouped content instead of bordered + web cards. +- Do give icon-only buttons an `accessibilityLabel` and mark titles with `accessibilityRole="header"`. +- Don't hardcode hex colors, font families, font sizes or `keyboardAppearance`. +- Don't put a JS title above content, a custom back arrow, or a custom tab bar. +- Don't use borders around inputs or cards on iOS, or cyan backgrounds anywhere but `filled` buttons. +- Don't wrap rows in pressable "cards" with shadows; that's the web look this replaced. + +### Native dependencies + +Added for the native UI: `expo-symbols` (SF / Material Symbols), `expo-haptics`, `@expo/ui` (sheets, +menus, pickers, segmented control), `expo-glass-effect` (Liquid Glass toast and sheet buttons), +`react-native-gesture-handler` + `react-native-reanimated` + `react-native-worklets` (swipe actions; +the app root is a `GestureHandlerRootView`). Removed: +`@expo-google-fonts/poppins`. These need a **new development build** (`npx expo run:ios` / +`run:android`, or EAS) — an old dev client will crash on the missing native modules. After changing +`app.config.ts` (e.g. `userInterfaceStyle`), regenerate native projects with +`npx expo prebuild --clean`. + +Building for the simulator with `xcodebuild` directly: keep ad-hoc signing (`CODE_SIGN_IDENTITY=-`). +`CODE_SIGNING_ALLOWED=NO` drops the entitlements, the keychain stops working, and you are signed +out on every launch. + +## Sharing code with the web + +`metro.config.js` watches only `../src`, and resolves bare imports from shared files (`zod`, +`date-fns`, …) from `mobile/node_modules`, so the web's `node_modules` is never bundled. It is +on the blocklist, so a mistake fails the build instead of shipping silently. + +The shared utils import enums from `@prisma/client`, which can't run in React Native. Metro serves +`src/shims/prisma-client.ts` for that import instead. TypeScript still sees the real Prisma types, +and the shim uses `satisfies` so `pnpm typecheck` fails if the schema's enums change without it. +If you add an enum to `schema.prisma` that shared code uses, add it to the shim. + +Mobile is excluded from the root `tsconfig.json`, ESLint, Prettier and Docker build. It has its own +`package.json`, lockfile and configs. + +## Auth + +Email code: `POST /api/mobile/auth/email` → `POST /api/mobile/auth/email/verify` returns +`{ token, user }`. Apple: `POST /api/mobile/auth/apple` with the identity token. The token is kept +in `lib/storage` and sent as `Authorization: Bearer ` on every tRPC call. Sign-out calls +`POST /api/mobile/auth/signout` with the device's push token, so the server forgets both at once. +Google: browser sign-in, then `POST /api/mobile/auth/exchange` +with a PKCE verifier (`lib/socialAuth.ts`). + +The guard in `app/_layout.tsx` sends signed-out users to sign-in, whatever link opened the app. +`useSaveLinkWhileSignedOut` remembers that link (e.g. `splitpro://join-group?groupId=…`) and +`useOpenPendingLink` in `(app)/_layout.tsx` opens it once the user signs in, however they sign in. +Notification taps are read when the signed-in layout mounts, so they also survive sign-in. + +## Not done yet + +Universal links / App Links are commented +out in `app.config.ts` until splitpro.app serves the `.well-known` files. diff --git a/mobile/app.config.ts b/mobile/app.config.ts new file mode 100644 index 0000000..a379684 --- /dev/null +++ b/mobile/app.config.ts @@ -0,0 +1,75 @@ +import { type ConfigContext, type ExpoConfig } from 'expo/config'; + +/** The brand's dark navy, behind the adaptive icon. */ +const ICON_BACKGROUND = '#030711'; + +// @koushikdotdev/splitpro on expo.dev. Push tokens and EAS builds are tied to it. +const EAS_PROJECT_ID = '82694b46-ca71-4652-a8cf-2674a5ced9e4'; + +export default ({ config }: ConfigContext): ExpoConfig => ({ + ...config, + name: 'SplitPro', + slug: 'splitpro', + owner: 'koushikdotdev', + scheme: 'splitpro', + version: '1.0.0', + orientation: 'portrait', + icon: './assets/icon.png', + // Follows the system appearance; colors come from semantic tokens (src/theme/tokens.ts). + userInterfaceStyle: 'automatic', + ios: { + bundleIdentifier: 'app.splitpro', + supportsTablet: true, + usesAppleSignIn: true, + // TODO: enable universal links once https://splitpro.app/.well-known/apple-app-site-association + // is served: associatedDomains: ['applinks:splitpro.app'], + }, + android: { + package: 'app.splitpro', + adaptiveIcon: { + foregroundImage: './assets/icon.png', + backgroundColor: ICON_BACKGROUND, + }, + // TODO: add App Links once https://splitpro.app/.well-known/assetlinks.json is served: + // intentFilters: [{ action: 'VIEW', autoVerify: true, category: ['BROWSABLE', 'DEFAULT'], + // data: [{ scheme: 'https', host: 'splitpro.app' }] }], + }, + plugins: [ + 'expo-router', + 'expo-status-bar', + // No biometrics, so no Face ID usage text. + ['expo-secure-store', { faceIDPermission: false }], + 'expo-localization', + 'expo-font', + 'expo-image', + 'expo-apple-authentication', + 'expo-web-browser', + [ + 'expo-image-picker', + { + photosPermission: 'SplitPro uses your photos to attach receipts to expenses.', + cameraPermission: 'SplitPro uses the camera to take photos of receipts.', + // Photos only, never video. + microphonePermission: false, + }, + ], + // TODO: add `icon`, a 96x96 white-on-transparent PNG, or Android shows a white square. + ['expo-notifications', { color: '#06b6d4', defaultChannel: 'default' }], + [ + 'expo-splash-screen', + { + image: './assets/splash-icon.png', + imageWidth: 160, + backgroundColor: '#ffffff', + dark: { backgroundColor: '#000000' }, + }, + ], + ], + extra: { + ...config.extra, + eas: { ...config.extra?.eas, projectId: EAS_PROJECT_ID }, + }, + experiments: { + typedRoutes: true, + }, +}); diff --git a/mobile/assets/icon.png b/mobile/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..280d2f5eb8754b32251b38eaad5a455fc9d3903c GIT binary patch literal 58828 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 XK*WU<4SX@_XPD2NID4FW6qWZsmZfS! literal 0 HcmV?d00001 diff --git a/mobile/assets/splash-icon.png b/mobile/assets/splash-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3db4993c2f594650baab72d70ae3c6da68ffb9cc GIT binary patch literal 14407 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 Tjc_Fd6k&^%gJq66EAsyV@Qx#n literal 0 HcmV?d00001 diff --git a/mobile/eas.json b/mobile/eas.json new file mode 100644 index 0000000..4446981 --- /dev/null +++ b/mobile/eas.json @@ -0,0 +1,36 @@ +{ + "cli": { + "version": ">= 25.0.0", + "appVersionSource": "remote" + }, + "build": { + "base": { + "node": "22.20.0", + "pnpm": "10.32.1", + "env": { + "EXPO_PUBLIC_API_URL": "https://splitpro.app" + } + }, + "simulator": { + "extends": "base", + "distribution": "internal", + "ios": { + "simulator": true + } + }, + "preview": { + "extends": "base", + "distribution": "internal", + "android": { + "buildType": "apk" + } + }, + "production": { + "extends": "base", + "autoIncrement": true + } + }, + "submit": { + "production": {} + } +} diff --git a/mobile/eslint.config.js b/mobile/eslint.config.js new file mode 100644 index 0000000..856b570 --- /dev/null +++ b/mobile/eslint.config.js @@ -0,0 +1,15 @@ +// https://docs.expo.dev/guides/using-eslint/ +const { defineConfig, globalIgnores } = require('eslint/config'); +const expoConfig = require('eslint-config-expo/flat'); + +module.exports = defineConfig([ + globalIgnores(['dist/*', '.expo/*', 'ios/*', 'android/*']), + expoConfig, + { + rules: { + // Match the web app's style (AGENTS.md at the repo root). + yoda: ['error', 'always', { onlyEquality: true }], + 'no-console': ['warn', { allow: ['info', 'warn', 'error', 'debug', 'trace'] }], + }, + }, +]); diff --git a/mobile/metro.config.js b/mobile/metro.config.js new file mode 100644 index 0000000..18f940d --- /dev/null +++ b/mobile/metro.config.js @@ -0,0 +1,48 @@ +// Learn more https://docs.expo.dev/guides/customizing-metro +const path = require('path'); +const { getDefaultConfig } = require('expo/metro-config'); + +const projectRoot = __dirname; +const repoRoot = path.resolve(projectRoot, '..'); +const sharedRoot = path.join(repoRoot, 'src'); +const prismaShim = path.join(projectRoot, 'src/shims/prisma-client.ts'); + +/** @type {import('expo/metro-config').MetroConfig} */ +const config = getDefaultConfig(projectRoot); + +// The app reuses pure logic from the web app (../src/utils, ../src/lib). Only watch that folder: +// the rest of the repo (the web's node_modules, .next, prisma) must never end up in the bundle. +config.watchFolders = [sharedRoot]; + +// Fail loudly instead of silently bundling a package from the web's node_modules. +const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +const defaultBlockList = config.resolver.blockList ?? []; +config.resolver.blockList = [ + ...(Array.isArray(defaultBlockList) ? defaultBlockList : [defaultBlockList]), + new RegExp(`^${escapeRegExp(path.join(repoRoot, 'node_modules'))}/.*`), +]; + +const isBareSpecifier = (moduleName) => + !moduleName.startsWith('.') && !moduleName.startsWith('/') && !moduleName.startsWith('~/'); + +config.resolver.resolveRequest = (context, moduleName, platform) => { + // The shared files import enums from @prisma/client. The real package is Node-only, so swap in a + // tiny shim with the same enum values. + if ('@prisma/client' === moduleName) { + return { type: 'sourceFile', filePath: prismaShim }; + } + + // Packages imported by shared files (zod, date-fns, ...) resolve from mobile/node_modules as if + // they were imported by the app, so the bundle never picks up the web's copies in ../node_modules. + if (context.originModulePath.startsWith(sharedRoot + path.sep) && isBareSpecifier(moduleName)) { + return context.resolveRequest( + { ...context, originModulePath: path.join(projectRoot, 'package.json') }, + moduleName, + platform, + ); + } + + return context.resolveRequest(context, moduleName, platform); +}; + +module.exports = config; diff --git a/mobile/package.json b/mobile/package.json new file mode 100644 index 0000000..40ad89a --- /dev/null +++ b/mobile/package.json @@ -0,0 +1,69 @@ +{ + "name": "splitpro-mobile", + "version": "1.0.0", + "private": true, + "main": "expo-router/entry", + "scripts": { + "start": "expo start", + "ios": "expo run:ios", + "android": "expo run:android", + "typecheck": "tsc --noEmit", + "test": "../node_modules/.bin/tsx --tsconfig tsconfig.json --test 'src/**/*.test.ts' && node --test src/lib/pkce.test.mjs", + "lint": "eslint .", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "dependencies": { + "@expo/ui": "~58.0.21", + "@formatjs/intl-pluralrules": "^6.3.16", + "@tanstack/react-query": "^4.44.0", + "@trpc/client": "10.45.4", + "@trpc/react-query": "10.45.4", + "@trpc/server": "10.45.4", + "date-fns": "^3.6.0", + "expo": "~58.0.16", + "expo-apple-authentication": "~58.0.2", + "expo-constants": "~58.0.12", + "expo-crypto": "~58.0.7", + "expo-device": "~58.0.5", + "expo-file-system": "~58.0.10", + "expo-font": "~58.0.9", + "expo-glass-effect": "~58.0.4", + "expo-haptics": "~58.0.7", + "expo-image": "~58.0.16", + "expo-image-picker": "~58.0.10", + "expo-linking": "~58.0.13", + "expo-localization": "~58.0.5", + "expo-notifications": "~58.1.5", + "expo-router": "~58.0.24", + "expo-secure-store": "~58.0.2", + "expo-sharing": "~58.0.19", + "expo-splash-screen": "~58.0.10", + "expo-status-bar": "~58.0.3", + "expo-symbols": "~58.0.4", + "expo-system-ui": "~58.0.6", + "expo-web-browser": "~58.0.6", + "i18next": "^26.5.3", + "react": "19.3.0", + "react-dom": "19.3.0", + "react-i18next": "^17.1.0", + "react-native": "0.88.0", + "react-native-gesture-handler": "~3.3.0", + "react-native-reanimated": "4.7.1", + "react-native-safe-area-context": "~5.10.1", + "react-native-screens": "~4.30.0", + "react-native-svg": "15.16.0", + "react-native-web": "^0.21.4", + "react-native-worklets": "0.13.0", + "superjson": "^2.2.6", + "zod": "^3.25.76", + "zustand": "^5.0.15" + }, + "devDependencies": { + "@types/react": "~19.3.0", + "eslint": "^9.39.5", + "eslint-config-expo": "~58.0.4", + "prettier": "^3.9.10", + "typescript": "~6.0.3" + } +} diff --git a/mobile/pnpm-lock.yaml b/mobile/pnpm-lock.yaml new file mode 100644 index 0000000..cda945a --- /dev/null +++ b/mobile/pnpm-lock.yaml @@ -0,0 +1,8513 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@expo/ui': + specifier: ~58.0.21 + version: 58.0.21(@babel/core@7.29.7)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@formatjs/intl-pluralrules': + specifier: ^6.3.16 + version: 6.3.16 + '@tanstack/react-query': + specifier: ^4.44.0 + version: 4.44.0(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@trpc/client': + specifier: 10.45.4 + version: 10.45.4(@trpc/server@10.45.4) + '@trpc/react-query': + specifier: 10.45.4 + version: 10.45.4(@tanstack/react-query@4.44.0(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(@trpc/client@10.45.4(@trpc/server@10.45.4))(@trpc/server@10.45.4)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@trpc/server': + specifier: 10.45.4 + version: 10.45.4 + date-fns: + specifier: ^3.6.0 + version: 3.6.0 + expo: + specifier: ~58.0.16 + version: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-apple-authentication: + specifier: ~58.0.2 + version: 58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-constants: + specifier: ~58.0.12 + version: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + expo-crypto: + specifier: ~58.0.7 + version: 58.0.7(expo@58.0.16) + expo-device: + specifier: ~58.0.5 + version: 58.0.5(expo@58.0.16) + expo-file-system: + specifier: ~58.0.10 + version: 58.0.10(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)) + expo-font: + specifier: ~58.0.9 + version: 58.0.9(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-glass-effect: + specifier: ~58.0.4 + version: 58.0.4(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-haptics: + specifier: ~58.0.7 + version: 58.0.7(expo@58.0.16) + expo-image: + specifier: ~58.0.16 + version: 58.0.16(expo@58.0.16)(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-image-picker: + specifier: ~58.0.10 + version: 58.0.10(expo@58.0.16) + expo-linking: + specifier: ~58.0.13 + version: 58.0.13(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-localization: + specifier: ~58.0.5 + version: 58.0.5(expo@58.0.16)(react@19.3.0) + expo-notifications: + specifier: ~58.1.5 + version: 58.1.5(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-router: + specifier: ~58.0.24 + version: 58.0.24(128dea09177de0be5e43cb7aba297f1e) + expo-secure-store: + specifier: ~58.0.2 + version: 58.0.2(expo@58.0.16) + expo-sharing: + specifier: ~58.0.19 + version: 58.0.19(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-splash-screen: + specifier: ~58.0.10 + version: 58.0.10(expo@58.0.16)(typescript@6.0.3) + expo-status-bar: + specifier: ~58.0.3 + version: 58.0.3(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-symbols: + specifier: ~58.0.4 + version: 58.0.4(expo-font@58.0.9)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-system-ui: + specifier: ~58.0.6 + version: 58.0.6(expo@58.0.16)(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)) + expo-web-browser: + specifier: ~58.0.6 + version: 58.0.6(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)) + i18next: + specifier: ^26.5.3 + version: 26.5.3(typescript@6.0.3) + react: + specifier: 19.3.0 + version: 19.3.0 + react-dom: + specifier: 19.3.0 + version: 19.3.0(react@19.3.0) + react-i18next: + specifier: ^17.1.0 + version: 17.1.0(i18next@26.5.3(typescript@6.0.3))(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react-native: + specifier: 0.88.0 + version: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + react-native-gesture-handler: + specifier: ~3.3.0 + version: 3.3.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-reanimated: + specifier: 4.7.1 + version: 4.7.1(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-safe-area-context: + specifier: ~5.10.1 + version: 5.10.1(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-screens: + specifier: ~4.30.0 + version: 4.30.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-svg: + specifier: 15.16.0 + version: 15.16.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-web: + specifier: ^0.21.4 + version: 0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react-native-worklets: + specifier: 0.13.0 + version: 0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + superjson: + specifier: ^2.2.6 + version: 2.2.6 + zod: + specifier: ^3.25.76 + version: 3.25.76 + zustand: + specifier: ^5.0.15 + version: 5.0.15(@types/react@19.3.0)(react@19.3.0)(use-sync-external-store@1.7.0(react@19.3.0)) + devDependencies: + '@types/react': + specifier: ~19.3.0 + version: 19.3.0 + eslint: + specifier: ^9.39.5 + version: 9.39.5 + eslint-config-expo: + specifier: ~58.0.4 + version: 58.0.4(eslint@9.39.5)(typescript@6.0.3) + prettier: + specifier: ^3.9.10 + version: 3.9.10 + typescript: + specifier: ~6.0.3 + version: 6.0.3 + +packages: + + 2g@1.0.1: + resolution: {integrity: sha512-+uViadKOS/wwR4pFu5g8TPn3QHpKqoX19JHCnp8k/3cLpImdcXozwvZA6Q/5PeW3AcU8neL8faaMidBcv7o8CA==} + hasBin: true + peerDependencies: + typescript: '>=5.8.0' + peerDependenciesMeta: + typescript: + optional: true + + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.29.7': + resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.29.7': + resolution: {integrity: sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.29.10': + resolution: {integrity: sha512-/YY9soQuWa8TURtHXHT+GbklpbAA+dZErxFGHIr6qgDg96xuGWrTAs1+MfjgVJPF0YLQsOVsOYs8lhgsPbOinQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.8': + resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.29.7': + resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.29.7': + resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.29.7': + resolution: {integrity: sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.29.7': + resolution: {integrity: sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.29.7': + resolution: {integrity: sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.10': + resolution: {integrity: sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.9': + resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-proposal-decorators@7.29.7': + resolution: {integrity: sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-export-default-from@7.29.7': + resolution: {integrity: sha512-p+G5BNXDcy3bOXplhY4HybQ1GxH3i2Tppmdm/3epyRu2VgJJZuUlZ61MqRTg582Q7ZLBdP7fePYvsumSEkMxcQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.29.7': + resolution: {integrity: sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-dynamic-import@7.8.3': + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-export-default-from@7.29.7': + resolution: {integrity: sha512-foag0BB37ROhdeIX9O8G0jX7hw0UekJc04cHMrYLOnrErsnBKqJGHJ8eDRpoCFZBvEPPygmmtw4qyU97qa4oOw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-flow@7.29.7': + resolution: {integrity: sha512-ajMX6QPcyomotqwpzhkYGxcK2i/us0rs1Qo9QvUpa+Fca0FTmqrzKrctoIYLMxcOhGZldGT/BAVkRGTWBiR8gQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.29.7': + resolution: {integrity: sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.29.7': + resolution: {integrity: sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-arrow-functions@7.29.7': + resolution: {integrity: sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.7': + resolution: {integrity: sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.29.7': + resolution: {integrity: sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.29.7': + resolution: {integrity: sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.29.7': + resolution: {integrity: sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.29.7': + resolution: {integrity: sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.29.7': + resolution: {integrity: sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.29.7': + resolution: {integrity: sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.29.7': + resolution: {integrity: sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-flow-strip-types@7.29.7': + resolution: {integrity: sha512-wRHeUjUjCZnMHmiO5bRgjFLcoEh7JyTdByOW11ahhwNa4V0bmeGEaIvt51yq0zQp2yWIpqfxXXPyUP6GFJZHOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.29.7': + resolution: {integrity: sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.29.7': + resolution: {integrity: sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.29.7': + resolution: {integrity: sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7': + resolution: {integrity: sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7': + resolution: {integrity: sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.29.7': + resolution: {integrity: sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.29.7': + resolution: {integrity: sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.29.7': + resolution: {integrity: sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.29.7': + resolution: {integrity: sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.29.7': + resolution: {integrity: sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.29.7': + resolution: {integrity: sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.29.7': + resolution: {integrity: sha512-+1wdDMGNb4UPeY3Q4L5yLiYe6TXPXubs4NjrgRFw13hPRLJfEMw2Q5OXkee6/IfdqePIeW4Jjwe3aBh7SdKz4Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.29.7': + resolution: {integrity: sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.29.7': + resolution: {integrity: sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.29.7': + resolution: {integrity: sha512-H5E+HBgDpr6Q5t+Aj11tL7XkIui1jhbIoArVQnqjgXo5/3YxkN7ZEBcWF4RQlB0T4rrxJQbXS6kiFV6B7XTqUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.8': + resolution: {integrity: sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.29.7': + resolution: {integrity: sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.29.7': + resolution: {integrity: sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.29.7': + resolution: {integrity: sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.29.9': + resolution: {integrity: sha512-FFwIwzU+7SCOuxxV4YtJql6T9981ZVTm+FHO5GhVsRqCTdy0WwrEZh3l42ARpXruJUDGOptdduHW6Zr7pNPLNg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.29.7': + resolution: {integrity: sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.29.7': + resolution: {integrity: sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.10': + resolution: {integrity: sha512-NpugTzbKgGrNe45Ui32cN8vCFFMxVtP/9rtfwv0nP5FRDAjvYBxJcLVpYA9mr1jxP6cnIT7x9LUzuDTbWYYNRA==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.10': + resolution: {integrity: sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.7': + resolution: {integrity: sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.5': + resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@expo-google-fonts/material-symbols@0.4.50': + resolution: {integrity: sha512-XNSgSfd+1p6wqRAzzhrckGngHJQ1/z+oCMdI5FN+x/VnDeMMFGkXsuRNPYcZTYYff1GwVwx4u6Gqnb30aALysw==} + + '@expo/cli@58.1.13': + resolution: {integrity: sha512-a3FBo818/laj78tmDe8j/oOmxv8XBtA7nYdQQNHjebj1+RbhJjlZNxc2e1SwFXj8pXtruCdrs7fNFQTAFjS6GA==} + hasBin: true + peerDependencies: + expo: '*' + expo-router: '*' + react-native: '*' + peerDependenciesMeta: + expo-router: + optional: true + react-native: + optional: true + + '@expo/code-signing-certificates@0.0.7': + resolution: {integrity: sha512-zP0tnfqrFFRL8INtOaQ6XwEYfdIpIH9vrEo7y0bHQGQa50z4/QWXE5CI4nRUHxqFW4MVWOwXFg1hom1aAZHNkQ==} + engines: {node: '>=22.13.0'} + + '@expo/config-plugins@58.0.9': + resolution: {integrity: sha512-HyP7V1QgDxeHcOEh4qQH7cfK7cI7wNp0y9lszAu98SRYCshhDbwB9gWpFfnpX1GQUtgiqG4Hvgh1z3ntcGwAjw==} + + '@expo/config-types@58.0.3': + resolution: {integrity: sha512-wyfrwkTT/hQHzwyqkXkngKxoOa8L6ovsTP4h/UukS1mTmssee5et6HOPoN5RtawdJPnm5JO28f//C/wXlpka8Q==} + + '@expo/config@58.0.6': + resolution: {integrity: sha512-PT1qv4s/R5A/NxXb4efGlFsYF5Consi7F8xSsJBAN090EGDr6U1EDQGOijFqzDc3JA2epD8zjKLJLOVB9YOewg==} + + '@expo/devcert@1.2.2': + resolution: {integrity: sha512-wz1YedXwdNbYqk/PRr34vixnuw1+l6uSwmPXUj649cot5iYNccb2zIOnK7Nonb1Pfd/dxAY6CvU6KM3uSdxC7A==} + + '@expo/devtools@58.0.2': + resolution: {integrity: sha512-WBj/K+vv8JPSmY70ennL04YYOHkpEsGGkfuVY9lfv4XO7Qhbt5qz4q6W7maME194I5oGcimRMigUFfWNkBe90w==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + peerDependenciesMeta: + expo: + optional: true + react: + optional: true + react-native: + optional: true + + '@expo/dom-webview@58.0.2': + resolution: {integrity: sha512-bLkREoP7qL3rEuzxP60xG+TjdPoGjbnZfxkvYo5imJxGWfKMOf7x962W06Pu+WWAr4gcDRk16iA+Clg8D0zjCg==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + '@expo/env@2.5.2': + resolution: {integrity: sha512-z8kCvBVJpd2S20a+Ab1otQgz8sJLeR7CXDTsuAMcNbYFsK10Fdhfb7rx9Ys1vvlbijnY55eZhQvJACajc1IjBQ==} + engines: {node: '>=20.12.0'} + + '@expo/fingerprint@0.21.5': + resolution: {integrity: sha512-4ngc+aPgMK56sYc47tfabmoaNdP7OvPBOH7QPgN3riSYM0Ev+KwsGRDius5jBBwjCI9ADp7IpjJEK9xlRYjjvA==} + hasBin: true + + '@expo/image-utils@0.12.5': + resolution: {integrity: sha512-nsFYd7GfDdwZa+S+p+EkVCkh7UKKNf0kfUXDQ53HbyMmNFD3psb5JYwU/2N+uZG5wOEfKGfQ5u7pk/wn2gMlBA==} + + '@expo/inline-modules@0.2.6': + resolution: {integrity: sha512-S8PK3wx6ogwunoQ7pqdPbklQGtXloeWTAOzWJ9yIL7xHFxvnI/Ryj0phA3KEGCMlaKZjaCP1h/3s7n/ueErRgQ==} + + '@expo/json-file@11.2.1': + resolution: {integrity: sha512-UPhKoFCj8BcwgLB1rKQ1CuR/REITnZLiqxHEHOeH1tPsdXcHGtUDh0P5bLbr7oU0nKVdtJ5rzyKx8jniMQdESQ==} + + '@expo/local-build-cache-provider@58.0.6': + resolution: {integrity: sha512-AJk3pslFNlwRMbUbfvxhu6CPA9U7A+JPb88VS/uWkG/S/QMJL90Iw4sPVfG4BOKfRUNkB8ipl432Dr4txjSMKw==} + + '@expo/log-box-utils@58.0.2': + resolution: {integrity: sha512-My8Lwe9FU/yDwwzqwi5LN2rzzDcJqIAZKrD9f0XHZEKz/FQnWJYdt1rsV7+RwqMGeGq2XsxTCVT1ggTCOvumxw==} + + '@expo/log-box@58.0.12': + resolution: {integrity: sha512-IzDYoFY2iUsmSDvl1V7YUM7UkCPDyMVS4e4a38c2LnFc1A3WGMUiQh+vsHLYTPKjIelu4r7/u4V7Gxtfa0oJgA==} + peerDependencies: + '@expo/dom-webview': ^58.0.2 + expo: '*' + react: '*' + react-native: '*' + peerDependenciesMeta: + expo: + optional: true + + '@expo/metro-config@58.0.15': + resolution: {integrity: sha512-uVfYUVEknMo+T0xpTO+0l/rnaQUqBBwE5ALnQ/82cVIelKfDvW53ygjAC/AUFreLxhtmsGDBXWusegn16AI/RQ==} + peerDependencies: + expo: '*' + peerDependenciesMeta: + expo: + optional: true + + '@expo/metro-file-map@58.0.5': + resolution: {integrity: sha512-Y2w8qKklLffZie28In4WF6f6e8nIJOhU0mZ5UaQdCiITVQm2a5teNdIDudEPkBsh8ItlvyHZt9n42PN2onRbkQ==} + + '@expo/metro-runtime@58.0.14': + resolution: {integrity: sha512-IIvTo+RpN5jZVuYspQdECsxQ03VGWjZnGS6wtr9U7DERBpykUe+ZSHDZ1hsrvQ7HAucsVoKr9np0xAscGEuXtg==} + peerDependencies: + '@expo/log-box': ^58.0.12 + expo: '*' + react: '*' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + + '@expo/metro@58.0.0': + resolution: {integrity: sha512-PMD640ihB0C3Oqm0AnDVJ/8qF2cKbRUEqGuSOr4tM/OTb9ktxsQqsiSSSeaOEgdCZBq20AxRS0d6WHNhhH2P+g==} + + '@expo/modules-macros-linux-arm64@0.21.0': + resolution: {integrity: sha512-et6K38xG21MBiYGrSfLlh3pD8ZuWkUrg7O1fdQxuLUvmFggb/C1ddo29SHLguJ+5Hjl+6J+ncEgpIWt6pQZjIw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@expo/modules-macros-linux-x64@0.21.0': + resolution: {integrity: sha512-p/vMS+FrWTvk+um3+8fd7/3VBJQxnPu8SjXGu4zs8lYPWaVOfpyjE80ziDW/KEOUyueT/U9DEzxX8JE/uDDdUg==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@expo/modules-macros-win32-arm64@0.21.0': + resolution: {integrity: sha512-u2+LDxUKqKvos5dTnZn37Pbp6gMmdGG566dh9fO8gWrS5qcoxBDuNeeB0ZXwrfmhhiL7JtT4AhH5FO7NP8dsfQ==} + cpu: [arm64] + os: [win32] + + '@expo/modules-macros-win32-x64@0.21.0': + resolution: {integrity: sha512-MPtZ6mYFJBs7aKfs5PZ9HikyXxn9OnxzObRkCM4vedRLwJ6mEPRaZEzWUyi9MS2SUVU7Lt4oQZPNp+gjTVEZkw==} + cpu: [x64] + os: [win32] + + '@expo/osascript@2.8.1': + resolution: {integrity: sha512-SCi+6q6uOkGhiAn6AIP/OPFgaIq/iKD2oYpnAOg2rShHStJ8ey7wyT127RbOaZXmlcY/62rHOX1WiiMnD8u/BA==} + engines: {node: '>=12'} + + '@expo/package-manager@1.14.2': + resolution: {integrity: sha512-sftl0eRVVCarI6grMdjAB3jX2pX1Mt3cdSnajlXS4QyeDkaKRM/ntBy6dcagj1VL0+cEfEqctlyvinmlZdNubg==} + + '@expo/platforms@58.0.1': + resolution: {integrity: sha512-KtLrtAvpShq16l9lTxd2fZSjULxcGxXrJTHA31iUVqrc+Af7aTAJW4ZB3yQBgi/w+kSb6BB/CG9RXI0ohbMm6g==} + + '@expo/plist@0.10.1': + resolution: {integrity: sha512-nuNOqj+r/hGJbZ1Ax3jUpZaOB8UAMHUrISALJEUKaCieTflYj7224EqFWmMpriCGk9wXS1gH+9GGVnSj0tWzuQ==} + + '@expo/prebuild-config@58.0.14': + resolution: {integrity: sha512-2wVzVDfXjRB3LzUbW5shOM/A+6eUUCfR+2bpZiWRBBZBtZP2HA5Zq1YgCio1tDqMGAHf2NQQDhvy/Rz1U6aC3A==} + + '@expo/require-utils@58.0.4': + resolution: {integrity: sha512-DvjS5NCitXYcad2Woe1EMHJKcbhTbE77HX0BgOQGL2LFHE3q2H0n8kCWDPBOCVJ63Drap3c35nwoJwF5TQL7Tw==} + peerDependencies: + typescript: ^5.0.0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@expo/router-server@58.0.15': + resolution: {integrity: sha512-iaPlGBpUpR0cEjZM0ScfHkWK3GCVHSMTb1pXkzhSf0vG7kkBgvtw6itZbYpEOzgoGbZfCO2we//3lhVG6898tw==} + peerDependencies: + '@expo/metro-runtime': ^58.0.14 + expo: '*' + expo-constants: ^58.0.12 + expo-font: ^58.0.9 + expo-router: '*' + expo-server: ^58.0.5 + react: '*' + react-dom: '*' + react-server-dom-webpack: ~19.0.1 || ~19.1.2 || ~19.2.1 || ~19.3.0 + peerDependenciesMeta: + '@expo/metro-runtime': + optional: true + expo-router: + optional: true + react-dom: + optional: true + react-server-dom-webpack: + optional: true + + '@expo/schema-utils@58.0.2': + resolution: {integrity: sha512-w28y8SG+5ZTdDdmH2ZnCQk9wHVwGzI9NqX5V4urJUFEnxbm7I129fJRkb8RIAJmMA1WKU5h3ONmranV473uaXQ==} + + '@expo/sdk-runtime-versions@1.0.1': + resolution: {integrity: sha512-kvisefkhxu8Fm/4M8G6DEqUaigrXfrSOm2lFw7hsk/nq0zchcp6B4wSk8rlheHY8FRi5iHxKtoVMGY/3M6h04A==} + + '@expo/spawn-async@1.8.0': + resolution: {integrity: sha512-eb9xxd/LbuEGSdua4NumCu/McVB9EM+F/JxB9pWgnERw4HQ9XyTNH1KapG6oqLWR8TuRK2LQfzJlmNi94CVobw==} + engines: {node: '>=12'} + + '@expo/sudo-prompt@9.3.2': + resolution: {integrity: sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==} + + '@expo/ui@58.0.21': + resolution: {integrity: sha512-O+8DoGcGKq0/QVkKAndrG26dr4Js5oVgfqhuVP4JpwJVQo/KyEQOBWhXbvmQ+1eG9rxYzRjGPNurYyf4BIbwcA==} + peerDependencies: + '@babel/core': '*' + expo: '*' + react: '*' + react-dom: '*' + react-native: '*' + react-native-worklets: '*' + peerDependenciesMeta: + '@babel/core': + optional: true + react-dom: + optional: true + react-native-worklets: + optional: true + + '@expo/ws-tunnel@2.0.1': + resolution: {integrity: sha512-mljsRffbOHzmSimYQbQu9h9NR3alwCCwEEouRGFL4QRTt8dNvsNtKEPa/5jHmtDLDtsh4xXsWKwzjN9BTpeXHQ==} + peerDependencies: + ws: ^8.0.0 + + '@expo/xcpretty@4.4.7': + resolution: {integrity: sha512-EbxYllZ7/ozONVZd425cm4XnolfW+AmSFT5aP7Jdno6oc3WrYQcHz2CO20z/2rwWwYgztmV2PXvYH+BQ8YFjqg==} + hasBin: true + + '@formatjs/bigdecimal@0.2.7': + resolution: {integrity: sha512-B4+XY/e4u5v261r3a37Kq2ax91gPZSKGyVpx8X5dygAggLlUz+6MeBpmAhaBFGB8WQ4JB1qD+QtKHk9aJkEb9Q==} + + '@formatjs/fast-memoize@3.1.7': + resolution: {integrity: sha512-zXfhLpvA6T7+efdt9JLbBwZ00tT7NsBMDVnDu8rpHeNNv8KfRZAMo2gkG0k9lK/Nzc//3kJ9pImsfuJxk3KhUA==} + + '@formatjs/intl-localematcher@0.9.0': + resolution: {integrity: sha512-Z7TD3ssNry1Av1dVDoq/mzpxGyxqWwU0ClWEo+BB3k0JQTeQvUGmeK9WZGYvlqStS0UqkaKXk3dfjsb6NaHAxw==} + + '@formatjs/intl-pluralrules@6.3.16': + resolution: {integrity: sha512-iOqCpBM2fo7bbbWqno+yN9WioepV01N2q3KawFZhRYADzijpzmIIA6cbFXrriCI1Mt2q5c7mceiKHoQkEFf0/Q==} + + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@isaacs/ttlcache@1.4.1': + resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} + engines: {node: '>=12'} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@1.2.5': + resolution: {integrity: sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 + + '@nolyfill/is-core-module@1.0.39': + resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==} + engines: {node: '>=12.4.0'} + + '@noxcturnal/noxcturnal-darwin-arm64@0.1.7': + resolution: {integrity: sha512-GItIncTnb/jh2/2hoK8nk85KJ3IeT8DeFCsihdcpV0W/dxDdCZjQK9Z5ph+v9klly01arfNKjwKFd6OvK9sKmQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@noxcturnal/noxcturnal-darwin-x64@0.1.7': + resolution: {integrity: sha512-IM2xQUneeV9p7BHOl49aQ315yBui/MlHDvYvweitB7PF6wtFzzw3LA4pL1fUUsO2E304FcEEo3W0Sqpy/qPLNg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@noxcturnal/noxcturnal-linux-arm64-gnu@0.1.7': + resolution: {integrity: sha512-t1fyVUo9tgzKbYQE80uUp+RrhooCkyptAm3U31NggQN7EgGQbRWogx5mDwVSG+ju3ZQQ2q9aW0bxp2PK5T6yCg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@noxcturnal/noxcturnal-linux-arm64-musl@0.1.7': + resolution: {integrity: sha512-fB2pT5qWylqsuertNAEL8zMmJ5i147ueH0n114lvezW0oYQwvznQVBAqatuUgT19JEmOK4widxfrqu/t5Nx9eA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@noxcturnal/noxcturnal-linux-x64-gnu@0.1.7': + resolution: {integrity: sha512-zrh+tt1joOXInYjinh4Ff51MJgUZsXi6vJe8Ew+y1pg//YoZbzBgmMz5W8Cf5p8VxcvPCHBbUKqVroA5FftGkg==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@noxcturnal/noxcturnal-linux-x64-musl@0.1.7': + resolution: {integrity: sha512-qGMlKBm9dG5PcuPqaBkixZkna9+y3A7qV296yYg178OPJWLnRBLksHN67wNzwPlKOtBS5b8nukrgWoJn3RXHzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@noxcturnal/noxcturnal-win32-arm64-msvc@0.1.7': + resolution: {integrity: sha512-R1FxKdMK56mk53mqm7psSk6lWuigQLysaoZopi9CMLwitUn5MIYFuBCjdPG+DjiWNTFbRrB/nrC3eO90ozVqBQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@noxcturnal/noxcturnal-win32-x64-msvc@0.1.7': + resolution: {integrity: sha512-g8ChcEDkQgi7pYFRL0IKG+suPVdHxbpz33PAuBJAptVy85nNrjtvfnX7KjH3SLFcr1vdcrm5wFjsUfOogYRkPQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@oxc-project/types@0.154.0': + resolution: {integrity: sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==} + + '@radix-ui/primitive@1.2.0': + resolution: {integrity: sha512-KABY+VMIRPJL+Vyzv/335FEhXXD/xDv8BMb1kl48/aXJZMH0LtHCTx5ga5RnxaEP3nZHtmTLf1P9vanmFX46bw==} + + '@radix-ui/react-collection@1.2.0': + resolution: {integrity: sha512-+yiQzqcc7Sy7/5s0jrMCjpPRFB3538VNrXPWdTLZhE/SCfgEws4aI6lHWN/vvcnyhHndROWBzqmqB4QBrITZ9Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.5': + resolution: {integrity: sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context@1.3.0': + resolution: {integrity: sha512-v5AYEocMISkbJ+1fTXzZpiFv7NRr3D2WiYbLIKf+FkmJ8VkP6d503eV2n34MFussHXY1pcoq3yfJiQH77dc4Mg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-direction@1.2.0': + resolution: {integrity: sha512-FtRA52a/r+LKStFT+neLUm+8vSe7wbzkbQGGeU8ixFiwC8NU14Evoq9ATECqL3eGbcUzJR4fyfA4KkK/q6dfqg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-id@1.1.4': + resolution: {integrity: sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-presence@1.1.11': + resolution: {integrity: sha512-Z7/atlkab36Z8hm+V8zYc79r0W+tiOB1o0tun1By94JyadkekLQmtEAnBSP9XKXBNQsStoStS4+gX10JpS5akA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.2.0': + resolution: {integrity: sha512-HCTSPMNqv55Qk0IX4geJbpyXazmqulcimwuyjxTkKi29v+QZbG2Zho9BnbBq4YS2PF+KlNb2CXoLz66uUmblkg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.2.1': + resolution: {integrity: sha512-UwraORzVUeEPMclhO1p0vz0qI+TbdDLO9i+FiOqhJyHKwdpCRCck9yVEscUnAMIzCiuNoQa8D4A9bIpOPXGt6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.5.0': + resolution: {integrity: sha512-tyYd9ddPXAysAbdbD9eYxgwpCSv6f3PncqVSNKQFSR5lcJVLz3cb/pANDoYrLiHBpXv7skortyUgGUWsYuPPFQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-tabs@1.2.1': + resolution: {integrity: sha512-hRoJlode+hg5ZNlR+3tkfkUliIybdTpD5lkAvHQ9yaXseGf7XVO9Ib2GPEIOuaJJbo7YWYbNpDDRfo8Dhf6/xA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.5': + resolution: {integrity: sha512-Y5GBf4NKeADoXI1geiMlMuMoURT3k9MizzzKhGb/m55H94aGigZ01PIpkvsO6lML13BA6XYAXSJ6gza7vTn5nw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.3.0': + resolution: {integrity: sha512-TAcBI7bw2ljYCbv4+zuTSd6zICu8pRt6SDN2vJ/Z06K2MXh6I9WYFe/A9ovlFDtR5HVHGm5iDxDoABm/++dbKg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.5': + resolution: {integrity: sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-is-hydrated@0.1.3': + resolution: {integrity: sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.4': + resolution: {integrity: sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@react-native-masked-view/masked-view@0.3.2': + resolution: {integrity: sha512-XwuQoW7/GEgWRMovOQtX3A4PrXhyaZm0lVUiY8qJDvdngjLms9Cpdck6SmGAUNqQwcj2EadHC1HwL0bEyoa/SQ==} + peerDependencies: + react: '>=16' + react-native: '>=0.57' + + '@react-native/asset-utils@0.88.0': + resolution: {integrity: sha512-Bj1DxQt5f4OrjdlgSVkZT37Z3hx5hUIN5AUDSqL/e99vgtTcqj5vnm067epZL1EF/QiqsniZO8Q1GSkItOakDg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/babel-plugin-codegen@0.88.0': + resolution: {integrity: sha512-leGEnCcS7Q0hTxvzvhNtr8zGQpI1gfWqXjzC4UedsFmNMv6kIo4s70o0XbtM30ZXbpfWe4BcSC8NKWuak5sI4A==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/babel-preset@0.88.0': + resolution: {integrity: sha512-iMfAHhFGNegnReSY6CYaWHncvyDwHq8olRs0zp9nRRApMAoCiLyfo1dwL/f39qt/MreD6xIqUs9SrTPYWobY6g==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@babel/core': '*' + + '@react-native/codegen@0.88.0': + resolution: {integrity: sha512-SAGg+XfzsrPiYTscbKa9bo2/H2ei2TjyxW8RTMq2Ps661kRK3AnmpMGVfrEFshEMr3FGEbuQIvj86X98kaXlRA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@babel/core': '*' + + '@react-native/community-cli-plugin@0.88.0': + resolution: {integrity: sha512-WrQdXbjVt1gwAay8ZzYtpOi9ly99ksJ0VMYFdVcMe6nq3vtiRgqKRpHgCdN6ySIbtr5o+aJ+Vr7OTDY98ec/Ow==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@react-native-community/cli': '*' + '@react-native/metro-config': 0.88.0 + peerDependenciesMeta: + '@react-native-community/cli': + optional: true + '@react-native/metro-config': + optional: true + + '@react-native/debugger-frontend@0.88.0': + resolution: {integrity: sha512-v5cnBaaWhDRPcQv8EC20zj53jOAKH7u2wnzzXS4JTNu+diPC+cA2+kC7rq3eKI5vGhlAcG2kDPoViRuC0AY0oA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/debugger-shell@0.88.0': + resolution: {integrity: sha512-p82zT8ZKNx7nIm/8zf8pi55sxm5KQBm8td47kzoJysTdqHLyPsRMUvDXtvCJIWadHSv7RJ6t/yiCc+IoImLBtw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/dev-middleware@0.88.0': + resolution: {integrity: sha512-sHLxVHOwfkF672ZzMepNh4d3IKbrZy3qXDKWSwN5LC5VJkzzZ5FdmSPP4N/CCn2pcKJ4oSqvojXwN4De3Xk92A==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/gradle-plugin@0.88.0': + resolution: {integrity: sha512-4jPSKslOfJj8NKY/jv9qmWkxZYmqPyamoS3Vs0JOFxw9t4PM6L/ea0fUsjNV0LxC9zJlvWilPJOCTOf7h8wlyw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/js-polyfills@0.88.0': + resolution: {integrity: sha512-Iq6v4+EWdOLv0M1+BpADQJBVfInl6FkABXCIBSi0FbvHahEYT+Y4UJ7Cm96p18gbEN1VKzqz3nbBbwLA6bx0rQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/metro-babel-transformer@0.88.0': + resolution: {integrity: sha512-xsUfzXrqKXeD7sBja7hkyBG32AGIwWJ3IEZ+UcNMRTR/sucnXXZ6Do40qXoeY52YC8b9//J+p51JIp2CC0DZKA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@babel/core': '*' + + '@react-native/metro-config@0.88.0': + resolution: {integrity: sha512-iPV2HNXlPs7xQDBJJGIjkH0x2psZwJeRIEpfSqxgqLaO5eEfE2Ccicfz2OBHBcIC5jKGGa4IoI/e26zMNDuTMQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + '@react-native/normalize-colors@0.74.89': + resolution: {integrity: sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg==} + + '@react-native/normalize-colors@0.88.0': + resolution: {integrity: sha512-eZCu3tGAQCfvMCPQJVY4dmoMX8ZZYBvqIGHX7lwOYyzNK+Dl8e5ky7ZoXub1Rq75oSrQXNNmSP2CDjNNXXZpFQ==} + + '@react-native/virtualized-lists@0.88.0': + resolution: {integrity: sha512-zpZIOAbobdS93edwHkNUdGDzvElNeQJqukRERRPns3/ucPvuMd2G4fYpmVJSVjhxtGCcLLB1PFndLYYfwaYoBQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + peerDependencies: + '@types/react': ^19.2.0 + react: '*' + react-native: 0.88.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@sinclair/typebox@0.27.12': + resolution: {integrity: sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==} + + '@tanstack/query-core@4.44.0': + resolution: {integrity: sha512-swSgb7OiPRR3UuIL7NuDrZNSMGmQD+wdtHxPD7j60SvBEnxbXurl5XOirtGEX2gm2hbK6mC8kMV1I+uO3l0UOw==} + + '@tanstack/react-query@4.44.0': + resolution: {integrity: sha512-RuIqHYrS98LrK/8kJJOJMMSQ/BCpojwsXDh7p0fBmp38ZOz6dlk+uyFRRusH+V+t3POoCsDOQ2zhomEYOeReXw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + + '@trpc/client@10.45.4': + resolution: {integrity: sha512-ItpH5FMIJFt862kbAgC8hf5NJnDLo0FwEvMEX6zSLCenzWD0UH6H/fvAX1suFo1e0wcAmMhiEU1Tl6xKk/Pd1g==} + peerDependencies: + '@trpc/server': 10.45.4 + + '@trpc/react-query@10.45.4': + resolution: {integrity: sha512-/JfbkFMztsYbpl94P9TWritMjbHqWxeHz4uwjHM3W2zUcIKT88FiFXVmD/jLitPLrKhi4yAONoaRks5SUm12fQ==} + peerDependencies: + '@tanstack/react-query': ^4.18.0 + '@trpc/client': 10.45.4 + '@trpc/server': 10.45.4 + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@trpc/server@10.45.4': + resolution: {integrity: sha512-5MuyK5sDuFVGHOT9EMVHgRjP5I5j3RqGymcb5D47UOp8tzn6LH0g1lEgYrAsOZ12vmk1gpxMw/v/y4xHHK/Qdg==} + + '@tybys/wasm-util@0.10.4': + resolution: {integrity: sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==} + + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/node@26.6.5': + resolution: {integrity: sha512-uMzsv9stDdofIZBx4UGh4Z9ZgXnGC9seRDscilBcTHAeOFk67MZg/k9bWVfO+bk4qZmG+l52hRnLwUiH2LnJTg==} + + '@types/react-test-renderer@19.3.0': + resolution: {integrity: sha512-TX4p2D4Z2oigM3SXU7+QyLSUnSR0vR1S1Pfxm/qFL9nHQ3jclgi6ioGoWQmlIr1DeKRVmPJrmNlhgM0JlWlLUg==} + + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@typescript-eslint/eslint-plugin@8.72.0': + resolution: {integrity: sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.72.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/parser@8.72.0': + resolution: {integrity: sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/project-service@8.72.0': + resolution: {integrity: sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/scope-manager@8.72.0': + resolution: {integrity: sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.72.0': + resolution: {integrity: sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/type-utils@8.72.0': + resolution: {integrity: sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/types@8.72.0': + resolution: {integrity: sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.72.0': + resolution: {integrity: sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/utils@8.72.0': + resolution: {integrity: sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + + '@typescript-eslint/visitor-keys@8.72.0': + resolution: {integrity: sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@ungap/structured-clone@1.4.0': + resolution: {integrity: sha512-1mEZtMKPM09vDmQt5y7YvmN2+DFTP7Tg0EWXdic8/C6VRnpb33e4ghisCIE3WZjsE2N8mf+QV1Zqh7ZFYLWInQ==} + + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.12.2': + resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.12.2': + resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.12.2': + resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} + cpu: [arm64] + os: [openharmony] + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} + cpu: [x64] + os: [win32] + + '@xmldom/xmldom@0.8.15': + resolution: {integrity: sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==} + engines: {node: '>=10.0.0'} + + '@xmldom/xmldom@0.9.12': + resolution: {integrity: sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==} + engines: {node: '>=14.6'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.19.0: + resolution: {integrity: sha512-oJlA3XiRm7Cyk6qFD2Jn8ak9B7jSy0qy00ADO3+8dpT0LSjFihQYv4C02LFCSYJV3Q37xYwwRy5m+IpIiUzqWw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + agent-cli-detector@0.1.7: + resolution: {integrity: sha512-d8OWDVdZMgjhLUT9ZPgSv/BdFFF9pVuscC0JdUSz3bjwE15gcp6u/o0/JooM2yyAWC49KThFhXlgTXRa9B7yng==} + engines: {node: '>=18.18'} + hasBin: true + + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + + anser@1.4.10: + resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-includes@3.2.0: + resolution: {integrity: sha512-VXY5eFRarnXcYxwBjJzPmEhH55+rmP79/+ueDhi0F+TuqfHCItagIHqxeUZrmgrOPa31QTh9H85DjX3FfJ0FTg==} + engines: {node: '>= 0.4'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.6: + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + babel-plugin-polyfill-corejs2@0.4.17: + resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.8: + resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-react-compiler@1.0.0: + resolution: {integrity: sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw==} + + babel-plugin-react-native-web@0.21.4: + resolution: {integrity: sha512-FSclsDTGi5EcvpbW3TM7s8GLWwQqo5wI9zQqJr2m0IoJRenSkp1+bVvdeZXTNznI5Ms9Bry7DLBR+C5Shb9gtw==} + + babel-plugin-syntax-hermes-parser@0.36.1: + resolution: {integrity: sha512-ycduwJbvdvIMmVvlAZqGggS+pm5Eu4Bk9pcV9Sm2Z4PJNRVsKkv0g7vHj+LeuC1gHTeF67sJXFOq61IlqCa2hA==} + + babel-plugin-transform-flow-enums@0.0.2: + resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} + + babel-preset-expo@58.0.18: + resolution: {integrity: sha512-H1mMGvDPiFHsQgOfZ083mhzy/Q1za1VAK9WiLsHrPvUElaXJ0oLyeacMCaboiqEgC8WrZeVFGBNKaHoV98wyiA==} + peerDependencies: + '@babel/runtime': ^7.20.0 + expo: '*' + expo-widgets: ^58.0.21 + react-refresh: '>=0.14.0 <1.0.0' + peerDependenciesMeta: + '@babel/runtime': + optional: true + expo: + optional: true + expo-widgets: + optional: true + + badgin@1.2.3: + resolution: {integrity: sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.11.30: + resolution: {integrity: sha512-YJs6Pz17RMNv8HoyKREtCY38E3BV1nPkWVmIb+XN1uHC1Vqt3KZCH/uJH9ZKRoiKb/icZ6tvehyee6RZNbFfRA==} + engines: {node: '>=6.0.0'} + hasBin: true + + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + bplist-creator@0.1.0: + resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} + + bplist-parser@0.3.1: + resolution: {integrity: sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==} + engines: {node: '>= 5.10.0'} + + bplist-parser@0.3.2: + resolution: {integrity: sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==} + engines: {node: '>= 5.10.0'} + + brace-expansion@1.1.21: + resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} + + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.29.4: + resolution: {integrity: sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.2: + resolution: {integrity: sha512-V2o8YS2EhrKMO9AumnkK0ynynfFlsajpYupwq7S46H5mhcanwxDkNTw3K67wPIcKTH1ffkA4vhMOtAc7gRmPZw==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001817: + resolution: {integrity: sha512-uZ1JG80BwhtMalIAGPxPfmNhHyd/B/nTdr3hITWlRamSyAdUStP1Gop01e7SD5q6J90ixJvWDbvmiFVfDgn4bw==} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cli-cursor@2.1.0: + resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} + engines: {node: '>=4'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.2: + resolution: {integrity: sha512-o8vI5RE5A6EVVOd9o41jKp41aJom+QTEO/Bx8MYNjexMo/Bv2WOjUfZr+aL0WnYSgymUy6zeguqLTsIhV0gMvQ==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + + content-type@2.1.0: + resolution: {integrity: sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==} + engines: {node: '>=18'} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + copy-anything@4.1.5: + resolution: {integrity: sha512-vePst2VLTSqPglW7Q98VwFpGiGpOHTyXIo81MO5VyLecA5zMbZw/P/V1vmwD1jksa2iJpn/YkDrJ3XhTfzUyhQ==} + engines: {node: '>=18'} + + core-js-compat@3.51.0: + resolution: {integrity: sha512-52r6fkXgxv4GLMjmFcMWRx7X9bw071xTTdrDcdyPGRqU2oE+9pCG0bAOMifSBdLw0JRBZKEF0q3B55qPlLuE8g==} + engines: {node: '>=6.4.0'} + + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-in-js-utils@3.1.0: + resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + date-fns@3.6.0: + resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dnssd-advertise@1.1.6: + resolution: {integrity: sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg==} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.462: + resolution: {integrity: sha512-9qpCBlXPy5v7n1Q7WTO5rW2StI4WNQhl96HpgXRZLPlNoXAD0LbsQUflovQYAO44Yia073ISusqohncvGSMbGA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + + es-abstract-get@1.0.0: + resolution: {integrity: sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==} + engines: {node: '>= 0.4'} + + es-abstract@1.24.2: + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.4.0: + resolution: {integrity: sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.4: + resolution: {integrity: sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-expo@58.0.4: + resolution: {integrity: sha512-IcgZtJVN7bJdMMPeEw8PtrbFie96+vqSZPzw/dhhRF+cKc1LaPksIhO3aA6boiMIFZuCrQyOl6lPaqI1579wqw==} + peerDependencies: + eslint: '>=8.10' + + eslint-import-resolver-node@0.3.10: + resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} + + eslint-import-resolver-typescript@3.10.1: + resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + eslint-plugin-import-x: '*' + peerDependenciesMeta: + eslint-plugin-import: + optional: true + eslint-plugin-import-x: + optional: true + + eslint-module-utils@2.14.0: + resolution: {integrity: sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-expo@1.2.1: + resolution: {integrity: sha512-6eIogfGM7tIq169MbqJTA0iaI9h/VGujSUAy85hA3OHvYecEYM8XE9fMLd7ywnQClnVkT3JgbW8NWyhEP8g5yw==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + peerDependencies: + eslint: '>=8.10' + + eslint-plugin-import@2.32.0: + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-react-hooks@7.1.1: + resolution: {integrity: sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0 + + eslint-plugin-react@7.37.5: + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.5: + resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + expo-apple-authentication@58.0.2: + resolution: {integrity: sha512-79hDIHImAxumuAuZYADfiJyY/k7jTNKHNkwf63KqH/ii7/N0FmSjjt/MJR4K1IaG/TR1RTXaFpsMQwHP/LEnrA==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-application@58.1.2: + resolution: {integrity: sha512-WYFdNHGaxe/j69oYREhK0cKsKYszuIuz399WXYCP+M1grfO+FCWB/RbuMgaXJsLWlzqhNjA/zLgfJ+33FwrQvw==} + peerDependencies: + expo: '*' + + expo-asset@58.0.17: + resolution: {integrity: sha512-CDYXjwNoTQh4s00pR99mkbwh6A5/eUDMqKXPoLnuTW6kYKzuQEVxLpOPTj5zg0uYpCA6KAHI294li0roYGMqHQ==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-constants@58.0.12: + resolution: {integrity: sha512-d3/dsps32nU4m6YJQbXQ1dIfn58GxfmJjTnZ0WtnhdSHTdG/oVsOakLqYRlX/FaLUKkQOSHXMf7hyCx+2a/HSQ==} + peerDependencies: + expo: '*' + react-native: '*' + + expo-crypto@58.0.7: + resolution: {integrity: sha512-g+4i4UpqQ5jNy1VPRvVVvr9aIdh8WwvxbpwL2ntiSESDRsXyVSeb8JM6tHVdC3b9J2nGxjtrhrsaWOo0jbSxlA==} + peerDependencies: + expo: '*' + + expo-device@58.0.5: + resolution: {integrity: sha512-GNyaHPwoiI/z2SGR14R6d9J7hFSW2JabZieJtC3l6/LO2mJYVCbhEsQ7/1ljGBeTUnFFWHcFLccdaWEhOWtaQQ==} + peerDependencies: + expo: '*' + + expo-file-system@58.0.10: + resolution: {integrity: sha512-n0M7amp/Bv9TAqVfTWq1zGykmQJWiPzDePZIKp8YYKkVvY7N65bo96sMBQlHkhAyW4I1B6MZABnybliy5DXQig==} + peerDependencies: + expo: '*' + react-native: '*' + + expo-font@58.0.9: + resolution: {integrity: sha512-C8sIeVA2NBb76xqqnQ6eVzfXezAfKJC4qVGU9ukKM4KXdLtkhH5bRCvRSc6qUFUmrcNoM3RjI78SEH3lhigRSg==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-glass-effect@58.0.4: + resolution: {integrity: sha512-PrxU1FINOpqpnjtZMXHAC/APLq3T3fDforMqQ+JRqRtIrlQ8wntrX8IztLxJBKD9s8cJJ8V9MAoI89aYRK8j9Q==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-haptics@58.0.7: + resolution: {integrity: sha512-mAY3rbng6EuYysq9wnJKhKwYYlDjqnPYcS5OXe3zj4TlAaOFMl/EfiSOuAMawc2nsXCAnwJ5U0E11nq5zQO0mg==} + peerDependencies: + expo: '*' + + expo-image-loader@58.0.3: + resolution: {integrity: sha512-zlHudxC8OObyqCHmvdxJqURI7886KJ0cUJyn7R/a8FOD9fP837xKDN+u4SIt7XsSSVPNXzMd4Y7mN0pmup8NGA==} + peerDependencies: + expo: '*' + + expo-image-picker@58.0.10: + resolution: {integrity: sha512-yqQC9UYMWSUxk6U0jaS1vE1w+b9Ru0FJmQ3KjUf9Q9oVg5xBxmg8+Ts+usazMAuPoskNIXJ++VZ+uK6br9yUGQ==} + peerDependencies: + expo: '*' + + expo-image@58.0.16: + resolution: {integrity: sha512-NrpsQGDtuMpXFuD6jQfTwzpWvJztfj9xELXfTaV3tHovEf4pIX2/gU91pnCP2F2IUMpGJCxyDyEqceJ0Bd+eCQ==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + react-native-web: '*' + peerDependenciesMeta: + react-native-web: + optional: true + + expo-keep-awake@58.0.3: + resolution: {integrity: sha512-wLRF+XeVsD/Rt/ZyX+A0mk1brdf8vefWizNAPzqV5eOCgkj23LCRZdN8gUi5X8UwyR8UJ7Y7Dzdz4YDGB/4c9Q==} + peerDependencies: + expo: '*' + react: '*' + + expo-linking@58.0.13: + resolution: {integrity: sha512-kQEyBGaKY3d9T4DXYzbkZBo1shJP4MupeboNW2TyM9mFR9hVtmcwUXijgAYaYEFkR+1yl7SJWS9Lq9dQ4rUd7Q==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-localization@58.0.5: + resolution: {integrity: sha512-2wyZl/5wn95l38AAtdaUAq2VMJWbGbgQQDEuIEkkemmsA/BZ8gS21Nq+7I2X9hDfL5Z+4hlyLVdPtDIH0vvt1A==} + peerDependencies: + expo: '*' + react: '*' + + expo-modules-autolinking@58.0.13: + resolution: {integrity: sha512-uzLFoTnAKabUdITvzRqWTvFkZsOdRPEXj7AEMAuBEhA2kGhqaBDa2EOWqPXVay0QJVoZuIQaEEgPGAXN1dPuYg==} + hasBin: true + + expo-modules-cli@0.3.1: + resolution: {integrity: sha512-dRLz4GMRi6lETbE729xFVforu9VI2hQ+YLMtVXfukHMjm6KposDOlJGCdYoZpB6oLVMK/NShc1q9v/u4yr1dkA==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + hasBin: true + + expo-modules-core@58.0.23: + resolution: {integrity: sha512-jsINDwUJ1ddCGMTQAROPnBHIvCyLFZNJcGT/3iFP5LcP+01edie2ZBx44NEYIPmQLb3Vnz8sC3rKouwo7vj2gQ==} + peerDependencies: + react: '*' + react-native: '*' + react-native-worklets: '>=0.13.0' + peerDependenciesMeta: + react-native-worklets: + optional: true + + expo-modules-jsi@58.0.16: + resolution: {integrity: sha512-+UwXQVGBJDmwCe2MgkeVLdMIXmUjCcmMakRrtlAmA5I7WwAt5QYcbVi3u7Cae9X12xKet9IpXzzJRPz5zM32LA==} + peerDependencies: + react-native: '*' + + expo-modules-macros@0.21.0: + resolution: {integrity: sha512-dCzN+IH3ss9audf0tvDPgwEuQJZ0WvlC60SfUDFhms8Gal1cXkYpyU7epTH2lj+ipGqghrXXjp+fmyo5wDX+YQ==} + + expo-notifications@58.1.5: + resolution: {integrity: sha512-5bf3l+nP/yIadq6v1f3pyOmEk0WRsEaSEcfJdpCXzOyaMwg5YtqR48sMPU0Wg7KESwOtLVtetSH6y3XkGzSiVw==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-router@58.0.24: + resolution: {integrity: sha512-k6Bb673jDAyq34W8V/XUiEmOR9jMRXIYIuBYjPDchi6tsp7MOCcD8qfjj5WMtHuKp3cGe89E3X35SJBaO3yLLw==} + peerDependencies: + '@expo/log-box': ^58.0.12 + '@expo/metro-runtime': ^58.0.14 + '@expo/ui': ^58.0.21 + '@testing-library/react-native': '>= 14.0.0' + expo: '*' + expo-constants: ^58.0.12 + expo-linking: ^58.0.13 + expo-symbols: ^58.0.4 + react: '*' + react-dom: '*' + react-native: '*' + react-native-gesture-handler: '*' + react-native-reanimated: '*' + react-native-safe-area-context: '>= 5.4.0' + react-native-screens: ^4.30.0 || ^5.0.0-alpha.3 + react-native-web: '*' + react-native-worklets: '*' + react-server-dom-webpack: ~19.0.4 || ~19.1.5 || ~19.2.4 || ~19.3.0 + peerDependenciesMeta: + '@expo/ui': + optional: true + '@testing-library/react-native': + optional: true + expo-symbols: + optional: true + react-dom: + optional: true + react-native-gesture-handler: + optional: true + react-native-reanimated: + optional: true + react-native-web: + optional: true + react-native-worklets: + optional: true + react-server-dom-webpack: + optional: true + + expo-secure-store@58.0.2: + resolution: {integrity: sha512-VupWWEuQF6IiQ06McSymtn7/tehs8ifThhFwAU4UK8poomZcaa2S0UVt/y7G2XozBdkI3xpiPSx+r0pS2zsuYQ==} + peerDependencies: + expo: '*' + + expo-server@58.0.5: + resolution: {integrity: sha512-FHYecxfGOuAhacHcanR6qCN8Cln9S+FFulcYetLu3ddDg55ohuCsMZ9U4Egzwdm+A2o6N+MdSoJKquBC5F9NIg==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + + expo-sharing@58.0.19: + resolution: {integrity: sha512-FzTUT7uquCBbWVwjYm1fogpO3UNBoj+XRCNrCv7GzRNy9f0KPzLZTnaqJw28nEvaesYg/Q9nAiwSwkH1Df/Bdg==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-splash-screen@58.0.10: + resolution: {integrity: sha512-rjzCLKo7SHSOkaFnVnh+bYWK/pO/vC05qvJe++AjaQidTSGLxD2buj7zWFLlbEEpkqP+wZYQHRyx2mvHyZrUQw==} + peerDependencies: + expo: '*' + + expo-status-bar@58.0.3: + resolution: {integrity: sha512-+GMLHLA81LB+/m2DteQAN7kvH8unVj3zYGSj8D6Csf+mCrc4P6jJwaSbrz17qTizzEIJ5lv6SuU9Zfyy2vSNoQ==} + peerDependencies: + expo: '*' + react: '*' + react-native: '*' + + expo-symbols@58.0.4: + resolution: {integrity: sha512-cZeIh4bf4uUI5GhI0BK88dV1BCoWlgp1fmbPuUY/bZnonmyGS881Yvy8MkbM+R+ozo7W9TdZFpbFRWjUA+spcA==} + peerDependencies: + expo: '*' + expo-font: '*' + react: '*' + react-native: '*' + + expo-system-ui@58.0.6: + resolution: {integrity: sha512-K1+GIYhNDc4J0lJAL0m8giesP1dgfavhN+joA6FQ45r1FXAWwS1PaueCiCJaq5hB6z5iAYT7b9XqYp76UU65yw==} + peerDependencies: + expo: '*' + react-native: '*' + react-native-web: '*' + peerDependenciesMeta: + react-native-web: + optional: true + + expo-web-browser@58.0.6: + resolution: {integrity: sha512-6/QtDqTOaTqM/ysYYdEZG4XDrWloOo1wVYCn4g3IgayF+1lZWTwMqa5j4kcn2TA1UBer8O7zbMQYLfSMppQ/zg==} + peerDependencies: + expo: '*' + react-native: '*' + + expo@58.0.16: + resolution: {integrity: sha512-LnWYyk8tYuXkNh4BSEnRhXXDtfPPJBWXOeyVtlnmRskWEyC641eqH3pDvXuX8NF2a6eg0E+rjRbZ94yO3DeM0g==} + engines: {node: ^22.13.0 || ^24.3.0 || ^26.0.0 || >=27.0.0} + hasBin: true + peerDependencies: + '@expo/dom-webview': '*' + '@expo/metro-runtime': '*' + react: '*' + react-dom: '*' + react-native: '*' + react-native-web: '*' + react-native-webview: '*' + peerDependenciesMeta: + '@expo/dom-webview': + optional: true + '@expo/metro-runtime': + optional: true + react-dom: + optional: true + react-native-web: + optional: true + react-native-webview: + optional: true + + exponential-backoff@3.1.3: + resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fb-dotslash@0.5.8: + resolution: {integrity: sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA==} + engines: {node: '>=20'} + hasBin: true + + fb-watchman@2.0.4: + resolution: {integrity: sha512-tGQtaoYisPDriJBN0mT5yZSyNETnJGA1gTYxaVRAE5KUO3LI9kPUc9WIu8JXcxaIci+faIKlzXqXyPgrmubtBQ==} + + fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + + fbjs@3.0.5: + resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetch-nodeshim@0.4.10: + resolution: {integrity: sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} + + flow-enums-runtime@0.0.6: + resolution: {integrity: sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==} + + flow-estree@0.327.0: + resolution: {integrity: sha512-f9vK751YUzD0qaHSpKc5/qQM6gqOlgGS+4ZRqTNcZOpVqn3mC55yEQ6dUG2K1eaVm5FbKkz9CFWe6XNvrkQFQg==} + engines: {node: '>=18'} + + flow-estree@0.331.0: + resolution: {integrity: sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w==} + engines: {node: '>=18'} + + flow-parser@0.327.0: + resolution: {integrity: sha512-/MYZ5hXWf5ozpbdfUDmazMgQXviLxWEiRLH3MppEGDdW0itRVqmB5UaU7QX+SBCDNiq+gEesSVn8nlxmPDyDkw==} + engines: {node: '>=0.4.0'} + + flow-parser@0.331.0: + resolution: {integrity: sha512-vEZcHIlnKeN8JSVtYFczj8sWJfHIJOkz+YG00O/oul/Bete+t1ZhTi+O6JRRLFYvGW+yJkZ0YgL16iStnbkUqQ==} + engines: {node: '>=0.4.0'} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.2.0: + resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.14.3: + resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==} + + getenv@2.0.0: + resolution: {integrity: sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==} + engines: {node: '>=6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + + hermes-compiler@260318099.0.4: + resolution: {integrity: sha512-8odcPFkPC82HlqCl0C5QI9mBN4rEAT+IAo55sJhzwKw//K3qZloiv3ex6J2O8CuBbhdmkJozfidNsset2KH25w==} + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-estree@0.36.1: + resolution: {integrity: sha512-guv1nQ6IJ7S83NRFPWc3SA7IBZrdNC9kapwOq6uXvF4wP+sDCgjzQbKPCoyYmoyZRzztF/n/c36l/rccCZSiCw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + hermes-parser@0.36.1: + resolution: {integrity: sha512-GApNk4zLHi2UWoWZZkx7LNCOSzLSc5lB55pZ/PhK7ycFeg7u5LcF88p/WbpIi1XUDtE0MpHE3uRR3u3KB7TjSQ==} + + hosted-git-info@7.0.2: + resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} + engines: {node: ^16.14.0 || >=18.0.0} + + html-parse-stringify@4.0.1: + resolution: {integrity: sha512-0zHsZJrK7S3K2aucXWL6ycoYJ/iNtIcFHC/nYQgFklPtrv5LpJctIiSCroWZWeuoXvuyFdzp6KzjJQ+OT5MfFw==} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + hyphenate-style-name@1.1.0: + resolution: {integrity: sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==} + + i18next@26.5.3: + resolution: {integrity: sha512-6pRwOwJ6lBCBB66fqNZaSoUmvsALHMord7FL6GsDhubT1CrPabTMEJIqddm0nn2YEbKofdI/3VAtGrQPuztY1Q==} + peerDependencies: + typescript: ^5 || ^6 || ^7 + peerDependenciesMeta: + typescript: + optional: true + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.13: + resolution: {integrity: sha512-2E8Q6rh+1RRSq/YdaGsNfXsEZy9FVqv6BSSrkmZJP7BnaoPnRfKL+YaofPvP+5rzdk144qSm6i4+hvPgUcbV4Q==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + inline-style-prefixer@7.0.1: + resolution: {integrity: sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.17.0: + resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-document.all@1.0.0: + resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jimp-compact@0.16.1: + resolution: {integrity: sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} + hasBin: true + + jsc-safe-url@0.2.4: + resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + lan-network@0.2.1: + resolution: {integrity: sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A==} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + + log-symbols@2.2.0: + resolution: {integrity: sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==} + engines: {node: '>=4'} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.5.3: + resolution: {integrity: sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + memoize-one@5.2.1: + resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} + + memoize-one@6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + metro-babel-transformer@0.87.1: + resolution: {integrity: sha512-orvRIGpb0yK1yMbk5YP3dhVKjmoxUkRB9fdltGJxNppEqus/1tFpNuf9KnGFR3Qjg0izoUrJ4z6WgoBvdkXPrA==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-cache-key@0.87.1: + resolution: {integrity: sha512-scqVVPMA2c+RVO12I3wyMDp5xCkRPLsyrcG4Qc3xfU5JR0EW/0sz2tjty+5UjMUtG09uiM1KYQ8HjWg7OQXHtw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-cache@0.87.1: + resolution: {integrity: sha512-juNPaj0Xi5tkLp8imXqvbSnEIijwKG36m7OiFFVJMqEkiURwAjkMFVek3/xpix1+LVQqO7kjVp3PvuvIM61mKQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-config@0.87.1: + resolution: {integrity: sha512-NmkDlc/qZAdo5gTkVTuO2AKE/khemRKRH5IA+SKfqUBJigI5GqZ5TOXhmEokhlkAqzjt8dyzKhzI6FHvXoXaTQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-core@0.87.1: + resolution: {integrity: sha512-xizzky/4+c/Mkznege8OW05j7bSdM39VPoEps61Se4+hf32UQujmbvLvIE9+UnP6kNEPVomk0Fw8NsBK9iRQmw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-file-map@0.87.1: + resolution: {integrity: sha512-9sPuNCojC3pS4vj+ZPY7FXmHGpdJeckXuKXQrDAfJvZc60AF8owRFTkI8XdwlwrmPIB2w++KraK9FMEXvC4wJw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-minify-terser@0.87.1: + resolution: {integrity: sha512-YK4k1oO1wV48hfE+Nbw2rJCnAgeabzrgT/xH5ha5n9gbK4p3HYFC898cERUiyTl9vRh58CNTiXRc88f7y6PfKg==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-resolver@0.87.1: + resolution: {integrity: sha512-FXH/brY69wT6sPxaSW8BhMmDGD/6irmBr/cL4rUi+VWwqR3pbvdcfUOfyjcHucgQ7pe5IW3xJY21eHKLVKNumQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-runtime@0.87.1: + resolution: {integrity: sha512-kjeuSvInsM6OzBjkCQsWxnkrKZFMKtnkCl38oXWRI9lDGs2L9hGs9Tak9sQYJ9h3gtDujneB7wZio+irgqJKDw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-source-map@0.87.1: + resolution: {integrity: sha512-Bqpm0PBGdy53pigIJb4HRF7QxD2pUOdgSmVh/4AWbP635kSCv+Y6ltVxUZgSnzS/QbSmzyCGijmRPlXMj2/qHw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-symbolicate@0.87.1: + resolution: {integrity: sha512-rcGvwabrg0lbXGRGRKl14PY3My3+dkno2jZYhdJEuH2DmjTtTkV5bYwgto4JtV/Lbe+sXE6GO1UGg654430uow==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + + metro-transform-plugins@0.87.1: + resolution: {integrity: sha512-qMiJ/x+VfqumFJJSefKS6nj8uojzC29b2/aK8vlMuFABIqGjDucICEOXd2Yt6k/XMFAgAcaJvShUOT0HLyYaPw==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro-transform-worker@0.87.1: + resolution: {integrity: sha512-VOzs3OV405FuOLYdAhqA2wsn1F9lvueDVxMDLvCKaQ44U+yknIqphJ9eMjjsGwLDZiJq9sW3DMLhjD27JxQgqQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + metro@0.87.1: + resolution: {integrity: sha512-1oyLU9elM7hPAsKIqKooEekwxiuWr27+MZBhUROPhzcbXhMDxK64GPF/hCXwBZVp1F89ODavCrBmJtLx9WtBoQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@1.2.0: + resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} + engines: {node: '>=4'} + + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multitars@1.0.2: + resolution: {integrity: sha512-6GwVw5eLi9sThdtlS4PKwC7yRLaf45pYhIEzKBHdKxi+YOXGKFX8acIniH+Uh/+k9mS2lQOupTccjoe5r0/1IQ==} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-postinstall@0.3.5: + resolution: {integrity: sha512-NFMjXXkyodBJnRrM0A6qxFO1OLUbrYLDhP1ZLetlXnyx41gKOAmVyROibq85j7I8dda4aZMs9L7kmRvvjNf7Cg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + negotiator@1.1.0: + resolution: {integrity: sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==} + engines: {node: '>=18'} + + node-exports-info@1.6.2: + resolution: {integrity: sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==} + engines: {node: '>= 0.4'} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-forge@1.4.0: + resolution: {integrity: sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==} + engines: {node: '>= 6.13.0'} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.59: + resolution: {integrity: sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==} + engines: {node: '>=18'} + + noxcturnal@0.1.7: + resolution: {integrity: sha512-RVIIdLx9Q6EsoHmTeg+n23ZeswbZozH3zNDXA3fw3tCS6i4PDNXhHwcNqzObDaS0Ak5BGZdOk5nb3QPl7H9r2Q==} + engines: {node: '>=18'} + + npm-package-arg@11.0.3: + resolution: {integrity: sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==} + engines: {node: ^16.14.0 || >=18.0.0} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nullthrows@1.1.1: + resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + + ob1@0.87.1: + resolution: {integrity: sha512-i8iA8uij0g1YQzS8uOJPSRCgwDjO9warIHUAu1Fqj877Wc3wlfxDYBioYWgKTBF2+URVJttyDWSEpmd99nlvtQ==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.9: + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + + onetime@2.0.1: + resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} + engines: {node: '>=4'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@3.4.0: + resolution: {integrity: sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==} + engines: {node: '>=6'} + + own-keys@1.0.2: + resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==} + engines: {node: '>= 0.4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-png@2.1.0: + resolution: {integrity: sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ==} + engines: {node: '>=10'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + plist@3.1.1: + resolution: {integrity: sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==} + engines: {node: '>=10.4.0'} + + pngjs@3.4.0: + resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} + engines: {node: '>=4.0.0'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.31: + resolution: {integrity: sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.9.10: + resolution: {integrity: sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + proc-log@4.2.0: + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + react-devtools-core@6.1.5: + resolution: {integrity: sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA==} + + react-dom@19.3.0: + resolution: {integrity: sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==} + peerDependencies: + react: ^19.3.0 + + react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + + react-freeze@1.0.4: + resolution: {integrity: sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA==} + engines: {node: '>=10'} + peerDependencies: + react: '>=17.0.0' + + react-i18next@17.1.0: + resolution: {integrity: sha512-4VouOnTDyvhvqXx6WZ+s3/cgSiaLutILdYkO3P1Ms+4qcKR7At+JP4Vi7IeHkVLyVV+DmN1l23Pn73UcwSGGPA==} + peerDependencies: + i18next: '>= 26.2.0' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + typescript: ^5 || ^6 || ^7 + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + typescript: + optional: true + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-is@19.3.1: + resolution: {integrity: sha512-RRieF6IyxQBkcK6pP8xOHprLTPW6QjRkbGdImtqNme+/hYVwCZkLQLdlZGOhUqXwkS9IEynaGvPJtv6XB/cz0Q==} + + react-native-drawer-layout@4.2.12: + resolution: {integrity: sha512-qYmntEctkMSodN7pnC2llV21nswImLFPHJeT3PJXSJqZdU4jzDATR8iVi66sXkrtoOLJ2+EvXxgd7sMMpV4ViA==} + peerDependencies: + react: '>= 18.2.0' + react-native: '*' + react-native-gesture-handler: '>= 2.0.0' + react-native-reanimated: '>= 2.0.0' + + react-native-gesture-handler@3.3.0: + resolution: {integrity: sha512-ZCTlJ09nE3GPbm7J74lvwpxmx1TQ/7MDlHZNLARVYTN82k21mJUJ7BmI9eWjEi8eevHiAudI5O1Cpnt0rJfoJA==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-is-edge-to-edge@1.3.1: + resolution: {integrity: sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-reanimated@4.7.1: + resolution: {integrity: sha512-HviDFSZ6V4KTRsrLS6hRbBJ4j63l/L8a5az0EoWdJwaMLYnBNyYISTDxwXpEYkMbAbLzCMCviIdiOxXHYQWcNA==} + peerDependencies: + react: '*' + react-native: 0.86 - 0.88 + react-native-worklets: 0.13.x + + react-native-safe-area-context@5.10.1: + resolution: {integrity: sha512-ax0T3cAHQIhuAjDQpJ9C1Le96aRiM9PF+Kmgg7Y8+mD7QJMEIx04cG0eG3EGUTdvymgOkCrkakgZFwuOIuNQGw==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-screens@4.30.0: + resolution: {integrity: sha512-FrZG/Q5gqoDu0SgP4d2Ly0qdio5DR1KdGPEYImhkz7tmrhpML4C39m6RYLGd5TVLHZwcCh8NPvW9rylevjD0uQ==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-svg@15.16.0: + resolution: {integrity: sha512-uh8yktufYeRU3W9Omi8+SPyLF9BVN4JmLflSgc9oOcKkSKk/S5JUmmTjKZq/L8GHfQUtCvcu/W6X4xhEfBBAjQ==} + peerDependencies: + react: '*' + react-native: '*' + + react-native-web@0.21.4: + resolution: {integrity: sha512-77B6KlalB4osNIck91TNFixPkYPsTbuNEvw8P7IV+4v4/5wZSBRKZnw0Zhx6YjuauDTz71gc8IW+fVhcBMjr5A==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + + react-native-worklets@0.13.0: + resolution: {integrity: sha512-1OrhAeAKaZF4XrBa4YbPQbKzNOpjh52HDlId8e6ete1OCHNdAlrQHzG4gznJ225EAj3dgQXHViJvK51M9B52jQ==} + peerDependencies: + '@babel/core': '*' + '@react-native/metro-config': '*' + react: '*' + react-native: 0.86 - 0.88 + + react-native@0.88.0: + resolution: {integrity: sha512-v/wee0nYWcammMYBnSat/e3WY/5iaf9YQOMcBrfKT/wPApPPlHp94hgZovBtwhMuthR01yc/8cGn0FpFTE/C4A==} + engines: {node: ^22.13.0 || ^24.3.0 || >= 26.0.0} + hasBin: true + peerDependencies: + '@types/react': ^19.1.1 + react: ^19.3.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react@19.3.0: + resolution: {integrity: sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==} + engines: {node: '>=0.10.0'} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerate-unicode-properties@10.3.0: + resolution: {integrity: sha512-9ns8odR8e9q3otKeHj3DE80jZYKg6zVeZKE+zQmRKXFoVUcuiTGeO6iusDhPRoIQQPVPRvH+SfBhrTud4eczuw==} + engines: {node: '>=4'} + + regenerate@1.5.0: + resolution: {integrity: sha512-1s+CxXjJ71i7LNVy8nYwg47XV4y6lAnOEhsMtSKq3WpmPfhl9LuKlTqKIn/3yUpE8lBz+W+TT88Bxyhnr0U4yw==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpu-core@6.5.3: + resolution: {integrity: sha512-E8VgUoSK+LMQrLboDxavm76MTBGrQhx9RiNuomRmYnZ10Uw12HrI8fkxOOncktb2hBpzIZ9SV/347euQHG5z+g==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.4: + resolution: {integrity: sha512-EWV80YgFaVgFrjGCAsV7oybp4GOxbls5RzBg8OB0nKEVXsBJR1JlV8Di1JhCROg3MzTfe1RI8yitIm1eOs68iA==} + hasBin: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve-workspace-root@2.0.1: + resolution: {integrity: sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==} + + resolve@1.22.13: + resolution: {integrity: sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==} + engines: {node: '>= 0.4'} + hasBin: true + + resolve@2.0.0-next.7: + resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@2.0.0: + resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} + engines: {node: '>=4'} + + rtl-detect@1.1.2: + resolution: {integrity: sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==} + + safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + sandbox-cli-detector@0.2.0: + resolution: {integrity: sha512-4lyHX0ZU0AZKwjgZ1InxZAa3PNpyEb8rOQ+Zss1ReYmhNzW0Q+h1zE5nvniXN0HaAWZaZE1zgVNEirb0R7LmNg==} + engines: {node: '>=18.18'} + hasBin: true + + sax@1.6.1: + resolution: {integrity: sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==} + engines: {node: '>=11.0.0'} + + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + + serialize-error@2.1.0: + resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} + engines: {node: '>=0.10.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + server-only@0.0.1: + resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sf-symbols-typescript@2.2.0: + resolution: {integrity: sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw==} + engines: {node: '>=10'} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.12.0: + resolution: {integrity: sha512-PcByqNyT/38F2kDNi006HAMRJaULuBzq/FOsw3qdZvX/GA9W/jamDaRskgHjubHiftXK5sIFxLNkvrXUwcof6Q==} + engines: {node: '>= 0.4'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + simple-plist@1.3.1: + resolution: {integrity: sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==} + + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slugify@1.6.9: + resolution: {integrity: sha512-vZ7rfeehZui7wQs438JXBckYLkIIdfHOXsaVEUMyS5fHo1483l1bMdo0EDSWYclY0yZKFOipDy4KHuKs6ssvdg==} + engines: {node: '>=8.0.0'} + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + stable-hash@0.0.5: + resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + stacktrace-parser@0.1.11: + resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} + engines: {node: '>=6'} + + standard-navigation@0.0.5: + resolution: {integrity: sha512-YAmzwAiiQVocZxO/VGPFiQHcu5pKiz09QIGC0MK6aRMoa3E0QkoTQgcqJr7ZZ3OMiNhu4DkaGElFI5htjOIDbw==} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + stream-buffers@2.2.0: + resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} + engines: {node: '>= 0.10.0'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string.prototype.matchall@4.1.0: + resolution: {integrity: sha512-tHNHTxInrYLCga9O9YGxWA3G9/nnzQw8UGAyqGx3Ar1pSTTzIuM4woFSq4SowkXCjJIwq5sIiQvEfRI9tCH1qQ==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + structured-headers@0.4.1: + resolution: {integrity: sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg==} + + styleq@0.1.3: + resolution: {integrity: sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA==} + + superjson@2.2.6: + resolution: {integrity: sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==} + engines: {node: '>=16'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + + terser@5.51.2: + resolution: {integrity: sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==} + engines: {node: '>=10'} + hasBin: true + + throat@5.0.0: + resolution: {integrity: sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toqr@0.1.1: + resolution: {integrity: sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA==} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.5: + resolution: {integrity: sha512-0FHJvLPqZ7KJzp17O13jfsAjsqazgrxBu2zEK95PmUz8lv2+GjRuxUInCr2Rk9Dms3ihN21zJ929ZO43yJ95QQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} + engines: {node: '>= 0.4'} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ua-parser-js@0.7.41: + resolution: {integrity: sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==} + hasBin: true + + ua-parser-js@1.0.41: + resolution: {integrity: sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + undici-types@8.9.0: + resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unrs-resolver@1.12.2: + resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} + + update-browserslist-db@1.3.4: + resolution: {integrity: sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + use-latest-callback@0.2.6: + resolution: {integrity: sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==} + peerDependencies: + react: '>=16.8' + + use-sync-external-store@1.7.0: + resolution: {integrity: sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@7.0.3: + resolution: {integrity: sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + validate-npm-package-name@5.0.1: + resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vlq@1.0.1: + resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + warn-once@0.1.1: + resolution: {integrity: sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-url-minimum@0.2.0: + resolution: {integrity: sha512-BtjXU1caNcCFfETP2DhqSeVPfRDl2MTUitI107RE34rJXjR/izfUtR5IoTFOK1WqjNLXbbeqaCH/mQAOLjpc8g==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.24: + resolution: {integrity: sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + ws@7.5.13: + resolution: {integrity: sha512-rsKI6xDBFVf4r/x8XyChGK04QR/XHroxs/jUcoWvtEZM8TPU/X/uIY9B1CsSzYws9ZJb/6bbBu7dPhFW00CAoA==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.22.0: + resolution: {integrity: sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==} + 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 + + xcode@3.0.1: + resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==} + engines: {node: '>=10.0.0'} + + xml2js@0.6.0: + resolution: {integrity: sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zustand@5.0.15: + resolution: {integrity: sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + 2g@1.0.1(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.10 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.29.7': + dependencies: + '@babel/types': 7.29.8 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.29.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/traverse': 7.29.10 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.29.10(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + regexpu-core: 6.5.3 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.13 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-member-expression-to-functions@7.29.7': + dependencies: + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.29.7': + dependencies: + '@babel/types': 7.29.8 + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-remap-async-to-generator@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-wrap-function': 7.29.7 + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-member-expression-to-functions': 7.29.7 + '@babel/helper-optimise-call-expression': 7.29.7 + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.29.7': + dependencies: + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.29.7': {} + + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helper-wrap-function@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.29.10': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.9': + dependencies: + '@babel/types': 7.29.8 + + '@babel/plugin-proposal-decorators@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-decorators': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-export-default-from@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-decorators@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-export-default-from@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-flow@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-arrow-functions@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-async-generator-functions@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7) + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-remap-async-to-generator': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoping@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-class-properties@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-globals': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7) + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-destructuring@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-export-namespace-from@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-flow-strip-types@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7) + + '@babel/plugin-transform-for-of@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-logical-assignment-operators@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-create-regexp-features-plugin': 7.29.10(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-nullish-coalescing-operator@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-object-rest-spread@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7) + '@babel/traverse': 7.29.10 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-optional-chaining@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-private-methods@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-regenerator@7.29.8(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-runtime@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.7) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.7) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.7) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-template-literals@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-typescript@7.29.9(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-annotate-as-pure': 7.29.7 + '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.29.7 + '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-regex@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-create-regexp-features-plugin': 7.29.10(@babel/core@7.29.7) + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/preset-typescript@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-typescript': 7.29.9(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.29.10': {} + + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.10': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5)': + dependencies: + eslint: 9.39.5 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.7': + dependencies: + ajv: 6.15.0 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.3.2 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.5': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@expo-google-fonts/material-symbols@0.4.50': {} + + '@expo/cli@58.1.13(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12)(expo-font@58.0.9)(expo-router@58.0.24)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3)': + dependencies: + 2g: 1.0.1(typescript@6.0.3) + '@expo/code-signing-certificates': 0.0.7 + '@expo/config': 58.0.6(typescript@6.0.3) + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + '@expo/devcert': 1.2.2 + '@expo/env': 2.5.2 + '@expo/image-utils': 0.12.5(typescript@6.0.3) + '@expo/inline-modules': 0.2.6(typescript@6.0.3) + '@expo/json-file': 11.2.1 + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/log-box-utils': 58.0.2 + '@expo/metro': 58.0.0 + '@expo/metro-config': 58.0.15(expo@58.0.16)(typescript@6.0.3) + '@expo/metro-file-map': 58.0.5(typescript@6.0.3) + '@expo/osascript': 2.8.1 + '@expo/package-manager': 1.14.2 + '@expo/platforms': 58.0.1 + '@expo/plist': 0.10.1 + '@expo/prebuild-config': 58.0.14(typescript@6.0.3) + '@expo/require-utils': 58.0.4(typescript@6.0.3) + '@expo/router-server': 58.0.15(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12)(expo-font@58.0.9)(expo-router@58.0.24)(expo-server@58.0.5)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@expo/schema-utils': 58.0.2 + '@expo/spawn-async': 1.8.0 + '@expo/ws-tunnel': 2.0.1(ws@8.22.0) + '@expo/xcpretty': 4.4.7 + '@react-native/asset-utils': 0.88.0 + '@react-native/dev-middleware': 0.88.0 + '@react-native/js-polyfills': 0.88.0 + accepts: 1.3.8 + agent-cli-detector: 0.1.7 + arg: 5.0.2 + bplist-creator: 0.1.0 + bplist-parser: 0.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + compression: 1.8.2 + connect: 3.7.0 + dnssd-advertise: 1.1.6 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-server: 58.0.5 + fetch-nodeshim: 0.4.10 + getenv: 2.0.0 + glob: 13.0.6 + lan-network: 0.2.1 + multitars: 1.0.2 + node-forge: 1.4.0 + npm-package-arg: 11.0.3 + ora: 3.4.0 + picomatch: 4.0.7 + pretty-format: 29.7.0 + progress: 2.0.3 + prompts: 2.4.2 + resolve-from: 5.0.0 + sandbox-cli-detector: 0.2.0 + semver: 7.8.5 + send: 0.19.2 + slugify: 1.6.9 + stacktrace-parser: 0.1.11 + structured-headers: 0.4.1 + terminal-link: 2.1.1 + toqr: 0.1.1 + wrap-ansi: 7.0.0 + ws: 8.22.0 + zod: 3.25.76 + optionalDependencies: + expo-router: 58.0.24(128dea09177de0be5e43cb7aba297f1e) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + transitivePeerDependencies: + - '@expo/dom-webview' + - '@expo/metro-runtime' + - bufferutil + - expo-constants + - expo-font + - react + - react-dom + - react-server-dom-webpack + - supports-color + - typescript + - utf-8-validate + + '@expo/code-signing-certificates@0.0.7': + dependencies: + node-forge: 1.4.0 + + '@expo/config-plugins@58.0.9(typescript@6.0.3)': + dependencies: + '@expo/config-types': 58.0.3 + '@expo/json-file': 11.2.1 + '@expo/plist': 0.10.1 + '@expo/require-utils': 58.0.4(typescript@6.0.3) + '@expo/sdk-runtime-versions': 1.0.1 + chalk: 4.1.2 + debug: 4.4.3 + getenv: 2.0.0 + glob: 13.0.6 + semver: 7.8.5 + slugify: 1.6.9 + xcode: 3.0.1 + xml2js: 0.6.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/config-types@58.0.3': {} + + '@expo/config@58.0.6(typescript@6.0.3)': + dependencies: + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + '@expo/config-types': 58.0.3 + '@expo/json-file': 11.2.1 + '@expo/platforms': 58.0.1 + '@expo/require-utils': 58.0.4(typescript@6.0.3) + deepmerge: 4.3.1 + getenv: 2.0.0 + glob: 13.0.6 + resolve-workspace-root: 2.0.1 + semver: 7.8.5 + slugify: 1.6.9 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/devcert@1.2.2': + dependencies: + '@expo/sudo-prompt': 9.3.2 + debug: 3.2.7 + transitivePeerDependencies: + - supports-color + + '@expo/devtools@58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + chalk: 4.1.2 + optionalDependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + '@expo/dom-webview@58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + '@expo/env@2.5.2': + dependencies: + chalk: 4.1.2 + debug: 4.4.3 + getenv: 2.0.0 + transitivePeerDependencies: + - supports-color + + '@expo/fingerprint@0.21.5': + dependencies: + '@expo/env': 2.5.2 + '@expo/spawn-async': 1.8.0 + arg: 5.0.2 + chalk: 4.1.2 + debug: 4.4.3 + getenv: 2.0.0 + glob: 13.0.6 + ignore: 5.3.2 + minimatch: 10.2.6 + resolve-from: 5.0.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + + '@expo/image-utils@0.12.5(typescript@6.0.3)': + dependencies: + '@expo/require-utils': 58.0.4(typescript@6.0.3) + '@expo/spawn-async': 1.8.0 + chalk: 4.1.2 + getenv: 2.0.0 + jimp-compact: 0.16.1 + parse-png: 2.1.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/inline-modules@0.2.6(typescript@6.0.3)': + dependencies: + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/json-file@11.2.1': + dependencies: + '@babel/code-frame': 7.29.7 + json5: 2.2.3 + + '@expo/local-build-cache-provider@58.0.6(typescript@6.0.3)': + dependencies: + '@expo/config': 58.0.6(typescript@6.0.3) + chalk: 4.1.2 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/log-box-utils@58.0.2': {} + + '@expo/log-box@58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + '@expo/dom-webview': 58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/log-box-utils': 58.0.2 + anser: 1.4.10 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + stacktrace-parser: 0.1.11 + optionalDependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + + '@expo/metro-config@58.0.15(expo@58.0.16)(typescript@6.0.3)': + dependencies: + 2g: 1.0.1(typescript@6.0.3) + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7 + '@babel/generator': 7.29.8 + '@expo/config': 58.0.6(typescript@6.0.3) + '@expo/env': 2.5.2 + '@expo/json-file': 11.2.1 + '@expo/metro': 58.0.0 + '@expo/platforms': 58.0.1 + '@expo/require-utils': 58.0.4(typescript@6.0.3) + '@expo/spawn-async': 1.8.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + '@react-native/js-polyfills': 0.88.0 + browserslist: 4.29.4 + chalk: 4.1.2 + debug: 4.4.3 + getenv: 2.0.0 + glob: 13.0.6 + hermes-parser: 0.36.1 + jsc-safe-url: 0.2.4 + lightningcss: 1.33.0 + noxcturnal: 0.1.7 + picomatch: 4.0.7 + postcss: 8.5.31 + resolve-from: 5.0.0 + optionalDependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + transitivePeerDependencies: + - bufferutil + - supports-color + - typescript + - utf-8-validate + + '@expo/metro-file-map@58.0.5(typescript@6.0.3)': + dependencies: + 2g: 1.0.1(typescript@6.0.3) + debug: 4.4.3 + fb-watchman: 2.0.4 + invariant: 2.2.4 + jest-worker: 29.7.0 + walker: 1.0.8 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/metro-runtime@58.0.14(@expo/log-box@58.0.12)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + anser: 1.4.10 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + pretty-format: 29.7.0 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + stacktrace-parser: 0.1.11 + whatwg-fetch: 3.6.20 + optionalDependencies: + react-dom: 19.3.0(react@19.3.0) + + '@expo/metro@58.0.0': + dependencies: + metro: 0.87.1 + metro-babel-transformer: 0.87.1 + metro-cache: 0.87.1 + metro-cache-key: 0.87.1 + metro-config: 0.87.1 + metro-core: 0.87.1 + metro-file-map: 0.87.1 + metro-minify-terser: 0.87.1 + metro-resolver: 0.87.1 + metro-runtime: 0.87.1 + metro-source-map: 0.87.1 + metro-symbolicate: 0.87.1 + metro-transform-plugins: 0.87.1 + metro-transform-worker: 0.87.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@expo/modules-macros-linux-arm64@0.21.0': + optional: true + + '@expo/modules-macros-linux-x64@0.21.0': + optional: true + + '@expo/modules-macros-win32-arm64@0.21.0': + optional: true + + '@expo/modules-macros-win32-x64@0.21.0': + optional: true + + '@expo/osascript@2.8.1': + dependencies: + '@expo/spawn-async': 1.8.0 + + '@expo/package-manager@1.14.2': + dependencies: + '@expo/json-file': 11.2.1 + '@expo/spawn-async': 1.8.0 + chalk: 4.1.2 + npm-package-arg: 11.0.3 + ora: 3.4.0 + resolve-workspace-root: 2.0.1 + + '@expo/platforms@58.0.1': {} + + '@expo/plist@0.10.1': + dependencies: + '@xmldom/xmldom': 0.8.15 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + '@expo/prebuild-config@58.0.14(typescript@6.0.3)': + dependencies: + '@expo/config': 58.0.6(typescript@6.0.3) + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + '@expo/config-types': 58.0.3 + '@expo/image-utils': 0.12.5(typescript@6.0.3) + '@expo/json-file': 11.2.1 + '@react-native/normalize-colors': 0.88.0 + debug: 4.4.3 + expo-modules-autolinking: 58.0.13(typescript@6.0.3) + resolve-from: 5.0.0 + semver: 7.8.5 + transitivePeerDependencies: + - supports-color + - typescript + + '@expo/require-utils@58.0.4(typescript@6.0.3)': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7 + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@expo/router-server@58.0.15(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12)(expo-font@58.0.9)(expo-router@58.0.24)(expo-server@58.0.5)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + debug: 4.4.3 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-constants: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + expo-font: 58.0.9(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-server: 58.0.5 + react: 19.3.0 + optionalDependencies: + '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-router: 58.0.24(128dea09177de0be5e43cb7aba297f1e) + react-dom: 19.3.0(react@19.3.0) + transitivePeerDependencies: + - supports-color + + '@expo/schema-utils@58.0.2': {} + + '@expo/sdk-runtime-versions@1.0.1': {} + + '@expo/spawn-async@1.8.0': + dependencies: + cross-spawn: 7.0.6 + + '@expo/sudo-prompt@9.3.2': {} + + '@expo/ui@58.0.21(@babel/core@7.29.7)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + sf-symbols-typescript: 2.2.0 + optionalDependencies: + '@babel/core': 7.29.7 + react-dom: 19.3.0(react@19.3.0) + react-native-worklets: 0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + + '@expo/ws-tunnel@2.0.1(ws@8.22.0)': + dependencies: + ws: 8.22.0 + + '@expo/xcpretty@4.4.7': + dependencies: + '@babel/code-frame': 7.29.7 + chalk: 4.1.2 + js-yaml: 4.3.2 + + '@formatjs/bigdecimal@0.2.7': {} + + '@formatjs/fast-memoize@3.1.7': {} + + '@formatjs/intl-localematcher@0.9.0': + dependencies: + '@formatjs/fast-memoize': 3.1.7 + + '@formatjs/intl-pluralrules@6.3.16': + dependencies: + '@formatjs/bigdecimal': 0.2.7 + '@formatjs/intl-localematcher': 0.9.0 + + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 + + '@humanfs/node@0.16.8': + dependencies: + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 + '@humanwhocodes/retry': 0.4.3 + + '@humanfs/types@0.15.0': {} + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@isaacs/ttlcache@1.4.1': {} + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.12 + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 26.6.5 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@napi-rs/wasm-runtime@1.2.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.4 + optional: true + + '@nolyfill/is-core-module@1.0.39': {} + + '@noxcturnal/noxcturnal-darwin-arm64@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-darwin-x64@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-linux-arm64-gnu@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-linux-arm64-musl@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-linux-x64-gnu@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-linux-x64-musl@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-win32-arm64-msvc@0.1.7': + optional: true + + '@noxcturnal/noxcturnal-win32-x64-msvc@0.1.7': + optional: true + + '@oxc-project/types@0.154.0': {} + + '@radix-ui/primitive@1.2.0': {} + + '@radix-ui/react-collection@1.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-compose-refs@1.1.5(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-context@1.3.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-direction@1.2.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-id@1.1.4(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-presence@1.1.11(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-primitive@2.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-roving-focus@1.2.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-collection': 1.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-primitive': 2.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-callback-ref': 1.1.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-is-hydrated': 0.1.3(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-slot@1.5.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.5(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-tabs@1.2.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-context': 1.3.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-direction': 1.2.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-id': 1.1.4(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-presence': 1.1.11(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-primitive': 2.2.0(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-roving-focus': 1.2.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@radix-ui/react-use-controllable-state': 1.3.0(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-callback-ref@1.1.5(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-controllable-state@1.3.0(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/primitive': 1.2.0 + '@radix-ui/react-use-effect-event': 0.0.5(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-effect-event@0.0.5(@types/react@19.3.0)(react@19.3.0)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.4(@types/react@19.3.0)(react@19.3.0) + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-is-hydrated@0.1.3(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@radix-ui/react-use-layout-effect@1.1.4(@types/react@19.3.0)(react@19.3.0)': + dependencies: + react: 19.3.0 + optionalDependencies: + '@types/react': 19.3.0 + + '@react-native-masked-view/masked-view@0.3.2(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + '@react-native/asset-utils@0.88.0': {} + + '@react-native/babel-plugin-codegen@0.88.0(@babel/core@7.29.7)': + dependencies: + '@babel/traverse': 7.29.10 + '@react-native/codegen': 0.88.0(@babel/core@7.29.7) + transitivePeerDependencies: + - '@babel/core' + - supports-color + + '@react-native/babel-preset@0.88.0(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-regenerator': 7.29.8(@babel/core@7.29.7) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-typescript': 7.29.9(@babel/core@7.29.7) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) + '@react-native/babel-plugin-codegen': 0.88.0(@babel/core@7.29.7) + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7) + flow-parser: 0.327.0 + react-refresh: 0.14.2 + transitivePeerDependencies: + - supports-color + + '@react-native/codegen@0.88.0(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.9 + flow-parser: 0.327.0 + invariant: 2.2.4 + nullthrows: 1.1.1 + tinyglobby: 0.2.17 + yargs: 17.7.3 + + '@react-native/community-cli-plugin@0.88.0(@react-native/metro-config@0.88.0(@babel/core@7.29.7))': + dependencies: + '@react-native/asset-utils': 0.88.0 + '@react-native/dev-middleware': 0.88.0 + commander: 12.1.0 + debug: 4.4.3 + invariant: 2.2.4 + metro: 0.87.1 + semver: 7.8.5 + optionalDependencies: + '@react-native/metro-config': 0.88.0(@babel/core@7.29.7) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/debugger-frontend@0.88.0': {} + + '@react-native/debugger-shell@0.88.0': + dependencies: + cross-spawn: 7.0.6 + debug: 4.4.3 + fb-dotslash: 0.5.8 + transitivePeerDependencies: + - supports-color + + '@react-native/dev-middleware@0.88.0': + dependencies: + '@isaacs/ttlcache': 1.4.1 + '@react-native/debugger-frontend': 0.88.0 + '@react-native/debugger-shell': 0.88.0 + connect: 3.7.0 + debug: 4.4.3 + invariant: 2.2.4 + nullthrows: 1.1.1 + open: 8.4.2 + serve-static: 1.16.3 + ws: 7.5.13 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/gradle-plugin@0.88.0': {} + + '@react-native/js-polyfills@0.88.0': {} + + '@react-native/metro-babel-transformer@0.88.0(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@react-native/babel-preset': 0.88.0(@babel/core@7.29.7) + flow-parser: 0.327.0 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + '@react-native/metro-config@0.88.0(@babel/core@7.29.7)': + dependencies: + '@react-native/js-polyfills': 0.88.0 + '@react-native/metro-babel-transformer': 0.88.0(@babel/core@7.29.7) + metro-config: 0.87.1 + metro-runtime: 0.87.1 + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - supports-color + - utf-8-validate + + '@react-native/normalize-colors@0.74.89': {} + + '@react-native/normalize-colors@0.88.0': {} + + '@react-native/virtualized-lists@0.88.0(@types/react@19.3.0)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + invariant: 2.2.4 + nullthrows: 1.1.1 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + optionalDependencies: + '@types/react': 19.3.0 + + '@rtsao/scc@1.1.0': {} + + '@sinclair/typebox@0.27.12': {} + + '@tanstack/query-core@4.44.0': {} + + '@tanstack/react-query@4.44.0(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)': + dependencies: + '@tanstack/query-core': 4.44.0 + react: 19.3.0 + use-sync-external-store: 1.7.0(react@19.3.0) + optionalDependencies: + react-dom: 19.3.0(react@19.3.0) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + '@trpc/client@10.45.4(@trpc/server@10.45.4)': + dependencies: + '@trpc/server': 10.45.4 + + '@trpc/react-query@10.45.4(@tanstack/react-query@4.44.0(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(@trpc/client@10.45.4(@trpc/server@10.45.4))(@trpc/server@10.45.4)(react-dom@19.3.0(react@19.3.0))(react@19.3.0)': + dependencies: + '@tanstack/react-query': 4.44.0(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@trpc/client': 10.45.4(@trpc/server@10.45.4) + '@trpc/server': 10.45.4 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + + '@trpc/server@10.45.4': {} + + '@tybys/wasm-util@0.10.4': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/estree@1.0.9': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/node@26.6.5': + dependencies: + undici-types: 8.9.0 + + '@types/react-test-renderer@19.3.0': + dependencies: + '@types/react': 19.3.0 + + '@types/react@19.3.0': + dependencies: + csstype: 3.2.3 + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@typescript-eslint/eslint-plugin@8.72.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint@9.39.5)(typescript@6.0.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.72.0 + '@typescript-eslint/type-utils': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + '@typescript-eslint/utils': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.72.0 + eslint: 9.39.5 + ignore: 7.0.13 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.72.0 + '@typescript-eslint/types': 8.72.0 + '@typescript-eslint/typescript-estree': 8.72.0(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.72.0 + debug: 4.4.3 + eslint: 9.39.5 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.72.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.72.0(typescript@6.0.3) + '@typescript-eslint/types': 8.72.0 + debug: 4.4.3 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.72.0': + dependencies: + '@typescript-eslint/types': 8.72.0 + '@typescript-eslint/visitor-keys': 8.72.0 + + '@typescript-eslint/tsconfig-utils@8.72.0(typescript@6.0.3)': + dependencies: + typescript: 6.0.3 + + '@typescript-eslint/type-utils@8.72.0(eslint@9.39.5)(typescript@6.0.3)': + dependencies: + '@typescript-eslint/types': 8.72.0 + '@typescript-eslint/typescript-estree': 8.72.0(typescript@6.0.3) + '@typescript-eslint/utils': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + debug: 4.4.3 + eslint: 9.39.5 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.72.0': {} + + '@typescript-eslint/typescript-estree@8.72.0(typescript@6.0.3)': + dependencies: + '@typescript-eslint/project-service': 8.72.0(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.72.0(typescript@6.0.3) + '@typescript-eslint/types': 8.72.0 + '@typescript-eslint/visitor-keys': 8.72.0 + debug: 4.4.3 + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.72.0(eslint@9.39.5)(typescript@6.0.3)': + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5) + '@typescript-eslint/scope-manager': 8.72.0 + '@typescript-eslint/types': 8.72.0 + '@typescript-eslint/typescript-estree': 8.72.0(typescript@6.0.3) + eslint: 9.39.5 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.72.0': + dependencies: + '@typescript-eslint/types': 8.72.0 + eslint-visitor-keys: 5.0.1 + + '@ungap/structured-clone@1.4.0': {} + + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + optional: true + + '@unrs/resolver-binding-android-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.2.5(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + optional: true + + '@xmldom/xmldom@0.8.15': {} + + '@xmldom/xmldom@0.9.12': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + accepts@2.0.0: + dependencies: + mime-types: 3.0.2 + negotiator: 1.1.0 + + acorn-jsx@5.3.2(acorn@8.19.0): + dependencies: + acorn: 8.19.0 + + acorn@8.19.0: {} + + agent-base@7.1.4: {} + + agent-cli-detector@0.1.7: {} + + ajv@6.15.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + anser@1.4.10: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@4.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + arg@5.0.2: {} + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.2.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + asap@2.0.6: {} + + async-function@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.7): + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/core': 7.29.7 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.7): + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7) + core-js-compat: 3.51.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.7): + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.7) + transitivePeerDependencies: + - supports-color + + babel-plugin-react-compiler@1.0.0: + dependencies: + '@babel/types': 7.29.8 + + babel-plugin-react-native-web@0.21.4: {} + + babel-plugin-syntax-hermes-parser@0.36.1: + dependencies: + hermes-parser: 0.36.1 + + babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.29.7): + dependencies: + '@babel/plugin-syntax-flow': 7.29.7(@babel/core@7.29.7) + transitivePeerDependencies: + - '@babel/core' + + babel-preset-expo@58.0.18(@babel/core@7.29.7)(@babel/runtime@7.29.10)(expo@58.0.16)(react-refresh@0.14.2): + dependencies: + '@babel/generator': 7.29.8 + '@babel/helper-module-imports': 7.29.7 + '@babel/plugin-proposal-decorators': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-proposal-export-default-from': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-export-default-from': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7) + '@babel/plugin-transform-async-generator-functions': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-async-to-generator': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-block-scoping': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-class-static-block': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-destructuring': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-export-namespace-from': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-flow-strip-types': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-for-of': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-logical-assignment-operators': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-object-rest-spread': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-optional-catch-binding': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-parameters': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-private-methods': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-private-property-in-object': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-runtime': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-typescript': 7.29.9(@babel/core@7.29.7) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) + '@react-native/babel-plugin-codegen': 0.88.0(@babel/core@7.29.7) + babel-plugin-react-compiler: 1.0.0 + babel-plugin-react-native-web: 0.21.4 + babel-plugin-syntax-hermes-parser: 0.36.1 + babel-plugin-transform-flow-enums: 0.0.2(@babel/core@7.29.7) + debug: 4.4.3 + react-refresh: 0.14.2 + optionalDependencies: + '@babel/runtime': 7.29.10 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + transitivePeerDependencies: + - '@babel/core' + - supports-color + + badgin@1.2.3: {} + + balanced-match@1.0.2: {} + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.11.30: {} + + big-integer@1.6.52: {} + + boolbase@1.0.0: {} + + bplist-creator@0.1.0: + dependencies: + stream-buffers: 2.2.0 + + bplist-parser@0.3.1: + dependencies: + big-integer: 1.6.52 + + bplist-parser@0.3.2: + dependencies: + big-integer: 1.6.52 + + brace-expansion@1.1.21: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.29.4: + dependencies: + baseline-browser-mapping: 2.11.30 + caniuse-lite: 1.0.30001817 + electron-to-chromium: 1.5.462 + node-releases: 2.0.59 + update-browserslist-db: 1.3.4(browserslist@4.29.4) + + bser@2.1.2: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + bytes@3.1.2: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001817: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + ci-info@3.9.0: {} + + cli-cursor@2.1.0: + dependencies: + restore-cursor: 2.0.0 + + cli-spinners@2.9.2: {} + + client-only@0.0.1: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + commander@12.1.0: {} + + commander@2.20.3: {} + + commander@7.2.0: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression@1.8.2: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + destroy: 1.2.0 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + connect@3.7.0: + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + + content-type@2.1.0: {} + + convert-source-map@2.0.0: {} + + copy-anything@4.1.5: {} + + core-js-compat@3.51.0: + dependencies: + browserslist: 4.29.4 + + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-in-js-utils@3.1.0: + dependencies: + hyphenate-style-name: 1.1.0 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-what@6.2.2: {} + + csstype@3.2.3: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + date-fns@3.6.0: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + depd@2.0.0: {} + + destroy@1.2.0: {} + + detect-libc@2.1.2: {} + + dnssd-advertise@1.1.6: {} + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.462: {} + + emoji-regex@8.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + entities@4.5.0: {} + + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + + es-abstract-get@1.0.0: + dependencies: + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + is-callable: 1.2.7 + object-inspect: 1.13.4 + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.4 + function.prototype.name: 1.2.0 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.2 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.4 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.5 + typed-array-length: 1.0.8 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.24 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.4.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + math-intrinsics: 1.1.0 + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.4 + + es-to-primitive@1.3.4: + dependencies: + es-abstract-get: 1.0.0 + es-define-property: 1.0.1 + es-errors: 1.3.0 + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-expo@58.0.4(eslint@9.39.5)(typescript@6.0.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.72.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint@9.39.5)(typescript@6.0.3) + '@typescript-eslint/parser': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + eslint: 9.39.5 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5) + eslint-plugin-expo: 1.2.1(eslint@9.39.5)(typescript@6.0.3) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5) + eslint-plugin-react: 7.37.5(eslint@9.39.5) + eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5) + globals: 16.5.0 + transitivePeerDependencies: + - eslint-import-resolver-webpack + - eslint-plugin-import-x + - supports-color + - typescript + + eslint-import-resolver-node@0.3.10: + dependencies: + debug: 3.2.7 + is-core-module: 2.17.0 + resolve: 2.0.0-next.7 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5): + dependencies: + '@nolyfill/is-core-module': 1.0.39 + debug: 4.4.3 + eslint: 9.39.5 + get-tsconfig: 4.14.3 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.17 + unrs-resolver: 1.12.2 + optionalDependencies: + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5) + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.14.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + eslint: 9.39.5 + eslint-import-resolver-node: 0.3.10 + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5) + transitivePeerDependencies: + - supports-color + + eslint-plugin-expo@1.2.1(eslint@9.39.5)(typescript@6.0.3): + dependencies: + '@typescript-eslint/types': 8.72.0 + '@typescript-eslint/utils': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + eslint: 9.39.5 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.2.0 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.39.5 + eslint-import-resolver-node: 0.3.10 + eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.72.0(eslint@9.39.5)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5) + hasown: 2.0.4 + is-core-module: 2.17.0 + is-glob: 4.0.3 + minimatch: 3.1.5 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.10 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.72.0(eslint@9.39.5)(typescript@6.0.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-react-hooks@7.1.1(eslint@9.39.5): + dependencies: + '@babel/core': 7.29.7 + '@babel/parser': 7.29.9 + eslint: 9.39.5 + hermes-parser: 0.25.1 + zod: 3.25.76 + zod-validation-error: 4.0.2(zod@3.25.76) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react@7.37.5(eslint@9.39.5): + dependencies: + array-includes: 3.2.0 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.4.0 + eslint: 9.39.5 + estraverse: 5.3.0 + hasown: 2.0.4 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.5 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.7 + semver: 6.3.1 + string.prototype.matchall: 4.1.0 + string.prototype.repeat: 1.0.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@9.39.5: + dependencies: + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.7 + '@eslint/js': 9.39.5 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.8 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + ajv: 6.15.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.19.0 + acorn-jsx: 5.3.2(acorn@8.19.0) + eslint-visitor-keys: 4.2.1 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + expo-apple-authentication@58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo-application@58.1.2(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + + expo-asset@58.0.17(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + dependencies: + '@expo/image-utils': 0.12.5(typescript@6.0.3) + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-constants: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + transitivePeerDependencies: + - supports-color + - typescript + + expo-constants@58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3): + dependencies: + '@expo/env': 2.5.2 + '@expo/require-utils': 58.0.4(typescript@6.0.3) + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + transitivePeerDependencies: + - supports-color + - typescript + + expo-crypto@58.0.7(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + + expo-device@58.0.5(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + ua-parser-js: 0.7.41 + + expo-file-system@58.0.10(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo-font@58.0.9(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo-glass-effect@58.0.4(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo-haptics@58.0.7(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + + expo-image-loader@58.0.3(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + + expo-image-picker@58.0.10(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-image-loader: 58.0.3(expo@58.0.16) + + expo-image@58.0.16(expo@58.0.16)(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + sf-symbols-typescript: 2.2.0 + optionalDependencies: + react-native-web: 0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + + expo-keep-awake@58.0.3(expo@58.0.16)(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + + expo-linking@58.0.13(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-constants: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + invariant: 2.2.4 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + transitivePeerDependencies: + - supports-color + - typescript + + expo-localization@58.0.5(expo@58.0.16)(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + rtl-detect: 1.1.2 + + expo-modules-autolinking@58.0.13(typescript@6.0.3): + dependencies: + '@expo/platforms': 58.0.1 + '@expo/require-utils': 58.0.4(typescript@6.0.3) + '@expo/spawn-async': 1.8.0 + chalk: 4.1.2 + commander: 7.2.0 + transitivePeerDependencies: + - supports-color + - typescript + + expo-modules-cli@0.3.1: + dependencies: + arg: 5.0.2 + + expo-modules-core@58.0.23(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + expo-modules-jsi: 58.0.16(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)) + expo-modules-macros: 0.21.0 + invariant: 2.2.4 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + optionalDependencies: + react-native-worklets: 0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + + expo-modules-jsi@58.0.16(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)): + dependencies: + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo-modules-macros@0.21.0: + optionalDependencies: + '@expo/modules-macros-linux-arm64': 0.21.0 + '@expo/modules-macros-linux-x64': 0.21.0 + '@expo/modules-macros-win32-arm64': 0.21.0 + '@expo/modules-macros-win32-x64': 0.21.0 + + expo-notifications@58.1.5(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + dependencies: + '@expo/image-utils': 0.12.5(typescript@6.0.3) + abort-controller: 3.0.0 + badgin: 1.2.3 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-application: 58.1.2(expo@58.0.16) + expo-constants: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + transitivePeerDependencies: + - supports-color + - typescript + + expo-router@58.0.24(128dea09177de0be5e43cb7aba297f1e): + dependencies: + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/schema-utils': 58.0.2 + '@radix-ui/react-slot': 1.5.0(@types/react@19.3.0)(react@19.3.0) + '@radix-ui/react-tabs': 1.2.1(@types/react@19.3.0)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + '@react-native-masked-view/masked-view': 0.3.2(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@react-native/normalize-colors': 0.88.0 + client-only: 0.0.1 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-constants: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + expo-glass-effect: 58.0.4(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-linking: 58.0.13(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-server: 58.0.5 + nanoid: 3.3.20 + react: 19.3.0 + react-fast-compare: 3.2.2 + react-is: 19.3.1 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + react-native-drawer-layout: 4.2.12(react-native-gesture-handler@3.3.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native-reanimated@4.7.1(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-safe-area-context: 5.10.1(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-screens: 4.30.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + server-only: 0.0.1 + sf-symbols-typescript: 2.2.0 + standard-navigation: 0.0.5 + optionalDependencies: + '@expo/ui': 58.0.21(@babel/core@7.29.7)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-symbols: 58.0.4(expo-font@58.0.9)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-dom: 19.3.0(react@19.3.0) + react-native-gesture-handler: 3.3.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-reanimated: 4.7.1(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-web: 0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react-native-worklets: 0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + + expo-secure-store@58.0.2(expo@58.0.16): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + + expo-server@58.0.5: {} + + expo-sharing@58.0.19(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + dependencies: + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + '@expo/config-types': 58.0.3 + '@expo/plist': 0.10.1 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + transitivePeerDependencies: + - supports-color + - typescript + + expo-splash-screen@58.0.10(expo@58.0.16)(typescript@6.0.3): + dependencies: + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + '@expo/image-utils': 0.12.5(typescript@6.0.3) + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + xml2js: 0.6.0 + transitivePeerDependencies: + - supports-color + - typescript + + expo-status-bar@58.0.3(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo-symbols@58.0.4(expo-font@58.0.9)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + '@expo-google-fonts/material-symbols': 0.4.50 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-font: 58.0.9(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + sf-symbols-typescript: 2.2.0 + + expo-system-ui@58.0.6(expo@58.0.16)(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)): + dependencies: + '@react-native/normalize-colors': 0.88.0 + debug: 4.4.3 + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + optionalDependencies: + react-native-web: 0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + transitivePeerDependencies: + - supports-color + + expo-web-browser@58.0.6(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)): + dependencies: + expo: 58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + expo@58.0.16(@babel/core@7.29.7)(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-router@58.0.24)(react-dom@19.3.0(react@19.3.0))(react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + dependencies: + '@babel/runtime': 7.29.10 + '@expo/cli': 58.1.13(@expo/dom-webview@58.0.2)(@expo/metro-runtime@58.0.14)(expo-constants@58.0.12)(expo-font@58.0.9)(expo-router@58.0.24)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + '@expo/config': 58.0.6(typescript@6.0.3) + '@expo/config-plugins': 58.0.9(typescript@6.0.3) + '@expo/devtools': 58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/fingerprint': 0.21.5 + '@expo/local-build-cache-provider': 58.0.6(typescript@6.0.3) + '@expo/log-box': 58.0.12(@expo/dom-webview@58.0.2)(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/log-box-utils': 58.0.2 + '@expo/metro': 58.0.0 + '@expo/metro-config': 58.0.15(expo@58.0.16)(typescript@6.0.3) + '@ungap/structured-clone': 1.4.0 + babel-preset-expo: 58.0.18(@babel/core@7.29.7)(@babel/runtime@7.29.10)(expo@58.0.16)(react-refresh@0.14.2) + expo-asset: 58.0.17(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3) + expo-constants: 58.0.12(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(typescript@6.0.3) + expo-file-system: 58.0.10(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0)) + expo-font: 58.0.9(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + expo-keep-awake: 58.0.3(expo@58.0.16)(react@19.3.0) + expo-modules-autolinking: 58.0.13(typescript@6.0.3) + expo-modules-cli: 0.3.1 + expo-modules-core: 58.0.23(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + pretty-format: 29.7.0 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + react-refresh: 0.14.2 + whatwg-url-minimum: 0.2.0 + optionalDependencies: + '@expo/dom-webview': 58.0.2(expo@58.0.16)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + '@expo/metro-runtime': 58.0.14(@expo/log-box@58.0.12)(expo@58.0.16)(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-dom: 19.3.0(react@19.3.0) + react-native-web: 0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + transitivePeerDependencies: + - '@babel/core' + - bufferutil + - expo-router + - expo-widgets + - react-native-worklets + - react-server-dom-webpack + - supports-color + - typescript + - utf-8-validate + + exponential-backoff@3.1.3: {} + + fast-deep-equal@3.1.3: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fb-dotslash@0.5.8: {} + + fb-watchman@2.0.4: + dependencies: + bser: 2.1.2 + + fbjs-css-vars@1.0.2: {} + + fbjs@3.0.5: + dependencies: + cross-fetch: 3.2.0 + fbjs-css-vars: 1.0.2 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 1.0.41 + transitivePeerDependencies: + - encoding + + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + + fetch-nodeshim@0.4.10: {} + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.4 + keyv: 4.5.4 + + flatted@3.4.4: {} + + flow-enums-runtime@0.0.6: {} + + flow-estree@0.327.0: {} + + flow-estree@0.331.0: {} + + flow-parser@0.327.0: + dependencies: + flow-estree: 0.327.0 + + flow-parser@0.331.0: + dependencies: + flow-estree: 0.331.0 + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + fresh@0.5.2: {} + + function-bind@1.1.2: {} + + function.prototype.name@1.2.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + es-define-property: 1.0.1 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + hasown: 2.0.4 + is-callable: 1.2.7 + is-document.all: 1.0.0 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.2 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + get-tsconfig@4.14.3: + dependencies: + resolve-pkg-maps: 1.0.0 + + getenv@2.0.0: {} + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@13.0.6: + dependencies: + minimatch: 10.2.6 + minipass: 7.1.3 + path-scurry: 2.0.2 + + globals@14.0.0: {} + + globals@16.5.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-bigints@1.1.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hermes-compiler@260318099.0.4: {} + + hermes-estree@0.25.1: {} + + hermes-estree@0.36.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + hermes-parser@0.36.1: + dependencies: + hermes-estree: 0.36.1 + + hosted-git-info@7.0.2: + dependencies: + lru-cache: 10.4.3 + + html-parse-stringify@4.0.1: {} + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + hyphenate-style-name@1.1.0: {} + + i18next@26.5.3(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + ignore@5.3.2: {} + + ignore@7.0.13: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inherits@2.0.4: {} + + inline-style-prefixer@7.0.1: + dependencies: + css-in-js-utils: 3.1.0 + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.4 + side-channel: 1.1.1 + + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.3.4: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-bun-module@2.0.0: + dependencies: + semver: 7.8.5 + + is-callable@1.2.7: {} + + is-core-module@2.17.0: + dependencies: + hasown: 2.0.4 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-docker@2.2.1: {} + + is-document.all@1.0.0: + dependencies: + call-bound: 1.0.4 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.24 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jest-get-type@29.6.3: {} + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 26.6.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.2 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-worker@29.7.0: + dependencies: + '@types/node': 26.6.5 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jimp-compact@0.16.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.3.2: + dependencies: + argparse: 2.0.1 + + jsc-safe-url@0.2.4: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.2.0 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kleur@3.0.3: {} + + lan-network@0.2.1: {} + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.debounce@4.0.8: {} + + lodash.merge@4.6.2: {} + + lodash.throttle@4.1.1: {} + + log-symbols@2.2.0: + dependencies: + chalk: 2.4.2 + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@10.4.3: {} + + lru-cache@11.5.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + math-intrinsics@1.1.0: {} + + mdn-data@2.0.14: {} + + memoize-one@5.2.1: {} + + memoize-one@6.0.0: {} + + merge-stream@2.0.0: {} + + metro-babel-transformer@0.87.1: + dependencies: + '@babel/core': 7.29.7 + flow-enums-runtime: 0.0.6 + flow-parser: 0.331.0 + metro-cache-key: 0.87.1 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-cache-key@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-cache@0.87.1: + dependencies: + exponential-backoff: 3.1.3 + flow-enums-runtime: 0.0.6 + https-proxy-agent: 7.0.6 + metro-core: 0.87.1 + transitivePeerDependencies: + - supports-color + + metro-config@0.87.1: + dependencies: + connect: 3.7.0 + flow-enums-runtime: 0.0.6 + jest-validate: 29.7.0 + metro: 0.87.1 + metro-cache: 0.87.1 + metro-core: 0.87.1 + metro-runtime: 0.87.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro-core@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + lodash.throttle: 4.1.1 + metro-resolver: 0.87.1 + + metro-file-map@0.87.1: + dependencies: + debug: 4.4.3 + fb-watchman: 2.0.4 + flow-enums-runtime: 0.0.6 + graceful-fs: 4.2.11 + invariant: 2.2.4 + jest-worker: 29.7.0 + micromatch: 4.0.8 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-minify-terser@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + terser: 5.51.2 + + metro-resolver@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + + metro-runtime@0.87.1: + dependencies: + '@babel/runtime': 7.29.10 + flow-enums-runtime: 0.0.6 + + metro-source-map@0.87.1: + dependencies: + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-symbolicate: 0.87.1 + nullthrows: 1.1.1 + ob1: 0.87.1 + source-map: 0.5.7 + vlq: 1.0.1 + transitivePeerDependencies: + - supports-color + + metro-symbolicate@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + invariant: 2.2.4 + metro-source-map: 0.87.1 + nullthrows: 1.1.1 + source-map: 0.5.7 + vlq: 1.0.1 + transitivePeerDependencies: + - supports-color + + metro-transform-plugins@0.87.1: + dependencies: + '@babel/core': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10 + flow-enums-runtime: 0.0.6 + nullthrows: 1.1.1 + transitivePeerDependencies: + - supports-color + + metro-transform-worker@0.87.1: + dependencies: + '@babel/core': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.9 + '@babel/types': 7.29.8 + flow-enums-runtime: 0.0.6 + metro: 0.87.1 + metro-babel-transformer: 0.87.1 + metro-cache: 0.87.1 + metro-cache-key: 0.87.1 + metro-minify-terser: 0.87.1 + metro-source-map: 0.87.1 + metro-transform-plugins: 0.87.1 + nullthrows: 1.1.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + metro@0.87.1: + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/core': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/parser': 7.29.9 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + accepts: 2.0.0 + connect: 3.7.0 + debug: 4.4.3 + error-stack-parser: 2.1.4 + flow-enums-runtime: 0.0.6 + flow-parser: 0.331.0 + graceful-fs: 4.2.11 + invariant: 2.2.4 + jest-worker: 29.7.0 + jsc-safe-url: 0.2.4 + lodash.throttle: 4.1.1 + metro-babel-transformer: 0.87.1 + metro-cache: 0.87.1 + metro-cache-key: 0.87.1 + metro-config: 0.87.1 + metro-core: 0.87.1 + metro-file-map: 0.87.1 + metro-resolver: 0.87.1 + metro-runtime: 0.87.1 + metro-source-map: 0.87.1 + metro-symbolicate: 0.87.1 + metro-transform-plugins: 0.87.1 + metro-transform-worker: 0.87.1 + mime-types: 3.0.2 + nullthrows: 1.1.1 + serialize-error: 2.1.0 + source-map: 0.5.7 + throat: 5.0.0 + ws: 7.5.13 + yargs: 17.7.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + mimic-fn@1.2.0: {} + + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.21 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + multitars@1.0.2: {} + + nanoid@3.3.20: {} + + napi-postinstall@0.3.5: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + negotiator@1.1.0: + dependencies: + content-type: 2.1.0 + + node-exports-info@1.6.2: + dependencies: + array.prototype.flatmap: 1.3.3 + es-errors: 1.3.0 + object.entries: 1.1.9 + semver: 6.3.1 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-forge@1.4.0: {} + + node-int64@0.4.0: {} + + node-releases@2.0.59: {} + + noxcturnal@0.1.7: + dependencies: + '@babel/code-frame': 7.29.7 + '@oxc-project/types': 0.154.0 + optionalDependencies: + '@noxcturnal/noxcturnal-darwin-arm64': 0.1.7 + '@noxcturnal/noxcturnal-darwin-x64': 0.1.7 + '@noxcturnal/noxcturnal-linux-arm64-gnu': 0.1.7 + '@noxcturnal/noxcturnal-linux-arm64-musl': 0.1.7 + '@noxcturnal/noxcturnal-linux-x64-gnu': 0.1.7 + '@noxcturnal/noxcturnal-linux-x64-musl': 0.1.7 + '@noxcturnal/noxcturnal-win32-arm64-msvc': 0.1.7 + '@noxcturnal/noxcturnal-win32-x64-msvc': 0.1.7 + + npm-package-arg@11.0.3: + dependencies: + hosted-git-info: 7.0.2 + proc-log: 4.2.0 + semver: 7.8.5 + validate-npm-package-name: 5.0.1 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nullthrows@1.1.1: {} + + ob1@0.87.1: + dependencies: + flow-enums-runtime: 0.0.6 + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.1.0: {} + + onetime@2.0.1: + dependencies: + mimic-fn: 1.2.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@3.4.0: + dependencies: + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-spinners: 2.9.2 + log-symbols: 2.2.0 + strip-ansi: 5.2.0 + wcwidth: 1.0.1 + + own-keys@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-png@2.1.0: + dependencies: + pngjs: 3.4.0 + + parseurl@1.3.3: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.5.3 + minipass: 7.1.3 + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.7: {} + + plist@3.1.1: + dependencies: + '@xmldom/xmldom': 0.9.12 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + pngjs@3.4.0: {} + + possible-typed-array-names@1.1.0: {} + + postcss-value-parser@4.2.0: {} + + postcss@8.5.31: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + prelude-ls@1.2.1: {} + + prettier@3.9.10: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + proc-log@4.2.0: {} + + progress@2.0.3: {} + + promise@7.3.1: + dependencies: + asap: 2.0.6 + + promise@8.3.0: + dependencies: + asap: 2.0.6 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + punycode@2.3.1: {} + + range-parser@1.2.1: {} + + react-devtools-core@6.1.5: + dependencies: + shell-quote: 1.12.0 + ws: 7.5.13 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + react-dom@19.3.0(react@19.3.0): + dependencies: + react: 19.3.0 + scheduler: 0.28.0 + + react-fast-compare@3.2.2: {} + + react-freeze@1.0.4(react@19.3.0): + dependencies: + react: 19.3.0 + + react-i18next@17.1.0(i18next@26.5.3(typescript@6.0.3))(react-dom@19.3.0(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0)(typescript@6.0.3): + dependencies: + '@babel/runtime': 7.29.10 + html-parse-stringify: 4.0.1 + i18next: 26.5.3(typescript@6.0.3) + react: 19.3.0 + use-sync-external-store: 1.7.0(react@19.3.0) + optionalDependencies: + react-dom: 19.3.0(react@19.3.0) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + typescript: 6.0.3 + + react-is@16.13.1: {} + + react-is@18.3.1: {} + + react-is@19.3.1: {} + + react-native-drawer-layout@4.2.12(react-native-gesture-handler@3.3.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native-reanimated@4.7.1(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + color: 4.2.3 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + react-native-gesture-handler: 3.3.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-reanimated: 4.7.1(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + use-latest-callback: 0.2.6(react@19.3.0) + + react-native-gesture-handler@3.3.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + '@types/react-test-renderer': 19.3.0 + invariant: 2.2.4 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + react-native-is-edge-to-edge@1.3.1(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + react-native-reanimated@4.7.1(react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + react-native-is-edge-to-edge: 1.3.1(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + react-native-worklets: 0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + semver: 7.8.5 + + react-native-safe-area-context@5.10.1(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + react-native-screens@4.30.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + react: 19.3.0 + react-freeze: 1.0.4(react@19.3.0) + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + warn-once: 0.1.1 + + react-native-svg@15.16.0(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + css-select: 5.2.2 + css-tree: 1.1.3 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + + react-native-web@0.21.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + dependencies: + '@babel/runtime': 7.29.10 + '@react-native/normalize-colors': 0.74.89 + fbjs: 3.0.5 + inline-style-prefixer: 7.0.1 + memoize-one: 6.0.0 + nullthrows: 1.1.1 + postcss-value-parser: 4.2.0 + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + styleq: 0.1.3 + transitivePeerDependencies: + - encoding + + react-native-worklets@0.13.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0): + dependencies: + '@babel/core': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/plugin-transform-arrow-functions': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-class-properties': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-classes': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-optional-chaining': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-shorthand-properties': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-template-literals': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-unicode-regex': 7.29.7(@babel/core@7.29.7) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7) + '@babel/traverse': 7.29.10 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + '@react-native/metro-config': 0.88.0(@babel/core@7.29.7) + convert-source-map: 2.0.0 + react: 19.3.0 + react-native: 0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0) + semver: 7.8.5 + whatwg-fetch: 3.6.20 + transitivePeerDependencies: + - supports-color + + react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0): + dependencies: + '@react-native/asset-utils': 0.88.0 + '@react-native/codegen': 0.88.0(@babel/core@7.29.7) + '@react-native/community-cli-plugin': 0.88.0(@react-native/metro-config@0.88.0(@babel/core@7.29.7)) + '@react-native/gradle-plugin': 0.88.0 + '@react-native/normalize-colors': 0.88.0 + '@react-native/virtualized-lists': 0.88.0(@types/react@19.3.0)(react-native@0.88.0(@babel/core@7.29.7)(@react-native/metro-config@0.88.0(@babel/core@7.29.7))(@types/react@19.3.0)(react@19.3.0))(react@19.3.0) + anser: 1.4.10 + ansi-regex: 5.0.1 + base64-js: 1.5.1 + flow-enums-runtime: 0.0.6 + flow-parser: 0.327.0 + hermes-compiler: 260318099.0.4 + invariant: 2.2.4 + memoize-one: 5.2.1 + metro-runtime: 0.87.1 + metro-source-map: 0.87.1 + nullthrows: 1.1.1 + pretty-format: 29.7.0 + promise: 8.3.0 + react: 19.3.0 + react-devtools-core: 6.1.5 + react-refresh: 0.14.2 + regenerator-runtime: 0.13.11 + scheduler: 0.28.0 + semver: 7.8.5 + stacktrace-parser: 0.1.11 + tinyglobby: 0.2.17 + whatwg-fetch: 3.6.20 + ws: 7.5.13 + yargs: 17.7.3 + optionalDependencies: + '@types/react': 19.3.0 + transitivePeerDependencies: + - '@babel/core' + - '@react-native-community/cli' + - '@react-native/metro-config' + - bufferutil + - supports-color + - utf-8-validate + + react-refresh@0.14.2: {} + + react@19.3.0: {} + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.3.0: + dependencies: + regenerate: 1.5.0 + + regenerate@1.5.0: {} + + regenerator-runtime@0.13.11: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@6.5.3: + dependencies: + regenerate: 1.5.0 + regenerate-unicode-properties: 10.3.0 + regjsgen: 0.8.0 + regjsparser: 0.13.4 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.13.4: + dependencies: + jsesc: 3.1.0 + + require-directory@2.1.1: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve-workspace-root@2.0.1: {} + + resolve@1.22.13: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.17.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.7: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.17.0 + node-exports-info: 1.6.2 + object-keys: 1.1.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@2.0.0: + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.7 + + rtl-detect@1.1.2: {} + + safe-array-concat@1.1.4: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + sandbox-cli-detector@0.2.0: {} + + sax@1.6.1: {} + + scheduler@0.28.0: {} + + semver@6.3.1: {} + + semver@7.8.5: {} + + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serialize-error@2.1.0: {} + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + server-only@0.0.1: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + + setimmediate@1.0.5: {} + + setprototypeof@1.2.0: {} + + sf-symbols-typescript@2.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.12.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + simple-plist@1.3.1: + dependencies: + bplist-creator: 0.1.0 + bplist-parser: 0.3.1 + plist: 3.1.1 + + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + + sisteransi@1.0.5: {} + + slugify@1.6.9: {} + + source-map-js@1.2.2: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + stable-hash@0.0.5: {} + + stackframe@1.3.4: {} + + stacktrace-parser@0.1.11: + dependencies: + type-fest: 0.7.1 + + standard-navigation@0.0.5: {} + + statuses@1.5.0: {} + + statuses@2.0.2: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + stream-buffers@2.2.0: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string.prototype.matchall@4.1.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.1 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.2 + + string.prototype.trim@1.2.11: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 + + string.prototype.trimend@1.0.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + strip-ansi@5.2.0: + dependencies: + ansi-regex: 4.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@3.0.0: {} + + strip-json-comments@3.1.1: {} + + structured-headers@0.4.1: {} + + styleq@0.1.3: {} + + superjson@2.2.6: + dependencies: + copy-anything: 4.1.5 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + terser@5.51.2: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.19.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + throat@5.0.0: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toidentifier@1.0.1: {} + + toqr@0.1.1: {} + + tr46@0.0.3: {} + + ts-api-utils@2.5.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: + optional: true + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.21.3: {} + + type-fest@0.7.1: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.5: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.8: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typescript@6.0.3: {} + + ua-parser-js@0.7.41: {} + + ua-parser-js@1.0.41: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@8.9.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unpipe@1.0.0: {} + + unrs-resolver@1.12.2: + dependencies: + napi-postinstall: 0.3.5 + optionalDependencies: + '@unrs/resolver-binding-android-arm-eabi': 1.12.2 + '@unrs/resolver-binding-android-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-x64': 1.12.2 + '@unrs/resolver-binding-freebsd-x64': 1.12.2 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-arm64-musl': 1.12.2 + '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-loong64-musl': 1.12.2 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2 + '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-musl': 1.12.2 + '@unrs/resolver-binding-openharmony-arm64': 1.12.2 + '@unrs/resolver-binding-wasm32-wasi': 1.12.2 + '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2 + '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 + '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 + + update-browserslist-db@1.3.4(browserslist@4.29.4): + dependencies: + browserslist: 4.29.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + use-latest-callback@0.2.6(react@19.3.0): + dependencies: + react: 19.3.0 + + use-sync-external-store@1.7.0(react@19.3.0): + dependencies: + react: 19.3.0 + + utils-merge@1.0.1: {} + + uuid@7.0.3: {} + + validate-npm-package-name@5.0.1: {} + + vary@1.1.2: {} + + vlq@1.0.1: {} + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + warn-once@0.1.1: {} + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webidl-conversions@3.0.1: {} + + whatwg-fetch@3.6.20: {} + + whatwg-url-minimum@0.2.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.2.0 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.24 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.24: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + ws@7.5.13: {} + + ws@8.22.0: {} + + xcode@3.0.1: + dependencies: + simple-plist: 1.3.1 + uuid: 7.0.3 + + xml2js@0.6.0: + dependencies: + sax: 1.6.1 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + xmlbuilder@15.1.1: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + zod-validation-error@4.0.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} + + zustand@5.0.15(@types/react@19.3.0)(react@19.3.0)(use-sync-external-store@1.7.0(react@19.3.0)): + optionalDependencies: + '@types/react': 19.3.0 + react: 19.3.0 + use-sync-external-store: 1.7.0(react@19.3.0) diff --git a/mobile/src/app/(app)/(tabs)/(account)/_layout.tsx b/mobile/src/app/(app)/(tabs)/(account)/_layout.tsx new file mode 100644 index 0000000..bc8de2b --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(account)/_layout.tsx @@ -0,0 +1,47 @@ +import { Stack } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { + groupedScreenOptions, + opaqueHeaderOptions, + stackScreenOptions, + tabRootOptions, +} from '@/theme/navigation'; + +const AccountLayout = () => { + const { t } = useTranslation(); + + return ( + + + {/* + Modal forms: Cancel on the left, the confirm action on the right. Opaque headers, as a + transparent header in a sheet covers the top of the content on iOS. + */} + + + + ); +}; + +export default AccountLayout; diff --git a/mobile/src/app/(app)/(tabs)/(account)/account.tsx b/mobile/src/app/(app)/(tabs)/(account)/account.tsx new file mode 100644 index 0000000..1a2952c --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(account)/account.tsx @@ -0,0 +1,241 @@ +import Constants from 'expo-constants'; +import { router } from 'expo-router'; +import * as WebBrowser from 'expo-web-browser'; +import React, { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Linking, RefreshControl, ScrollView, StyleSheet, View } from 'react-native'; + +import { NotificationsSection } from '@/components/account/NotificationsSection'; +import { XLogo } from '@/components/account/XLogo'; +import { shareDataExport } from '@/components/account/downloadData'; +import { + Avatar, + ListRow, + SETTINGS_ICON_SIZE, + Section, + SettingsIcon, + Skeleton, + Spinner, + Text, + icons, + rowInset, + toast, +} from '@/components/ui'; +import { api } from '@/lib/api'; +import { API_URL } from '@/lib/config'; +import { confirmAction } from '@/lib/dialogs'; +import { useAuthStore } from '@/store/authStore'; +import { colors, spacing } from '@/theme/tokens'; + +const GITHUB_URL = 'https://github.com/oss-apps/split-pro'; +const X_URL = 'https://twitter.com/KM_Koushik_'; +const PROFILE_AVATAR_SIZE = 60; + +const openInApp = (url: string) => { + WebBrowser.openBrowserAsync(url).catch(console.warn); +}; + +/** External sites open in their own app (X, GitHub) when it's installed. */ +const openExternal = (url: string) => { + Linking.openURL(url).catch(console.warn); +}; + +const iconInset = rowInset(SETTINGS_ICON_SIZE); + +/** Port of the web's src/pages/account.tsx, laid out like the Settings app. */ +const Account = () => { + const { t } = useTranslation(); + const signOut = useAuthStore((state) => state.signOut); + const sessionUser = useAuthStore((state) => state.user); + const meQuery = api.user.me.useQuery(); + const downloadData = api.user.downloadData.useMutation(); + const [signingOut, setSigningOut] = useState(false); + const [refreshing, setRefreshing] = useState(false); + const user = meQuery.data ?? sessionUser; + const version = Constants.expoConfig?.version; + + const onRefresh = useCallback(() => { + setRefreshing(true); + meQuery.refetch().finally(() => setRefreshing(false)); + }, [meQuery]); + + const confirmSignOut = () => + confirmAction({ + title: t('account.sign_out'), + message: t('account.sign_out_confirm'), + confirmLabel: t('account.sign_out'), + cancelLabel: t('common.cancel'), + destructive: true, + onConfirm: () => { + setSigningOut(true); + signOut().catch(console.warn); + }, + }); + + const exportData = async () => { + try { + const data = await downloadData.mutateAsync(); + + if (!(await shareDataExport(data, t('account.download_data')))) { + toast.error(t('account.download_unavailable')); + } + } catch (error) { + console.warn(error); + toast.error(t('account.download_failed')); + } + }; + + const profile = user ? ( + + } + title={ + + {user.name ?? user.email} + + } + subtitle={user.name && user.email ? user.email : undefined} + accessory="chevron" + accessibilityLabel={t('account.edit_details')} + onPress={() => router.push('/edit-profile')} + /> + ) : ( + + + + + + + + ); + + return ( + // The scroll view is the screen's first view, so the large title collapses with it. + } + > +

{profile}
+ + + + {user ? ( +
+ } + title={t('account.currency')} + detail={user.currency} + /> +
+ ) : null} + +
+ } + title={t('account.feedback')} + accessory="chevron" + onPress={() => router.push('/feedback')} + /> + } + title={t('account.faq')} + accessory="chevron" + onPress={() => openInApp(`${API_URL}/faq`)} + /> + } + title={t('account.privacy')} + accessory="chevron" + onPress={() => openInApp(`${API_URL}/privacy`)} + /> + } + title={t('account.terms')} + accessory="chevron" + onPress={() => openInApp(`${API_URL}/terms`)} + /> +
+ +
+ } + title={t('account.download_data')} + right={downloadData.isLoading ? : undefined} + accessory={downloadData.isLoading ? undefined : 'chevron'} + disabled={downloadData.isLoading} + onPress={() => void exportData()} + /> + } + title={t('account.import_splitwise')} + subtitle={t('account.on_website')} + accessory="chevron" + onPress={() => openInApp(`${API_URL}/import-splitwise`)} + /> +
+ +
+ } + title={t('account.star_github')} + accessory="chevron" + onPress={() => openExternal(GITHUB_URL)} + /> + {(tint) => } + } + title={t('account.follow_x')} + accessory="chevron" + onPress={() => openExternal(X_URL)} + /> +
+ + {version ? ( +
+ +
+ ) : null} + +
+ + {t('account.sign_out')} + + } + right={signingOut ? : undefined} + disabled={signingOut} + onPress={confirmSignOut} + accessibilityLabel={t('account.sign_out')} + /> +
+ + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + paddingTop: spacing[2], + paddingBottom: spacing[8], + }, + profileLoading: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing[3], + padding: spacing[4], + }, + profileLoadingText: { + flex: 1, + gap: spacing[2], + }, +}); + +export default Account; diff --git a/mobile/src/app/(app)/(tabs)/(account)/edit-profile.tsx b/mobile/src/app/(app)/(tabs)/(account)/edit-profile.tsx new file mode 100644 index 0000000..31387d7 --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(account)/edit-profile.tsx @@ -0,0 +1,105 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ScrollView, StyleSheet, View } from 'react-native'; + +import { useCurrentUser } from '@/components/expense'; +import { Avatar, Input, ModalHeader, Section, Text, icons, toast } from '@/components/ui'; +import { api } from '@/lib/api'; +import { goBackOr, useConfirmDiscard } from '@/lib/navigation'; +import { colors, spacing } from '@/theme/tokens'; + +/** Port of the web's src/components/Account/UpdateDetails.tsx, as a modal form like Contacts' edit. */ +const EditProfile = () => { + const { t } = useTranslation(); + const user = useCurrentUser(); + const utils = api.useUtils(); + const updateDetails = api.user.updateUserDetail.useMutation(); + const savedName = user?.name ?? ''; + const [name, setName] = useState(savedName); + const trimmed = name.trim(); + const isDirty = trimmed !== savedName.trim(); + const allowClose = useConfirmDiscard(isDirty && !updateDetails.isLoading); + + const save = async () => { + if (!trimmed || !isDirty) { + return; + } + + try { + await updateDetails.mutateAsync({ name: trimmed }); + } catch (error) { + console.warn(error); + toast.error(t('account.details_failed')); + return; + } + + await utils.user.me.invalidate(); + toast.success(t('account.details_updated')); + allowClose(); + goBackOr('/account'); + }; + + return ( + // The scroll view comes first, so it scrolls under the header. + <> + + + + {user?.email ? ( + + {user.email} + + ) : null} + +
+ void save()} + accessibilityLabel={t('account.name_label')} + /> +
+
+ goBackOr('/account')} + confirm={{ + label: t('account.save'), + icon: icons.check, + disabled: !trimmed || !isDirty, + loading: updateDetails.isLoading, + onPress: () => void save(), + }} + /> + + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + profile: { + alignItems: 'center', + gap: spacing[3], + paddingTop: spacing[4], + paddingBottom: spacing[6], + }, +}); + +export default EditProfile; diff --git a/mobile/src/app/(app)/(tabs)/(account)/feedback.tsx b/mobile/src/app/(app)/(tabs)/(account)/feedback.tsx new file mode 100644 index 0000000..29b6014 --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(account)/feedback.tsx @@ -0,0 +1,94 @@ +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { ScrollView, StyleSheet } from 'react-native'; + +import { Input, ModalHeader, Section, icons, toast } from '@/components/ui'; +import { api } from '@/lib/api'; +import { goBackOr, useConfirmDiscard } from '@/lib/navigation'; +import { colors, spacing } from '@/theme/tokens'; + +/** The server's `submitFeedback` minimum. */ +const MIN_LENGTH = 10; + +/** Port of the web's src/components/Account/SubmitFeedback.tsx, as a modal form. */ +const Feedback = () => { + const { t } = useTranslation(); + const submitFeedback = api.user.submitFeedback.useMutation(); + const [feedback, setFeedback] = useState(''); + const trimmed = feedback.trim(); + const allowClose = useConfirmDiscard(0 < trimmed.length && !submitFeedback.isLoading); + + const submit = async () => { + if (MIN_LENGTH > trimmed.length) { + return; + } + + try { + await submitFeedback.mutateAsync({ feedback: trimmed }); + } catch (error) { + console.warn(error); + toast.error(t('account.feedback_failed')); + return; + } + + toast.success(t('account.feedback_sent')); + allowClose(); + goBackOr('/account'); + }; + + return ( + // The scroll view comes first, so it scrolls under the header. + <> + +
+ +
+
+ goBackOr('/account')} + confirm={{ + label: t('account.feedback_submit'), + icon: icons.sendFill, + disabled: MIN_LENGTH > trimmed.length, + loading: submitFeedback.isLoading, + onPress: () => void submit(), + }} + /> + + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + paddingTop: spacing[4], + }, + input: { + minHeight: 180, + paddingTop: spacing[3], + paddingBottom: spacing[3], + }, +}); + +export default Feedback; diff --git a/mobile/src/app/(app)/(tabs)/(activity)/_layout.tsx b/mobile/src/app/(app)/(tabs)/(activity)/_layout.tsx new file mode 100644 index 0000000..20a4f4d --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(activity)/_layout.tsx @@ -0,0 +1,17 @@ +import { Stack } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { stackScreenOptions, tabRootOptions } from '@/theme/navigation'; + +const ActivityLayout = () => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +export default ActivityLayout; diff --git a/mobile/src/app/(app)/(tabs)/(activity)/activity.tsx b/mobile/src/app/(app)/(tabs)/(activity)/activity.tsx new file mode 100644 index 0000000..bbe2f6e --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(activity)/activity.tsx @@ -0,0 +1,184 @@ +import { isSameDay, isToday, isYesterday } from 'date-fns'; +import { Stack } from 'expo-router'; +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RefreshControl, SectionList, StyleSheet, View } from 'react-native'; + +import { formatShortDate } from '~/utils/dates'; + +import { type ActivityEntry, ActivityItem } from '@/components/activity/ActivityItem'; +import { AddExpenseAction, EXPENSE_ICON_SIZE, useCurrentUser } from '@/components/expense'; +import { + EmptyState, + FullScreenSpinner, + InsetStickyHeader, + Separator, + Text, + icons, + rowInset, +} from '@/components/ui'; +import { getDeviceLocale } from '@/i18n'; +import { api } from '@/lib/api'; +import { colors, layout, spacing } from '@/theme/tokens'; + +type ActivitySection = { key: string; title: string; data: ActivityEntry[] }; + +const matches = (entry: ActivityEntry, query: string) => { + const { expense } = entry; + return [ + expense.name, + expense.group?.name, + expense.paidByUser.name, + expense.paidByUser.email, + expense.deletedByUser?.name, + ].some((value) => value?.toLocaleLowerCase().includes(query)); +}; + +/** + * Port of the web's src/pages/activity.tsx: every expense the user is part of, newest first, + * grouped by the day it was added under sticky headers, like Mail. The API returns the whole + * list, so there's no paging and search filters on the device. + */ +const Activity = () => { + const { t } = useTranslation(); + const user = useCurrentUser(); + const expensesQuery = api.user.getAllExpenses.useQuery(); + const [refreshing, setRefreshing] = useState(false); + const [search, setSearch] = useState(''); + const [isSearching, setIsSearching] = useState(false); + const query = search.trim().toLocaleLowerCase(); + + const onRefresh = useCallback(() => { + setRefreshing(true); + expensesQuery.refetch().finally(() => setRefreshing(false)); + }, [expensesQuery]); + + const sections = useMemo(() => { + const now = new Date(); + const dayTitle = (date: Date) => { + if (isToday(date)) { + return t('activity.today'); + } + + if (isYesterday(date)) { + return t('activity.yesterday'); + } + + return formatShortDate(date, now, getDeviceLocale()); + }; + const entries = expensesQuery.data ?? []; + const filtered = query ? entries.filter((entry) => matches(entry, query)) : entries; + + return filtered.reduce((result, entry) => { + const { createdAt } = entry.expense; + const last = result[result.length - 1]; + + if (last && last.data[0] && isSameDay(last.data[0].expense.createdAt, createdAt)) { + last.data.push(entry); + return result; + } + + result.push({ key: createdAt.toISOString(), title: dayTitle(createdAt), data: [entry] }); + return result; + }, []); + }, [expensesQuery.data, query, t]); + + const empty = (() => { + if (expensesQuery.isLoading || !user) { + return ; + } + + if (expensesQuery.isError) { + return ( + void expensesQuery.refetch()} + /> + ); + } + + if (query) { + return ( + + ); + } + + return ; + })(); + + return ( + // No wrapping view: the list must be the screen's first view for the large title to collapse. + <> + entry.expenseId} + // Scrolls under the transparent header and collapses the large title. + contentInsetAdjustmentBehavior="automatic" + keyboardDismissMode="on-drag" + style={styles.screen} + // InsetStickyHeader pins below the navigation bar, which the search bar hides while it's + // active; results scroll with their headers instead, like Mail's. + stickySectionHeadersEnabled={!isSearching} + StickyHeaderComponent={InsetStickyHeader} + renderSectionHeader={({ section }) => ( + + + {section.title} + + + )} + renderItem={({ item }) => + user ? ( + + ) : null + } + ItemSeparatorComponent={() => } + ListEmptyComponent={empty} + contentContainerStyle={sections.length ? styles.list : styles.emptyList} + refreshControl={} + /> + setSearch(event.nativeEvent.text)} + onFocus={() => setIsSearching(true)} + onCancelButtonPress={() => { + setSearch(''); + setIsSearching(false); + }} + /> + + + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.background, + }, + list: { + paddingBottom: spacing[12], + }, + emptyList: { + flexGrow: 1, + }, + sectionHeader: { + backgroundColor: colors.background, + paddingHorizontal: layout.rowPadding, + paddingTop: spacing[4], + paddingBottom: spacing[2], + }, +}); + +export default Activity; diff --git a/mobile/src/app/(app)/(tabs)/(balances)/_layout.tsx b/mobile/src/app/(app)/(tabs)/(balances)/_layout.tsx new file mode 100644 index 0000000..3b9579d --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(balances)/_layout.tsx @@ -0,0 +1,17 @@ +import { Stack } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { stackScreenOptions, tabRootOptions } from '@/theme/navigation'; + +const BalancesLayout = () => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +export default BalancesLayout; diff --git a/mobile/src/app/(app)/(tabs)/(balances)/balances.tsx b/mobile/src/app/(app)/(tabs)/(balances)/balances.tsx new file mode 100644 index 0000000..e690b50 --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(balances)/balances.tsx @@ -0,0 +1,122 @@ +import { router } from 'expo-router'; +import React, { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlatList, RefreshControl, Share, StyleSheet } from 'react-native'; + +import { AddExpenseAction } from '@/components/expense'; +import { BalanceTotals } from '@/components/friend/BalanceTotals'; +import { FriendBalanceRow } from '@/components/friend/FriendBalanceRow'; +import { EmptyState, FullScreenSpinner, Separator, icons, rowInset } from '@/components/ui'; +import { api } from '@/lib/api'; +import { API_URL } from '@/lib/config'; +import { colors, layout, spacing } from '@/theme/tokens'; + +/** Port of the web's src/pages/balances.tsx: totals, then one row per friend with a balance. */ +const Balances = () => { + const { t } = useTranslation(); + const balanceQuery = api.user.getBalances.useQuery(); + const [refreshing, setRefreshing] = useState(false); + + const onRefresh = useCallback(() => { + setRefreshing(true); + balanceQuery.refetch().finally(() => setRefreshing(false)); + }, [balanceQuery]); + + const shareApp = useCallback(() => { + Share.share({ + title: t('balances.share_title'), + message: `${t('balances.share_message')} ${API_URL}`, + url: API_URL, + }).catch(console.warn); + }, [t]); + + const data = balanceQuery.data; + + const empty = (() => { + if (balanceQuery.isLoading) { + return ; + } + + if (balanceQuery.isError || !data) { + return ( + void balanceQuery.refetch()} + /> + ); + } + + return ( + router.push('/add')} + /> + ); + })(); + + // The list is always rendered, also while loading: the navigation bar tracks the scroll view + // it finds when the screen appears, to collapse the large title. + const body = ( + String(item.friendId)} + // Scrolls under the transparent header and collapses the large title. + contentInsetAdjustmentBehavior="automatic" + style={styles.screen} + renderItem={({ item }) => ( + + router.push({ + pathname: '/balances/[friendId]', + params: { friendId: String(item.friendId) }, + }) + } + /> + )} + ItemSeparatorComponent={() => } + ListHeaderComponent={ + data ? : undefined + } + ListEmptyComponent={empty} + contentContainerStyle={data?.balances.length ? styles.list : styles.emptyList} + refreshControl={} + /> + ); + + return ( + // No wrapping view: the list must be the screen's first view for the large title to collapse. + <> + {body} + + + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.background, + }, + list: { + paddingBottom: spacing[12], + }, + emptyList: { + flexGrow: 1, + }, +}); + +export default Balances; diff --git a/mobile/src/app/(app)/(tabs)/(groups)/_layout.tsx b/mobile/src/app/(app)/(tabs)/(groups)/_layout.tsx new file mode 100644 index 0000000..da534c3 --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(groups)/_layout.tsx @@ -0,0 +1,17 @@ +import { Stack } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { stackScreenOptions, tabRootOptions } from '@/theme/navigation'; + +const GroupsLayout = () => { + const { t } = useTranslation(); + + return ( + + + + ); +}; + +export default GroupsLayout; diff --git a/mobile/src/app/(app)/(tabs)/(groups)/groups.tsx b/mobile/src/app/(app)/(tabs)/(groups)/groups.tsx new file mode 100644 index 0000000..c26211f --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/(groups)/groups.tsx @@ -0,0 +1,96 @@ +import { router } from 'expo-router'; +import React, { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlatList, RefreshControl, StyleSheet } from 'react-native'; + +import { AddExpenseAction } from '@/components/expense'; +import { GroupBalanceRow } from '@/components/group/GroupBalanceRow'; +import { EmptyState, FullScreenSpinner, Separator, icons, rowInset } from '@/components/ui'; +import { api } from '@/lib/api'; +import { colors, layout, spacing } from '@/theme/tokens'; + +const openCreateGroup = () => router.push('/groups/new'); + +/** Every group you're in with your balance in it, like the web's src/pages/groups.tsx. */ +const Groups = () => { + const { t } = useTranslation(); + const groupsQuery = api.group.getAllGroupsWithBalances.useQuery(); + const [refreshing, setRefreshing] = useState(false); + + const onRefresh = useCallback(() => { + setRefreshing(true); + groupsQuery.refetch().finally(() => setRefreshing(false)); + }, [groupsQuery]); + + const groups = groupsQuery.data ?? []; + + const empty = (() => { + if (groupsQuery.isLoading) { + return ; + } + + if (groupsQuery.isError && !groupsQuery.data) { + return ( + void groupsQuery.refetch()} + /> + ); + } + + return ( + + ); + })(); + + return ( + // No wrapping view: the list must be the screen's first view for the large title to collapse. + <> + String(group.id)} + // Scrolls under the transparent header and collapses the large title. + contentInsetAdjustmentBehavior="automatic" + style={styles.screen} + renderItem={({ item }) => } + ItemSeparatorComponent={() => } + ListEmptyComponent={empty} + contentContainerStyle={groups.length ? styles.list : styles.emptyList} + refreshControl={} + /> + + + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.background, + }, + list: { + paddingBottom: spacing[12], + }, + emptyList: { + flexGrow: 1, + }, +}); + +export default Groups; diff --git a/mobile/src/app/(app)/(tabs)/_layout.tsx b/mobile/src/app/(app)/(tabs)/_layout.tsx new file mode 100644 index 0000000..baf1c9b --- /dev/null +++ b/mobile/src/app/(app)/(tabs)/_layout.tsx @@ -0,0 +1,47 @@ +import { NativeTabs } from 'expo-router/native-tabs'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { icons } from '@/components/ui'; +import { colors } from '@/theme/tokens'; + +/** + * The system tab bar: UITabBar on iOS (Liquid Glass on iOS 26), Material navigation bar on + * Android. Each tab is a group with its own native stack, for the large-title header. "Add expense" + * isn't a tab: it's the "+" in each tab's navigation bar (a FAB on Android), see AddExpenseAction. + */ +const TabsLayout = () => { + const { t } = useTranslation(); + + return ( + + + + {t('tabs.balances')} + + + + {t('tabs.groups')} + + + + {t('tabs.activity')} + + + + {t('tabs.account')} + + + ); +}; + +export default TabsLayout; diff --git a/mobile/src/app/(app)/_layout.tsx b/mobile/src/app/(app)/_layout.tsx new file mode 100644 index 0000000..6d3dc95 --- /dev/null +++ b/mobile/src/app/(app)/_layout.tsx @@ -0,0 +1,83 @@ +import { Stack } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; + +import { useOpenPendingLink } from '@/providers/usePendingLink'; +import { usePushNotifications } from '@/providers/usePushNotifications'; +import { groupedScreenOptions, stackScreenOptions } from '@/theme/navigation'; + +// A screen opened from a link at launch still has the tabs to go back to. +export const unstable_settings = { + anchor: '(tabs)', +}; + +/** Signed-in screens: the tabs plus every detail screen and modal pushed on top of them. */ +const AppLayout = () => { + const { t } = useTranslation(); + usePushNotifications(); + useOpenPendingLink(); + + return ( + + + + + + + + + + + + + + + ); +}; + +export default AppLayout; diff --git a/mobile/src/app/(app)/add.tsx b/mobile/src/app/(app)/add.tsx new file mode 100644 index 0000000..e222aaa --- /dev/null +++ b/mobile/src/app/(app)/add.tsx @@ -0,0 +1,272 @@ +import { Stack, router, useLocalSearchParams } from 'expo-router'; +import { useHeaderHeight } from 'expo-router/react-navigation'; +import React, { useEffect, useId } from 'react'; +import { useTranslation } from 'react-i18next'; +import { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, View } from 'react-native'; +import { create } from 'zustand'; + +import { AddExpenseForm } from '@/components/add-expense/AddExpenseForm'; +import { getFormSnapshot } from '@/components/add-expense/formChanges'; +import { useSaveExpense } from '@/components/add-expense/useSaveExpense'; +import { EmptyState, ModalHeader, Spinner, icons } from '@/components/ui'; +import { api } from '@/lib/api'; +import { goBackOr, useConfirmDiscard } from '@/lib/navigation'; +import { getEditFormState, isCurrentForm, useAddExpenseStore } from '@/store/addExpenseStore'; +import { colors, spacing } from '@/theme/tokens'; + +// Refetching these would re-seed the form and wipe what the user entered, e.g. after switching apps. +const SEED_QUERY_OPTIONS = { refetchOnWindowFocus: false, refetchOnReconnect: false } as const; + +type SeedKey = 'group' | 'friend' | 'expense'; + +/** + * One add or edit form: the screen that opened it, the generation it belongs to, which requested + * seeds have loaded, and the form once they all have (to tell whether it was changed). + */ +type FormSeeds = { + owner: string; + formKey: string; + generation: number; + seeded?: string; +} & Record; + +/** The open form's seeds. Kept outside React state: seeding syncs it with the form store. */ +const useFormSeeds = create<{ form: FormSeeds | null }>()(() => ({ form: null })); +const withSeededSnapshot = (form: FormSeeds | null) => + form && form.group && form.friend && form.expense && undefined === form.seeded + ? { ...form, seeded: getFormSnapshot(useAddExpenseStore.getState()) } + : form; +const setForm = (update: (current: FormSeeds | null) => FormSeeds | null) => + useFormSeeds.setState((state) => ({ form: withSeededSnapshot(update(state.form)) })); + +/** + * Add/edit expense modal. Params match the web's /add: `friendId` or `groupId` to preselect who + * it's with, `expenseId` to edit. Seeding follows the web's src/pages/add.tsx: each requested seed + * is applied once, to the form it was requested for. + */ +const AddExpense = () => { + const { t } = useTranslation(); + const params = useLocalSearchParams<{ + friendId?: string; + groupId?: string; + expenseId?: string; + }>(); + const groupId = parseInt(params.groupId ?? '', 10) || 0; + const friendId = parseInt(params.friendId ?? '', 10) || 0; + const expenseId = params.expenseId || undefined; + const formKey = [expenseId, params.groupId, params.friendId] + .map((value) => value ?? '') + .join('|'); + + const { setCurrentUser, selectGroup, setParticipants, resetState } = useAddExpenseStore( + (s) => s.actions, + ); + const currentUser = useAddExpenseStore((s) => s.currentUser); + const meQuery = api.user.me.useQuery(undefined, SEED_QUERY_OPTIONS); + const me = meQuery.data; + + // Another add screen can mount before this one unmounts, e.g. "Add new" after an error. + const owner = useId(); + const form = useFormSeeds((state) => state.form); + const isCurrentKey = form?.owner === owner && form.formKey === formKey; + const isFormReady = !!form && isCurrentKey && form.group && form.friend && form.expense; + + // Start from a clean form for every add or edit form, once we know who is adding it. + useEffect(() => { + if (!me) { + return; + } + + setCurrentUser({ + id: me.id, + currency: me.currency, + emailVerified: null, + name: me.name ?? null, + email: me.email ?? null, + image: me.image ?? null, + }); + resetState(); + setForm(() => ({ + owner, + formKey, + generation: useAddExpenseStore.getState().formGeneration, + group: !groupId, + friend: !friendId, + expense: !expenseId, + })); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [formKey, me?.id]); + + useEffect( + () => () => { + if (useFormSeeds.getState().form?.owner !== owner) { + return; + } + + resetState(); + setForm(() => null); + }, + [owner, resetState], + ); + + const canSeed = (key: SeedKey) => + !!form && isCurrentKey && !form[key] && isCurrentForm(form.generation) && !!currentUser; + const markSeeded = (key: SeedKey) => + setForm((current) => + current?.owner === owner && current.formKey === formKey + ? { ...current, [key]: true } + : current, + ); + + const groupQuery = api.group.getGroupDetails.useQuery( + { groupId }, + { enabled: !!groupId, ...SEED_QUERY_OPTIONS }, + ); + const friendQuery = api.user.getFriend.useQuery( + { friendId }, + { enabled: !!friendId, ...SEED_QUERY_OPTIONS }, + ); + const expenseQuery = api.user.getExpenseDetails.useQuery( + { expenseId: expenseId ?? '' }, + { enabled: !!expenseId, ...SEED_QUERY_OPTIONS }, + ); + + const hasSeedError = + meQuery.isError || + (!!groupId && (groupQuery.isError || null === groupQuery.data)) || + (!!friendId && (friendQuery.isError || null === friendQuery.data)) || + (!!expenseId && expenseQuery.isError); + + useEffect(() => { + const group = groupQuery.data; + if (!canSeed('group') || !currentUser || group?.id !== groupId) { + return; + } + + selectGroup( + group, + group.groupUsers.map((groupUser) => groupUser.user), + ); + useAddExpenseStore.setState({ showFriends: false }); + markSeeded('group'); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [form, groupQuery.data, currentUser]); + + useEffect(() => { + const friend = friendQuery.data; + if (!canSeed('friend') || !currentUser || friend?.id !== friendId) { + return; + } + + setParticipants([currentUser, friend]); + useAddExpenseStore.setState({ showFriends: false }); + markSeeded('friend'); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [form, friendQuery.data, currentUser]); + + useEffect(() => { + const expense = expenseQuery.data; + if (!canSeed('expense') || !expense || expense.id !== expenseId) { + return; + } + + useAddExpenseStore.setState(getEditFormState(expense)); + markSeeded('expense'); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [form, expenseQuery.data, currentUser]); + + const isReady = !!currentUser && isFormReady; + const snapshot = useAddExpenseStore(getFormSnapshot); + const allowClose = useConfirmDiscard(isReady && snapshot !== form?.seeded); + const { save, isSaving, isSaveDisabled, isAmountTooLarge } = useSaveExpense( + expenseId, + allowClose, + ); + + const close = () => goBackOr(); + // Android's header is opaque, so only iOS content starts under it. + const headerHeight = useHeaderHeight(); + const headerInset = 'ios' === Platform.OS ? headerHeight : 0; + + const content = ( + + {isReady ? ( + + ) : hasSeedError ? ( + router.replace('/add')} + /> + ) : ( + + + + )} + + ); + + return ( + <> + {'android' === Platform.OS ? ( + // Edge to edge, the window doesn't resize for the keyboard. iOS insets the scroll view. + + {content} + + ) : ( + content + )} + + + + ); +}; + +const styles = StyleSheet.create({ + fill: { + flex: 1, + }, + screen: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + flexGrow: 1, + paddingBottom: spacing[8], + }, + loading: { + alignItems: 'center', + paddingTop: spacing[12] * 2, + }, +}); + +export default AddExpense; diff --git a/mobile/src/app/(app)/balances/[friendId].tsx b/mobile/src/app/(app)/balances/[friendId].tsx new file mode 100644 index 0000000..5f6124a --- /dev/null +++ b/mobile/src/app/(app)/balances/[friendId].tsx @@ -0,0 +1,317 @@ +import { Stack, router, useLocalSearchParams } from 'expo-router'; +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RefreshControl, SectionList, StyleSheet, View } from 'react-native'; + +import { isNewMonth } from '~/utils/dates'; +import { getNetWithFriend, hasShareWithFriend } from '~/utils/expenseLabels'; +import { getSettleableCurrencies } from '~/utils/settleUp'; + +import { + EXPENSE_ICON_SIZE, + ExpenseListItem, + MonthHeader, + useCurrentUser, +} from '@/components/expense'; +import { buildFriendExpensesCsv, shareCsv } from '@/components/friend/exportCsv'; +import { BalanceBreakdown, FriendSummary } from '@/components/friend/FriendSummary'; +import { + EmptyState, + FullScreenSpinner, + HeaderActions, + QuickActions, + Screen, + SectionCell, + icons, + rowInset, + toast, +} from '@/components/ui'; +import { api } from '@/lib/api'; +import { confirmAction, showMessage } from '@/lib/dialogs'; +import { goBackOr } from '@/lib/navigation'; +import { colors, spacing } from '@/theme/tokens'; + +/** Port of the web's src/pages/balances/[friendId].tsx. */ +const FriendBalance = () => { + const { t } = useTranslation(); + const params = useLocalSearchParams<{ friendId: string }>(); + const friendId = Number(params.friendId); + const enabled = Number.isInteger(friendId) && 0 < friendId; + const currentUser = useCurrentUser(); + const utils = api.useUtils(); + + const friendQuery = api.user.getFriend.useQuery({ friendId }, { enabled }); + const expensesQuery = api.user.getExpensesWithFriend.useQuery({ friendId }, { enabled }); + const balancesQuery = api.user.getBalancesWithFriend.useQuery({ friendId }, { enabled }); + const breakdownQuery = api.user.getBalanceBreakdownWithFriend.useQuery({ friendId }, { enabled }); + const deleteFriendMutation = api.user.deleteFriend.useMutation(); + + const [refreshing, setRefreshing] = useState(false); + const [exporting, setExporting] = useState(false); + + const friend = friendQuery.data; + const friendName = friend?.name ?? friend?.email ?? ''; + const expenses = useMemo(() => expensesQuery.data ?? [], [expensesQuery.data]); + const balances = balancesQuery.data ?? []; + // The export keeps every expense; the list skips those where neither owes the other anything. + const listedExpenses = useMemo( + () => + currentUser + ? expenses.filter((expense) => hasShareWithFriend(expense, currentUser.id, friendId)) + : [], + [currentUser, expenses, friendId], + ); + // One inset-grouped section per month, like a statement. + const sections = useMemo( + () => + listedExpenses.reduce<{ key: string; date: Date; data: typeof listedExpenses }[]>( + (result, expense, index) => { + const previous = listedExpenses[index - 1]; + const last = result[result.length - 1]; + + if (!last || isNewMonth(expense.expenseDate, previous?.expenseDate)) { + result.push({ key: expense.id, date: expense.expenseDate, data: [expense] }); + } else { + last.data.push(expense); + } + + return result; + }, + [], + ), + [listedExpenses], + ); + const canSettle = 0 < getSettleableCurrencies(breakdownQuery.data ?? []).length; + + const onRefresh = useCallback(() => { + setRefreshing(true); + Promise.all([ + friendQuery.refetch(), + expensesQuery.refetch(), + balancesQuery.refetch(), + breakdownQuery.refetch(), + ]).finally(() => setRefreshing(false)); + }, [friendQuery, expensesQuery, balancesQuery, breakdownQuery]); + + const removeFriend = useCallback(async () => { + try { + await deleteFriendMutation.mutateAsync({ friendId }); + } catch (error) { + toast.error(error instanceof Error ? error.message : t('balances.friend.remove_failed')); + return; + } + + toast.success(t('balances.friend.removed', { name: friendName })); + utils.user.invalidate().catch(console.error); + goBackOr(); + }, [deleteFriendMutation, friendId, friendName, t, utils]); + + const confirmRemove = useCallback(() => { + // Same rule as the server: only friends without outstanding balances can be removed. + if (balances.length) { + showMessage( + t('balances.friend.remove_blocked_title'), + t('balances.friend.remove_blocked'), + t('balances.ok'), + ); + return; + } + + confirmAction({ + title: t('balances.friend.remove_confirm_title'), + message: t('balances.friend.remove_confirm', { name: friendName }), + confirmLabel: t('balances.friend.remove_action'), + cancelLabel: t('common.cancel'), + destructive: true, + onConfirm: () => void removeFriend(), + }); + }, [balances.length, friendName, removeFriend, t]); + + const exportExpenses = useCallback(async () => { + if (!currentUser) { + return; + } + + setExporting(true); + try { + const csv = buildFriendExpensesCsv({ + expenses, + currentUserId: currentUser.id, + friendId, + friendName, + }); + const shared = await shareCsv( + csv, + t('balances.friend.export_file_name', { name: friendName }), + t('balances.friend.export_title', { name: friendName }), + ); + if (!shared) { + toast.error(t('balances.friend.export_unavailable')); + } + } catch (error) { + console.error(error); + toast.error(t('balances.friend.export_failed')); + } finally { + setExporting(false); + } + }, [currentUser, expenses, friendId, friendName, t]); + + const header = ( + <> + + {friend ? ( + + ) : null} + + ); + + const isLoading = + friendQuery.isLoading || expensesQuery.isLoading || balancesQuery.isLoading || !currentUser; + + if (!enabled || (!isLoading && !friendQuery.isError && !friend)) { + return ( + + {header} + + + ); + } + + if (friendQuery.isError || expensesQuery.isError || balancesQuery.isError) { + return ( + + {header} + + + ); + } + + if (isLoading || !friend || !currentUser) { + return ( + <> + {header} + + + ); + } + + return ( + <> + {header} + expense.id} + // Scrolls under the transparent header. + contentInsetAdjustmentBehavior="automatic" + stickySectionHeadersEnabled={false} + renderSectionHeader={({ section }) => } + renderItem={({ item, index, section }) => ( + + + + )} + ListHeaderComponent={ + + + + + router.push({ + pathname: '/settle-up', + params: { friendId: String(friendId) }, + }), + }, + { + label: t('balances.friend.add_expense'), + icon: icons.add, + onPress: () => + router.push({ pathname: '/add', params: { friendId: String(friendId) } }), + }, + { + label: t('balances.friend.export'), + icon: icons.export, + disabled: !expenses.length, + loading: exporting, + onPress: () => void exportExpenses(), + }, + ]} + /> + + {breakdownQuery.data ? : null} + + } + ListEmptyComponent={ + + } + contentContainerStyle={styles.content} + refreshControl={} + /> + + ); +}; + +const styles = StyleSheet.create({ + list: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + paddingBottom: spacing[12], + }, + header: { + gap: spacing[5], + paddingTop: spacing[2], + paddingBottom: spacing[2], + }, + actions: { + paddingHorizontal: spacing[4], + }, +}); + +export default FriendBalance; diff --git a/mobile/src/app/(app)/expenses/[expenseId].tsx b/mobile/src/app/(app)/expenses/[expenseId].tsx new file mode 100644 index 0000000..1f295ad --- /dev/null +++ b/mobile/src/app/(app)/expenses/[expenseId].tsx @@ -0,0 +1,155 @@ +import { router, useLocalSearchParams } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { RefreshControl, ScrollView, StyleSheet } from 'react-native'; + +import { ExpenseDetails } from '@/components/expense-detail/ExpenseDetails'; +import { canDeleteExpense, canEditExpense } from '@/components/expense-detail/expenseDetail'; +import { + EmptyState, + FullScreenSpinner, + type HeaderAction, + HeaderActions, + icons, + toast, +} from '@/components/ui'; +import { api } from '@/lib/api'; +import { confirmAction } from '@/lib/dialogs'; +import { haptics } from '@/lib/haptics'; +import { goBackOr } from '@/lib/navigation'; +import { colors } from '@/theme/tokens'; + +/** + * Expense details for group and non-group expenses, like the web's /expenses/[expenseId] and + * /groups/[groupId]/expenses/[expenseId]. `user.getExpenseDetails` lets group members see any + * expense of their group, so the optional `groupId` param isn't needed to load it. + */ +const ExpenseDetail = () => { + const { t } = useTranslation(); + const { expenseId } = useLocalSearchParams<{ expenseId: string; groupId?: string }>(); + const utils = api.useUtils(); + const meQuery = api.user.me.useQuery(); + const expenseQuery = api.user.getExpenseDetails.useQuery({ expenseId }); + const deleteMutation = api.user.deleteExpense.useMutation(); + + const expense = expenseQuery.data; + const userId = meQuery.data?.id; + const canEdit = !!expense && canEditExpense(expense); + const canDelete = !!expense && undefined !== userId && canDeleteExpense(expense, userId); + + const onDelete = () => { + haptics.warning(); + confirmAction({ + destructive: true, + title: t('expense.detail.delete_title'), + message: t('expense.detail.delete_message'), + confirmLabel: t('expense.detail.delete_confirm'), + cancelLabel: t('common.cancel'), + onConfirm: () => + deleteMutation.mutate( + { expenseId }, + { + onSuccess: () => { + Promise.all([ + utils.user.invalidate(), + utils.group.invalidate(), + utils.recurring.invalidate(), + ]).catch(console.error); + toast.success(t('expense.detail.deleted')); + goBackOr(); + }, + onError: (error) => toast.error(error.message || t('expense.detail.delete_failed')), + }, + ), + }); + }; + + const actions: HeaderAction[] = [ + ...(canEdit + ? [ + { + label: t('expense.detail.edit'), + icon: icons.edit, + onPress: () => router.push({ pathname: '/add', params: { expenseId } }), + }, + ] + : []), + ...(canDelete + ? [ + { + label: t('common.more'), + icon: icons.more, + loading: deleteMutation.isLoading, + menu: [ + { + label: t('expense.detail.delete'), + icon: icons.trash, + destructive: true, + onPress: onDelete, + }, + ], + }, + ] + : []), + ]; + + const isNotFound = 'NOT_FOUND' === expenseQuery.error?.data?.code; + + const content = (() => { + if (expense && undefined !== userId) { + return ; + } + + if (expenseQuery.isError) { + return isNotFound ? ( + + ) : ( + void expenseQuery.refetch()} + /> + ); + } + + return ; + })(); + + return ( + <> + {/* Scrolls under the transparent header (overrides the layout's opaque header) */} + void expenseQuery.refetch()} + /> + } + > + {content} + + {actions.length ? : null} + + ); +}; + +const styles = StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + flexGrow: 1, + }, +}); + +export default ExpenseDetail; diff --git a/mobile/src/app/(app)/groups/[groupId].tsx b/mobile/src/app/(app)/groups/[groupId].tsx new file mode 100644 index 0000000..ce90bf7 --- /dev/null +++ b/mobile/src/app/(app)/groups/[groupId].tsx @@ -0,0 +1,301 @@ +import { Stack, router, useIsPreview } from 'expo-router'; +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RefreshControl, SectionList, StyleSheet, View } from 'react-native'; + +import { isNewMonth } from '~/utils/dates'; +import { getNetForUser } from '~/utils/expenseLabels'; + +import { + EXPENSE_ICON_SIZE, + ExpenseListItem, + MonthHeader, + useCurrentUser, +} from '@/components/expense'; +import { GroupStatsSheet } from '@/components/group/GroupStatsSheet'; +import { GroupBalances, GroupSummary } from '@/components/group/GroupSummary'; +import { NoMembers } from '@/components/group/NoMembers'; +import { shareInviteLink } from '@/components/group/invite'; +import { + retryGroupQuery, + useGroupDetails, + useGroupIdParam, +} from '@/components/group/useGroupDetails'; +import { useGroupExit } from '@/components/group/useGroupExit'; +import { + EmptyState, + FullScreenSpinner, + HeaderActions, + QuickActions, + Screen, + SectionCell, + Spinner, + icons, + rowInset, +} from '@/components/ui'; +import { type RouterOutputs, api } from '@/lib/api'; +import { colors, spacing } from '@/theme/tokens'; + +type Expense = RouterOutputs['group']['getExpenses'][number]; + +/** A group's balances and expenses, like the web's src/pages/groups/[groupId].tsx. */ +const GroupDetail = () => { + const { t } = useTranslation(); + const groupId = useGroupIdParam(); + const user = useCurrentUser(); + const [statsOpen, setStatsOpen] = useState(false); + const [refreshing, setRefreshing] = useState(false); + + const { query: groupQuery, group, notFound } = useGroupDetails(groupId); + const expensesQuery = api.group.getExpenses.useQuery( + { groupId }, + { enabled: Number.isInteger(groupId), retry: retryGroupQuery }, + ); + const exit = useGroupExit(group, user?.id); + // A long-pressed row in the Groups tab shows this screen as a preview, which has no header. + const isPreview = useIsPreview(); + + const expenses = useMemo(() => expensesQuery.data ?? [], [expensesQuery.data]); + // One inset-grouped section per month, like a statement. + const sections = useMemo( + () => + expenses.reduce<{ key: string; date: Date; data: Expense[] }[]>((result, expense, index) => { + const previous = expenses[index - 1]; + const last = result[result.length - 1]; + + if (!last || isNewMonth(expense.expenseDate, previous?.expenseDate)) { + result.push({ key: expense.id, date: expense.expenseDate, data: [expense] }); + } else { + last.data.push(expense); + } + + return result; + }, []), + [expenses], + ); + + const onRefresh = useCallback(() => { + setRefreshing(true); + Promise.all([groupQuery.refetch(), expensesQuery.refetch()]).finally(() => + setRefreshing(false), + ); + }, [groupQuery, expensesQuery]); + + const params = { groupId: String(groupId) }; + + const header = isPreview ? null : ( + <> + + {group ? ( + router.push({ pathname: '/groups/[groupId]/info', params }), + }, + { + label: t('groups.stats'), + icon: icons.stats, + onPress: () => setStatsOpen(true), + }, + { + label: t('groups.add_members'), + icon: icons.groupAdd, + onPress: () => router.push({ pathname: '/groups/[groupId]/add-members', params }), + }, + { + label: t('groups.share_invite_link'), + icon: icons.share, + onPress: () => void shareInviteLink(group, t), + }, + { + items: [ + { + label: exit.label, + icon: exit.icon, + destructive: true, + onPress: exit.onPress, + }, + ], + }, + ], + }, + ]} + /> + ) : null} + + ); + + if (notFound || (!group && groupQuery.isError)) { + return ( + + {header} + + + ); + } + + if (!group || !user) { + return ( + <> + {header} + + + ); + } + + const members = group.groupUsers.map((groupUser) => groupUser.user); + const hasNoMembers = + 1 === group.groupUsers.length && !expensesQuery.isLoading && !expenses.length; + + const listHeader = ( + + + + router.push({ pathname: '/add', params }), + }, + { + label: t('groups.settle_up'), + icon: icons.settle, + onPress: () => router.push({ pathname: '/settle-up', params }), + }, + { + label: t('groups.invite'), + icon: icons.share, + onPress: () => void shareInviteLink(group, t), + }, + ]} + /> + + {/* One child each, so the header's `gap` doesn't add to the sections' own spacing */} + + {hasNoMembers ? : null} + + + + ); + + const empty = (() => { + if (hasNoMembers) { + return null; + } + + if (expensesQuery.isLoading) { + return ( + + + + ); + } + + if (expensesQuery.isError) { + return ( + void expensesQuery.refetch()} + /> + ); + } + + return ( + router.push({ pathname: '/add', params })} + /> + ); + })(); + + return ( + <> + {header} + expense.id} + // Scrolls under the transparent header. + contentInsetAdjustmentBehavior="automatic" + stickySectionHeadersEnabled={false} + renderSectionHeader={({ section }) => } + renderItem={({ item, index, section }) => ( + + participant.userId !== item.paidBy, + )?.user + : undefined + } + net={getNetForUser(item, user.id)} + /> + + )} + ListHeaderComponent={listHeader} + ListEmptyComponent={empty ?? undefined} + contentContainerStyle={styles.content} + refreshControl={} + /> + setStatsOpen(false)} + /> + + ); +}; + +const styles = StyleSheet.create({ + list: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + flexGrow: 1, + paddingBottom: spacing[12], + }, + header: { + gap: spacing[5], + paddingTop: spacing[2], + paddingBottom: spacing[2], + }, + actions: { + paddingHorizontal: spacing[4], + }, + loading: { + paddingVertical: spacing[8], + alignItems: 'center', + }, +}); + +export default GroupDetail; diff --git a/mobile/src/app/(app)/groups/[groupId]/add-members.tsx b/mobile/src/app/(app)/groups/[groupId]/add-members.tsx new file mode 100644 index 0000000..fb65cc5 --- /dev/null +++ b/mobile/src/app/(app)/groups/[groupId]/add-members.tsx @@ -0,0 +1,287 @@ +import { Stack, router } from 'expo-router'; +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { SectionList, StyleSheet, View } from 'react-native'; +import { z } from 'zod'; + +import { getPersonName } from '@/components/expense'; +import { useGroupDetails, useGroupIdParam } from '@/components/group/useGroupDetails'; +import { + Avatar, + EmptyState, + FullScreenSpinner, + Icon, + ListRow, + ModalHeader, + Screen, + Section, + SectionCell, + SectionHeader, + Spinner, + Text, + icons, + rowInset, + toast, +} from '@/components/ui'; +import { type RouterOutputs, api } from '@/lib/api'; +import { useAppConfig } from '@/lib/appConfig'; +import { haptics } from '@/lib/haptics'; +import { colors, spacing } from '@/theme/tokens'; + +const emailSchema = z.string().trim().toLowerCase().email(); +const FRIEND_AVATAR = 36; + +type Friend = RouterOutputs['user']['getFriends'][number]; +type FriendSection = { key: string; title: string; data: Friend[] }; + +/** Pick friends to add, or add someone new by email, like the web's `AddMembers` drawer. */ +const AddMembers = () => { + const { t } = useTranslation(); + const groupId = useGroupIdParam(); + const utils = api.useUtils(); + const { group, notFound } = useGroupDetails(groupId); + const friendsQuery = api.user.getFriends.useQuery(); + const addMembersMutation = api.group.addMembers.useMutation(); + const inviteFriendMutation = api.user.inviteFriend.useMutation(); + const { invitesEnabled } = useAppConfig(); + const [sendingInvite, setSendingInvite] = useState(false); + const [selected, setSelected] = useState>(() => new Set()); + const [query, setQuery] = useState(''); + + const isSaving = addMembersMutation.isLoading || inviteFriendMutation.isLoading; + + const save = (userIds: number[]) => { + if (!userIds.length) { + router.back(); + return; + } + + addMembersMutation.mutate( + { groupId, userIds }, + { + onSuccess: () => { + void utils.group.getGroupDetails.invalidate({ groupId }); + void utils.group.getAllGroups.invalidate(); + toast.success(t('groups.members_added', { count: userIds.length })); + router.back(); + }, + onError: (error) => toast.error(error.message || t('common.something_went_wrong')), + }, + ); + }; + + const header = ( + <> + setQuery(event.nativeEvent.text)} + autoCapitalize="none" + inputType="email" + hideWhenScrolling={false} + // Keeps Cancel and Done reachable while searching. + hideNavigationBar={false} + obscureBackground={false} + placement="stacked" + /> + router.back()} + confirm={{ + label: t('groups.done'), + disabled: !selected.size || isSaving, + loading: addMembersMutation.isLoading, + onPress: () => save([...selected]), + }} + /> + + ); + + if (notFound) { + return ( + + {header} + + + ); + } + + if (!group) { + return ( + <> + {header} + + + ); + } + + const memberIds = new Set(group.groupUsers.map((groupUser) => groupUser.userId)); + const search = query.trim().toLowerCase(); + const candidates = (friendsQuery.data ?? []).filter((friend) => !memberIds.has(friend.id)); + const matches = candidates.filter((friend) => + getPersonName(friend).toLowerCase().includes(search), + ); + // Ticked friends the search hides stay on screen, so they can be seen and unticked. + const hiddenSelected = candidates.filter( + (friend) => selected.has(friend.id) && !matches.includes(friend), + ); + const sections: FriendSection[] = [ + ...(hiddenSelected.length + ? [{ key: 'selected', title: t('groups.selected_title'), data: hiddenSelected }] + : []), + ...(matches.length + ? [ + { + key: 'friends', + title: + selected.size && !hiddenSelected.length + ? `${t('groups.friends')} · ${t('groups.selected', { count: selected.size })}` + : t('groups.friends'), + data: matches, + }, + ] + : []), + ]; + const email = emailSchema.safeParse(query); + + const toggle = (userId: number) => { + haptics.selection(); + setSelected((previous) => { + const next = new Set(previous); + if (next.has(userId)) { + next.delete(userId); + } else { + next.add(userId); + } + return next; + }); + }; + + const addByEmail = (sendInviteEmail: boolean) => { + if (!email.success) { + return; + } + + setSendingInvite(sendInviteEmail); + inviteFriendMutation.mutate( + { email: email.data, sendInviteEmail }, + { + onSuccess: (user) => { + void utils.user.getFriends.invalidate(); + save([...selected, user.id]); + }, + onError: (error) => toast.error(error.message || t('common.something_went_wrong')), + }, + ); + }; + + const emailActions = email.success ? ( +
+ {invitesEnabled ? ( + } + title={t('invite.send')} + action + disabled={isSaving} + right={inviteFriendMutation.isLoading && sendingInvite ? : undefined} + onPress={() => addByEmail(true)} + /> + ) : null} + } + title={ + + {t('groups.add_to_splitpro', { email: email.data })} + + } + action + disabled={isSaving} + right={inviteFriendMutation.isLoading && !sendingInvite ? : undefined} + onPress={() => addByEmail(false)} + /> +
+ ) : null; + + const noMatches = + '' !== search && !matches.length && !email.success && !friendsQuery.isLoading ? ( + + ) : null; + + const empty = (() => { + if (friendsQuery.isLoading) { + return ( + + + + ); + } + + if (email.success || '' !== search) { + return null; + } + + return ; + })(); + + return ( + <> + {header} + String(friend.id)} + style={styles.list} + contentInsetAdjustmentBehavior="automatic" + keyboardShouldPersistTaps="handled" + keyboardDismissMode="on-drag" + contentContainerStyle={styles.content} + stickySectionHeadersEnabled={false} + ListHeaderComponent={emailActions ?? undefined} + ListFooterComponent={hiddenSelected.length ? (noMatches ?? undefined) : undefined} + ListEmptyComponent={empty ?? noMatches ?? undefined} + renderSectionHeader={({ section }) => } + renderItem={({ item, index, section }) => ( + + + } + title={getPersonName(item)} + subtitle={item.name && item.email ? item.email : undefined} + accessory={selected.has(item.id) ? 'checkmark' : undefined} + onPress={() => toggle(item.id)} + /> + + )} + /> + + ); +}; + +const styles = StyleSheet.create({ + list: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + flexGrow: 1, + paddingTop: spacing[4], + paddingBottom: spacing[12], + }, + loading: { + paddingVertical: spacing[8], + alignItems: 'center', + }, +}); + +export default AddMembers; diff --git a/mobile/src/app/(app)/groups/[groupId]/default-split.tsx b/mobile/src/app/(app)/groups/[groupId]/default-split.tsx new file mode 100644 index 0000000..9352bd1 --- /dev/null +++ b/mobile/src/app/(app)/groups/[groupId]/default-split.tsx @@ -0,0 +1,260 @@ +import { SegmentedControl } from '@expo/ui/community/segmented-control'; +import { router } from 'expo-router'; +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, TextInput, View } from 'react-native'; + +import { + DEFAULT_SPLIT_TYPES, + type DefaultSplit, + type DefaultSplitType, + getDefaultSplitError, + getEditorSplit, + getEditorValues, + getGroupDefaultSplit, +} from '~/utils/defaultSplit'; +import { sumHundredths } from '~/utils/numbers'; + +import { getPersonName } from '@/components/expense'; +import { useGroupDetails, useGroupIdParam } from '@/components/group/useGroupDetails'; +import { + Avatar, + EmptyState, + FullScreenSpinner, + ListRow, + ModalHeader, + Screen, + Section, + Spinner, + Text, + icons, + rowInset, + toast, +} from '@/components/ui'; +import { type RouterOutputs, api } from '@/lib/api'; +import { haptics } from '@/lib/haptics'; +import { useConfirmDiscard } from '@/lib/navigation'; +import { colors, layout, spacing, typography } from '@/theme/tokens'; + +type GroupDetails = NonNullable; + +const MEMBER_AVATAR = 30; + +const TYPE_LABELS = { + EQUAL: 'groups.split_equal', + PERCENTAGE: 'groups.split_percentage', + SHARE: 'groups.split_share', +} as const satisfies Record; + +const close = () => router.back(); + +/** The editor, once the group is loaded so it can start from the current default. */ +const DefaultSplitEditor: React.FC<{ group: GroupDetails }> = ({ group }) => { + const { t } = useTranslation(); + const utils = api.useUtils(); + const setDefaultSplitMutation = api.group.setDefaultSplit.useMutation(); + const members = group.groupUsers.map((groupUser) => groupUser.user); + const memberIds = members.map((member) => member.id); + const current = getGroupDefaultSplit(group); + const [initial] = useState(() => ({ + splitType: current?.splitType ?? 'EQUAL', + values: getEditorValues(current, memberIds), + })); + const [splitType, setSplitType] = useState(initial.splitType); + const [values, setValues] = useState(initial.values); + const [removing, setRemoving] = useState(false); + const allowClose = useConfirmDiscard( + splitType !== initial.splitType || JSON.stringify(values) !== JSON.stringify(initial.values), + ); + + const split = getEditorSplit(splitType, values[splitType], memberIds); + const error = getDefaultSplitError(split, memberIds); + const remainingPercentage = (10_000 - sumHundredths(Object.values(split.shares))) / 100; + const isSaving = setDefaultSplitMutation.isLoading; + + const setValue = (memberId: number, value: string) => + setValues((previous) => ({ + ...previous, + [splitType]: { ...previous[splitType], [memberId]: value }, + })); + + const save = (splitToSave: DefaultSplit | null) => { + setRemoving(null === splitToSave); + setDefaultSplitMutation.mutate( + { groupId: group.id, split: splitToSave }, + { + onSuccess: () => { + void utils.group.getGroupDetails.invalidate({ groupId: group.id }); + void utils.group.getAllGroups.invalidate(); + allowClose(); + router.back(); + }, + onError: (mutationError) => toast.error(mutationError.message), + }, + ); + }; + + return ( + + save(split), + }} + /> + + + t(TYPE_LABELS[type]))} + selectedIndex={DEFAULT_SPLIT_TYPES.indexOf(splitType)} + onChange={({ nativeEvent }) => { + const type = DEFAULT_SPLIT_TYPES[nativeEvent.selectedSegmentIndex]; + if (type) { + haptics.selection(); + setSplitType(type); + } + }} + /> + + +
+ {members.map((member) => { + const name = getPersonName(member); + const value = values[splitType][member.id]; + const avatar = ( + + ); + + if ('EQUAL' === splitType) { + const isIncluded = '0' !== value; + + return ( + { + haptics.selection(); + setValue(member.id, isIncluded ? '0' : '1'); + }} + /> + ); + } + + return ( + + setValue(member.id, text.replace(',', '.'))} + keyboardType="decimal-pad" + selectTextOnFocus + placeholder="0" + placeholderTextColor={colors.placeholder} + accessibilityLabel={`${name} ${t(TYPE_LABELS[splitType])}`} + selectionColor={colors.tint} + cursorColor={colors.tint} + style={styles.valueInput} + /> + + {'PERCENTAGE' === splitType ? '%' : t('groups.shares_unit')} + + + } + /> + ); + })} + {'PERCENTAGE' === splitType ? ( + + {`${remainingPercentage}%`} + + } + /> + ) : null} +
+ + {current ? ( +
+ : undefined} + onPress={() => save(null)} + /> +
+ ) : null} +
+ ); +}; + +/** Sets the split new expenses in the group start with, like the web's `GroupDefaultSplit`. */ +const DefaultSplitScreen = () => { + const { t } = useTranslation(); + const groupId = useGroupIdParam(); + const { group, notFound } = useGroupDetails(groupId); + + return ( + <> + {notFound ? ( + + + + + ) : group ? ( + + ) : ( + <> + + + + )} + + ); +}; + +const styles = StyleSheet.create({ + segments: { + paddingHorizontal: layout.sectionMargin, + paddingTop: spacing[2], + paddingBottom: spacing[6], + }, + value: { + flexDirection: 'row', + alignItems: 'center', + gap: spacing[1], + }, + valueInput: { + ...typography.body, + lineHeight: undefined, + minWidth: 64, + paddingVertical: spacing[1], + color: colors.label, + textAlign: 'right', + }, + unit: { + minWidth: 20, + }, +}); + +export default DefaultSplitScreen; diff --git a/mobile/src/app/(app)/groups/[groupId]/info.tsx b/mobile/src/app/(app)/groups/[groupId]/info.tsx new file mode 100644 index 0000000..a5211ec --- /dev/null +++ b/mobile/src/app/(app)/groups/[groupId]/info.tsx @@ -0,0 +1,160 @@ +import { router } from 'expo-router'; +import React, { useCallback, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { RefreshControl, StyleSheet, View } from 'react-native'; + +import { getPersonName, useCurrentUser } from '@/components/expense'; +import { DefaultSplitSection } from '@/components/group/DefaultSplitSummary'; +import { GroupRecurringRules } from '@/components/group/GroupRecurringRules'; +import { useGroupDetails, useGroupIdParam } from '@/components/group/useGroupDetails'; +import { useGroupExit } from '@/components/group/useGroupExit'; +import { + Avatar, + EmptyState, + FullScreenSpinner, + Icon, + ListRow, + Screen, + Section, + Spinner, + Text, + icons, + rowInset, +} from '@/components/ui'; +import { api } from '@/lib/api'; +import { formatDate } from '@/lib/dates'; +import { getCurrency } from '@/lib/money'; +import { colors, spacing } from '@/theme/tokens'; + +const MEMBER_AVATAR = 32; + +/** Members, default split, recurring expenses and leave/delete, like the web's "Group info". */ +const GroupInfo = () => { + const { t } = useTranslation(); + const groupId = useGroupIdParam(); + const user = useCurrentUser(); + const utils = api.useUtils(); + const { query, group, notFound } = useGroupDetails(groupId); + const exit = useGroupExit(group, user?.id); + const [refreshing, setRefreshing] = useState(false); + + const onRefresh = useCallback(() => { + setRefreshing(true); + Promise.all([query.refetch(), utils.recurring.getGroupRules.invalidate({ groupId })]).finally( + () => setRefreshing(false), + ); + }, [groupId, query, utils]); + + if (notFound || (!group && query.isError)) { + return ( + + void query.refetch()} + /> + + ); + } + + if (!group || !user) { + return ( + <> + + + ); + } + + const currencyName = getCurrency(group.defaultCurrency)?.name; + + return ( + } + > + + + + {group.name} + + + +
+ {group.groupUsers.map(({ user: member }) => ( + + } + title={getPersonName(member)} + /> + ))} + + + + } + title={t('groups.add_members')} + action + onPress={() => + router.push({ + pathname: '/groups/[groupId]/add-members', + params: { groupId: String(groupId) }, + }) + } + /> +
+ + + + + +
+ + +
+ +
+ : undefined} + onPress={exit.onPress} + /> +
+
+ ); +}; + +const styles = StyleSheet.create({ + title: { + alignItems: 'center', + gap: spacing[2], + paddingHorizontal: spacing[4], + paddingTop: spacing[2], + paddingBottom: spacing[6], + }, + iconSlot: { + width: MEMBER_AVATAR, + alignItems: 'center', + }, +}); + +export default GroupInfo; diff --git a/mobile/src/app/(app)/groups/new.tsx b/mobile/src/app/(app)/groups/new.tsx new file mode 100644 index 0000000..b19dfe6 --- /dev/null +++ b/mobile/src/app/(app)/groups/new.tsx @@ -0,0 +1,121 @@ +import { router } from 'expo-router'; +import React, { useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, View } from 'react-native'; + +import { useCurrentUser } from '@/components/expense'; +import { + Avatar, + CurrencySheet, + Input, + ListRow, + ModalHeader, + Screen, + Section, + toast, +} from '@/components/ui'; +import { api } from '@/lib/api'; +import { getCurrency } from '@/lib/money'; +import { useConfirmDiscard } from '@/lib/navigation'; +import { spacing } from '@/theme/tokens'; + +/** Create a group, like the web's src/components/group/CreateGroup.tsx drawer. */ +const NewGroup = () => { + const { t } = useTranslation(); + const user = useCurrentUser(); + const utils = api.useUtils(); + const createGroup = api.group.create.useMutation(); + const [name, setName] = useState(''); + const [nameError, setNameError] = useState(null); + const [currency, setCurrency] = useState(); + const [pickerOpen, setPickerOpen] = useState(false); + // Every new group starts from the user's own currency. + const groupCurrency = currency ?? getCurrency(user?.currency ?? '')?.code ?? 'USD'; + const currencyName = getCurrency(groupCurrency)?.name; + const allowClose = useConfirmDiscard('' !== name.trim() || undefined !== currency); + + const onSubmit = () => { + const trimmed = name.trim(); + + if ('' === trimmed) { + setNameError(t('groups.name_required')); + return; + } + + createGroup.mutate( + { name: trimmed, currency: groupCurrency }, + { + onSuccess: (group) => { + void utils.group.getAllGroupsWithBalances.invalidate(); + void utils.group.getAllGroups.invalidate(); + allowClose(); + router.dismiss(); + router.push({ pathname: '/groups/[groupId]', params: { groupId: String(group.id) } }); + }, + onError: (error) => toast.error(error.message || t('common.something_went_wrong')), + }, + ); + }; + + return ( + + router.back()} + confirm={{ + label: t('groups.create'), + disabled: '' === name.trim(), + loading: createGroup.isLoading, + onPress: onSubmit, + }} + /> + + + + + +
+ { + setName(value); + setNameError(null); + }} + placeholder={t('groups.name_placeholder')} + accessibilityLabel={t('groups.name_placeholder')} + autoFocus + autoCapitalize="words" + returnKeyType="done" + onSubmitEditing={onSubmit} + maxLength={100} + /> +
+ +
+ setPickerOpen(true)} + /> +
+ + setPickerOpen(false)} + /> +
+ ); +}; + +const styles = StyleSheet.create({ + avatar: { + alignItems: 'center', + paddingTop: spacing[4], + paddingBottom: spacing[6], + }, +}); + +export default NewGroup; diff --git a/mobile/src/app/(app)/join-group.tsx b/mobile/src/app/(app)/join-group.tsx new file mode 100644 index 0000000..71bc2fa --- /dev/null +++ b/mobile/src/app/(app)/join-group.tsx @@ -0,0 +1,86 @@ +import { router, useLocalSearchParams } from 'expo-router'; +import React, { useEffect, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, View } from 'react-native'; + +import { Icon, Screen, Spinner, Text, icons, toast } from '@/components/ui'; +import { api } from '@/lib/api'; +import { colors, spacing } from '@/theme/tokens'; + +/** + * Opens an invite link, `/join-group?groupId=` like the web's src/pages/join-group.tsx: + * joins the group (or skips that if you're already in it) and opens it. + */ +const JoinGroup = () => { + const { t } = useTranslation(); + const { groupId: publicId } = useLocalSearchParams<{ groupId?: string }>(); + const utils = api.useUtils(); + const joinGroupMutation = api.group.joinGroup.useMutation(); + const started = useRef(false); + + useEffect(() => { + if (started.current) { + return; + } + started.current = true; + + const openGroup = (groupId: number) => + router.replace({ pathname: '/groups/[groupId]', params: { groupId: String(groupId) } }); + // Back to the tabs under this screen, rather than a second copy of them + const openGroups = () => router.dismissTo('/groups'); + + const join = async () => { + if (!publicId) { + openGroups(); + return; + } + + try { + const memberships = await utils.group.getAllGroups.fetch(); + const existing = memberships.find((membership) => publicId === membership.group.publicId); + + if (existing) { + openGroup(existing.groupId); + return; + } + + const group = await joinGroupMutation.mutateAsync({ groupId: publicId }); + toast.success(t('groups.joined', { name: group.name })); + void utils.group.getAllGroupsWithBalances.invalidate(); + void utils.group.getAllGroups.invalidate(); + openGroup(group.id); + } catch (error) { + console.warn(error); + toast.error(t('groups.join_failed')); + openGroups(); + } + }; + + void join(); + }, [joinGroupMutation, publicId, t, utils]); + + return ( + // Shown for a moment while the invite is accepted, like ContentUnavailableView with progress. + + + + + {t('groups.joining')} + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + gap: spacing[4], + paddingHorizontal: spacing[8], + }, +}); + +export default JoinGroup; diff --git a/mobile/src/app/(app)/new.tsx b/mobile/src/app/(app)/new.tsx new file mode 100644 index 0000000..4da9658 --- /dev/null +++ b/mobile/src/app/(app)/new.tsx @@ -0,0 +1,7 @@ +import { Redirect } from 'expo-router'; +import React from 'react'; + +/** Backs the Add tab button, which opens /add. Only reachable through a deep link to /new. */ +const NewExpense = () => ; + +export default NewExpense; diff --git a/mobile/src/app/(app)/settle-up.tsx b/mobile/src/app/(app)/settle-up.tsx new file mode 100644 index 0000000..dbbe67e --- /dev/null +++ b/mobile/src/app/(app)/settle-up.tsx @@ -0,0 +1,82 @@ +import { Stack, useLocalSearchParams } from 'expo-router'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { ScrollView, StyleSheet } from 'react-native'; + +import { FriendSettleUp, GroupSettleUp } from '@/components/settle'; +import { SettleHeader } from '@/components/settle/shared'; +import { EmptyState, icons } from '@/components/ui'; +import { colors, spacing } from '@/theme/tokens'; + +const toId = (value: string | undefined) => { + const id = Number(value); + return Number.isInteger(id) && 0 < id ? id : undefined; +}; + +/** + * Settle-up form sheet. `?friendId=` settles with a friend across all balances or one shared group; + * `?groupId=` (optionally with `friendId`) settles inside that group only. Each step sets the + * sheet's native header (title, Close/Back, Save). + */ +const SettleUp = () => { + const { t } = useTranslation(); + const params = useLocalSearchParams<{ friendId?: string; groupId?: string }>(); + const friendId = toId(params.friendId); + const groupId = toId(params.groupId); + + const content = (() => { + if (groupId) { + return ; + } + + if (friendId) { + return ; + } + + return ( + <> + + + + ); + })(); + + return ( + <> + + {content} + + {/* The layout hides the header; each step shows its title and buttons in it instead */} + + + ); +}; + +const styles = StyleSheet.create({ + sheet: { + flex: 1, + backgroundColor: colors.groupedBackground, + }, + content: { + flexGrow: 1, + paddingBottom: spacing[8], + }, +}); + +export default SettleUp; diff --git a/mobile/src/app/(auth)/_layout.tsx b/mobile/src/app/(auth)/_layout.tsx new file mode 100644 index 0000000..20ff0c9 --- /dev/null +++ b/mobile/src/app/(auth)/_layout.tsx @@ -0,0 +1,15 @@ +import { Stack } from 'expo-router'; +import React from 'react'; + +import { stackScreenOptions } from '@/theme/navigation'; + +const AuthLayout = () => ( + + + {/* A bare native header: only the back button, which goes back to change the email */} + + + +); + +export default AuthLayout; diff --git a/mobile/src/app/(auth)/oauth-callback.tsx b/mobile/src/app/(auth)/oauth-callback.tsx new file mode 100644 index 0000000..c73fdee --- /dev/null +++ b/mobile/src/app/(auth)/oauth-callback.tsx @@ -0,0 +1,24 @@ +import { router } from 'expo-router'; +import React, { useEffect } from 'react'; + +import { FullScreenSpinner } from '@/components/ui'; + +/** + * The Google sign-in redirect (`splitpro://oauth-callback?code=…`). openAuthSessionAsync reads the + * code itself; on Android the URL also arrives as a deep link and lands here, so step back to the + * sign-in screen, which finishes the sign-in. + */ +const OAuthCallback = () => { + useEffect(() => { + if (router.canGoBack()) { + router.back(); + return; + } + + router.replace('/sign-in'); + }, []); + + return ; +}; + +export default OAuthCallback; diff --git a/mobile/src/app/(auth)/sign-in.tsx b/mobile/src/app/(auth)/sign-in.tsx new file mode 100644 index 0000000..c2406e8 --- /dev/null +++ b/mobile/src/app/(auth)/sign-in.tsx @@ -0,0 +1,325 @@ +import * as AppleAuthentication from 'expo-apple-authentication'; +import { router } from 'expo-router'; +import React, { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; +import { Image, Pressable, StyleSheet, View, useColorScheme } from 'react-native'; +import Svg, { Path } from 'react-native-svg'; +import { z } from 'zod'; + +import { Button, Input, Screen, Spinner, Text, toast } from '@/components/ui'; +import { AuthApiError, type SignInResult, getAuthProviders, sendEmailCode } from '@/lib/authApi'; +import { isAppleSignInAvailable, signInWithApple, signInWithGoogle } from '@/lib/socialAuth'; +import { useAuthStore } from '@/store/authStore'; +import { colors, spacing } from '@/theme/tokens'; + +const emailSchema = z.string().trim().toLowerCase().email(); +const appIcon = require('../../../assets/icon.png') as number; + +const BUTTON_HEIGHT = 50; +const ICON_SIZE = 88; + +type SocialProvider = 'google' | 'apple'; + +const SOCIAL_SIGN_IN = { + google: signInWithGoogle, + apple: signInWithApple, +} satisfies Record Promise>; + +/** Google's sign-in button colors (developers.google.com/identity/branding-guidelines). */ +const GOOGLE_BUTTON = { + light: { background: '#ffffff', border: '#747775', text: '#1f1f1f' }, + dark: { background: '#131314', border: '#8e918f', text: '#e3e3e3' }, +} as const; + +const errorMessage = (error: unknown, fallback: string) => + error instanceof AuthApiError ? error.message : fallback; + +/** Google's four-color "G". */ +const GoogleLogo = () => ( + + + + + + +); + +const GoogleButton: React.FC<{ + label: string; + loading: boolean; + disabled: boolean; + onPress: () => void; +}> = ({ label, loading, disabled, onPress }) => { + const palette = GOOGLE_BUTTON['dark' === useColorScheme() ? 'dark' : 'light']; + + return ( + [ + styles.socialButton, + styles.googleButton, + { backgroundColor: palette.background, borderColor: palette.border }, + pressed ? styles.pressed : null, + disabled && !loading ? styles.disabled : null, + ]} + > + {loading ? ( + + ) : ( + <> + + {/* Google's guidelines: the button's text follows the platform font, medium weight */} + + {label} + + + )} + + ); +}; + +const SignIn = () => { + const { t } = useTranslation(); + const scheme = useColorScheme(); + const signIn = useAuthStore((state) => state.signIn); + const [email, setEmail] = useState(''); + const [emailError, setEmailError] = useState(null); + const [sending, setSending] = useState(false); + const [socialPending, setSocialPending] = useState(null); + const [appleAvailable, setAppleAvailable] = useState(false); + // null until the server answers: show every option rather than none if it can't be reached + const [providers, setProviders] = useState(null); + const busy = sending || null !== socialPending; + const showGoogle = !providers || providers.includes('google'); + const showEmail = !providers || providers.includes('email'); + const showSocial = showGoogle || appleAvailable; + + useEffect(() => { + isAppleSignInAvailable().then(setAppleAvailable).catch(console.warn); + getAuthProviders().then(setProviders).catch(console.warn); + }, []); + + const onSendCode = async () => { + if (busy) { + return; + } + + const parsed = emailSchema.safeParse(email); + + if (!parsed.success) { + setEmailError(t('auth.invalid_email')); + return; + } + + setEmailError(null); + setSending(true); + + try { + await sendEmailCode(parsed.data); + router.push({ pathname: '/verify', params: { email: parsed.data } }); + } catch (error) { + setEmailError(errorMessage(error, t('common.something_went_wrong'))); + } finally { + setSending(false); + } + }; + + const onSocialSignIn = async (provider: SocialProvider) => { + if (busy) { + return; + } + + setSocialPending(provider); + + try { + const result = await SOCIAL_SIGN_IN[provider](); + + // Signing in flips the protected routes, which replaces this screen with the app + if (result) { + await signIn(result); + } + } catch (error) { + toast.error(errorMessage(error, t('auth.sign_in_failed'))); + } finally { + setSocialPending(null); + } + }; + + return ( + + + + + + {t('common.app_name')} + + + {t('auth.tagline')} + + + + + {/* HIG: Sign in with Apple is at least as prominent as other sign-in options */} + {appleAvailable ? ( + + onSocialSignIn('apple')} + /> + {'apple' === socialPending ? ( + + + + ) : null} + + ) : null} + {showGoogle ? ( + onSocialSignIn('google')} + /> + ) : null} + + {showSocial && showEmail ? ( + + + {t('auth.or')} + + + ) : null} + + {showEmail ? ( + <> + { + setEmail(value); + setEmailError(null); + }} + placeholder={t('auth.email_placeholder')} + keyboardType="email-address" + autoCapitalize="none" + autoCorrect={false} + autoComplete="email" + textContentType="emailAddress" + returnKeyType="send" + editable={!busy} + onSubmitEditing={onSendCode} + error={emailError} + accessibilityLabel={t('auth.email_placeholder')} + /> +