diff --git a/.gitignore b/.gitignore index 23b408c..1e80292 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ .mf .wrangler .dev.vars +wrangler.json* +wrangler.toml diff --git a/.vscode/extensions.json b/.vscode/extensions.json index dac0ec1..1cd9acc 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,7 @@ { - "recommendations": ["biomejs.biome", "redhat.vscode-yaml"] + "recommendations": [ + "biomejs.biome", + "redhat.vscode-yaml", + "lokalise.i18n-ally" + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index e0826d7..41b8f4b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -46,5 +46,9 @@ }, "[yaml]": { "editor.defaultFormatter": "redhat.vscode-yaml" - } + }, + "i18n-ally.defaultNamespace": "translation", + "i18n-ally.localesPaths": ["app/lib/i18n/locales"], + "i18n-ally.keystyle": "nested", + "cSpell.words": ["unixepoch"] } diff --git a/app/components/auth-layout.tsx b/app/components/auth-layout.tsx index 28e1090..f685dbb 100644 --- a/app/components/auth-layout.tsx +++ b/app/components/auth-layout.tsx @@ -1,6 +1,9 @@ import { ArrowLeftIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; import { Link } from "react-router"; import { Button } from "~/components/ui/button"; +import { ColorSchemeToggle } from "./color-scheme-toggle"; +import { LangSwitcher } from "./lang/lang-switcher"; export function AuthLayout({ title, @@ -11,13 +14,19 @@ export function AuthLayout({ description: string; children: React.ReactNode; }) { + const { t } = useTranslation(); + return (
+
+ + +
diff --git a/app/components/error-boundary.tsx b/app/components/error-boundary.tsx index f761bd2..962a491 100644 --- a/app/components/error-boundary.tsx +++ b/app/components/error-boundary.tsx @@ -1,4 +1,5 @@ import { MehIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; import { isRouteErrorResponse, useRouteError } from "react-router"; import { buttonVariants } from "./ui/button"; @@ -78,9 +79,10 @@ export function ProductionErrorDisplay({ export function GeneralErrorBoundary() { const error = useRouteError(); + const { t } = useTranslation(); - const defaultMessage = "Oops! App Crashed 💥"; - const defaultDetails = "Please reload the page. or try again later."; + const defaultMessage = t("errors.crashed.title"); + const defaultDetails = t("errors.crashed.description"); // Handle route errors, Example: 404, 500, 503 if (isRouteErrorResponse(error)) { diff --git a/app/components/lang/lang-switcher.tsx b/app/components/lang/lang-switcher.tsx new file mode 100644 index 0000000..cfba4ab --- /dev/null +++ b/app/components/lang/lang-switcher.tsx @@ -0,0 +1,48 @@ +import { useTranslation } from "react-i18next"; +import { Button } from "~/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "~/components/ui/dropdown-menu"; +import { type SupportedLng, locales, localesByLang } from "~/lib/i18n/config"; +import { useSetLocale } from "~/lib/i18n/hook"; + +export function LangSwitcher() { + // const hydrated = useHydrated(); + const setLocale = useSetLocale(); + const { i18n } = useTranslation(); + + const handleChange = (e: React.MouseEvent) => { + const lang = e.currentTarget.dataset.lang as SupportedLng; + setLocale(lang); + }; + + // if (!hydrated) { + // return null; + // } + + return ( + + + + + + {locales.map((v) => { + return ( + + {v.label} + + ); + })} + + + ); +} diff --git a/app/components/settings/account-action.tsx b/app/components/settings/account-action.tsx index 08e64e2..d349ae7 100644 --- a/app/components/settings/account-action.tsx +++ b/app/components/settings/account-action.tsx @@ -2,6 +2,7 @@ import { CircleAlertIcon } from "lucide-react"; import { useState } from "react"; import { useFetcher } from "react-router"; +import { useTranslation } from "react-i18next"; import { Button } from "~/components/ui/button"; import { Dialog, @@ -17,6 +18,7 @@ import { Input } from "~/components/ui/input"; import { LoadingButton } from "../forms"; export function DeleteAccount({ email }: { email: string }) { + const { t } = useTranslation(); const [inputValue, setInputValue] = useState(""); const fetcher = useFetcher({ key: "delete-account" }); const isPending = fetcher.state !== "idle"; @@ -25,7 +27,7 @@ export function DeleteAccount({ email }: { email: string }) { @@ -38,11 +40,11 @@ export function DeleteAccount({ email }: { email: string }) {
- Final confirmation + {t("account.confirmation")} - This action cannot be undone. To confirm, please enter the email - address {email}. + {t("account.confirmationWarn")}{" "} + {email}.
@@ -61,12 +63,12 @@ export function DeleteAccount({ email }: { email: string }) { ({ key: "change-password" }); const isPending = fetcher.state !== "idle"; const [open, setOpen] = useState(false); @@ -41,16 +43,13 @@ export function ChangePassword() { - Change Password - - Make changes to your password here. You can change your password and - set a new password. - + {t("password.change.title")} + {t("password.change.action")} diff --git a/app/components/settings/settings-menu.tsx b/app/components/settings/settings-menu.tsx index 66c1d33..ce02ea6 100644 --- a/app/components/settings/settings-menu.tsx +++ b/app/components/settings/settings-menu.tsx @@ -1,3 +1,4 @@ +import type { i18n } from "i18next"; import { HardDriveIcon, KeyIcon, @@ -6,6 +7,7 @@ import { SunMoonIcon, UserIcon, } from "lucide-react"; +import { useTranslation } from "react-i18next"; import { NavLink, href } from "react-router"; import { cn } from "~/lib/utils"; @@ -16,35 +18,41 @@ interface MenuItem { icon: LucideIcon; } -const menuItems: MenuItem[] = [ - { - title: "Account", - url: href("/settings/account"), - icon: UserIcon, - }, - { - title: "Appearance", - url: href("/settings/appearance"), - icon: SunMoonIcon, - }, - { - title: "Connections", - url: href("/settings/connections"), - icon: Link2Icon, - }, - { - title: "Sessions", - url: href("/settings/sessions"), - icon: HardDriveIcon, - }, - { - title: "Password", - url: href("/settings/password"), - icon: KeyIcon, - }, -]; +function getMenuItems(i18n: i18n): MenuItem[] { + const { t } = i18n; + return [ + { + title: t("account.title"), + url: href("/settings/account"), + icon: UserIcon, + }, + { + title: t("appearance.title"), + url: href("/settings/appearance"), + icon: SunMoonIcon, + }, + { + title: t("connections.title"), + url: href("/settings/connections"), + icon: Link2Icon, + }, + { + title: t("sessions.title"), + url: href("/settings/sessions"), + icon: HardDriveIcon, + }, + { + title: t("user.password"), + url: href("/settings/password"), + icon: KeyIcon, + }, + ]; +} export function Menu() { + const { i18n } = useTranslation(); + const menuItems = getMenuItems(i18n); + return (
diff --git a/app/components/user-nav.tsx b/app/components/user-nav.tsx index 4b0ab13..876a9a6 100644 --- a/app/components/user-nav.tsx +++ b/app/components/user-nav.tsx @@ -3,9 +3,11 @@ import { useNavigate, useSubmit } from "react-router"; import { CircleGaugeIcon, HomeIcon, + LayoutDashboardIcon, LogOutIcon, UserCogIcon, } from "lucide-react"; +import { useTranslation } from "react-i18next"; import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar"; import { DropdownMenu, @@ -20,6 +22,7 @@ import { getAvatarUrl } from "~/lib/utils"; import { Button } from "./ui/button"; export function UserNav() { + const { t } = useTranslation(); const { user } = useAuthUser(); const navigate = useNavigate(); const submit = useSubmit(); @@ -62,7 +65,15 @@ export function UserNav() { }} > - Home Page + {t("home.title")} + + { + navigate("/dashboard"); + }} + > + + {t("dashboard.title")} { @@ -70,12 +81,12 @@ export function UserNav() { }} > - Account Settings + {t("dashboard.account.label")} {/* Todo: coming soon */} - Admin Dashboard + {t("dashboard.admin.label")} - Log out + {t("auth.signOut")} diff --git a/app/entry.client.tsx b/app/entry.client.tsx new file mode 100644 index 0000000..c1d0ba7 --- /dev/null +++ b/app/entry.client.tsx @@ -0,0 +1,30 @@ +import i18next from "i18next"; +import LanguageDetector from "i18next-browser-languagedetector"; +import { StrictMode, startTransition } from "react"; +import { hydrateRoot } from "react-dom/client"; +import { I18nextProvider, initReactI18next } from "react-i18next"; +import { HydratedRouter } from "react-router/dom"; +import { config } from "~/lib/i18n/config"; + +async function main() { + await i18next + .use(initReactI18next) + .use(LanguageDetector) + .init({ + ...config, + detection: { order: ["htmlTag"], caches: [] }, + }); + + startTransition(() => { + hydrateRoot( + document, + + + + + , + ); + }); +} + +main().catch((error) => console.error(error)); diff --git a/app/entry.server.tsx b/app/entry.server.tsx index daf529c..0fc6fe5 100644 --- a/app/entry.server.tsx +++ b/app/entry.server.tsx @@ -1,18 +1,22 @@ import { isbot } from "isbot"; import { renderToReadableStream } from "react-dom/server"; +import { I18nextProvider } from "react-i18next"; import type { AppLoadContext, EntryContext, HandleErrorFunction, + unstable_RouterContextProvider, } from "react-router"; import { ServerRouter } from "react-router"; import { NonceProvider } from "./hooks/use-nonce"; +import { getInstance } from "./middlewares/i18next"; export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, - routerContext: EntryContext, + entryContext: EntryContext, + routerContext: unstable_RouterContextProvider, _loadContext: AppLoadContext, ) { let shellRendered = false; @@ -30,7 +34,9 @@ export default async function handleRequest( const body = await renderToReadableStream( - + + + , { onError(error: unknown) { @@ -50,7 +56,7 @@ export default async function handleRequest( // Ensure requests from bots and SPA Mode renders wait for all content to load before responding // https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation - if ((userAgent && isbot(userAgent)) || routerContext.isSpaMode) { + if ((userAgent && isbot(userAgent)) || entryContext.isSpaMode) { await body.allReady; } diff --git a/app/lib/color-scheme/components.tsx b/app/lib/color-scheme/components.tsx index 326c3d5..0322df1 100644 --- a/app/lib/color-scheme/components.tsx +++ b/app/lib/color-scheme/components.tsx @@ -16,7 +16,7 @@ import { useRouteLoaderData, useSubmit, } from "react-router"; -import { z } from "zod"; +import { z } from "~/lib/validations/zod-i18n"; import type { loader as rootLoader } from "~/root"; export const ColorSchemeSchema = z.object({ diff --git a/app/lib/env.server.ts b/app/lib/env.server.ts index cca48bd..33d8b10 100644 --- a/app/lib/env.server.ts +++ b/app/lib/env.server.ts @@ -1,5 +1,5 @@ import { env as cloudflareEnv } from "cloudflare:workers"; -import { z } from "zod"; +import { z } from "~/lib/validations/zod-i18n"; /** * Server environment schema definition with validation rules diff --git a/app/lib/i18n/config.ts b/app/lib/i18n/config.ts new file mode 100644 index 0000000..20c7153 --- /dev/null +++ b/app/lib/i18n/config.ts @@ -0,0 +1,59 @@ +import type { InitOptions } from "i18next"; +import en from "./locales/en"; +import zh from "./locales/zh"; + +export const fallbackLng = "en"; +export const supportedLngs = ["en", "zh"] as const; +export const defaultNS = "translation"; + +export type SupportedLng = (typeof supportedLngs)[number]; + +// export type Resources = { [K in SupportedLng]: typeof en }; +export type Resources = Record; +export const resources = { + en, + zh, +} satisfies Resources; + +// export const supportedList = Object.keys(resources).map((v) => v); +export const supportedList = supportedLngs.map((v) => v.toString()); + +export interface Locale { + name: string; + label: string; + locale: string; + lang: SupportedLng; +} + +export const locales: Array = [ + { name: "English", label: "English", locale: "en-US", lang: "en" }, + { name: "SimpleChinese", label: "简体中文", locale: "zh-CN", lang: "zh" }, +] as const; + +export const localesByLang: Record = locales.reduce( + (acc, language) => { + acc[language.lang] = language; + return acc; + }, + {} as Record, +); + +export const config = { + // This is the list of languages your application supports + supportedLngs, + // This is the language you want to use in case + // if the user language is not in the supportedLngs + fallbackLng, + // The default namespace of i18next is "translation", but you can customize it here + defaultNS, + // instead of backend + resources, +} satisfies InitOptions; + +// zod-i18n +// https://github.com/aiji42/zod-i18n/blob/main/packages/core/locales/en/zod.json +// export type ZodResources = Record>; +// export const zodResources = { +// en: { zod: en.zod }, +// zh: { zod: zh.zod }, +// } satisfies ZodResources; diff --git a/app/lib/i18n/detector.ts b/app/lib/i18n/detector.ts new file mode 100644 index 0000000..a862a39 --- /dev/null +++ b/app/lib/i18n/detector.ts @@ -0,0 +1,72 @@ +import { createCookie, createCookieSessionStorage } from "react-router"; +import { fallbackLng, supportedList } from "./config"; + +const methods = ["cookie", "session", "path"] as const; + +export type Method = (typeof methods)[number]; + +export const localeCookie = createCookie("lng", { + path: "/", + sameSite: "lax", + secure: process.env.NODE_ENV === "production", + secrets: [process.env.BETTER_AUTH_SECRET], + // secrets: ["secrets"], + httpOnly: true, +}); + +export const localeSession = createCookieSessionStorage({ + cookie: { + name: "session", + path: "/", + sameSite: "lax", + secure: process.env.NODE_ENV === "production", + secrets: [process.env.BETTER_AUTH_SECRET], + // secrets: ["secrets"], + httpOnly: true, + }, +}); + +export async function detect( + request: Request, + method: Method, +): Promise { + if (method === "cookie") { + return await fromCookie(request); + } + if (method === "session") { + return await fromSession(request); + } + if (method === "path") { + return fromPath(request); + } + return fallbackLng; +} + +async function fromCookie(request: Request): Promise { + // if (!localeCookie) return fallbackLng; + const lng = await localeCookie.parse(request.headers.get("Cookie")); + // console.log("fromCookie lng =>", lng); + return lng || fallbackLng; +} + +async function fromSession(request: Request): Promise { + // if (!localeSession) return fallbackLng; + const session = await localeSession.getSession(request.headers.get("Cookie")); + const lng = session.get("lng"); + // console.log("fromSession lng =>", lng); + return lng || fallbackLng; +} + +function fromPath(request: Request) { + const { pathname } = new URL(request.url); + return findLocaleByPath(pathname); +} + +export function findLocaleByPath(pathname: string) { + const segments = pathname.split("/"); + const lang = segments.at(1); + if (lang && supportedList.includes(lang)) { + return lang; + } + return fallbackLng; +} diff --git a/app/lib/i18n/hook.ts b/app/lib/i18n/hook.ts new file mode 100644 index 0000000..aa83ea9 --- /dev/null +++ b/app/lib/i18n/hook.ts @@ -0,0 +1,22 @@ +import { useLocation, useSubmit } from "react-router"; +import type { SupportedLng } from "./config"; + +export function useSetLocale() { + const { pathname, search, hash } = useLocation(); + const submit = useSubmit(); + + return (locale: SupportedLng) => { + submit( + { + locale, + returnTo: pathname + search + hash, + }, + { + method: "post", + action: "/api/locale", + preventScrollReset: true, + replace: true, + }, + ); + }; +} diff --git a/app/lib/i18n/locales/en.ts b/app/lib/i18n/locales/en.ts new file mode 100644 index 0000000..c151021 --- /dev/null +++ b/app/lib/i18n/locales/en.ts @@ -0,0 +1,171 @@ +import resource from "zod-i18n-map/locales/en/zod.json"; + +const translation = { + title: "React Router(v7) <0/> with Better Auth", + description: + "This is a template that can be deployed on Cloudflare Workers, built with React Router v7 (Remix), Better Auth, Drizzle ORM, and D1.", + common: { + refresh: "Refresh", + submit: "Submit", + cancel: "Cancel", + add: "Add", + adding: "Adding...", + delete: "Delete", + deleting: "Deleting...", + save: "Save", + saving: "Saving...", + }, + user: { + name: "Name", + token: "Token", + email: "Email", + password: "Password", + currentPassword: "Current password", + newPassword: "New password", + confirmPassword: "Confirm password", + }, + auth: { + signIn: "Sign In", + signingIn: "Signing in...", + signInTitle: "Sign in to your account", + signInWelcome: "Welcome back! Please sign in to continue.", + signInWith: "Login with <0>{{name}}", + signUp: "Sign Up", + signingUp: "Signing Up...", + signUpContinue: "Or continue with", + signUpTitle: "Create your account", + signUpWelcome: "Welcome! Please fill in the details to get started.", + signingUpSuccess: + "Sign up successful! Please check your email for a verification link.", + enterPassword: "Enter a unique password", + signOut: "Sign Out", + signingOut: "Signing Out...", + forgotPasswordTitle: "Forgot your password?", + forgotPasswordDescription: + "Enter your email address and we will send you a password reset link.", + enterEmail: "Enter your email", + sendResetLink: "Send reset link", + sendingResetLink: "Sending reset link...", + sentLinkSuccess: "Password reset link sent to your email!", + resetPasswordTitle: "Reset your password", + resetPasswordDescription: + "Enter your new password below, minimum 8 characters, maximum 32 characters.", + resetPassword: "Reset Password", + resettingPassword: "Resetting Password...", + newPassword: "New password", + confirmPassword: "Confirm new password", + backSignIn: "Back to sign in", + noAccount: "Don't have an account?", + haveAccount: "Already have an account?", + serviceAndPolicy: + "By clicking continue, you agree to our <0>Terms of Service and <1>Privacy Policy.", + }, + home: { + title: "Home", + start: "Get Started", + star: "Star on Github", + }, + todo: { + title: "Todo List", + today: "Today is", + add: "Add a todo", + noFound: "No todos found", + }, + dashboard: { + title: "Dashboard", + welcome: + "Welcome to your dashboard. Here you can manage your todos and account settings.", + todo: { + label: "Todo List", + description: "Create and manage your todos", + }, + account: { + label: "Account Settings", + description: "Manage your account settings", + }, + admin: { + label: "Admin Dashboard", + }, + }, + account: { + title: "Account", + description: "Click avatar to change profile picture.", + deleted: "Account deleted.", + avatar: "Avatar", + noAvatar: "No avatar to delete.", + avatarDeleted: "Avatar deleted.", + avatarUpdated: "Avatar updated.", + nameEmail: "Name & Email address", + currentSignIn: "Current sign in", + signInAs: "You are signed in as", + deleteAccount: "Delete account", + permanentlyDeleteAccount: "Permanently delete your account.", + confirmation: "Final confirmation", + confirmationWarn: + "This action cannot be undone. To confirm, please enter the email address", + }, + appearance: { + title: "Appearance", + description: + "Customize the appearance of the app. Automatically switch between day and night themes.", + }, + connections: { + title: "Connections", + description: "You can connect your account to third-party services below.", + }, + sessions: { + title: "Sessions", + description: + "If necessary, you can sign out of all other browser sessions. Some of your recent sessions are listed below, but this list may not be complete. If you think your account has been compromised, you should also update your password.", + noSessions: "No sessions found.", + otherSignedOut: "Other sessions signed out successfully.", + }, + password: { + title: "Password", + change: { + title: "Change your password", + description: + "If you have already set your password, you can update it here. If you have forgotten your password, please reset it below.", + success: "Password changed successfully! Other sessions revoked.", + action: + "Make changes to your password here. You can change your password and set a new password.", + }, + reset: { + title: "Reset your password", + description: + "If you have forgotten your password, you can reset it here. Alternatively, if have signed up via Github / Google and more, you can set your password here too.", + success: "Password reset successfully! Please sign in again.", + }, + }, + errors: { + invalidData: "Invalid form data.", + invalidIntent: "Invalid intent.", + unexpected: "An unexpected error occurred.", + loadingSessions: "Error loading sessions", + signInFailed: "{{provider}} sign in failed.", + invalidLoginMethod: "Invalid login method.", + crashed: { + title: "Oops! App Crashed 💥", + description: "Please reload the page or try again later.", + }, + notFound: { + title: "Oops! Page Not Found.", + description: + "It seems like the page you're looking for does not exist or might have been removed.", + }, + }, +}; + +const zod = { + custom: { + ...translation.user, + isRequired: "{{field}} is required.", + passwordNotMatch: "New password and confirm password do not match.", + }, + ...resource, +}; + +export default { + translation, + zod, +}; diff --git a/app/lib/i18n/locales/zh.ts b/app/lib/i18n/locales/zh.ts new file mode 100644 index 0000000..322f789 --- /dev/null +++ b/app/lib/i18n/locales/zh.ts @@ -0,0 +1,163 @@ +import resource from "zod-i18n-map/locales/zh-CN/zod.json"; + +const translation = { + title: "React Router(v7) <0/> with Better Auth", + description: + "这是一个可以在CloudFlare Workers上部署的模板,该模板是由React Router V7(Remix),Better Auth,Drizzle Orm和D1构建的。", + common: { + refresh: "刷新", + submit: "提交", + cancel: "取消", + add: "添加", + adding: "正在添加...", + delete: "删除", + deleting: "正在删除...", + save: "保存", + saving: "正在保存...", + }, + user: { + name: "昵称", + token: "令牌", + email: "邮箱", + password: "密码", + currentPassword: "当前密码", + newPassword: "新密码", + confirmPassword: "确认密码", + }, + auth: { + signIn: "登录", + signingIn: "登录中...", + signInTitle: "账户登录", + signInWelcome: "欢迎回来!请继续登录", + signInWith: "通过<0>{{name}}登录", + signUp: "注册", + signingUp: "正在注册...", + signUpContinue: "或者", + signUpTitle: "账户注册", + signUpWelcome: "欢迎!请填写详细信息", + signingUpSuccess: "注册成功!请检查您的电子邮件以获取认证链接", + enterPassword: "输入个性密码", + signOut: "登出", + signingOut: "正在登出...", + forgotPasswordTitle: "忘记密码?", + forgotPasswordDescription: + "输入您的电子邮件地址,我们将向您发送密码重置链接", + enterEmail: "输入您的电子邮件", + sendResetLink: "发送密码重置链接", + sendingResetLink: "正在发送密码重置链接...", + sentLinkSuccess: "密码重置链接已发送到您的邮件中!", + resetPasswordTitle: "重置您的密码", + resetPasswordDescription: "在下面输入您的新密码,至少8个字符,最大32个字符", + resetPassword: "重置密码", + resettingPassword: "正在重置密码...", + newPassword: "新密码", + confirmPassword: "确认新密码", + backSignIn: "返回登录", + noAccount: "还没有账户?", + haveAccount: "已有账户?", + serviceAndPolicy: "单击继续,同意我们的 <0>服务条款 与 <1>隐私政策", + }, + home: { + title: "主页", + start: "开始", + star: "在Github上点赞", + }, + todo: { + title: "待办事项列表", + today: "今天是", + add: "添加待办事项", + noFound: "没有待办事项", + }, + dashboard: { + title: "控制面板", + welcome: "欢迎来到控制面板,您可以在这里管理您的待办事项和帐户设置。", + todo: { + label: "待办事项", + description: "创建和管理您的待办事项", + }, + account: { + label: "帐户设置", + description: "管理您的帐户设置", + }, + admin: { + label: "管理面板", + }, + }, + account: { + title: "帐户", + description: "点击头像更改个人资料图片", + deleted: "帐户已删除", + avatar: "头像", + noAvatar: "没有头像", + avatarDeleted: "头像已删除", + avatarUpdated: "头像已更新", + nameEmail: "昵称 & 邮箱", + currentSignIn: "当前登录", + signInAs: "当前登录账户为", + deleteAccount: "删除帐户", + permanentlyDeleteAccount: "永久删除帐户", + confirmation: "最终确认", + confirmationWarn: "该动作不能撤消,请输入电子邮件地址以确认。", + }, + appearance: { + title: "外观", + description: "自定义应用程序的外观。自动在白天和黑夜主题之间切换。", + }, + connections: { + title: "关联", + description: "您可以将您的帐户关联到下面的第三方登录服务。", + }, + sessions: { + title: "会话", + description: + "如有必要,您可以登出其他所有浏览器会话。以下是您最近的会话,但此列表可能不完整。如果您认为您的帐户已被盗用,则应该更新密码。", + noSessions: "没有会话", + otherSignedOut: "其他会话登出成功", + }, + password: { + title: "密码", + change: { + title: "更改密码", + description: + "如果您已经设置了密码,则可以在此处进行更新。如果您忘记了密码,请在下面重置。", + success: "密码成功更改了!其他会话已被撤销。", + action: "在此处更改密码。您可以更改密码并设置新密码。", + }, + reset: { + title: "重置密码", + description: + "如果您忘记了密码,则可以在此处重置。另外,如果已经通过Github / Google注册,则可以在此处设置密码", + success: "密码重置成功!请再次登录。", + }, + }, + errors: { + invalidData: "无效的表单数据", + invalidIntent: "无效的意图", + unexpected: "发生意外错误", + loadingSessions: "加载会话错误", + signInFailed: "{{provider}} 登录失败", + invalidLoginMethod: "无效的登录方法", + crashed: { + title: "哇哦!应用崩溃了 💥", + description: "请重新加载页面或稍后再试。", + }, + notFound: { + title: "哇哦!找不到此页面", + description: "似乎您要访问的页面不存在或可能已被删除。", + }, + }, +}; + +const zod = { + custom: { + ...translation.user, + isRequired: "{{field}}是必填的", + passwordNotMatch: "新密码和确认密码不匹配", + }, + ...resource, +}; + +export default { + translation, + zod, +}; diff --git a/app/lib/i18n/middleware.ts b/app/lib/i18n/middleware.ts new file mode 100644 index 0000000..b25c557 --- /dev/null +++ b/app/lib/i18n/middleware.ts @@ -0,0 +1,57 @@ +import { + type InitOptions, + type Module, + type NewableModule, + createInstance, + type i18n, +} from "i18next"; +import { + type unstable_MiddlewareFunction, + type unstable_RouterContextProvider, + unstable_createContext, +} from "react-router"; +import { detect } from "./detector"; + +export function unstable_createI18nextMiddleware({ + options, + plugins = [], +}: unstable_createI18nextMiddleware.Params): unstable_createI18nextMiddleware.ReturnType { + const localeContext = unstable_createContext(); + const i18nextContext = unstable_createContext(); + + return [ + async function i18nextMiddleware({ request, context }, next) { + const lng = await detect(request, "cookie"); + context.set(localeContext, lng); + + const instance = createInstance(options); + for (const plugin of plugins ?? []) instance.use(plugin); + await instance.init({ lng }); + context.set(i18nextContext, instance); + + return await next(); + }, + (context) => context.get(localeContext), + (context) => context.get(i18nextContext), + ]; +} + +export namespace unstable_createI18nextMiddleware { + export interface Params { + /** + * The i18next options used to initialize the internal i18next instance. + */ + options: InitOptions; + /** + * The i18next plugins used to extend the internal i18next instance + * when creating a new TFunction. + */ + plugins?: NewableModule[] | Module[]; + } + + export type ReturnType = [ + unstable_MiddlewareFunction, + (context: unstable_RouterContextProvider) => string, + (context: unstable_RouterContextProvider) => i18n, + ]; +} diff --git a/app/lib/i18n/schema.ts b/app/lib/i18n/schema.ts new file mode 100644 index 0000000..6604778 --- /dev/null +++ b/app/lib/i18n/schema.ts @@ -0,0 +1,9 @@ +import { z } from "~/lib/validations/zod-i18n"; +import { supportedLngs } from "./config"; + +export const LocaleSchema = z.object({ + locale: z.enum(supportedLngs), + returnTo: z.string().optional(), +}); + +export type LocaleFormData = z.infer; diff --git a/app/lib/validations/auth.ts b/app/lib/validations/auth.ts index ae1af10..7bc731c 100644 --- a/app/lib/validations/auth.ts +++ b/app/lib/validations/auth.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z, zodT } from "./zod-i18n"; type passwordSchemaType = z.infer; @@ -15,7 +15,8 @@ const passwordConfirmationRefinement = ( ctx.addIssue({ path: ["confirmPassword"], code: z.ZodIssueCode.custom, - message: "New password and confirm password do not match.", + // message: "New password and confirm password do not match.", + params: { i18n: "custom.passwordNotMatch" }, }); } }; @@ -24,21 +25,33 @@ const customSignInErrorMap: z.ZodErrorMap = (issue, ctx) => { if (issue.code === z.ZodIssueCode.invalid_union_discriminator) { return { message: "Invalid sign-in provider specified." }; } + if (issue.code === z.ZodIssueCode.invalid_type) { + if ( + issue.expected === "string" && + ["undefined", "null"].includes(issue.received) + ) { + return { + message: zodT("custom.isRequired", { + field: zodT(`custom.${issue.path[0]}`), + }), + }; + } + } return { message: ctx.defaultError }; }; export const emailSchema = z - .string({ message: "Email is required." }) - .email({ message: "Invalid email address." }) + .string({ errorMap: customSignInErrorMap }) + .email() .toLowerCase() .trim(); export const passwordSchema = z - .string({ message: "Password is required." }) - .min(8, "Password must be at least 8 characters long.") - .max(32, "Password must be less than 32 characters long."); + .string({ errorMap: customSignInErrorMap }) + .min(8) + .max(32); -export const tokenSchema = z.string().min(1, "Token is required."); +export const tokenSchema = z.string().min(1); export const signInSchema = z.discriminatedUnion( "provider", @@ -61,10 +74,7 @@ export const signInSchema = z.discriminatedUnion( export const signUpSchema = z.object({ email: emailSchema, password: passwordSchema, - name: z - .string({ message: "Name is required." }) - .min(3, "Name must be at least 3 characters long.") - .trim(), + name: z.string().min(3).trim(), }); export const forgetPasswordSchema = z.object({ @@ -77,6 +87,7 @@ export const resetPasswordSchema = z newPassword: passwordSchema, confirmPassword: passwordSchema, }) + // .refine(() => false, { params: { i18n: "test_custom_key" } }); .superRefine(passwordConfirmationRefinement); export const changePasswordSchema = z diff --git a/app/lib/validations/settings.ts b/app/lib/validations/settings.ts index 998db4a..f02e256 100644 --- a/app/lib/validations/settings.ts +++ b/app/lib/validations/settings.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "./zod-i18n"; export const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB diff --git a/app/lib/validations/todo.ts b/app/lib/validations/todo.ts index 0ac5381..8419875 100644 --- a/app/lib/validations/todo.ts +++ b/app/lib/validations/todo.ts @@ -1,4 +1,4 @@ -import { z } from "zod"; +import { z } from "./zod-i18n"; export const todoIdSchema = z.string().transform((val) => Number(val)); diff --git a/app/lib/validations/zod-i18n.ts b/app/lib/validations/zod-i18n.ts new file mode 100644 index 0000000..9659b0e --- /dev/null +++ b/app/lib/validations/zod-i18n.ts @@ -0,0 +1,19 @@ +import i18next from "i18next"; +import { z } from "zod"; +import { zodI18nMap } from "zod-i18n-map"; + +z.setErrorMap(zodI18nMap); + +// const setZodLanguage = (language: SupportedLng) => { +// i18next.changeLanguage(language); +// z.setErrorMap(makeZodI18nMap({ t: i18next.t })); +// }; + +function zodT(key: string, options?: Record) { + return i18next.t(key, { + ns: "zod", + ...options, + }); +} + +export { z, zodT }; diff --git a/app/lib/middlewares/auth-guard.server.ts b/app/middlewares/auth-guard.server.ts similarity index 96% rename from app/lib/middlewares/auth-guard.server.ts rename to app/middlewares/auth-guard.server.ts index 12b021e..bf67fee 100644 --- a/app/lib/middlewares/auth-guard.server.ts +++ b/app/middlewares/auth-guard.server.ts @@ -35,7 +35,7 @@ export const noAuthMiddleware: unstable_MiddlewareFunction = async ( const authSession = await getAuthSession(request); if (authSession) { - throw redirect("/home"); + throw redirect("/dashboard"); } return await next(); diff --git a/app/middlewares/i18next.ts b/app/middlewares/i18next.ts new file mode 100644 index 0000000..8bf6982 --- /dev/null +++ b/app/middlewares/i18next.ts @@ -0,0 +1,9 @@ +import { initReactI18next } from "react-i18next"; +import { config } from "~/lib/i18n/config"; +import { unstable_createI18nextMiddleware } from "~/lib/i18n/middleware"; + +export const [i18nextMiddleware, getLocale, getInstance] = + unstable_createI18nextMiddleware({ + options: config, + plugins: [initReactI18next], + }); diff --git a/app/root.tsx b/app/root.tsx index 610f859..dde67a4 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -8,11 +8,11 @@ import { } from "react-router"; import { getToast } from "remix-toast"; import { Toaster, toast as notify } from "sonner"; - import { ProgressBar } from "./components/progress-bar"; import { useNonce } from "./hooks/use-nonce"; import "./styles/app.css"; import { useEffect } from "react"; +import { useTranslation } from "react-i18next"; import type { Route } from "./+types/root"; import { GeneralErrorBoundary } from "./components/error-boundary"; import { @@ -22,6 +22,7 @@ import { import { parseColorScheme } from "./lib/color-scheme/server"; import { getPublicEnv } from "./lib/env.server"; import { requestMiddleware } from "./lib/http.server"; +import { getLocale, i18nextMiddleware } from "./middlewares/i18next"; export const links: Route.LinksFunction = () => [ { rel: "preconnect", href: "https://fonts.googleapis.com" }, @@ -40,21 +41,32 @@ export const links: Route.LinksFunction = () => [ }, ]; -export async function loader({ request }: Route.LoaderArgs) { +export const unstable_middleware = [i18nextMiddleware]; + +export async function loader({ request, context }: Route.LoaderArgs) { await requestMiddleware(request); const colorScheme = await parseColorScheme(request); const { toast, headers } = await getToast(request); - - return data({ ENV: getPublicEnv(), colorScheme, toast }, { headers }); + // get locale and set + const locale = getLocale(context); + // use session + // const session = await localeSession.getSession(request.headers.get("Cookie")); + // session.set("lng", locale); + // headers.append("Set-Cookie", await localeSession.commitSession(session)); + // use cookie + // headers.append("Set-Cookie", await localeCookie.serialize(locale)); + return data({ locale, ENV: getPublicEnv(), colorScheme, toast }, { headers }); } export function Layout({ children }: { children: React.ReactNode }) { const nonce = useNonce(); const colorScheme = useColorScheme(); + const { i18n } = useTranslation(); return ( @@ -80,8 +92,14 @@ export function Layout({ children }: { children: React.ReactNode }) { } export default function App({ loaderData }: Route.ComponentProps) { - const { ENV, toast } = loaderData; + const { ENV, toast, locale } = loaderData; const nonce = useNonce(); + const { i18n } = useTranslation(); + // console.log(`App => locale = ${locale}, i18n.language = ${i18n.language}`); + + useEffect(() => { + if (i18n.language !== locale) i18n.changeLanguage(locale); + }, [locale, i18n]); useEffect(() => { if (toast?.type === "error") { diff --git a/app/routes.ts b/app/routes.ts index c415d50..6a6c563 100644 --- a/app/routes.ts +++ b/app/routes.ts @@ -11,7 +11,7 @@ export default [ // User routes layout("routes/layout.tsx", [ - route("home", "routes/home.tsx"), + route("dashboard", "routes/dashboard.tsx"), route("todos", "routes/todos.tsx"), ...prefix("settings", [ @@ -43,6 +43,7 @@ export default [ ...prefix("api", [ route("auth/error", "routes/api/better-error.tsx"), route("auth/*", "routes/api/better.tsx"), + route("locale", "routes/api/locale.ts"), route("color-scheme", "routes/api/color-scheme.ts"), ]), diff --git a/app/routes/api/locale.ts b/app/routes/api/locale.ts new file mode 100644 index 0000000..46ced2f --- /dev/null +++ b/app/routes/api/locale.ts @@ -0,0 +1,27 @@ +import { parseWithZod } from "@conform-to/zod"; +import { data, redirect } from "react-router"; +import { localeCookie } from "~/lib/i18n/detector"; +import { LocaleSchema } from "~/lib/i18n/schema"; +import type { Route } from "./+types/color-scheme"; + +export async function action({ request }: Route.ActionArgs) { + const formData = await request.clone().formData(); + const submission = parseWithZod(formData, { schema: LocaleSchema }); + + if (submission.status !== "success") { + throw data("Invalid locale scheme", { status: 400 }); + } + + const { locale, returnTo } = submission.value; + + // use session + // const session = await localeSession.getSession(request.headers.get("Cookie")); + // session.set("lng", locale); + // return redirect(returnTo || "/", { + // headers: { "Set-Cookie": await localeSession.commitSession(session) }, + // }); + // use cookie + return redirect(returnTo || "/", { + headers: { "Set-Cookie": await localeCookie.serialize(locale) }, + }); +} diff --git a/app/routes/auth/forget-password.tsx b/app/routes/auth/forget-password.tsx index 92490ed..68f2972 100644 --- a/app/routes/auth/forget-password.tsx +++ b/app/routes/auth/forget-password.tsx @@ -1,8 +1,8 @@ import { getFormProps, getInputProps, useForm } from "@conform-to/react"; import { getZodConstraint, parseWithZod } from "@conform-to/zod"; +import { getI18n, useTranslation } from "react-i18next"; import { Form, Link } from "react-router"; import { toast } from "sonner"; - import { AuthLayout } from "~/components/auth-layout"; import { InputField, LoadingButton } from "~/components/forms"; import { useIsPending } from "~/hooks/use-is-pending"; @@ -16,6 +16,7 @@ export const meta: Route.MetaFunction = () => { }; export async function clientAction({ request }: Route.ClientActionArgs) { + const { t } = getI18n(); const formData = await request.formData(); const submission = parseWithZod(formData, { schema: forgetPasswordSchema }); @@ -29,8 +30,8 @@ export async function clientAction({ request }: Route.ClientActionArgs) { }); return error - ? toast.error(error.message || "An unexpected error occurred.") - : toast.success("Password reset link sent to your email!"); + ? toast.error(error.message || t("errors.unexpected")) + : toast.success(t("auth.sentLinkSuccess")); } export default function ForgetPasswordRoute() { @@ -42,34 +43,35 @@ export default function ForgetPasswordRoute() { shouldRevalidate: "onInput", }); + const { t } = useTranslation(); const isPending = useIsPending({ formMethod: "POST", }); return (
- ← Back to sign in + ← {t("auth.backSignIn")}
diff --git a/app/routes/auth/layout.tsx b/app/routes/auth/layout.tsx index 7aa32d6..f74307d 100644 --- a/app/routes/auth/layout.tsx +++ b/app/routes/auth/layout.tsx @@ -1,5 +1,5 @@ import { Outlet } from "react-router"; -import { noAuthMiddleware } from "~/lib/middlewares/auth-guard.server"; +import { noAuthMiddleware } from "~/middlewares/auth-guard.server"; export const unstable_middleware = [noAuthMiddleware]; diff --git a/app/routes/auth/reset-password.tsx b/app/routes/auth/reset-password.tsx index 5489066..502cec9 100644 --- a/app/routes/auth/reset-password.tsx +++ b/app/routes/auth/reset-password.tsx @@ -3,6 +3,7 @@ import { getZodConstraint, parseWithZod } from "@conform-to/zod"; import { Form, Link, data, redirect } from "react-router"; import { toast } from "sonner"; +import { getI18n, useTranslation } from "react-i18next"; import { AuthLayout } from "~/components/auth-layout"; import { LoadingButton, PasswordField } from "~/components/forms"; import { useIsPending } from "~/hooks/use-is-pending"; @@ -23,6 +24,7 @@ export async function loader({ request }: Route.LoaderArgs) { } export async function clientAction({ request }: Route.ClientActionArgs) { + const { t } = getI18n(); const formData = await request.formData(); const submission = parseWithZod(formData, { schema: resetPasswordSchema }); @@ -36,10 +38,10 @@ export async function clientAction({ request }: Route.ClientActionArgs) { }); if (error) { - return toast.error(error.message || "An unexpected error occurred."); + return toast.error(error.message || t("errors.unexpected")); } - toast.success("Password reset successfully! Please sign in again."); + toast.success(t("password.reset.success")); return redirect("/auth/sign-in"); } @@ -54,41 +56,42 @@ export default function ResetPasswordRoute({ shouldRevalidate: "onInput", }); + const { t } = useTranslation(); const isPending = useIsPending({ formMethod: "POST", }); return (
- ← Back to sign in + ← {t("auth.backSignIn")}
diff --git a/app/routes/auth/sign-in.tsx b/app/routes/auth/sign-in.tsx index a4da7b5..4d605e9 100644 --- a/app/routes/auth/sign-in.tsx +++ b/app/routes/auth/sign-in.tsx @@ -1,14 +1,13 @@ import { getFormProps, getInputProps, useForm } from "@conform-to/react"; import { getZodConstraint, parseWithZod } from "@conform-to/zod"; +import { Trans, getI18n, useTranslation } from "react-i18next"; import { Form, Link, redirect, useNavigation } from "react-router"; import { toast } from "sonner"; - import { AuthLayout } from "~/components/auth-layout"; import { InputField, LoadingButton, PasswordField } from "~/components/forms"; import { Button } from "~/components/ui/button"; import { authClient } from "~/lib/auth/auth.client"; -import { SOCIAL_PROVIDER_CONFIGS } from "~/lib/config"; -import { AppInfo } from "~/lib/config"; +import { AppInfo, SOCIAL_PROVIDER_CONFIGS } from "~/lib/config"; import { signInSchema } from "~/lib/validations/auth"; import type { Route } from "./+types/sign-in"; @@ -17,11 +16,12 @@ export const meta: Route.MetaFunction = () => { }; export async function clientAction({ request }: Route.ClientActionArgs) { + const { t } = getI18n(); const formData = await request.clone().formData(); const submission = parseWithZod(formData, { schema: signInSchema }); if (submission.status !== "success") { - return toast.error("Invalid form data."); + return toast.error(t("errors.invalidData")); } switch (submission.value.provider) { @@ -42,19 +42,21 @@ export async function clientAction({ request }: Route.ClientActionArgs) { const { provider } = submission.value; const { error } = await authClient.signIn.social({ provider, - callbackURL: "/home", + callbackURL: "/dashboard", }); if (error) { - return toast.error(error.message || `${provider} sign in failed.`); + return toast.error( + error.message || t("errors.signInFailed", { provider }), + ); } break; } default: - return toast.error("Invalid login method."); + return toast.error(t("errors.invalidLoginMethod")); } - return redirect("/home"); + return redirect("/dashboard"); } export default function SignInRoute() { @@ -67,6 +69,7 @@ export default function SignInRoute() { }); const navigation = useNavigation(); + const { t } = useTranslation(); const isPending = (provider: string) => navigation.formData?.get("provider") === provider && navigation.state !== "idle"; @@ -74,13 +77,13 @@ export default function SignInRoute() { return ( {/* Sign in form */}
- Password + {t("user.password")} - Forgot your password? + {t("auth.forgotPasswordTitle")} ), @@ -114,32 +117,36 @@ export default function SignInRoute() { />
- Or continue with + {t("auth.signUpContinue")}
{/* Social login */} {SOCIAL_PROVIDER_CONFIGS.length > 0 && (
- {SOCIAL_PROVIDER_CONFIGS.map((config) => ( -
- + {SOCIAL_PROVIDER_CONFIGS.map(({ id, name, icon: Icon }) => ( + +
@@ -149,9 +156,9 @@ export default function SignInRoute() { {/* Sign up */}
- Don't have an account?{" "} + {t("auth.noAccount")}{" "} - Sign up + {t("auth.signUp")}
diff --git a/app/routes/auth/sign-up.tsx b/app/routes/auth/sign-up.tsx index 03a042a..956eaf4 100644 --- a/app/routes/auth/sign-up.tsx +++ b/app/routes/auth/sign-up.tsx @@ -3,6 +3,7 @@ import { getZodConstraint, parseWithZod } from "@conform-to/zod"; import { Form, Link, redirect } from "react-router"; import { toast } from "sonner"; +import { Trans, getI18n, useTranslation } from "react-i18next"; import { AuthLayout } from "~/components/auth-layout"; import { InputField, LoadingButton, PasswordField } from "~/components/forms"; import { useIsPending } from "~/hooks/use-is-pending"; @@ -16,6 +17,7 @@ export const meta: Route.MetaFunction = () => { }; export async function clientAction({ request }: Route.ClientActionArgs) { + const { t } = getI18n(); const formData = await request.formData(); const submission = parseWithZod(formData, { schema: signUpSchema }); @@ -24,17 +26,15 @@ export async function clientAction({ request }: Route.ClientActionArgs) { } const { error } = await authClient.signUp.email({ - callbackURL: "/home", + callbackURL: "/dashboard", ...submission.value, }); if (error) { - return toast.error(error.message || "An unexpected error occurred."); + return toast.error(error.message || t("errors.unexpected")); } - toast.success( - "Sign up successful! Please check your email for a verification link.", - ); + toast.success(t("auth.signingUpSuccess")); return redirect("/auth/sign-in"); } @@ -47,19 +47,20 @@ export default function SignUpRoute() { shouldRevalidate: "onInput", }); + const { t } = useTranslation(); const isPending = useIsPending({ formMethod: "POST", }); return ( {/* Sign up form */}
{/* Terms of service */} {/* Sign in */}
- Already have an account?{" "} + {t("auth.haveAccount")}{" "} - Sign in + {t("auth.signIn")}
diff --git a/app/routes/home.tsx b/app/routes/dashboard.tsx similarity index 65% rename from app/routes/home.tsx rename to app/routes/dashboard.tsx index f16102d..469677a 100644 --- a/app/routes/home.tsx +++ b/app/routes/dashboard.tsx @@ -1,9 +1,11 @@ import { ListTodoIcon, type LucideIcon, UserCogIcon } from "lucide-react"; -import { Link, href } from "react-router"; +import { Link, href, useLoaderData } from "react-router"; +import { useTranslation } from "react-i18next"; import { useAuthUser } from "~/hooks/use-auth-user"; import { AppInfo } from "~/lib/config"; -import type { Route } from "./+types/home"; +import { getInstance, getLocale } from "~/middlewares/i18next"; +import type { Route } from "./+types/dashboard"; type NavLink = { to: string; @@ -16,20 +18,34 @@ export const meta: Route.MetaFunction = () => { return [{ title: `Home - ${AppInfo.name}` }]; }; -export default function HomeRoute(_: Route.ComponentProps) { +export async function loader({ context }: Route.LoaderArgs) { + const { t } = getInstance(context); + const locale = getLocale(context); + const date = new Date().toLocaleDateString(locale, { + year: "numeric", + month: "2-digit", + day: "2-digit", + }); + return { date, title: t("title"), description: t("description") }; +} + +export default function DashboardRoute(_: Route.ComponentProps) { const { user } = useAuthUser(); + const { date } = useLoaderData(); + const { t } = useTranslation(); + const navLinks: NavLink[] = [ { to: href("/todos"), icon: ListTodoIcon, - label: "Todo List", - description: "Create and manage your todos", + label: t("dashboard.todo.label"), + description: t("dashboard.todo.description"), }, { to: href("/settings/account"), icon: UserCogIcon, - label: "Account Settings", - description: "Manage your account settings", + label: t("dashboard.account.label"), + description: t("dashboard.account.description"), }, ]; @@ -40,8 +56,7 @@ export default function HomeRoute(_: Route.ComponentProps) { 👋 Hi, {user.name}!

- Welcome to your dashboard. Here you can manage your todos and account - settings. + {t("dashboard.welcome")} {date}

diff --git a/app/routes/images.ts b/app/routes/images.ts index 644e9aa..4ec6be6 100644 --- a/app/routes/images.ts +++ b/app/routes/images.ts @@ -3,8 +3,8 @@ import type { Route } from "./+types/images"; export const loader = async ({ params, context }: Route.LoaderArgs) => { const key = params["*"]; - const _context = context.get(adapterContext); - const object = await _context.cloudflare.env.R2.get(key); + const { cloudflare } = context.get(adapterContext); + const object = await cloudflare.env.R2.get(key); if (!object) { return new Response(null, { status: 404 }); } diff --git a/app/routes/index.tsx b/app/routes/index.tsx index 56adb43..c2de9b7 100644 --- a/app/routes/index.tsx +++ b/app/routes/index.tsx @@ -1,9 +1,11 @@ import { ArrowRightIcon } from "lucide-react"; import { Link, href } from "react-router"; +import { Trans, useTranslation } from "react-i18next"; import { AppLogo } from "~/components/app-logo"; import { ColorSchemeToggle } from "~/components/color-scheme-toggle"; import { GithubIcon } from "~/components/icons"; +import { LangSwitcher } from "~/components/lang/lang-switcher"; import { Button, buttonVariants } from "~/components/ui/button"; import { AppInfo } from "~/lib/config"; import { cn } from "~/lib/utils"; @@ -13,10 +15,13 @@ export const meta: Route.MetaFunction = () => { return [{ title: AppInfo.name }]; }; -export default function HomeRoute() { +export default function DashboardRoute() { + const { t } = useTranslation(); + return (
-
+
+
@@ -24,11 +29,11 @@ export default function HomeRoute() {
- React Router v7
with Better auth. + ]} />

- {AppInfo.description} + {t("description")}

@@ -38,14 +43,14 @@ export default function HomeRoute() { reloadDocument > - Star on Github + {t("home.star")} - Get Started + {t("home.start")}
diff --git a/app/routes/layout.tsx b/app/routes/layout.tsx index 95d647c..cc43afe 100644 --- a/app/routes/layout.tsx +++ b/app/routes/layout.tsx @@ -1,12 +1,12 @@ import { CircleFadingPlusIcon } from "lucide-react"; import { Link, Outlet, data, href } from "react-router"; - import { AppLogo } from "~/components/app-logo"; import { ColorSchemeToggle } from "~/components/color-scheme-toggle"; +import { LangSwitcher } from "~/components/lang/lang-switcher"; import { Button } from "~/components/ui/button"; import { UserNav } from "~/components/user-nav"; import { authSessionContext } from "~/lib/contexts"; -import { authMiddleware } from "~/lib/middlewares/auth-guard.server"; +import { authMiddleware } from "~/middlewares/auth-guard.server"; import type { Route } from "./+types/layout"; export const unstable_middleware = [authMiddleware]; @@ -21,7 +21,7 @@ export default function AuthenticatedLayout(_: Route.ComponentProps) { <>
- +
@@ -30,6 +30,7 @@ export default function AuthenticatedLayout(_: Route.ComponentProps) { +
diff --git a/app/routes/not-found.tsx b/app/routes/not-found.tsx index cd61edf..2a71b02 100644 --- a/app/routes/not-found.tsx +++ b/app/routes/not-found.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from "react-i18next"; import { ProductionErrorDisplay } from "~/components/error-boundary"; import { AppInfo } from "~/lib/config"; import type { Route } from "./+types/not-found"; @@ -15,10 +16,12 @@ export default function NotFound() { } export function ErrorBoundary() { + const { t } = useTranslation(); + return ( ); } diff --git a/app/routes/settings/account.tsx b/app/routes/settings/account.tsx index ef60012..230f576 100644 --- a/app/routes/settings/account.tsx +++ b/app/routes/settings/account.tsx @@ -1,6 +1,7 @@ import { parseWithZod } from "@conform-to/zod"; import { dataWithError, dataWithSuccess } from "remix-toast"; +import { useTranslation } from "react-i18next"; import AvatarCropper from "~/components/avatar-cropper"; import { DeleteAccount, SignOut } from "~/components/settings/account-action"; import { SettingRow } from "~/components/settings/setting-row"; @@ -11,6 +12,7 @@ import { AppInfo } from "~/lib/config"; import { adapterContext, authSessionContext } from "~/lib/contexts"; import { getAvatarUrl } from "~/lib/utils"; import { accountSchema } from "~/lib/validations/settings"; +import { getInstance } from "~/middlewares/i18next"; import type { Route } from "./+types/account"; export const meta: Route.MetaFunction = () => { @@ -18,12 +20,13 @@ export const meta: Route.MetaFunction = () => { }; export async function action({ request, context }: Route.ActionArgs) { + const { t } = getInstance(context); try { const formData = await request.clone().formData(); const submission = parseWithZod(formData, { schema: accountSchema }); if (submission.status !== "success") { - return dataWithError(null, "Invalid form data."); + return dataWithError(null, t("errors.invalidData")); } const auth = serverAuth(); @@ -39,23 +42,23 @@ export async function action({ request, context }: Route.ActionArgs) { auth.api.revokeSessions({ headers }), auth.api.deleteUser({ body: {}, asResponse: false, headers }), ]); - message = "Account deleted."; + message = t("account.deleted"); break; case "delete-avatar": { if (!user.image) { - return dataWithError(null, "No avatar to delete."); + return dataWithError(null, t("account.noAvatar")); } await Promise.all([ deleteUserImageFromR2(user.image), auth.api.updateUser({ - body: { image: null }, + body: { image: undefined }, asResponse: false, headers, }), ]); - message = "Avatar deleted."; + message = t("account.avatarDeleted"); break; } @@ -76,30 +79,31 @@ export async function action({ request, context }: Route.ActionArgs) { headers, }), ]); - message = "Avatar updated."; + message = t("account.avatarUpdated"); break; } default: - return dataWithError(null, "Invalid intent."); + return dataWithError(null, t("errors.invalidIntent")); } return dataWithSuccess(null, message); } catch (error) { console.error("Account action error:", error); - return dataWithError(null, "An unexpected error occurred."); + return dataWithError(null, t("errors.unexpected")); } } export default function AccountRoute() { + const { t } = useTranslation(); const { user } = useAuthUser(); const { avatarUrl, placeholderUrl } = getAvatarUrl(user.image, user.name); return ( - + } /> } /> diff --git a/app/routes/settings/appearance.tsx b/app/routes/settings/appearance.tsx index e38bd36..e5fe8c1 100644 --- a/app/routes/settings/appearance.tsx +++ b/app/routes/settings/appearance.tsx @@ -1,5 +1,6 @@ import { CheckIcon, MinusIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; import { SettingsLayout } from "~/components/settings/settings-layout"; import { RadioGroup, RadioGroupItem } from "~/components/ui/radio-group"; import { @@ -27,11 +28,12 @@ export const meta: Route.MetaFunction = () => { export default function AppearanceRoute() { const setColorScheme = useSetColorScheme(); const colorScheme = useColorScheme(); + const { t } = useTranslation(); return ( { const account = accounts.find((acc) => acc.provider === config.id); return { @@ -37,8 +39,8 @@ export default function ConnectionsRoute({ return (
diff --git a/app/routes/settings/password.tsx b/app/routes/settings/password.tsx index b0f84b5..12774ed 100644 --- a/app/routes/settings/password.tsx +++ b/app/routes/settings/password.tsx @@ -1,7 +1,7 @@ import { parseWithZod } from "@conform-to/zod"; +import { getI18n, useTranslation } from "react-i18next"; import { Link, href } from "react-router"; import { toast } from "sonner"; - import { ChangePassword } from "~/components/settings/password-action"; import { SettingRow } from "~/components/settings/setting-row"; import { SettingsLayout } from "~/components/settings/settings-layout"; @@ -17,6 +17,8 @@ export const meta: Route.MetaFunction = () => { }; export async function clientAction({ request }: Route.ClientActionArgs) { + const { t } = getI18n(); + const formData = await request.formData(); const submission = parseWithZod(formData, { schema: changePasswordSchema }); @@ -31,32 +33,34 @@ export async function clientAction({ request }: Route.ClientActionArgs) { }); if (result.error) { - toast.error(result.error.message || "An unexpected error occurred."); + toast.error(result.error.message || t("errors.unexpected")); return { status: "error" }; } - toast.success("Password changed successfully! Other sessions revoked."); + toast.success(t("password.change.success")); return { status: "success" }; } export default function ChangePasswordRoute() { + const { t } = useTranslation(); + return ( - + } /> - Reset password ↗ + {t("password.reset.title")} ↗ } /> diff --git a/app/routes/settings/sessions.tsx b/app/routes/settings/sessions.tsx index 96269f0..19a2a1b 100644 --- a/app/routes/settings/sessions.tsx +++ b/app/routes/settings/sessions.tsx @@ -2,6 +2,7 @@ import { Suspense } from "react"; import { Await, data, useNavigate } from "react-router"; import { toast } from "sonner"; +import { getI18n, useTranslation } from "react-i18next"; import { SignOutOfOtherSessions } from "~/components/settings/session-action"; import { SessionItem } from "~/components/settings/session-item"; import { SettingsLayout } from "~/components/settings/settings-layout"; @@ -24,25 +25,27 @@ export async function loader({ request }: Route.LoaderArgs) { } export async function clientAction(_: Route.ClientActionArgs) { - const { error } = await authClient.revokeOtherSessions(); + const { t } = getI18n(); + const { error } = await authClient.revokeOtherSessions(); if (error) { - toast.error(error.message || "An unexpected error occurred."); + toast.error(error.message || t("errors.unexpected")); return { status: "error" }; } - toast.success("Other sessions signed out successfully."); + toast.success(t("sessions.otherSignedOut")); return { status: "success" }; } export default function SessionsRoute({ loaderData }: Route.ComponentProps) { + const { t } = useTranslation(); const { session } = useAuthUser(); const navigate = useNavigate(); return (
-

Error loading sessions.

+

{t("errors.loadingSessions")}

} @@ -80,7 +83,7 @@ export default function SessionsRoute({ loaderData }: Route.ComponentProps) {
{resolvedSessions.length === 0 ? ( -
No sessions found.
+
{t("sessions.noSessions")}
) : ( resolvedSessions.map((item) => (
-

Todo List

+

{t("todo.title")}

- Today is {formatDate(new Date(), "MMMM d, yyyy")} + {t("todo.today")} {formatDate(new Date(), "MMMM d, yyyy")}
@@ -124,7 +125,7 @@ export default function TodosRoute({
{todos.length === 0 ? ( -

No todos found

+

{t("todo.noFound")}

) : (
    {todos.map((todo: SelectTodo) => ( diff --git a/package.json b/package.json index 65578a5..803a0c3 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ "db:drop": "drizzle-kit drop", "db:generate": "drizzle-kit generate", "db:apply": "wrangler d1 migrations apply DB --local", - "db:apply-prod": "wrangler d1 migrations apply DB --remote" + "db:apply-prod": "wrangler d1 migrations apply DB --preview --remote" }, "dependencies": { - "@conform-to/react": "^1.5.0", - "@conform-to/zod": "^1.5.0", + "@conform-to/react": "^1.6.0", + "@conform-to/zod": "^1.6.0", "@origin-space/image-cropper": "^0.1.9", "@radix-ui/react-alert-dialog": "^1.1.13", "@radix-ui/react-avatar": "^1.1.9", @@ -35,40 +35,44 @@ "@radix-ui/react-slot": "^1.2.2", "@radix-ui/react-tooltip": "^1.2.6", "@react-router/cloudflare": "^7.6.0", - "better-auth": "^1.2.7", + "better-auth": "^1.2.8", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "date-fns": "^4.1.0", - "drizzle-orm": "~0.43.1", + "drizzle-orm": "^0.43.1", + "i18next": "^25.2.0", + "i18next-browser-languagedetector": "^8.1.0", "isbot": "^5.1.28", - "lucide-react": "^0.510.0", + "lucide-react": "^0.511.0", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-i18next": "^15.5.1", "react-router": "^7.6.0", "remix-toast": "^3.1.0", "sonner": "^2.0.3", "spin-delay": "^2.0.1", - "tailwind-merge": "^3.2.0", + "tailwind-merge": "^3.3.0", "tailwindcss-animate": "^1.0.7", - "zod": "^3.24.4" + "zod": "^3.25.7", + "zod-i18n-map": "^2.27.0" }, "devDependencies": { - "@biomejs/biome": "1.9.4", - "@cloudflare/vite-plugin": "^1.1.1", - "@cloudflare/workers-types": "^4.20250510.0", + "@biomejs/biome": "^1.9.4", + "@cloudflare/vite-plugin": "^1.2.3", + "@cloudflare/workers-types": "^4.20250520.0", "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", "@react-router/dev": "^7.6.0", "@tailwindcss/vite": "^4.1.7", - "@types/node": "^22.15.17", - "@types/react": "^19.1.3", - "@types/react-dom": "^19.1.4", - "drizzle-kit": "~0.31.1", - "lefthook": "^1.11.12", - "tailwindcss": "^4.1.5", + "@types/node": "^22.15.19", + "@types/react": "^19.1.4", + "@types/react-dom": "^19.1.5", + "drizzle-kit": "^0.31.1", + "lefthook": "^1.11.13", + "tailwindcss": "^4.1.7", "typescript": "^5.8.3", "vite": "^6.3.5", "vite-tsconfig-paths": "^5.1.4", - "wrangler": "^4.14.4" + "wrangler": "^4.16.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b599c2..f9d2e74 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,53 +9,53 @@ importers: .: dependencies: '@conform-to/react': - specifier: ^1.5.0 - version: 1.5.0(react@19.1.0) + specifier: ^1.6.0 + version: 1.6.0(react@19.1.0) '@conform-to/zod': - specifier: ^1.5.0 - version: 1.5.0(zod@3.24.4) + specifier: ^1.6.0 + version: 1.6.0(zod@3.25.7) '@origin-space/image-cropper': specifier: ^0.1.9 version: 0.1.9(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-alert-dialog': specifier: ^1.1.13 - version: 1.1.13(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-avatar': specifier: ^1.1.9 - version: 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-checkbox': specifier: ^1.3.1 - version: 1.3.1(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.3.1(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-dialog': specifier: ^1.1.13 - version: 1.1.13(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-dropdown-menu': specifier: ^2.1.14 - version: 2.1.14(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-label': specifier: ^2.1.6 - version: 2.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-radio-group': specifier: ^1.3.6 - version: 1.3.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.3.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-select': specifier: ^2.2.4 - version: 2.2.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 2.2.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slider': specifier: ^1.3.4 - version: 1.3.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.3.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@radix-ui/react-slot': specifier: ^1.2.2 - version: 1.2.2(@types/react@19.1.3)(react@19.1.0) + version: 1.2.2(@types/react@19.1.4)(react@19.1.0) '@radix-ui/react-tooltip': specifier: ^1.2.6 - version: 1.2.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + version: 1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@react-router/cloudflare': specifier: ^7.6.0 - version: 7.6.0(@cloudflare/workers-types@4.20250510.0)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(tsup@8.4.0(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3))(typescript@5.8.3) + version: 7.6.0(@cloudflare/workers-types@4.20250520.0)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(tsup@8.4.0(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3))(typescript@5.8.3) better-auth: - specifier: ^1.2.7 - version: 1.2.7 + specifier: ^1.2.8 + version: 1.2.8 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 @@ -66,20 +66,29 @@ importers: specifier: ^4.1.0 version: 4.1.0 drizzle-orm: - specifier: ~0.43.1 - version: 0.43.1(@cloudflare/workers-types@4.20250510.0)(gel@2.1.0)(kysely@0.27.6) + specifier: ^0.43.1 + version: 0.43.1(@cloudflare/workers-types@4.20250520.0)(gel@2.1.0)(kysely@0.28.2) + i18next: + specifier: ^25.2.0 + version: 25.2.0(typescript@5.8.3) + i18next-browser-languagedetector: + specifier: ^8.1.0 + version: 8.1.0 isbot: specifier: ^5.1.28 version: 5.1.28 lucide-react: - specifier: ^0.510.0 - version: 0.510.0(react@19.1.0) + specifier: ^0.511.0 + version: 0.511.0(react@19.1.0) react: specifier: ^19.1.0 version: 19.1.0 react-dom: specifier: ^19.1.0 version: 19.1.0(react@19.1.0) + react-i18next: + specifier: ^15.5.1 + version: 15.5.1(i18next@25.2.0(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3) react-router: specifier: ^7.6.0 version: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -93,66 +102,69 @@ importers: specifier: ^2.0.1 version: 2.0.1(react@19.1.0) tailwind-merge: - specifier: ^3.2.0 - version: 3.2.0 + specifier: ^3.3.0 + version: 3.3.0 tailwindcss-animate: specifier: ^1.0.7 - version: 1.0.7(tailwindcss@4.1.5) + version: 1.0.7(tailwindcss@4.1.7) zod: - specifier: ^3.24.4 - version: 3.24.4 + specifier: ^3.25.7 + version: 3.25.7 + zod-i18n-map: + specifier: ^2.27.0 + version: 2.27.0(i18next@25.2.0(typescript@5.8.3))(zod@3.25.7) devDependencies: '@biomejs/biome': - specifier: 1.9.4 + specifier: ^1.9.4 version: 1.9.4 '@cloudflare/vite-plugin': - specifier: ^1.1.1 - version: 1.1.1(rollup@4.41.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1))(workerd@1.20250507.0)(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0)) + specifier: ^1.2.3 + version: 1.2.3(rollup@4.41.0)(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1))(workerd@1.20250508.0)(wrangler@4.16.0(@cloudflare/workers-types@4.20250520.0)) '@cloudflare/workers-types': - specifier: ^4.20250510.0 - version: 4.20250510.0 + specifier: ^4.20250520.0 + version: 4.20250520.0 '@commitlint/cli': specifier: ^19.8.1 - version: 19.8.1(@types/node@22.15.17)(typescript@5.8.3) + version: 19.8.1(@types/node@22.15.19)(typescript@5.8.3) '@commitlint/config-conventional': specifier: ^19.8.1 version: 19.8.1 '@react-router/dev': specifier: ^7.6.0 - version: 7.6.0(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1))(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0)) + version: 7.6.0(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1))(wrangler@4.16.0(@cloudflare/workers-types@4.20250520.0)) '@tailwindcss/vite': specifier: ^4.1.7 - version: 4.1.7(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1)) + version: 4.1.7(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1)) '@types/node': - specifier: ^22.15.17 - version: 22.15.17 + specifier: ^22.15.19 + version: 22.15.19 '@types/react': - specifier: ^19.1.3 - version: 19.1.3 - '@types/react-dom': specifier: ^19.1.4 - version: 19.1.4(@types/react@19.1.3) + version: 19.1.4 + '@types/react-dom': + specifier: ^19.1.5 + version: 19.1.5(@types/react@19.1.4) drizzle-kit: - specifier: ~0.31.1 + specifier: ^0.31.1 version: 0.31.1 lefthook: - specifier: ^1.11.12 - version: 1.11.12 + specifier: ^1.11.13 + version: 1.11.13 tailwindcss: - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^4.1.7 + version: 4.1.7 typescript: specifier: ^5.8.3 version: 5.8.3 vite: specifier: ^6.3.5 - version: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) + version: 6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1)) + version: 5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1)) wrangler: - specifier: ^4.14.4 - version: 4.14.4(@cloudflare/workers-types@4.20250510.0) + specifier: ^4.16.0 + version: 4.16.0(@cloudflare/workers-types@4.20250520.0) packages: @@ -279,6 +291,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.27.1': + resolution: {integrity: sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -291,8 +307,8 @@ packages: resolution: {integrity: sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==} engines: {node: '>=6.9.0'} - '@better-auth/utils@0.2.4': - resolution: {integrity: sha512-ayiX87Xd5sCHEplAdeMgwkA0FgnXsEZBgDn890XHHwSWNqqRZDYOq3uj2Ei2leTv1I2KbG5HHn60Ah1i2JWZjQ==} + '@better-auth/utils@0.2.5': + resolution: {integrity: sha512-uI2+/8h/zVsH8RrYdG8eUErbuGBk16rZKQfz8CjxQOyCE6v7BqFYEbFwvOkvl1KbUdxhqOnXp78+uE5h8qVEgQ==} '@better-fetch/fetch@1.1.18': resolution: {integrity: sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==} @@ -354,53 +370,53 @@ packages: resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} engines: {node: '>=18.0.0'} - '@cloudflare/unenv-preset@2.3.1': - resolution: {integrity: sha512-Xq57Qd+ADpt6hibcVBO0uLG9zzRgyRhfCUgBT9s+g3+3Ivg5zDyVgLFy40ES1VdNcu8rPNSivm9A+kGP5IVaPg==} + '@cloudflare/unenv-preset@2.3.2': + resolution: {integrity: sha512-MtUgNl+QkQyhQvv5bbWP+BpBC1N0me4CHHuP2H4ktmOMKdB/6kkz/lo+zqiA4mEazb4y+1cwyNjVrQ2DWeE4mg==} peerDependencies: - unenv: 2.0.0-rc.15 - workerd: ^1.20250320.0 + unenv: 2.0.0-rc.17 + workerd: ^1.20250508.0 peerDependenciesMeta: workerd: optional: true - '@cloudflare/vite-plugin@1.1.1': - resolution: {integrity: sha512-ZzLtAiN/XMxsOKrjF3S7VdKrj3fRMF7wZHUNUjbaZXnW9MSPgndp//edjYl4nzIkX0ZDeAG/iWzAhW1AFsw5HQ==} + '@cloudflare/vite-plugin@1.2.3': + resolution: {integrity: sha512-fMrcylP2i4fVwbvEj+LbPU+DnZUgswXnzCtkk8b4mp7q4JbDL57YkhSSpkLtOQoPQYsjUspQhSna97h/cuoX5w==} peerDependencies: vite: ^6.1.0 wrangler: ^3.101.0 || ^4.0.0 - '@cloudflare/workerd-darwin-64@1.20250507.0': - resolution: {integrity: sha512-xC+8hmQuOUUNCVT9DWpLMfxhR4Xs4kI8v7Bkybh4pzGC85moH6fMfCBNaP0YQCNAA/BR56aL/AwfvMVGskTK/A==} + '@cloudflare/workerd-darwin-64@1.20250508.0': + resolution: {integrity: sha512-9x09MrA9Y5RQs3zqWvWns8xHgM2pVNXWpeJ+3hQYu4PrwPFZXtTD6b/iMmOnlYKzINlREq1RGeEybMFyWEUlUg==} engines: {node: '>=16'} cpu: [x64] os: [darwin] - '@cloudflare/workerd-darwin-arm64@1.20250507.0': - resolution: {integrity: sha512-Oynff5H8yM4trfUFaKdkOvPV3jac8mg7QC19ILZluCVgLx/JGEVLEJ7do1Na9rLqV8CK4gmUXPrUMX7uerhQgg==} + '@cloudflare/workerd-darwin-arm64@1.20250508.0': + resolution: {integrity: sha512-0Ili+nE2LLRzYue/yPc1pepSyNNg6LxR3/ng/rlQzVQUxPXIXldHFkJ/ynsYwQnAcf6OxasSi/kbTm6yvDoSAQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] - '@cloudflare/workerd-linux-64@1.20250507.0': - resolution: {integrity: sha512-/HAA+Zg/R7Q/Smyl835FUFKjotZN1UzN9j/BHBd0xKmKov97QkXAX8gsyGnyKqRReIOinp8x/8+UebTICR7VJw==} + '@cloudflare/workerd-linux-64@1.20250508.0': + resolution: {integrity: sha512-5saVrZ3uVwYxvBa7BaonXjeqB6X0YF3ak05qvBaWcmZ3FNmnarMm2W8842cnbhnckDVBpB/iDo51Sy6Y7y1jcw==} engines: {node: '>=16'} cpu: [x64] os: [linux] - '@cloudflare/workerd-linux-arm64@1.20250507.0': - resolution: {integrity: sha512-NMPibSdOYeycU0IrKkgOESFJQy7dEpHvuatZxQxlT+mIQK0INzI3irp2kKxhF99s25kPC4p+xg9bU3ugTrs3VQ==} + '@cloudflare/workerd-linux-arm64@1.20250508.0': + resolution: {integrity: sha512-muQe1pkxRi3eaq1Q417xvfGd2SlktbLTzNhT5Yftsx8OecWrYuB8i4ttR6Nr5ER06bfEj0FqQjqJJhcp6wLLUQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] - '@cloudflare/workerd-windows-64@1.20250507.0': - resolution: {integrity: sha512-c91fhNP8ufycdIDqjVyKTqeb4ewkbAYXFQbLreMVgh4LLQQPDDEte8wCdmaFy5bIL0M9d85PpdCq51RCzq/FaQ==} + '@cloudflare/workerd-windows-64@1.20250508.0': + resolution: {integrity: sha512-EJj8iTWFMqjgvZUxxNvzK7frA1JMFi3y/9eDIdZPL/OaQh3cmk5Lai5DCXsKYUxfooMBZWYTp53zOLrvuJI8VQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] - '@cloudflare/workers-types@4.20250510.0': - resolution: {integrity: sha512-VLdSYUooX2QhdlzyBnnLAqa5B3xWyr5vdvya9NZk2BJNmRt2iblSLunj7iBKiW9J+SIBHz7c+kUzUJKoFLKRjg==} + '@cloudflare/workers-types@4.20250520.0': + resolution: {integrity: sha512-bMPrpZREctlSaKtqIp3mdRjgyRSgioPQDUlhOeCUYRIo9DzWUACvw/u5kq3GQMmE4V1/nVCGHb7a1Ie8f5wG5g==} '@commitlint/cli@19.8.1': resolution: {integrity: sha512-LXUdNIkspyxrlV6VDHWBmCZRtkEVRpBKxi2Gtw3J54cGWhLCTouVD/Q6ZSaSvd2YaDObWK8mDjrz3TIKtaQMAA==} @@ -471,16 +487,16 @@ packages: resolution: {integrity: sha512-/yCrWGCoA1SVKOks25EGadP9Pnj0oAIHGpl2wH2M2Y46dPM2ueb8wyCVOD7O3WCTkaJ0IkKvzhl1JY7+uCT2Dw==} engines: {node: '>=v18'} - '@conform-to/dom@1.5.0': - resolution: {integrity: sha512-7cbIjD3SZzidTzQTLqDhcu2FtkB1l/ZwPlv/mlZgBiezyHd//gBoauGygemcOToEqHahRYFLYwovmKqdjTMARA==} + '@conform-to/dom@1.6.0': + resolution: {integrity: sha512-+eww0JbVsZ4W07yLiJHD5j7JnTztjJPw5Z1dRtSRxmFP4quy9Tuc5RRevghT3wgxbbg0Z1v3sxSOutW3TgLTFQ==} - '@conform-to/react@1.5.0': - resolution: {integrity: sha512-j6fq1UTJ8rLxT4hMZRj9Qyi1lYrALsuno3024/nORYjmqThm2K7wsB1Aaox67SxcR5p4fpva4d8pOkzOSBYN2g==} + '@conform-to/react@1.6.0': + resolution: {integrity: sha512-ZPqlBnrauU+IczG8EZCT7Rn3ecGZFww8axmOb6GIM8uDZ7UkPlnFc3zgFKbqsThD31M8hr2BdwSxQ0yKIqxNXw==} peerDependencies: react: '>=18' - '@conform-to/zod@1.5.0': - resolution: {integrity: sha512-bk+S0sFSfyVL7UVbHAjComnGq4p4vGMtfyyxFB8116XTnxQVyk88dXhj/ApxPQTktWn+OukDWyz5TQ92t/qo+A==} + '@conform-to/zod@1.6.0': + resolution: {integrity: sha512-NF9OqarwTYGCwj6yTXpGUa/h10WsiO8njSp+WXAnKhMJDZmwweNlSHX0OGZ9tHkiIARWyzP1sxQB9OIF0lAL5A==} peerDependencies: zod: ^3.21.0 @@ -803,22 +819,6 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} - '@hattip/adapter-node@0.0.49': - resolution: {integrity: sha512-BE+Y8Q4U0YcH34FZUYU4DssGKOaZLbNL0zK57Z41UZp0m9kS79ZIolBmjjpPhTVpIlRY3Rs+uhXbVXKk7mUcJA==} - - '@hattip/core@0.0.49': - resolution: {integrity: sha512-3/ZJtC17cv8m6Sph8+nw4exUp9yhEf2Shi7HK6AHSUSBtaaQXZ9rJBVxTfZj3PGNOR/P49UBXOym/52WYKFTJQ==} - - '@hattip/headers@0.0.49': - resolution: {integrity: sha512-rrB2lEhTf0+MNVt5WdW184Ky706F1Ze9Aazn/R8c+/FMUYF9yjem2CgXp49csPt3dALsecrnAUOHFiV0LrrHXA==} - - '@hattip/polyfills@0.0.49': - resolution: {integrity: sha512-5g7W5s6Gq+HDxwULGFQ861yAnEx3yd9V8GDwS96HBZ1nM1u93vN+KTuwXvNsV7Z3FJmCrD/pgU8WakvchclYuA==} - - '@hattip/walk@0.0.49': - resolution: {integrity: sha512-AgJgKLooZyQnzMfoFg5Mo/aHM+HGBC9ExpXIjNqGimYTRgNbL/K7X5EM1kR2JY90BNKk9lo6Usq1T/nWFdT7TQ==} - hasBin: true - '@hexagon/base64@1.1.28': resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==} @@ -956,15 +956,15 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - '@kamilkisiela/fast-url-parser@1.1.4': - resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} - '@levischuck/tiny-cbor@0.2.11': resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==} '@mjackson/node-fetch-server@0.2.0': resolution: {integrity: sha512-EMlH1e30yzmTpGLQjlFmaDAjyOeZhng1/XCd7DExR8PNAnG/G1tyruZxEoUe11ClnwGhGrtsdnyyUx1frSzjng==} + '@mjackson/node-fetch-server@0.6.1': + resolution: {integrity: sha512-9ZJnk/DJjt805uv5PPv11haJIW+HHf3YEEyVXv+8iLQxLD/iXA68FH220XoiTPBC4gCg5q+IMadDw8qPqlA5wg==} + '@noble/ciphers@0.6.0': resolution: {integrity: sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==} @@ -1487,201 +1487,101 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.40.2': - resolution: {integrity: sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==} - cpu: [arm] - os: [android] - '@rollup/rollup-android-arm-eabi@4.41.0': resolution: {integrity: sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.40.2': - resolution: {integrity: sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==} - cpu: [arm64] - os: [android] - '@rollup/rollup-android-arm64@4.41.0': resolution: {integrity: sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.40.2': - resolution: {integrity: sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==} - cpu: [arm64] - os: [darwin] - '@rollup/rollup-darwin-arm64@4.41.0': resolution: {integrity: sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.40.2': - resolution: {integrity: sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==} - cpu: [x64] - os: [darwin] - '@rollup/rollup-darwin-x64@4.41.0': resolution: {integrity: sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.40.2': - resolution: {integrity: sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==} - cpu: [arm64] - os: [freebsd] - '@rollup/rollup-freebsd-arm64@4.41.0': resolution: {integrity: sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.40.2': - resolution: {integrity: sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==} - cpu: [x64] - os: [freebsd] - '@rollup/rollup-freebsd-x64@4.41.0': resolution: {integrity: sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.40.2': - resolution: {integrity: sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==} - cpu: [arm] - os: [linux] - '@rollup/rollup-linux-arm-gnueabihf@4.41.0': resolution: {integrity: sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.40.2': - resolution: {integrity: sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==} - cpu: [arm] - os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.41.0': resolution: {integrity: sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.40.2': - resolution: {integrity: sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==} - cpu: [arm64] - os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.41.0': resolution: {integrity: sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.40.2': - resolution: {integrity: sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==} - cpu: [arm64] - os: [linux] - '@rollup/rollup-linux-arm64-musl@4.41.0': resolution: {integrity: sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.40.2': - resolution: {integrity: sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==} - cpu: [loong64] - os: [linux] - '@rollup/rollup-linux-loongarch64-gnu@4.41.0': resolution: {integrity: sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': - resolution: {integrity: sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==} - cpu: [ppc64] - os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.41.0': resolution: {integrity: sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.40.2': - resolution: {integrity: sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==} - cpu: [riscv64] - os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.41.0': resolution: {integrity: sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.40.2': - resolution: {integrity: sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==} - cpu: [riscv64] - os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.41.0': resolution: {integrity: sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.40.2': - resolution: {integrity: sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==} - cpu: [s390x] - os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.41.0': resolution: {integrity: sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.40.2': - resolution: {integrity: sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==} - cpu: [x64] - os: [linux] - '@rollup/rollup-linux-x64-gnu@4.41.0': resolution: {integrity: sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.40.2': - resolution: {integrity: sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==} - cpu: [x64] - os: [linux] - '@rollup/rollup-linux-x64-musl@4.41.0': resolution: {integrity: sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.40.2': - resolution: {integrity: sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==} - cpu: [arm64] - os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.41.0': resolution: {integrity: sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.40.2': - resolution: {integrity: sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==} - cpu: [ia32] - os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.41.0': resolution: {integrity: sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.40.2': - resolution: {integrity: sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==} - cpu: [x64] - os: [win32] - '@rollup/rollup-win32-x64-msvc@4.41.0': resolution: {integrity: sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==} cpu: [x64] @@ -1790,24 +1690,16 @@ packages: '@types/estree@1.0.7': resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==} - '@types/node@22.15.17': - resolution: {integrity: sha512-wIX2aSZL5FE+MR0JlvF87BNVrtFWf6AE6rxSE9X7OwnVvoyCQjpzSRJ+M87se/4QCkCiebQAqrJ0y6fwIyi7nw==} + '@types/node@22.15.19': + resolution: {integrity: sha512-3vMNr4TzNQyjHcRZadojpRaD9Ofr6LsonZAoQ+HMUa/9ORTPoxVIw0e0mpqWpdjj8xybyCM+oKOUH2vwFu/oEw==} - '@types/react-dom@19.1.4': - resolution: {integrity: sha512-WxYAszDYgsMV31OVyoG4jbAgJI1Gw0Xq9V19zwhy6+hUUJlJIdZ3r/cbdmTqFv++SktQkZ/X+46yGFxp5XJBEg==} + '@types/react-dom@19.1.5': + resolution: {integrity: sha512-CMCjrWucUBZvohgZxkjd6S9h0nZxXjzus6yDfUb+xLxYM7VvjKNH1tQrE9GWLql1XoOP4/Ds3bwFqShHUYraGg==} peerDependencies: '@types/react': ^19.0.0 - '@types/react@19.1.3': - resolution: {integrity: sha512-dLWQ+Z0CkIvK1J8+wrDPwGxEYFA4RAyHoZPxHVGspYmFVnwGSNT24cGIhFJrtfRnWVuW8X7NO52gCXmhkVUWGQ==} - - '@whatwg-node/fetch@0.9.23': - resolution: {integrity: sha512-7xlqWel9JsmxahJnYVUj/LLxWcnA93DR4c9xlw3U814jWTiYalryiH1qToik1hOxweKKRLi4haXHM5ycRksPBA==} - engines: {node: '>=18.0.0'} - - '@whatwg-node/node-fetch@0.6.0': - resolution: {integrity: sha512-tcZAhrpx6oVlkEsRngeTEEE7I5/QdLjeEz4IlekabGaESP7+Dkm/6a9KcF1KdCBB7mO9PXtBkwCuTCt8+UPg8Q==} - engines: {node: '>=18.0.0'} + '@types/react@19.1.4': + resolution: {integrity: sha512-EB1yiiYdvySuIITtD5lhW4yPyJ31RkJkkDw794LaQYrxCSaQV/47y5o1FMC4zF9ZyjUjzJMZwbovEnT5yHTW6g==} JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} @@ -1850,8 +1742,8 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - aria-hidden@1.2.4: - resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} array-ify@1.0.0: @@ -1870,8 +1762,8 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - better-auth@1.2.7: - resolution: {integrity: sha512-2hCB263GSrgetsMUZw8vv9O1e4S4AlYJW3P4e8bX9u3Q3idv4u9BzDFCblpTLuL4YjYovghMCN0vurAsctXOAQ==} + better-auth@1.2.8: + resolution: {integrity: sha512-y8ry7ZW3/3ZIr82Eo1zUDtMzdoQlFnwNuZ0+b0RxoNZgqmvgTIc/0tCDC7NDJerqSu4UCzer0dvYxBsv3WMIGg==} better-call@1.0.9: resolution: {integrity: sha512-Qfm0gjk0XQz0oI7qvTK1hbqTsBY4xV2hsHAxF8LZfUYl3RaECCIifXuVqtPpZJWvlCCMlQSvkvhhyuApGUba6g==} @@ -1896,10 +1788,6 @@ packages: peerDependencies: esbuild: '>=0.18' - busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -1908,8 +1796,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001717: - resolution: {integrity: sha512-auPpttCq6BDEG8ZAuHJIplGw6GODhjw+/11e7IjpnYCxZcW/ONgPs0KVBJ0d1bY3e2+7PRe5RCLyP+PfwVgkYw==} + caniuse-lite@1.0.30001718: + resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==} chalk@5.4.1: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} @@ -2017,15 +1905,6 @@ packages: date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} - debug@4.4.0: - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -2153,8 +2032,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.151: - resolution: {integrity: sha512-Rl6uugut2l9sLojjS4H4SAr3A4IgACMLgpuEMPYCVcKydzfyPrn5absNRju38IhQOf/NwjJY8OGWjlteqYeBCA==} + electron-to-chromium@1.5.155: + resolution: {integrity: sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2212,15 +2091,9 @@ packages: exsolve@1.0.5: resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==} - fast-decode-uri-component@1.0.1: - resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-querystring@1.1.2: - resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} - fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} @@ -2313,6 +2186,20 @@ packages: resolution: {integrity: sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + html-parse-stringify@3.0.1: + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + + i18next-browser-languagedetector@8.1.0: + resolution: {integrity: sha512-mHZxNx1Lq09xt5kCauZ/4bsXOEA2pfpwSoU11/QTJB+pD94iONFwp+ohqi///PwiFvjFOxe1akYCdHyFo1ng5Q==} + + i18next@25.2.0: + resolution: {integrity: sha512-ERhJICsxkw1vE7G0lhCUYv4ZxdBEs03qblt1myJs94rYRK9loJF3xDj8mgQz3LmCyp0yYrNjbN/1/GWZTZDGCA==} + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -2405,62 +2292,62 @@ packages: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} - kysely@0.27.6: - resolution: {integrity: sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==} - engines: {node: '>=14.0.0'} + kysely@0.28.2: + resolution: {integrity: sha512-4YAVLoF0Sf0UTqlhgQMFU9iQECdah7n+13ANkiuVfRvlK+uI0Etbgd7bVP36dKlG+NXWbhGua8vnGt+sdhvT7A==} + engines: {node: '>=18.0.0'} - lefthook-darwin-arm64@1.11.12: - resolution: {integrity: sha512-nB3rZVGoign6lhlbdfT1/knk4fV4Kx7kgbho8oSFcpw/o2qRQpLqmclCWUTtf+Pyj4vCzE7hiee/m+uQtvu19w==} + lefthook-darwin-arm64@1.11.13: + resolution: {integrity: sha512-gHwHofXupCtzNLN+8esdWfFTnAEkmBxE/WKA0EwxPPJXdZYa1GUsiG5ipq/CdG/0j8ekYyM9Hzyrrk5BqJ42xw==} cpu: [arm64] os: [darwin] - lefthook-darwin-x64@1.11.12: - resolution: {integrity: sha512-ExNz8ctFRRaVz2wpvjmOtV4GeZcRdsAZwnZbmvlu1fMcJ6WtjAuR6fB0ybtcsc03/zBNrfShiq+VtZLkGv8Oeg==} + lefthook-darwin-x64@1.11.13: + resolution: {integrity: sha512-zYxkWNUirmTidhskY9J9AwxvdMi3YKH+TqZ3AQ1EOqkOwPBWJQW5PbnzsXDrd3YnrtZScYm/tE/moXJpEPPIpQ==} cpu: [x64] os: [darwin] - lefthook-freebsd-arm64@1.11.12: - resolution: {integrity: sha512-3Si6YJ8YLEMJ6TGsaBI2ni64XSrJX69N4gX7OKQp85IXeizPUEy7oorYAJCUaw5nMffRbIkzxNTjaMkcn4iwag==} + lefthook-freebsd-arm64@1.11.13: + resolution: {integrity: sha512-gJzWnllcMcivusmPorEkXPpEciKotlBHn7QxWwYaSjss/U3YdZu+NTjDO30b3qeiVlyq4RAZ4BPKJODXxHHwUA==} cpu: [arm64] os: [freebsd] - lefthook-freebsd-x64@1.11.12: - resolution: {integrity: sha512-J18MNYZKkVdHJ5K54MT8kxJ/W4TBUxD8aCi4e+Oliw8UXAiwaJSTGPkdY5P8aUlVYDknN2w+6I99Dxre6CJRFw==} + lefthook-freebsd-x64@1.11.13: + resolution: {integrity: sha512-689XdchgtDvZQWFFx1szUvm/mqrq/v6laki0odq5FAfcSgUeLu3w+z6UicBS5l55eFJuQTDNKARFqrKJ04e+Vw==} cpu: [x64] os: [freebsd] - lefthook-linux-arm64@1.11.12: - resolution: {integrity: sha512-oIWcj7mcHnFB4tcfz4dsZTnDTXIyF7cjCEqhDQTvqJQLbE1XRfjU0RzQdgSKrzdmXIcUFB+lmcgeRwJnKBEJ8Q==} + lefthook-linux-arm64@1.11.13: + resolution: {integrity: sha512-ujCLbaZg5S/Ao8KZAcNSb+Y3gl898ZEM0YKyiZmZo22dFFpm/5gcV46pF3xaqIw5IpH+3YYDTKDU+qTetmARyQ==} cpu: [arm64] os: [linux] - lefthook-linux-x64@1.11.12: - resolution: {integrity: sha512-sr9X5dW5dl9Fa3Kdk3x66DPGgCz/rykm+JHIyQGfnuvZnaeqkEaXgNubBaVGBbOimagXgtA5DwXc6D6fzUYALA==} + lefthook-linux-x64@1.11.13: + resolution: {integrity: sha512-O5WdodeBtFOXQlvPcckqp4W/yqVM9DbVQBkvOxwSJlmsxO4sGYK1TqdxH9ihLB85B2kPPssZj9ze36/oizzhVQ==} cpu: [x64] os: [linux] - lefthook-openbsd-arm64@1.11.12: - resolution: {integrity: sha512-4TuX8c/lwky1DSNIY6knIFlMIHQZrVBxh6O5vSTjOAjKv5YmIkNgeUlwcBD+SMru9tQBj7MvOpJSkVkaLK5hhQ==} + lefthook-openbsd-arm64@1.11.13: + resolution: {integrity: sha512-SyBpciUfvY/lUDbZu7L6MtL/SVG2+yMTckBgb4PdJQhJlisY0IsyOYdlTw2icPPrY7JnwdsFv8UW0EJOB76W4g==} cpu: [arm64] os: [openbsd] - lefthook-openbsd-x64@1.11.12: - resolution: {integrity: sha512-Y/rPvyXtsIH+pxACfLHwxqc2Ahk+aExj8Izce3zXp75Wki5DH+6TXm5tWj5CgIuefL7CMqNFsOZCjEe1+SyM+w==} + lefthook-openbsd-x64@1.11.13: + resolution: {integrity: sha512-6+/0j6O2dzo9cjTWUKfL2J6hRR7Krna/ssqnW8cWh8QHZKO9WJn34epto9qgjeHwSysou8byI7Mwv5zOGthLCQ==} cpu: [x64] os: [openbsd] - lefthook-windows-arm64@1.11.12: - resolution: {integrity: sha512-OJaElGktzsMrkmIpXBqwlc+eZx5kwxx+tJFByTXiW/rb8ttBwj0ueVyfo3lw/PqqlbMy73qc9Uj3CHYkaKsDKw==} + lefthook-windows-arm64@1.11.13: + resolution: {integrity: sha512-w5TwZ8bsZ17uOMtYGc5oEb4tCHjNTSeSXRy6H9Yic8E7IsPZtZLkaZGnIIwgXFuhhrcCdc6FuTvKt2tyV7EW2g==} cpu: [arm64] os: [win32] - lefthook-windows-x64@1.11.12: - resolution: {integrity: sha512-ZhKsisibIcaG+rv9i7UJUgnuejI6mfaS5T3FreqsWt5vAsEIvLLNmZUA15MHPr99n+L4La1YQ2jTqie1kH57dA==} + lefthook-windows-x64@1.11.13: + resolution: {integrity: sha512-7lvwnIs8CNOXKU4y3i1Pbqna+QegIORkSD2VCuHBNpIJ8H84NpjoG3tKU91IM/aI1a2eUvCk+dw+1rfMRz7Ytg==} cpu: [x64] os: [win32] - lefthook@1.11.12: - resolution: {integrity: sha512-refh8mlcNtwJfmHDH+2mN1KTIVjp1EHlrjzOjfH/hJ4vFQByH2+1KfFDlJLX9V16VESwUNyOGkEZ9cJEF6zNgg==} + lefthook@1.11.13: + resolution: {integrity: sha512-SDTk3D4nW1XRpR9u9fdYQ/qj1xeZVIwZmIFdJUnyq+w9ZLdCCvIrOmtD8SFiJowSevISjQDC+f9nqyFXUxc0SQ==} hasBin: true lightningcss-darwin-arm64@1.30.1: @@ -2585,8 +2472,8 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} - lucide-react@0.510.0: - resolution: {integrity: sha512-p8SQRAMVh7NhsAIETokSqDrc5CHnDLbV29mMnzaXx+Vc/hnqQzwI2r0FMWCcoTXnbw2KEjy48xwpGdEL+ck06Q==} + lucide-react@0.511.0: + resolution: {integrity: sha512-VK5a2ydJ7xm8GvBeKLS9mu1pVK6ucef9780JVUjw6bAjJL/QXnd4Y0p7SPeOUMC27YhzNCZvm5d/QX0Tp3rc0w==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2597,21 +2484,13 @@ packages: resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} engines: {node: '>=16.10'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - mime@3.0.0: resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} engines: {node: '>=10.0.0'} hasBin: true - miniflare@4.20250507.0: - resolution: {integrity: sha512-EgbQRt/Hnr8HCmW2J/4LRNE3yOzJTdNd98XJ8gnGXFKcimXxUFPiWP3k1df+ZPCtEHp6cXxi8+jP7v9vuIbIsg==} + miniflare@4.20250508.3: + resolution: {integrity: sha512-43oTmZ0CCmUcieetI5YDDyX0IiwhOcVIWzdBBCqWXK3F1XgQwg4d3fTqRyJnCmHIoaYx9CE1kTEKZC1UahPQhA==} engines: {node: '>=18.0.0'} hasBin: true @@ -2654,9 +2533,6 @@ packages: resolution: {integrity: sha512-k1oiVNN4hDK8NcNERSZLQiMfRzEGtfnvZvdBvey3SQbgn8Dcrk0h1I6vpxApjb10PFUflZrgJ2WEZyJQ+5v7YQ==} engines: {node: ^18.0.0 || >=20.0.0} - node-fetch-native@1.6.6: - resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==} - node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -2800,6 +2676,22 @@ packages: peerDependencies: react: ^19.1.0 + react-i18next@15.5.1: + resolution: {integrity: sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA==} + peerDependencies: + i18next: '>= 23.2.3' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + typescript: ^5 + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + typescript: + optional: true + react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -2814,8 +2706,8 @@ packages: '@types/react': optional: true - react-remove-scroll@2.6.3: - resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} + react-remove-scroll@2.7.0: + resolution: {integrity: sha512-sGsQtcjMqdQyijAHytfGEELB8FufGbfXIsvUTe+NLx1GDRJCXtCFLBLUI1eyZCKXXvbEU2C6gai0PZKoIE9Vbg==} engines: {node: '>=10'} peerDependencies: '@types/react': '*' @@ -2880,11 +2772,6 @@ packages: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} - rollup@4.40.2: - resolution: {integrity: sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - rollup@4.41.0: resolution: {integrity: sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -2900,11 +2787,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.7.1: - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} @@ -2988,10 +2870,6 @@ packages: stream-slice@0.1.2: resolution: {integrity: sha512-QzQxpoacatkreL6jsxnVb7X5R/pGw9OUv2qWTYWnmLpg4NdN31snPy/f3TdQE1ZUXaThRvj1Zw4/OGg0ZkaLMA==} - streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -3013,17 +2891,14 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true - tailwind-merge@3.2.0: - resolution: {integrity: sha512-FQT/OVqCD+7edmmJpsgCsY820RTD5AkBryuG5IUqR5YQZSdj5xlH5nLgH7YPths7WsLPSpSBNneJdM8aS8aeFA==} + tailwind-merge@3.3.0: + resolution: {integrity: sha512-fyW/pEfcQSiigd5SNn0nApUOxx0zB/dm6UDU/rEwc2c3sX2smWUNbapHv+QRqLGVp9GWX3THIa7MUGPo+YkDzQ==} tailwindcss-animate@1.0.7: resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} peerDependencies: tailwindcss: '>=3.0.0 || insiders' - tailwindcss@4.1.5: - resolution: {integrity: sha512-nYtSPfWGDiWgCkwQG/m+aX83XCwf62sBgg3bIlNiiOcggnS1x3uVRDAuyelBFL+vJdOPPCGElxv9DjHJjRHiVA==} - tailwindcss@4.1.7: resolution: {integrity: sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==} @@ -3119,12 +2994,12 @@ packages: resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} - undici@6.21.2: - resolution: {integrity: sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==} + undici@6.21.3: + resolution: {integrity: sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==} engines: {node: '>=18.17'} - unenv@2.0.0-rc.15: - resolution: {integrity: sha512-J/rEIZU8w6FOfLNz/hNKsnY+fFHWnu9MH4yRbSZF3xbbGHovcetXPs7sD+9p8L6CeNC//I9bhRYAOsBt2u7/OA==} + unenv@2.0.0-rc.17: + resolution: {integrity: sha512-B06u0wXkEd+o5gOCMl/ZHl5cfpYbDZKAT+HWTL+Hws6jWu7dCiqBBXXXzMFcFVJb8D4ytAnYmxJA83uwOQRSsg==} unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} @@ -3140,9 +3015,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - urlpattern-polyfill@10.1.0: - resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==} - use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -3236,6 +3108,10 @@ packages: yaml: optional: true + void-elements@3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -3257,17 +3133,17 @@ packages: engines: {node: ^16.13.0 || >=18.0.0} hasBin: true - workerd@1.20250507.0: - resolution: {integrity: sha512-OXaGjEh5THT9iblwWIyPrYBoaPe/d4zN03Go7/w8CmS8sma7//O9hjbk43sboWkc89taGPmU0/LNyZUUiUlHeQ==} + workerd@1.20250508.0: + resolution: {integrity: sha512-ffLxe7dXSuGoA6jb3Qx2SClIV1aLHfJQ6RhGhzYHjQgv7dL6fdUOSIIGgzmu2mRKs+WFSujp6c8WgKquco6w3w==} engines: {node: '>=16'} hasBin: true - wrangler@4.14.4: - resolution: {integrity: sha512-HIdOdiMIcJV5ymw80RKsr3Uzen/p1kRX4jnCEmR2XVeoEhV2Qw6GABxS5WMTlSES2/vEX0Y+ezUAdsprcUhJ5g==} + wrangler@4.16.0: + resolution: {integrity: sha512-zQojiBJKAWRVG4WdUgTP5/i9N5UcwOixhWljnBrcKxJd+kpqUXVV/L03ytO+0cnr5IhgYUs7qhjd8EWU6UwPfg==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: - '@cloudflare/workers-types': ^4.20250507.0 + '@cloudflare/workers-types': ^4.20250508.0 peerDependenciesMeta: '@cloudflare/workers-types': optional: true @@ -3318,11 +3194,17 @@ packages: youch@3.3.4: resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==} + zod-i18n-map@2.27.0: + resolution: {integrity: sha512-ORu9XpiVh3WDiEUs5Cr9siGgnpeODoBsTIgSD8sQCH9B//f9KowlzqHUEdPYb3vFonaSH8yPvPCOFM4niwp3Sg==} + peerDependencies: + i18next: '>=21.3.0' + zod: '>=3.17.0' + zod@3.22.3: resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==} - zod@3.24.4: - resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + zod@3.25.7: + resolution: {integrity: sha512-YGdT1cVRmKkOg6Sq7vY7IkxdphySKnXhaUmFI4r4FcuFVNgpCb9tZfNwXbT6BPjD5oz0nubFsoo9pIqKrDcCvg==} snapshots: @@ -3352,7 +3234,7 @@ snapshots: '@babel/traverse': 7.27.1 '@babel/types': 7.27.1 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.1 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -3497,6 +3379,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/runtime@7.27.1': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -3510,7 +3394,7 @@ snapshots: '@babel/parser': 7.27.2 '@babel/template': 7.27.2 '@babel/types': 7.27.1 - debug: 4.4.0 + debug: 4.4.1 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -3520,7 +3404,7 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@better-auth/utils@0.2.4': + '@better-auth/utils@0.2.5': dependencies: typescript: 5.8.3 uncrypto: 0.1.3 @@ -3566,24 +3450,24 @@ snapshots: dependencies: mime: 3.0.0 - '@cloudflare/unenv-preset@2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250507.0)': + '@cloudflare/unenv-preset@2.3.2(unenv@2.0.0-rc.17)(workerd@1.20250508.0)': dependencies: - unenv: 2.0.0-rc.15 + unenv: 2.0.0-rc.17 optionalDependencies: - workerd: 1.20250507.0 + workerd: 1.20250508.0 - '@cloudflare/vite-plugin@1.1.1(rollup@4.41.0)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1))(workerd@1.20250507.0)(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0))': + '@cloudflare/vite-plugin@1.2.3(rollup@4.41.0)(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1))(workerd@1.20250508.0)(wrangler@4.16.0(@cloudflare/workers-types@4.20250520.0))': dependencies: - '@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250507.0) - '@hattip/adapter-node': 0.0.49 + '@cloudflare/unenv-preset': 2.3.2(unenv@2.0.0-rc.17)(workerd@1.20250508.0) + '@mjackson/node-fetch-server': 0.6.1 '@rollup/plugin-replace': 6.0.2(rollup@4.41.0) get-port: 7.1.0 - miniflare: 4.20250507.0 + miniflare: 4.20250508.3 picocolors: 1.1.1 tinyglobby: 0.2.13 - unenv: 2.0.0-rc.15 - vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) - wrangler: 4.14.4(@cloudflare/workers-types@4.20250510.0) + unenv: 2.0.0-rc.17 + vite: 6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) + wrangler: 4.16.0(@cloudflare/workers-types@4.20250520.0) ws: 8.18.0 transitivePeerDependencies: - bufferutil @@ -3591,28 +3475,28 @@ snapshots: - utf-8-validate - workerd - '@cloudflare/workerd-darwin-64@1.20250507.0': + '@cloudflare/workerd-darwin-64@1.20250508.0': optional: true - '@cloudflare/workerd-darwin-arm64@1.20250507.0': + '@cloudflare/workerd-darwin-arm64@1.20250508.0': optional: true - '@cloudflare/workerd-linux-64@1.20250507.0': + '@cloudflare/workerd-linux-64@1.20250508.0': optional: true - '@cloudflare/workerd-linux-arm64@1.20250507.0': + '@cloudflare/workerd-linux-arm64@1.20250508.0': optional: true - '@cloudflare/workerd-windows-64@1.20250507.0': + '@cloudflare/workerd-windows-64@1.20250508.0': optional: true - '@cloudflare/workers-types@4.20250510.0': {} + '@cloudflare/workers-types@4.20250520.0': {} - '@commitlint/cli@19.8.1(@types/node@22.15.17)(typescript@5.8.3)': + '@commitlint/cli@19.8.1(@types/node@22.15.19)(typescript@5.8.3)': dependencies: '@commitlint/format': 19.8.1 '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@22.15.17)(typescript@5.8.3) + '@commitlint/load': 19.8.1(@types/node@22.15.19)(typescript@5.8.3) '@commitlint/read': 19.8.1 '@commitlint/types': 19.8.1 tinyexec: 1.0.1 @@ -3650,7 +3534,7 @@ snapshots: '@commitlint/is-ignored@19.8.1': dependencies: '@commitlint/types': 19.8.1 - semver: 7.7.1 + semver: 7.7.2 '@commitlint/lint@19.8.1': dependencies: @@ -3659,7 +3543,7 @@ snapshots: '@commitlint/rules': 19.8.1 '@commitlint/types': 19.8.1 - '@commitlint/load@19.8.1(@types/node@22.15.17)(typescript@5.8.3)': + '@commitlint/load@19.8.1(@types/node@22.15.19)(typescript@5.8.3)': dependencies: '@commitlint/config-validator': 19.8.1 '@commitlint/execute-rule': 19.8.1 @@ -3667,7 +3551,7 @@ snapshots: '@commitlint/types': 19.8.1 chalk: 5.4.1 cosmiconfig: 9.0.0(typescript@5.8.3) - cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.17)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@22.15.19)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -3718,17 +3602,17 @@ snapshots: '@types/conventional-commits-parser': 5.0.1 chalk: 5.4.1 - '@conform-to/dom@1.5.0': {} + '@conform-to/dom@1.6.0': {} - '@conform-to/react@1.5.0(react@19.1.0)': + '@conform-to/react@1.6.0(react@19.1.0)': dependencies: - '@conform-to/dom': 1.5.0 + '@conform-to/dom': 1.6.0 react: 19.1.0 - '@conform-to/zod@1.5.0(zod@3.24.4)': + '@conform-to/zod@1.6.0(zod@3.25.7)': dependencies: - '@conform-to/dom': 1.5.0 - zod: 3.24.4 + '@conform-to/dom': 1.6.0 + zod: 3.25.7 '@cspotcode/source-map-support@0.8.1': dependencies: @@ -3911,30 +3795,6 @@ snapshots: '@floating-ui/utils@0.2.9': {} - '@hattip/adapter-node@0.0.49': - dependencies: - '@hattip/core': 0.0.49 - '@hattip/polyfills': 0.0.49 - '@hattip/walk': 0.0.49 - - '@hattip/core@0.0.49': {} - - '@hattip/headers@0.0.49': - dependencies: - '@hattip/core': 0.0.49 - - '@hattip/polyfills@0.0.49': - dependencies: - '@hattip/core': 0.0.49 - '@whatwg-node/fetch': 0.9.23 - node-fetch-native: 1.6.6 - - '@hattip/walk@0.0.49': - dependencies: - '@hattip/headers': 0.0.49 - cac: 6.7.14 - mime-types: 2.1.35 - '@hexagon/base64@1.1.28': {} '@img/sharp-darwin-arm64@0.33.5': @@ -4047,12 +3907,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@kamilkisiela/fast-url-parser@1.1.4': {} - '@levischuck/tiny-cbor@0.2.11': {} '@mjackson/node-fetch-server@0.2.0': {} + '@mjackson/node-fetch-server@0.6.1': {} + '@noble/ciphers@0.6.0': {} '@noble/hashes@1.8.0': {} @@ -4065,7 +3925,7 @@ snapshots: proc-log: 3.0.0 promise-inflight: 1.0.1 promise-retry: 2.0.1 - semver: 7.7.1 + semver: 7.7.2 which: 3.0.1 transitivePeerDependencies: - bluebird @@ -4078,7 +3938,7 @@ snapshots: json-parse-even-better-errors: 3.0.2 normalize-package-data: 5.0.0 proc-log: 3.0.0 - semver: 7.7.1 + semver: 7.7.2 transitivePeerDependencies: - bluebird @@ -4134,435 +3994,435 @@ snapshots: '@radix-ui/primitive@1.1.2': {} - '@radix-ui/react-alert-dialog@1.1.13(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-alert-dialog@1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-dialog': 1.1.13(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-dialog': 1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-arrow@1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-arrow@1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-avatar@1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-avatar@1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-checkbox@1.3.1(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-checkbox@1.3.1(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-collection@1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-collection@1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-context@1.1.2(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-context@1.1.2(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-dialog@1.1.13(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dialog@1.1.13(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) - aria-hidden: 1.2.4 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) + aria-hidden: 1.2.6 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-remove-scroll: 2.6.3(@types/react@19.1.3)(react@19.1.0) + react-remove-scroll: 2.7.0(@types/react@19.1.4)(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-direction@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-direction@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-dismissable-layer@1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dismissable-layer@1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-dropdown-menu@2.1.14(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-dropdown-menu@2.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-menu': 2.1.14(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-menu': 2.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-focus-guards@1.1.2(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-focus-guards@1.1.2(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-focus-scope@1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-focus-scope@1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-id@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-id@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-label@2.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-label@2.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-menu@2.1.14(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-menu@2.1.14(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-direction': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) - aria-hidden: 1.2.4 + '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) + aria-hidden: 1.2.6 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-remove-scroll: 2.6.3(@types/react@19.1.3)(react@19.1.0) + react-remove-scroll: 2.7.0(@types/react@19.1.4)(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-popper@1.2.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-popper@1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@floating-ui/react-dom': 2.1.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-arrow': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-arrow': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.4)(react@19.1.0) '@radix-ui/rect': 1.1.1 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-portal@1.1.8(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-portal@1.1.8(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-presence@1.1.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-presence@1.1.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-primitive@2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-primitive@2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-radio-group@1.3.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-radio-group@1.3.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-direction': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-roving-focus': 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-roving-focus': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-roving-focus@1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-roving-focus@1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-direction': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-select@2.2.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-select@2.2.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-direction': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-visually-hidden': 1.2.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - aria-hidden: 1.2.4 + '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-focus-guards': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-focus-scope': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-visually-hidden': 1.2.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + aria-hidden: 1.2.6 react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - react-remove-scroll: 2.6.3(@types/react@19.1.3)(react@19.1.0) + react-remove-scroll: 2.7.0(@types/react@19.1.4)(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-slider@1.3.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-slider@1.3.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/number': 1.1.1 '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-direction': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-collection': 1.1.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-direction': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-slot@1.2.2(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-slot@1.2.2(@types/react@19.1.4)(react@19.1.0)': dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-tooltip@1.2.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-tooltip@1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@radix-ui/primitive': 1.1.2 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-visually-hidden': 1.2.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-dismissable-layer': 1.1.9(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-popper': 1.2.6(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-portal': 1.1.8(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-slot': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-visually-hidden': 1.2.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.1.4)(react@19.1.0)': dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.1.3)(react@19.1.0) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.1.4)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.1.4)(react@19.1.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 use-sync-external-store: 1.5.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-previous@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-previous@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-rect@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-rect@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: '@radix-ui/rect': 1.1.1 react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-use-size@1.1.1(@types/react@19.1.3)(react@19.1.0)': + '@radix-ui/react-use-size@1.1.1(@types/react@19.1.4)(react@19.1.0)': dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.3)(react@19.1.0) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.1.4)(react@19.1.0) react: 19.1.0 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@radix-ui/react-visually-hidden@1.2.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + '@radix-ui/react-visually-hidden@1.2.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: - '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.4(@types/react@19.1.3))(@types/react@19.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@radix-ui/react-primitive': 2.1.2(@types/react-dom@19.1.5(@types/react@19.1.4))(@types/react@19.1.4)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 - '@types/react-dom': 19.1.4(@types/react@19.1.3) + '@types/react': 19.1.4 + '@types/react-dom': 19.1.5(@types/react@19.1.4) '@radix-ui/rect@1.1.1': {} - '@react-router/cloudflare@7.6.0(@cloudflare/workers-types@4.20250510.0)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(tsup@8.4.0(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3))(typescript@5.8.3)': + '@react-router/cloudflare@7.6.0(@cloudflare/workers-types@4.20250520.0)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(tsup@8.4.0(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3))(typescript@5.8.3)': dependencies: - '@cloudflare/workers-types': 4.20250510.0 + '@cloudflare/workers-types': 4.20250520.0 react-router: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) tsup: 8.4.0(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3) optionalDependencies: typescript: 5.8.3 - '@react-router/dev@7.6.0(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1))(wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0))': + '@react-router/dev@7.6.0(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1)(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1))(wrangler@4.16.0(@cloudflare/workers-types@4.20250520.0))': dependencies: '@babel/core': 7.27.1 '@babel/generator': 7.27.1 @@ -4588,14 +4448,14 @@ snapshots: prettier: 2.8.8 react-refresh: 0.14.2 react-router: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - semver: 7.7.1 + semver: 7.7.2 set-cookie-parser: 2.7.1 valibot: 0.41.0(typescript@5.8.3) - vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) - vite-node: 3.0.0-beta.2(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) + vite: 6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) + vite-node: 3.0.0-beta.2(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) optionalDependencies: typescript: 5.8.3 - wrangler: 4.14.4(@cloudflare/workers-types@4.20250510.0) + wrangler: 4.16.0(@cloudflare/workers-types@4.20250520.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4618,7 +4478,7 @@ snapshots: react-router: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) source-map-support: 0.5.21 stream-slice: 0.1.2 - undici: 6.21.2 + undici: 6.21.3 optionalDependencies: typescript: 5.8.3 @@ -4637,123 +4497,63 @@ snapshots: optionalDependencies: rollup: 4.41.0 - '@rollup/rollup-android-arm-eabi@4.40.2': - optional: true - '@rollup/rollup-android-arm-eabi@4.41.0': optional: true - '@rollup/rollup-android-arm64@4.40.2': - optional: true - '@rollup/rollup-android-arm64@4.41.0': optional: true - '@rollup/rollup-darwin-arm64@4.40.2': - optional: true - '@rollup/rollup-darwin-arm64@4.41.0': optional: true - '@rollup/rollup-darwin-x64@4.40.2': - optional: true - '@rollup/rollup-darwin-x64@4.41.0': optional: true - '@rollup/rollup-freebsd-arm64@4.40.2': - optional: true - '@rollup/rollup-freebsd-arm64@4.41.0': optional: true - '@rollup/rollup-freebsd-x64@4.40.2': - optional: true - '@rollup/rollup-freebsd-x64@4.41.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.40.2': - optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.41.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.40.2': - optional: true - '@rollup/rollup-linux-arm-musleabihf@4.41.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.40.2': - optional: true - '@rollup/rollup-linux-arm64-gnu@4.41.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.40.2': - optional: true - '@rollup/rollup-linux-arm64-musl@4.41.0': optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.40.2': - optional: true - '@rollup/rollup-linux-loongarch64-gnu@4.41.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.40.2': - optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.41.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.40.2': - optional: true - '@rollup/rollup-linux-riscv64-gnu@4.41.0': optional: true - '@rollup/rollup-linux-riscv64-musl@4.40.2': - optional: true - '@rollup/rollup-linux-riscv64-musl@4.41.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.40.2': - optional: true - '@rollup/rollup-linux-s390x-gnu@4.41.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.40.2': - optional: true - '@rollup/rollup-linux-x64-gnu@4.41.0': optional: true - '@rollup/rollup-linux-x64-musl@4.40.2': - optional: true - '@rollup/rollup-linux-x64-musl@4.41.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.40.2': - optional: true - '@rollup/rollup-win32-arm64-msvc@4.41.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.40.2': - optional: true - '@rollup/rollup-win32-ia32-msvc@4.41.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.40.2': - optional: true - '@rollup/rollup-win32-x64-msvc@4.41.0': optional: true @@ -4833,43 +4633,31 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.7 '@tailwindcss/oxide-win32-x64-msvc': 4.1.7 - '@tailwindcss/vite@4.1.7(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1))': + '@tailwindcss/vite@4.1.7(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1))': dependencies: '@tailwindcss/node': 4.1.7 '@tailwindcss/oxide': 4.1.7 tailwindcss: 4.1.7 - vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) + vite: 6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) '@types/conventional-commits-parser@5.0.1': dependencies: - '@types/node': 22.15.17 + '@types/node': 22.15.19 '@types/estree@1.0.7': {} - '@types/node@22.15.17': + '@types/node@22.15.19': dependencies: undici-types: 6.21.0 - '@types/react-dom@19.1.4(@types/react@19.1.3)': + '@types/react-dom@19.1.5(@types/react@19.1.4)': dependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - '@types/react@19.1.3': + '@types/react@19.1.4': dependencies: csstype: 3.1.3 - '@whatwg-node/fetch@0.9.23': - dependencies: - '@whatwg-node/node-fetch': 0.6.0 - urlpattern-polyfill: 10.1.0 - - '@whatwg-node/node-fetch@0.6.0': - dependencies: - '@kamilkisiela/fast-url-parser': 1.1.4 - busboy: 1.6.0 - fast-querystring: 1.1.2 - tslib: 2.8.1 - JSONStream@1.3.5: dependencies: jsonparse: 1.3.1 @@ -4902,7 +4690,7 @@ snapshots: argparse@2.0.1: {} - aria-hidden@1.2.4: + aria-hidden@1.2.6: dependencies: tslib: 2.8.1 @@ -4929,9 +4717,9 @@ snapshots: balanced-match@1.0.2: {} - better-auth@1.2.7: + better-auth@1.2.8: dependencies: - '@better-auth/utils': 0.2.4 + '@better-auth/utils': 0.2.5 '@better-fetch/fetch': 1.1.18 '@noble/ciphers': 0.6.0 '@noble/hashes': 1.8.0 @@ -4940,9 +4728,9 @@ snapshots: better-call: 1.0.9 defu: 6.1.4 jose: 5.10.0 - kysely: 0.27.6 + kysely: 0.28.2 nanostores: 0.11.4 - zod: 3.24.4 + zod: 3.25.7 better-call@1.0.9: dependencies: @@ -4959,8 +4747,8 @@ snapshots: browserslist@4.24.5: dependencies: - caniuse-lite: 1.0.30001717 - electron-to-chromium: 1.5.151 + caniuse-lite: 1.0.30001718 + electron-to-chromium: 1.5.155 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.5) @@ -4971,15 +4759,11 @@ snapshots: esbuild: 0.25.4 load-tsconfig: 0.2.5 - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - cac@6.7.14: {} callsites@3.1.0: {} - caniuse-lite@1.0.30001717: {} + caniuse-lite@1.0.30001718: {} chalk@5.4.1: {} @@ -5011,13 +4795,11 @@ snapshots: dependencies: color-name: 1.1.4 simple-swizzle: 0.2.2 - optional: true color@4.2.3: dependencies: color-convert: 2.0.1 color-string: 1.9.1 - optional: true commander@4.1.1: {} @@ -5049,9 +4831,9 @@ snapshots: cookie@1.0.2: {} - cosmiconfig-typescript-loader@6.1.0(@types/node@22.15.17)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): + cosmiconfig-typescript-loader@6.1.0(@types/node@22.15.19)(cosmiconfig@9.0.0(typescript@5.8.3))(typescript@5.8.3): dependencies: - '@types/node': 22.15.17 + '@types/node': 22.15.19 cosmiconfig: 9.0.0(typescript@5.8.3) jiti: 2.4.2 typescript: 5.8.3 @@ -5079,10 +4861,6 @@ snapshots: date-fns@4.1.0: {} - debug@4.4.0: - dependencies: - ms: 2.1.3 - debug@4.4.1: dependencies: ms: 2.1.3 @@ -5108,15 +4886,15 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.43.1(@cloudflare/workers-types@4.20250510.0)(gel@2.1.0)(kysely@0.27.6): + drizzle-orm@0.43.1(@cloudflare/workers-types@4.20250520.0)(gel@2.1.0)(kysely@0.28.2): optionalDependencies: - '@cloudflare/workers-types': 4.20250510.0 + '@cloudflare/workers-types': 4.20250520.0 gel: 2.1.0 - kysely: 0.27.6 + kysely: 0.28.2 eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.151: {} + electron-to-chromium@1.5.155: {} emoji-regex@8.0.0: {} @@ -5142,7 +4920,7 @@ snapshots: esbuild-register@3.6.0(esbuild@0.25.4): dependencies: - debug: 4.4.0 + debug: 4.4.1 esbuild: 0.25.4 transitivePeerDependencies: - supports-color @@ -5208,14 +4986,8 @@ snapshots: exsolve@1.0.5: {} - fast-decode-uri-component@1.0.1: {} - fast-deep-equal@3.1.3: {} - fast-querystring@1.1.2: - dependencies: - fast-decode-uri-component: 1.0.1 - fast-uri@3.0.6: {} fdir@6.4.4(picomatch@4.0.2): @@ -5308,6 +5080,20 @@ snapshots: dependencies: lru-cache: 7.18.3 + html-parse-stringify@3.0.1: + dependencies: + void-elements: 3.1.0 + + i18next-browser-languagedetector@8.1.0: + dependencies: + '@babel/runtime': 7.27.1 + + i18next@25.2.0(typescript@5.8.3): + dependencies: + '@babel/runtime': 7.27.1 + optionalDependencies: + typescript: 5.8.3 + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -5319,8 +5105,7 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.2: - optional: true + is-arrayish@0.3.2: {} is-core-module@2.16.1: dependencies: @@ -5377,50 +5162,50 @@ snapshots: jsonparse@1.3.1: {} - kysely@0.27.6: {} + kysely@0.28.2: {} - lefthook-darwin-arm64@1.11.12: + lefthook-darwin-arm64@1.11.13: optional: true - lefthook-darwin-x64@1.11.12: + lefthook-darwin-x64@1.11.13: optional: true - lefthook-freebsd-arm64@1.11.12: + lefthook-freebsd-arm64@1.11.13: optional: true - lefthook-freebsd-x64@1.11.12: + lefthook-freebsd-x64@1.11.13: optional: true - lefthook-linux-arm64@1.11.12: + lefthook-linux-arm64@1.11.13: optional: true - lefthook-linux-x64@1.11.12: + lefthook-linux-x64@1.11.13: optional: true - lefthook-openbsd-arm64@1.11.12: + lefthook-openbsd-arm64@1.11.13: optional: true - lefthook-openbsd-x64@1.11.12: + lefthook-openbsd-x64@1.11.13: optional: true - lefthook-windows-arm64@1.11.12: + lefthook-windows-arm64@1.11.13: optional: true - lefthook-windows-x64@1.11.12: + lefthook-windows-x64@1.11.13: optional: true - lefthook@1.11.12: + lefthook@1.11.13: optionalDependencies: - lefthook-darwin-arm64: 1.11.12 - lefthook-darwin-x64: 1.11.12 - lefthook-freebsd-arm64: 1.11.12 - lefthook-freebsd-x64: 1.11.12 - lefthook-linux-arm64: 1.11.12 - lefthook-linux-x64: 1.11.12 - lefthook-openbsd-arm64: 1.11.12 - lefthook-openbsd-x64: 1.11.12 - lefthook-windows-arm64: 1.11.12 - lefthook-windows-x64: 1.11.12 + lefthook-darwin-arm64: 1.11.13 + lefthook-darwin-x64: 1.11.13 + lefthook-freebsd-arm64: 1.11.13 + lefthook-freebsd-x64: 1.11.13 + lefthook-linux-arm64: 1.11.13 + lefthook-linux-x64: 1.11.13 + lefthook-openbsd-arm64: 1.11.13 + lefthook-openbsd-x64: 1.11.13 + lefthook-windows-arm64: 1.11.13 + lefthook-windows-x64: 1.11.13 lightningcss-darwin-arm64@1.30.1: optional: true @@ -5507,7 +5292,7 @@ snapshots: lru-cache@7.18.3: {} - lucide-react@0.510.0(react@19.1.0): + lucide-react@0.511.0(react@19.1.0): dependencies: react: 19.1.0 @@ -5517,24 +5302,19 @@ snapshots: meow@12.1.1: {} - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - mime@3.0.0: {} - miniflare@4.20250507.0: + miniflare@4.20250508.3: dependencies: '@cspotcode/source-map-support': 0.8.1 acorn: 8.14.0 acorn-walk: 8.3.2 exit-hook: 2.2.1 glob-to-regexp: 0.4.1 + sharp: 0.33.5 stoppable: 1.1.0 undici: 5.29.0 - workerd: 1.20250507.0 + workerd: 1.20250508.0 ws: 8.18.0 youch: 3.3.4 zod: 3.22.3 @@ -5570,20 +5350,18 @@ snapshots: nanostores@0.11.4: {} - node-fetch-native@1.6.6: {} - node-releases@2.0.19: {} normalize-package-data@5.0.0: dependencies: hosted-git-info: 6.1.3 is-core-module: 2.16.1 - semver: 7.7.1 + semver: 7.7.2 validate-npm-package-license: 3.0.4 npm-install-checks@6.3.0: dependencies: - semver: 7.7.1 + semver: 7.7.2 npm-normalize-package-bin@3.0.1: {} @@ -5591,7 +5369,7 @@ snapshots: dependencies: hosted-git-info: 6.1.3 proc-log: 3.0.0 - semver: 7.7.1 + semver: 7.7.2 validate-npm-package-name: 5.0.1 npm-pick-manifest@8.0.2: @@ -5599,7 +5377,7 @@ snapshots: npm-install-checks: 6.3.0 npm-normalize-package-bin: 3.0.1 npm-package-arg: 10.1.0 - semver: 7.7.1 + semver: 7.7.2 object-assign@4.1.1: {} @@ -5686,26 +5464,36 @@ snapshots: react: 19.1.0 scheduler: 0.26.0 + react-i18next@15.5.1(i18next@25.2.0(typescript@5.8.3))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3): + dependencies: + '@babel/runtime': 7.27.1 + html-parse-stringify: 3.0.1 + i18next: 25.2.0(typescript@5.8.3) + react: 19.1.0 + optionalDependencies: + react-dom: 19.1.0(react@19.1.0) + typescript: 5.8.3 + react-refresh@0.14.2: {} - react-remove-scroll-bar@2.3.8(@types/react@19.1.3)(react@19.1.0): + react-remove-scroll-bar@2.3.8(@types/react@19.1.4)(react@19.1.0): dependencies: react: 19.1.0 - react-style-singleton: 2.2.3(@types/react@19.1.3)(react@19.1.0) + react-style-singleton: 2.2.3(@types/react@19.1.4)(react@19.1.0) tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - react-remove-scroll@2.6.3(@types/react@19.1.3)(react@19.1.0): + react-remove-scroll@2.7.0(@types/react@19.1.4)(react@19.1.0): dependencies: react: 19.1.0 - react-remove-scroll-bar: 2.3.8(@types/react@19.1.3)(react@19.1.0) - react-style-singleton: 2.2.3(@types/react@19.1.3)(react@19.1.0) + react-remove-scroll-bar: 2.3.8(@types/react@19.1.4)(react@19.1.0) + react-style-singleton: 2.2.3(@types/react@19.1.4)(react@19.1.0) tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.1.3)(react@19.1.0) - use-sidecar: 1.1.3(@types/react@19.1.3)(react@19.1.0) + use-callback-ref: 1.3.3(@types/react@19.1.4)(react@19.1.0) + use-sidecar: 1.1.3(@types/react@19.1.4)(react@19.1.0) optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: @@ -5715,13 +5503,13 @@ snapshots: optionalDependencies: react-dom: 19.1.0(react@19.1.0) - react-style-singleton@2.2.3(@types/react@19.1.3)(react@19.1.0): + react-style-singleton@2.2.3(@types/react@19.1.4)(react@19.1.0): dependencies: get-nonce: 1.0.1 react: 19.1.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 react@19.1.0: {} @@ -5730,7 +5518,7 @@ snapshots: remix-toast@3.1.0(react-router@7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)): dependencies: react-router: 7.6.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - zod: 3.24.4 + zod: 3.25.7 require-directory@2.1.1: {} @@ -5744,32 +5532,6 @@ snapshots: retry@0.12.0: {} - rollup@4.40.2: - dependencies: - '@types/estree': 1.0.7 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.40.2 - '@rollup/rollup-android-arm64': 4.40.2 - '@rollup/rollup-darwin-arm64': 4.40.2 - '@rollup/rollup-darwin-x64': 4.40.2 - '@rollup/rollup-freebsd-arm64': 4.40.2 - '@rollup/rollup-freebsd-x64': 4.40.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.40.2 - '@rollup/rollup-linux-arm-musleabihf': 4.40.2 - '@rollup/rollup-linux-arm64-gnu': 4.40.2 - '@rollup/rollup-linux-arm64-musl': 4.40.2 - '@rollup/rollup-linux-loongarch64-gnu': 4.40.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.40.2 - '@rollup/rollup-linux-riscv64-gnu': 4.40.2 - '@rollup/rollup-linux-riscv64-musl': 4.40.2 - '@rollup/rollup-linux-s390x-gnu': 4.40.2 - '@rollup/rollup-linux-x64-gnu': 4.40.2 - '@rollup/rollup-linux-x64-musl': 4.40.2 - '@rollup/rollup-win32-arm64-msvc': 4.40.2 - '@rollup/rollup-win32-ia32-msvc': 4.40.2 - '@rollup/rollup-win32-x64-msvc': 4.40.2 - fsevents: 2.3.3 - rollup@4.41.0: dependencies: '@types/estree': 1.0.7 @@ -5802,10 +5564,7 @@ snapshots: semver@6.3.1: {} - semver@7.7.1: {} - - semver@7.7.2: - optional: true + semver@7.7.2: {} set-cookie-parser@2.7.1: {} @@ -5813,7 +5572,7 @@ snapshots: dependencies: color: 4.2.3 detect-libc: 2.0.4 - semver: 7.7.1 + semver: 7.7.2 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.5 '@img/sharp-darwin-x64': 0.33.5 @@ -5834,7 +5593,6 @@ snapshots: '@img/sharp-wasm32': 0.33.5 '@img/sharp-win32-ia32': 0.33.5 '@img/sharp-win32-x64': 0.33.5 - optional: true shebang-command@2.0.0: dependencies: @@ -5850,7 +5608,6 @@ snapshots: simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 - optional: true sonner@2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0): dependencies: @@ -5899,8 +5656,6 @@ snapshots: stream-slice@0.1.2: {} - streamsearch@1.1.0: {} - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -5931,13 +5686,11 @@ snapshots: pirates: 4.0.7 ts-interface-checker: 0.1.13 - tailwind-merge@3.2.0: {} + tailwind-merge@3.3.0: {} - tailwindcss-animate@1.0.7(tailwindcss@4.1.5): + tailwindcss-animate@1.0.7(tailwindcss@4.1.7): dependencies: - tailwindcss: 4.1.5 - - tailwindcss@4.1.5: {} + tailwindcss: 4.1.7 tailwindcss@4.1.7: {} @@ -6026,9 +5779,9 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 - undici@6.21.2: {} + undici@6.21.3: {} - unenv@2.0.0-rc.15: + unenv@2.0.0-rc.17: dependencies: defu: 6.1.4 exsolve: 1.0.5 @@ -6046,22 +5799,20 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - urlpattern-polyfill@10.1.0: {} - - use-callback-ref@1.3.3(@types/react@19.1.3)(react@19.1.0): + use-callback-ref@1.3.3(@types/react@19.1.4)(react@19.1.0): dependencies: react: 19.1.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 - use-sidecar@1.1.3(@types/react@19.1.3)(react@19.1.0): + use-sidecar@1.1.3(@types/react@19.1.4)(react@19.1.0): dependencies: detect-node-es: 1.1.0 react: 19.1.0 tslib: 2.8.1 optionalDependencies: - '@types/react': 19.1.3 + '@types/react': 19.1.4 use-sync-external-store@1.5.0(react@19.1.0): dependencies: @@ -6078,13 +5829,13 @@ snapshots: validate-npm-package-name@5.0.1: {} - vite-node@3.0.0-beta.2(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1): + vite-node@3.0.0-beta.2(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1): dependencies: cac: 6.7.14 - debug: 4.4.0 + debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 1.1.2 - vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) + vite: 6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) transitivePeerDependencies: - '@types/node' - jiti @@ -6099,31 +5850,33 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1)): + vite-tsconfig-paths@5.1.4(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1)): dependencies: - debug: 4.4.0 + debug: 4.4.1 globrex: 0.1.2 tsconfck: 3.1.5(typescript@5.8.3) optionalDependencies: - vite: 6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1) + vite: 6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1) transitivePeerDependencies: - supports-color - typescript - vite@6.3.5(@types/node@22.15.17)(jiti@2.4.2)(lightningcss@1.30.1): + vite@6.3.5(@types/node@22.15.19)(jiti@2.4.2)(lightningcss@1.30.1): dependencies: esbuild: 0.25.4 fdir: 6.4.4(picomatch@4.0.2) picomatch: 4.0.2 postcss: 8.5.3 - rollup: 4.40.2 + rollup: 4.41.0 tinyglobby: 0.2.13 optionalDependencies: - '@types/node': 22.15.17 + '@types/node': 22.15.19 fsevents: 2.3.3 jiti: 2.4.2 lightningcss: 1.30.1 + void-elements@3.1.0: {} + webidl-conversions@4.0.2: {} whatwg-url@7.1.0: @@ -6145,26 +5898,26 @@ snapshots: isexe: 3.1.1 optional: true - workerd@1.20250507.0: + workerd@1.20250508.0: optionalDependencies: - '@cloudflare/workerd-darwin-64': 1.20250507.0 - '@cloudflare/workerd-darwin-arm64': 1.20250507.0 - '@cloudflare/workerd-linux-64': 1.20250507.0 - '@cloudflare/workerd-linux-arm64': 1.20250507.0 - '@cloudflare/workerd-windows-64': 1.20250507.0 + '@cloudflare/workerd-darwin-64': 1.20250508.0 + '@cloudflare/workerd-darwin-arm64': 1.20250508.0 + '@cloudflare/workerd-linux-64': 1.20250508.0 + '@cloudflare/workerd-linux-arm64': 1.20250508.0 + '@cloudflare/workerd-windows-64': 1.20250508.0 - wrangler@4.14.4(@cloudflare/workers-types@4.20250510.0): + wrangler@4.16.0(@cloudflare/workers-types@4.20250520.0): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 - '@cloudflare/unenv-preset': 2.3.1(unenv@2.0.0-rc.15)(workerd@1.20250507.0) + '@cloudflare/unenv-preset': 2.3.2(unenv@2.0.0-rc.17)(workerd@1.20250508.0) blake3-wasm: 2.1.5 esbuild: 0.25.4 - miniflare: 4.20250507.0 + miniflare: 4.20250508.3 path-to-regexp: 6.3.0 - unenv: 2.0.0-rc.15 - workerd: 1.20250507.0 + unenv: 2.0.0-rc.17 + workerd: 1.20250508.0 optionalDependencies: - '@cloudflare/workers-types': 4.20250510.0 + '@cloudflare/workers-types': 4.20250520.0 fsevents: 2.3.3 sharp: 0.33.5 transitivePeerDependencies: @@ -6211,6 +5964,11 @@ snapshots: mustache: 4.2.0 stacktracey: 2.1.8 + zod-i18n-map@2.27.0(i18next@25.2.0(typescript@5.8.3))(zod@3.25.7): + dependencies: + i18next: 25.2.0(typescript@5.8.3) + zod: 3.25.7 + zod@3.22.3: {} - zod@3.24.4: {} + zod@3.25.7: {} diff --git a/vite.config.ts b/vite.config.ts index 677015b..1251947 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,6 +5,14 @@ import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; export default defineConfig({ + server: { + // 监听所有IP地址 + host: "0.0.0.0", + // 指定dev sever的端口号,默认为 5173 + port: 3000, + // 自动打开浏览器运行以下路径的页面 + open: "/", + }, plugins: [ cloudflare({ viteEnvironment: { name: "ssr" }, diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index 0483181..10f0de2 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -1,16 +1,16 @@ /* eslint-disable */ -// Generated by Wrangler by running `wrangler types` (hash: b9e4888a7a07f84c0197fe92f56decf1) -// Runtime types generated with workerd@1.20250507.0 2025-04-04 nodejs_compat,nodejs_compat_populate_process_env +// Generated by Wrangler by running `wrangler types` (hash: e19c972b62f0b7d9a8b219313c43dfbf) +// Runtime types generated with workerd@1.20250508.0 2025-04-15 nodejs_compat,nodejs_compat_populate_process_env declare namespace Cloudflare { interface Env { - APP_KV: KVNamespace; - ENVIRONMENT: string; - BETTER_AUTH_SECRET: string; - BETTER_AUTH_URL: string; - GITHUB_CLIENT_ID: string; - GITHUB_CLIENT_SECRET: string; - GOOGLE_CLIENT_ID: string; - GOOGLE_CLIENT_SECRET: string; + APP_KV: KVNamespace; + ENVIRONMENT: string; + BETTER_AUTH_SECRET: string; + BETTER_AUTH_URL: string; + GITHUB_CLIENT_ID: string; + GITHUB_CLIENT_SECRET: string; + GOOGLE_CLIENT_ID: string; + GOOGLE_CLIENT_SECRET: string; R2: R2Bucket; DB: D1Database; } @@ -20,7 +20,7 @@ type StringifyValues> = { [Binding in keyof EnvType]: EnvType[Binding] extends string ? EnvType[Binding] : string; }; declare namespace NodeJS { - interface ProcessEnv extends StringifyValues> {} + interface ProcessEnv extends StringifyValues> {} } // Begin runtime types @@ -4595,7 +4595,7 @@ interface IncomingRequestCfPropertiesTLSClientAuthPlaceholder { certNotAfter: ""; } /** Possible outcomes of TLS verification */ -declare type CertVerificationStatus = +declare type CertVerificationStatus = /** Authentication succeeded */ "SUCCESS" /** No certificate was presented */ @@ -4654,7 +4654,7 @@ interface D1ExecResult { count: number; duration: number; } -type D1SessionConstraint = +type D1SessionConstraint = // Indicates that the first query should go to the primary, and the rest queries // using the same D1DatabaseSession will go to any replica that is consistent with // the bookmark maintained by the session (returned by the first query). @@ -5092,7 +5092,7 @@ declare namespace Rpc { // The reason for using a generic type here is to build a serializable subset of structured // cloneable composite types. This allows types defined with the "interface" keyword to pass the // serializable check as well. Otherwise, only types defined with the "type" keyword would pass. - type Serializable = + type Serializable = // Structured cloneables BaseType // Structured cloneable composites @@ -5347,8 +5347,8 @@ declare namespace TailStream { } interface SpanOpen { readonly type: "spanOpen"; - readonly op?: string; - readonly info?: FetchEventInfo | JsRpcEventInfo | Attribute[]; + readonly name: string; + readonly info?: FetchEventInfo | JsRpcEventInfo | Attributes; } interface SpanClose { readonly type: "spanClose"; @@ -5372,7 +5372,7 @@ declare namespace TailStream { } interface Return { readonly type: "return"; - readonly info?: FetchResponseInfo | Attribute[]; + readonly info?: FetchResponseInfo | Attributes; } interface Link { readonly type: "link"; @@ -5382,21 +5382,23 @@ declare namespace TailStream { readonly spanId: string; } interface Attribute { - readonly type: "attribute"; readonly name: string; - readonly value: string | string[] | boolean | boolean[] | number | number[]; + readonly value: string | string[] | boolean | boolean[] | number | number[] | bigint | bigint[]; + } + interface Attributes { + readonly type: "attributes"; + readonly info: Attribute[]; } - type Mark = DiagnosticChannelEvent | Exception | Log | Return | Link | Attribute[]; interface TailEvent { readonly traceId: string; readonly invocationId: string; readonly spanId: string; readonly timestamp: Date; readonly sequence: number; - readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | Mark; + readonly event: Onset | Outcome | Hibernate | SpanOpen | SpanClose | DiagnosticChannelEvent | Exception | Log | Return | Link | Attributes; } type TailEventHandler = (event: TailEvent) => void | Promise; - type TailEventHandlerName = "onset" | "outcome" | "hibernate" | "spanOpen" | "spanClose" | "diagnosticChannel" | "exception" | "log" | "return" | "link" | "attribute"; + type TailEventHandlerName = "outcome" | "hibernate" | "spanOpen" | "spanClose" | "diagnosticChannel" | "exception" | "log" | "return" | "link" | "attributes"; type TailEventHandlerObject = Record; type TailEventHandlerType = TailEventHandler | TailEventHandlerObject; } diff --git a/wrangler.jsonc b/wrangler.example.jsonc similarity index 100% rename from wrangler.jsonc rename to wrangler.example.jsonc