File size: 2,211 Bytes
246d201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import React from "react";
import { ChevronLeft } from "#/assets/chevron-left";
import { ChevronRight } from "#/assets/chevron-right";
import { ImagePreview } from "./image-preview";
import { cn } from "#/utils/utils";

interface ImageCarouselProps {
  size: "small" | "large";
  images: string[];
  onRemove?: (index: number) => void;
}

export function ImageCarousel({

  size = "small",

  images,

  onRemove,

}: ImageCarouselProps) {
  const scrollContainerRef = React.useRef<HTMLDivElement>(null);
  const [isScrollable, setIsScrollable] = React.useState(false);
  const [isAtStart, setIsAtStart] = React.useState(true);
  const [isAtEnd, setIsAtEnd] = React.useState(false);

  React.useEffect(() => {
    const scrollContainer = scrollContainerRef.current;

    if (scrollContainer) {
      const hasScroll =
        scrollContainer.scrollWidth > scrollContainer.clientWidth;
      setIsScrollable(hasScroll);
    }
  }, [images]);

  const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
    const scrollContainer = event.currentTarget;
    setIsAtStart(scrollContainer.scrollLeft === 0);
    setIsAtEnd(
      scrollContainer.scrollLeft + scrollContainer.clientWidth ===
        scrollContainer.scrollWidth,
    );
  };

  return (
    <div data-testid="image-carousel" className="relative">

      {isScrollable && (

        <div className="absolute right-full transform top-1/2 -translate-y-1/2">

          <ChevronLeft active={!isAtStart} />

        </div>

      )}

      <div

        ref={scrollContainerRef}

        onScroll={handleScroll}

        className={cn(

          "flex overflow-x-auto",

          size === "small" && "gap-2",

          size === "large" && "gap-4",

        )}

      >

        {images.map((src, index) => (

          <ImagePreview

            key={index}

            size={size}

            src={src}

            onRemove={onRemove && (() => onRemove(index))}

          />

        ))}

      </div>

      {isScrollable && (

        <div className="absolute left-full transform top-1/2 -translate-y-1/2">

          <ChevronRight active={!isAtEnd} />

        </div>

      )}

    </div>
  );
}