"use client"; import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; type CardItem = { id: number; region: string; name: string; address: string; image: string; }; interface HorizontalCardScrollerProps { items: CardItem[]; } export default function HorizontalCardScroller({ items }: HorizontalCardScrollerProps) { const scrollRef = useRef(null); const trackRef = useRef(null); const [thumbWidth, setThumbWidth] = useState(60); const [thumbLeft, setThumbLeft] = useState(0); const [isDragging, setIsDragging] = useState(false); const dragOffsetRef = useRef(0); const CARD_WIDTH = 384; const CARD_GAP = 16; // Tailwind gap-4 const SCROLL_STEP = CARD_WIDTH + CARD_GAP; const updateThumb = useCallback(() => { const scroller = scrollRef.current; const track = trackRef.current; if (!scroller || !track) return; const { scrollWidth, clientWidth, scrollLeft } = scroller; const trackWidth = track.clientWidth; if (scrollWidth <= 0 || trackWidth <= 0) return; const ratioVisible = Math.max(0, Math.min(1, clientWidth / scrollWidth)); const newThumbWidth = Math.max(40, Math.round(trackWidth * ratioVisible)); const maxThumbLeft = Math.max(0, trackWidth - newThumbWidth); const ratioPosition = scrollWidth === clientWidth ? 0 : scrollLeft / (scrollWidth - clientWidth); const newThumbLeft = Math.round(maxThumbLeft * ratioPosition); setThumbWidth(newThumbWidth); setThumbLeft(newThumbLeft); }, []); useEffect(() => { updateThumb(); const el = scrollRef.current; if (!el) return; const onScroll = () => updateThumb(); const onResize = () => updateThumb(); el.addEventListener("scroll", onScroll); window.addEventListener("resize", onResize); return () => { el.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onResize); }; }, [updateThumb]); useEffect(() => { if (!isDragging) return; const onMove = (e: MouseEvent) => { const el = scrollRef.current; const track = trackRef.current; if (!el || !track) return; const rect = track.getBoundingClientRect(); let x = e.clientX - rect.left - dragOffsetRef.current; x = Math.max(0, Math.min(x, rect.width - thumbWidth)); setThumbLeft(x); const ratio = rect.width === thumbWidth ? 0 : x / (rect.width - thumbWidth); const targetScrollLeft = ratio * (el.scrollWidth - el.clientWidth); el.scrollLeft = targetScrollLeft; }; const onUp = () => setIsDragging(false); window.addEventListener("mousemove", onMove); window.addEventListener("mouseup", onUp); return () => { window.removeEventListener("mousemove", onMove); window.removeEventListener("mouseup", onUp); }; }, [isDragging, thumbWidth]); const handleThumbMouseDown = (e: React.MouseEvent) => { const rect = trackRef.current?.getBoundingClientRect(); if (!rect) return; dragOffsetRef.current = e.clientX - rect.left - thumbLeft; setIsDragging(true); e.preventDefault(); }; const scrollByStep = (direction: 1 | -1) => { const el = scrollRef.current; if (!el) return; el.scrollBy({ left: direction * SCROLL_STEP, behavior: "smooth" }); }; return (
{items.map((card) => (
{card.name}

{card.region}

{card.name}

{card.address}

))}
); }