Carousel.tsx
import React from "react";export default function Carousel() {  const ref = React.useRef<HTMLDivElement>(null);  const [index, setIndex] = React.useState(0);  const [numberOfImages, setNumberOfImages] = React.useState(3);  React.useEffect(() => {    if (!ref.current) return;    const observer = new IntersectionObserver(      (entries) => {        entries.forEach((entry) => {          if (entry.isIntersecting) {            if ((entry.target as HTMLImageElement).complete === false) {              return;            }            const index = (entry.target as HTMLImageElement).dataset.index;            if (index) {              setIndex(Number(index));            }          }        });      },      {        root: ref.current,        threshold: 1,      }    );    const children = ref.current.children;    for (let i = 0; i < children.length; i++) {      (children[i] as HTMLImageElement).dataset.index = i.toString();      observer.observe(children[i]);    }    return () => {      observer.disconnect();    };  }, [numberOfImages]);  return (    <>      <section className="relative">        <button          onClick={() => ref.current?.scrollBy(-1000, 0)}          className="absolute top-1/2 left-0 text-4xl"        >          ⬅️        </button>        <button          onClick={() => ref.current?.scrollBy(1000, 0)}          className="absolute top-1/2 right-0 text-4xl"        >          ➡️        </button>        <nav className="absolute bottom-8 flex justify-center w-full">          <ul className="flex gap-2 text-7xl text-gray-400 font-thin">            {[...Array(numberOfImages)].map((_, i) => {              return (                <li key={i}>                  <button                    className={i === index ? "text-white" : ""}                    onClick={() => {                      ref.current?.scrollTo({                        left: i * 1000,                      });                    }}                  >                    _                  </button>                </li>              );            })}          </ul>        </nav>        <div          ref={ref}          className="scroll-smooth overflow-x-scroll whitespace-nowrap snap-x snap-mandatory"          style={{ scrollbarWidth: "none" }}          // wait for scrollbarwidth to be supported to hide scrollbar        >          {[...Array(numberOfImages)].map((_, i) => {            return (              <img                src="//unsplash.it/1000/400"                className="inline-block snap-start"                key={i}                onLoad={() => ref.current?.scrollTo({ left: 0 })}                // images are loaded at different orders, so we need to somehow start at the first image by using this hack              />            );          })}        </div>      </section>      <label>        Number of Images        <input          type="range"          min={1}          max={6}          value={numberOfImages}          onChange={(e) => setNumberOfImages(Number(e.target.value))}        />      </label>    </>  );}