"use client"; import React from "react"; import { ArrowRight, Link2, Unlink2, Plus, Trash2, Pencil, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { PopComponentDefinitionV5, PopDataConnection, } from "../types/pop-layout"; import { PopComponentRegistry, } from "@/lib/registry/PopComponentRegistry"; // ======================================== // Props // ======================================== interface ConnectionEditorProps { component: PopComponentDefinitionV5; allComponents: PopComponentDefinitionV5[]; connections: PopDataConnection[]; onAddConnection?: (conn: Omit) => void; onUpdateConnection?: (connectionId: string, conn: Omit) => void; onRemoveConnection?: (connectionId: string) => void; } // ======================================== // ConnectionEditor // ======================================== export default function ConnectionEditor({ component, allComponents, connections, onAddConnection, onUpdateConnection, onRemoveConnection, }: ConnectionEditorProps) { const registeredComp = PopComponentRegistry.getComponent(component.type); const meta = registeredComp?.connectionMeta; const outgoing = connections.filter( (c) => c.sourceComponent === component.id ); const incoming = connections.filter( (c) => c.targetComponent === component.id ); const hasSendable = meta?.sendable && meta.sendable.length > 0; const hasReceivable = meta?.receivable && meta.receivable.length > 0; if (!hasSendable && !hasReceivable) { return (

연결 없음

이 컴포넌트는 다른 컴포넌트와 연결할 수 없습니다

); } return (
{hasSendable && ( )} {hasReceivable && ( )}
); } // ======================================== // 보내기 섹션 // ======================================== interface SendSectionProps { component: PopComponentDefinitionV5; allComponents: PopComponentDefinitionV5[]; outgoing: PopDataConnection[]; onAddConnection?: (conn: Omit) => void; onUpdateConnection?: (connectionId: string, conn: Omit) => void; onRemoveConnection?: (connectionId: string) => void; } function SendSection({ component, allComponents, outgoing, onAddConnection, onUpdateConnection, onRemoveConnection, }: SendSectionProps) { const [editingId, setEditingId] = React.useState(null); return (
{outgoing.map((conn) => (
{editingId === conn.id ? ( { onUpdateConnection?.(conn.id, data); setEditingId(null); }} onCancel={() => setEditingId(null)} submitLabel="수정" /> ) : (
{conn.label || `→ ${allComponents.find((c) => c.id === conn.targetComponent)?.label || conn.targetComponent}`} {onRemoveConnection && ( )}
)}
))} onAddConnection?.(data)} submitLabel="연결 추가" />
); } // ======================================== // 단순 연결 폼 (이벤트 타입: "어디로" 1개만) // ======================================== interface SimpleConnectionFormProps { component: PopComponentDefinitionV5; allComponents: PopComponentDefinitionV5[]; initial?: PopDataConnection; onSubmit: (data: Omit) => void; onCancel?: () => void; submitLabel: string; } function SimpleConnectionForm({ component, allComponents, initial, onSubmit, onCancel, submitLabel, }: SimpleConnectionFormProps) { const [selectedTargetId, setSelectedTargetId] = React.useState( initial?.targetComponent || "" ); const targetCandidates = allComponents.filter((c) => { if (c.id === component.id) return false; const reg = PopComponentRegistry.getComponent(c.type); return reg?.connectionMeta?.receivable && reg.connectionMeta.receivable.length > 0; }); const handleSubmit = () => { if (!selectedTargetId) return; const targetComp = allComponents.find((c) => c.id === selectedTargetId); const srcLabel = component.label || component.id; const tgtLabel = targetComp?.label || targetComp?.id || "?"; onSubmit({ sourceComponent: component.id, sourceField: "", sourceOutput: "_auto", targetComponent: selectedTargetId, targetField: "", targetInput: "_auto", label: `${srcLabel} → ${tgtLabel}`, }); if (!initial) { setSelectedTargetId(""); } }; return (
{onCancel && (

연결 수정

)} {!onCancel && (

새 연결 추가

)}
어디로?
); } // ======================================== // 받기 섹션 (읽기 전용: 연결된 소스만 표시) // ======================================== interface ReceiveSectionProps { component: PopComponentDefinitionV5; allComponents: PopComponentDefinitionV5[]; incoming: PopDataConnection[]; } function ReceiveSection({ component, allComponents, incoming, }: ReceiveSectionProps) { return (
{incoming.length > 0 ? (
{incoming.map((conn) => { const sourceComp = allComponents.find( (c) => c.id === conn.sourceComponent ); return (
{sourceComp?.label || conn.sourceComponent}
); })}
) : (

연결된 소스가 없습니다

)}
); }