diff --git a/frontend/components/pop/designer/PopDesigner.tsx b/frontend/components/pop/designer/PopDesigner.tsx index 8bcc8f3a..f4dfd3fa 100644 --- a/frontend/components/pop/designer/PopDesigner.tsx +++ b/frontend/components/pop/designer/PopDesigner.tsx @@ -652,6 +652,9 @@ export default function PopDesigner({ ? (updates) => handleUpdateComponent(selectedComponentId, updates) : undefined } + allComponents={Object.values(layout.components)} + onSelectComponent={setSelectedComponentId} + selectedComponentId={selectedComponentId} /> diff --git a/frontend/components/pop/designer/panels/ComponentEditorPanel.tsx b/frontend/components/pop/designer/panels/ComponentEditorPanel.tsx index ddb7ac79..0a9d6037 100644 --- a/frontend/components/pop/designer/panels/ComponentEditorPanel.tsx +++ b/frontend/components/pop/designer/panels/ComponentEditorPanel.tsx @@ -7,7 +7,6 @@ import { PopGridPosition, GridMode, GRID_BREAKPOINTS, - PopComponentType, } from "../types/pop-layout"; import { Settings, @@ -16,6 +15,7 @@ import { Grid3x3, MoveHorizontal, MoveVertical, + Layers, } from "lucide-react"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Label } from "@/components/ui/label"; @@ -36,12 +36,21 @@ interface ComponentEditorPanelProps { onUpdateComponent?: (updates: Partial) => void; /** 추가 className */ className?: string; + /** 그리드에 배치된 모든 컴포넌트 */ + allComponents?: PopComponentDefinitionV5[]; + /** 컴포넌트 선택 콜백 */ + onSelectComponent?: (componentId: string) => void; + /** 현재 선택된 컴포넌트 ID */ + selectedComponentId?: string | null; } // ======================================== // 컴포넌트 타입별 라벨 // ======================================== -const COMPONENT_TYPE_LABELS: Record = { +const COMPONENT_TYPE_LABELS: Record = { + "pop-sample": "샘플", + "pop-text": "텍스트", + "pop-dashboard": "대시보드", "pop-field": "필드", "pop-button": "버튼", "pop-list": "리스트", @@ -61,6 +70,9 @@ export default function ComponentEditorPanel({ currentMode, onUpdateComponent, className, + allComponents, + onSelectComponent, + selectedComponentId, }: ComponentEditorPanelProps) { const breakpoint = GRID_BREAKPOINTS[currentMode]; @@ -118,7 +130,44 @@ export default function ComponentEditorPanel({ {/* 위치 탭 */} - + + {/* 배치된 컴포넌트 목록 */} + {allComponents && allComponents.length > 0 && ( +
+
+ + + 배치된 컴포넌트 ({allComponents.length}) + +
+
+ {allComponents.map((comp) => { + const label = comp.label + || COMPONENT_TYPE_LABELS[comp.type] + || comp.type; + const isActive = comp.id === selectedComponentId; + return ( + + ); + })} +
+
+
+ )} + +
+ ); + } + + // 미등록: preview 컴포넌트 또는 기본 플레이스홀더 return ( -
- {/* 헤더 */} -
- - {component.label || typeLabel} +
+ {PreviewComponent ? ( + + ) : ( + + {typeLabel} -
- - {/* 내용: 등록된 preview 컴포넌트 또는 기본 플레이스홀더 */} -
- {PreviewComponent ? ( - - ) : ( - - {typeLabel} - - )} -
- - {/* 위치 정보 표시 (유효 위치 사용) */} -
- {effectivePosition.col},{effectivePosition.row} - ({effectivePosition.colSpan}×{effectivePosition.rowSpan}) -
+ )}
); }