"use client"; import React, { useRef, useState, useEffect } from "react"; import { ComponentData } from "@/types/screen"; interface ResponsiveGridRendererProps { components: ComponentData[]; canvasWidth: number; canvasHeight: number; renderComponent: (component: ComponentData) => React.ReactNode; } function getComponentTypeId(component: ComponentData): string { const direct = (component as any).componentType || (component as any).widgetType; if (direct) return direct; const url = (component as any).url; if (url && typeof url === "string") { const parts = url.split("/"); return parts[parts.length - 1]; } return component.type || ""; } /** * CSS transform scale 기반 렌더링. * 디자이너와 동일하게 캔버스 해상도(px)로 레이아웃 후 CSS scale로 축소/확대. * 텍스트, 패딩, 버튼 등 모든 요소가 균일하게 스케일링되어 WYSIWYG 보장. */ function ProportionalRenderer({ components, canvasWidth, canvasHeight, renderComponent, }: ResponsiveGridRendererProps) { const containerRef = useRef(null); const [containerW, setContainerW] = useState(0); useEffect(() => { const el = containerRef.current; if (!el) return; const ro = new ResizeObserver((entries) => { const w = entries[0]?.contentRect.width; if (w && w > 0) setContainerW(w); }); ro.observe(el); return () => ro.disconnect(); }, []); const topLevel = components.filter((c) => !c.parentId); const scale = containerW > 0 ? containerW / canvasWidth : 1; const maxBottom = topLevel.reduce((max, c) => { const bottom = c.position.y + (c.size?.height || 40); return Math.max(max, bottom); }, 0); return (
0 ? `${maxBottom * scale}px` : "200px" }} > {containerW > 0 && (
{topLevel.map((component) => { const typeId = getComponentTypeId(component); return (
{renderComponent(component)}
); })}
)}
); } export function ResponsiveGridRenderer({ components, canvasWidth, canvasHeight, renderComponent, }: ResponsiveGridRendererProps) { return ( ); } export default ResponsiveGridRenderer;