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",
"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"

View File

@ -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"
}
}

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

View File

@ -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";

View File

@ -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,

View File

@ -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";

View File

@ -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";

View File

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

View File

@ -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";

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 { isOnDevice } from "../main";

View File

@ -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"));

View File

@ -1,4 +1,4 @@
import { Outlet } from "react-router-dom";
import { Outlet } from "react-router";
function Root() {
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 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;

View File

@ -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;

View File

@ -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";

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 { Button } from "@components/Button";

View File

@ -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;

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";
const loader = ({ params }: LoaderFunctionArgs) => {
const loader: LoaderFunction = ({ params }: LoaderFunctionArgs) => {
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 { 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`)

View File

@ -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";

View File

@ -1,4 +1,4 @@
import { useNavigate } from "react-router-dom";
import { useNavigate } from "react-router";
import { useCallback } from "react";
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 { 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 { 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 { LuTrash2 } from "react-icons/lu";

View File

@ -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,

View File

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

View File

@ -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" };
}
};

View File

@ -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<string>): Promise<CloudLoaderResp> =>
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);
};

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 { 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 {

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 { 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<DeviceStatus>);
@ -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");

View File

@ -1,4 +1,4 @@
import { useLocation, useSearchParams } from "react-router-dom";
import { useLocation, useSearchParams } from "react-router";
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";

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 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<DeviceStatus>);
@ -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;

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 { 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<DeviceStatus>);
@ -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;

View File

@ -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<DeviceStatus>);