// apps/dm/app/(landing)/reuse/_components/ImageSlider.tsx "use client"; import Image from "next/image"; import { useEffect, useMemo, useRef, useState } from "react"; type Slide = { src: string; alt?: string }; type Props = { slides: Slide[]; className?: string; maxWidthClassName?: string; // 예: "max-w-[760px]" }; export default function CaseImageSlider({ slides, className = "", maxWidthClassName = "max-w-[760px]", }: Props) { const safeSlides = useMemo(() => slides.filter(Boolean), [slides]); const [idx, setIdx] = useState(0); const [dragging, setDragging] = useState(false); const startX = useRef(0); const deltaX = useRef(0); const total = safeSlides.length; const canSlide = total > 1; const go = (dir: number) => { if (!canSlide) return; setIdx((prev) => { const next = prev + dir; if (next < 0) return total - 1; if (next >= total) return 0; return next; }); }; // ← → 키보드 지원(선택) useEffect(() => { const onKey = (e: KeyboardEvent) => { if (!canSlide) return; if (e.key === "ArrowLeft") go(-1); if (e.key === "ArrowRight") go(1); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [canSlide, total]); // 드래그(마우스/터치)로 넘기기 const onPointerDown = (e: React.PointerEvent) => { if (!canSlide) return; setDragging(true); startX.current = e.clientX; deltaX.current = 0; (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId); }; const onPointerMove = (e: React.PointerEvent) => { if (!dragging) return; deltaX.current = e.clientX - startX.current; }; const onPointerUp = () => { if (!dragging) return; setDragging(false); const threshold = 60; // 넘김 감도 if (deltaX.current > threshold) go(-1); else if (deltaX.current < -threshold) go(1); deltaX.current = 0; }; if (!total) return null; return (
{/* 좌측 버튼 */} {/* 우측 버튼 */} {/* 뷰포트 */}
{safeSlides.map((s, i) => (
{s.alt
))}
{/* 도트 */} {canSlide && (
{safeSlides.map((_, i) => { const active = i === idx; return (
)}
); }