diff --git a/ui/package-lock.json b/ui/package-lock.json index 9304cec..13c6e99 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "kvm-ui", - "version": "2025.09.03.1500", + "version": "2025.09.03.2100", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kvm-ui", - "version": "2025.09.03.1500", + "version": "2025.09.03.2100", "dependencies": { "@headlessui/react": "^2.2.7", "@headlessui/tailwindcss": "^0.2.2", @@ -30,7 +30,7 @@ "react-dom": "^19.1.1", "react-hot-toast": "^2.6.0", "react-icons": "^5.5.0", - "react-router-dom": "^6.22.3", + "react-router": "^7.8.2", "react-simple-keyboard": "^3.8.119", "react-use-websocket": "^4.13.0", "react-xtermjs": "^1.0.10", @@ -54,7 +54,7 @@ "@types/validator": "^13.15.3", "@typescript-eslint/eslint-plugin": "^8.42.0", "@typescript-eslint/parser": "^8.42.0", - "@vitejs/plugin-react-swc": "^3.10.2", + "@vitejs/plugin-react-swc": "^4.0.1", "autoprefixer": "^10.4.21", "eslint": "^9.34.0", "eslint-config-prettier": "^10.1.8", @@ -68,7 +68,7 @@ "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^4.1.12", "typescript": "^5.9.2", - "vite": "^6.3.5", + "vite": "^7.1.4", "vite-tsconfig-paths": "^5.1.4" }, "engines": { @@ -1019,19 +1019,10 @@ } } }, - "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "version": "1.0.0-beta.32", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz", + "integrity": "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==", "dev": true, "license": "MIT" }, @@ -2311,14 +2302,17 @@ } }, "node_modules/@vitejs/plugin-react-swc": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz", - "integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.0.1.tgz", + "integrity": "sha512-NQhPjysi5duItyrMd5JWZFf2vNOuSMyw+EoZyTBDzk+DkfYD8WNrsUs09sELV2cr1P15nufsN25hsUBt4CKF9Q==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.27", - "@swc/core": "^1.12.11" + "@rolldown/pluginutils": "1.0.0-beta.32", + "@swc/core": "^1.13.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7" @@ -2850,6 +2844,15 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -5881,35 +5884,25 @@ } }, "node_modules/react-router": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", - "integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz", + "integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.0" + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" }, "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.30.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.1.tgz", - "integrity": "sha512-llKsgOkZdbPU1Eg3zK8lCn+sjD9wMRZZPuzmdWWX5SUs8OFkN5HnFVC0u5KMeMaC9aoancFI/KoLuKPqN+hxHw==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.0", - "react-router": "6.30.1" + "react": ">=18", + "react-dom": ">=18" }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } } }, "node_modules/react-simple-keyboard": { @@ -6202,6 +6195,12 @@ "node": ">=10" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6894,23 +6893,23 @@ } }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.4.tgz", + "integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==", "license": "MIT", "dependencies": { "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.14" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -6919,14 +6918,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" diff --git a/ui/package.json b/ui/package.json index 923bf57..4c98825 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,7 +1,7 @@ { "name": "kvm-ui", "private": true, - "version": "2025.09.03.1500", + "version": "2025.09.03.2100", "type": "module", "engines": { "node": "22.15.0" @@ -41,7 +41,7 @@ "react-dom": "^19.1.1", "react-hot-toast": "^2.6.0", "react-icons": "^5.5.0", - "react-router-dom": "^6.22.3", + "react-router": "^7.8.2", "react-simple-keyboard": "^3.8.119", "react-use-websocket": "^4.13.0", "react-xtermjs": "^1.0.10", @@ -65,7 +65,7 @@ "@types/validator": "^13.15.3", "@typescript-eslint/eslint-plugin": "^8.42.0", "@typescript-eslint/parser": "^8.42.0", - "@vitejs/plugin-react-swc": "^3.10.2", + "@vitejs/plugin-react-swc": "^4.0.1", "autoprefixer": "^10.4.21", "eslint": "^9.34.0", "eslint-config-prettier": "^10.1.8", @@ -79,7 +79,7 @@ "prettier-plugin-tailwindcss": "^0.6.14", "tailwindcss": "^4.1.12", "typescript": "^5.9.2", - "vite": "^6.3.5", + "vite": "^7.1.4", "vite-tsconfig-paths": "^5.1.4" } } diff --git a/ui/src/components/AuthLayout.tsx b/ui/src/components/AuthLayout.tsx index 6c6d5da..7d66e95 100644 --- a/ui/src/components/AuthLayout.tsx +++ b/ui/src/components/AuthLayout.tsx @@ -1,4 +1,4 @@ -import { useLocation, useNavigation, useSearchParams } from "react-router-dom"; +import { useLocation, useNavigation, useSearchParams } from "react-router"; import { Button, LinkButton } from "@components/Button"; import { GoogleIcon } from "@components/Icons"; diff --git a/ui/src/components/Button.tsx b/ui/src/components/Button.tsx index b7f0950..b1dc3ab 100644 --- a/ui/src/components/Button.tsx +++ b/ui/src/components/Button.tsx @@ -1,5 +1,6 @@ import React, { JSX } from "react"; -import { FetcherWithComponents, Link, LinkProps, useNavigation } from "react-router-dom"; +import { Link, useNavigation } from "react-router"; +import type { FetcherWithComponents, LinkProps } from "react-router"; import ExtLink from "@/components/ExtLink"; import LoadingSpinner from "@/components/LoadingSpinner"; diff --git a/ui/src/components/Fieldset.tsx b/ui/src/components/Fieldset.tsx index 9a37e79..06b7ab9 100644 --- a/ui/src/components/Fieldset.tsx +++ b/ui/src/components/Fieldset.tsx @@ -1,6 +1,7 @@ import React from "react"; import clsx from "clsx"; -import { FetcherWithComponents, useNavigation } from "react-router-dom"; +import { useNavigation } from "react-router"; +import type { FetcherWithComponents } from "react-router"; export default function Fieldset({ children, diff --git a/ui/src/components/Header.tsx b/ui/src/components/Header.tsx index 4bb7a97..a290114 100644 --- a/ui/src/components/Header.tsx +++ b/ui/src/components/Header.tsx @@ -1,5 +1,5 @@ import { useCallback } from "react"; -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router"; import { ArrowLeftEndOnRectangleIcon, ChevronDownIcon } from "@heroicons/react/16/solid"; import { Button, Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react"; import { LuMonitorSmartphone } from "react-icons/lu"; diff --git a/ui/src/components/KvmCard.tsx b/ui/src/components/KvmCard.tsx index 91296c5..7ef8712 100644 --- a/ui/src/components/KvmCard.tsx +++ b/ui/src/components/KvmCard.tsx @@ -1,6 +1,6 @@ import { MdConnectWithoutContact } from "react-icons/md"; import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react"; -import { Link } from "react-router-dom"; +import { Link } from "react-router"; import { LuEllipsisVertical } from "react-icons/lu"; import Card from "@components/Card"; diff --git a/ui/src/components/SimpleNavbar.tsx b/ui/src/components/SimpleNavbar.tsx index 7652ad0..1e1c19e 100644 --- a/ui/src/components/SimpleNavbar.tsx +++ b/ui/src/components/SimpleNavbar.tsx @@ -1,4 +1,4 @@ -import { Link } from "react-router-dom"; +import { Link } from "react-router"; import React from "react"; import Container from "@/components/Container"; diff --git a/ui/src/components/popovers/MountPopover.tsx b/ui/src/components/popovers/MountPopover.tsx index 1381293..8b6a8a5 100644 --- a/ui/src/components/popovers/MountPopover.tsx +++ b/ui/src/components/popovers/MountPopover.tsx @@ -6,7 +6,7 @@ import { LuRadioReceiver, } from "react-icons/lu"; import { useClose } from "@headlessui/react"; -import { useLocation } from "react-router-dom"; +import { useLocation } from "react-router"; import { Button } from "@components/Button"; import Card, { GridCard } from "@components/Card"; diff --git a/ui/src/hooks/useAppNavigation.ts b/ui/src/hooks/useAppNavigation.ts index 6c9270a..af9a247 100644 --- a/ui/src/hooks/useAppNavigation.ts +++ b/ui/src/hooks/useAppNavigation.ts @@ -1,4 +1,5 @@ -import { useNavigate, useParams, NavigateOptions } from "react-router-dom"; +import { useNavigate, useParams } from "react-router"; +import type { NavigateOptions } from "react-router"; import { useCallback, useMemo } from "react"; import { isOnDevice } from "../main"; diff --git a/ui/src/main.tsx b/ui/src/main.tsx index 5374658..87b3b18 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -7,7 +7,7 @@ import { redirect, RouterProvider, useRouteError, -} from "react-router-dom"; +} from "react-router"; import { ExclamationTriangleIcon } from "@heroicons/react/16/solid"; import { CLOUD_API, DEVICE_API } from "@/ui.config"; @@ -28,7 +28,7 @@ import DeviceIdRename from "@routes/devices.$id.rename"; import DevicesRoute from "@routes/devices"; import SettingsIndexRoute from "@routes/devices.$id.settings._index"; import SettingsAccessIndexRoute from "@routes/devices.$id.settings.access._index"; -const Notifications = lazy(() => import("@/notifications")); +import Notifications from "@/notifications"; const SignupRoute = lazy(() => import("@routes/signup")); const LoginRoute = lazy(() => import("@routes/login")); const DevicesAlreadyAdopted = lazy(() => import("@routes/devices.already-adopted")); diff --git a/ui/src/root.tsx b/ui/src/root.tsx index 9413055..8995fd9 100644 --- a/ui/src/root.tsx +++ b/ui/src/root.tsx @@ -1,4 +1,4 @@ -import { Outlet } from "react-router-dom"; +import { Outlet } from "react-router"; function Root() { return ; diff --git a/ui/src/routes/adopt.tsx b/ui/src/routes/adopt.tsx index 8b8325b..b7079f5 100644 --- a/ui/src/routes/adopt.tsx +++ b/ui/src/routes/adopt.tsx @@ -1,8 +1,8 @@ -import { LoaderFunctionArgs, redirect } from "react-router-dom"; +import { redirect } from "react-router"; +import type { LoaderFunction, LoaderFunctionArgs } from "react-router"; import { DEVICE_API } from "@/ui.config"; - -import api from "../api"; +import api from "@/api"; export interface CloudState { connected: boolean; @@ -10,7 +10,7 @@ export interface CloudState { appUrl: string; } -const loader = async ({ request }: LoaderFunctionArgs) => { +const loader: LoaderFunction = async ({ request }: LoaderFunctionArgs) => { const url = new URL(request.url); const searchParams = url.searchParams; @@ -37,7 +37,7 @@ const loader = async ({ request }: LoaderFunctionArgs) => { }; export default function AdoptRoute() { - return <>; + return (<>); } AdoptRoute.loader = loader; diff --git a/ui/src/routes/devices.$id.deregister.tsx b/ui/src/routes/devices.$id.deregister.tsx index 8c0a87f..e5dd2a3 100644 --- a/ui/src/routes/devices.$id.deregister.tsx +++ b/ui/src/routes/devices.$id.deregister.tsx @@ -1,11 +1,5 @@ -import { - ActionFunctionArgs, - Form, - LoaderFunctionArgs, - redirect, - useActionData, - useLoaderData, -} from "react-router-dom"; +import { Form, redirect, useActionData, useLoaderData } from "react-router"; +import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "react-router"; import { ChevronLeftIcon } from "@heroicons/react/16/solid"; import { Button, LinkButton } from "@components/Button"; @@ -22,7 +16,7 @@ interface LoaderData { user: User; } -const action = async ({ request }: ActionFunctionArgs) => { +const action: ActionFunction = async ({ request }: ActionFunctionArgs) => { const { deviceId } = Object.fromEntries(await request.formData()); try { @@ -34,17 +28,17 @@ const action = async ({ request }: ActionFunctionArgs) => { }); if (!res.ok) { - return { message: "There was an error renaming your device. Please try again." }; + return { message: "There was an error deregistering your device. Please try again." }; } } catch (e) { console.error(e); - return { message: "There was an error renaming your device. Please try again." }; + return { message: "There was an error deregistering your device. Please try again." }; } return redirect("/devices"); }; -const loader = async ({ params }: LoaderFunctionArgs) => { +const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => { const user = await checkAuth(); const { id } = params; diff --git a/ui/src/routes/devices.$id.mount.tsx b/ui/src/routes/devices.$id.mount.tsx index 68979be..c62308d 100644 --- a/ui/src/routes/devices.$id.mount.tsx +++ b/ui/src/routes/devices.$id.mount.tsx @@ -7,7 +7,7 @@ import { } from "react-icons/lu"; import { PlusCircleIcon, ExclamationTriangleIcon } from "@heroicons/react/20/solid"; import { TrashIcon } from "@heroicons/react/16/solid"; -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router"; import Card, { GridCard } from "@/components/Card"; import { Button } from "@components/Button"; diff --git a/ui/src/routes/devices.$id.other-session.tsx b/ui/src/routes/devices.$id.other-session.tsx index 16cb479..8a767d5 100644 --- a/ui/src/routes/devices.$id.other-session.tsx +++ b/ui/src/routes/devices.$id.other-session.tsx @@ -1,4 +1,4 @@ -import { useNavigate, useOutletContext } from "react-router-dom"; +import { useNavigate, useOutletContext } from "react-router"; import { GridCard } from "@/components/Card"; import { Button } from "@components/Button"; diff --git a/ui/src/routes/devices.$id.rename.tsx b/ui/src/routes/devices.$id.rename.tsx index 2852561..39f06bc 100644 --- a/ui/src/routes/devices.$id.rename.tsx +++ b/ui/src/routes/devices.$id.rename.tsx @@ -1,11 +1,5 @@ -import { - ActionFunctionArgs, - Form, - LoaderFunctionArgs, - redirect, - useActionData, - useLoaderData, -} from "react-router-dom"; +import { Form, redirect, useActionData, useLoaderData } from "react-router"; +import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "react-router"; import { ChevronLeftIcon } from "@heroicons/react/16/solid"; import { Button, LinkButton } from "@components/Button"; @@ -25,7 +19,7 @@ interface LoaderData { user: User; } -const action = async ({ params, request }: ActionFunctionArgs) => { +const action: ActionFunction = async ({ params, request }: ActionFunctionArgs) => { const { id } = params; const { name } = Object.fromEntries(await request.formData()); @@ -48,7 +42,7 @@ const action = async ({ params, request }: ActionFunctionArgs) => { return redirect("/devices"); }; -const loader = async ({ params }: LoaderFunctionArgs) => { +const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => { const user = await checkAuth(); const { id } = params; diff --git a/ui/src/routes/devices.$id.settings._index.tsx b/ui/src/routes/devices.$id.settings._index.tsx index 4fb35ed..e4a9d7f 100644 --- a/ui/src/routes/devices.$id.settings._index.tsx +++ b/ui/src/routes/devices.$id.settings._index.tsx @@ -1,8 +1,9 @@ -import { LoaderFunctionArgs, redirect } from "react-router-dom"; +import { redirect } from "react-router"; +import type { LoaderFunction, LoaderFunctionArgs } from "react-router"; import { getDeviceUiPath } from "../hooks/useAppNavigation"; -const loader = ({ params }: LoaderFunctionArgs) => { +const loader: LoaderFunction = ({ params }: LoaderFunctionArgs) => { return redirect(getDeviceUiPath("/settings/general", params.id)); } diff --git a/ui/src/routes/devices.$id.settings.access._index.tsx b/ui/src/routes/devices.$id.settings.access._index.tsx index 31b7bb7..b5ccca0 100644 --- a/ui/src/routes/devices.$id.settings.access._index.tsx +++ b/ui/src/routes/devices.$id.settings.access._index.tsx @@ -1,4 +1,5 @@ -import { useLoaderData, useNavigate } from "react-router-dom"; +import { useLoaderData, useNavigate } from "react-router"; +import type { LoaderFunction } from "react-router"; import { ShieldCheckIcon } from "@heroicons/react/24/outline"; import { useCallback, useEffect, useState } from "react"; @@ -26,7 +27,7 @@ export interface TLSState { privateKey?: string; } -const loader = async () => { +const loader: LoaderFunction = async () => { if (isOnDevice) { const status = await api .GET(`${DEVICE_API}/device`) diff --git a/ui/src/routes/devices.$id.settings.access.local-auth.tsx b/ui/src/routes/devices.$id.settings.access.local-auth.tsx index 50b2cc4..5f5231d 100644 --- a/ui/src/routes/devices.$id.settings.access.local-auth.tsx +++ b/ui/src/routes/devices.$id.settings.access.local-auth.tsx @@ -1,5 +1,5 @@ import { useState, useEffect } from "react"; -import { useLocation, useRevalidator } from "react-router-dom"; +import { useLocation, useRevalidator } from "react-router"; import { Button } from "@components/Button"; import { InputFieldWithLabel } from "@/components/InputField"; diff --git a/ui/src/routes/devices.$id.settings.general.reboot.tsx b/ui/src/routes/devices.$id.settings.general.reboot.tsx index 0bf114c..db0e053 100644 --- a/ui/src/routes/devices.$id.settings.general.reboot.tsx +++ b/ui/src/routes/devices.$id.settings.general.reboot.tsx @@ -1,4 +1,4 @@ -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router"; import { useCallback } from "react"; import { useJsonRpc } from "@/hooks/useJsonRpc"; diff --git a/ui/src/routes/devices.$id.settings.general.update.tsx b/ui/src/routes/devices.$id.settings.general.update.tsx index b719d7e..80ba0f7 100644 --- a/ui/src/routes/devices.$id.settings.general.update.tsx +++ b/ui/src/routes/devices.$id.settings.general.update.tsx @@ -1,4 +1,4 @@ -import { useLocation, useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router"; import { useCallback, useEffect, useRef, useState } from "react"; import { CheckCircleIcon } from "@heroicons/react/20/solid"; diff --git a/ui/src/routes/devices.$id.settings.macros.add.tsx b/ui/src/routes/devices.$id.settings.macros.add.tsx index 1b3ce30..7a9f493 100644 --- a/ui/src/routes/devices.$id.settings.macros.add.tsx +++ b/ui/src/routes/devices.$id.settings.macros.add.tsx @@ -1,4 +1,4 @@ -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router"; import { useState } from "react"; import { KeySequence, useMacrosStore, generateMacroId } from "@/hooks/stores"; diff --git a/ui/src/routes/devices.$id.settings.macros.edit.tsx b/ui/src/routes/devices.$id.settings.macros.edit.tsx index 336fe85..131fa1c 100644 --- a/ui/src/routes/devices.$id.settings.macros.edit.tsx +++ b/ui/src/routes/devices.$id.settings.macros.edit.tsx @@ -1,4 +1,4 @@ -import { useNavigate, useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router"; import { useState, useEffect } from "react"; import { LuTrash2 } from "react-icons/lu"; diff --git a/ui/src/routes/devices.$id.settings.macros.tsx b/ui/src/routes/devices.$id.settings.macros.tsx index 734f17e..94fded3 100644 --- a/ui/src/routes/devices.$id.settings.macros.tsx +++ b/ui/src/routes/devices.$id.settings.macros.tsx @@ -1,5 +1,5 @@ import { useEffect, Fragment, useMemo, useState, useCallback } from "react"; -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router"; import { LuPenLine, LuCopy, diff --git a/ui/src/routes/devices.$id.settings.tsx b/ui/src/routes/devices.$id.settings.tsx index 5a61778..49f2636 100644 --- a/ui/src/routes/devices.$id.settings.tsx +++ b/ui/src/routes/devices.$id.settings.tsx @@ -1,4 +1,4 @@ -import { NavLink, Outlet, useLocation } from "react-router-dom"; +import { NavLink, Outlet, useLocation } from "react-router"; import { LuSettings, LuMouse, diff --git a/ui/src/routes/devices.$id.setup.tsx b/ui/src/routes/devices.$id.setup.tsx index 1c477d6..2fd65f5 100644 --- a/ui/src/routes/devices.$id.setup.tsx +++ b/ui/src/routes/devices.$id.setup.tsx @@ -1,12 +1,5 @@ -import { - ActionFunctionArgs, - Form, - LoaderFunctionArgs, - redirect, - useActionData, - useParams, - useSearchParams, -} from "react-router-dom"; +import { Form, redirect, useActionData, useParams, useSearchParams } from "react-router"; +import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "react-router"; import SimpleNavbar from "@components/SimpleNavbar"; import GridBackground from "@components/GridBackground"; @@ -20,7 +13,7 @@ import { CLOUD_API } from "@/ui.config"; import api from "../api"; -const loader = async ({ params }: LoaderFunctionArgs) => { +const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => { await checkAuth(); const res = await fetch(`${CLOUD_API}/devices/${params.id}`, { method: "GET", @@ -35,7 +28,7 @@ const loader = async ({ params }: LoaderFunctionArgs) => { } }; -const action = async ({ request }: ActionFunctionArgs) => { +const action: ActionFunction = async ({ request }: ActionFunctionArgs) => { // Handle form submission const { name, id, returnTo } = Object.fromEntries(await request.formData()); const res = await api.PUT(`${CLOUD_API}/devices/${id}`, { name }); @@ -43,7 +36,7 @@ const action = async ({ request }: ActionFunctionArgs) => { if (res.ok) { return redirect(returnTo?.toString() ?? `/devices/${id}`); } else { - return { error: "There was an error creating your device" }; + return { error: "There was an error registering your device" }; } }; diff --git a/ui/src/routes/devices.$id.tsx b/ui/src/routes/devices.$id.tsx index 9be05f6..a60c39a 100644 --- a/ui/src/routes/devices.$id.tsx +++ b/ui/src/routes/devices.$id.tsx @@ -1,8 +1,6 @@ import { lazy, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { - LoaderFunctionArgs, Outlet, - Params, redirect, useLoaderData, useLocation, @@ -10,7 +8,8 @@ import { useOutlet, useParams, useSearchParams, -} from "react-router-dom"; +} from "react-router"; +import type { LoaderFunction, LoaderFunctionArgs, Params } from "react-router"; import { useInterval } from "usehooks-ts"; import { FocusTrap } from "focus-trap-react"; import { motion, AnimatePresence } from "framer-motion"; @@ -112,7 +111,7 @@ const cloudLoader = async (params: Params): Promise => return { user, iceConfig, deviceName: device.name || device.id }; }; -const loader = ({ params }: LoaderFunctionArgs) => { +const loader: LoaderFunction = ({ params }: LoaderFunctionArgs) => { return import.meta.env.MODE === "device" ? deviceLoader() : cloudLoader(params); }; diff --git a/ui/src/routes/devices.tsx b/ui/src/routes/devices.tsx index b6af0f0..1dac696 100644 --- a/ui/src/routes/devices.tsx +++ b/ui/src/routes/devices.tsx @@ -1,4 +1,5 @@ -import { useLoaderData, useRevalidator } from "react-router-dom"; +import { useLoaderData, useRevalidator } from "react-router"; +import type { LoaderFunction } from "react-router"; import { LuMonitorSmartphone } from "react-icons/lu"; import { ArrowRightIcon } from "@heroicons/react/16/solid"; import { useInterval } from "usehooks-ts"; @@ -16,7 +17,7 @@ interface LoaderData { user: User; } -const loader = async () => { +const loader: LoaderFunction = async () => { const user = await checkAuth(); try { diff --git a/ui/src/routes/login-local.tsx b/ui/src/routes/login-local.tsx index b2b189c..5fab7e6 100644 --- a/ui/src/routes/login-local.tsx +++ b/ui/src/routes/login-local.tsx @@ -1,4 +1,5 @@ -import { ActionFunctionArgs, Form, redirect, useActionData } from "react-router-dom"; +import { Form, redirect, useActionData } from "react-router"; +import type { ActionFunction, ActionFunctionArgs, LoaderFunction } from "react-router"; import { useState } from "react"; import { LuEye, LuEyeOff } from "react-icons/lu"; @@ -17,7 +18,7 @@ import ExtLink from "../components/ExtLink"; import { DeviceStatus } from "./welcome-local"; -const loader = async () => { +const loader: LoaderFunction = async () => { const res = await api .GET(`${DEVICE_API}/device/status`) .then(res => res.json() as Promise); @@ -29,7 +30,7 @@ const loader = async () => { return null; }; -const action = async ({ request }: ActionFunctionArgs) => { +const action: ActionFunction = async ({ request }: ActionFunctionArgs) => { const formData = await request.formData(); const password = formData.get("password"); diff --git a/ui/src/routes/login.tsx b/ui/src/routes/login.tsx index e2347a7..fb0f0c4 100644 --- a/ui/src/routes/login.tsx +++ b/ui/src/routes/login.tsx @@ -1,4 +1,4 @@ -import { useLocation, useSearchParams } from "react-router-dom"; +import { useLocation, useSearchParams } from "react-router"; import AuthLayout from "@components/AuthLayout"; diff --git a/ui/src/routes/signup.tsx b/ui/src/routes/signup.tsx index af06400..c6efbcb 100644 --- a/ui/src/routes/signup.tsx +++ b/ui/src/routes/signup.tsx @@ -1,4 +1,4 @@ -import { useLocation, useSearchParams } from "react-router-dom"; +import { useLocation, useSearchParams } from "react-router"; import AuthLayout from "@components/AuthLayout"; diff --git a/ui/src/routes/welcome-local.mode.tsx b/ui/src/routes/welcome-local.mode.tsx index 06ca62a..8d1a808 100644 --- a/ui/src/routes/welcome-local.mode.tsx +++ b/ui/src/routes/welcome-local.mode.tsx @@ -1,4 +1,5 @@ -import { ActionFunctionArgs, Form, redirect, useActionData } from "react-router-dom"; +import { Form, redirect, useActionData } from "react-router"; +import type { ActionFunction, ActionFunctionArgs, LoaderFunction } from "react-router"; import { useState } from "react"; import GridBackground from "@components/GridBackground"; @@ -14,7 +15,7 @@ import api from "../api"; import { DeviceStatus } from "./welcome-local"; -const loader = async () => { +const loader: LoaderFunction = async () => { const res = await api .GET(`${DEVICE_API}/device/status`) .then(res => res.json() as Promise); @@ -23,7 +24,7 @@ const loader = async () => { return null; }; -const action = async ({ request }: ActionFunctionArgs) => { +const action: ActionFunction = async ({ request }: ActionFunctionArgs) => { const formData = await request.formData(); const localAuthMode = formData.get("localAuthMode"); if (!localAuthMode) return { error: "Please select an authentication mode" }; @@ -162,5 +163,5 @@ export default function WelcomeLocalModeRoute() { ); } -WelcomeLocalModeRoute.action = action; WelcomeLocalModeRoute.loader = loader; +WelcomeLocalModeRoute.action = action; diff --git a/ui/src/routes/welcome-local.password.tsx b/ui/src/routes/welcome-local.password.tsx index 4b2c05d..d0b7c7a 100644 --- a/ui/src/routes/welcome-local.password.tsx +++ b/ui/src/routes/welcome-local.password.tsx @@ -1,4 +1,5 @@ -import { ActionFunctionArgs, Form, redirect, useActionData } from "react-router-dom"; +import { Form, redirect, useActionData } from "react-router"; +import type { ActionFunction, ActionFunctionArgs, LoaderFunction } from "react-router"; import { useState, useRef, useEffect } from "react"; import { LuEye, LuEyeOff } from "react-icons/lu"; @@ -15,7 +16,7 @@ import api from "../api"; import { DeviceStatus } from "./welcome-local"; -const loader = async () => { +const loader: LoaderFunction = async () => { const res = await api .GET(`${DEVICE_API}/device/status`) .then(res => res.json() as Promise); @@ -24,7 +25,7 @@ const loader = async () => { return null; }; -const action = async ({ request }: ActionFunctionArgs) => { +const action: ActionFunction = async ({ request }: ActionFunctionArgs) => { const formData = await request.formData(); const password = formData.get("password"); const confirmPassword = formData.get("confirmPassword"); @@ -174,5 +175,5 @@ export default function WelcomeLocalPasswordRoute() { ); } -WelcomeLocalPasswordRoute.action = action; WelcomeLocalPasswordRoute.loader = loader; +WelcomeLocalPasswordRoute.action = action; diff --git a/ui/src/routes/welcome-local.tsx b/ui/src/routes/welcome-local.tsx index c516952..d7ff117 100644 --- a/ui/src/routes/welcome-local.tsx +++ b/ui/src/routes/welcome-local.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import { cx } from "cva"; -import { redirect } from "react-router-dom"; +import { redirect } from "react-router"; +import type { LoaderFunction } from "react-router"; import GridBackground from "@components/GridBackground"; import Container from "@components/Container"; @@ -17,7 +18,7 @@ export interface DeviceStatus { isSetup: boolean; } -const loader = async () => { +const loader: LoaderFunction = async () => { const res = await api .GET(`${DEVICE_API}/device/status`) .then(res => res.json() as Promise);