diff --git a/src/components/listing-image-gallery/components/SharedModal.tsx b/src/components/listing-image-gallery/components/SharedModal.tsx new file mode 100644 index 0000000..0ccd603 --- /dev/null +++ b/src/components/listing-image-gallery/components/SharedModal.tsx @@ -0,0 +1,225 @@ +"use client"; + +import { + ArrowDownTrayIcon, + ArrowTopRightOnSquareIcon, + ArrowUturnLeftIcon, + ChevronLeftIcon, + ChevronRightIcon, + XMarkIcon, +} from "@heroicons/react/24/outline"; +import { AnimatePresence, motion, MotionConfig } from "framer-motion"; +import Image from "next/image"; +import { useState } from "react"; +import { useSwipeable } from "react-swipeable"; +import { DEMO_IMAGE } from "../ListingImageGallery"; +import { variants } from "@/utils/animationVariants"; +import downloadPhoto from "../utils/downloadPhoto"; +import { range } from "../utils/range"; +import type { ListingGalleryImage } from "../utils/types"; +import Twitter from "./Icons/Twitter"; + +interface SharedModalProps { + index: number; + images?: ListingGalleryImage[]; + currentPhoto?: ListingGalleryImage; + changePhotoId: (newVal: number) => void; + closeModal: () => void; + navigation: boolean; + direction?: number; +} + +export default function SharedModal({ + index, + images = DEMO_IMAGE, + changePhotoId, + closeModal, + navigation, + currentPhoto, + direction, +}: SharedModalProps) { + const [loaded, setLoaded] = useState(false); + + let filteredImages = images?.filter((img: ListingGalleryImage) => + range(index - 15, index + 15).includes(img.id) + ); + + const handlers = useSwipeable({ + onSwipedLeft: () => { + if (index < images?.length - 1) { + changePhotoId(index + 1); + } + }, + onSwipedRight: () => { + if (index > 0) { + changePhotoId(index - 1); + } + }, + trackMouse: true, + }); + + let currentImage = images ? images[index] : currentPhoto; + + return ( + +
+ {/* Main image */} +
+
+ + + Chisfis listing gallery setLoaded(true)} + sizes="(max-width: 1025px) 100vw, 1280px" + /> + + +
+
+ + {/* Buttons + bottom nav bar */} +
+ {/* Buttons */} + {loaded && ( +
+ {navigation && ( + <> + {index > 0 && ( + + )} + {index + 1 < images.length && ( + + )} + + )} +
+ {navigation ? ( + + + + ) : ( + + + + )} + +
+
+ +
+
+ )} + {/* Bottom Nav bar */} + {navigation && ( +
+ + + {filteredImages.map(({ id, url }) => ( + changePhotoId(id)} + key={id} + className={`${ + id === index + ? "z-20 rounded-md shadow shadow-black/50" + : "z-10" + } ${id === 0 ? "rounded-l-md" : ""} ${ + id === images.length - 1 ? "rounded-r-md" : "" + } relative inline-block w-full shrink-0 transform-gpu overflow-hidden focus:outline-none`} + > + small photos on the bottom + + ))} + + +
+ )} +
+
+
+ ); +} diff --git a/src/components/listing-image-gallery/styles/index.css b/src/components/listing-image-gallery/styles/index.css new file mode 100644 index 0000000..316f50a --- /dev/null +++ b/src/components/listing-image-gallery/styles/index.css @@ -0,0 +1,5 @@ +@supports (font: -apple-system-body) and (-webkit-appearance: none) { + img[loading="lazy"] { + clip-path: inset(0.6px); + } +}