Add show details page

This commit is contained in:
Zoe Roux 2022-08-15 01:39:09 +02:00
parent dfe6fa7cda
commit 9b80b340e3
23 changed files with 492 additions and 83 deletions

View File

@ -0,0 +1,9 @@
{
"show": {
"play": "Play",
"trailer": "Play Trailer",
"studio": "Studio",
"genre": "Genres",
"genre-none": "No genres"
}
}

View File

@ -0,0 +1,9 @@
{
"show": {
"play": "Lecture",
"trailer": "Jouer le trailer",
"studio": "Studio",
"genre": "Genres",
"genre-none": "Aucun genres"
}
}

View File

@ -24,16 +24,6 @@
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
experimental: {
swcPlugins: [
[
"next-superjson-plugin",
{
excluded: [],
},
],
],
},
env: {
KYOO_URL: process.env.KYOO_URL ?? "http://localhost:5000",
},

View File

@ -26,11 +26,11 @@
"@mui/icons-material": "^5.8.4",
"@mui/material": "^5.8.7",
"next": "12.2.2",
"next-superjson-plugin": "^0.3.0",
"next-translate": "^1.5.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-query": "^4.0.0-beta.23",
"superjson": "^1.9.1",
"zod": "^3.18.0"
},
"devDependencies": {

View File

@ -0,0 +1,33 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { styled, experimental_sx as sx } from "@mui/system";
export const Container = styled("div")(sx({
display: "flex",
pl: "15px",
pr: "15px",
mx: "auto",
width: {
sm: "540px",
md: "880px",
lg: "1170px",
},
}));

View File

@ -64,7 +64,7 @@ export const KyooTitle = (props: { sx: SxProps<Theme> }) => {
mr: 2,
fontFamily: "monospace",
fontWeight: 700,
color: "white",
color: "white"
}}
>
Kyoo
@ -84,7 +84,7 @@ export const Navbar = (barProps: AppBarProps) => {
const { data, error, isSuccess, isError } = useFetch(NavbarQuery);
return (
<AppBar position="sticky">
<AppBar position="sticky" {...barProps}>
<Toolbar>
<IconButton
size="large"
@ -118,7 +118,7 @@ export const Navbar = (barProps: AppBarProps) => {
</Box>
<Tooltip title={t("navbar.login")}>
<IconButton sx={{ p: 0 }} href="/auth/login">
<Avatar alt={t("navbar.login")} />
<Avatar alt={t("navbar.login")}/>
</IconButton>
</Tooltip>
</Toolbar>

View File

@ -19,15 +19,11 @@
*/
import { Box, Skeleton, styled } from "@mui/material";
import {
SyntheticEvent,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { SyntheticEvent, useEffect, useLayoutEffect, useRef, useState } from "react";
import { ComponentsOverrides, ComponentsProps, ComponentsVariants } from "@mui/material";
import { withThemeProps } from "~/utils/with-theme";
import type { Property } from "csstype";
import { ResponsiveStyleValue } from "@mui/system";
type ImageOptions = {
radius?: string;
@ -35,14 +31,17 @@ type ImageOptions = {
};
type ImageProps = {
img?: string;
img?: string | null;
alt: string;
} & ImageOptions;
type ImagePropsWithLoading =
| (ImageProps & { loading?: false })
| (ImageProps & { loading?: boolean })
| (Partial<ImageProps> & { loading: true });
type Width = ResponsiveStyleValue<Property.Width<(string & {}) | 0>>;
type Height = ResponsiveStyleValue<Property.Height<(string & {}) | 0>>;
const _Image = ({
img,
alt,
@ -55,8 +54,8 @@ const _Image = ({
...others
}: ImagePropsWithLoading &
(
| { aspectRatio?: string; width: string | number; height: string | number }
| { aspectRatio: string; width?: string | number; height?: string | number }
| { aspectRatio?: string; width: Width; height: Height }
| { aspectRatio: string; width?: Width; height?: Height }
)) => {
const [showLoading, setLoading] = useState<boolean>(loading);
const imgRef = useRef<HTMLImageElement>(null);
@ -101,7 +100,9 @@ const _Image = ({
export const Image = styled(_Image)({});
// eslint-disable-next-line jsx-a11y/alt-text
const _Poster = (props: ImagePropsWithLoading) => <_Image aspectRatio="2 / 3" {...props} />;
const _Poster = (
props: ImagePropsWithLoading & { width?: Width; height?: Height },
) => <_Image aspectRatio="2 / 3" {...props} />;
declare module "@mui/material/styles" {
interface ComponentsPropsList {

View File

@ -1,3 +0,0 @@
body {
margin: 0 !important;
}

View File

@ -43,7 +43,7 @@ export interface Page<T> {
*
* @format uri
*/
next?: string;
next: string | null;
/**
* The number of items in the current page.
@ -60,7 +60,7 @@ export const Paged = <Item>(item: z.ZodType<Item>): z.ZodSchema<Page<Item>> =>
z.object({
this: z.string(),
first: z.string(),
next: z.string().optional(),
next: z.string().nullable(),
count: z.number(),
items: z.array(item),
});

View File

@ -22,6 +22,7 @@ import { z } from "zod";
import { zdate } from "~/utils/zod";
import { ImagesP, ResourceP } from "../traits";
import { GenreP } from "./genre";
import { StudioP } from "./studio";
/**
* The enum containing show's status.
@ -58,7 +59,7 @@ export const ShowP = z.preprocess(
/**
* The date this show started airing. It can be null if this is unknown.
*/
startAir: zdate().optional(),
startAir: zdate().nullable(),
/**
* The date this show finished airing. It can also be null if this is unknown.
*/
@ -67,6 +68,10 @@ export const ShowP = z.preprocess(
* The list of genres (themes) this show has.
*/
genres: z.array(GenreP).optional(),
/**
* The studio that made this show.
*/
studio: StudioP.optional(),
}),
);

View File

@ -0,0 +1,34 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { z } from "zod";
import { ResourceP } from "../traits/resource";
export const StudioP = ResourceP.extend({
/**
* The name of this studio.
*/
name: z.string(),
});
/**
* A studio that make shows.
*/
export type Studio = z.infer<typeof StudioP>;

View File

@ -28,33 +28,31 @@ export const ImagesP = z.object({
* be null. If the kyoo's instance is not capable of handling this kind of image for the specific
* resource, this field won't be present.
*/
poster: z.string().transform(imageFn).optional(),
poster: z.string().transform(imageFn).optional().nullable(),
/**
* An url to the thumbnail of this resource. If this resource does not have an image, the link
* will be null. If the kyoo's instance is not capable of handling this kind of image for the
* specific resource, this field won't be present.
*/
thumbnail: z.string().transform(imageFn).optional(),
thumbnail: z.string().transform(imageFn).optional().nullable(),
/**
* An url to the logo of this resource. If this resource does not have an image, the link will be
* null. If the kyoo's instance is not capable of handling this kind of image for the specific
* resource, this field won't be present.
*/
logo: z.string().transform(imageFn).optional(),
logo: z.string().transform(imageFn).optional().nullable(),
/**
* An url to the thumbnail of this resource. If this resource does not have an image, the link
* will be null. If the kyoo's instance is not capable of handling this kind of image for the
* specific resource, this field won't be present.
*/
trailer: z.string().transform(imageFn).optional(),
trailer: z.string().transform(imageFn).optional().nullable(),
});
/**
* Base traits for items that has image resources.
*/
export type Images = z.infer<typeof ImagesP>;
export const imageList = ["poster", "thumbnail", "logo", "trailer"];

26
front/src/models/utils.ts Normal file
View File

@ -0,0 +1,26 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
export const getDisplayDate = (startAir: Date, endAir?: Date | null) => {
if (!endAir || startAir.getFullYear() === endAir.getFullYear()) {
return startAir.getFullYear();
}
return startAir.getFullYear() + (endAir ? ` - ${endAir.getFullYear()}` : "");
};

View File

@ -18,7 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { useState } from "react";
import React, { useState } from "react";
import appWithI18n from "next-translate/appWithI18n";
import { ThemeProvider } from "@mui/material";
import NextApp, { AppContext } from "next/app";
@ -27,13 +27,18 @@ import { Hydrate, QueryClientProvider } from "react-query";
import { createQueryClient, fetchQuery, QueryIdentifier, QueryPage } from "~/utils/query";
import { defaultTheme } from "~/utils/themes/default-theme";
import { Navbar, NavbarQuery } from "~/components/navbar";
import "../global.css";
import { Box } from "@mui/system";
import superjson from "superjson";
// Simply silence a SSR warning (see https://github.com/facebook/react/issues/14927 for more details)
if (typeof window === "undefined") {
React.useLayoutEffect = React.useEffect;
}
const AppWithNavbar = ({ children }: { children: JSX.Element }) => {
return (
<>
<Navbar/>
{/* <Navbar /> */}
{/* TODO: add an option to disable the navbar in the component */}
<Box>{children}</Box>
</>
@ -42,19 +47,27 @@ const AppWithNavbar = ({ children }: { children: JSX.Element }) => {
const App = ({ Component, pageProps }: AppProps) => {
const [queryClient] = useState(() => createQueryClient());
const { queryState, ...props } = pageProps;
const { queryState, ...props } = superjson.deserialize<any>(pageProps ?? {});
// TODO: tranform date string to date instances in the queryState
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={queryState}>
<ThemeProvider theme={defaultTheme}>
<AppWithNavbar>
<Component {...props} />
</AppWithNavbar>
</ThemeProvider>
</Hydrate>
</QueryClientProvider>
<>
<style jsx global>{`
body {
margin: 0px;
padding: 0px;
}
`}</style>
<QueryClientProvider client={queryClient}>
<Hydrate state={queryState}>
<ThemeProvider theme={defaultTheme}>
<AppWithNavbar>
<Component {...props} />
</AppWithNavbar>
</ThemeProvider>
</Hydrate>
</QueryClientProvider>
</>
);
};
@ -67,7 +80,7 @@ App.getInitialProps = async (ctx: AppContext) => {
urls.push(NavbarQuery);
appProps.pageProps.queryState = await fetchQuery(urls);
return appProps;
return { pageProps: superjson.serialize(appProps.pageProps) };
};
// The as any is needed since appWithI18n as wrong type hints
@ -77,7 +90,7 @@ export default appWithI18n(App as any, {
defaultLocale: "en",
loader: false,
pages: {
"*": ["common"],
"*": ["common", "browse"],
},
loadLocaleFrom: (locale, namespace) =>
import(`../../locales/${locale}/${namespace}`).then((m) => m.default),

View File

@ -18,20 +18,228 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { Box, Typography } from "@mui/material";
import { LocalMovies, PlayArrow } from "@mui/icons-material";
import {
alpha,
Box,
Divider,
Fab,
IconButton,
Skeleton,
SxProps,
Tooltip,
Typography,
useTheme,
} from "@mui/material";
import useTranslation from "next-translate/useTranslation";
import Head from "next/head";
import { Navbar } from "~/components/navbar";
import { Image, Poster } from "~/components/poster";
import { Show, ShowP } from "~/models";
import { QueryIdentifier, QueryPage, useFetch } from "~/utils/query";
import { getDisplayDate } from "~/models/utils";
import { useScroll } from "~/utils/hooks/use-scroll";
import { withRoute } from "~/utils/router";
import { Container } from "~/components/container";
import { makeTitle } from "~/utils/utils";
import { Link } from "~/utils/link";
import { Studio } from "~/models/resources/studio";
const StudioText = ({
studio,
loading = false,
sx,
}: {
studio?: Studio;
loading?: boolean;
sx?: SxProps;
}) => {
const { t } = useTranslation("browse");
if (!loading && !studio) return null;
return (
<Typography sx={sx}>
{t("show.studio")}:{" "}
{loading ? (
<Skeleton width="5rem" sx={{ display: "inline-flex" }} />
) : (
<Link href={`/studio/${studio!.slug}`}>{studio!.name}</Link>
)}
</Typography>
);
};
const ShowHeader = ({ data }: { data?: Show }) => {
/* const scroll = useScroll(); */
const { t } = useTranslation("browse");
console.log(data);
// TODO: tweek the navbar color with the theme.
const ShowHeader = (data: Show) => {
return (
<>
<Image img={data.thumbnail} alt="" height="60vh" width="100%" sx={{ positon: "relative" }} />
<Poster img={data.poster} alt={`${data.name}`} />
<Typography variant="h1" component="h1">
{data.name}
</Typography>
{/* TODO: Add a shadow on navbar items */}
{/* TODO: Put the navbar outside of the scrollbox */}
<Navbar
position="fixed"
sx={{ backgroundColor: `rgba(0, 0, 0, ${0 /*0.4 + scroll / 1000*/})` }}
/>
<Image
img={data?.thumbnail}
alt=""
loading={!data}
width="100%"
height={{ xs: "40vh", sm: "60vh", lg: "70vh" }}
sx={{
minHeight: { xs: "350px", sm: "400px", lg: "550px" },
position: "relative",
"&::after": {
content: '""',
position: "absolute",
top: 0,
bottom: 0,
right: 0,
left: 0,
background: "linear-gradient(to bottom, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.6) 100%)",
},
}}
/>
<Container
sx={{
position: "relative",
marginTop: { xs: "-30%", sm: "-25%", md: "-15rem", lg: "-21rem", xl: "-23rem" },
display: "flex",
flexDirection: { xs: "column", sm: "row" },
alignItems: { xs: "center", sm: "unset" },
textAlign: { xs: "center", sm: "unset" },
}}
>
<Poster
img={data?.poster}
alt={data?.name ?? ""}
loading={!data}
width={{ xs: "50%", md: "25%" }}
sx={{ maxWidth: { xs: "175px", sm: "unset" }, flexShrink: 0 }}
/>
<Box sx={{ alignSelf: { xs: "center", sm: "end", md: "center" }, pl: { sm: "2.5rem" } }}>
<Typography
variant="h3"
component="h1"
sx={{
color: { md: "white" },
fontWeight: { md: 900 },
mb: ".5rem",
}}
>
{data?.name ?? <Skeleton width="15rem" />}
</Typography>
{(!data || data.startAir) && (
<Typography variant="h5" sx={{ color: { md: "white" }, fontWeight: 300, mb: ".5rem" }}>
{data != undefined ? (
getDisplayDate(data.startAir!, data.endAir)
) : (
<Skeleton width="5rem" sx={{ mx: { xs: "auto", sm: "unset" } }} />
)}
</Typography>
)}
<Box sx={{ "& > *": { m: ".3rem !important" } }}>
<Tooltip title={t("show.play")}>
<Fab color="primary" size="small" aria-label={t("show.play")}>
<PlayArrow />
</Fab>
</Tooltip>
<Tooltip title={t("show.trailer")} aria-label={t("show.trailer")}>
<IconButton>
<LocalMovies sx={{ color: { md: "white" } }} />
</IconButton>
</Tooltip>
</Box>
</Box>
<Box
sx={{
display: { xs: "none", md: "flex" },
position: "absolute",
right: 0,
top: 0,
bottom: 0,
width: "25%",
flexDirection: "column",
alignSelf: "end",
pr: "15px",
}}
>
{data?.logo && (
<Image
img={data.logo}
alt=""
width="100%"
height="100px"
sx={{ display: { xs: "none", lg: "unset" } }}
/>
)}
<StudioText loading={!data} studio={data?.studio} sx={{ mt: "auto", mb: 3 }} />
</Box>
</Container>
<Container sx={{ display: { xs: "block", sm: "none" }, pt: 3 }}>
<StudioText loading={!data} studio={data?.studio} sx={{ mb: 1 }} />
<Typography sx={{ mb: 1 }}>
{t("show.genre")}
{": "}
{!data ? (
<Skeleton width="10rem" sx={{ display: "inline-flex" }} />
) : data?.genres ? (
data.genres.map((genre, i) => [
i > 0 && ", ",
<Link key={genre.id} href={`/genres/${genre.slug}`}>
{genre.name}
</Link>,
])
) : (
t("show.genre-none")
)}
</Typography>
</Container>
<Container sx={{ pt: 2 }}>
<Typography align="justify" sx={{ flexBasis: 0, flexGrow: 1, pt: { sm: 2 } }}>
{data?.overview ?? [...Array(4)].map((_, i) => <Skeleton key={i} />)}
</Typography>
<Divider
orientation="vertical"
variant="middle"
flexItem
sx={{ mx: 2, display: { xs: "none", sm: "block" } }}
/>
<Box sx={{ flexBasis: "25%", display: { xs: "none", sm: "block" } }}>
<StudioText
loading={!data}
studio={data?.studio}
sx={{ display: { xs: "none", sm: "block", md: "none" }, pb: 2 }}
/>
<Typography variant="h4" component="h2">
{t("show.genre")}
</Typography>
{!data || data.genres ? (
<ul>
{(data ? data.genres! : [...Array(3)]).map((genre, i) => (
<li key={genre?.id ?? i}>
<Typography>
{genre ? (
<Link href={`/genres/${genre.slug}`}>{genre.name}</Link>
) : (
<Skeleton />
)}
</Typography>
</li>
))}
</ul>
) : (
<Typography>{t("show.genre-none")}</Typography>
)}
</Box>
</Container>
</>
);
};
@ -40,19 +248,22 @@ const query = (slug: string): QueryIdentifier<Show> => ({
parser: ShowP,
path: ["shows", slug],
params: {
fields: ["genres"],
fields: ["genres", "studio"],
},
});
const ShowDetails: QueryPage<{ slug: string }> = ({ slug }) => {
const { data, error } = useFetch(query(slug));
console.log("error", data);
if (!data) return <p>oups</p>;
if (error) return <p>oups</p>;
return (
<>
<ShowHeader {...data} />
<Head>
<title>{makeTitle(data?.name)}</title>
<meta name="description" content={data?.overview} />
</Head>
<ShowHeader data={data} />
</>
);
};

1
front/src/styled-jsx.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="styled-jsx" />

View File

@ -0,0 +1,35 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { useState, useEffect } from "react";
export const useScroll = () => {
const [scroll, setScroll] = useState(0);
const scrollHandler = () => {
setScroll(window.scrollY);
};
useEffect(() => {
window.addEventListener("scroll", scrollHandler);
return () => window.removeEventListener("scroll", scrollHandler);
}, []);
return scroll;
};

View File

@ -18,7 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import React, { forwardRef, Ref } from "react";
import { forwardRef, Ref } from "react";
import NLink, { LinkProps as NLinkProps} from "next/link";
import { Button as MButton, ButtonProps, Link as MLink, LinkProps as MLinkProps} from "@mui/material";

View File

@ -27,7 +27,7 @@ import {
useQuery,
} from "react-query";
import { z } from "zod";
import { imageList, KyooErrors, Page } from "~/models";
import { KyooErrors, Page } from "~/models";
import { Paged } from "~/models/page";
const queryFn = async <Data>(

View File

@ -18,14 +18,26 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { createTheme } from "@mui/material";
import { createTheme, responsiveFontSizes } from "@mui/material";
export const defaultTheme = createTheme({
components: {
MuiSkeleton: {
defaultProps: {
animation: "wave",
export const defaultTheme = responsiveFontSizes(
createTheme({
components: {
MuiSkeleton: {
defaultProps: {
animation: "wave",
},
},
Poster: {
defaultProps: {
radius: "1%",
},
},
MuiLink: {
defaultProps: {
underline: "hover",
},
},
},
},
});
}),
);

23
front/src/utils/utils.ts Normal file
View File

@ -0,0 +1,23 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
export const makeTitle = (title?: string) => {
return title ? `${title} - Kyoo` : "Kyoo";
};

View File

@ -24,7 +24,7 @@ export const zdate = () => {
return z.preprocess((arg) => {
if (arg instanceof Date) return arg;
if (typeof arg === "string" && /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/.test(arg)) {
if (typeof arg === "string" && /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?/.test(arg)) {
return new Date(arg);
}

View File

@ -767,6 +767,13 @@ convert-source-map@^1.5.0:
dependencies:
safe-buffer "~5.1.1"
copy-anything@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.2.tgz#7189171ff5e1893b2287e8bf574b8cd448ed50b1"
integrity sha512-CzATjGXzUQ0EvuvgOCI6A4BGOo2bcVx8B+eC2nF862iv9fopnPQwlrbACakNCHRIJbCSBj+J/9JeDf60k64MkA==
dependencies:
is-what "^4.1.6"
core-js-pure@^3.20.2:
version "3.23.4"
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.23.4.tgz#aba5c7fb297063444f6bf93afb0362151679a012"
@ -1385,7 +1392,7 @@ has@^1.0.3:
dependencies:
function-bind "^1.1.1"
hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -1536,6 +1543,11 @@ is-weakref@^1.0.2:
dependencies:
call-bind "^1.0.2"
is-what@^4.1.6:
version "4.1.7"
resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.7.tgz#c41dc1d2d2d6a9285c624c2505f61849c8b1f9cc"
integrity sha512-DBVOQNiPKnGMxRMLIYSwERAS5MVY1B7xYiGnpgctsOFvVDz9f9PFXXxMcTOHuoqYp4NK9qFYQaIC1NRRxLMpBQ==
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -1938,13 +1950,6 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
next-superjson-plugin@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/next-superjson-plugin/-/next-superjson-plugin-0.3.0.tgz#81145f275c1e555be68867c104cc21113f96c675"
integrity sha512-M0Soj1P2t9peCyzNndEJiS48O2m88X9UGsCXDy8WHyGwWw1S7eCOEg9MiMqR+X1GD5C3hsdtHKMsKqrZOzr+SQ==
dependencies:
hoist-non-react-statics "^3.3.2"
next-translate@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/next-translate/-/next-translate-1.5.0.tgz#b1e5c4a8e55e31b3ed1b9428529f27c289c6b7bc"
@ -2416,6 +2421,13 @@ stylis@4.0.13:
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91"
integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==
superjson@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/superjson/-/superjson-1.9.1.tgz#e23bd2e8cf0f4ade131d6d769754cac7eaa8ab34"
integrity sha512-oT3HA2nPKlU1+5taFgz/HDy+GEaY+CWEbLzaRJVD4gZ7zMVVC4GDNFdgvAZt6/VuIk6D2R7RtPAiCHwmdzlMmg==
dependencies:
copy-anything "^3.0.2"
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"