Switch to YARL
This commit is contained in:
15
package-lock.json
generated
15
package-lock.json
generated
@@ -33,7 +33,8 @@
|
||||
"sharp": "^0.33.3",
|
||||
"tailwind-scrollbar": "^3.1.0",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "^5.4.5",
|
||||
"yet-another-react-lightbox": "^3.17.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
@@ -6397,6 +6398,18 @@
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/yet-another-react-lightbox": {
|
||||
"version": "3.17.4",
|
||||
"resolved": "https://registry.npmjs.org/yet-another-react-lightbox/-/yet-another-react-lightbox-3.17.4.tgz",
|
||||
"integrity": "sha512-XDCZoEXsjkbRy7Pxk+nsQthbYqW7V2INHv9Qn9GmdILP4GH7wANsRF31TCXIKMU4etr3UHmPzClLXf7KpIwDYQ==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0",
|
||||
"react-dom": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"sharp": "^0.33.3",
|
||||
"tailwind-scrollbar": "^3.1.0",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "^5.4.5",
|
||||
"yet-another-react-lightbox": "^3.17.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
import React, { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
||||
|
||||
import YARL, {
|
||||
isImageFitCover,
|
||||
isImageSlide,
|
||||
useLightboxProps,
|
||||
useLightboxState,
|
||||
} from "yet-another-react-lightbox";
|
||||
import Thumbnails from "yet-another-react-lightbox/plugins/thumbnails";
|
||||
import Zoom from "yet-another-react-lightbox/plugins/zoom";
|
||||
import Captions from "yet-another-react-lightbox/plugins/captions";
|
||||
import "yet-another-react-lightbox/styles.css";
|
||||
import "yet-another-react-lightbox/plugins/thumbnails.css";
|
||||
import "yet-another-react-lightbox/plugins/captions.css";
|
||||
|
||||
|
||||
type ImageData = {
|
||||
width: number,
|
||||
@@ -24,53 +37,77 @@ type LightboxProps = {
|
||||
imageData: ImageData[]
|
||||
}
|
||||
|
||||
export default function Lightbox(props: LightboxProps): React.JSX.Element {
|
||||
const [active, setActive] = useState<ImageData | null>(null);
|
||||
|
||||
function NextJsImage({ slide, offset, rect, unoptimized = false }: {slide: ImageData, offset: number, rect: {width: number, height: number}, unoptimized: boolean}): React.JSX.Element {
|
||||
const {
|
||||
on: { click },
|
||||
carousel: { imageFit },
|
||||
} = useLightboxProps();
|
||||
|
||||
const { currentIndex } = useLightboxState();
|
||||
|
||||
const cover = isImageSlide(slide) && isImageFitCover(slide, imageFit);
|
||||
|
||||
const width = !cover
|
||||
? Math.round(
|
||||
Math.min(rect.width, (rect.height / slide.height) * slide.width),
|
||||
)
|
||||
: rect.width;
|
||||
|
||||
const height = !cover
|
||||
? Math.round(
|
||||
Math.min(rect.height, (rect.width / slide.width) * slide.height),
|
||||
)
|
||||
: rect.height;
|
||||
|
||||
console.log(slide);
|
||||
|
||||
return (
|
||||
<div style={{ position: "relative", width, height }}>
|
||||
<Image
|
||||
fill
|
||||
alt=""
|
||||
src={slide}
|
||||
loading="eager"
|
||||
unoptimized={unoptimized}
|
||||
draggable={false}
|
||||
blurDataURL={slide.blur}
|
||||
placeholder={slide.blur}
|
||||
style={{
|
||||
objectFit: cover ? "cover" : "contain",
|
||||
cursor: click ? "pointer" : undefined,
|
||||
}}
|
||||
sizes={`${Math.ceil((width / window.innerWidth) * 100)}vw`}
|
||||
onClick={
|
||||
offset === 0 ? (): void => click?.({ index: currentIndex }) : undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function MyLightbox(props: LightboxProps): React.JSX.Element {
|
||||
const [active, setActive] = useState<number | null>(null);
|
||||
return (
|
||||
<>
|
||||
<div className="grid gap-2 grid-cols-3">
|
||||
{props.children.map((image, index) => (
|
||||
<button key={`lightbox_img_${index}`} onClick={(() => {
|
||||
setActive(props.imageData[index]);
|
||||
setActive(index);
|
||||
})}>
|
||||
{image}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{ active ? (
|
||||
<div className="fixed top-0 left-0 w-full h-full z-30">
|
||||
<div className="bg-black bg-opacity-80 w-full h-full p-12">
|
||||
<div className="flex flex-col w-full h-full">
|
||||
<div className="p-1 mb-4">
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">{active.exif.DateTimeOriginal?.toLocaleDateString()}</span>
|
||||
<button className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple" onClick={() => setActive(null)}>
|
||||
<span>x</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="relative w-full h-full m-auto">
|
||||
<Image
|
||||
alt={active.src}
|
||||
src={active.src}
|
||||
className="opacity-100 object-contain m-auto"
|
||||
loading="eager"
|
||||
unoptimized={true}
|
||||
fill
|
||||
blurDataURL={active.blur}
|
||||
placeholder={active.blur}
|
||||
<YARL
|
||||
open={!!active}
|
||||
close={() => setActive(null)}
|
||||
index={active ?? undefined}
|
||||
slides={props.imageData}
|
||||
// @ts-expect-error - Todo - This just passes the slide through, but it doesn't know the type
|
||||
render={{ slide: (args) => NextJsImage({...args, unoptimized: true }), thumbnail: NextJsImage }}
|
||||
plugins={[Thumbnails, Zoom, Captions]}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row flex-wrap self-center justify-center gap-4 max-w-3xl mt-4">
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">{active.camera}</span>
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">{active.exif.LensModel}</span>
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">{active.exif.FocalLength}mm</span>
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">f/{active.exif.FNumber}</span>
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">ISO {active.exif.ISOSpeedRatings}</span>
|
||||
<span className="text-white py-1.5 px-3 bg-dracula-bg-lighter border border-dracula-purple">{active.exif.ExposureBiasValue}EV</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user