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 <></>; | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										31
									
								
								src/components/LightBox.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/components/LightBox.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint