Upgrade vite and react-router (#778)

| Package                           | From | To       |
|----------------------------------|-----------|---------|
react-router                       | ( new ) | 7.8.2 |
react-router-dom             | 6.22.3 | ( del ) |
@vitejs/plugin-react-swc | 3.10.2 | 4.0.1 |
vite                                      | 6.3.5   | 7.1.4 |
This commit is contained in:
Marc Brooks 2025-09-04 05:20:01 -05:00 committed by GitHub
parent 1dda6184da
commit 5f3dd89d55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 136 additions and 147 deletions

117
ui/package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "kvm-ui", "name": "kvm-ui",
"version": "2025.09.03.1500", "version": "2025.09.03.2100",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "kvm-ui", "name": "kvm-ui",
"version": "2025.09.03.1500", "version": "2025.09.03.2100",
"dependencies": { "dependencies": {
"@headlessui/react": "^2.2.7", "@headlessui/react": "^2.2.7",
"@headlessui/tailwindcss": "^0.2.2", "@headlessui/tailwindcss": "^0.2.2",
@ -30,7 +30,7 @@
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-hot-toast": "^2.6.0", "react-hot-toast": "^2.6.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-router-dom": "^6.22.3", "react-router": "^7.8.2",
"react-simple-keyboard": "^3.8.119", "react-simple-keyboard": "^3.8.119",
"react-use-websocket": "^4.13.0", "react-use-websocket": "^4.13.0",
"react-xtermjs": "^1.0.10", "react-xtermjs": "^1.0.10",
@ -54,7 +54,7 @@
"@types/validator": "^13.15.3", "@types/validator": "^13.15.3",
"@typescript-eslint/eslint-plugin": "^8.42.0", "@typescript-eslint/eslint-plugin": "^8.42.0",
"@typescript-eslint/parser": "^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", "autoprefixer": "^10.4.21",
"eslint": "^9.34.0", "eslint": "^9.34.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
@ -68,7 +68,7 @@
"prettier-plugin-tailwindcss": "^0.6.14", "prettier-plugin-tailwindcss": "^0.6.14",
"tailwindcss": "^4.1.12", "tailwindcss": "^4.1.12",
"typescript": "^5.9.2", "typescript": "^5.9.2",
"vite": "^6.3.5", "vite": "^7.1.4",
"vite-tsconfig-paths": "^5.1.4" "vite-tsconfig-paths": "^5.1.4"
}, },
"engines": { "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": { "node_modules/@rolldown/pluginutils": {
"version": "1.0.0-beta.27", "version": "1.0.0-beta.32",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.32.tgz",
"integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", "integrity": "sha512-QReCdvxiUZAPkvp1xpAg62IeNzykOFA6syH2CnClif4YmALN1XKpB39XneL80008UbtMShthSVDKmrx05N1q/g==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@ -2311,14 +2302,17 @@
} }
}, },
"node_modules/@vitejs/plugin-react-swc": { "node_modules/@vitejs/plugin-react-swc": {
"version": "3.11.0", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.0.1.tgz",
"integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==", "integrity": "sha512-NQhPjysi5duItyrMd5JWZFf2vNOuSMyw+EoZyTBDzk+DkfYD8WNrsUs09sELV2cr1P15nufsN25hsUBt4CKF9Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@rolldown/pluginutils": "1.0.0-beta.27", "@rolldown/pluginutils": "1.0.0-beta.32",
"@swc/core": "^1.12.11" "@swc/core": "^1.13.2"
},
"engines": {
"node": "^20.19.0 || >=22.12.0"
}, },
"peerDependencies": { "peerDependencies": {
"vite": "^4 || ^5 || ^6 || ^7" "vite": "^4 || ^5 || ^6 || ^7"
@ -2850,6 +2844,15 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"license": "MIT" "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": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -5881,35 +5884,25 @@
} }
}, },
"node_modules/react-router": { "node_modules/react-router": {
"version": "6.30.1", "version": "7.8.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.1.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.2.tgz",
"integrity": "sha512-X1m21aEmxGXqENEPG3T6u0Th7g0aS4ZmoNynhbs+Cn+q+QGTLt+d5IQ2bHAXKzKcxGJjxACpVbnYQSCRcfxHlQ==", "integrity": "sha512-7M2fR1JbIZ/jFWqelpvSZx+7vd7UlBTfdZqf6OSdF9g6+sfdqJDAWcak6ervbHph200ePlu+7G8LdoiC3ReyAQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@remix-run/router": "1.23.0" "cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=20.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": ">=16.8" "react": ">=18",
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
} }
},
"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"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8"
} }
}, },
"node_modules/react-simple-keyboard": { "node_modules/react-simple-keyboard": {
@ -6202,6 +6195,12 @@
"node": ">=10" "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": { "node_modules/set-function-length": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@ -6894,23 +6893,23 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "6.3.5", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.4.tgz",
"integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.4.4", "fdir": "^6.5.0",
"picomatch": "^4.0.2", "picomatch": "^4.0.3",
"postcss": "^8.5.3", "postcss": "^8.5.6",
"rollup": "^4.34.9", "rollup": "^4.43.0",
"tinyglobby": "^0.2.13" "tinyglobby": "^0.2.14"
}, },
"bin": { "bin": {
"vite": "bin/vite.js" "vite": "bin/vite.js"
}, },
"engines": { "engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0" "node": "^20.19.0 || >=22.12.0"
}, },
"funding": { "funding": {
"url": "https://github.com/vitejs/vite?sponsor=1" "url": "https://github.com/vitejs/vite?sponsor=1"
@ -6919,14 +6918,14 @@
"fsevents": "~2.3.3" "fsevents": "~2.3.3"
}, },
"peerDependencies": { "peerDependencies": {
"@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node": "^20.19.0 || >=22.12.0",
"jiti": ">=1.21.0", "jiti": ">=1.21.0",
"less": "*", "less": "^4.0.0",
"lightningcss": "^1.21.0", "lightningcss": "^1.21.0",
"sass": "*", "sass": "^1.70.0",
"sass-embedded": "*", "sass-embedded": "^1.70.0",
"stylus": "*", "stylus": ">=0.54.8",
"sugarss": "*", "sugarss": "^5.0.0",
"terser": "^5.16.0", "terser": "^5.16.0",
"tsx": "^4.8.1", "tsx": "^4.8.1",
"yaml": "^2.4.2" "yaml": "^2.4.2"

View File

@ -1,7 +1,7 @@
{ {
"name": "kvm-ui", "name": "kvm-ui",
"private": true, "private": true,
"version": "2025.09.03.1500", "version": "2025.09.03.2100",
"type": "module", "type": "module",
"engines": { "engines": {
"node": "22.15.0" "node": "22.15.0"
@ -41,7 +41,7 @@
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-hot-toast": "^2.6.0", "react-hot-toast": "^2.6.0",
"react-icons": "^5.5.0", "react-icons": "^5.5.0",
"react-router-dom": "^6.22.3", "react-router": "^7.8.2",
"react-simple-keyboard": "^3.8.119", "react-simple-keyboard": "^3.8.119",
"react-use-websocket": "^4.13.0", "react-use-websocket": "^4.13.0",
"react-xtermjs": "^1.0.10", "react-xtermjs": "^1.0.10",
@ -65,7 +65,7 @@
"@types/validator": "^13.15.3", "@types/validator": "^13.15.3",
"@typescript-eslint/eslint-plugin": "^8.42.0", "@typescript-eslint/eslint-plugin": "^8.42.0",
"@typescript-eslint/parser": "^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", "autoprefixer": "^10.4.21",
"eslint": "^9.34.0", "eslint": "^9.34.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
@ -79,7 +79,7 @@
"prettier-plugin-tailwindcss": "^0.6.14", "prettier-plugin-tailwindcss": "^0.6.14",
"tailwindcss": "^4.1.12", "tailwindcss": "^4.1.12",
"typescript": "^5.9.2", "typescript": "^5.9.2",
"vite": "^6.3.5", "vite": "^7.1.4",
"vite-tsconfig-paths": "^5.1.4" "vite-tsconfig-paths": "^5.1.4"
} }
} }

View File

@ -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 { Button, LinkButton } from "@components/Button";
import { GoogleIcon } from "@components/Icons"; import { GoogleIcon } from "@components/Icons";

View File

@ -1,5 +1,6 @@
import React, { JSX } from "react"; 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 ExtLink from "@/components/ExtLink";
import LoadingSpinner from "@/components/LoadingSpinner"; import LoadingSpinner from "@/components/LoadingSpinner";

View File

@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import clsx from "clsx"; 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({ export default function Fieldset({
children, children,

View File

@ -1,5 +1,5 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router";
import { ArrowLeftEndOnRectangleIcon, ChevronDownIcon } from "@heroicons/react/16/solid"; import { ArrowLeftEndOnRectangleIcon, ChevronDownIcon } from "@heroicons/react/16/solid";
import { Button, Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react"; import { Button, Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react";
import { LuMonitorSmartphone } from "react-icons/lu"; import { LuMonitorSmartphone } from "react-icons/lu";

View File

@ -1,6 +1,6 @@
import { MdConnectWithoutContact } from "react-icons/md"; import { MdConnectWithoutContact } from "react-icons/md";
import { Menu, MenuButton, MenuItem, MenuItems } from "@headlessui/react"; 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 { LuEllipsisVertical } from "react-icons/lu";
import Card from "@components/Card"; import Card from "@components/Card";

View File

@ -1,4 +1,4 @@
import { Link } from "react-router-dom"; import { Link } from "react-router";
import React from "react"; import React from "react";
import Container from "@/components/Container"; import Container from "@/components/Container";

View File

@ -6,7 +6,7 @@ import {
LuRadioReceiver, LuRadioReceiver,
} from "react-icons/lu"; } from "react-icons/lu";
import { useClose } from "@headlessui/react"; import { useClose } from "@headlessui/react";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router";
import { Button } from "@components/Button"; import { Button } from "@components/Button";
import Card, { GridCard } from "@components/Card"; import Card, { GridCard } from "@components/Card";

View File

@ -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 { useCallback, useMemo } from "react";
import { isOnDevice } from "../main"; import { isOnDevice } from "../main";

View File

@ -7,7 +7,7 @@ import {
redirect, redirect,
RouterProvider, RouterProvider,
useRouteError, useRouteError,
} from "react-router-dom"; } from "react-router";
import { ExclamationTriangleIcon } from "@heroicons/react/16/solid"; import { ExclamationTriangleIcon } from "@heroicons/react/16/solid";
import { CLOUD_API, DEVICE_API } from "@/ui.config"; 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 DevicesRoute from "@routes/devices";
import SettingsIndexRoute from "@routes/devices.$id.settings._index"; import SettingsIndexRoute from "@routes/devices.$id.settings._index";
import SettingsAccessIndexRoute from "@routes/devices.$id.settings.access._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 SignupRoute = lazy(() => import("@routes/signup"));
const LoginRoute = lazy(() => import("@routes/login")); const LoginRoute = lazy(() => import("@routes/login"));
const DevicesAlreadyAdopted = lazy(() => import("@routes/devices.already-adopted")); const DevicesAlreadyAdopted = lazy(() => import("@routes/devices.already-adopted"));

View File

@ -1,4 +1,4 @@
import { Outlet } from "react-router-dom"; import { Outlet } from "react-router";
function Root() { function Root() {
return <Outlet />; return <Outlet />;

View File

@ -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 { DEVICE_API } from "@/ui.config";
import api from "@/api";
import api from "../api";
export interface CloudState { export interface CloudState {
connected: boolean; connected: boolean;
@ -10,7 +10,7 @@ export interface CloudState {
appUrl: string; appUrl: string;
} }
const loader = async ({ request }: LoaderFunctionArgs) => { const loader: LoaderFunction = async ({ request }: LoaderFunctionArgs) => {
const url = new URL(request.url); const url = new URL(request.url);
const searchParams = url.searchParams; const searchParams = url.searchParams;
@ -37,7 +37,7 @@ const loader = async ({ request }: LoaderFunctionArgs) => {
}; };
export default function AdoptRoute() { export default function AdoptRoute() {
return <></>; return (<></>);
} }
AdoptRoute.loader = loader; AdoptRoute.loader = loader;

View File

@ -1,11 +1,5 @@
import { import { Form, redirect, useActionData, useLoaderData } from "react-router";
ActionFunctionArgs, import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "react-router";
Form,
LoaderFunctionArgs,
redirect,
useActionData,
useLoaderData,
} from "react-router-dom";
import { ChevronLeftIcon } from "@heroicons/react/16/solid"; import { ChevronLeftIcon } from "@heroicons/react/16/solid";
import { Button, LinkButton } from "@components/Button"; import { Button, LinkButton } from "@components/Button";
@ -22,7 +16,7 @@ interface LoaderData {
user: User; user: User;
} }
const action = async ({ request }: ActionFunctionArgs) => { const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
const { deviceId } = Object.fromEntries(await request.formData()); const { deviceId } = Object.fromEntries(await request.formData());
try { try {
@ -34,17 +28,17 @@ const action = async ({ request }: ActionFunctionArgs) => {
}); });
if (!res.ok) { 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) { } catch (e) {
console.error(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"); return redirect("/devices");
}; };
const loader = async ({ params }: LoaderFunctionArgs) => { const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => {
const user = await checkAuth(); const user = await checkAuth();
const { id } = params; const { id } = params;

View File

@ -7,7 +7,7 @@ import {
} from "react-icons/lu"; } from "react-icons/lu";
import { PlusCircleIcon, ExclamationTriangleIcon } from "@heroicons/react/20/solid"; import { PlusCircleIcon, ExclamationTriangleIcon } from "@heroicons/react/20/solid";
import { TrashIcon } from "@heroicons/react/16/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 Card, { GridCard } from "@/components/Card";
import { Button } from "@components/Button"; import { Button } from "@components/Button";

View File

@ -1,4 +1,4 @@
import { useNavigate, useOutletContext } from "react-router-dom"; import { useNavigate, useOutletContext } from "react-router";
import { GridCard } from "@/components/Card"; import { GridCard } from "@/components/Card";
import { Button } from "@components/Button"; import { Button } from "@components/Button";

View File

@ -1,11 +1,5 @@
import { import { Form, redirect, useActionData, useLoaderData } from "react-router";
ActionFunctionArgs, import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "react-router";
Form,
LoaderFunctionArgs,
redirect,
useActionData,
useLoaderData,
} from "react-router-dom";
import { ChevronLeftIcon } from "@heroicons/react/16/solid"; import { ChevronLeftIcon } from "@heroicons/react/16/solid";
import { Button, LinkButton } from "@components/Button"; import { Button, LinkButton } from "@components/Button";
@ -25,7 +19,7 @@ interface LoaderData {
user: User; user: User;
} }
const action = async ({ params, request }: ActionFunctionArgs) => { const action: ActionFunction = async ({ params, request }: ActionFunctionArgs) => {
const { id } = params; const { id } = params;
const { name } = Object.fromEntries(await request.formData()); const { name } = Object.fromEntries(await request.formData());
@ -48,7 +42,7 @@ const action = async ({ params, request }: ActionFunctionArgs) => {
return redirect("/devices"); return redirect("/devices");
}; };
const loader = async ({ params }: LoaderFunctionArgs) => { const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => {
const user = await checkAuth(); const user = await checkAuth();
const { id } = params; const { id } = params;

View File

@ -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"; import { getDeviceUiPath } from "../hooks/useAppNavigation";
const loader = ({ params }: LoaderFunctionArgs) => { const loader: LoaderFunction = ({ params }: LoaderFunctionArgs) => {
return redirect(getDeviceUiPath("/settings/general", params.id)); return redirect(getDeviceUiPath("/settings/general", params.id));
} }

View File

@ -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 { ShieldCheckIcon } from "@heroicons/react/24/outline";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
@ -26,7 +27,7 @@ export interface TLSState {
privateKey?: string; privateKey?: string;
} }
const loader = async () => { const loader: LoaderFunction = async () => {
if (isOnDevice) { if (isOnDevice) {
const status = await api const status = await api
.GET(`${DEVICE_API}/device`) .GET(`${DEVICE_API}/device`)

View File

@ -1,5 +1,5 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useLocation, useRevalidator } from "react-router-dom"; import { useLocation, useRevalidator } from "react-router";
import { Button } from "@components/Button"; import { Button } from "@components/Button";
import { InputFieldWithLabel } from "@/components/InputField"; import { InputFieldWithLabel } from "@/components/InputField";

View File

@ -1,4 +1,4 @@
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router";
import { useCallback } from "react"; import { useCallback } from "react";
import { useJsonRpc } from "@/hooks/useJsonRpc"; import { useJsonRpc } from "@/hooks/useJsonRpc";

View File

@ -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 { useCallback, useEffect, useRef, useState } from "react";
import { CheckCircleIcon } from "@heroicons/react/20/solid"; import { CheckCircleIcon } from "@heroicons/react/20/solid";

View File

@ -1,4 +1,4 @@
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router";
import { useState } from "react"; import { useState } from "react";
import { KeySequence, useMacrosStore, generateMacroId } from "@/hooks/stores"; import { KeySequence, useMacrosStore, generateMacroId } from "@/hooks/stores";

View File

@ -1,4 +1,4 @@
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { LuTrash2 } from "react-icons/lu"; import { LuTrash2 } from "react-icons/lu";

View File

@ -1,5 +1,5 @@
import { useEffect, Fragment, useMemo, useState, useCallback } from "react"; import { useEffect, Fragment, useMemo, useState, useCallback } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router";
import { import {
LuPenLine, LuPenLine,
LuCopy, LuCopy,

View File

@ -1,4 +1,4 @@
import { NavLink, Outlet, useLocation } from "react-router-dom"; import { NavLink, Outlet, useLocation } from "react-router";
import { import {
LuSettings, LuSettings,
LuMouse, LuMouse,

View File

@ -1,12 +1,5 @@
import { import { Form, redirect, useActionData, useParams, useSearchParams } from "react-router";
ActionFunctionArgs, import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "react-router";
Form,
LoaderFunctionArgs,
redirect,
useActionData,
useParams,
useSearchParams,
} from "react-router-dom";
import SimpleNavbar from "@components/SimpleNavbar"; import SimpleNavbar from "@components/SimpleNavbar";
import GridBackground from "@components/GridBackground"; import GridBackground from "@components/GridBackground";
@ -20,7 +13,7 @@ import { CLOUD_API } from "@/ui.config";
import api from "../api"; import api from "../api";
const loader = async ({ params }: LoaderFunctionArgs) => { const loader: LoaderFunction = async ({ params }: LoaderFunctionArgs) => {
await checkAuth(); await checkAuth();
const res = await fetch(`${CLOUD_API}/devices/${params.id}`, { const res = await fetch(`${CLOUD_API}/devices/${params.id}`, {
method: "GET", 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 // Handle form submission
const { name, id, returnTo } = Object.fromEntries(await request.formData()); const { name, id, returnTo } = Object.fromEntries(await request.formData());
const res = await api.PUT(`${CLOUD_API}/devices/${id}`, { name }); const res = await api.PUT(`${CLOUD_API}/devices/${id}`, { name });
@ -43,7 +36,7 @@ const action = async ({ request }: ActionFunctionArgs) => {
if (res.ok) { if (res.ok) {
return redirect(returnTo?.toString() ?? `/devices/${id}`); return redirect(returnTo?.toString() ?? `/devices/${id}`);
} else { } else {
return { error: "There was an error creating your device" }; return { error: "There was an error registering your device" };
} }
}; };

View File

@ -1,8 +1,6 @@
import { lazy, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { lazy, useCallback, useEffect, useMemo, useRef, useState } from "react";
import { import {
LoaderFunctionArgs,
Outlet, Outlet,
Params,
redirect, redirect,
useLoaderData, useLoaderData,
useLocation, useLocation,
@ -10,7 +8,8 @@ import {
useOutlet, useOutlet,
useParams, useParams,
useSearchParams, useSearchParams,
} from "react-router-dom"; } from "react-router";
import type { LoaderFunction, LoaderFunctionArgs, Params } from "react-router";
import { useInterval } from "usehooks-ts"; import { useInterval } from "usehooks-ts";
import { FocusTrap } from "focus-trap-react"; import { FocusTrap } from "focus-trap-react";
import { motion, AnimatePresence } from "framer-motion"; import { motion, AnimatePresence } from "framer-motion";
@ -112,7 +111,7 @@ const cloudLoader = async (params: Params<string>): Promise<CloudLoaderResp> =>
return { user, iceConfig, deviceName: device.name || device.id }; 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); return import.meta.env.MODE === "device" ? deviceLoader() : cloudLoader(params);
}; };

View File

@ -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 { LuMonitorSmartphone } from "react-icons/lu";
import { ArrowRightIcon } from "@heroicons/react/16/solid"; import { ArrowRightIcon } from "@heroicons/react/16/solid";
import { useInterval } from "usehooks-ts"; import { useInterval } from "usehooks-ts";
@ -16,7 +17,7 @@ interface LoaderData {
user: User; user: User;
} }
const loader = async () => { const loader: LoaderFunction = async () => {
const user = await checkAuth(); const user = await checkAuth();
try { try {

View File

@ -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 { useState } from "react";
import { LuEye, LuEyeOff } from "react-icons/lu"; import { LuEye, LuEyeOff } from "react-icons/lu";
@ -17,7 +18,7 @@ import ExtLink from "../components/ExtLink";
import { DeviceStatus } from "./welcome-local"; import { DeviceStatus } from "./welcome-local";
const loader = async () => { const loader: LoaderFunction = async () => {
const res = await api const res = await api
.GET(`${DEVICE_API}/device/status`) .GET(`${DEVICE_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>); .then(res => res.json() as Promise<DeviceStatus>);
@ -29,7 +30,7 @@ const loader = async () => {
return null; return null;
}; };
const action = async ({ request }: ActionFunctionArgs) => { const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
const formData = await request.formData(); const formData = await request.formData();
const password = formData.get("password"); const password = formData.get("password");

View File

@ -1,4 +1,4 @@
import { useLocation, useSearchParams } from "react-router-dom"; import { useLocation, useSearchParams } from "react-router";
import AuthLayout from "@components/AuthLayout"; import AuthLayout from "@components/AuthLayout";

View File

@ -1,4 +1,4 @@
import { useLocation, useSearchParams } from "react-router-dom"; import { useLocation, useSearchParams } from "react-router";
import AuthLayout from "@components/AuthLayout"; import AuthLayout from "@components/AuthLayout";

View File

@ -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 { useState } from "react";
import GridBackground from "@components/GridBackground"; import GridBackground from "@components/GridBackground";
@ -14,7 +15,7 @@ import api from "../api";
import { DeviceStatus } from "./welcome-local"; import { DeviceStatus } from "./welcome-local";
const loader = async () => { const loader: LoaderFunction = async () => {
const res = await api const res = await api
.GET(`${DEVICE_API}/device/status`) .GET(`${DEVICE_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>); .then(res => res.json() as Promise<DeviceStatus>);
@ -23,7 +24,7 @@ const loader = async () => {
return null; return null;
}; };
const action = async ({ request }: ActionFunctionArgs) => { const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
const formData = await request.formData(); const formData = await request.formData();
const localAuthMode = formData.get("localAuthMode"); const localAuthMode = formData.get("localAuthMode");
if (!localAuthMode) return { error: "Please select an authentication mode" }; if (!localAuthMode) return { error: "Please select an authentication mode" };
@ -162,5 +163,5 @@ export default function WelcomeLocalModeRoute() {
); );
} }
WelcomeLocalModeRoute.action = action;
WelcomeLocalModeRoute.loader = loader; WelcomeLocalModeRoute.loader = loader;
WelcomeLocalModeRoute.action = action;

View File

@ -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 { useState, useRef, useEffect } from "react";
import { LuEye, LuEyeOff } from "react-icons/lu"; import { LuEye, LuEyeOff } from "react-icons/lu";
@ -15,7 +16,7 @@ import api from "../api";
import { DeviceStatus } from "./welcome-local"; import { DeviceStatus } from "./welcome-local";
const loader = async () => { const loader: LoaderFunction = async () => {
const res = await api const res = await api
.GET(`${DEVICE_API}/device/status`) .GET(`${DEVICE_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>); .then(res => res.json() as Promise<DeviceStatus>);
@ -24,7 +25,7 @@ const loader = async () => {
return null; return null;
}; };
const action = async ({ request }: ActionFunctionArgs) => { const action: ActionFunction = async ({ request }: ActionFunctionArgs) => {
const formData = await request.formData(); const formData = await request.formData();
const password = formData.get("password"); const password = formData.get("password");
const confirmPassword = formData.get("confirmPassword"); const confirmPassword = formData.get("confirmPassword");
@ -174,5 +175,5 @@ export default function WelcomeLocalPasswordRoute() {
); );
} }
WelcomeLocalPasswordRoute.action = action;
WelcomeLocalPasswordRoute.loader = loader; WelcomeLocalPasswordRoute.loader = loader;
WelcomeLocalPasswordRoute.action = action;

View File

@ -1,6 +1,7 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { cx } from "cva"; 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 GridBackground from "@components/GridBackground";
import Container from "@components/Container"; import Container from "@components/Container";
@ -17,7 +18,7 @@ export interface DeviceStatus {
isSetup: boolean; isSetup: boolean;
} }
const loader = async () => { const loader: LoaderFunction = async () => {
const res = await api const res = await api
.GET(`${DEVICE_API}/device/status`) .GET(`${DEVICE_API}/device/status`)
.then(res => res.json() as Promise<DeviceStatus>); .then(res => res.json() as Promise<DeviceStatus>);