Test

test
 avatar
unknown
plain_text
2 years ago
2.6 kB
3
Indexable
import React, { Children, cloneElement, useCallback, useEffect, useState } from "react";
import { useSwipeable } from "react-swipeable";

import styles from "./PhotoGaleryCarousel.module.scss";

interface IProps {
  children: JSX.Element[];
  setActiveIndex: (activeIndex: number) => void;
  activeIndex: number;
}

interface CarouselItemType {
  children: object;
  width: string;
}

export const CarouselItem: React.FC<CarouselItemType> = ({ children, width }) => {
  return (
    <div className={styles.carouselItem} style={{ width: width }}>
      {children}
    </div>
  );
};

const PhotoGaleryCarousel: React.FC<IProps> = ({ children, setActiveIndex, activeIndex }) => {
  const [screenWidth, setScreenWidth] = useState<number>(window.innerWidth);
  const updateIndex = useCallback(
    (newIndex: number) => {
      if (newIndex < 0) {
        newIndex = Children.count(children) - 1;
      } else if (newIndex >= Children.count(children)) {
        newIndex = 0;
      }
      setActiveIndex(newIndex);
    },
    [children]
  );

  const handleResize = () => {
    setScreenWidth(window.innerWidth);
  };

  const previousImage = () => {
    updateIndex(activeIndex - 1);
  };

  const nextImage = () => {
    updateIndex(activeIndex + 1);
  };

  useEffect(() => {
    handleResize();
  }, []);

  const handlers = useSwipeable({
    onSwipedLeft: () => {
      nextImage();
    },
    onSwipedRight: () => {
      if (activeIndex > 0) {
        previousImage();
      }
    }
  });

  window.addEventListener("resize", handleResize);

  return (
    <div {...handlers} className={styles.carousel}>
      <div
        className={styles.inner}
        style={{
          transform: `translateX(-${
            screenWidth < 576
              ? activeIndex === -1
                ? 0
                : activeIndex === 0
                ? 93
                : activeIndex * 100 + 93
              : screenWidth > 992
              ? activeIndex === -1
                ? 0
                : activeIndex === 0
                ? 50
                : activeIndex * 100 + 50
              : activeIndex === -1
              ? 0
              : activeIndex === 0
              ? 85
              : activeIndex * 100 + 85
          }%)`
        }}
      >
        {Children.map(children, (child: JSX.Element) => {
          return cloneElement(child, { width: "100%" });
        })}
      </div>
    </div>
  );
};

export default PhotoGaleryCarousel;