diff --git a/src/components/Carousel.tsx b/src/components/Carousel.tsx index 93c0d93..b6edb17 100644 --- a/src/components/Carousel.tsx +++ b/src/components/Carousel.tsx @@ -23,6 +23,7 @@ interface CarouselProps { className?: string; hideArrows?: boolean; hideDots?: boolean; + mode?: "snap" | "free" | "free-snap" } const Carousel = ({ @@ -35,23 +36,31 @@ const Carousel = ({ autoplayInterval = 3000, className, hideArrows = false, - hideDots = false + hideDots = false, + mode = "snap" }: CarouselProps) => { const [currentSlide, setCurrentSlide] = useState(0); const [loaded, setLoaded] = useState(false); const [gridConfig, setGridConfig] = useState(gridLg); useEffect(() => { + const mqSm = window.matchMedia("(max-width: 640px)"); + const mqMd = window.matchMedia("(max-width: 1024px)"); + const updateGrid = () => { - const width = window.innerWidth; - if (width <= 640) setGridConfig(gridSm); - else if (width <= 1024) setGridConfig(gridMd); + if (mqSm.matches) setGridConfig(gridSm); + else if (mqMd.matches) setGridConfig(gridMd); else setGridConfig(gridLg); }; + updateGrid(); - window.addEventListener("resize", updateGrid); - return () => window.removeEventListener("resize", updateGrid); - }, [gridSm, gridMd, gridLg]); + mqSm.addEventListener("change", updateGrid); + mqMd.addEventListener("change", updateGrid); + return () => { + mqSm.removeEventListener("change", updateGrid); + mqMd.removeEventListener("change", updateGrid); + }; + }, [gridSm, gridMd, gridLg]) const itemsPerSlide = gridConfig.itemsPerSlide ?? gridConfig.cols * gridConfig.rows; const groupedItems = React.useMemo(() => { @@ -65,7 +74,8 @@ const Carousel = ({ const [sliderRef, instanceRef] = useKeenSlider({ loop: true, - mode: "snap", + mode: mode, + renderMode: "precision", slides: { perView: 1, spacing: 15 }, slideChanged: (slider) => setCurrentSlide(slider.track.details.rel), created: () => setLoaded(true), @@ -135,43 +145,50 @@ const Carousel = ({ ); }; -const Slides = ({className, sliderRef, renderItem, groupedItems, gridConfig, itemsPerSlide}) => { - if (itemsPerSlide === 1) { +interface SlidesProps { + className: string; + sliderRef: (node: HTMLDivElement) => void; + renderItem: (item: any, index: number) => React.ReactNode; + groupedItems: T[][] + gridConfig: GridConfig; + itemsPerSlide: number; +} + +const Slides = React.memo>( + ({ className, sliderRef, renderItem, groupedItems, gridConfig, itemsPerSlide }) => { + if (itemsPerSlide === 1) { + return ( +
+ {groupedItems.map((group, i) => ( +
+ {group.map((item) => renderItem(item, i))} +
+ ))} +
+ ); + } + return (
- { - groupedItems.map((group, i) => { - return ( -
- {group.map((item, j) => renderItem(item, i))} -
- ); - })} -
- ) - } - - {/* Slides */} - return (
- {groupedItems.map((group, i) => ( -
-
- {group.map((item, j) => ( + {groupedItems.map((group, i) => ( +
- {renderItem(item, i * itemsPerSlide + j)} + {group.map((item, j) => ( +
+ {renderItem(item, i * itemsPerSlide + j)} +
+ ))}
- ))} -
+
+ ))}
- ))} -
) -} + ); + } +); export default React.memo(Carousel); diff --git a/src/components/Gallery.tsx b/src/components/Gallery.tsx index baa59bf..20bcad1 100644 --- a/src/components/Gallery.tsx +++ b/src/components/Gallery.tsx @@ -1,14 +1,14 @@ import React, {useState} from 'react'; import {X, ChevronLeft, ChevronRight, Heart} from 'lucide-react'; -import posadevFila from '@/img/posadev-fila.jpg'; -import posadevReferentes from '@/img/IMG_7461.jpg'; -import posadevAsistencia from '@/img/PXL_20241208_011903817.jpg'; -import posadevTecnologia from '@/img/IMG_7425.jpg'; -import voluntarios from '@/img/gallery/voluntarios.jpg'; -import hazzim from '@/img/gallery/Hazzim.jpg'; -import dinamicas from '@/img/gallery/Dinamicas.jpg'; -import gabriel from '@/img/gallery/Gabriel.jpg'; -import posadev from '@/img/gallery/posadev.jpg' +import posadevFila from '@/img/gallery/posadev-fila.webp'; +import posadevReferentes from '@/img/gallery/IMG_7461.webp'; +import posadevAsistencia from '@/img/gallery/PXL_20241208_011903817.webp'; +import posadevTecnologia from '@/img/gallery/IMG_7425.webp'; +import voluntarios from '@/img/gallery/voluntarios.webp'; +import hazzim from '@/img/gallery/Hazzim.webp'; +import dinamicas from '@/img/gallery/Dinamicas.webp'; +import gabriel from '@/img/gallery/Gabriel.webp'; +import posadev from '@/img/gallery/posadev.webp' import dinamicaSponsor from '@/img/gallery/DinamicaSponsor.png' import invocacionDemo from '@/img/gallery/invocacionDemo.png' import tamales from '@/img/gallery/tamales.png' @@ -101,9 +101,7 @@ const Gallery = () => { const renderPhoto = React.useCallback( (image: IImage, index: number) => ( - ), - [setSelectedImage] - ); + ), []); const closeLightbox = () => { setSelectedImage(null); @@ -151,11 +149,13 @@ const Gallery = () => {
{/* Gallery grid */} + renderItem={renderPhoto} + /> {/* Lightbox */} {selectedImage !== null && (
diff --git a/src/components/Photo.tsx b/src/components/Photo.tsx index cd08288..809ac72 100644 --- a/src/components/Photo.tsx +++ b/src/components/Photo.tsx @@ -15,21 +15,23 @@ const Photo: React.FC = ({image, setSelectedImage, index}) => { }; return (