diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000000..2a73945fdf --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(pnpm typecheck:*)", + "Bash(pnpm build:*)", + "Bash(pnpm typecheck:i18n:*)" + ] + } +} diff --git a/clients/apps/web/package.json b/clients/apps/web/package.json index 583dd951bb..f18913793b 100644 --- a/clients/apps/web/package.json +++ b/clients/apps/web/package.json @@ -41,6 +41,7 @@ "@polar-sh/checkout": "workspace:^", "@polar-sh/client": "workspace:*", "@polar-sh/customer-portal": "workspace:*", + "@polar-sh/i18n": "workspace:^", "@polar-sh/mdx": "workspace:*", "@polar-sh/sdk": "^0.42.1", "@polar-sh/ui": "workspace:*", diff --git a/clients/apps/web/src/app/checkout/[clientSecret]/CheckoutPage.tsx b/clients/apps/web/src/app/checkout/[clientSecret]/CheckoutPage.tsx index 116451fa9e..ad9236144f 100644 --- a/clients/apps/web/src/app/checkout/[clientSecret]/CheckoutPage.tsx +++ b/clients/apps/web/src/app/checkout/[clientSecret]/CheckoutPage.tsx @@ -3,16 +3,18 @@ import Checkout from '@/components/Checkout/Checkout' import CheckoutLayout from '@/components/Checkout/CheckoutLayout' import type { ExperimentVariant } from '@/experiments' -import { useCheckout } from '@polar-sh/checkout/providers' +import { type SupportedLocale, useCheckout } from '@polar-sh/checkout/providers' const ClientPage = ({ embed, theme, layoutVariant, + locale, }: { embed: boolean theme?: 'light' | 'dark' layoutVariant: ExperimentVariant<'checkout_layout_experiment'> + locale: SupportedLocale }) => { const { checkout } = useCheckout() @@ -23,7 +25,12 @@ const ClientPage = ({ theme={theme} layoutVariant={layoutVariant} > - + ) } diff --git a/clients/apps/web/src/app/checkout/[clientSecret]/confirmation/page.tsx b/clients/apps/web/src/app/checkout/[clientSecret]/confirmation/page.tsx index 1801bcb7b5..9b9a54c411 100644 --- a/clients/apps/web/src/app/checkout/[clientSecret]/confirmation/page.tsx +++ b/clients/apps/web/src/app/checkout/[clientSecret]/confirmation/page.tsx @@ -1,5 +1,6 @@ import { CheckoutConfirmation } from '@/components/Checkout/CheckoutConfirmation' import CheckoutLayout from '@/components/Checkout/CheckoutLayout' +import { resolveCheckoutLocale } from '@/i18n/utils' import { getServerURL } from '@/utils/api' import { PolarCore } from '@polar-sh/sdk/core' import { checkoutsClientGet } from '@polar-sh/sdk/funcs/checkoutsClientGet' @@ -13,14 +14,18 @@ export default async function Page(props: { embed?: string theme?: 'light' | 'dark' customer_session_token?: string + locale?: string }> }) { const searchParams = await props.searchParams - - const { embed, theme, customer_session_token } = searchParams - const params = await props.params + const { + embed, + theme, + customer_session_token, + locale: searchParamLocale, + } = searchParams const { clientSecret } = params const client = new PolarCore({ serverURL: getServerURL() }) @@ -61,6 +66,12 @@ export default async function Page(props: { redirect(checkout.url) } + // Type cast needed until @polar-sh/sdk is updated with locale field + const locale = await resolveCheckoutLocale( + searchParamLocale, + (checkout as typeof checkout & { locale?: string }).locale, + ) + return ( ) diff --git a/clients/apps/web/src/app/checkout/[clientSecret]/page.tsx b/clients/apps/web/src/app/checkout/[clientSecret]/page.tsx index 4dd520cb84..d7d5718329 100644 --- a/clients/apps/web/src/app/checkout/[clientSecret]/page.tsx +++ b/clients/apps/web/src/app/checkout/[clientSecret]/page.tsx @@ -1,4 +1,5 @@ import { getExperiment } from '@/experiments/server' +import { resolveCheckoutLocale } from '@/i18n/utils' import { getPublicServerURL, getServerURL } from '@/utils/api' import { CheckoutFormProvider, @@ -13,14 +14,16 @@ import CheckoutPage from './CheckoutPage' export default async function Page(props: { params: Promise<{ clientSecret: string }> - searchParams: Promise<{ embed?: string; theme?: 'light' | 'dark' }> + searchParams: Promise<{ + embed?: string + theme?: 'light' | 'dark' + locale?: string + }> }) { const searchParams = await props.searchParams - - const { embed: _embed, theme } = searchParams - const params = await props.params + const { embed: _embed, theme, locale: searchParamLocale } = searchParams const { clientSecret } = params const embed = _embed === 'true' @@ -76,6 +79,11 @@ export default async function Page(props: { redirect(`/checkout/${checkout.clientSecret}/confirmation`) } + // Type cast needed until @polar-sh/sdk is updated with locale field + const locale = await resolveCheckoutLocale( + searchParamLocale, + (checkout as typeof checkout & { locale?: string }).locale, + ) const layoutVariant = await getExperiment('checkout_layout_experiment') return ( @@ -88,6 +96,7 @@ export default async function Page(props: { theme={theme} embed={embed} layoutVariant={layoutVariant} + locale={locale} /> diff --git a/clients/apps/web/src/app/checkout/layout.tsx b/clients/apps/web/src/app/checkout/layout.tsx new file mode 100644 index 0000000000..ed9fa2b0fc --- /dev/null +++ b/clients/apps/web/src/app/checkout/layout.tsx @@ -0,0 +1,7 @@ +export default function CheckoutLayout({ + children, +}: { + children: React.ReactNode +}) { + return children +} diff --git a/clients/apps/web/src/components/Checkout/Checkout.tsx b/clients/apps/web/src/components/Checkout/Checkout.tsx index d628265aa1..a4cee13d05 100644 --- a/clients/apps/web/src/components/Checkout/Checkout.tsx +++ b/clients/apps/web/src/components/Checkout/Checkout.tsx @@ -15,7 +15,11 @@ import { type ProductCheckoutPublic, } from '@polar-sh/checkout/guards' import { useCheckoutFulfillmentListener } from '@polar-sh/checkout/hooks' -import { useCheckout, useCheckoutForm } from '@polar-sh/checkout/providers' +import { + type SupportedLocale, + useCheckout, + useCheckoutForm, +} from '@polar-sh/checkout/providers' import type { CheckoutConfirmStripe } from '@polar-sh/sdk/models/components/checkoutconfirmstripe' import type { CheckoutPublicConfirmed } from '@polar-sh/sdk/models/components/checkoutpublicconfirmed' import type { CheckoutUpdatePublic } from '@polar-sh/sdk/models/components/checkoutupdatepublic' @@ -39,12 +43,14 @@ export interface CheckoutProps { embed?: boolean theme?: 'light' | 'dark' layoutVariant?: ExperimentVariant<'checkout_layout_experiment'> + locale?: SupportedLocale } const Checkout = ({ embed: _embed, theme: _theme, layoutVariant = 'control', + locale, }: CheckoutProps) => { const isLayoutTreatment = layoutVariant === 'treatment' const { client } = useCheckout() @@ -206,6 +212,7 @@ const Checkout = ({ ) => Promise } themePreset={themePreset} + locale={locale} /> {checkout.productPrice.amountType === 'custom' && ( ) @@ -278,6 +286,7 @@ const Checkout = ({ ) => Promise } themePreset={themePreset} + locale={locale} /> {checkout.productPrice.amountType === 'custom' && ( Promise } isLayoutTreatment={isLayoutTreatment} + locale={locale} /> )} @@ -312,6 +322,7 @@ const Checkout = ({ themePreset={themePreset} disabled={shouldBlockCheckout} isUpdatePending={isUpdatePending} + locale={locale} /> diff --git a/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx b/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx index ecb83f47a0..0080f2609e 100644 --- a/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx +++ b/clients/apps/web/src/components/Checkout/CheckoutBenefits.tsx @@ -1,9 +1,15 @@ +'use client' + import { useCustomerBenefitGrants } from '@/hooks/queries/customerPortal' import { useCustomerSSE } from '@/hooks/sse' import { createClientSideAPI } from '@/utils/client' import type { ProductCheckoutPublic } from '@polar-sh/checkout/guards' +import { + getTranslations, + type SupportedLocale, +} from '@polar-sh/checkout/providers' import { List, ListItem } from '@polar-sh/ui/components/atoms/List' -import { useEffect } from 'react' +import { useEffect, useMemo } from 'react' import { BenefitGrant } from '../Benefit/BenefitGrant' import { SpinnerNoMargin } from '../Shared/Spinner' @@ -11,13 +17,16 @@ interface CheckoutBenefitsProps { checkout: ProductCheckoutPublic customerSessionToken?: string maxWaitingTimeMs?: number + locale?: SupportedLocale } const CheckoutBenefits = ({ checkout, customerSessionToken, maxWaitingTimeMs = 15000, + locale = 'en', }: CheckoutBenefitsProps) => { + const t = useMemo(() => getTranslations(locale), [locale]) const api = createClientSideAPI(customerSessionToken) const { data: benefitGrants, refetch } = useCustomerBenefitGrants(api, { checkout_id: checkout.id, @@ -70,7 +79,7 @@ const CheckoutBenefits = ({

- Granting benefits... + {t.confirmation.grantingBenefits}

)} diff --git a/clients/apps/web/src/components/Checkout/CheckoutCard.tsx b/clients/apps/web/src/components/Checkout/CheckoutCard.tsx index c6ab2b10a1..10921187e8 100644 --- a/clients/apps/web/src/components/Checkout/CheckoutCard.tsx +++ b/clients/apps/web/src/components/Checkout/CheckoutCard.tsx @@ -6,13 +6,16 @@ import { CheckoutSeatSelector, } from '@polar-sh/checkout/components' import type { ProductCheckoutPublic } from '@polar-sh/checkout/guards' +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { CheckoutUpdatePublic } from '@polar-sh/sdk/models/components/checkoutupdatepublic' import ShadowBox from '@polar-sh/ui/components/atoms/ShadowBox' +import { useMemo } from 'react' export interface CheckoutCardProps { checkout: ProductCheckoutPublic update?: (body: CheckoutUpdatePublic) => Promise disabled?: boolean isLayoutTreatment?: boolean + locale?: SupportedLocale } export const CheckoutCard = ({ @@ -20,26 +23,33 @@ export const CheckoutCard = ({ update, disabled, isLayoutTreatment = false, + locale = 'en', }: CheckoutCardProps) => { + const t = useMemo(() => getTranslations(locale), [locale]) const { product, productPrice } = checkout const isSeatBased = productPrice && productPrice.amountType === 'seat_based' return ( {isSeatBased && update ? ( - + ) : ( )} {product.benefits.length > 0 ? (
-

Included

+

{t.form.included}

diff --git a/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx b/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx index 5c22dc437a..822354cebe 100644 --- a/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx +++ b/clients/apps/web/src/components/Checkout/CheckoutConfirmation.tsx @@ -5,6 +5,10 @@ import { usePostHog } from '@/hooks/posthog' import { useCheckoutClientSSE } from '@/hooks/sse' import { getServerURL } from '@/utils/api' import { hasProductCheckout } from '@polar-sh/checkout/guards' +import { + getTranslations, + type SupportedLocale, +} from '@polar-sh/checkout/providers' import { PolarCore } from '@polar-sh/sdk/core' import { checkoutsClientGet } from '@polar-sh/sdk/funcs/checkoutsClientGet' import type { CheckoutPublic } from '@polar-sh/sdk/models/components/checkoutpublic' @@ -15,7 +19,6 @@ import { Elements, ElementsConsumer } from '@stripe/react-stripe-js' import { Stripe, loadStripe } from '@stripe/stripe-js' import { useRouter } from 'next/navigation' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import LogoType from '../Brand/LogoType' import { SpinnerNoMargin } from '../Shared/Spinner' import CheckoutBenefits from './CheckoutBenefits' import CheckoutSeatInvitations from './CheckoutSeatInvitations' @@ -30,9 +33,11 @@ const isIntegrationError = ( const StripeRequiresAction = ({ stripe, checkout, + confirmPaymentLabel, }: { stripe: Stripe | null checkout: CheckoutPublic + confirmPaymentLabel: string }) => { const [pendingHandling, setPendingHandling] = useState(false) const [success, setSuccess] = useState(false) @@ -84,7 +89,7 @@ const StripeRequiresAction = ({ onClick={() => handleNextAction(stripe)} loading={pendingHandling} > - Confirm payment + {confirmPaymentLabel} ) } @@ -99,6 +104,7 @@ export interface CheckoutConfirmationProps { customerSessionToken?: string disabled?: boolean maxWaitingTimeMs?: number + locale?: SupportedLocale } export const CheckoutConfirmation = ({ @@ -108,9 +114,11 @@ export const CheckoutConfirmation = ({ customerSessionToken, disabled, maxWaitingTimeMs = 15000, + locale = 'en', }: CheckoutConfirmationProps) => { const router = useRouter() const posthog = usePostHog() + const t = useMemo(() => getTranslations(locale), [locale]) const client = useMemo(() => new PolarCore({ serverURL: getServerURL() }), []) const [checkout, setCheckout] = useState(_checkout) const { status, organization } = checkout @@ -194,21 +202,22 @@ export const CheckoutConfirmation = ({ name={organization.name} />

- {status === 'confirmed' && 'We are processing your order'} - {status === 'succeeded' && 'Your order was successful!'} - {status === 'failed' && - 'A problem occurred while processing your order'} + {status === 'confirmed' && t.confirmation.processing} + {status === 'succeeded' && t.confirmation.success} + {status === 'failed' && t.confirmation.failed}

- {status === 'confirmed' && - 'Please wait while we are listening for those webhooks.'} + {status === 'confirmed' && t.confirmation.waitingWebhooks} {status === 'succeeded' && ( <> {hasProductCheckout(checkout) && - `You're now eligible for the benefits of ${checkout.product.name}.`} + t.confirmation.eligible.replace( + '{productName}', + checkout.product.name, + )} )} - {status === 'failed' && 'Please try again or contact support.'} + {status === 'failed' && t.confirmation.tryAgain}

{status === 'confirmed' && (
@@ -216,7 +225,11 @@ export const CheckoutConfirmation = ({ {({ stripe }) => ( - + )} @@ -233,20 +246,12 @@ export const CheckoutConfirmation = ({ checkout={checkout} customerSessionToken={customerSessionToken} maxWaitingTimeMs={maxWaitingTimeMs} + locale={locale} /> )} -

- This order was processed by our online reseller & Merchant of - Record, Polar, who also handles order-related inquiries and - returns. -

)}
-
- Powered by - -
) } diff --git a/clients/apps/web/src/i18n/utils.ts b/clients/apps/web/src/i18n/utils.ts new file mode 100644 index 0000000000..115a35e6ba --- /dev/null +++ b/clients/apps/web/src/i18n/utils.ts @@ -0,0 +1,53 @@ +import { + DEFAULT_LOCALE, + isSupportedLocale, + SUPPORTED_LOCALES, + type SupportedLocale, +} from '@polar-sh/i18n' +import { headers } from 'next/headers' + +function getLocaleFromAcceptLanguage( + acceptLanguage: string | null, +): SupportedLocale { + if (!acceptLanguage) return DEFAULT_LOCALE + + const languages = acceptLanguage + .split(',') + .map((lang) => { + const [code, qValue] = lang.trim().split(';q=') + return { + code: code.split('-')[0].toLowerCase(), + q: qValue ? parseFloat(qValue) : 1, + } + }) + .sort((a, b) => b.q - a.q) + + for (const { code } of languages) { + if (SUPPORTED_LOCALES.includes(code as SupportedLocale)) { + return code as SupportedLocale + } + } + + return DEFAULT_LOCALE +} + +export async function resolveCheckoutLocale( + searchParamLocale?: string, + checkoutLocale?: string | null, +): Promise { + // 1. Query param takes priority + if (searchParamLocale && isSupportedLocale(searchParamLocale)) { + return searchParamLocale + } + + // 2. Checkout's locale (forced or inherited from customer) + if (checkoutLocale && isSupportedLocale(checkoutLocale)) { + return checkoutLocale + } + + // 3. Accept-Language header + const headersList = await headers() + const acceptLanguage = headersList.get('accept-language') + + return getLocaleFromAcceptLanguage(acceptLanguage) +} diff --git a/clients/packages/checkout/package.json b/clients/packages/checkout/package.json index 4315dd8a4f..c31daa1152 100644 --- a/clients/packages/checkout/package.json +++ b/clients/packages/checkout/package.json @@ -50,6 +50,7 @@ "access": "public" }, "dependencies": { + "@polar-sh/i18n": "workspace:^", "@polar-sh/sdk": "^0.42.1", "@polar-sh/ui": "workspace:^", "event-source-plus": "^0.1.15", diff --git a/clients/packages/checkout/src/components/AmountLabel.tsx b/clients/packages/checkout/src/components/AmountLabel.tsx index d1fc83e0a2..af3162f9d7 100644 --- a/clients/packages/checkout/src/components/AmountLabel.tsx +++ b/clients/packages/checkout/src/components/AmountLabel.tsx @@ -1,3 +1,4 @@ +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { SubscriptionRecurringInterval } from '@polar-sh/sdk/models/components/subscriptionrecurringinterval' import { useMemo } from 'react' @@ -9,6 +10,7 @@ interface AmountLabelProps { currency: string interval?: SubscriptionRecurringInterval | null intervalCount?: number | null + locale?: SupportedLocale } const AmountLabel: React.FC = ({ @@ -16,14 +18,23 @@ const AmountLabel: React.FC = ({ currency, interval, intervalCount, + locale = 'en', }) => { + const t = useMemo(() => getTranslations(locale), [locale]) + const intervalDisplay = useMemo(() => { if (!interval) { return '' } - const formatted = formatRecurringInterval(interval, intervalCount, 'short') + const formatted = formatRecurringInterval( + interval, + intervalCount, + 'short', + t.pricing.interval, + locale, + ) return formatted ? ` / ${formatted}` : '' - }, [interval, intervalCount]) + }, [interval, intervalCount, t.pricing.interval, locale]) const minimumFractionDigits = useMemo( // Show 0 decimals if a round number, show default decimals (2 for USD) otherwise diff --git a/clients/packages/checkout/src/components/CheckoutForm.tsx b/clients/packages/checkout/src/components/CheckoutForm.tsx index 7226a07a71..d863509c56 100644 --- a/clients/packages/checkout/src/components/CheckoutForm.tsx +++ b/clients/packages/checkout/src/components/CheckoutForm.tsx @@ -1,5 +1,10 @@ 'use client' +import { + DEFAULT_LOCALE, + getTranslations, + type SupportedLocale, +} from '@polar-sh/i18n' import { CountryAlpha2Input } from '@polar-sh/sdk/models/components/addressinput' import type { CheckoutConfirmStripe } from '@polar-sh/sdk/models/components/checkoutconfirmstripe' import type { CheckoutPublic } from '@polar-sh/sdk/models/components/checkoutpublic' @@ -94,6 +99,7 @@ interface BaseCheckoutFormProps { disabled?: boolean isUpdatePending?: boolean themePreset: ThemingPresetProps + locale?: SupportedLocale } const BaseCheckoutForm = ({ @@ -107,7 +113,9 @@ const BaseCheckoutForm = ({ isUpdatePending, children, themePreset: themePresetProps, + locale = DEFAULT_LOCALE, }: React.PropsWithChildren) => { + const t = useMemo(() => getTranslations(locale), [locale]) const interval = hasProductCheckout(checkout) ? hasLegacyRecurringPrices(checkout.prices[checkout.product.id]) ? checkout.productPrice.recurringInterval @@ -271,6 +279,19 @@ const BaseCheckoutForm = ({ } }, [checkout, resetField]) + // Sync locale to checkout if it differs from the resolved locale (e.g., from querystring) + // Type casts needed until @polar-sh/sdk is updated with locale field + useEffect(() => { + if ( + locale && + locale !== (checkout as CheckoutPublic & { locale?: string }).locale + ) { + update({ locale } as CheckoutUpdatePublic).catch(() => {}) + } + // Only run on mount - we don't want to re-sync if checkout updates + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + const formattedDiscountDuration = useMemo(() => { if (!checkout.discount) { return '' @@ -321,23 +342,23 @@ const BaseCheckoutForm = ({ const totalLabel = useMemo(() => { if (interval) { const formatted = formatRecurringInterval(interval, intervalCount, 'long') - return `Every ${formatted}` + return `${t.pricing.every} ${formatted}` } - return 'Total' - }, [interval, intervalCount]) + return t.pricing.total + }, [interval, intervalCount, t]) const checkoutLabel = useMemo(() => { if (checkout.activeTrialInterval) { - return `Start Trial` + return t.buttons.startTrial } if (checkout.isPaymentFormRequired) { - return interval ? 'Subscribe' : 'Pay' + return interval ? t.buttons.subscribe : t.buttons.pay } - return 'Submit' - }, [checkout, interval]) + return t.buttons.submit + }, [checkout, interval, t]) return (
@@ -352,11 +373,11 @@ const BaseCheckoutForm = ({ control={control} name="customerEmail" rules={{ - required: 'This field is required', + required: t.form.required, }} render={({ field }) => ( - Email + {t.form.email} ( - Cardholder name + {t.form.cardholderName} - - I'm purchasing as a business - + {t.form.businessPurchase}
@@ -433,11 +452,11 @@ const BaseCheckoutForm = ({ control={control} name="customerBillingName" rules={{ - required: 'This field is required', + required: t.form.required, }} render={({ field }) => ( - Business name + {t.form.businessName} - Billing address + {t.form.billingAddress} {isDisplayedField(checkout.billingAddressFields.line1) && ( ( @@ -471,7 +490,7 @@ const BaseCheckoutForm = ({ @@ -490,7 +509,7 @@ const BaseCheckoutForm = ({ required: isRequiredField( checkout.billingAddressFields.line2, ) - ? 'This field is required' + ? t.form.required : false, }} render={({ field }) => ( @@ -498,7 +517,7 @@ const BaseCheckoutForm = ({ @@ -524,7 +543,7 @@ const BaseCheckoutForm = ({ required: isRequiredField( checkout.billingAddressFields.postalCode, ) - ? 'This field is required' + ? t.form.required : false, }} render={({ field }) => ( @@ -532,7 +551,7 @@ const BaseCheckoutForm = ({ @@ -553,7 +572,7 @@ const BaseCheckoutForm = ({ required: isRequiredField( checkout.billingAddressFields.city, ) - ? 'This field is required' + ? t.form.required : false, }} render={({ field }) => ( @@ -561,7 +580,7 @@ const BaseCheckoutForm = ({ @@ -582,7 +601,7 @@ const BaseCheckoutForm = ({ required: isRequiredField( checkout.billingAddressFields.state, ) - ? 'This field is required' + ? t.form.required : false, }} render={({ field }) => ( @@ -592,6 +611,11 @@ const BaseCheckoutForm = ({ country={country} value={field.value || ''} onChange={field.onChange} + labels={{ + state: t.form.state, + province: t.form.province, + stateOrProvince: t.form.stateOrProvince, + }} /> @@ -610,7 +634,7 @@ const BaseCheckoutForm = ({ required: isRequiredField( checkout.billingAddressFields.country, ) - ? 'This field is required' + ? t.form.required : false, }} render={({ field }) => ( @@ -622,6 +646,7 @@ const BaseCheckoutForm = ({ autoComplete="billing country" value={field.value || undefined} onChange={field.onChange} + placeholder={t.form.country} /> @@ -643,9 +668,9 @@ const BaseCheckoutForm = ({ render={({ field }) => ( -
Tax ID
+
{t.form.taxId}
- Optional + {t.form.optional}
@@ -665,7 +690,7 @@ const BaseCheckoutForm = ({ size="sm" onClick={addTaxID} > - Apply + {t.form.apply} )} {validTaxID && ( @@ -695,9 +720,9 @@ const BaseCheckoutForm = ({ render={({ field }) => ( -
Discount code
+
{t.form.discountCode}
- Optional + {t.form.optional}
@@ -723,7 +748,7 @@ const BaseCheckoutForm = ({ size="sm" onClick={addDiscountCode} > - Apply + {t.form.apply} )} {checkoutDiscounted && ( @@ -752,9 +777,7 @@ const BaseCheckoutForm = ({ control={control} name={`customFieldData.${customField.slug}`} rules={{ - required: required - ? 'This field is required' - : undefined, + required: required ? t.form.required : undefined, }} render={({ field }) => ( {checkout.currency ? ( <> - + @@ -792,7 +816,7 @@ const BaseCheckoutForm = ({ checkout.discountAmount % 100 === 0 ? 0 : 2, )} - + {formatCurrencyNumber( checkout.netAmount, checkout.currency, @@ -802,7 +826,7 @@ const BaseCheckoutForm = ({ )} - + {checkout.taxAmount !== null ? formatCurrencyNumber( checkout.taxAmount, @@ -819,6 +843,7 @@ const BaseCheckoutForm = ({ currency={checkout.currency} interval={interval} intervalCount={intervalCount} + locale={locale} /> {formattedDiscountDuration && ( @@ -828,19 +853,25 @@ const BaseCheckoutForm = ({
{meteredPrices.length > 0 && ( - + )} {meteredPrices.map((meteredPrice) => ( - + ))} ) : ( - Free + {t.pricing.free} )} {(checkout.trialEnd || (checkout.activeTrialInterval && @@ -850,14 +881,14 @@ const BaseCheckoutForm = ({ checkout.activeTrialIntervalCount && ( 1 ? 's' : ''} trial`} + title={`${checkout.activeTrialIntervalCount} ${checkout.activeTrialInterval}${checkout.activeTrialIntervalCount > 1 ? 's' : ''} ${t.pricing.trial}`} > - Free + {t.pricing.free} )} {checkout.trialEnd && ( - Trial ends{' '} + {t.pricing.trialEnds}{' '} - Payments are currently unavailable + {t.errors.paymentsUnavailable}

)} {errors.root && ( @@ -898,8 +929,7 @@ const BaseCheckoutForm = ({

- This order is processed by our online reseller & Merchant of Record, - Polar, who also handles order-related inquiries and returns. + {t.footer.merchantInfo}

- Powered by + {t.footer.poweredBy} @@ -929,6 +959,7 @@ interface CheckoutFormProps { isUpdatePending?: boolean theme?: 'light' | 'dark' themePreset: ThemingPresetProps + locale?: SupportedLocale } const StripeCheckoutForm = (props: CheckoutFormProps) => { @@ -941,6 +972,7 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { disabled, isUpdatePending, themePreset: themePresetProps, + locale, } = props const { paymentProcessorMetadata: { publishable_key }, @@ -985,7 +1017,7 @@ const StripeCheckoutForm = (props: CheckoutFormProps) => { stripe={stripePromise} options={{ ...elementsOptions, - locale: 'en', + locale: locale || 'en', customerSessionClientSecret: ( checkout.paymentProcessorMetadata as { customer_session_client_secret?: string diff --git a/clients/packages/checkout/src/components/CheckoutPricing.tsx b/clients/packages/checkout/src/components/CheckoutPricing.tsx index 809e84c342..c19674055a 100644 --- a/clients/packages/checkout/src/components/CheckoutPricing.tsx +++ b/clients/packages/checkout/src/components/CheckoutPricing.tsx @@ -1,5 +1,6 @@ 'use client' +import type { SupportedLocale } from '@polar-sh/i18n' import type { CheckoutPublic } from '@polar-sh/sdk/models/components/checkoutpublic' import type { CheckoutUpdatePublic } from '@polar-sh/sdk/models/components/checkoutupdatepublic' import { ProductCheckoutPublic } from '../guards' @@ -13,13 +14,21 @@ import ProductPriceLabel from './ProductPriceLabel' const CheckoutProductAmountLabel = ({ checkout, layout = 'default', + locale = 'en', }: { checkout: ProductCheckoutPublic layout?: 'default' | 'stacked' + locale?: SupportedLocale }) => { const { product, productPrice, discount } = checkout if (!discount || productPrice.amountType !== 'fixed') { - return + return ( + + ) } return ( @@ -39,10 +48,15 @@ const CheckoutProductAmountLabel = ({ : product.recurringInterval } intervalCount={product.recurringIntervalCount} + locale={locale} />
- +
@@ -61,6 +75,7 @@ interface CheckoutPricingProps { update?: (data: CheckoutUpdatePublic) => Promise disabled?: boolean layout?: 'default' | 'stacked' + locale?: SupportedLocale } const CheckoutPricing = ({ @@ -68,6 +83,7 @@ const CheckoutPricing = ({ update, disabled, layout = 'default', + locale = 'en', }: CheckoutPricingProps) => { const { product, productPrice, amount } = checkout @@ -76,13 +92,17 @@ const CheckoutPricing = ({

{productPrice.amountType !== 'custom' ? ( - + ) : ( formatCurrencyNumber(amount, productPrice.priceCurrency, 0) )}

- +
) diff --git a/clients/packages/checkout/src/components/CheckoutProductSwitcher.tsx b/clients/packages/checkout/src/components/CheckoutProductSwitcher.tsx index d2bddec8c0..65e5b9380e 100644 --- a/clients/packages/checkout/src/components/CheckoutProductSwitcher.tsx +++ b/clients/packages/checkout/src/components/CheckoutProductSwitcher.tsx @@ -1,5 +1,6 @@ 'use client' +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { CheckoutUpdatePublic } from '@polar-sh/sdk/models/components/checkoutupdatepublic' import { LegacyRecurringProductPrice } from '@polar-sh/sdk/models/components/legacyrecurringproductprice.js' import type { ProductPrice } from '@polar-sh/sdk/models/components/productprice.js' @@ -9,7 +10,7 @@ import { } from '@polar-sh/ui/components/ui/radio-group' import { ThemingPresetProps } from '@polar-sh/ui/hooks/theming' import { cn } from '@polar-sh/ui/lib/utils' -import { Fragment, useCallback } from 'react' +import { Fragment, useCallback, useMemo } from 'react' import type { ProductCheckoutPublic } from '../guards' import { formatRecurringFrequency, @@ -22,13 +23,16 @@ interface CheckoutProductSwitcherProps { update?: (data: CheckoutUpdatePublic) => Promise disabled?: boolean themePreset: ThemingPresetProps + locale?: SupportedLocale } const CheckoutProductSwitcher = ({ checkout, update, themePreset, + locale = 'en', }: CheckoutProductSwitcherProps) => { + const t = useMemo(() => getTranslations(locale), [locale]) const { product: selectedProduct, productPrice: selectedPrice, @@ -71,11 +75,16 @@ const CheckoutProductSwitcher = ({ const intervalCount = product.recurringIntervalCount if (interval) { - const recurringLabel = formatRecurringFrequency(interval, intervalCount) - return `Billed ${recurringLabel}` + const recurringLabel = formatRecurringFrequency( + interval, + intervalCount, + t.pricing.frequency, + locale, + ) + return t.pricing.billed.replace('{frequency}', recurringLabel) } - return `One-time purchase` + return t.pricing.oneTimePurchase } return ( @@ -105,7 +114,11 @@ const CheckoutProductSwitcher = ({ />
{product.name}
- +
@@ -137,6 +150,7 @@ const CheckoutProductSwitcher = ({
diff --git a/clients/packages/checkout/src/components/CheckoutSeatSelector.tsx b/clients/packages/checkout/src/components/CheckoutSeatSelector.tsx index fda7c9b6cb..2149fe9132 100644 --- a/clients/packages/checkout/src/components/CheckoutSeatSelector.tsx +++ b/clients/packages/checkout/src/components/CheckoutSeatSelector.tsx @@ -1,23 +1,27 @@ 'use client' +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { CheckoutUpdatePublic } from '@polar-sh/sdk/models/components/checkoutupdatepublic' import { HTTPValidationError } from '@polar-sh/sdk/models/errors/httpvalidationerror' import Button from '@polar-sh/ui/components/atoms/Button' import Input from '@polar-sh/ui/components/atoms/Input' import { formatCurrencyAndAmount } from '@polar-sh/ui/lib/money' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import type { ProductCheckoutPublic } from '../guards' import MeteredPricesDisplay from './MeteredPricesDisplay' export interface CheckoutSeatSelectorProps { checkout: ProductCheckoutPublic update: (body: CheckoutUpdatePublic) => Promise + locale?: SupportedLocale } const CheckoutSeatSelector = ({ checkout, update, + locale = 'en', }: CheckoutSeatSelectorProps) => { + const t = useMemo(() => getTranslations(locale), [locale]) const [isUpdating, setIsUpdating] = useState(false) const [isEditing, setIsEditing] = useState(false) const [inputValue, setInputValue] = useState('') @@ -149,13 +153,14 @@ const CheckoutSeatSelector = ({ {formatCurrencyAndAmount(netAmount, currency, 0)}

- {formatCurrencyAndAmount(pricePerSeat, currency, 0)} per seat + {formatCurrencyAndAmount(pricePerSeat, currency, 0)}{' '} + {t.pricing.perSeat}

{/* Seat Selector */}
- +
) } diff --git a/clients/packages/checkout/src/components/MeteredPriceLabel.tsx b/clients/packages/checkout/src/components/MeteredPriceLabel.tsx index 514ee0be50..b5348db9b2 100644 --- a/clients/packages/checkout/src/components/MeteredPriceLabel.tsx +++ b/clients/packages/checkout/src/components/MeteredPriceLabel.tsx @@ -1,11 +1,19 @@ +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { ProductPriceMeteredUnit } from '@polar-sh/sdk/models/components/productpricemeteredunit.js' +import { useMemo } from 'react' import { formatUnitAmount } from '../utils/money' interface MeteredPriceLabelProps { price: ProductPriceMeteredUnit + locale?: SupportedLocale } -const MeteredPriceLabel: React.FC = ({ price }) => { +const MeteredPriceLabel: React.FC = ({ + price, + locale = 'en', +}) => { + const t = useMemo(() => getTranslations(locale), [locale]) + return (
{formatUnitAmount( @@ -13,7 +21,7 @@ const MeteredPriceLabel: React.FC = ({ price }) => { price.priceCurrency, )} - / unit + {t.pricing.perUnit}
) diff --git a/clients/packages/checkout/src/components/MeteredPricesDisplay.tsx b/clients/packages/checkout/src/components/MeteredPricesDisplay.tsx index c6fee3a575..b6a7ec060b 100644 --- a/clients/packages/checkout/src/components/MeteredPricesDisplay.tsx +++ b/clients/packages/checkout/src/components/MeteredPricesDisplay.tsx @@ -1,5 +1,6 @@ 'use client' +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { ProductPrice } from '@polar-sh/sdk/models/components/productprice' import { useMemo } from 'react' import { ProductCheckoutPublic } from '../guards' @@ -28,9 +29,14 @@ const GaugeIcon = ({ className }: { className?: string }) => { interface MeteredPricesDisplayProps { checkout: ProductCheckoutPublic + locale?: SupportedLocale } -const MeteredPricesDisplay = ({ checkout }: MeteredPricesDisplayProps) => { +const MeteredPricesDisplay = ({ + checkout, + locale = 'en', +}: MeteredPricesDisplayProps) => { + const t = useMemo(() => getTranslations(locale), [locale]) const { product, prices, productPrice } = checkout // Get the metered prices, minus the currently selected one, in case there are only metered prices @@ -48,14 +54,20 @@ const MeteredPricesDisplay = ({ checkout }: MeteredPricesDisplayProps) => { return (
-

+ Additional metered usage

+

+ {t.pricing.additionalMeteredUsage} +

{meteredPrices.map((price) => (
- +
))}
diff --git a/clients/packages/checkout/src/components/ProductPriceLabel.tsx b/clients/packages/checkout/src/components/ProductPriceLabel.tsx index 13302bea84..7f22ccf54c 100644 --- a/clients/packages/checkout/src/components/ProductPriceLabel.tsx +++ b/clients/packages/checkout/src/components/ProductPriceLabel.tsx @@ -1,6 +1,8 @@ +import { getTranslations, type SupportedLocale } from '@polar-sh/i18n' import type { CheckoutProduct } from '@polar-sh/sdk/models/components/checkoutproduct' import type { LegacyRecurringProductPrice } from '@polar-sh/sdk/models/components/legacyrecurringproductprice' import type { ProductPrice } from '@polar-sh/sdk/models/components/productprice' +import { useMemo } from 'react' import { isLegacyRecurringPrice } from '../utils/product' import AmountLabel from './AmountLabel' import MeteredPriceLabel from './MeteredPriceLabel' @@ -8,12 +10,16 @@ import MeteredPriceLabel from './MeteredPriceLabel' interface ProductPriceLabelProps { product: CheckoutProduct price: ProductPrice | LegacyRecurringProductPrice + locale?: SupportedLocale } const ProductPriceLabel: React.FC = ({ product, price, + locale = 'en', }) => { + const t = useMemo(() => getTranslations(locale), [locale]) + if (price.amountType === 'fixed') { return ( = ({ : product.recurringInterval } intervalCount={product.recurringIntervalCount} + locale={locale} /> ) } else if (price.amountType === 'custom') { - return
Pay what you want
+ return ( +
{t.pricing.payWhatYouWant}
+ ) } else if (price.amountType === 'free') { - return
Free
+ return
{t.pricing.free}
} else if (price.amountType === 'metered_unit') { return (
{price.meter.name} {' — '} - +
) } diff --git a/clients/packages/checkout/src/embed.ts b/clients/packages/checkout/src/embed.ts index 942801664e..97311480c0 100644 --- a/clients/packages/checkout/src/embed.ts +++ b/clients/packages/checkout/src/embed.ts @@ -92,6 +92,7 @@ class EmbedCheckout { * * @param url A Checkout Link. * @param theme The theme of the embedded checkout. Defaults to `light`. + * @param locale The locale of the embedded checkout. Defaults to browser detection. * @returns A promise that resolves to an instance of EmbedCheckout. * The promise resolves when the embedded checkout is fully loaded. @@ -99,6 +100,7 @@ class EmbedCheckout { public static async create( url: string, theme?: 'light' | 'dark', + locale?: string, ): Promise { const styleSheet = document.createElement('style') styleSheet.innerText = ` @@ -144,6 +146,9 @@ class EmbedCheckout { if (theme) { parsedURL.searchParams.set('theme', theme) } + if (locale) { + parsedURL.searchParams.set('locale', locale) + } const embedURL = parsedURL.toString() // Create iframe @@ -182,10 +187,11 @@ class EmbedCheckout { * The Checkout Link is either the `href` attribute for a link element or the value of `data-polar-checkout` attribute. * * The theme can be optionally set using the `data-polar-checkout-theme` attribute. + * The locale can be optionally set using the `data-polar-checkout-locale` attribute. * * @example * ```html - * Checkout + * Checkout * ``` */ public static init(): void { @@ -291,7 +297,9 @@ class EmbedCheckout { | 'light' | 'dark' | undefined - EmbedCheckout.create(url, theme) + const locale = + checkoutElement.getAttribute('data-polar-checkout-locale') || undefined + EmbedCheckout.create(url, theme, locale) } /** diff --git a/clients/packages/checkout/src/providers/index.ts b/clients/packages/checkout/src/providers/index.ts index e94b3f3c49..16134cab36 100644 --- a/clients/packages/checkout/src/providers/index.ts +++ b/clients/packages/checkout/src/providers/index.ts @@ -1,5 +1,7 @@ 'use client' +export { getTranslations } from '@polar-sh/i18n' +export type { CheckoutTranslations, SupportedLocale } from '@polar-sh/i18n' export { CheckoutFormContext, CheckoutFormProvider, diff --git a/clients/packages/checkout/src/utils/product.ts b/clients/packages/checkout/src/utils/product.ts index 1506261c1d..0ab7399b11 100644 --- a/clients/packages/checkout/src/utils/product.ts +++ b/clients/packages/checkout/src/utils/product.ts @@ -1,54 +1,84 @@ +import type { CheckoutTranslations } from '@polar-sh/i18n' import type { LegacyRecurringProductPrice } from '@polar-sh/sdk/models/components/legacyrecurringproductprice' import type { ProductPrice } from '@polar-sh/sdk/models/components/productprice' import type { ProductPriceMeteredUnit } from '@polar-sh/sdk/models/components/productpricemeteredunit' import type { SubscriptionRecurringInterval } from '@polar-sh/sdk/models/components/subscriptionrecurringinterval' -const ordinalRules = new Intl.PluralRules('en', { type: 'ordinal' }) - -const suffixes = { - zero: '', - one: 'st', - two: 'nd', - few: 'rd', - many: '', - other: 'th', -} as const - -const ordinal = (number: number): string => { - const category = ordinalRules.select(number) - const suffix = suffixes[category] - return number + suffix +const createOrdinalFormatter = (locale: string) => { + const ordinalRules = new Intl.PluralRules(locale, { type: 'ordinal' }) + + if (locale === 'nl') { + return (number: number): string => `${number}e` + } + + const suffixes = { + zero: '', + one: 'st', + two: 'nd', + few: 'rd', + many: '', + other: 'th', + } as const + + return (number: number): string => { + const category = ordinalRules.select(number) + const suffix = suffixes[category] + return number + suffix + } } +const defaultIntervalTranslations: CheckoutTranslations['pricing']['interval'] = + { + day: 'dy', + week: 'wk', + month: 'mo', + year: 'yr', + } + +const defaultFrequencyTranslations: CheckoutTranslations['pricing']['frequency'] = + { + daily: 'daily', + weekly: 'weekly', + monthly: 'monthly', + yearly: 'yearly', + every: 'every {ordinal} {interval}', + } + /** * Format a recurring interval with optional count for display in amounts/periods * @param interval - The recurring interval (day, week, month, year) * @param intervalCount - The number of intervals (e.g., 2 for "2nd month") * @param format - Display format: 'short' (mo, yr) or 'long' (month, year) + * @param translations - Optional translations for interval labels + * @param locale - Optional locale for ordinal formatting (default: 'en') * @returns Formatted string like "month", "2nd month", "mo", "3rd wk" */ export const formatRecurringInterval = ( interval: SubscriptionRecurringInterval | null | undefined, intervalCount?: number | null, format: 'short' | 'long' = 'long', + translations?: CheckoutTranslations['pricing']['interval'], + locale: string = 'en', ): string => { if (!interval) { return '' } + const ordinal = createOrdinalFormatter(locale) const count = intervalCount && intervalCount > 1 ? intervalCount : null const prefix = count ? `${ordinal(count)} ` : '' + const t = translations ?? defaultIntervalTranslations if (format === 'short') { switch (interval) { case 'day': - return `${prefix}dy` + return `${prefix}${t.day}` case 'week': - return `${prefix}wk` + return `${prefix}${t.week}` case 'month': - return `${prefix}mo` + return `${prefix}${t.month}` case 'year': - return `${prefix}yr` + return `${prefix}${t.year}` default: return '' } @@ -61,31 +91,39 @@ export const formatRecurringInterval = ( * Format a recurring frequency for display in billing descriptions * @param interval - The recurring interval (day, week, month, year) * @param intervalCount - The number of intervals (e.g., 2 for "every 2nd month") + * @param translations - Optional translations for frequency labels + * @param locale - Optional locale for ordinal formatting (default: 'en') * @returns Formatted string like "monthly", "every 2nd month", "yearly", "every 3rd week" */ export const formatRecurringFrequency = ( interval: SubscriptionRecurringInterval | null | undefined, intervalCount?: number | null, + translations?: CheckoutTranslations['pricing']['frequency'], + locale: string = 'en', ): string => { if (!interval) { return '' } + const ordinal = createOrdinalFormatter(locale) const count = intervalCount && intervalCount > 1 ? intervalCount : null + const t = translations ?? defaultFrequencyTranslations if (count) { - return `every ${ordinal(count)} ${interval}` + return t.every + .replace('{ordinal}', ordinal(count)) + .replace('{interval}', interval) } switch (interval) { case 'day': - return 'daily' + return t.daily case 'week': - return 'weekly' + return t.weekly case 'month': - return 'monthly' + return t.monthly case 'year': - return 'yearly' + return t.yearly default: return interval } diff --git a/clients/packages/client/src/v1.ts b/clients/packages/client/src/v1.ts index 723fef90c8..0b6a3770b2 100644 --- a/clients/packages/client/src/v1.ts +++ b/clients/packages/client/src/v1.ts @@ -7473,6 +7473,7 @@ export interface components { /** @description The error information if the benefit grant failed with an unrecoverable error. */ error?: components['schemas']['BenefitGrantError'] | null customer: components['schemas']['Customer'] + member?: components['schemas']['Member'] | null benefit: components['schemas']['BenefitCustom'] properties: components['schemas']['BenefitGrantCustomProperties'] previous_properties?: @@ -7559,6 +7560,7 @@ export interface components { /** @description The error information if the benefit grant failed with an unrecoverable error. */ error?: components['schemas']['BenefitGrantError'] | null customer: components['schemas']['Customer'] + member?: components['schemas']['Member'] | null benefit: components['schemas']['BenefitDiscord'] properties: components['schemas']['BenefitGrantDiscordProperties'] previous_properties?: @@ -7639,6 +7641,7 @@ export interface components { /** @description The error information if the benefit grant failed with an unrecoverable error. */ error?: components['schemas']['BenefitGrantError'] | null customer: components['schemas']['Customer'] + member?: components['schemas']['Member'] | null benefit: components['schemas']['BenefitDownloadables'] properties: components['schemas']['BenefitGrantDownloadablesProperties'] previous_properties?: @@ -7739,6 +7742,7 @@ export interface components { /** @description The error information if the benefit grant failed with an unrecoverable error. */ error?: components['schemas']['BenefitGrantError'] | null customer: components['schemas']['Customer'] + member?: components['schemas']['Member'] | null benefit: components['schemas']['BenefitGitHubRepository'] properties: components['schemas']['BenefitGrantGitHubRepositoryProperties'] previous_properties?: @@ -7821,6 +7825,7 @@ export interface components { /** @description The error information if the benefit grant failed with an unrecoverable error. */ error?: components['schemas']['BenefitGrantError'] | null customer: components['schemas']['Customer'] + member?: components['schemas']['Member'] | null benefit: components['schemas']['BenefitLicenseKeys'] properties: components['schemas']['BenefitGrantLicenseKeysProperties'] previous_properties?: @@ -7834,6 +7839,8 @@ export interface components { /** Benefit Grant Id */ benefit_grant_id: string benefit_type: components['schemas']['BenefitType'] + /** Member Id */ + member_id?: string } /** BenefitGrantMeterCreditProperties */ BenefitGrantMeterCreditProperties: { @@ -7913,6 +7920,7 @@ export interface components { /** @description The error information if the benefit grant failed with an unrecoverable error. */ error?: components['schemas']['BenefitGrantError'] | null customer: components['schemas']['Customer'] + member?: components['schemas']['Member'] | null benefit: components['schemas']['BenefitMeterCredit'] properties: components['schemas']['BenefitGrantMeterCreditProperties'] previous_properties?: @@ -9059,6 +9067,11 @@ export interface components { customer_billing_address: components['schemas']['Address'] | null /** Customer Tax Id */ customer_tax_id: string | null + /** + * Locale + * @description Locale for translations. + */ + locale?: string | null /** Payment Processor Metadata */ payment_processor_metadata: { [key: string]: string @@ -9181,6 +9194,11 @@ export interface components { customer_billing_address?: components['schemas']['AddressInput'] | null /** Customer Tax Id */ customer_tax_id?: string | null + /** + * Locale + * @description Locale for translations. E.g. 'en', 'nl', 'sv'. + */ + locale?: string | null /** * Discount Code * @description Discount code to apply to the checkout. @@ -10055,6 +10073,11 @@ export interface components { * @description If you plan to embed the checkout session, set this to the Origin of the embedding page. It'll allow the Polar iframe to communicate with the parent page. */ embed_origin?: string | null + /** + * Locale + * @description Locale for translations. E.g. 'en', 'nl', 'sv'. + */ + locale?: string | null /** * Product Price Id * Format: uuid4 @@ -10280,6 +10303,11 @@ export interface components { * @description If you plan to embed the checkout session, set this to the Origin of the embedding page. It'll allow the Polar iframe to communicate with the parent page. */ embed_origin?: string | null + /** + * Locale + * @description Locale for translations. E.g. 'en', 'nl', 'sv'. + */ + locale?: string | null currency?: components['schemas']['PresentmentCurrency'] | null /** * Product Id @@ -10422,6 +10450,11 @@ export interface components { * @description If you plan to embed the checkout session, set this to the Origin of the embedding page. It'll allow the Polar iframe to communicate with the parent page. */ embed_origin?: string | null + /** + * Locale + * @description Locale for translations. E.g. 'en', 'nl', 'sv'. + */ + locale?: string | null currency?: components['schemas']['PresentmentCurrency'] | null /** * Products @@ -10652,6 +10685,11 @@ export interface components { customer_billing_address: components['schemas']['Address'] | null /** Customer Tax Id */ customer_tax_id: string | null + /** + * Locale + * @description Locale for translations. + */ + locale?: string | null /** Payment Processor Metadata */ payment_processor_metadata: { [key: string]: string @@ -10909,6 +10947,11 @@ export interface components { customer_billing_address: components['schemas']['Address'] | null /** Customer Tax Id */ customer_tax_id: string | null + /** + * Locale + * @description Locale for translations. + */ + locale?: string | null /** Payment Processor Metadata */ payment_processor_metadata: { [key: string]: string @@ -11017,6 +11060,11 @@ export interface components { customer_billing_address?: components['schemas']['AddressInput'] | null /** Customer Tax Id */ customer_tax_id?: string | null + /** + * Locale + * @description Locale for translations. E.g. 'en', 'nl', 'sv'. + */ + locale?: string | null /** @description The interval unit for the trial period. */ trial_interval?: components['schemas']['TrialInterval'] | null /** @@ -11138,6 +11186,11 @@ export interface components { customer_billing_address?: components['schemas']['AddressInput'] | null /** Customer Tax Id */ customer_tax_id?: string | null + /** + * Locale + * @description Locale for translations. E.g. 'en', 'nl', 'sv'. + */ + locale?: string | null /** * Discount Code * @description Discount code to apply to the checkout. @@ -12466,6 +12519,14 @@ export interface components { billing_address: components['schemas']['Address'] | null /** Tax Id */ tax_id: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * Format: uuid4 @@ -12903,6 +12964,14 @@ export interface components { billing_address?: components['schemas']['AddressInput'] | null /** Tax Id */ tax_id?: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * @description The ID of the organization owning the customer. **Required unless you use an organization token.** @@ -14261,6 +14330,14 @@ export interface components { billing_address: components['schemas']['Address'] | null /** Tax Id */ tax_id: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * Format: uuid4 @@ -14955,6 +15032,14 @@ export interface components { billing_address?: components['schemas']['AddressInput'] | null /** Tax Id */ tax_id?: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * External Id * @description The ID of the customer in your system. This must be unique within the organization. Once set, it can't be updated. @@ -14992,6 +15077,14 @@ export interface components { billing_address?: components['schemas']['AddressInput'] | null /** Tax Id */ tax_id?: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null } /** * CustomerUpdatedEvent @@ -15188,6 +15281,14 @@ export interface components { billing_address: components['schemas']['Address'] | null /** Tax Id */ tax_id: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * Format: uuid4 @@ -17575,6 +17676,14 @@ export interface components { billing_address: components['schemas']['Address'] | null /** Tax Id */ tax_id: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * Format: uuid4 @@ -19599,6 +19708,14 @@ export interface components { billing_address: components['schemas']['Address'] | null /** Tax Id */ tax_id: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * Format: uuid4 @@ -23560,6 +23677,14 @@ export interface components { billing_address: components['schemas']['Address'] | null /** Tax Id */ tax_id: [string, components['schemas']['TaxIDFormat']] | null + /** + * Locale + * @description The locale of the customer, used for translations. + * @example en + * @example nl + * @example sv + */ + locale?: string | null /** * Organization Id * Format: uuid4 @@ -31068,7 +31193,6 @@ export interface operations { | 'W-SU' | 'WET' | 'Zulu' - | 'localtime' /** @description Interval between two timestamps. */ interval: components['schemas']['TimeInterval'] /** @description Filter by organization ID. */ @@ -35943,7 +36067,6 @@ export interface operations { | 'W-SU' | 'WET' | 'Zulu' - | 'localtime' /** @description Interval between two dates. */ interval: components['schemas']['TimeInterval'] /** @description Filter events following filter clauses. JSON string following the same schema a meter filter clause. */ @@ -38766,7 +38889,6 @@ export const pathsV1MetricsGetParametersQueryTimezoneValues: ReadonlyArray< 'W-SU', 'WET', 'Zulu', - 'localtime', ] export const pathsV1EventsStatisticsTimeseriesGetParametersQueryTimezoneValues: ReadonlyArray< paths['/v1/events/statistics/timeseries']['get']['parameters']['query']['timezone'] @@ -39369,7 +39491,6 @@ export const pathsV1EventsStatisticsTimeseriesGetParametersQueryTimezoneValues: 'W-SU', 'WET', 'Zulu', - 'localtime', ] export const accountTypeValues: ReadonlyArray< components['schemas']['AccountType'] diff --git a/clients/packages/i18n/locales/en.json b/clients/packages/i18n/locales/en.json new file mode 100644 index 0000000000..c1313b58a7 --- /dev/null +++ b/clients/packages/i18n/locales/en.json @@ -0,0 +1,143 @@ +{ + "form": { + "email": "Email", + "cardholderName": "Cardholder name", + "billingAddress": "Billing address", + "businessPurchase": "I'm purchasing as a business", + "businessName": "Business name", + "taxId": "Tax ID", + "discountCode": "Discount code", + "optional": "Optional", + "apply": "Apply", + "line1": "Line 1", + "line2": "Line 2", + "postalCode": "Postal code", + "city": "City", + "required": "This field is required", + "country": "Country", + "state": "State", + "province": "Province", + "stateOrProvince": "State / Province", + "included": "Included" + }, + "pricing": { + "subtotal": "Subtotal", + "taxableAmount": "Taxable amount", + "taxes": "Taxes", + "total": "Total", + "every": "Every", + "additionalMeteredUsage": "+ Additional metered usage", + "free": "Free", + "forFirstInterval": "for the first", + "forFirstMonths": "for the first {count} months", + "forFirstYears": "for the first {count} years", + "trial": "trial", + "trialPlural": "trial", + "trialEnds": "Trial ends", + "payWhatYouWant": "Pay what you want", + "perUnit": "/ unit", + "perSeat": "per seat", + "numberOfSeats": "Number of seats", + "billed": "Billed {frequency}", + "oneTimePurchase": "One-time purchase", + "interval": { + "day": "dy", + "week": "wk", + "month": "mo", + "year": "yr" + }, + "frequency": { + "daily": "daily", + "weekly": "weekly", + "monthly": "monthly", + "yearly": "yearly", + "every": "every {ordinal} {interval}" + } + }, + "buttons": { + "startTrial": "Start Trial", + "subscribe": "Subscribe", + "pay": "Pay", + "submit": "Submit" + }, + "footer": { + "merchantInfo": "This order is processed by our online reseller & Merchant of Record, Polar, who also handles order-related inquiries and returns.", + "poweredBy": "Powered by" + }, + "errors": { + "paymentsUnavailable": "Payments are currently unavailable" + }, + "confirmation": { + "processing": "We are processing your order", + "success": "Your order was successful!", + "failed": "A problem occurred while processing your order", + "waitingWebhooks": "Please wait while we are listening for those webhooks.", + "eligible": "You're now eligible for the benefits of {productName}.", + "tryAgain": "Please try again or contact support.", + "confirmPayment": "Confirm payment", + "grantingBenefits": "Granting benefits..." + }, + "email": { + "common": { + "accessPurchase": "Access my purchase", + "manageSubscription": "Manage my subscription", + "viewSubscription": "View my subscription", + "completePayment": "Complete Payment", + "troubleWithButton": "If you're having trouble with the button above, copy and paste the URL below into your web browser." + }, + "orderConfirmation": { + "subject": "Thank you for your order!", + "preview": "Thank you for your order of {description}!", + "heading": "Thank you for your order!", + "processed": "Your order of {description} is now processed." + }, + "subscriptionConfirmation": { + "subject": "Your subscription to {product} is now active", + "preview": "Thank you for your subscription to {product}!", + "heading": "Thank you for your subscription!", + "active": "Your subscription to {product} is now active." + }, + "subscriptionCycled": { + "subject": "Your subscription to {product} has been renewed", + "preview": "Your subscription to {product} has been renewed", + "heading": "Your subscription has been renewed", + "renewed": "Your subscription to {product} has been renewed." + }, + "subscriptionCancellation": { + "subject": "Your subscription to {product} has been canceled", + "preview": "Your subscription to {product} has been canceled", + "heading": "Your subscription has been canceled", + "sorryToSeeYouGo": "We're sorry to see you go! Your subscription to {product} will remain active until {endDate}, after which it will be canceled.", + "changeYourMind": "If you change your mind, you can renew your subscription anytime before the end date.", + "benefitsContinue": "Meanwhile, you will continue to have access to the following benefits:" + }, + "subscriptionPastDue": { + "subject": "Your {product} subscription payment is past due", + "preview": "Your {product} subscription payment is past due", + "heading": "Your subscription payment is past due", + "paymentFailed": "We were unable to process your payment for your {product} subscription. Your subscription is now past due and access to benefits has been temporarily suspended.", + "updatePayment": "To restore access to your subscription benefits, please update your payment method and complete the payment." + }, + "subscriptionRevoked": { + "subject": "Your subscription to {product} has now ended", + "preview": "Your subscription to {product} has now ended", + "heading": "Your subscription has now ended", + "thankYou": "Thank you for being a subscriber of {product}.", + "welcomeBack": "We hope to see you again in the future - you're always welcome back." + }, + "subscriptionUncanceled": { + "subject": "Your subscription to {product} is now uncanceled", + "preview": "Your subscription to {product} is now uncanceled", + "heading": "Your subscription is now uncanceled", + "noLongerCanceled": "Your subscription to {product} is no longer canceled." + }, + "subscriptionUpdated": { + "subject": "Your subscription has been updated to {product}", + "preview": "Your subscription has been updated to {product}", + "heading": "Your subscription has been updated", + "changedTo": "Your subscription has been successfully changed to {product}.", + "immediateWithCharge": "The changes take effect immediately. The pro-rated amount has been charged to your account as part of this update.", + "immediateNextCycle": "The changes take effect immediately. The pro-rated amount will be reflected on your next billing cycle." + } + } +} diff --git a/clients/packages/i18n/locales/nl.json b/clients/packages/i18n/locales/nl.json new file mode 100644 index 0000000000..059b0c0ff3 --- /dev/null +++ b/clients/packages/i18n/locales/nl.json @@ -0,0 +1,143 @@ +{ + "form": { + "email": "E-mail", + "cardholderName": "Naam kaarthouder", + "billingAddress": "Factuuradres", + "businessPurchase": "Ik koop als bedrijf", + "businessName": "Bedrijfsnaam", + "taxId": "BTW-nummer", + "discountCode": "Kortingscode", + "optional": "Optioneel", + "apply": "Toepassen", + "line1": "Adresregel 1", + "line2": "Adresregel 2", + "postalCode": "Postcode", + "city": "Plaats", + "required": "Dit veld is verplicht", + "country": "Land", + "state": "Staat", + "province": "Provincie", + "stateOrProvince": "Staat / Provincie", + "included": "Inbegrepen" + }, + "pricing": { + "subtotal": "Subtotaal", + "taxableAmount": "Belastbaar bedrag", + "taxes": "Belastingen", + "total": "Totaal", + "every": "Elke", + "additionalMeteredUsage": "+ Extra verbruikskosten", + "free": "Gratis", + "forFirstInterval": "voor de eerste", + "forFirstMonths": "voor de eerste {count} maanden", + "forFirstYears": "voor de eerste {count} jaren", + "trial": "proefperiode", + "trialPlural": "proefperiode", + "trialEnds": "Proefperiode eindigt", + "payWhatYouWant": "Betaal wat je wilt", + "perUnit": "/ eenheid", + "perSeat": "per zetel", + "numberOfSeats": "Aantal zetels", + "billed": "Gefactureerd {frequency}", + "oneTimePurchase": "Eenmalige aankoop", + "interval": { + "day": "dg", + "week": "wk", + "month": "p.m.", + "year": "p.j." + }, + "frequency": { + "daily": "dagelijks", + "weekly": "wekelijks", + "monthly": "maandelijks", + "yearly": "jaarlijks", + "every": "elke {ordinal}e {interval}" + } + }, + "buttons": { + "startTrial": "Start proefperiode", + "subscribe": "Abonneren", + "pay": "Betalen", + "submit": "Verzenden" + }, + "footer": { + "merchantInfo": "Deze bestelling wordt verwerkt door onze online reseller & Merchant of Record, Polar, die ook bestellingsgerelateerde vragen en retouren afhandelt.", + "poweredBy": "Mogelijk gemaakt door" + }, + "errors": { + "paymentsUnavailable": "Betalingen zijn momenteel niet beschikbaar" + }, + "confirmation": { + "processing": "We verwerken uw bestelling", + "success": "Uw bestelling is gelukt!", + "failed": "Er is een probleem opgetreden bij het verwerken van uw bestelling", + "waitingWebhooks": "Even geduld terwijl we naar de webhooks luisteren.", + "eligible": "U komt nu in aanmerking voor de voordelen van {productName}.", + "tryAgain": "Probeer het opnieuw of neem contact op met support.", + "confirmPayment": "Bevestig betaling", + "grantingBenefits": "Voordelen worden toegekend..." + }, + "email": { + "common": { + "accessPurchase": "Naar mijn aankoop", + "manageSubscription": "Beheer mijn abonnement", + "viewSubscription": "Bekijk mijn abonnement", + "completePayment": "Betaling voltooien", + "troubleWithButton": "Als de knop hierboven niet werkt, kopieer en plak dan de onderstaande URL in uw webbrowser." + }, + "orderConfirmation": { + "subject": "Bedankt voor uw bestelling!", + "preview": "Bedankt voor uw bestelling van {description}!", + "heading": "Bedankt voor uw bestelling!", + "processed": "Uw bestelling van {description} is nu verwerkt." + }, + "subscriptionConfirmation": { + "subject": "Uw abonnement op {product} is nu actief", + "preview": "Bedankt voor uw abonnement op {product}!", + "heading": "Bedankt voor uw abonnement!", + "active": "Uw abonnement op {product} is nu actief." + }, + "subscriptionCycled": { + "subject": "Uw abonnement op {product} is verlengd", + "preview": "Uw abonnement op {product} is verlengd", + "heading": "Uw abonnement is verlengd", + "renewed": "Uw abonnement op {product} is verlengd." + }, + "subscriptionCancellation": { + "subject": "Uw abonnement op {product} is opgezegd", + "preview": "Uw abonnement op {product} is opgezegd", + "heading": "Uw abonnement is opgezegd", + "sorryToSeeYouGo": "Jammer dat u vertrekt! Uw abonnement op {product} blijft actief tot {endDate}, daarna wordt het beëindigd.", + "changeYourMind": "Als u van gedachten verandert, kunt u uw abonnement op elk moment vóór de einddatum verlengen.", + "benefitsContinue": "In de tussentijd behoudt u toegang tot de volgende voordelen:" + }, + "subscriptionPastDue": { + "subject": "Uw betaling voor {product} is achterstallig", + "preview": "Uw betaling voor {product} is achterstallig", + "heading": "Uw abonnementsbetaling is achterstallig", + "paymentFailed": "We konden uw betaling voor uw {product} abonnement niet verwerken. Uw abonnement is nu achterstallig en de toegang tot voordelen is tijdelijk opgeschort.", + "updatePayment": "Om de toegang tot uw abonnementsvoordelen te herstellen, werk uw betaalmethode bij en voltooi de betaling." + }, + "subscriptionRevoked": { + "subject": "Uw abonnement op {product} is nu beëindigd", + "preview": "Uw abonnement op {product} is nu beëindigd", + "heading": "Uw abonnement is nu beëindigd", + "thankYou": "Bedankt dat u abonnee was van {product}.", + "welcomeBack": "We hopen u in de toekomst weer te zien - u bent altijd welkom terug." + }, + "subscriptionUncanceled": { + "subject": "Uw abonnement op {product} is niet langer opgezegd", + "preview": "Uw abonnement op {product} is niet langer opgezegd", + "heading": "Uw abonnement is niet langer opgezegd", + "noLongerCanceled": "Uw abonnement op {product} is niet langer opgezegd." + }, + "subscriptionUpdated": { + "subject": "Uw abonnement is bijgewerkt naar {product}", + "preview": "Uw abonnement is bijgewerkt naar {product}", + "heading": "Uw abonnement is bijgewerkt", + "changedTo": "Uw abonnement is succesvol gewijzigd naar {product}.", + "immediateWithCharge": "De wijzigingen gaan direct in. Het pro-rata bedrag is als onderdeel van deze update in rekening gebracht.", + "immediateNextCycle": "De wijzigingen gaan direct in. Het pro-rata bedrag wordt verrekend in uw volgende factureringsperiode." + } + } +} diff --git a/clients/packages/i18n/locales/sv.json b/clients/packages/i18n/locales/sv.json new file mode 100644 index 0000000000..f7ef8c9eb1 --- /dev/null +++ b/clients/packages/i18n/locales/sv.json @@ -0,0 +1,143 @@ +{ + "form": { + "email": "E-post", + "cardholderName": "Kortinnehavarens namn", + "billingAddress": "Faktureringsadress", + "businessPurchase": "Jag köper som företag", + "businessName": "Företagsnamn", + "taxId": "Organisationsnummer", + "discountCode": "Rabattkod", + "optional": "Valfritt", + "apply": "Använd", + "line1": "Adressrad 1", + "line2": "Adressrad 2", + "postalCode": "Postnummer", + "city": "Stad", + "required": "Detta fält är obligatoriskt", + "country": "Land", + "state": "Delstat", + "province": "Provins", + "stateOrProvince": "Delstat / Provins", + "included": "Inkluderat" + }, + "pricing": { + "subtotal": "Delsumma", + "taxableAmount": "Beskattningsbart belopp", + "taxes": "Skatter", + "total": "Totalt", + "every": "Varje", + "additionalMeteredUsage": "+ Ytterligare mätbar användning", + "free": "Gratis", + "forFirstInterval": "för den första", + "forFirstMonths": "för de första {count} månaderna", + "forFirstYears": "för de första {count} åren", + "trial": "provperiod", + "trialPlural": "provperiod", + "trialEnds": "Provperioden slutar", + "payWhatYouWant": "Betala vad du vill", + "perUnit": "/ enhet", + "perSeat": "per licens", + "numberOfSeats": "Antal licenser", + "billed": "Faktureras {frequency}", + "oneTimePurchase": "Engångsköp", + "interval": { + "day": "dg", + "week": "ve", + "month": "mån", + "year": "år" + }, + "frequency": { + "daily": "dagligen", + "weekly": "veckovis", + "monthly": "månadsvis", + "yearly": "årsvis", + "every": "var {ordinal} {interval}" + } + }, + "buttons": { + "startTrial": "Starta provperiod", + "subscribe": "Prenumerera", + "pay": "Betala", + "submit": "Skicka" + }, + "footer": { + "merchantInfo": "Denna beställning hanteras av vår onlineåterförsäljare och betalningsansvarige, Polar, som även hanterar orderrelaterade förfrågningar och returer.", + "poweredBy": "Drivs av" + }, + "errors": { + "paymentsUnavailable": "Betalningar är för närvarande otillgängliga" + }, + "confirmation": { + "processing": "Vi behandlar din beställning", + "success": "Din beställning genomfördes!", + "failed": "Ett problem uppstod vid behandlingen av din beställning", + "waitingWebhooks": "Vänta medan vi lyssnar efter webhooks.", + "eligible": "Du har nu tillgång till förmånerna för {productName}.", + "tryAgain": "Försök igen eller kontakta supporten.", + "confirmPayment": "Bekräfta betalning", + "grantingBenefits": "Tilldelar förmåner..." + }, + "email": { + "common": { + "accessPurchase": "Gå till mitt köp", + "manageSubscription": "Hantera min prenumeration", + "viewSubscription": "Visa min prenumeration", + "completePayment": "Slutför betalning", + "troubleWithButton": "Om du har problem med knappen ovan, kopiera och klistra in URL:en nedan i din webbläsare." + }, + "orderConfirmation": { + "subject": "Tack för din beställning!", + "preview": "Tack för din beställning av {description}!", + "heading": "Tack för din beställning!", + "processed": "Din beställning av {description} är nu behandlad." + }, + "subscriptionConfirmation": { + "subject": "Din prenumeration på {product} är nu aktiv", + "preview": "Tack för din prenumeration på {product}!", + "heading": "Tack för din prenumeration!", + "active": "Din prenumeration på {product} är nu aktiv." + }, + "subscriptionCycled": { + "subject": "Din prenumeration på {product} har förnyats", + "preview": "Din prenumeration på {product} har förnyats", + "heading": "Din prenumeration har förnyats", + "renewed": "Din prenumeration på {product} har förnyats." + }, + "subscriptionCancellation": { + "subject": "Din prenumeration på {product} har avslutats", + "preview": "Din prenumeration på {product} har avslutats", + "heading": "Din prenumeration har avslutats", + "sorryToSeeYouGo": "Tråkigt att du lämnar oss! Din prenumeration på {product} förblir aktiv till {endDate}, därefter avslutas den.", + "changeYourMind": "Om du ändrar dig kan du förnya din prenumeration när som helst före slutdatumet.", + "benefitsContinue": "Under tiden kommer du fortsatt ha tillgång till följande förmåner:" + }, + "subscriptionPastDue": { + "subject": "Din betalning för {product} är försenad", + "preview": "Din betalning för {product} är försenad", + "heading": "Din prenumerationsbetalning är försenad", + "paymentFailed": "Vi kunde inte behandla din betalning för din {product}-prenumeration. Din prenumeration är nu försenad och tillgången till förmåner har tillfälligt pausats.", + "updatePayment": "För att återställa tillgången till dina prenumerationsförmåner, uppdatera din betalningsmetod och slutför betalningen." + }, + "subscriptionRevoked": { + "subject": "Din prenumeration på {product} har nu avslutats", + "preview": "Din prenumeration på {product} har nu avslutats", + "heading": "Din prenumeration har nu avslutats", + "thankYou": "Tack för att du var prenumerant på {product}.", + "welcomeBack": "Vi hoppas att vi ses igen i framtiden - du är alltid välkommen tillbaka." + }, + "subscriptionUncanceled": { + "subject": "Din prenumeration på {product} är inte längre avslutad", + "preview": "Din prenumeration på {product} är inte längre avslutad", + "heading": "Din prenumeration är inte längre avslutad", + "noLongerCanceled": "Din prenumeration på {product} är inte längre avslutad." + }, + "subscriptionUpdated": { + "subject": "Din prenumeration har uppdaterats till {product}", + "preview": "Din prenumeration har uppdaterats till {product}", + "heading": "Din prenumeration har uppdaterats", + "changedTo": "Din prenumeration har ändrats till {product}.", + "immediateWithCharge": "Ändringarna träder i kraft omedelbart. Det proportionella beloppet har debiterats ditt konto som en del av denna uppdatering.", + "immediateNextCycle": "Ändringarna träder i kraft omedelbart. Det proportionella beloppet kommer att återspeglas på din nästa faktureringscykel." + } + } +} diff --git a/clients/packages/i18n/package.json b/clients/packages/i18n/package.json new file mode 100644 index 0000000000..a0944e6a33 --- /dev/null +++ b/clients/packages/i18n/package.json @@ -0,0 +1,30 @@ +{ + "name": "@polar-sh/i18n", + "version": "0.1.0", + "private": true, + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.cjs" + }, + "./locales/*": "./locales/*" + }, + "files": [ + "dist", + "locales" + ], + "scripts": { + "build": "tsup", + "dev": "tsup --watch" + }, + "dependencies": { + "react": "^19.0.0" + }, + "devDependencies": { + "@types/react": "^19.0.0", + "tsup": "^8.0.0", + "typescript": "^5.0.0" + } +} diff --git a/clients/packages/i18n/src/context.tsx b/clients/packages/i18n/src/context.tsx new file mode 100644 index 0000000000..1f1dccccbd --- /dev/null +++ b/clients/packages/i18n/src/context.tsx @@ -0,0 +1,17 @@ +import en from '../locales/en.json' +import nl from '../locales/nl.json' +import sv from '../locales/sv.json' +import type { CheckoutTranslations, SupportedLocale } from './types' +import { DEFAULT_LOCALE } from './types' + +const translations: Record = { + en: en as CheckoutTranslations, + nl: nl as CheckoutTranslations, + sv: sv as CheckoutTranslations, +} + +export function getTranslations( + locale: SupportedLocale = DEFAULT_LOCALE, +): CheckoutTranslations { + return translations[locale] ?? translations[DEFAULT_LOCALE] +} diff --git a/clients/packages/i18n/src/index.ts b/clients/packages/i18n/src/index.ts new file mode 100644 index 0000000000..e8cbc5994f --- /dev/null +++ b/clients/packages/i18n/src/index.ts @@ -0,0 +1,10 @@ +export { + DEFAULT_LOCALE, + SUPPORTED_LOCALES, + isSupportedLocale, + type CheckoutTranslations, + type EmailTranslations, + type SupportedLocale, +} from './types' + +export { getTranslations } from './context' diff --git a/clients/packages/i18n/src/types.ts b/clients/packages/i18n/src/types.ts new file mode 100644 index 0000000000..97135aa5fd --- /dev/null +++ b/clients/packages/i18n/src/types.ts @@ -0,0 +1,153 @@ +export const SUPPORTED_LOCALES = ['en', 'nl', 'sv'] as const +export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number] +export const DEFAULT_LOCALE: SupportedLocale = 'en' + +export function isSupportedLocale(locale: string): locale is SupportedLocale { + return SUPPORTED_LOCALES.includes(locale as SupportedLocale) +} + +export interface CheckoutTranslations { + form: { + email: string + cardholderName: string + billingAddress: string + businessPurchase: string + businessName: string + taxId: string + discountCode: string + optional: string + apply: string + line1: string + line2: string + postalCode: string + city: string + required: string + country: string + state: string + province: string + stateOrProvince: string + included: string + } + pricing: { + subtotal: string + taxableAmount: string + taxes: string + total: string + every: string + additionalMeteredUsage: string + free: string + forFirstInterval: string + forFirstMonths: string + forFirstYears: string + trial: string + trialPlural: string + trialEnds: string + payWhatYouWant: string + perUnit: string + perSeat: string + numberOfSeats: string + billed: string + oneTimePurchase: string + interval: { + day: string + week: string + month: string + year: string + } + frequency: { + daily: string + weekly: string + monthly: string + yearly: string + every: string + } + } + buttons: { + startTrial: string + subscribe: string + pay: string + submit: string + } + footer: { + merchantInfo: string + poweredBy: string + } + errors: { + paymentsUnavailable: string + } + confirmation: { + processing: string + success: string + failed: string + waitingWebhooks: string + eligible: string + tryAgain: string + confirmPayment: string + grantingBenefits: string + } + email: EmailTranslations +} + +export interface EmailTranslations { + common: { + accessPurchase: string + manageSubscription: string + viewSubscription: string + completePayment: string + troubleWithButton: string + } + orderConfirmation: { + subject: string + preview: string + heading: string + processed: string + } + subscriptionConfirmation: { + subject: string + preview: string + heading: string + active: string + } + subscriptionCycled: { + subject: string + preview: string + heading: string + renewed: string + } + subscriptionCancellation: { + subject: string + preview: string + heading: string + sorryToSeeYouGo: string + changeYourMind: string + benefitsContinue: string + } + subscriptionPastDue: { + subject: string + preview: string + heading: string + paymentFailed: string + updatePayment: string + } + subscriptionRevoked: { + subject: string + preview: string + heading: string + thankYou: string + welcomeBack: string + } + subscriptionUncanceled: { + subject: string + preview: string + heading: string + noLongerCanceled: string + } + subscriptionUpdated: { + subject: string + preview: string + heading: string + changedTo: string + immediateWithCharge: string + immediateNextCycle: string + } +} diff --git a/clients/packages/i18n/tsconfig.json b/clients/packages/i18n/tsconfig.json new file mode 100644 index 0000000000..889ca4dd1c --- /dev/null +++ b/clients/packages/i18n/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "react-jsx", + "strict": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist", + "rootDir": "./src", + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/clients/packages/i18n/tsup.config.ts b/clients/packages/i18n/tsup.config.ts new file mode 100644 index 0000000000..a12e6efd69 --- /dev/null +++ b/clients/packages/i18n/tsup.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['esm', 'cjs'], + dts: true, + sourcemap: true, + clean: true, + external: ['react'], +}) diff --git a/clients/packages/ui/src/components/atoms/CountryPicker.tsx b/clients/packages/ui/src/components/atoms/CountryPicker.tsx index 8bc17aec1c..378555e3b4 100644 --- a/clients/packages/ui/src/components/atoms/CountryPicker.tsx +++ b/clients/packages/ui/src/components/atoms/CountryPicker.tsx @@ -29,6 +29,7 @@ const CountryPicker = ({ className, itemClassName, contentClassName, + placeholder = 'Country', }: { allowedCountries: readonly string[] value?: string @@ -38,6 +39,7 @@ const CountryPicker = ({ className?: string itemClassName?: string contentClassName?: string + placeholder?: string }) => { const countryMap = getCountryList(allowedCountries as TCountryCode[]) return ( @@ -49,7 +51,7 @@ const CountryPicker = ({ > = { 'CA-SK': 'Saskatchewan', } +interface CountryStatePickerLabels { + state?: string + province?: string + stateOrProvince?: string +} + const CountryStatePicker = ({ className, value, @@ -85,6 +91,7 @@ const CountryStatePicker = ({ itemClassName, contentClassName, disabled, + labels, }: { className?: string contentClassName?: string @@ -94,7 +101,12 @@ const CountryStatePicker = ({ country?: string autoComplete?: string disabled?: boolean + labels?: CountryStatePickerLabels }) => { + const stateLabel = labels?.state ?? 'State' + const provinceLabel = labels?.province ?? 'Province' + const stateOrProvinceLabel = labels?.stateOrProvince ?? 'State / Province' + if (country === 'US' || country === 'CA') { const states = country === 'US' ? US_STATES : CA_PROVINCES return ( @@ -106,7 +118,7 @@ const CountryStatePicker = ({ > onChange(e.target.value)} disabled={disabled} diff --git a/clients/pnpm-lock.yaml b/clients/pnpm-lock.yaml index 8a5c8a2ed1..4285a81136 100644 --- a/clients/pnpm-lock.yaml +++ b/clients/pnpm-lock.yaml @@ -51,46 +51,46 @@ importers: version: 0.4.1 '@expo/metro-runtime': specifier: ~6.1.2 - version: 6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@expo/ui': specifier: 0.2.0-beta.7 - version: 0.2.0-beta.7(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 0.2.0-beta.7(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@expo/vector-icons': specifier: ^15.0.3 - version: 15.0.3(expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 15.0.3(expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@gorhom/bottom-sheet': specifier: ^5.2.8 - version: 5.2.8(@types/react@19.2.3)(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 5.2.8(@types/react@19.2.3)(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@polar-sh/client': specifier: workspace:* version: link:../../packages/client '@react-native-async-storage/async-storage': specifier: 2.2.0 - version: 2.2.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 2.2.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) '@react-native-community/cli': specifier: latest - version: 20.0.2(typescript@5.9.3) + version: 20.1.0(typescript@5.9.3) '@react-native-community/netinfo': specifier: ^11.4.1 - version: 11.4.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 11.4.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) '@react-navigation/bottom-tabs': specifier: ^7.8.12 - version: 7.8.12(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 7.8.12(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@react-navigation/native': specifier: ^7.1.25 - version: 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@sentry/react-native': specifier: ^7.7.0 - version: 7.7.0(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 7.7.0(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@shopify/flash-list': specifier: 2.0.2 - version: 2.0.2(@babel/runtime@7.28.4)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 2.0.2(@babel/runtime@7.28.4)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@shopify/react-native-skia': specifier: 2.2.12 - version: 2.2.12(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 2.2.12(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@shopify/restyle': specifier: ^2.4.5 - version: 2.4.5(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 2.4.5(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@tanstack/react-query': specifier: ^5.90.12 version: 5.90.12(react@19.1.0) @@ -99,22 +99,22 @@ importers: version: 4.1.0 expo: specifier: ~54.0.29 - version: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-asset: specifier: ~12.0.11 - version: 12.0.11(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 12.0.11(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-auth-session: specifier: ~7.0.10 - version: 7.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 7.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-blur: specifier: ~15.0.8 - version: 15.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 15.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-clipboard: specifier: ~8.0.8 - version: 8.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 8.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-constants: specifier: ~18.0.12 - version: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) expo-crypto: specifier: ~15.0.8 version: 15.0.8(expo@54.0.29) @@ -126,25 +126,25 @@ importers: version: 8.0.10(expo@54.0.29) expo-font: specifier: ~14.0.10 - version: 14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-haptics: specifier: ~15.0.8 version: 15.0.8(expo@54.0.29) expo-image: specifier: ~3.0.11 - version: 3.0.11(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 3.0.11(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-insights: specifier: ~0.10.8 version: 0.10.8(expo@54.0.29) expo-linking: specifier: ~8.0.10 - version: 8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-notifications: specifier: ~0.32.15 - version: 0.32.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 0.32.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-router: specifier: ~6.0.19 - version: 6.0.19(daa6e6378deabbbe32c786346aac9231) + version: 6.0.19(40cf5459a2da5a2ee24052faf185eb05) expo-secure-store: specifier: ~15.0.8 version: 15.0.8(expo@54.0.29) @@ -153,25 +153,25 @@ importers: version: 31.0.12(expo@54.0.29) expo-status-bar: specifier: ~3.0.9 - version: 3.0.9(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 3.0.9(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-store-review: specifier: ^9.0.9 - version: 9.0.9(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 9.0.9(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) expo-symbols: specifier: ~1.0.8 - version: 1.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 1.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) expo-system-ui: specifier: ~6.0.9 - version: 6.0.9(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 6.0.9(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) expo-updates: specifier: ~29.0.15 - version: 29.0.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 29.0.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-web-browser: specifier: ~15.0.10 - version: 15.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + version: 15.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) nativewind: specifier: ^4.2.1 - version: 4.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)) + version: 4.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)) patch-package: specifier: ^8.0.1 version: 8.0.1 @@ -189,31 +189,31 @@ importers: version: 7.68.0(react@19.1.0) react-native: specifier: 0.81.5 - version: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + version: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) react-native-gesture-handler: specifier: ~2.28.0 - version: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-reanimated: specifier: ~4.1.6 - version: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-safe-area-context: specifier: ^5.6.2 - version: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-screens: specifier: ~4.16.0 - version: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-svg: specifier: 15.12.1 - version: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-web: specifier: ~0.21.2 version: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-native-webview: specifier: 13.15.0 - version: 13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-worklets: specifier: 0.5.1 - version: 0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) slugify: specifier: ^1.6.6 version: 1.6.6 @@ -222,7 +222,7 @@ importers: version: 3.4.19(yaml@2.8.2) victory-native: specifier: ^41.20.2 - version: 41.20.2(304cb029cd54f6dc7590a1eb71d5c0a3) + version: 41.20.2(56acb8d1da5f9cc0e4ae48affe1ead3b) devDependencies: '@babel/core': specifier: ^7.28.5 @@ -247,10 +247,10 @@ importers: version: 10.0.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + version: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) jest-expo: specifier: ~54.0.16 - version: 54.0.16(@babel/core@7.28.5)(expo@54.0.29)(jest@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + version: 54.0.16(@babel/core@7.28.5)(expo@54.0.29)(jest@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-test-renderer: specifier: 18.3.1 version: 18.3.1(react@19.1.0) @@ -298,7 +298,7 @@ importers: version: 2.0.1(react-dom@19.2.3(react@19.2.3))(react-hook-form@7.70.0(react@19.2.3))(react@19.2.3) '@mdx-js/loader': specifier: ^3.1.1 - version: 3.1.1(webpack@5.102.1) + version: 3.1.1(webpack@5.102.1(@swc/core@1.15.7)) '@mdx-js/react': specifier: ^3.1.1 version: 3.1.1(@types/react@19.2.3)(react@19.2.3) @@ -313,7 +313,7 @@ importers: version: 7.3.6(@emotion/react@11.14.0(@types/react@19.2.3)(react@19.2.3))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.2.3)(react@19.2.3))(@types/react@19.2.3)(react@19.2.3))(@types/react@19.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@next/mdx': specifier: 16.1.1 - version: 16.1.1(@mdx-js/loader@3.1.1(webpack@5.102.1))(@mdx-js/react@3.1.1(@types/react@19.2.3)(react@19.2.3)) + version: 16.1.1(@mdx-js/loader@3.1.1(webpack@5.102.1(@swc/core@1.15.7)))(@mdx-js/react@3.1.1(@types/react@19.2.3)(react@19.2.3)) '@next/third-parties': specifier: 16.1.1 version: 16.1.1(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3) @@ -326,6 +326,9 @@ importers: '@polar-sh/customer-portal': specifier: workspace:* version: link:../../packages/customer-portal + '@polar-sh/i18n': + specifier: workspace:^ + version: link:../../packages/i18n '@polar-sh/mdx': specifier: workspace:* version: link:../../packages/mdx @@ -352,7 +355,7 @@ importers: version: 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.3))(@types/react@19.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@sentry/nextjs': specifier: ^10.32.1 - version: 10.32.1(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.102.1) + version: 10.32.1(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.102.1(@swc/core@1.15.7)) '@shikijs/rehype': specifier: ^3.20.0 version: 3.20.0 @@ -593,7 +596,7 @@ importers: version: 4.1.18 ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@22.19.3)(typescript@5.9.3) + version: 10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3) typescript: specifier: 5.9.3 version: 5.9.3 @@ -618,6 +621,9 @@ importers: packages/checkout: dependencies: + '@polar-sh/i18n': + specifier: workspace:^ + version: link:../i18n '@polar-sh/sdk': specifier: ^0.42.1 version: 0.42.1 @@ -657,7 +663,7 @@ importers: version: 5.44.1 tsup: specifier: ^8.5.1 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) + version: 8.5.1(@swc/core@1.15.7)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) typescript: specifier: latest version: 5.9.3 @@ -679,7 +685,7 @@ importers: version: 7.10.1(typescript@5.9.3) tsup: specifier: ^8.5.1 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) + version: 8.5.1(@swc/core@1.15.7)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) typescript: specifier: latest version: 5.9.3 @@ -719,7 +725,7 @@ importers: version: 2.12.7(@types/node@25.0.2)(typescript@5.9.3) tsup: specifier: ^8.0.0 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) + version: 8.5.1(@swc/core@1.15.7)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) typescript: specifier: latest version: 5.9.3 @@ -763,6 +769,22 @@ importers: specifier: ^8.50.0 version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + packages/i18n: + dependencies: + react: + specifier: ^19.0.0 + version: 19.2.3 + devDependencies: + '@types/react': + specifier: 19.2.3 + version: 19.2.3 + tsup: + specifier: ^8.0.0 + version: 8.5.1(@swc/core@1.15.7)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) + typescript: + specifier: ^5.0.0 + version: 5.9.3 + packages/mdx: dependencies: estree-util-is-identifier-name: @@ -893,7 +915,7 @@ importers: version: 19.2.3(react@19.2.3) tsup: specifier: ^8.5.1 - version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) + version: 8.5.1(@swc/core@1.15.7)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2) typescript: specifier: 5.9.3 version: 5.9.3 @@ -3611,41 +3633,41 @@ packages: peerDependencies: react-native: ^0.0.0-0 || >=0.65 <1.0 - '@react-native-community/cli-clean@20.0.2': - resolution: {integrity: sha512-hfbC69fTD0fqZCCep8aqnVztBXUhAckNhi76lEV7USENtgBRwNq2s1wATgKAzOhxKuAL9TEkf5TZ/Dhp/YLhCQ==} + '@react-native-community/cli-clean@20.1.0': + resolution: {integrity: sha512-77L4DifWfxAT8ByHnkypge7GBMYpbJAjBGV+toowt5FQSGaTBDcBHCX+FFqFRukD5fH6i8sZ41Gtw+nbfCTTIA==} - '@react-native-community/cli-config-android@20.0.2': - resolution: {integrity: sha512-5yZ2Grr89omnMptV36ilV4EIrRLrIYQAsTTVU/hNI2vL7lz6WB8rPhP5QuovXk3TIjl1Wz2r9A6ZNO2SNJ8nig==} + '@react-native-community/cli-config-android@20.1.0': + resolution: {integrity: sha512-3A01ZDyFeCALzzPcwP/fleHoP3sGNq1UX7FzxkTrOFX8RRL9ntXNXQd27E56VU4BBxGAjAJT4Utw8pcOjJceIA==} - '@react-native-community/cli-config-apple@20.0.2': - resolution: {integrity: sha512-6MLL9Duu/JytqI6XfYuc78LSkRGfJoCqTSfqTJzBNSnz6S7XJps9spGBlgvrGh/j0howBpQlFH0J8Ws4N4mCxA==} + '@react-native-community/cli-config-apple@20.1.0': + resolution: {integrity: sha512-n6JVs8Q3yxRbtZQOy05ofeb1kGtspGN3SgwPmuaqvURF9fsuS7c4/9up2Kp9C+1D2J1remPJXiZLNGOcJvfpOA==} - '@react-native-community/cli-config@20.0.2': - resolution: {integrity: sha512-OuSAyqTv0MBbRqSyO+80IKasHnwLESydZBTrLjIGwGhDokMH07mZo8Io2H8X300WWa57LC2L8vQf73TzGS3ikQ==} + '@react-native-community/cli-config@20.1.0': + resolution: {integrity: sha512-1x9rhLLR/dKKb92Lb5O0l0EmUG08FHf+ZVyVEf9M+tX+p5QIm52MRiy43R0UAZ2jJnFApxRk+N3sxoYK4Dtnag==} - '@react-native-community/cli-doctor@20.0.2': - resolution: {integrity: sha512-PQ8BdoNDE2OaMGLH66HZE7FV4qj0iWBHi0lkPUTb8eJJ+vlvzUtBf0N9QSv2TAzFjA59a2FElk6jBWnDC/ql1A==} + '@react-native-community/cli-doctor@20.1.0': + resolution: {integrity: sha512-QfJF1GVjA4PBrIT3SJ0vFFIu0km1vwOmLDlOYVqfojajZJ+Dnvl0f94GN1il/jT7fITAxom///XH3/URvi7YTQ==} - '@react-native-community/cli-platform-android@20.0.2': - resolution: {integrity: sha512-Wo2AIkdv3PMEMT4k7QiNm3smNpWK6rd+glVH4Nm6Hco1EgLQ4I9x+gwcS1yN53UHYtq9YnguDCXk2L8duUESDQ==} + '@react-native-community/cli-platform-android@20.1.0': + resolution: {integrity: sha512-TeHPDThOwDppQRpndm9kCdRCBI8AMy3HSIQ+iy7VYQXL5BtZ5LfmGdusoj7nVN/ZGn0Lc6Gwts5qowyupXdeKg==} - '@react-native-community/cli-platform-apple@20.0.2': - resolution: {integrity: sha512-PdsQVFLY+wGnAN1kZ38XzzWiUlqaG1cXdpkQ1rYaiiNu3PVTc2/KtteLcPG/wbApbfoPggQ/ffh+JGg7NL+HNw==} + '@react-native-community/cli-platform-apple@20.1.0': + resolution: {integrity: sha512-0ih1hrYezSM2cuOlVnwBEFtMwtd8YgpTLmZauDJCv50rIumtkI1cQoOgLoS4tbPCj9U/Vn2a9BFH0DLFOOIacg==} - '@react-native-community/cli-platform-ios@20.0.2': - resolution: {integrity: sha512-bVOqLsBztT+xVV65uztJ7R/dtjj4vaPXJU1RLi35zLtr1APAxzf+2ydiixxtBjNFylM3AZlF8iL5WXjeWVqrmA==} + '@react-native-community/cli-platform-ios@20.1.0': + resolution: {integrity: sha512-XN7Da9z4WsJxtqVtEzY8q2bv22OsvzaFP5zy5+phMWNoJlU4lf7IvBSxqGYMpQ9XhYP7arDw5vmW4W34s06rnA==} - '@react-native-community/cli-server-api@20.0.2': - resolution: {integrity: sha512-u4tUzWnc+qthaDvd1NxdCqCNMY7Px6dAH1ODAXMtt+N27llGMJOl0J3slMx03dScftOWbGM61KA5cCpaxphYVQ==} + '@react-native-community/cli-server-api@20.1.0': + resolution: {integrity: sha512-Tb415Oh8syXNT2zOzLzFkBXznzGaqKCiaichxKzGCDKg6JGHp3jSuCmcTcaPeYC7oc32n/S3Psw7798r4Q/7lA==} - '@react-native-community/cli-tools@20.0.2': - resolution: {integrity: sha512-bPYhRYggW9IIM8pvrZF/0r6HaxCyEWDn6zfPQPMWlkQUwkzFZ8GBY/M7yiHgDzozWKPT4DqZPumrq806Vcksow==} + '@react-native-community/cli-tools@20.1.0': + resolution: {integrity: sha512-/YmzHGOkY6Bgrv4OaA1L8rFqsBlQd1EB2/ipAoKPiieV0EcB5PUamUSuNeFU3sBZZTYQCUENwX4wgOHgFUlDnQ==} - '@react-native-community/cli-types@20.0.2': - resolution: {integrity: sha512-OZzy6U4M8Szg8iiF459OoTjRKggxLrdhZVHKfRhrAUfojhjRiWbJNkkPxJtOIPeNSgsB0heizgpE4QwCgnYeuQ==} + '@react-native-community/cli-types@20.1.0': + resolution: {integrity: sha512-D0kDspcwgbVXyNjwicT7Bb1JgXjijTw1JJd+qxyF/a9+sHv7TU4IchV+gN38QegeXqVyM4Ym7YZIvXMFBmyJqA==} - '@react-native-community/cli@20.0.2': - resolution: {integrity: sha512-ocgRFKRLX8b5rEK38SJfpr0AMl6SqseWljk6c5LxCG/zpCfPPNQdXq1OsDvmEwsqO4OEQ6tmOaSm9OgTm6FhbQ==} + '@react-native-community/cli@20.1.0': + resolution: {integrity: sha512-441WsVtRe4nGJ9OzA+QMU1+22lA6Q2hRWqqIMKD0wjEMLqcSfOZyu2UL9a/yRpL/dRpyUsU4n7AxqKfTKO/Csg==} engines: {node: '>=20.19.4'} hasBin: true @@ -4257,9 +4279,88 @@ packages: resolution: {integrity: sha512-ggs5k+/0FUJcIgNY08aZTqpBTtbExkJMYMLSMwyucrhtWexVOEY1KJmhBsxf+E/Q15f5rbwBpj+t0t2AW2oCsQ==} engines: {node: '>=12.16'} + '@swc/core-darwin-arm64@1.15.7': + resolution: {integrity: sha512-+hNVUfezUid7LeSHqnhoC6Gh3BROABxjlDNInuZ/fie1RUxaEX4qzDwdTgozJELgHhvYxyPIg1ro8ibnKtgO4g==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.15.7': + resolution: {integrity: sha512-ZAFuvtSYZTuXPcrhanaD5eyp27H8LlDzx2NAeVyH0FchYcuXf0h5/k3GL9ZU6Jw9eQ63R1E8KBgpXEJlgRwZUQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.15.7': + resolution: {integrity: sha512-K3HTYocpqnOw8KcD8SBFxiDHjIma7G/X+bLdfWqf+qzETNBrzOub/IEkq9UaeupaJiZJkPptr/2EhEXXWryS/A==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.15.7': + resolution: {integrity: sha512-HCnVIlsLnCtQ3uXcXgWrvQ6SAraskLA9QJo9ykTnqTH6TvUYqEta+TdTdGjzngD6TOE7XjlAiUs/RBtU8Z0t+Q==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-arm64-musl@1.15.7': + resolution: {integrity: sha512-/OOp9UZBg4v2q9+x/U21Jtld0Wb8ghzBScwhscI7YvoSh4E8RALaJ1msV8V8AKkBkZH7FUAFB7Vbv0oVzZsezA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@swc/core-linux-x64-gnu@1.15.7': + resolution: {integrity: sha512-VBbs4gtD4XQxrHuQ2/2+TDZpPQQgrOHYRnS6SyJW+dw0Nj/OomRqH+n5Z4e/TgKRRbieufipeIGvADYC/90PYQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-musl@1.15.7': + resolution: {integrity: sha512-kVuy2unodso6p0rMauS2zby8/bhzoGRYxBDyD6i2tls/fEYAE74oP0VPFzxIyHaIjK1SN6u5TgvV9MpyJ5xVug==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@swc/core-win32-arm64-msvc@1.15.7': + resolution: {integrity: sha512-uddYoo5Xmo1XKLhAnh4NBIyy5d0xk33x1sX3nIJboFySLNz878ksCFCZ3IBqrt1Za0gaoIWoOSSSk0eNhAc/sw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.15.7': + resolution: {integrity: sha512-rqq8JjNMLx3QNlh0aPTtN/4+BGLEHC94rj9mkH1stoNRf3ra6IksNHMHy+V1HUqElEgcZyx+0yeXx3eLOTcoFw==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.15.7': + resolution: {integrity: sha512-4BK06EGdPnuplgcNhmSbOIiLdRgHYX3v1nl4HXo5uo4GZMfllXaCyBUes+0ePRfwbn9OFgVhCWPcYYjMT6hycQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.15.7': + resolution: {integrity: sha512-kTGB8XI7P+pTKW83tnUEDVP4zduF951u3UAOn5eTi0vyW6MvL56A3+ggMdfuVFtDI0/DsbSzf5z34HVBbuScWw==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@swc/types@0.1.25': + resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} + '@tailwindcss/forms@0.5.11': resolution: {integrity: sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==} peerDependencies: @@ -7961,8 +8062,8 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - ky@1.14.2: - resolution: {integrity: sha512-q3RBbsO5A5zrPhB6CaCS8ZUv+NWCXv6JJT4Em0i264G9W0fdPB8YRfnnEi7Dm7X7omAkBIPojzYJ2D1oHTHqug==} + ky@1.14.1: + resolution: {integrity: sha512-hYje4L9JCmpEQBtudo+v52X5X8tgWXUYyPcxKSuxQNboqufecl9VMWjGiucAFH060AwPXHZuH+WB2rrqfkmafw==} engines: {node: '>=18'} lan-network@0.1.7: @@ -10776,8 +10877,8 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} - type-fest@5.3.1: - resolution: {integrity: sha512-VCn+LMHbd4t6sF3wfU/+HKT63C9OoyrSIf4b+vtWHpt2U7/4InZG467YDNMFMR70DdHjAdpPWmw2lzRdg0Xqqg==} + type-fest@5.4.1: + resolution: {integrity: sha512-xygQcmneDyzsEuKZrFbRMne5HDqMs++aFzefrJTgEIKjQ3rekM+RPfFCVq2Gp1VIDqddoYeppCj4Pcb+RZW0GQ==} engines: {node: '>=20'} type-is@1.6.18: @@ -11192,8 +11293,8 @@ packages: warn-once@0.1.1: resolution: {integrity: sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q==} - watchpack@2.5.0: - resolution: {integrity: sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==} + watchpack@2.4.4: + resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==} engines: {node: '>=10.13.0'} wcwidth@1.0.1: @@ -11246,6 +11347,7 @@ packages: whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} @@ -12407,7 +12509,7 @@ snapshots: dependencies: '@react-navigation/core': 7.13.6(react@19.1.0) '@react-navigation/devtools': 7.0.45(react@19.1.0) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) nanoid: 5.1.6 transitivePeerDependencies: - react @@ -12415,7 +12517,7 @@ snapshots: '@dev-plugins/react-query@0.1.0(@tanstack/react-query@5.90.12(react@19.1.0))(expo@54.0.29)': dependencies: '@tanstack/react-query': 5.90.12(react@19.1.0) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) flatted: 3.3.3 '@discoveryjs/json-ext@0.5.7': {} @@ -12750,7 +12852,7 @@ snapshots: '@expo-google-fonts/instrument-serif@0.4.1': {} - '@expo/cli@54.0.19(expo-router@6.0.19)(expo@54.0.29)(graphql@16.12.0)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))': + '@expo/cli@54.0.19(expo-router@6.0.19)(expo@54.0.29)(graphql@16.12.0)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))': dependencies: '@0no-co/graphql.web': 1.2.0(graphql@16.12.0) '@expo/code-signing-certificates': 0.0.5 @@ -12784,7 +12886,7 @@ snapshots: connect: 3.7.0 debug: 4.4.3(supports-color@10.2.2) env-editor: 0.4.2 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-server: 1.0.5 freeport-async: 2.0.0 getenv: 2.0.0 @@ -12817,8 +12919,8 @@ snapshots: wrap-ansi: 7.0.0 ws: 8.18.3 optionalDependencies: - expo-router: 6.0.19(daa6e6378deabbbe32c786346aac9231) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo-router: 6.0.19(40cf5459a2da5a2ee24052faf185eb05) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) transitivePeerDependencies: - bufferutil - graphql @@ -12876,12 +12978,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@expo/devtools@0.1.8(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@expo/devtools@0.1.8(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: chalk: 4.1.2 optionalDependencies: react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) '@expo/env@2.0.8': dependencies: @@ -12951,19 +13053,19 @@ snapshots: postcss: 8.4.49 resolve-from: 5.0.0 optionalDependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate - '@expo/metro-runtime@6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@expo/metro-runtime@6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: anser: 1.4.10 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) pretty-format: 29.7.0 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) stacktrace-parser: 0.1.11 whatwg-fetch: 3.6.20 optionalDependencies: @@ -13023,7 +13125,7 @@ snapshots: '@expo/json-file': 10.0.8 '@react-native/normalize-colors': 0.81.5 debug: 4.4.3(supports-color@10.2.2) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) resolve-from: 5.0.0 semver: 7.7.3 xml2js: 0.6.0 @@ -13040,18 +13142,18 @@ snapshots: '@expo/sudo-prompt@9.3.2': {} - '@expo/ui@0.2.0-beta.7(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@expo/ui@0.2.0-beta.7(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) sf-symbols-typescript: 2.2.0 - '@expo/vector-icons@15.0.3(expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@expo/vector-icons@15.0.3(expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: - expo-font: 14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-font: 14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) '@expo/ws-tunnel@1.0.6': {} @@ -13092,22 +13194,22 @@ snapshots: - supports-color - utf-8-validate - '@gorhom/bottom-sheet@5.2.8(@types/react@19.2.3)(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@gorhom/bottom-sheet@5.2.8(@types/react@19.2.3)(react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: - '@gorhom/portal': 1.0.14(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@gorhom/portal': 1.0.14(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) invariant: 2.2.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) optionalDependencies: '@types/react': 19.2.3 - '@gorhom/portal@1.0.14(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@gorhom/portal@1.0.14(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: nanoid: 3.3.11 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) '@hapi/hoek@9.3.0': {} @@ -13309,27 +13411,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -13358,7 +13460,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -13376,7 +13478,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 25.0.2 + '@types/node': 22.19.3 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -13398,7 +13500,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 25.0.2 + '@types/node': 22.19.3 chalk: 4.1.2 collect-v8-coverage: 1.0.3 exit: 0.1.2 @@ -13468,7 +13570,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 25.0.2 + '@types/node': 22.19.3 '@types/yargs': 17.0.35 chalk: 4.1.2 @@ -13592,12 +13694,12 @@ snapshots: js-yaml: 4.1.1 tinyglobby: 0.2.15 - '@mdx-js/loader@3.1.1(webpack@5.102.1)': + '@mdx-js/loader@3.1.1(webpack@5.102.1(@swc/core@1.15.7))': dependencies: '@mdx-js/mdx': 3.1.1 source-map: 0.7.6 optionalDependencies: - webpack: 5.102.1 + webpack: 5.102.1(@swc/core@1.15.7) transitivePeerDependencies: - supports-color @@ -13777,11 +13879,11 @@ snapshots: dependencies: fast-glob: 3.3.1 - '@next/mdx@16.1.1(@mdx-js/loader@3.1.1(webpack@5.102.1))(@mdx-js/react@3.1.1(@types/react@19.2.3)(react@19.2.3))': + '@next/mdx@16.1.1(@mdx-js/loader@3.1.1(webpack@5.102.1(@swc/core@1.15.7)))(@mdx-js/react@3.1.1(@types/react@19.2.3)(react@19.2.3))': dependencies: source-map: 0.7.6 optionalDependencies: - '@mdx-js/loader': 3.1.1(webpack@5.102.1) + '@mdx-js/loader': 3.1.1(webpack@5.102.1(@swc/core@1.15.7)) '@mdx-js/react': 3.1.1(@types/react@19.2.3)(react@19.2.3) '@next/swc-darwin-arm64@16.1.1': @@ -14870,86 +14972,86 @@ snapshots: '@radix-ui/rect@1.1.1': {} - '@react-native-async-storage/async-storage@2.2.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))': + '@react-native-async-storage/async-storage@2.2.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))': dependencies: merge-options: 3.0.4 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - '@react-native-community/cli-clean@20.0.2': + '@react-native-community/cli-clean@20.1.0': dependencies: - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-tools': 20.1.0 execa: 5.1.1 fast-glob: 3.3.3 + picocolors: 1.1.1 - '@react-native-community/cli-config-android@20.0.2': + '@react-native-community/cli-config-android@20.1.0': dependencies: - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-tools': 20.1.0 fast-glob: 3.3.3 fast-xml-parser: 4.5.3 + picocolors: 1.1.1 - '@react-native-community/cli-config-apple@20.0.2': + '@react-native-community/cli-config-apple@20.1.0': dependencies: - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-tools': 20.1.0 execa: 5.1.1 fast-glob: 3.3.3 + picocolors: 1.1.1 - '@react-native-community/cli-config@20.0.2(typescript@5.9.3)': + '@react-native-community/cli-config@20.1.0(typescript@5.9.3)': dependencies: - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-tools': 20.1.0 cosmiconfig: 9.0.0(typescript@5.9.3) deepmerge: 4.3.1 fast-glob: 3.3.3 joi: 17.13.3 + picocolors: 1.1.1 transitivePeerDependencies: - typescript - '@react-native-community/cli-doctor@20.0.2(typescript@5.9.3)': + '@react-native-community/cli-doctor@20.1.0(typescript@5.9.3)': dependencies: - '@react-native-community/cli-config': 20.0.2(typescript@5.9.3) - '@react-native-community/cli-platform-android': 20.0.2 - '@react-native-community/cli-platform-apple': 20.0.2 - '@react-native-community/cli-platform-ios': 20.0.2 - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-config': 20.1.0(typescript@5.9.3) + '@react-native-community/cli-platform-android': 20.1.0 + '@react-native-community/cli-platform-apple': 20.1.0 + '@react-native-community/cli-platform-ios': 20.1.0 + '@react-native-community/cli-tools': 20.1.0 command-exists: 1.2.9 deepmerge: 4.3.1 envinfo: 7.21.0 execa: 5.1.1 node-stream-zip: 1.15.0 ora: 5.4.1 + picocolors: 1.1.1 semver: 7.7.3 wcwidth: 1.0.1 yaml: 2.8.2 transitivePeerDependencies: - typescript - '@react-native-community/cli-platform-android@20.0.2': + '@react-native-community/cli-platform-android@20.1.0': dependencies: - '@react-native-community/cli-config-android': 20.0.2 - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-config-android': 20.1.0 + '@react-native-community/cli-tools': 20.1.0 execa: 5.1.1 logkitty: 0.7.1 + picocolors: 1.1.1 - '@react-native-community/cli-platform-apple@20.0.2': + '@react-native-community/cli-platform-apple@20.1.0': dependencies: - '@react-native-community/cli-config-apple': 20.0.2 - '@react-native-community/cli-tools': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-config-apple': 20.1.0 + '@react-native-community/cli-tools': 20.1.0 execa: 5.1.1 fast-xml-parser: 4.5.3 + picocolors: 1.1.1 - '@react-native-community/cli-platform-ios@20.0.2': + '@react-native-community/cli-platform-ios@20.1.0': dependencies: - '@react-native-community/cli-platform-apple': 20.0.2 + '@react-native-community/cli-platform-apple': 20.1.0 - '@react-native-community/cli-server-api@20.0.2': + '@react-native-community/cli-server-api@20.1.0': dependencies: - '@react-native-community/cli-tools': 20.0.2 + '@react-native-community/cli-tools': 20.1.0 body-parser: 1.20.4 compression: 1.8.1 connect: 3.7.0 @@ -14964,38 +15066,38 @@ snapshots: - supports-color - utf-8-validate - '@react-native-community/cli-tools@20.0.2': + '@react-native-community/cli-tools@20.1.0': dependencies: '@vscode/sudo-prompt': 9.3.1 appdirsjs: 1.2.7 - chalk: 4.1.2 execa: 5.1.1 find-up: 5.0.0 launch-editor: 2.12.0 mime: 2.6.0 ora: 5.4.1 + picocolors: 1.1.1 prompts: 2.4.2 semver: 7.7.3 - '@react-native-community/cli-types@20.0.2': + '@react-native-community/cli-types@20.1.0': dependencies: joi: 17.13.3 - '@react-native-community/cli@20.0.2(typescript@5.9.3)': + '@react-native-community/cli@20.1.0(typescript@5.9.3)': dependencies: - '@react-native-community/cli-clean': 20.0.2 - '@react-native-community/cli-config': 20.0.2(typescript@5.9.3) - '@react-native-community/cli-doctor': 20.0.2(typescript@5.9.3) - '@react-native-community/cli-server-api': 20.0.2 - '@react-native-community/cli-tools': 20.0.2 - '@react-native-community/cli-types': 20.0.2 - chalk: 4.1.2 + '@react-native-community/cli-clean': 20.1.0 + '@react-native-community/cli-config': 20.1.0(typescript@5.9.3) + '@react-native-community/cli-doctor': 20.1.0(typescript@5.9.3) + '@react-native-community/cli-server-api': 20.1.0 + '@react-native-community/cli-tools': 20.1.0 + '@react-native-community/cli-types': 20.1.0 commander: 9.5.0 deepmerge: 4.3.1 execa: 5.1.1 find-up: 5.0.0 fs-extra: 8.1.0 graceful-fs: 4.2.11 + picocolors: 1.1.1 prompts: 2.4.2 semver: 7.7.3 transitivePeerDependencies: @@ -15004,9 +15106,9 @@ snapshots: - typescript - utf-8-validate - '@react-native-community/netinfo@11.4.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))': + '@react-native-community/netinfo@11.4.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))': dependencies: - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) '@react-native/assets-registry@0.81.5': {} @@ -15078,7 +15180,7 @@ snapshots: nullthrows: 1.1.1 yargs: 17.7.2 - '@react-native/community-cli-plugin@0.81.5(@react-native-community/cli@20.0.2(typescript@5.9.3))': + '@react-native/community-cli-plugin@0.81.5(@react-native-community/cli@20.1.0(typescript@5.9.3))': dependencies: '@react-native/dev-middleware': 0.81.5 debug: 4.4.3(supports-color@10.2.2) @@ -15088,7 +15190,7 @@ snapshots: metro-core: 0.83.3 semver: 7.7.3 optionalDependencies: - '@react-native-community/cli': 20.0.2(typescript@5.9.3) + '@react-native-community/cli': 20.1.0(typescript@5.9.3) transitivePeerDependencies: - bufferutil - supports-color @@ -15124,24 +15226,24 @@ snapshots: '@react-native/normalize-colors@0.81.5': {} - '@react-native/virtualized-lists@0.81.5(@types/react@19.2.3)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@react-native/virtualized-lists@0.81.5(@types/react@19.2.3)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: invariant: 2.2.4 nullthrows: 1.1.1 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) optionalDependencies: '@types/react': 19.2.3 - '@react-navigation/bottom-tabs@7.8.12(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@react-navigation/bottom-tabs@7.8.12(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: - '@react-navigation/elements': 2.9.2(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/elements': 2.9.2(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) color: 4.2.3 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) sf-symbols-typescript: 2.2.0 transitivePeerDependencies: - '@react-native-masked-view/masked-view' @@ -15165,38 +15267,38 @@ snapshots: react: 19.1.0 stacktrace-parser: 0.1.11 - '@react-navigation/elements@2.9.2(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@react-navigation/elements@2.9.2(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: - '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) color: 4.2.3 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) use-latest-callback: 0.2.6(react@19.1.0) use-sync-external-store: 1.6.0(react@19.1.0) - '@react-navigation/native-stack@7.8.6(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@react-navigation/native-stack@7.8.6(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: - '@react-navigation/elements': 2.9.2(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/elements': 2.9.2(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) color: 4.2.3 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) sf-symbols-typescript: 2.2.0 warn-once: 0.1.1 transitivePeerDependencies: - '@react-native-masked-view/masked-view' - '@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: '@react-navigation/core': 7.13.6(react@19.1.0) escape-string-regexp: 4.0.0 fast-deep-equal: 3.1.3 nanoid: 3.3.11 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) use-latest-callback: 0.2.6(react@19.1.0) '@react-navigation/routers@7.5.2': @@ -15488,7 +15590,7 @@ snapshots: '@sentry/core@10.32.1': {} - '@sentry/nextjs@10.32.1(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.102.1)': + '@sentry/nextjs@10.32.1(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(next@16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3)(webpack@5.102.1(@swc/core@1.15.7))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.38.0 @@ -15500,7 +15602,7 @@ snapshots: '@sentry/opentelemetry': 10.32.1(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) '@sentry/react': 10.32.1(react@19.2.3) '@sentry/vercel-edge': 10.32.1 - '@sentry/webpack-plugin': 4.6.1(webpack@5.102.1) + '@sentry/webpack-plugin': 4.6.1(webpack@5.102.1(@swc/core@1.15.7)) next: 16.1.1(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) resolve: 1.22.8 rollup: 4.53.5 @@ -15579,7 +15681,7 @@ snapshots: '@opentelemetry/semantic-conventions': 1.38.0 '@sentry/core': 10.32.1 - '@sentry/react-native@7.7.0(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@sentry/react-native@7.7.0(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: '@sentry/babel-plugin-component-annotate': 4.6.1 '@sentry/browser': 10.26.0 @@ -15588,9 +15690,9 @@ snapshots: '@sentry/react': 10.26.0(react@19.1.0) '@sentry/types': 10.26.0 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) optionalDependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - encoding - supports-color @@ -15619,12 +15721,12 @@ snapshots: '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) '@sentry/core': 10.32.1 - '@sentry/webpack-plugin@4.6.1(webpack@5.102.1)': + '@sentry/webpack-plugin@4.6.1(webpack@5.102.1(@swc/core@1.15.7))': dependencies: '@sentry/bundler-plugin-core': 4.6.1 unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.102.1 + webpack: 5.102.1(@swc/core@1.15.7) transitivePeerDependencies: - encoding - supports-color @@ -15671,26 +15773,26 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@shopify/flash-list@2.0.2(@babel/runtime@7.28.4)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@shopify/flash-list@2.0.2(@babel/runtime@7.28.4)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: '@babel/runtime': 7.28.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) tslib: 2.8.1 - '@shopify/react-native-skia@2.2.12(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@shopify/react-native-skia@2.2.12(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: canvaskit-wasm: 0.40.0 react: 19.1.0 react-reconciler: 0.31.0(react@19.1.0) optionalDependencies: - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - '@shopify/restyle@2.4.5(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': + '@shopify/restyle@2.4.5(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)': dependencies: react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) '@sideway/address@4.1.5': dependencies: @@ -15727,10 +15829,65 @@ snapshots: '@stripe/stripe-js@7.9.0': {} + '@swc/core-darwin-arm64@1.15.7': + optional: true + + '@swc/core-darwin-x64@1.15.7': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.15.7': + optional: true + + '@swc/core-linux-arm64-gnu@1.15.7': + optional: true + + '@swc/core-linux-arm64-musl@1.15.7': + optional: true + + '@swc/core-linux-x64-gnu@1.15.7': + optional: true + + '@swc/core-linux-x64-musl@1.15.7': + optional: true + + '@swc/core-win32-arm64-msvc@1.15.7': + optional: true + + '@swc/core-win32-ia32-msvc@1.15.7': + optional: true + + '@swc/core-win32-x64-msvc@1.15.7': + optional: true + + '@swc/core@1.15.7': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.25 + optionalDependencies: + '@swc/core-darwin-arm64': 1.15.7 + '@swc/core-darwin-x64': 1.15.7 + '@swc/core-linux-arm-gnueabihf': 1.15.7 + '@swc/core-linux-arm64-gnu': 1.15.7 + '@swc/core-linux-arm64-musl': 1.15.7 + '@swc/core-linux-x64-gnu': 1.15.7 + '@swc/core-linux-x64-musl': 1.15.7 + '@swc/core-win32-arm64-msvc': 1.15.7 + '@swc/core-win32-ia32-msvc': 1.15.7 + '@swc/core-win32-x64-msvc': 1.15.7 + optional: true + + '@swc/counter@0.1.3': + optional: true + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 + '@swc/types@0.1.25': + dependencies: + '@swc/counter': 0.1.3 + optional: true + '@tailwindcss/forms@0.5.11(tailwindcss@4.1.18)': dependencies: mini-svg-data-uri: 1.4.4 @@ -16047,7 +16204,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 25.0.2 + '@types/node': 22.19.3 '@types/hammerjs@2.0.46': {} @@ -16074,7 +16231,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 25.0.2 + '@types/node': 22.19.3 '@types/tough-cookie': 4.0.5 parse5: 7.3.0 @@ -16111,6 +16268,7 @@ snapshots: '@types/node@25.0.2': dependencies: undici-types: 7.16.0 + optional: true '@types/parse-json@4.0.2': {} @@ -16985,7 +17143,7 @@ snapshots: resolve-from: 5.0.0 optionalDependencies: '@babel/runtime': 7.28.4 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - '@babel/core' - supports-color @@ -17219,7 +17377,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 25.0.2 + '@types/node': 22.19.3 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -17230,7 +17388,7 @@ snapshots: chromium-edge-launcher@0.2.0: dependencies: - '@types/node': 25.0.2 + '@types/node': 22.19.3 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -17441,13 +17599,13 @@ snapshots: crawler-user-agents@1.24.0: {} - create-jest@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)): + create-jest@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -18390,61 +18548,61 @@ snapshots: expo-application@7.0.8(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-asset@12.0.11(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-asset@12.0.11(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@expo/image-utils': 0.8.8 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) transitivePeerDependencies: - supports-color - expo-auth-session@7.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-auth-session@7.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: expo-application: 7.0.8(expo@54.0.29) - expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) expo-crypto: 15.0.8(expo@54.0.29) - expo-linking: 8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-web-browser: 15.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-linking: 8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-web-browser: 15.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) invariant: 2.2.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) transitivePeerDependencies: - expo - supports-color - expo-blur@15.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-blur@15.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - expo-clipboard@8.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-clipboard@8.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - expo-constants@18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): + expo-constants@18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): dependencies: '@expo/config': 12.0.12 '@expo/env': 2.0.8 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) transitivePeerDependencies: - supports-color expo-crypto@15.0.8(expo@54.0.29): dependencies: base64-js: 1.5.1 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-dev-client@6.0.20(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-dev-launcher: 6.0.20(expo@54.0.29) expo-dev-menu: 7.0.18(expo@54.0.29) expo-dev-menu-interface: 2.0.0(expo@54.0.29) @@ -18456,7 +18614,7 @@ snapshots: expo-dev-launcher@6.0.20(expo@54.0.29): dependencies: ajv: 8.17.1 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-dev-menu: 7.0.18(expo@54.0.29) expo-manifests: 1.0.10(expo@54.0.29) transitivePeerDependencies: @@ -18464,62 +18622,62 @@ snapshots: expo-dev-menu-interface@2.0.0(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-dev-menu@7.0.18(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-dev-menu-interface: 2.0.0(expo@54.0.29) expo-device@8.0.10(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) ua-parser-js: 0.7.41 expo-eas-client@1.0.8: {} - expo-file-system@19.0.21(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): + expo-file-system@19.0.21(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) fontfaceobserver: 2.3.0 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) expo-haptics@15.0.8(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-image@3.0.11(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-image@3.0.11(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) optionalDependencies: react-native-web: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) expo-insights@0.10.8(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-eas-client: 1.0.8 expo-json-utils@0.15.0: {} expo-keep-awake@15.0.8(expo@54.0.29)(react@19.1.0): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react: 19.1.0 - expo-linking@8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-linking@8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: - expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) invariant: 2.2.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) transitivePeerDependencies: - expo - supports-color @@ -18527,7 +18685,7 @@ snapshots: expo-manifests@1.0.10(expo@54.0.29): dependencies: '@expo/config': 12.0.12 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-json-utils: 0.15.0 transitivePeerDependencies: - supports-color @@ -18540,42 +18698,42 @@ snapshots: require-from-string: 2.0.2 resolve-from: 5.0.0 - expo-modules-core@3.0.29(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-modules-core@3.0.29(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: invariant: 2.2.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - expo-notifications@0.32.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-notifications@0.32.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@expo/image-utils': 0.8.8 '@ide/backoff': 1.0.0 abort-controller: 3.0.0 assert: 2.1.0 badgin: 1.2.3 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-application: 7.0.8(expo@54.0.29) - expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) transitivePeerDependencies: - supports-color - expo-router@6.0.19(daa6e6378deabbbe32c786346aac9231): + expo-router@6.0.19(40cf5459a2da5a2ee24052faf185eb05): dependencies: - '@expo/metro-runtime': 6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@expo/metro-runtime': 6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@expo/schema-utils': 0.1.8 '@radix-ui/react-slot': 1.2.0(@types/react@19.2.3)(react@19.1.0) '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.3))(@types/react@19.2.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@react-navigation/bottom-tabs': 7.8.12(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - '@react-navigation/native-stack': 7.8.6(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/bottom-tabs': 7.8.12(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/native': 7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-navigation/native-stack': 7.8.6(@react-navigation/native@7.1.25(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) client-only: 0.0.1 debug: 4.4.3(supports-color@10.2.2) escape-string-regexp: 4.0.0 - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) - expo-linking: 8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-linking: 8.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-server: 1.0.5 fast-deep-equal: 3.1.3 invariant: 2.2.4 @@ -18583,10 +18741,10 @@ snapshots: query-string: 7.1.3 react: 19.1.0 react-fast-compare: 3.2.2 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-screens: 4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) semver: 7.6.3 server-only: 0.0.1 sf-symbols-typescript: 2.2.0 @@ -18595,8 +18753,8 @@ snapshots: vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.3))(@types/react@19.2.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) optionalDependencies: react-dom: 19.1.0(react@19.1.0) - react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) react-native-web: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - '@react-native-masked-view/masked-view' @@ -18606,42 +18764,42 @@ snapshots: expo-secure-store@15.0.8(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-server@1.0.5: {} expo-splash-screen@31.0.12(expo@54.0.29): dependencies: '@expo/prebuild-config': 54.0.7(expo@54.0.29) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - supports-color - expo-status-bar@3.0.9(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-status-bar@3.0.9(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-store-review@9.0.9(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): + expo-store-review@9.0.9(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) expo-structured-headers@5.0.0: {} - expo-symbols@1.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): + expo-symbols@1.0.8(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) sf-symbols-typescript: 2.2.0 - expo-system-ui@6.0.9(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): + expo-system-ui@6.0.9(expo@54.0.29)(react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): dependencies: '@react-native/normalize-colors': 0.81.5 debug: 4.4.3(supports-color@10.2.2) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) optionalDependencies: react-native-web: 0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) transitivePeerDependencies: @@ -18649,9 +18807,9 @@ snapshots: expo-updates-interface@2.0.0(expo@54.0.29): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-updates@29.0.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo-updates@29.0.15(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@expo/code-signing-certificates': 0.0.5 '@expo/plist': 0.4.8 @@ -18659,7 +18817,7 @@ snapshots: arg: 4.1.0 chalk: 4.1.2 debug: 4.4.3(supports-color@10.2.2) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-eas-client: 1.0.8 expo-manifests: 1.0.10(expo@54.0.29) expo-structured-headers: 5.0.0 @@ -18668,44 +18826,44 @@ snapshots: glob: 13.0.0 ignore: 5.3.2 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) resolve-from: 5.0.0 transitivePeerDependencies: - supports-color - expo-web-browser@15.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): + expo-web-browser@15.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)): dependencies: - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - expo@54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + expo@54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@babel/runtime': 7.28.4 - '@expo/cli': 54.0.19(expo-router@6.0.19)(expo@54.0.29)(graphql@16.12.0)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + '@expo/cli': 54.0.19(expo-router@6.0.19)(expo@54.0.29)(graphql@16.12.0)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) '@expo/config': 12.0.12 '@expo/config-plugins': 54.0.4 - '@expo/devtools': 0.1.8(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@expo/devtools': 0.1.8(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@expo/fingerprint': 0.15.4 '@expo/metro': 54.1.0 '@expo/metro-config': 54.0.11(expo@54.0.29) - '@expo/vector-icons': 15.0.3(expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@expo/vector-icons': 15.0.3(expo-font@14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) '@ungap/structured-clone': 1.3.0 babel-preset-expo: 54.0.8(@babel/core@7.28.5)(@babel/runtime@7.28.4)(expo@54.0.29)(react-refresh@0.14.2) - expo-asset: 12.0.11(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) - expo-file-system: 19.0.21(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) - expo-font: 14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-asset: 12.0.11(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-constants: 18.0.12(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-file-system: 19.0.21(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0)) + expo-font: 14.0.10(expo@54.0.29)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) expo-keep-awake: 15.0.8(expo@54.0.29)(react@19.1.0) expo-modules-autolinking: 3.0.23 - expo-modules-core: 3.0.29(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo-modules-core: 3.0.29(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) pretty-format: 29.7.0 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) react-refresh: 0.14.2 whatwg-url-without-unicode: 8.0.0-3 optionalDependencies: - '@expo/metro-runtime': 6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-webview: 13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@expo/metro-runtime': 6.1.2(expo@54.0.29)(react-dom@19.1.0(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-webview: 13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - '@babel/core' - bufferutil @@ -19718,7 +19876,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.0(babel-plugin-macros@3.1.0) @@ -19738,16 +19896,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)): + jest-cli@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + create-jest: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + jest-config: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -19757,7 +19915,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)): + jest-config@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)): dependencies: '@babel/core': 7.28.5 '@jest/test-sequencer': 29.7.0 @@ -19782,8 +19940,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 25.0.2 - ts-node: 10.9.2(@types/node@25.0.2)(typescript@5.9.3) + '@types/node': 22.19.3 + ts-node: 10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -19813,7 +19971,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 25.0.2 + '@types/node': 22.19.3 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3 @@ -19827,25 +19985,25 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 jest-mock: 29.7.0 jest-util: 29.7.0 - jest-expo@54.0.16(@babel/core@7.28.5)(expo@54.0.29)(jest@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + jest-expo@54.0.16(@babel/core@7.28.5)(expo@54.0.29)(jest@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@expo/config': 12.0.12 '@expo/json-file': 10.0.8 '@jest/create-cache-key-function': 29.7.0 '@jest/globals': 29.7.0 babel-jest: 29.7.0(@babel/core@7.28.5) - expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + expo: 54.0.29(@babel/core@7.28.5)(@expo/metro-runtime@6.1.2)(expo-router@6.0.19)(graphql@16.12.0)(react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) jest-environment-jsdom: 29.7.0 jest-snapshot: 29.7.0 jest-watch-select-projects: 2.0.0 - jest-watch-typeahead: 2.2.1(jest@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3))) + jest-watch-typeahead: 2.2.1(jest@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3))) json5: 2.2.3 lodash: 4.17.21 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) react-test-renderer: 19.1.0(react@19.1.0) server-only: 0.0.1 stacktrace-js: 2.0.2 @@ -19864,7 +20022,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 25.0.2 + '@types/node': 22.19.3 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -19903,7 +20061,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -19938,7 +20096,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -19966,7 +20124,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 chalk: 4.1.2 cjs-module-lexer: 1.4.3 collect-v8-coverage: 1.0.3 @@ -20012,7 +20170,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -20033,11 +20191,11 @@ snapshots: chalk: 3.0.0 prompts: 2.4.2 - jest-watch-typeahead@2.2.1(jest@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3))): + jest-watch-typeahead@2.2.1(jest@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3))): dependencies: ansi-escapes: 6.2.1 chalk: 4.1.2 - jest: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + jest: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) jest-regex-util: 29.6.3 jest-watcher: 29.7.0 slash: 5.1.0 @@ -20048,7 +20206,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 25.0.2 + '@types/node': 22.19.3 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -20063,17 +20221,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 25.0.2 + '@types/node': 22.19.3 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)): + jest@29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@25.0.2)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3)) + jest-cli: 29.7.0(@types/node@22.19.3)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -20292,7 +20450,7 @@ snapshots: kleur@3.0.3: {} - ky@1.14.2: {} + ky@1.14.1: {} lan-network@0.1.7: {} @@ -21444,7 +21602,7 @@ snapshots: statuses: 2.0.2 strict-event-emitter: 0.5.1 tough-cookie: 6.0.0 - type-fest: 5.3.1 + type-fest: 5.4.1 until-async: 3.0.2 yargs: 17.7.2 optionalDependencies: @@ -21470,7 +21628,7 @@ snapshots: statuses: 2.0.2 strict-event-emitter: 0.5.1 tough-cookie: 6.0.0 - type-fest: 5.3.1 + type-fest: 5.4.1 until-async: 3.0.2 yargs: 17.7.2 optionalDependencies: @@ -21507,11 +21665,11 @@ snapshots: napi-postinstall@0.3.4: {} - nativewind@4.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)): + nativewind@4.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)): dependencies: comment-json: 4.5.0 debug: 4.4.3(supports-color@10.2.2) - react-native-css-interop: 0.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)) + react-native-css-interop: 0.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)) tailwindcss: 3.4.19(yaml@2.8.2) transitivePeerDependencies: - react @@ -21839,7 +21997,7 @@ snapshots: package-json@10.0.1: dependencies: - ky: 1.14.2 + ky: 1.14.1 registry-auth-token: 5.1.0 registry-url: 6.0.1 semver: 7.7.3 @@ -22291,7 +22449,7 @@ snapshots: react-is@19.2.3: {} - react-native-css-interop@0.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)): + react-native-css-interop@0.2.1(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0)(tailwindcss@3.4.19(yaml@2.8.2)): dependencies: '@babel/helper-module-imports': 7.27.1 '@babel/traverse': 7.28.5 @@ -22299,57 +22457,57 @@ snapshots: debug: 4.4.3(supports-color@10.2.2) lightningcss: 1.27.0 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) semver: 7.7.3 tailwindcss: 3.4.19(yaml@2.8.2) optionalDependencies: - react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-svg: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-safe-area-context: 5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-svg: 15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - supports-color - react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-gesture-handler@2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@egjs/hammerjs': 2.0.17 hoist-non-react-statics: 3.3.2 invariant: 2.2.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-is-edge-to-edge@1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-is-edge-to-edge@1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@babel/core': 7.28.5 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-worklets: 0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-worklets: 0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) semver: 7.7.2 - react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-safe-area-context@5.6.2(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-screens@4.16.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: react: 19.1.0 react-freeze: 1.0.4(react@19.1.0) - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-is-edge-to-edge: 1.2.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) warn-once: 0.1.1 - react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-svg@15.12.1(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: css-select: 5.2.2 css-tree: 1.1.3 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) warn-once: 0.1.1 react-native-web@0.21.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): @@ -22367,14 +22525,14 @@ snapshots: transitivePeerDependencies: - encoding - react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-webview@13.15.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: escape-string-regexp: 4.0.0 invariant: 2.2.4 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): + react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0): dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) @@ -22388,21 +22546,21 @@ snapshots: '@babel/preset-typescript': 7.28.5(@babel/core@7.28.5) convert-source-map: 2.0.0 react: 19.1.0 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) semver: 7.7.2 transitivePeerDependencies: - supports-color - react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0): + react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0): dependencies: '@jest/create-cache-key-function': 29.7.0 '@react-native/assets-registry': 0.81.5 '@react-native/codegen': 0.81.5(@babel/core@7.28.5) - '@react-native/community-cli-plugin': 0.81.5(@react-native-community/cli@20.0.2(typescript@5.9.3)) + '@react-native/community-cli-plugin': 0.81.5(@react-native-community/cli@20.1.0(typescript@5.9.3)) '@react-native/gradle-plugin': 0.81.5 '@react-native/js-polyfills': 0.81.5 '@react-native/normalize-colors': 0.81.5 - '@react-native/virtualized-lists': 0.81.5(@types/react@19.2.3)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@react-native/virtualized-lists': 0.81.5(@types/react@19.2.3)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) abort-controller: 3.0.0 anser: 1.4.10 ansi-regex: 5.0.1 @@ -23517,14 +23675,16 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.16(webpack@5.102.1): + terser-webpack-plugin@5.3.16(@swc/core@1.15.7)(webpack@5.102.1(@swc/core@1.15.7)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.1 - webpack: 5.102.1 + webpack: 5.102.1(@swc/core@1.15.7) + optionalDependencies: + '@swc/core': 1.15.7 terser@5.44.1: dependencies: @@ -23653,7 +23813,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-node@10.9.2(@types/node@22.19.3)(typescript@5.9.3): + ts-node@10.9.2(@swc/core@1.15.7)(@types/node@22.19.3)(typescript@5.9.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.12 @@ -23670,25 +23830,8 @@ snapshots: typescript: 5.9.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - - ts-node@10.9.2(@types/node@25.0.2)(typescript@5.9.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.12 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 25.0.2 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.9.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optional: true + optionalDependencies: + '@swc/core': 1.15.7 tsconfck@3.1.6(typescript@5.9.3): optionalDependencies: @@ -23703,7 +23846,7 @@ snapshots: tslib@2.8.1: {} - tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2): + tsup@8.5.1(@swc/core@1.15.7)(jiti@2.6.1)(postcss@8.5.6)(typescript@5.9.3)(yaml@2.8.2): dependencies: bundle-require: 5.1.0(esbuild@0.27.1) cac: 6.7.14 @@ -23723,6 +23866,7 @@ snapshots: tinyglobby: 0.2.15 tree-kill: 1.2.2 optionalDependencies: + '@swc/core': 1.15.7 postcss: 8.5.6 typescript: 5.9.3 transitivePeerDependencies: @@ -23772,7 +23916,7 @@ snapshots: type-fest@4.41.0: {} - type-fest@5.3.1: + type-fest@5.4.1: dependencies: tagged-tag: 1.0.0 @@ -23848,7 +23992,8 @@ snapshots: undici-types@6.21.0: {} - undici-types@7.16.0: {} + undici-types@7.16.0: + optional: true undici@5.29.0: dependencies: @@ -24067,18 +24212,18 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - victory-native@41.20.2(304cb029cd54f6dc7590a1eb71d5c0a3): + victory-native@41.20.2(56acb8d1da5f9cc0e4ae48affe1ead3b): dependencies: - '@shopify/react-native-skia': 2.2.12(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + '@shopify/react-native-skia': 2.2.12(react-native-reanimated@4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) d3-scale: 4.0.2 d3-shape: 3.2.0 d3-zoom: 3.0.0 its-fine: 1.2.5(@types/react@19.2.3)(react@19.1.0) react: 19.1.0 react-fast-compare: 3.2.2 - react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) - react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) - react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.0.2(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native: 0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0) + react-native-gesture-handler: 2.28.0(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) + react-native-reanimated: 4.1.6(@babel/core@7.28.5)(react-native-worklets@0.5.1(@babel/core@7.28.5)(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0))(react-native@0.81.5(@babel/core@7.28.5)(@react-native-community/cli@20.1.0(typescript@5.9.3))(@types/react@19.2.3)(react@19.1.0))(react@19.1.0) transitivePeerDependencies: - '@types/react' @@ -24272,7 +24417,7 @@ snapshots: warn-once@0.1.1: {} - watchpack@2.5.0: + watchpack@2.4.4: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 @@ -24316,7 +24461,7 @@ snapshots: webpack-virtual-modules@0.5.0: {} - webpack@5.102.1: + webpack@5.102.1(@swc/core@1.15.7): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -24340,8 +24485,8 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(webpack@5.102.1) - watchpack: 2.5.0 + terser-webpack-plugin: 5.3.16(@swc/core@1.15.7)(webpack@5.102.1(@swc/core@1.15.7)) + watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: - '@swc/core' diff --git a/server/emails/src/emails/order_confirmation.tsx b/server/emails/src/emails/order_confirmation.tsx index bb8a404838..5bee3154f1 100644 --- a/server/emails/src/emails/order_confirmation.tsx +++ b/server/emails/src/emails/order_confirmation.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Hr, @@ -22,18 +27,34 @@ export function OrderConfirmation({ product, order, url, -}: schemas['OrderConfirmationProps']) { + locale = 'en', +}: schemas['OrderConfirmationProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Thank you for your order of {order.description}! + + {t.orderConfirmation.preview.replace('{description}', order.description)} +
- Thank you for your order! + {t.orderConfirmation.heading} - Your order of {order.description}{' '} - is now processed. + {t.orderConfirmation.processed + .split('{description}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {order.description} + + ) : ( + part + ), + )}
{product && ( @@ -42,7 +63,7 @@ export function OrderConfirmation({ )}
- +
)} @@ -50,10 +71,7 @@ export function OrderConfirmation({
- - If you're having trouble with the button above, copy and paste the URL - below into your web browser. - + {t.common.troubleWithButton} {url} @@ -71,6 +89,7 @@ OrderConfirmation.PreviewProps = { product, order, url: 'https://polar.sh/acme-inc/portal/orders/12345', + locale: 'en', } export default OrderConfirmation diff --git a/server/emails/src/emails/subscription_cancellation.tsx b/server/emails/src/emails/subscription_cancellation.tsx index 8e041ab319..4ea1fd16e0 100644 --- a/server/emails/src/emails/subscription_cancellation.tsx +++ b/server/emails/src/emails/subscription_cancellation.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Link, Preview, Section, Text } from '@react-email/components' import BodyText from '../components/BodyText' import Button from '../components/Button' @@ -7,16 +12,19 @@ import Wrapper from '../components/Wrapper' import { organization, product } from '../preview' import type { schemas } from '../types' -function BenefitsSection({ benefits }: { benefits: any[] }) { - // Only render if there are actual benefits to display +function BenefitsSection({ + benefits, + label, +}: { + benefits: any[] + label: string +}) { if (benefits.length === 0) { return null } return ( <> - - Meanwhile, you will continue to have access to the following benefits: - + {label}
    {benefits.map((benefit, index) => (
  • {benefit.description}
  • @@ -32,41 +40,59 @@ export function SubscriptionCancellation({ product, subscription, url, -}: schemas['SubscriptionCancellationProps']) { - const endDate = new Date(subscription.ends_at!).toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric', - }) + locale = 'en', +}: schemas['SubscriptionCancellationProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + + const dateLocale = + safeLocale === 'nl' ? 'nl-NL' : safeLocale === 'sv' ? 'sv-SE' : 'en-US' + const endDate = new Date(subscription.ends_at!).toLocaleDateString( + dateLocale, + { + year: 'numeric', + month: 'long', + day: 'numeric', + }, + ) return ( - Your subscription to {product.name} has been canceled + + {t.subscriptionCancellation.preview.replace('{product}', product.name)} +
    - Your subscription has been canceled + {t.subscriptionCancellation.heading} - We're sorry to see you go! Your subscription to{' '} - {product.name} will remain active - until {endDate}, after which it - will be canceled. + {t.subscriptionCancellation.sorryToSeeYouGo + .replace('{product}', product.name) + .replace('{endDate}', endDate) + .split(product.name) + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )} - - If you change your mind, you can renew your subscription anytime - before the end date. - - + {t.subscriptionCancellation.changeYourMind} +
    - +
    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser: - + {t.common.troubleWithButton} {url} @@ -83,9 +109,10 @@ SubscriptionCancellation.PreviewProps = { organization, product, subscription: { - ends_at: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), // 30 days from now + ends_at: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), }, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', + locale: 'en', } export default SubscriptionCancellation diff --git a/server/emails/src/emails/subscription_confirmation.tsx b/server/emails/src/emails/subscription_confirmation.tsx index 683b1dda37..8077952d66 100644 --- a/server/emails/src/emails/subscription_confirmation.tsx +++ b/server/emails/src/emails/subscription_confirmation.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Hr, @@ -23,32 +28,45 @@ export function SubscriptionConfirmation({ subscription, order, url, -}: schemas['SubscriptionConfirmationProps']) { + locale = 'en', +}: schemas['SubscriptionConfirmationProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Thank you for your subscription to {product.name}! + + {t.subscriptionConfirmation.preview.replace('{product}', product.name)} +
    - Thank you for your subscription! + {t.subscriptionConfirmation.heading} - Your subscription to {product.name}{' '} - is now active. + {t.subscriptionConfirmation.active + .split('{product}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )}
    {product.benefits.length > 0 && }
    - +


    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser. - + {t.common.troubleWithButton} {url} @@ -70,6 +88,7 @@ SubscriptionConfirmation.PreviewProps = { }, order, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', + locale: 'en', } export default SubscriptionConfirmation diff --git a/server/emails/src/emails/subscription_cycled.tsx b/server/emails/src/emails/subscription_cycled.tsx index c3249186b0..e86ef9c024 100644 --- a/server/emails/src/emails/subscription_cycled.tsx +++ b/server/emails/src/emails/subscription_cycled.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Hr, @@ -22,31 +27,44 @@ export function SubscriptionCycled({ subscription, order, url, -}: schemas['SubscriptionCycledProps']) { + locale = 'en', +}: schemas['SubscriptionCycledProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Your subscription to {product.name} has been renewed + + {t.subscriptionCycled.preview.replace('{product}', product.name)} +
    - Your subscription has been renewed + {t.subscriptionCycled.heading} - Your subscription to {product.name}{' '} - has been renewed. + {t.subscriptionCycled.renewed + .split('{product}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )}
    - +


    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser. - + {t.common.troubleWithButton} {url} @@ -68,6 +86,7 @@ SubscriptionCycled.PreviewProps = { }, order, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', + locale: 'en', } export default SubscriptionCycled diff --git a/server/emails/src/emails/subscription_past_due.tsx b/server/emails/src/emails/subscription_past_due.tsx index 91b16d0a1e..94becf524f 100644 --- a/server/emails/src/emails/subscription_past_due.tsx +++ b/server/emails/src/emails/subscription_past_due.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Link, Preview, Section, Text } from '@react-email/components' import BodyText from '../components/BodyText' import Button from '../components/Button' @@ -14,39 +19,47 @@ export function SubscriptionPastDue({ subscription, url, payment_url, -}: schemas['SubscriptionPastDueProps']) { + locale = 'en', +}: schemas['SubscriptionPastDueProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Your {product.name} subscription payment is past due + + {t.subscriptionPastDue.preview.replace('{product}', product.name)} +
    - Your subscription payment is past due + {t.subscriptionPastDue.heading} - We were unable to process your payment for your{' '} - {product.name} subscription. Your - subscription is now past due and access to benefits has been - temporarily suspended. - - - To restore access to your subscription benefits, please update your - payment method and complete the payment. + {t.subscriptionPastDue.paymentFailed + .split('{product}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )} + {t.subscriptionPastDue.updatePayment}
    {payment_url && (
    - +
    )}
    - +
    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser: - + {t.common.troubleWithButton} {url} @@ -69,6 +82,7 @@ SubscriptionPastDue.PreviewProps = { }, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', payment_url: 'https://invoice.stripe.com/i/acct_123/test', + locale: 'en', } export default SubscriptionPastDue diff --git a/server/emails/src/emails/subscription_revoked.tsx b/server/emails/src/emails/subscription_revoked.tsx index 2d4002bc10..8c2df7ec75 100644 --- a/server/emails/src/emails/subscription_revoked.tsx +++ b/server/emails/src/emails/subscription_revoked.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Link, Preview, Section, Text } from '@react-email/components' import BodyText from '../components/BodyText' import Button from '../components/Button' @@ -13,31 +18,42 @@ export function SubscriptionRevoked({ product, subscription, url, -}: schemas['SubscriptionRevokedProps']) { + locale = 'en', +}: schemas['SubscriptionRevokedProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Your subscription to {product.name} has now ended + + {t.subscriptionRevoked.preview.replace('{product}', product.name)} +
    - Your subscription has now ended + {t.subscriptionRevoked.heading} - Thank you for being a subscriber of{' '} - {product.name}. - - - We hope to see you again in the future - you're always welcome back. + {t.subscriptionRevoked.thankYou + .split('{product}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )} + {t.subscriptionRevoked.welcomeBack}
    - +
    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser. - + {t.common.troubleWithButton} {url} @@ -58,6 +74,7 @@ SubscriptionRevoked.PreviewProps = { status: 'canceled', }, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', + locale: 'en', } export default SubscriptionRevoked diff --git a/server/emails/src/emails/subscription_uncanceled.tsx b/server/emails/src/emails/subscription_uncanceled.tsx index 6e302cff60..441c3aba70 100644 --- a/server/emails/src/emails/subscription_uncanceled.tsx +++ b/server/emails/src/emails/subscription_uncanceled.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Link, Preview, Section, Text } from '@react-email/components' import BodyText from '../components/BodyText' import Button from '../components/Button' @@ -13,28 +18,41 @@ export function SubscriptionUncanceled({ product, subscription, url, -}: schemas['SubscriptionUncanceledProps']) { + locale = 'en', +}: schemas['SubscriptionUncanceledProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Your subscription to {product.name} is now uncanceled + + {t.subscriptionUncanceled.preview.replace('{product}', product.name)} +
    - Your subscription is now uncanceled + {t.subscriptionUncanceled.heading} - Your subscription to {product.name}{' '} - is no longer canceled. + {t.subscriptionUncanceled.noLongerCanceled + .split('{product}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )}
    - +
    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser. - + {t.common.troubleWithButton} {url} @@ -55,6 +73,7 @@ SubscriptionUncanceled.PreviewProps = { status: 'active', }, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', + locale: 'en', } export default SubscriptionUncanceled diff --git a/server/emails/src/emails/subscription_updated.tsx b/server/emails/src/emails/subscription_updated.tsx index bd15caa4c7..7f053370e4 100644 --- a/server/emails/src/emails/subscription_updated.tsx +++ b/server/emails/src/emails/subscription_updated.tsx @@ -1,3 +1,8 @@ +import { + getEmailTranslations, + isSupportedLocale, + type SupportedLocale, +} from '../i18n' import { Heading, Hr, @@ -23,49 +28,56 @@ export function SubscriptionUpdated({ subscription, order, url, -}: schemas['SubscriptionUpdatedProps']) { + locale = 'en', +}: schemas['SubscriptionUpdatedProps'] & { locale?: string }) { + const safeLocale: SupportedLocale = isSupportedLocale(locale) ? locale : 'en' + const t = getEmailTranslations(safeLocale) + return ( - Your subscription has been updated to {product.name} + + {t.subscriptionUpdated.preview.replace('{product}', product.name)} +
    - Your subscription has been updated + {t.subscriptionUpdated.heading} - Your subscription has been successfully changed to{' '} - {product.name}. + {t.subscriptionUpdated.changedTo + .split('{product}') + .map((part, i, arr) => + i < arr.length - 1 ? ( + + {part} + {product.name} + + ) : ( + part + ), + )}
    {product.benefits.length > 0 && }
    - +

    {order ? ( <>
    - - The changes take effect immediately. The pro-rated amount has been - charged to your account as part of this update. - + {t.subscriptionUpdated.immediateWithCharge}
    ) : (
    - - The changes take effect immediately. The pro-rated amount will be - reflected on your next billing cycle. - + {t.subscriptionUpdated.immediateNextCycle}
    )}
    - - If you're having trouble with the button above, copy and paste the URL - below into your web browser. - + {t.common.troubleWithButton} {url} @@ -87,6 +99,7 @@ SubscriptionUpdated.PreviewProps = { }, order, url: 'https://polar.sh/acme-inc/portal/subscriptions/12345', + locale: 'en', } export default SubscriptionUpdated diff --git a/server/emails/src/i18n.ts b/server/emails/src/i18n.ts new file mode 100644 index 0000000000..f5edee2f3e --- /dev/null +++ b/server/emails/src/i18n.ts @@ -0,0 +1,26 @@ +// Import locale files directly from the i18n package (single source of truth) +import en from '../../../clients/packages/i18n/locales/en.json' +import nl from '../../../clients/packages/i18n/locales/nl.json' +import sv from '../../../clients/packages/i18n/locales/sv.json' + +export const SUPPORTED_LOCALES = ['en', 'nl', 'sv'] as const +export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number] +export const DEFAULT_LOCALE: SupportedLocale = 'en' + +export function isSupportedLocale(locale: string): locale is SupportedLocale { + return SUPPORTED_LOCALES.includes(locale as SupportedLocale) +} + +type EmailTranslations = (typeof en)['email'] + +const translations: Record = { + en: en.email, + nl: nl.email, + sv: sv.email, +} + +export function getEmailTranslations( + locale: SupportedLocale = DEFAULT_LOCALE, +): EmailTranslations { + return translations[locale] || translations[DEFAULT_LOCALE] +} diff --git a/server/emails/tsconfig.json b/server/emails/tsconfig.json index 27652e4b16..46a41b92c4 100644 --- a/server/emails/tsconfig.json +++ b/server/emails/tsconfig.json @@ -27,9 +27,9 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "CommonJS" /* Specify what module code is generated. */, + "module": "ESNext" /* Specify what module code is generated. */, // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "commonjs" /* Specify how TypeScript looks up a file from a given module specifier. */, + "moduleResolution": "bundler" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ @@ -46,6 +46,7 @@ // "resolveJsonModule": true, /* Enable importing .json files. */ // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + "resolveJsonModule": true, /* Enable importing .json files. */ /* JavaScript Support */ // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ diff --git a/server/migrations/versions/2026-01-06-1654_add_locale_to_customers_and_checkouts.py b/server/migrations/versions/2026-01-06-1654_add_locale_to_customers_and_checkouts.py new file mode 100644 index 0000000000..88d591dbf7 --- /dev/null +++ b/server/migrations/versions/2026-01-06-1654_add_locale_to_customers_and_checkouts.py @@ -0,0 +1,32 @@ +"""Add locale to customers and checkouts + +Revision ID: f74ec458db91 +Revises: 4b8c9d0e1f2a +Create Date: 2026-01-06 16:54:36.624325 + +""" + +import sqlalchemy as sa +from alembic import op + +# Polar Custom Imports + +# revision identifiers, used by Alembic. +revision = "f74ec458db91" +down_revision = "4b8c9d0e1f2a" +branch_labels: tuple[str] | None = None +depends_on: tuple[str] | None = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("checkouts", sa.Column("locale", sa.String(length=10), nullable=True)) + op.add_column("customers", sa.Column("locale", sa.String(length=10), nullable=True)) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("customers", "locale") + op.drop_column("checkouts", "locale") + # ### end Alembic commands ### diff --git a/server/polar/checkout/schemas.py b/server/polar/checkout/schemas.py index 46a88e2ba4..2da372c393 100644 --- a/server/polar/checkout/schemas.py +++ b/server/polar/checkout/schemas.py @@ -125,6 +125,14 @@ ), ), ] +Locale = Annotated[ + str | None, + Field( + default=None, + max_length=10, + description="Locale for translations. E.g. 'en', 'nl', 'sv'.", + ), +] _external_customer_id_description = ( "ID of the customer in your system. " @@ -240,6 +248,7 @@ class CheckoutCreateBase( success_url: SuccessURL = None return_url: ReturnURL = None embed_origin: EmbedOrigin = None + locale: Locale = None class CheckoutPriceCreate(CheckoutCreateBase): @@ -360,6 +369,7 @@ class CheckoutUpdateBase(CustomFieldDataInputMixin, Schema): customer_billing_name: Annotated[str | None, EmptyStrToNoneValidator] = None customer_billing_address: CustomerBillingAddressInput | None = None customer_tax_id: Annotated[str | None, EmptyStrToNoneValidator] = None + locale: Locale = None class CheckoutUpdate( @@ -559,6 +569,7 @@ class CheckoutBase(CustomFieldDataOutputMixin, TimestampedSchema, IDSchema): customer_tax_id: str | None = Field( validation_alias=AliasChoices("customer_tax_id_number", "customer_tax_id") ) + locale: str | None = Field(default=None, description="Locale for translations.") payment_processor_metadata: dict[str, str] diff --git a/server/polar/checkout/service.py b/server/polar/checkout/service.py index c43e6d389c..f7024b6b49 100644 --- a/server/polar/checkout/service.py +++ b/server/polar/checkout/service.py @@ -522,6 +522,10 @@ async def create( ): checkout.is_business_customer = True + # Inherit locale from customer if not explicitly set + if checkout.locale is None and checkout.customer.locale is not None: + checkout.locale = checkout.customer.locale + if checkout.payment_processor == PaymentProcessor.stripe: checkout.payment_processor_metadata = { **(checkout.payment_processor_metadata or {}), @@ -2339,6 +2343,8 @@ async def _create_or_update_customer( customer.billing_address = checkout.customer_billing_address if checkout.customer_tax_id is not None: customer.tax_id = checkout.customer_tax_id + if checkout.locale is not None: + customer.locale = checkout.locale customer.stripe_customer_id = stripe_customer_id customer.user_metadata = { diff --git a/server/polar/customer/schemas/customer.py b/server/polar/customer/schemas/customer.py index 96793a8099..b9ad51ed45 100644 --- a/server/polar/customer/schemas/customer.py +++ b/server/polar/customer/schemas/customer.py @@ -49,6 +49,9 @@ ] +_locale_description = "The locale of the customer, used for translations." + + class CustomerCreate(MetadataInputMixin, Schema): external_id: Annotated[str | None, EmptyStrToNoneValidator] = Field( default=None, @@ -61,6 +64,12 @@ class CustomerCreate(MetadataInputMixin, Schema): name: CustomerNameInput | None = None billing_address: AddressInput | None = None tax_id: TaxID | None = None + locale: str | None = Field( + default=None, + max_length=10, + description=_locale_description, + examples=["en", "nl", "sv"], + ) organization_id: OrganizationID | None = Field( default=None, description=( @@ -85,6 +94,12 @@ class CustomerUpdateBase(MetadataInputMixin, Schema): name: CustomerNameInput | None = None billing_address: AddressInput | None = None tax_id: TaxID | None = None + locale: str | None = Field( + default=None, + max_length=10, + description=_locale_description, + examples=["en", "nl", "sv"], + ) class CustomerUpdate(CustomerUpdateBase): @@ -117,6 +132,11 @@ class CustomerBase(MetadataOutputMixin, TimestampedSchema, IDSchema): name: str | None = Field(description=_name_description, examples=[_name_example]) billing_address: Address | None tax_id: TaxID | None + locale: str | None = Field( + default=None, + description="The locale of the customer, used for translations.", + examples=["en", "nl", "sv"], + ) organization_id: UUID4 = Field( description="The ID of the organization owning the customer.", examples=[ORGANIZATION_ID_EXAMPLE], diff --git a/server/polar/email/schemas.py b/server/polar/email/schemas.py index 19f9a8a5b5..cb3ff721cd 100644 --- a/server/polar/email/schemas.py +++ b/server/polar/email/schemas.py @@ -59,6 +59,7 @@ class OrderEmail(OrderBase): class EmailProps(BaseModel): email: str + locale: str = "en" class LoginCodeProps(EmailProps): diff --git a/server/polar/models/checkout.py b/server/polar/models/checkout.py index 9d775d434b..ae989ded5a 100644 --- a/server/polar/models/checkout.py +++ b/server/polar/models/checkout.py @@ -228,6 +228,7 @@ def customer(cls) -> Mapped[Customer | None]: customer_tax_id: Mapped[TaxID | None] = mapped_column( TaxIDType, nullable=True, default=None ) + locale: Mapped[str | None] = mapped_column(String(10), nullable=True, default=None) customer_metadata: Mapped[MetadataColumn] # Only set when a checkout is attached to an existing subscription (free-to-paid upgrades). diff --git a/server/polar/models/customer.py b/server/polar/models/customer.py index 6f580d6a02..42c16ed8a0 100644 --- a/server/polar/models/customer.py +++ b/server/polar/models/customer.py @@ -180,6 +180,8 @@ class Customer(MetadataMixin, RecordModel): invoice_next_number: Mapped[int] = mapped_column(Integer, nullable=False, default=1) + locale: Mapped[str | None] = mapped_column(String(10), nullable=True, default=None) + organization_id: Mapped[UUID] = mapped_column( Uuid, ForeignKey("organizations.id", ondelete="cascade"), diff --git a/server/polar/order/service.py b/server/polar/order/service.py index 0ac946a3c6..cf0a5a3bd6 100644 --- a/server/polar/order/service.py +++ b/server/polar/order/service.py @@ -1393,6 +1393,7 @@ async def send_confirmation_email( "template": template_name, "props": { "email": customer.email, + "locale": customer.locale or "en", "organization": organization, "product": product, "order": order, diff --git a/server/polar/subscription/service.py b/server/polar/subscription/service.py index be5b5093a6..4e7f809dde 100644 --- a/server/polar/subscription/service.py +++ b/server/polar/subscription/service.py @@ -2340,6 +2340,7 @@ async def _send_customer_email( "template": template_name, "props": { "email": subscription.customer.email, + "locale": customer.locale or "en", "organization": organization, "product": product, "subscription": subscription,