"use client"; /** * V2Layout 설정 패널 * 토스식 단계별 UX: 레이아웃 타입 카드 선택 -> 타입별 설정 -> 고급 설정(접힘) */ import React, { useState } from "react"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { LayoutGrid, PanelLeftClose, MoveHorizontal, Minus, MonitorPlay, Settings, ChevronDown, } from "lucide-react"; import { cn } from "@/lib/utils"; // ─── 레이아웃 타입 카드 정의 ─── const LAYOUT_TYPE_CARDS = [ { value: "grid", icon: LayoutGrid, title: "그리드", description: "행과 열로 배치해요", }, { value: "split", icon: PanelLeftClose, title: "분할 패널", description: "영역을 나눠서 배치해요", }, { value: "flex", icon: MoveHorizontal, title: "플렉스", description: "유연하게 배치해요", }, { value: "divider", icon: Minus, title: "구분선", description: "영역을 구분해요", }, { value: "screen-embed", icon: MonitorPlay, title: "화면 임베드", description: "다른 화면을 불러와요", }, ] as const; interface V2LayoutConfigPanelProps { config: Record; onChange: (config: Record) => void; } export const V2LayoutConfigPanel: React.FC = ({ config, onChange, }) => { const [advancedOpen, setAdvancedOpen] = useState(false); const updateConfig = (field: string, value: any) => { onChange({ ...config, [field]: value }); }; const currentLayoutType = config.layoutType || config.type || "grid"; const isGridType = currentLayoutType === "grid"; const isSplitType = currentLayoutType === "split"; const isFlexType = currentLayoutType === "flex"; const isScreenEmbedType = currentLayoutType === "screen-embed"; return (
{/* ─── 1단계: 레이아웃 타입 선택 (카드) ─── */}

어떤 레이아웃을 사용하나요?

{LAYOUT_TYPE_CARDS.map((card) => { const Icon = card.icon; const isSelected = currentLayoutType === card.value; return ( ); })}
{/* ─── 2단계: 타입별 설정 ─── */} {/* 그리드 타입 설정 */} {isGridType && (
그리드 설정
컬럼 수
간격 (px) updateConfig("gap", e.target.value)} placeholder="16" className="h-8 w-[180px] text-sm" />

12컬럼 그리드

표준 12컬럼 그리드 시스템을 사용해요

updateConfig("use12Column", checked)} />
)} {/* 분할 패널 타입 설정 */} {isSplitType && (
분할 설정
분할 방향
비율 (%) updateConfig("splitRatio", [Number(e.target.value), 100 - Number(e.target.value)])} placeholder="50" min="10" max="90" className="mt-1 h-8 text-sm" />
나머지

크기 조절

사용자가 패널 크기를 드래그해서 조절할 수 있어요

updateConfig("resizable", checked)} />
)} {/* 플렉스 타입 설정 */} {isFlexType && (
플렉스 설정
방향
정렬
교차축 정렬
간격 (px) updateConfig("gap", e.target.value)} placeholder="16" className="h-8 w-[180px] text-sm" />

줄바꿈 허용

공간이 부족하면 다음 줄로 넘겨요

updateConfig("wrap", checked)} />
)} {/* 화면 임베드 타입 설정 */} {isScreenEmbedType && (
임베드 설정
화면 ID updateConfig("screenId", e.target.value ? Number(e.target.value) : undefined)} placeholder="화면 ID 입력" className="h-8 w-[180px] text-sm" />
)} {/* 구분선 타입: 별도 설정 없음 - 빈 상태 표시 */} {currentLayoutType === "divider" && (

추가 설정이 없어요

구분선은 기본 스타일로 표시돼요

)} {/* ─── 3단계: 고급 설정 (그리드/플렉스 타입에서만) ─── */} {(isGridType || isFlexType || isSplitType) && (
{isGridType && (

반응형 그리드

화면 크기에 따라 컬럼 수가 자동 조정돼요

updateConfig("responsive", checked)} />
)} {isFlexType && (
최소 아이템 너비 updateConfig("minItemWidth", e.target.value)} placeholder="자동" className="h-8 w-[180px] text-sm" />
)} {isSplitType && (
최소 패널 크기 (px) updateConfig("minPanelSize", e.target.value ? Number(e.target.value) : undefined)} placeholder="자동" className="h-8 w-[180px] text-sm" />
)}
)}
); }; V2LayoutConfigPanel.displayName = "V2LayoutConfigPanel"; export default V2LayoutConfigPanel;