{/* 공통: colspan */}
{element.colspan || 1}
{/* 방향 설정 (수직/수평) — header, divider, spacer 제외 */}
{!["header", "divider", "spacer"].includes(element.type) && (
onUpdate({ ...element, direction: value })
}
className="flex gap-4"
>
)}
{/* 헤더 설정 */}
{element.type === "header" && (
)}
{/* 데이터 셀 설정 */}
{element.type === "dataCell" && (
)}
{/* 구분선 설정 */}
{element.type === "divider" && (
)}
{/* 뱃지 설정 */}
{element.type === "badge" && (
<>
onUpdate({ ...element, label: e.target.value } as CardBadgeElement)
}
placeholder="예: 상태"
className="h-9 text-sm"
/>
>
)}
{/* 이미지 설정 */}
{element.type === "image" && (
<>
onUpdate({ ...element, columnName: e.target.value } as CardImageElement)}
placeholder="image_url"
className="h-9 text-sm"
/>
onUpdate({ ...element, height: parseInt(e.target.value) || 80 } as CardImageElement)}
className="h-9 text-sm"
/>
>
)}
{/* 숫자/금액 설정 */}
{element.type === "number" && (
<>
onUpdate({ ...element, label: e.target.value } as CardNumberElement)}
placeholder="금액"
className="h-9 text-sm"
/>
onUpdate({ ...element, columnName: e.target.value } as CardNumberElement)}
placeholder="amount"
className="h-9 text-sm"
/>
{(element as CardNumberElement).numberFormat === "currency" && (
onUpdate({ ...element, currencySuffix: e.target.value } as CardNumberElement)}
placeholder="원"
className="h-9 text-sm"
/>
)}
>
)}
{/* 날짜 설정 */}
{element.type === "date" && (
<>
onUpdate({ ...element, label: e.target.value } as CardDateElement)}
placeholder="날짜"
className="h-9 text-sm"
/>
onUpdate({ ...element, columnName: e.target.value } as CardDateElement)}
placeholder="created_at"
className="h-9 text-sm"
/>
onUpdate({ ...element, dateFormat: e.target.value } as CardDateElement)}
placeholder="YYYY-MM-DD"
className="h-9 text-sm"
/>
>
)}
{/* 링크 설정 */}
{element.type === "link" && (
<>
onUpdate({ ...element, label: e.target.value } as CardLinkElement)}
placeholder="링크"
className="h-9 text-sm"
/>
onUpdate({ ...element, columnName: e.target.value } as CardLinkElement)}
placeholder="url"
className="h-9 text-sm"
/>
onUpdate({ ...element, linkText: e.target.value } as CardLinkElement)}
placeholder="자동 (URL 표시)"
className="h-9 text-sm"
/>
onUpdate({ ...element, openInNewTab: !!checked } as CardLinkElement)}
/>
>
)}
{/* 상태 설정 */}
{element.type === "status" && (
<>
onUpdate({ ...element, columnName: e.target.value } as CardStatusElement)}
placeholder="status"
className="h-9 text-sm"
/>
{((element as CardStatusElement).statusMappings || []).map((mapping, i) => (
{
const mappings = [...((element as CardStatusElement).statusMappings || [])];
mappings[i] = { ...mappings[i], value: e.target.value };
onUpdate({ ...element, statusMappings: mappings } as CardStatusElement);
}}
placeholder="값"
className="h-8 text-xs flex-1"
/>
{
const mappings = [...((element as CardStatusElement).statusMappings || [])];
mappings[i] = { ...mappings[i], label: e.target.value };
onUpdate({ ...element, statusMappings: mappings } as CardStatusElement);
}}
placeholder="라벨"
className="h-8 text-xs flex-1"
/>
{
const mappings = [...((element as CardStatusElement).statusMappings || [])];
mappings[i] = { ...mappings[i], color: e.target.value };
onUpdate({ ...element, statusMappings: mappings } as CardStatusElement);
}}
className="w-8 h-8 rounded cursor-pointer border border-gray-200"
/>
))}
>
)}
{/* 빈 공간 설정 */}
{element.type === "spacer" && (
onUpdate({ ...element, height: parseInt(e.target.value) || 16 } as CardSpacerElement)}
className="h-9 text-sm"
/>
)}
{/* 고정 텍스트 설정 */}
{element.type === "staticText" && (
<>
>
)}
);
}
export function CardCanvasEditor({ rows, onRowsChange }: CardCanvasEditorProps) {
const [selectedCell, setSelectedCell] = useState<{
rowIndex: number;
cellIndex: number;
} | null>(null);
const [collapsedRows, setCollapsedRows] = useState