diff --git a/package-lock.json b/package-lock.json index 40976587..fcb8207d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5200,11 +5200,6 @@ "integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==", "dev": true }, - "node_modules/embla-carousel": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.1.tgz", - "integrity": "sha512-JUb5+FOHobSiWQ2EJNaueCNT/cQU9L6XWBbWmorWPQT9bkbk+fhsuLr8wWrzXKagO3oWszBO7MSx+GfaRk4E6A==" - }, "node_modules/embla-carousel-react": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/embla-carousel-react/-/embla-carousel-react-8.5.1.tgz", @@ -5217,7 +5212,12 @@ "react": "^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, - "node_modules/embla-carousel-reactive-utils": { + "node_modules/embla-carousel-react/node_modules/embla-carousel": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/embla-carousel/-/embla-carousel-8.5.1.tgz", + "integrity": "sha512-JUb5+FOHobSiWQ2EJNaueCNT/cQU9L6XWBbWmorWPQT9bkbk+fhsuLr8wWrzXKagO3oWszBO7MSx+GfaRk4E6A==" + }, + "node_modules/embla-carousel-react/node_modules/embla-carousel-reactive-utils": { "version": "8.5.1", "resolved": "https://registry.npmjs.org/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.5.1.tgz", "integrity": "sha512-n7VSoGIiiDIc4MfXF3ZRTO59KDp820QDuyBDGlt5/65+lumPHxX2JLz0EZ23hZ4eg4vZGUXwMkYv02fw2JVo/A==", diff --git a/src/components/ImageCarousel/index.tsx b/src/components/ImageCarousel/index.tsx index 3ca0ff5f..b891e281 100644 --- a/src/components/ImageCarousel/index.tsx +++ b/src/components/ImageCarousel/index.tsx @@ -1,6 +1,6 @@ -import { Carousel, CarouselContent, CarouselItem } from '@/components/ui/carousel' +import { Carousel, CarouselApi, CarouselContent, CarouselItem } from '@/components/ui/carousel' import { TImageInfo } from '@/types' -import { useState } from 'react' +import { useEffect, useState } from 'react' import Lightbox from 'yet-another-react-lightbox' import Zoom from 'yet-another-react-lightbox/plugins/zoom' import Image from '../Image' @@ -13,16 +13,35 @@ export function ImageCarousel({ images: TImageInfo[] isNsfw?: boolean }) { - const [index, setIndex] = useState(-1) + const [api, setApi] = useState() + const [currentIndex, setCurrentIndex] = useState(0) + const [lightboxIndex, setLightboxIndex] = useState(-1) + + useEffect(() => { + if (!api) { + return + } + + setCurrentIndex(api.selectedScrollSnap()) + + api.on('select', () => { + setCurrentIndex(api.selectedScrollSnap()) + }) + }, [api]) const handlePhotoClick = (event: React.MouseEvent, current: number) => { event.preventDefault() - setIndex(current) + setLightboxIndex(current) + } + + const onDotClick = (index: number) => { + api?.scrollTo(index) + setCurrentIndex(index) } return ( <> - + {images.map((image, index) => ( @@ -31,12 +50,15 @@ export function ImageCarousel({ ))} + {images.length > 1 && ( + + )} ({ src: url }))} plugins={[Zoom]} - open={index >= 0} - close={() => setIndex(-1)} + open={lightboxIndex >= 0} + close={() => setLightboxIndex(-1)} controller={{ closeOnBackdropClick: true, closeOnPullUp: true, @@ -48,3 +70,25 @@ export function ImageCarousel({ ) } + +function CarouselDot({ + total, + currentIndex, + onClick +}: { + total: number + currentIndex: number + onClick: (index: number) => void +}) { + return ( +
+ {Array.from({ length: total }).map((_, index) => ( +
onClick(index)} + /> + ))} +
+ ) +}