ERP-node/frontend/lib/registry/pop-components/pop-dashboard/modes/ArrowsMode.tsx

104 lines
3.0 KiB
TypeScript

"use client";
/**
* 좌우 버튼 표시 모드
*
* 화살표 버튼으로 아이템을 한 장씩 넘기는 모드
* 터치 최적화: 최소 44x44px 터치 영역
*/
import React, { useState, useCallback } from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
// ===== Props =====
export interface ArrowsModeProps {
/** 총 아이템 수 */
itemCount: number;
/** 페이지 인디케이터 표시 여부 */
showIndicator?: boolean;
/** 현재 인덱스에 해당하는 아이템 렌더링 */
renderItem: (index: number) => React.ReactNode;
}
// ===== 메인 컴포넌트 =====
export function ArrowsModeComponent({
itemCount,
showIndicator = true,
renderItem,
}: ArrowsModeProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const goToPrev = useCallback(() => {
setCurrentIndex((prev) => (prev > 0 ? prev - 1 : itemCount - 1));
}, [itemCount]);
const goToNext = useCallback(() => {
setCurrentIndex((prev) => (prev < itemCount - 1 ? prev + 1 : 0));
}, [itemCount]);
if (itemCount === 0) {
return (
<div className="flex h-full w-full items-center justify-center">
<span className="text-xs text-muted-foreground"> </span>
</div>
);
}
return (
<div className="flex h-full w-full flex-col">
{/* 콘텐츠 + 화살표 */}
<div className="relative flex min-h-0 flex-1 items-center">
{/* 왼쪽 화살표 */}
{itemCount > 1 && (
<button
type="button"
onClick={goToPrev}
className="absolute left-0 z-10 flex h-11 w-11 items-center justify-center rounded-full bg-background/80 shadow-sm transition-colors hover:bg-accent active:scale-95"
aria-label="이전"
>
<ChevronLeft className="h-5 w-5" />
</button>
)}
{/* 아이템 */}
<div className="h-full w-full px-12">
{renderItem(currentIndex)}
</div>
{/* 오른쪽 화살표 */}
{itemCount > 1 && (
<button
type="button"
onClick={goToNext}
className="absolute right-0 z-10 flex h-11 w-11 items-center justify-center rounded-full bg-background/80 shadow-sm transition-colors hover:bg-accent active:scale-95"
aria-label="다음"
>
<ChevronRight className="h-5 w-5" />
</button>
)}
</div>
{/* 페이지 인디케이터 */}
{showIndicator && itemCount > 1 && (
<div className="flex items-center justify-center gap-1.5 py-1">
{Array.from({ length: itemCount }).map((_, i) => (
<button
type="button"
key={i}
onClick={() => setCurrentIndex(i)}
className={`h-1.5 rounded-full transition-all ${
i === currentIndex
? "w-4 bg-primary"
: "w-1.5 bg-muted-foreground/30"
}`}
aria-label={`${i + 1}번째 아이템`}
/>
))}
</div>
)}
</div>
);
}