export function ScrollGrid()

in src/components/ScrollGrid/index.tsx [12:75]


export function ScrollGrid({ wrap = false, children, onIndicatorToggle }: ScrollGridProps) {
  const [showIndicator, setShowIndicator] = useState(false);
  const [barWidth, setBarWidth] = useState(0);
  const [barLeft, setBarLeft] = useState(0);
  const scrollerRef = useRef(null);
  const ratioRef = useRef(0.04);
  const onIndicatorToggleRef = useLatest(onIndicatorToggle);

  useEffect(() => {
    if (wrap) return;

    function updateIndicator() {
      const scroller = scrollerRef.current;
      if (!scroller) return;

      const { scrollWidth, clientWidth } = scroller;
      if (scrollWidth === clientWidth) {
        setShowIndicator(false);
        return;
      }

      const ratio = indicatorWidth / scrollWidth;
      ratioRef.current = ratio;
      setShowIndicator(true);
      setBarWidth(clientWidth * ratio);
    }

    updateIndicator();

    window.addEventListener('resize', updateIndicator);
    return () => {
      window.removeEventListener('resize', updateIndicator);
    };
  }, [wrap]);

  useEffect(() => {
    onIndicatorToggleRef.current?.(showIndicator);
  }, [onIndicatorToggleRef, showIndicator]);

  const handleScroll = (e: React.UIEvent<HTMLDivElement, UIEvent>) => {
    const { scrollLeft } = e.target as HTMLDivElement;
    setBarLeft(scrollLeft * ratioRef.current);
  };

  return (
    <div className="ScrollGrid" data-wrap={wrap}>
      <div
        className="ScrollGrid-scroller"
        ref={scrollerRef}
        onScroll={wrap ? undefined : handleScroll}
      >
        <div className="ScrollGrid-inner">{children}</div>
      </div>
      {showIndicator && (
        <div className="ScrollGrid-indicator">
          <div
            className="ScrollGrid-indicatorBar"
            style={{ width: barWidth, transform: `translateX(${barLeft}px)` }}
          />
        </div>
      )}
    </div>
  );
}