Update all UI dependencies and update React version to 18 (#2127)

This commit is contained in:
Liang Yi 2023-06-04 23:03:59 +08:00 committed by GitHub
parent 07f6666d46
commit 933a456b03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1364 additions and 1246 deletions

File diff suppressed because it is too large Load Diff

View File

@ -13,17 +13,17 @@
},
"private": true,
"dependencies": {
"@mantine/core": "^5.6.0",
"@mantine/dropzone": "^5.6.0",
"@mantine/form": "^5.6.0",
"@mantine/hooks": "^5.6.0",
"@mantine/modals": "^5.6.0",
"@mantine/notifications": "^5.6.0",
"axios": "^0.27.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"@mantine/core": "^6.0.0",
"@mantine/dropzone": "^6.0.0",
"@mantine/form": "^6.0.0",
"@mantine/hooks": "^6.0.0",
"@mantine/modals": "^6.0.0",
"@mantine/notifications": "^6.0.0",
"axios": "^1.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-query": "^3.39.2",
"react-router-dom": "~6.3.0",
"react-router-dom": "~6.10.0",
"socket.io-client": "^4.5.3"
},
"devDependencies": {
@ -34,36 +34,35 @@
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^12.1.0",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/lodash": "^4.14.0",
"@types/node": "^18.11.7",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/node": "^18.16.0",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@types/react-table": "^7.7.0",
"@vitejs/plugin-react": "^2.2.0",
"@vitest/coverage-c8": "^0.28.5",
"@vitest/ui": "^0.29.1",
"@vitejs/plugin-react": "^4.0.0",
"vitest": "^0.30.1",
"@vitest/coverage-c8": "^0.30.0",
"@vitest/ui": "^0.30.0",
"clsx": "^1.2.0",
"eslint": "^8.26.0",
"eslint": "^8.39.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-testing-library": "^5.9.0",
"husky": "^8.0.2",
"jsdom": "^20.0.1",
"jsdom": "^21.0.0",
"lodash": "^4.17.0",
"moment": "^2.29",
"prettier": "^2.7.0",
"prettier": "^2.8.0",
"prettier-plugin-organize-imports": "^3.1.0",
"pretty-quick": "^3.1.0",
"react-table": "^7.8.0",
"recharts": "~2.1.0",
"sass": "^1.55.0",
"typescript": "^4",
"vite": "^3.2.1",
"vite-plugin-checker": "^0.5.5",
"vitest": "^0.25.0"
"recharts": "~2.5.0",
"sass": "^1.62.0",
"typescript": "^5",
"vite": "^4.3.0",
"vite-plugin-checker": "^0.5.5"
},
"scripts": {
"start": "vite",

View File

@ -15,12 +15,12 @@ import {
Avatar,
Badge,
Burger,
createStyles,
Divider,
Group,
Header,
MediaQuery,
Menu,
createStyles,
} from "@mantine/core";
import { FunctionComponent } from "react";

View File

@ -357,9 +357,11 @@ const NavbarItem: FunctionComponent<NavbarItemProps> = ({
></FontAwesomeIcon>
)}
{name}
<Badge className={classes.badge} radius="xs" hidden={shouldHideBadge}>
{badge}
</Badge>
{shouldHideBadge === false && (
<Badge className={classes.badge} radius="xs">
{badge}
</Badge>
)}
</Text>
</NavLink>
);

View File

@ -1,11 +1,11 @@
import AppNavbar from "@/App/Navbar";
import { RouterNames } from "@/Router/RouterNames";
import ErrorBoundary from "@/components/ErrorBoundary";
import { Layout } from "@/constants";
import NavbarProvider from "@/contexts/Navbar";
import OnlineProvider from "@/contexts/Online";
import { notification } from "@/modules/task";
import CriticalError from "@/pages/errors/CriticalError";
import { RouterNames } from "@/Router/RouterNames";
import { Environment } from "@/utilities";
import { AppShell } from "@mantine/core";
import { useWindowEvent } from "@mantine/hooks";

View File

@ -6,7 +6,13 @@ import {
MantineThemeOverride,
} from "@mantine/core";
import { useColorScheme } from "@mantine/hooks";
import { FunctionComponent, useCallback, useEffect, useState } from "react";
import {
FunctionComponent,
PropsWithChildren,
useCallback,
useEffect,
useState,
} from "react";
const theme: MantineThemeOverride = {
fontFamily: "Roboto, open sans, Helvetica Neue, Helvetica, Arial, sans-serif",
@ -45,7 +51,7 @@ function useAutoColorScheme() {
const emotionCache = createEmotionCache({ key: "bazarr" });
const ThemeProvider: FunctionComponent = ({ children }) => {
const ThemeProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
const { colorScheme, toggleColorScheme } = useAutoColorScheme();
return (

View File

@ -1,12 +1,11 @@
import App from "@/App";
import { useBadges } from "@/apis/hooks";
import { useEnabledStatus } from "@/apis/hooks/site";
import App from "@/App";
import { Lazy } from "@/components/async";
import Authentication from "@/pages/Authentication";
import BlacklistMoviesView from "@/pages/Blacklist/Movies";
import BlacklistSeriesView from "@/pages/Blacklist/Series";
import Episodes from "@/pages/Episodes";
import NotFound from "@/pages/errors/NotFound";
import MoviesHistoryView from "@/pages/History/Movies";
import SeriesHistoryView from "@/pages/History/Series";
import MovieView from "@/pages/Movies";
@ -31,6 +30,7 @@ import SystemReleasesView from "@/pages/System/Releases";
import SystemTasksView from "@/pages/System/Tasks";
import WantedMoviesView from "@/pages/Wanted/Movies";
import WantedSeriesView from "@/pages/Wanted/Series";
import NotFound from "@/pages/errors/NotFound";
import { Environment } from "@/utilities";
import {
faClock,
@ -42,13 +42,13 @@ import {
faPlay,
} from "@fortawesome/free-solid-svg-icons";
import {
createContext,
FunctionComponent,
createContext,
lazy,
useContext,
useMemo,
} from "react";
import { BrowserRouter } from "react-router-dom";
import { RouterProvider, createBrowserRouter } from "react-router-dom";
import Redirector from "./Redirector";
import { RouterNames } from "./RouterNames";
import { CustomRouteObject } from "./type";
@ -315,12 +315,18 @@ function useRoutes(): CustomRouteObject[] {
const RouterItemContext = createContext<CustomRouteObject[]>([]);
export const Router: FunctionComponent = ({ children }) => {
export const Router: FunctionComponent = () => {
const routes = useRoutes();
// TODO: Move this outside the function component scope
const router = useMemo(
() => createBrowserRouter(routes, { basename: Environment.baseUrl }),
[routes]
);
return (
<RouterItemContext.Provider value={routes}>
<BrowserRouter basename={Environment.baseUrl}>{children}</BrowserRouter>
<RouterProvider router={router}></RouterProvider>
</RouterItemContext.Provider>
);
};

View File

@ -3,9 +3,9 @@ import { usePageSize } from "@/utilities/storage";
import { useCallback, useEffect, useState } from "react";
import {
QueryKey,
UseQueryResult,
useQuery,
useQueryClient,
UseQueryResult,
} from "react-query";
import { QueryKeys } from "./keys";

View File

@ -1,11 +1,11 @@
import UIError from "@/pages/errors/UIError";
import { Component } from "react";
import { Component, PropsWithChildren } from "react";
interface State {
error: Error | null;
}
class ErrorBoundary extends Component<object, State> {
class ErrorBoundary extends Component<PropsWithChildren, State> {
constructor(props: object) {
super(props);
this.state = { error: null };

View File

@ -1,7 +1,7 @@
import { LoadingOverlay } from "@mantine/core";
import { FunctionComponent, Suspense } from "react";
import { FunctionComponent, PropsWithChildren, Suspense } from "react";
const Lazy: FunctionComponent = ({ children }) => {
const Lazy: FunctionComponent<PropsWithChildren> = ({ children }) => {
return <Suspense fallback={<LoadingOverlay visible />}>{children}</Suspense>;
};

View File

@ -1,6 +1,6 @@
import { useMovieSubtitleModification } from "@/apis/hooks";
import { useModals, withModal } from "@/modules/modals";
import { task, TaskGroup } from "@/modules/task";
import { TaskGroup, task } from "@/modules/task";
import { useTableStyles } from "@/styles";
import { useArrayAction, useSelectorOptions } from "@/utilities";
import FormUtils from "@/utilities/form";
@ -28,9 +28,9 @@ import { useForm } from "@mantine/form";
import { isString } from "lodash";
import { FunctionComponent, useEffect, useMemo } from "react";
import { Column } from "react-table";
import TextPopover from "../TextPopover";
import { Action, Selector } from "../inputs";
import { SimpleTable } from "../tables";
import TextPopover from "../TextPopover";
type SubtitleFile = {
file: File;

View File

@ -1,4 +1,4 @@
export * from "./inputs";
export { default as Search } from "./Search";
export * from "./inputs";
export * from "./tables";
export { default as Toolbox } from "./toolbox";

View File

@ -4,7 +4,7 @@ import {
faXmark,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createStyles, Group, Stack, Text } from "@mantine/core";
import { Group, Stack, Text, createStyles } from "@mantine/core";
import { Dropzone } from "@mantine/dropzone";
import { FunctionComponent } from "react";

View File

@ -12,11 +12,11 @@ import { Badge, Center, Text } from "@mantine/core";
import { FunctionComponent, useMemo } from "react";
import { Column } from "react-table";
import { PageTable } from "..";
import TextPopover from "../TextPopover";
import MutateAction from "../async/MutateAction";
import QueryOverlay from "../async/QueryOverlay";
import { HistoryIcon } from "../bazarr";
import Language from "../bazarr/Language";
import TextPopover from "../TextPopover";
interface MovieHistoryViewProps {
movie: Item.Movie;

View File

@ -105,7 +105,7 @@ function ManualSearchView<T extends SupportType>(props: Props<T>) {
</Anchor>
);
} else {
return value;
return <Text>{value}</Text>;
}
},
},

View File

@ -4,7 +4,7 @@ import { SimpleTable } from "@/components/tables";
import { useCustomSelection } from "@/components/tables/plugins";
import { withModal } from "@/modules/modals";
import { isMovie } from "@/utilities";
import { Badge, Button, Divider, Group, Stack } from "@mantine/core";
import { Badge, Button, Divider, Group, Stack, Text } from "@mantine/core";
import { FunctionComponent, useMemo, useState } from "react";
import { Column, useRowSelect } from "react-table";
@ -60,9 +60,9 @@ const SubtitleToolView: FunctionComponent<SubtitleToolViewProps> = ({
}
if (idx !== -1) {
return path.slice(idx + 1);
return <Text>{path.slice(idx + 1)}</Text>;
} else {
return path;
return <Text>{path}</Text>;
}
},
},

View File

@ -30,7 +30,7 @@ const PageControl: FunctionComponent<Props> = ({
<Pagination
size="sm"
color={isLoading ? "gray" : "primary"}
page={index + 1}
value={index + 1}
onChange={(page) => goto(page - 1)}
hidden={count <= 1}
total={count}

View File

@ -3,8 +3,8 @@ import { useEffect } from "react";
import { usePagination, useTable } from "react-table";
import BaseTable from "./BaseTable";
import PageControl from "./PageControl";
import { useDefaultSettings } from "./plugins";
import { SimpleTableProps } from "./SimpleTable";
import { useDefaultSettings } from "./plugins";
type Props<T extends object> = SimpleTableProps<T> & {
autoScroll?: boolean;

View File

@ -4,12 +4,12 @@ import {
CellProps,
Column,
ColumnInstance,
ensurePluginOrder,
HeaderProps,
Hooks,
MetaBase,
TableInstance,
TableToggleCommonProps,
ensurePluginOrder,
} from "react-table";
const pluginName = "useCustomSelection";

View File

@ -1,5 +1,5 @@
import { createStyles, Group } from "@mantine/core";
import { FunctionComponent } from "react";
import { FunctionComponent, PropsWithChildren } from "react";
import ToolboxButton, { ToolboxMutateButton } from "./Button";
const useStyles = createStyles((theme) => ({
@ -11,7 +11,7 @@ const useStyles = createStyles((theme) => ({
},
}));
declare type ToolboxComp = FunctionComponent & {
declare type ToolboxComp = FunctionComponent<PropsWithChildren> & {
Button: typeof ToolboxButton;
MutateButton: typeof ToolboxMutateButton;
};

View File

@ -1,20 +1,19 @@
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import { useRoutes } from "react-router-dom";
import { createRoot } from "react-dom/client";
import { Router } from "./Router";
import { AllProviders } from "./providers";
import { useRouteItems } from "./Router";
const RouteApp = () => {
const items = useRouteItems();
const container = document.getElementById("root");
return useRoutes(items);
};
ReactDOM.render(
<StrictMode>
<AllProviders>
<RouteApp />
</AllProviders>
</StrictMode>,
document.getElementById("root")
);
if (container === null) {
Error("Cannot initialize app, root not found");
} else {
const root = createRoot(container);
root.render(
<StrictMode>
<AllProviders>
<Router />
</AllProviders>
</StrictMode>
);
}

View File

@ -2,19 +2,19 @@ import {
ModalsProvider as MantineModalsProvider,
ModalsProviderProps as MantineModalsProviderProps,
} from "@mantine/modals";
import { FunctionComponent, useMemo } from "react";
import { FunctionComponent, PropsWithChildren, useMemo } from "react";
import { ModalComponent, StaticModals } from "./WithModal";
const DefaultModalProps: MantineModalsProviderProps["modalProps"] = {
centered: true,
styles: {
modal: {
maxWidth: "100%",
},
// modals: {
// maxWidth: "100%",
// },
},
};
const ModalsProvider: FunctionComponent = ({ children }) => {
const ModalsProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
const modals = useMemo(
() =>
StaticModals.reduce<Record<string, ModalComponent>>((prev, curr) => {

View File

@ -5,8 +5,11 @@ import { useCallback, useContext, useMemo } from "react";
import { ModalComponent, ModalIdContext } from "./WithModal";
export function useModals() {
const { openContextModal: openMantineContextModal, ...rest } =
useMantineModals();
const {
openContextModal: openMantineContextModal,
closeContextModal: closeContextModalRaw,
...rest
} = useMantineModals();
const openContextModal = useCallback(
<ARGS extends {}>(

View File

@ -1,3 +1,3 @@
export * from "./hooks";
export { default as ModalsProvider } from "./ModalsProvider";
export { default as withModal } from "./WithModal";
export * from "./hooks";

View File

@ -1,6 +1,6 @@
import { debounce, forIn, remove, uniq } from "lodash";
import { onlineManager } from "react-query";
import { io, Socket } from "socket.io-client";
import { Socket, io } from "socket.io-client";
import { Environment, isDevEnv, isTestEnv } from "../../utilities";
import { ENSURE, GROUP, LOG } from "../../utilities/console";
import { createDefaultReducer } from "./reducer";

View File

@ -1,3 +1,4 @@
import { RouterNames } from "@/Router/RouterNames";
import {
useEpisodesBySeriesId,
useIsAnyActionRunning,
@ -11,9 +12,8 @@ import { ItemEditModal } from "@/components/forms/ItemEditForm";
import { SeriesUploadModal } from "@/components/forms/SeriesUploadForm";
import { SubtitleToolsModal } from "@/components/modals";
import { useModals } from "@/modules/modals";
import { notification, task, TaskGroup } from "@/modules/task";
import { TaskGroup, notification, task } from "@/modules/task";
import ItemOverview from "@/pages/views/ItemOverview";
import { RouterNames } from "@/Router/RouterNames";
import { useLanguageProfileBy } from "@/utilities/languages";
import {
faAdjust,

View File

@ -1,10 +1,10 @@
import { useDownloadEpisodeSubtitles, useEpisodesProvider } from "@/apis/hooks";
import { useShowOnlyDesired } from "@/apis/hooks/site";
import { Action, GroupTable } from "@/components";
import TextPopover from "@/components/TextPopover";
import { AudioList } from "@/components/bazarr";
import { EpisodeHistoryModal } from "@/components/modals";
import { EpisodeSearchModal } from "@/components/modals/ManualSearchModal";
import TextPopover from "@/components/TextPopover";
import { useModals } from "@/modules/modals";
import { useTableStyles } from "@/styles";
import { BuildKey, filterSubtitleBy } from "@/utilities";
@ -84,7 +84,7 @@ const Table: FunctionComponent<Props> = ({ episodes, profile, disabled }) => {
{
accessor: "season",
Cell: (row) => {
return `Season ${row.value}`;
return <Text>Season {row.value}</Text>;
},
},
{

View File

@ -11,8 +11,8 @@ import { useSelectorOptions } from "@/utilities";
import {
Box,
Container,
createStyles,
SimpleGrid,
createStyles,
useMantineTheme,
} from "@mantine/core";
import { useDocumentTitle } from "@mantine/hooks";

View File

@ -1,3 +1,4 @@
import { RouterNames } from "@/Router/RouterNames";
import {
useDownloadMovieSubtitles,
useIsMovieActionRunning,
@ -15,9 +16,8 @@ import { MovieUploadModal } from "@/components/forms/MovieUploadForm";
import { MovieHistoryModal, SubtitleToolsModal } from "@/components/modals";
import { MovieSearchModal } from "@/components/modals/ManualSearchModal";
import { useModals } from "@/modules/modals";
import { notification, task, TaskGroup } from "@/modules/task";
import { TaskGroup, notification, task } from "@/modules/task";
import ItemOverview from "@/pages/views/ItemOverview";
import { RouterNames } from "@/Router/RouterNames";
import { useLanguageProfileBy } from "@/utilities/languages";
import {
faCloudUploadAlt,

View File

@ -65,15 +65,19 @@ const MovieView: FunctionComponent = () => {
accessor: "missing_subtitles",
Cell: (row) => {
const missing = row.value;
return missing.map((v) => (
<Badge
mr="xs"
color="yellow"
key={BuildKey(v.code2, v.hi, v.forced)}
>
<Language.Text value={v}></Language.Text>
</Badge>
));
return (
<>
{missing.map((v) => (
<Badge
mr="xs"
color="yellow"
key={BuildKey(v.code2, v.hi, v.forced)}
>
<Language.Text value={v}></Language.Text>
</Badge>
))}
</>
);
},
},
{

View File

@ -1,7 +1,7 @@
import { Action, SimpleTable } from "@/components";
import {
anyCutoff,
ProfileEditModal,
anyCutoff,
} from "@/components/forms/ProfileEditForm";
import { useModals } from "@/modules/modals";
import { BuildKey, useArrayAction } from "@/utilities";
@ -87,15 +87,19 @@ const Table: FunctionComponent = () => {
Cell: (row) => {
const items = row.value;
if (!items) {
return false;
return null;
}
return items.map((v, idx) => {
return (
<Badge key={BuildKey(idx, v)} color="gray">
{v}
</Badge>
);
});
return (
<>
{items.map((v, idx) => {
return (
<Badge key={BuildKey(idx, v)} color="gray">
{v}
</Badge>
);
})}
</>
);
},
},
{
@ -104,15 +108,19 @@ const Table: FunctionComponent = () => {
Cell: (row) => {
const items = row.value;
if (!items) {
return false;
return null;
}
return items.map((v, idx) => {
return (
<Badge key={BuildKey(idx, v)} color="gray">
{v}
</Badge>
);
});
return (
<>
{items.map((v, idx) => {
return (
<Badge key={BuildKey(idx, v)} color="gray">
{v}
</Badge>
);
})}
</>
);
},
},
{

View File

@ -6,15 +6,15 @@ import {
Button,
Divider,
Group,
Text as MantineText,
SimpleGrid,
Stack,
Text as MantineText,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { capitalize } from "lodash";
import {
forwardRef,
FunctionComponent,
forwardRef,
useCallback,
useMemo,
useRef,
@ -28,8 +28,8 @@ import {
useFormActions,
useStagedValues,
} from "../utilities/FormValues";
import { useSettingValue } from "../utilities/hooks";
import { SettingsProvider, useSettings } from "../utilities/SettingsProvider";
import { useSettingValue } from "../utilities/hooks";
import { ProviderInfo, ProviderList } from "./list";
const ProviderKey = "settings-general-enabled_providers";

View File

@ -1,9 +1,16 @@
import { Text } from "@mantine/core";
import { FunctionComponent } from "react";
import { FunctionComponent, PropsWithChildren } from "react";
export const Message: FunctionComponent<{
interface MessageProps {
type?: "warning" | "info";
}> = ({ type = "info", children }) => {
}
type Props = PropsWithChildren<MessageProps>;
export const Message: FunctionComponent<Props> = ({
type = "info",
children,
}) => {
return (
<Text size="sm" color={type === "info" ? "dimmed" : "yellow"} my={0}>
{children}

View File

@ -1,12 +1,14 @@
import { Divider, Stack, Title } from "@mantine/core";
import { FunctionComponent } from "react";
import { FunctionComponent, PropsWithChildren } from "react";
interface SectionProps {
header: string;
hidden?: boolean;
}
export const Section: FunctionComponent<SectionProps> = ({
type Props = PropsWithChildren<SectionProps>;
export const Section: FunctionComponent<Props> = ({
header,
hidden,
children,

View File

@ -1,5 +1,5 @@
import { Collapse, Stack } from "@mantine/core";
import { FunctionComponent, useMemo, useRef } from "react";
import { FunctionComponent, PropsWithChildren, useMemo, useRef } from "react";
import { useSettingValue } from "../utilities/hooks";
interface ContentProps {
@ -8,7 +8,9 @@ interface ContentProps {
indent?: boolean;
}
const CollapseBox: FunctionComponent<ContentProps> = ({
type Props = PropsWithChildren<ContentProps>;
const CollapseBox: FunctionComponent<Props> = ({
on,
indent,
children,

View File

@ -1,11 +1,11 @@
import { rawRender, RenderOptions, screen } from "@/tests";
import { useForm } from "@mantine/form";
import { FunctionComponent, ReactElement } from "react";
import { FunctionComponent, PropsWithChildren, ReactElement } from "react";
import { describe, it } from "vitest";
import { FormContext, FormValues } from "../utilities/FormValues";
import { Number, Text } from "./forms";
const FormSupport: FunctionComponent = ({ children }) => {
const FormSupport: FunctionComponent<PropsWithChildren> = ({ children }) => {
const form = useForm<FormValues>({
initialValues: {
settings: {},

View File

@ -1,7 +1,7 @@
import {
Action as GlobalAction,
FileBrowser,
FileBrowserProps,
Action as GlobalAction,
MultiSelector as GlobalMultiSelector,
MultiSelectorProps as GlobalMultiSelectorProps,
Selector as GlobalSelector,
@ -12,17 +12,17 @@ import ChipInput, { ChipInputProps } from "@/components/inputs/ChipInput";
import { useSliderMarks } from "@/utilities";
import {
Input,
Slider as MantineSlider,
SliderProps as MantineSliderProps,
NumberInput,
NumberInputProps,
PasswordInput,
PasswordInputProps,
Slider as MantineSlider,
SliderProps as MantineSliderProps,
Switch,
TextInput,
TextInputProps,
} from "@mantine/core";
import { FunctionComponent, ReactText } from "react";
import { FunctionComponent, ReactNode, ReactText } from "react";
import { BaseInput, useBaseInput } from "../utilities/hooks";
export type NumberProps = BaseInput<number> & NumberInputProps;
@ -34,7 +34,10 @@ export const Number: FunctionComponent<NumberProps> = (props) => {
<NumberInput
{...rest}
value={value ?? 0}
onChange={(val = 0) => {
onChange={(val) => {
if (val === "") {
val = 0;
}
update(val);
}}
></NumberInput>
@ -126,7 +129,9 @@ export function MultiSelector<T extends string | number>(
}
type SliderProps = BaseInput<number> &
Omit<MantineSliderProps, "onChange" | "onChangeEnd" | "marks">;
Omit<MantineSliderProps, "onChange" | "onChangeEnd" | "marks" | "label"> & {
label?: ReactNode;
};
export const Slider: FunctionComponent<SliderProps> = (props) => {
const { value, update, rest } = useBaseInput(props);

View File

@ -63,11 +63,11 @@ export const URLTestButton: FunctionComponent<{
};
export * from "./Card";
export * from "./collapse";
export { default as CollapseBox } from "./collapse";
export * from "./forms";
export * from "./Layout";
export { default as Layout } from "./Layout";
export * from "./Message";
export * from "./pathMapper";
export * from "./Section";
export * from "./collapse";
export { default as CollapseBox } from "./collapse";
export * from "./forms";
export * from "./pathMapper";

View File

@ -1,4 +1,9 @@
import { createContext, FunctionComponent, useContext } from "react";
import {
createContext,
FunctionComponent,
PropsWithChildren,
useContext,
} from "react";
const SettingsContext = createContext<Settings | null>(null);
@ -12,7 +17,9 @@ type SettingsProviderProps = {
value: Settings | null;
};
export const SettingsProvider: FunctionComponent<SettingsProviderProps> = ({
type Props = PropsWithChildren<SettingsProviderProps>;
export const SettingsProvider: FunctionComponent<Props> = ({
value,
children,
}) => {

View File

@ -13,7 +13,13 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Anchor, Container, Divider, Grid, Stack, Text } from "@mantine/core";
import { useDocumentTitle } from "@mantine/hooks";
import moment from "moment";
import { FunctionComponent, ReactNode, useCallback, useState } from "react";
import {
FunctionComponent,
PropsWithChildren,
ReactNode,
useCallback,
useState,
} from "react";
import Table from "./table";
interface InfoProps {
@ -53,10 +59,13 @@ function Label(props: IconProps): JSX.Element {
);
}
const InfoContainer: FunctionComponent<{ title: string }> = ({
title,
children,
}) => {
interface InfoContainerProps {
title: string;
}
const InfoContainer: FunctionComponent<
PropsWithChildren<InfoContainerProps>
> = ({ title, children }) => {
return (
<Stack>
<h4>{title}</h4>

View File

@ -4,7 +4,7 @@ import {
useMovieWantedPagination,
} from "@/apis/hooks";
import Language from "@/components/bazarr/Language";
import { task, TaskGroup } from "@/modules/task";
import { TaskGroup, task } from "@/modules/task";
import WantedView from "@/pages/views/WantedView";
import { BuildKey } from "@/utilities";
import { faSearch } from "@fortawesome/free-solid-svg-icons";

View File

@ -4,7 +4,7 @@ import {
useSeriesAction,
} from "@/apis/hooks";
import Language from "@/components/bazarr/Language";
import { task, TaskGroup } from "@/modules/task";
import { TaskGroup, task } from "@/modules/task";
import WantedView from "@/pages/views/WantedView";
import { useTableStyles } from "@/styles";
import { BuildKey } from "@/utilities";

View File

@ -5,17 +5,17 @@ import {
useProfileItemsToLanguages,
} from "@/utilities/languages";
import {
faBookmark as farBookmark,
faFolder,
faBookmark as farBookmark,
} from "@fortawesome/free-regular-svg-icons";
import {
IconDefinition,
faBookmark,
faClone,
faLanguage,
faMusic,
faStream,
faTags,
IconDefinition,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
@ -23,7 +23,6 @@ import {
Badge,
BadgeProps,
Box,
createStyles,
Grid,
Group,
HoverCard,
@ -33,6 +32,7 @@ import {
Stack,
Text,
Title,
createStyles,
} from "@mantine/core";
import { FunctionComponent, useMemo } from "react";

View File

@ -1,28 +1,24 @@
import queryClient from "@/apis/queries";
import ThemeProvider from "@/App/theme";
import queryClient from "@/apis/queries";
import { ModalsProvider } from "@/modules/modals";
import "@fontsource/roboto/300.css";
import { NotificationsProvider } from "@mantine/notifications";
import { FunctionComponent } from "react";
import { Notifications } from "@mantine/notifications";
import { FunctionComponent, PropsWithChildren } from "react";
import { QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";
import { Router } from "./Router";
import { Environment } from "./utilities";
export const AllProviders: FunctionComponent = ({ children }) => {
export const AllProviders: FunctionComponent<PropsWithChildren> = ({
children,
}) => {
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<ModalsProvider>
<NotificationsProvider limit={5}>
<Router>
{/* c8 ignore next 3 */}
{Environment.queryDev && (
<ReactQueryDevtools initialIsOpen={false} />
)}
{children}
</Router>
</NotificationsProvider>
<Notifications limit={5} />
{/* c8 ignore next 3 */}
{Environment.queryDev && <ReactQueryDevtools initialIsOpen={false} />}
{children}
</ModalsProvider>
</ThemeProvider>
</QueryClientProvider>

View File

@ -1,11 +1,33 @@
import { AllProviders } from "@/providers";
import { render, RenderOptions } from "@testing-library/react";
import { FunctionComponent, ReactElement, StrictMode } from "react";
import {
FunctionComponent,
PropsWithChildren,
ReactElement,
StrictMode,
} from "react";
import {
createBrowserRouter,
RouteObject,
RouterProvider,
} from "react-router-dom";
const AllProvidersWithStrictMode: FunctionComponent<PropsWithChildren> = ({
children,
}) => {
const route: RouteObject = {
path: "/",
element: children,
};
// TODO: Update router system
const router = createBrowserRouter([route]);
const AllProvidersWithStrictMode: FunctionComponent = ({ children }) => {
return (
<StrictMode>
<AllProviders>{children}</AllProviders>
<AllProviders>
<RouterProvider router={router} />
</AllProviders>
</StrictMode>
);
};

View File

@ -1,41 +1,9 @@
// A workaround of built-in hooks in React-Router v6
// https://gist.github.com/rmorse/426ffcc579922a82749934826fa9f743
import type { Blocker, History, Transition } from "history";
import { useContext, useEffect } from "react";
// eslint-disable-next-line camelcase
import { UNSAFE_NavigationContext } from "react-router-dom";
export function useBlocker(blocker: Blocker, when = true) {
const navigator = useContext(UNSAFE_NavigationContext).navigator as History;
useEffect(() => {
if (!when) return;
const unblock = navigator.block((tx: Transition) => {
const autoUnblockingTx = {
...tx,
retry() {
// Automatically unblock the transition so it can play all the way
// through before retrying it. TODO: Figure out how to re-enable
// this block if the transition is cancelled for some reason.
unblock();
tx.retry();
},
};
blocker(autoUnblockingTx);
});
return unblock;
}, [navigator, blocker, when]);
}
import { unstable_usePrompt as useUnstablePrompt } from "react-router-dom";
// TODO: Replace with Mantine's confirmation modal
export function usePrompt(when: boolean, message: string) {
useBlocker((tx) => {
if (window.confirm(message)) {
tx.retry();
}
}, when);
useUnstablePrompt({ when, message });
}