Guest User

carousel

a guest
Aug 15th, 2023
38
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. 'use client';
  2.  
  3. import { useEffect } from 'react';
  4.  
  5. import { CarouselArrow } from '@components/carousels/partials/Arrow';
  6. import { CarouselDot } from '@components/carousels/partials/Dot';
  7. import { ImageWithPreview } from '@components/ImageWithPreview';
  8. import { useCarousel } from '@hooks/useCarousel';
  9. import type { ImageWithAltAndCaption } from '@shared/types';
  10. import { clsxm } from '@utils';
  11.  
  12. type Props = {
  13.   images: ImageWithAltAndCaption[];
  14.   options?: {
  15.     animations?: boolean;
  16.     preview?: {
  17.       enabled?: boolean;
  18.       type?: 'single' | 'multiple';
  19.     };
  20.     loop?: boolean;
  21.     slidePosition?: number;
  22.   };
  23.   classNames?: {
  24.     images?: {
  25.       container?: string;
  26.       image?: string;
  27.     };
  28.   };
  29. };
  30.  
  31. export const ImageCarousel = ({ classNames, images, options }: Props) => {
  32.   // Carousel Options
  33.   const { animations = true, loop = false, preview, slidePosition } = options ?? {};
  34.   const { enabled: hasPreview = true, type: previewType = 'single' } = preview ?? {};
  35.  
  36.   // Class Names
  37.   const { container: imageContainerClassName = '', image: imageClassName = '' } =
  38.     classNames?.images ?? {};
  39.  
  40.   // Instance Carousel
  41.   const { currentSlide, instanceRef, loaded, sliderRef } = useCarousel({
  42.     breakpoints: {
  43.       '(max-width: 768px)': {
  44.         slides: {
  45.           spacing: 10,
  46.         },
  47.       },
  48.       '(min-width: 769px)': {
  49.         slides: {
  50.           origin: 'center',
  51.           perView: 2,
  52.           spacing: 20,
  53.         },
  54.       },
  55.     },
  56.     initial: 0,
  57.     loop,
  58.     mode: 'free-snap',
  59.     renderMode: 'performance',
  60.   });
  61.  
  62.   const slidesLength = instanceRef?.current?.track.details?.slides?.length ?? images.length;
  63.  
  64.   useEffect(() => {
  65.     if (slidePosition && loaded && instanceRef.current) {
  66.       instanceRef.current?.moveToIdx(slidePosition);
  67.     }
  68.   }, [instanceRef, loaded, slidePosition]);
  69.  
  70.   return (
  71.     <section className={clsxm([{ invisible: !loaded && !instanceRef.current }])}>
  72.       <div
  73.         className="keen-slider cursor-grab"
  74.         data-aos={animations ? 'fade-left' : undefined}
  75.         ref={sliderRef}
  76.       >
  77.         {images.map(image => (
  78.           <ImageWithPreview
  79.             key={image.asset?._ref}
  80.             image={image}
  81.             images={images}
  82.             classNames={{
  83.               container: clsxm(['keen-slider__slide', imageContainerClassName]),
  84.               image: clsxm([
  85.                 'bg-zinc-700 shadow-sm shadow-zinc-600/10 h-full max-h-[400px] w-full aspect-[none] md:aspect-video',
  86.                 imageClassName,
  87.               ]),
  88.             }}
  89.             preview={{
  90.               enabled: hasPreview,
  91.               type: previewType,
  92.             }}
  93.           />
  94.         ))}
  95.       </div>
  96.  
  97.       {loaded && instanceRef.current && (
  98.         <nav className="mt-2 flex items-center justify-between gap-4">
  99.           <div className="flex items-center gap-4" data-aos={animations ? 'fade-right' : undefined}>
  100.             <CarouselArrow
  101.               left
  102.               disabled={currentSlide === 0}
  103.               onClick={(e: any) => e.stopPropagation() || instanceRef.current?.prev()}
  104.             />
  105.  
  106.             <CarouselArrow
  107.               disabled={currentSlide === slidesLength - 1}
  108.               onClick={(e: any) => e.stopPropagation() || instanceRef.current?.next()}
  109.             />
  110.           </div>
  111.  
  112.           <div className="flex items-center gap-2" data-aos={animations ? 'fade-right' : undefined}>
  113.             {[...Array(slidesLength).keys()].map(idx => (
  114.               <CarouselDot
  115.                 key={idx}
  116.                 id={idx}
  117.                 isCurrentSlide={currentSlide === idx}
  118.                 variant="dark"
  119.                 onClick={() => {
  120.                   instanceRef.current?.moveToIdx(idx);
  121.                 }}
  122.               />
  123.             ))}
  124.           </div>
  125.         </nav>
  126.       )}
  127.     </section>
  128.   );
  129. };
  130.  
Advertisement
Add Comment
Please, Sign In to add comment