"use client"; /** * V2Group 설정 패널 * 토스식 단계별 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 { Button } from "@/components/ui/button"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible"; import { LayoutList, Rows3, ChevronsDownUp, SquareStack, AppWindow, FileInput, Settings, ChevronDown, Plus, Trash2, } from "lucide-react"; import { cn } from "@/lib/utils"; // ─── 그룹 타입 카드 정의 ─── const GROUP_TYPE_CARDS = [ { value: "section", icon: LayoutList, title: "섹션", description: "기본 영역 구분이에요", }, { value: "tabs", icon: Rows3, title: "탭", description: "탭으로 내용을 나눠요", }, { value: "accordion", icon: ChevronsDownUp, title: "아코디언", description: "접었다 펼 수 있어요", }, { value: "card", icon: SquareStack, title: "카드 섹션", description: "카드 형태로 묶어요", }, { value: "modal", icon: AppWindow, title: "모달", description: "팝업으로 표시해요", }, { value: "form-modal", icon: FileInput, title: "폼 모달", description: "입력 폼 팝업이에요", }, ] as const; interface V2GroupConfigPanelProps { config: Record; onChange: (config: Record) => void; } export const V2GroupConfigPanel: React.FC = ({ config, onChange, }) => { const [advancedOpen, setAdvancedOpen] = useState(false); const updateConfig = (field: string, value: any) => { onChange({ ...config, [field]: value }); }; const currentGroupType = config.groupType || config.type || "section"; const isSectionType = currentGroupType === "section" || currentGroupType === "accordion"; const isModalType = currentGroupType === "modal" || currentGroupType === "form-modal"; const isTabsType = currentGroupType === "tabs"; const tabs = config.tabs || []; const addTab = () => { const newTabs = [...tabs, { id: `tab-${Date.now()}`, label: "새 탭", content: "" }]; updateConfig("tabs", newTabs); }; const updateTab = (index: number, field: string, value: string) => { const newTabs = [...tabs]; newTabs[index] = { ...newTabs[index], [field]: value }; updateConfig("tabs", newTabs); }; const removeTab = (index: number) => { const newTabs = tabs.filter((_: any, i: number) => i !== index); updateConfig("tabs", newTabs); }; return (
{/* ─── 1단계: 그룹 타입 선택 (카드) ─── */}

어떤 방식으로 영역을 구성하나요?

{GROUP_TYPE_CARDS.map((card) => { const Icon = card.icon; const isSelected = currentGroupType === card.value; return ( ); })}
{/* ─── 2단계: 기본 설정 ─── */}
기본 설정
제목 updateConfig("title", e.target.value)} placeholder="그룹 제목" className="h-8 w-[180px] text-sm" />
{/* ─── 3단계: 타입별 설정 ─── */} {/* 탭 타입: 탭 목록 관리 */} {isTabsType && (
탭 목록
{tabs.length > 0 ? (
{tabs.map((tab: any, index: number) => (
updateTab(index, "id", e.target.value)} placeholder="ID" className="h-8 flex-1 text-sm" /> updateTab(index, "label", e.target.value)} placeholder="라벨" className="h-8 flex-1 text-sm" />
))}
) : (

아직 탭이 없어요

위의 추가 버튼으로 탭을 만들어보세요

)}
)} {/* 섹션/아코디언 타입: 접기/펴기 옵션 */} {isSectionType && (

접기/펴기

사용자가 섹션을 접었다 펼 수 있어요

updateConfig("collapsible", checked)} />
{config.collapsible && (

기본으로 펼침

처음에 펼쳐진 상태로 보여줘요

updateConfig("defaultOpen", checked)} />
)}
)} {/* 모달/폼모달 타입: 모달 옵션 */} {isModalType && (
모달 설정
모달 크기

닫기 버튼

모달 우측 상단에 X 버튼이 표시돼요

updateConfig("closeable", checked)} />

배경 클릭 닫기

모달 바깥을 클릭하면 닫혀요

updateConfig("backdrop", checked)} />
)} {/* ─── 4단계: 고급 설정 (기본 접혀있음) ─── */}

헤더 표시

그룹 상단에 제목 영역이 표시돼요

updateConfig("showHeader", checked)} />
); }; V2GroupConfigPanel.displayName = "V2GroupConfigPanel"; export default V2GroupConfigPanel;