Added lightbox
This commit is contained in:
parent
151ae0b126
commit
f4c2e2cba5
|
@ -50,7 +50,7 @@ export function getImgSizesByQuality(
|
|||
|
||||
type ImgProps = {
|
||||
className?: string;
|
||||
image: StrapiImage;
|
||||
image?: StrapiImage;
|
||||
quality?: ImageQuality;
|
||||
alt?: ImageProps["alt"];
|
||||
layout?: ImageProps["layout"];
|
||||
|
@ -60,42 +60,46 @@ type ImgProps = {
|
|||
};
|
||||
|
||||
export default function Img(props: ImgProps): JSX.Element {
|
||||
const imgSize = getImgSizesByQuality(
|
||||
props.image.width,
|
||||
props.image.height,
|
||||
props.quality ? props.quality : ImageQuality.Small
|
||||
);
|
||||
if (props.image) {
|
||||
const imgSize = getImgSizesByQuality(
|
||||
props.image.width,
|
||||
props.image.height,
|
||||
props.quality ? props.quality : ImageQuality.Small
|
||||
);
|
||||
|
||||
if (props.rawImg) {
|
||||
return (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
className={props.className}
|
||||
src={getAssetURL(
|
||||
props.image.url,
|
||||
props.quality ? props.quality : ImageQuality.Small
|
||||
)}
|
||||
alt={props.alt ? props.alt : props.image.alternativeText}
|
||||
width={imgSize.width}
|
||||
height={imgSize.height}
|
||||
/>
|
||||
);
|
||||
if (props.rawImg) {
|
||||
return (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
className={props.className}
|
||||
src={getAssetURL(
|
||||
props.image.url,
|
||||
props.quality ? props.quality : ImageQuality.Small
|
||||
)}
|
||||
alt={props.alt ? props.alt : props.image.alternativeText}
|
||||
width={imgSize.width}
|
||||
height={imgSize.height}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Image
|
||||
className={props.className}
|
||||
src={getAssetURL(
|
||||
props.image.url,
|
||||
props.quality ? props.quality : ImageQuality.Small
|
||||
)}
|
||||
alt={props.alt ? props.alt : props.image.alternativeText}
|
||||
width={props.layout === "fill" ? undefined : imgSize.width}
|
||||
height={props.layout === "fill" ? undefined : imgSize.height}
|
||||
layout={props.layout}
|
||||
objectFit={props.objectFit}
|
||||
priority={props.priority}
|
||||
unoptimized
|
||||
/>
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Image
|
||||
className={props.className}
|
||||
src={getAssetURL(
|
||||
props.image.url,
|
||||
props.quality ? props.quality : ImageQuality.Small
|
||||
)}
|
||||
alt={props.alt ? props.alt : props.image.alternativeText}
|
||||
width={props.layout === "fill" ? undefined : imgSize.width}
|
||||
height={props.layout === "fill" ? undefined : imgSize.height}
|
||||
layout={props.layout}
|
||||
objectFit={props.objectFit}
|
||||
priority={props.priority}
|
||||
unoptimized
|
||||
/>
|
||||
);
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import { StrapiImage } from "graphql/operations-types";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import Img, { ImageQuality } from "./Img";
|
||||
import Popup from "./Popup";
|
||||
|
||||
export type LightBoxProps = {
|
||||
setState:
|
||||
| Dispatch<SetStateAction<boolean>>
|
||||
| Dispatch<SetStateAction<boolean | undefined>>;
|
||||
state: boolean;
|
||||
image?: StrapiImage;
|
||||
};
|
||||
|
||||
export default function LightBox(props: LightBoxProps): JSX.Element {
|
||||
return (
|
||||
<Popup
|
||||
setState={props.setState}
|
||||
state={props.state}
|
||||
fillViewport
|
||||
hideBackground
|
||||
>
|
||||
<Img
|
||||
className="rounded-lg"
|
||||
image={props.image}
|
||||
layout="fill"
|
||||
objectFit="contain"
|
||||
quality={ImageQuality.Large}
|
||||
/>
|
||||
</Popup>
|
||||
);
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import HorizontalLine from "components/HorizontalLine";
|
||||
import Img, { ImageQuality } from "components/Img";
|
||||
import InsetBox from "components/InsetBox";
|
||||
import ToolTip from "components/ToolTip";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
|
@ -200,6 +201,43 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
|
|||
);
|
||||
},
|
||||
},
|
||||
img: {
|
||||
component: (props: {
|
||||
alt: string;
|
||||
src: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
caption?: string;
|
||||
name?: string;
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{props.src.startsWith("/uploads/") ? (
|
||||
<div className="relative w-full aspect-video my-8">
|
||||
<Img
|
||||
image={{
|
||||
__typename: "UploadFile",
|
||||
alternativeText: props.alt,
|
||||
url: props.src,
|
||||
width: props.width || 1500,
|
||||
height: props.height || 1000,
|
||||
caption: props.caption || "",
|
||||
name: props.name || "",
|
||||
}}
|
||||
layout="fill"
|
||||
objectFit="contain"
|
||||
quality={ImageQuality.Medium}
|
||||
></Img>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid place-content-center my-8">
|
||||
<img {...props} className="max-h-[50vh] " />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -2,12 +2,17 @@ import { Dispatch, SetStateAction } from "react";
|
|||
import Button from "./Button";
|
||||
|
||||
export type PopupProps = {
|
||||
setState: Dispatch<SetStateAction<boolean | undefined>>;
|
||||
setState:
|
||||
| Dispatch<SetStateAction<boolean>>
|
||||
| Dispatch<SetStateAction<boolean | undefined>>;
|
||||
state?: boolean;
|
||||
children: React.ReactNode;
|
||||
fillViewport?: boolean;
|
||||
hideBackground?: boolean;
|
||||
};
|
||||
|
||||
export default function Popup(props: PopupProps): JSX.Element {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`fixed inset-0 z-50 grid place-content-center transition-[backdrop-filter] duration-500 ${
|
||||
|
@ -15,6 +20,10 @@ export default function Popup(props: PopupProps): JSX.Element {
|
|||
? "[backdrop-filter:blur(2px)]"
|
||||
: "pointer-events-none touch-none"
|
||||
}`}
|
||||
onKeyUp={(e) => {
|
||||
if (e.key.match("Escape")) props.setState(false);
|
||||
}}
|
||||
tabIndex={0}
|
||||
>
|
||||
<div
|
||||
className={`fixed bg-shade inset-0 transition-all duration-500 ${
|
||||
|
@ -25,8 +34,12 @@ export default function Popup(props: PopupProps): JSX.Element {
|
|||
}}
|
||||
/>
|
||||
<div
|
||||
className={`relative p-10 bg-light rounded-lg shadow-2xl shadow-shade grid gap-4 place-items-center transition-transform ${
|
||||
className={`p-10 grid gap-4 place-items-center transition-transform ${
|
||||
props.state ? "scale-100" : "scale-0"
|
||||
} ${props.fillViewport ? "absolute inset-10 top-20" : "relative"} ${
|
||||
props.hideBackground
|
||||
? ""
|
||||
: "bg-light rounded-lg shadow-2xl shadow-shade"
|
||||
}`}
|
||||
>
|
||||
<Button
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
Enum_Componentmetadatabooks_Binding_Type,
|
||||
Enum_Componentmetadatabooks_Page_Order,
|
||||
GetLibraryItemQuery,
|
||||
StrapiImage,
|
||||
} from "graphql/operations-types";
|
||||
import {
|
||||
convertMmToInch,
|
||||
|
@ -34,6 +35,9 @@ import { useAppLayout } from "contexts/AppLayoutContext";
|
|||
import { useRouter } from "next/router";
|
||||
import ContentTOCLine from "components/Library/ContentTOCLine";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import { useState } from "react";
|
||||
import Popup from "components/Popup";
|
||||
import LightBox from "components/LightBox";
|
||||
|
||||
interface LibrarySlugProps extends AppStaticProps {
|
||||
item: GetLibraryItemQuery["libraryItems"]["data"][number]["attributes"];
|
||||
|
@ -52,6 +56,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
|
||||
sortContent(item.contents);
|
||||
|
||||
const [lightboxOpened, setLightboxOpened] = useState(false);
|
||||
const [lightboxImage, setLightboxImage] = useState<StrapiImage>();
|
||||
|
||||
const subPanel = (
|
||||
<SubPanel>
|
||||
<ReturnButton
|
||||
|
@ -104,6 +111,12 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.large}>
|
||||
<LightBox
|
||||
image={lightboxImage}
|
||||
setState={setLightboxOpened}
|
||||
state={lightboxOpened}
|
||||
/>
|
||||
|
||||
<ReturnButton
|
||||
href="/library/"
|
||||
title={langui.library}
|
||||
|
@ -112,7 +125,15 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
className="mb-10"
|
||||
/>
|
||||
<div className="grid place-items-center gap-12">
|
||||
<div className="drop-shadow-shade-xl w-full h-[50vh] mobile:h-[60vh] desktop:mb-16 relative cursor-pointer">
|
||||
<div
|
||||
className="drop-shadow-shade-xl w-full h-[50vh] mobile:h-[60vh] desktop:mb-16 relative cursor-pointer"
|
||||
onClick={() => {
|
||||
if (item.thumbnail.data) {
|
||||
setLightboxImage(item.thumbnail.data.attributes);
|
||||
setLightboxOpened(true);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.thumbnail.data ? (
|
||||
<Img
|
||||
image={item.thumbnail.data.attributes}
|
||||
|
@ -160,6 +181,10 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
<div
|
||||
key={galleryItem.id}
|
||||
className="relative aspect-square hover:scale-[1.02] transition-transform cursor-pointer"
|
||||
onClick={() => {
|
||||
setLightboxImage(galleryItem.attributes);
|
||||
setLightboxOpened(true);
|
||||
}}
|
||||
>
|
||||
<div className="bg-light absolute inset-0 rounded-lg drop-shadow-shade-md"></div>
|
||||
<Img
|
||||
|
|
Loading…
Reference in New Issue