"use client"; /** * 스크롤 표시 모드 * * 가로 스크롤 + CSS scroll-snap으로 아이템 단위 스냅 * 터치 스와이프 네이티브 지원 */ import React, { useRef, useState, useEffect, useCallback } from "react"; // ===== Props ===== export interface ScrollModeProps { /** 총 아이템 수 */ itemCount: number; /** 페이지 인디케이터 표시 여부 */ showIndicator?: boolean; /** 현재 인덱스에 해당하는 아이템 렌더링 */ renderItem: (index: number) => React.ReactNode; } // ===== 메인 컴포넌트 ===== export function ScrollModeComponent({ itemCount, showIndicator = true, renderItem, }: ScrollModeProps) { const scrollRef = useRef(null); const [activeIndex, setActiveIndex] = useState(0); // 스크롤 위치로 현재 인덱스 계산 const handleScroll = useCallback(() => { const el = scrollRef.current; if (!el || !el.clientWidth) return; const index = Math.round(el.scrollLeft / el.clientWidth); setActiveIndex(Math.min(index, itemCount - 1)); }, [itemCount]); useEffect(() => { const el = scrollRef.current; if (!el) return; el.addEventListener("scroll", handleScroll, { passive: true }); return () => el.removeEventListener("scroll", handleScroll); }, [handleScroll]); if (itemCount === 0) { return (
아이템 없음
); } return (
{/* 스크롤 영역 */}
{Array.from({ length: itemCount }).map((_, i) => (
{renderItem(i)}
))}
{/* 페이지 인디케이터 */} {showIndicator && itemCount > 1 && (
{Array.from({ length: itemCount }).map((_, i) => ( ))}
)}
); }