jskim-node #421

Merged
kjs merged 33 commits from jskim-node into main 2026-03-18 17:43:51 +09:00
3 changed files with 46 additions and 32 deletions
Showing only changes of commit ba8a2fec2b - Show all commits

View File

@ -592,10 +592,10 @@ const RealtimePreviewDynamicComponent: React.FC<RealtimePreviewProps> = ({
isResizing ? "none" : isResizing ? "none" :
isOnSplitPanel ? (isDraggingSplitPanel ? "none" : "left 0.15s ease-out, width 0.15s ease-out") : undefined, isOnSplitPanel ? (isDraggingSplitPanel ? "none" : "left 0.15s ease-out, width 0.15s ease-out") : undefined,
} : { } : {
// 런타임 모드: 부모(ResponsiveGridRenderer)가 위치/너비 관리 // 런타임 모드: CSS scale 기반 - 캔버스 픽셀 크기 그대로 사용, 부모가 scale()로 축소
...safeComponentStyle, ...safeComponentStyle,
width: "100%", width: "100%",
height: displayHeight, height: "100%",
position: "relative" as const, position: "relative" as const,
}; };

View File

@ -23,8 +23,9 @@ function getComponentTypeId(component: ComponentData): string {
} }
/** /**
* . * CSS transform scale .
* , . * (px) CSS scale로 /.
* , , WYSIWYG .
*/ */
function ProportionalRenderer({ function ProportionalRenderer({
components, components,
@ -47,7 +48,7 @@ function ProportionalRenderer({
}, []); }, []);
const topLevel = components.filter((c) => !c.parentId); const topLevel = components.filter((c) => !c.parentId);
const ratio = containerW > 0 ? containerW / canvasWidth : 1; const scale = containerW > 0 ? containerW / canvasWidth : 1;
const maxBottom = topLevel.reduce((max, c) => { const maxBottom = topLevel.reduce((max, c) => {
const bottom = c.position.y + (c.size?.height || 40); const bottom = c.position.y + (c.size?.height || 40);
@ -58,11 +59,20 @@ function ProportionalRenderer({
<div <div
ref={containerRef} ref={containerRef}
data-screen-runtime="true" data-screen-runtime="true"
className="bg-background relative w-full overflow-x-hidden" className="bg-background w-full overflow-hidden"
style={{ minHeight: containerW > 0 ? `${maxBottom * ratio}px` : "200px" }} style={{ height: containerW > 0 ? `${maxBottom * scale}px` : "200px" }}
> >
{containerW > 0 && {containerW > 0 && (
topLevel.map((component) => { <div
style={{
width: `${canvasWidth}px`,
height: `${maxBottom}px`,
transform: `scale(${scale})`,
transformOrigin: "top left",
position: "relative",
}}
>
{topLevel.map((component) => {
const typeId = getComponentTypeId(component); const typeId = getComponentTypeId(component);
return ( return (
<div <div
@ -71,10 +81,10 @@ function ProportionalRenderer({
data-component-type={typeId} data-component-type={typeId}
style={{ style={{
position: "absolute", position: "absolute",
left: `${(component.position.x / canvasWidth) * 100}%`, left: `${component.position.x}px`,
top: `${component.position.y * ratio}px`, top: `${component.position.y}px`,
width: `${((component.size?.width || 100) / canvasWidth) * 100}%`, width: `${component.size?.width || 100}px`,
height: `${(component.size?.height || 40) * ratio}px`, height: `${component.size?.height || 40}px`,
zIndex: component.position.z || 1, zIndex: component.position.z || 1,
}} }}
> >
@ -83,6 +93,8 @@ function ProportionalRenderer({
); );
})} })}
</div> </div>
)}
</div>
); );
} }

View File

@ -2522,9 +2522,11 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
// 우측 패널 컬럼 헤더 드래그 (디자인 모드에서 컬럼 순서 변경) // 우측 패널 컬럼 헤더 드래그 (디자인 모드에서 컬럼 순서 변경)
const handleRightColumnDragStart = useCallback( const handleRightColumnDragStart = useCallback(
(columnIndex: number, source: "main" | number) => { (e: React.DragEvent, columnIndex: number, source: "main" | number) => {
setRightDraggedColumnIndex(columnIndex); setRightDraggedColumnIndex(columnIndex);
setRightDragSource(source); setRightDragSource(source);
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.setData("text/plain", `col-${source}-${columnIndex}`);
}, },
[], [],
); );
@ -4181,7 +4183,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
isDragging && "opacity-50", isDragging && "opacity-50",
)} )}
draggable={canDragTabColumns} draggable={canDragTabColumns}
onDragStart={() => canDragTabColumns && handleRightColumnDragStart(idx, tabIndex)} onDragStart={(e) => canDragTabColumns && handleRightColumnDragStart(e, idx, tabIndex)}
onDragOver={(e) => canDragTabColumns && handleRightColumnDragOver(e, idx)} onDragOver={(e) => canDragTabColumns && handleRightColumnDragOver(e, idx)}
onDragEnd={handleRightColumnDragEnd} onDragEnd={handleRightColumnDragEnd}
onDrop={(e) => canDragTabColumns && handleRightColumnDrop(e, idx, tabIndex)} onDrop={(e) => canDragTabColumns && handleRightColumnDrop(e, idx, tabIndex)}
@ -4318,7 +4320,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
isDragging && "opacity-50", isDragging && "opacity-50",
)} )}
draggable={canDragListTabColumns} draggable={canDragListTabColumns}
onDragStart={() => canDragListTabColumns && handleRightColumnDragStart(idx, listTabIndex)} onDragStart={(e) => canDragListTabColumns && handleRightColumnDragStart(e, idx, listTabIndex)}
onDragOver={(e) => canDragListTabColumns && handleRightColumnDragOver(e, idx)} onDragOver={(e) => canDragListTabColumns && handleRightColumnDragOver(e, idx)}
onDragEnd={handleRightColumnDragEnd} onDragEnd={handleRightColumnDragEnd}
onDrop={(e) => canDragListTabColumns && handleRightColumnDrop(e, idx, listTabIndex)} onDrop={(e) => canDragListTabColumns && handleRightColumnDrop(e, idx, listTabIndex)}
@ -4745,7 +4747,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
textAlign: col.align || "left", textAlign: col.align || "left",
}} }}
draggable={isDraggable} draggable={isDraggable}
onDragStart={() => isDraggable && handleRightColumnDragStart(configColIndex, "main")} onDragStart={(e) => isDraggable && handleRightColumnDragStart(e, configColIndex, "main")}
onDragOver={(e) => isDraggable && handleRightColumnDragOver(e, configColIndex)} onDragOver={(e) => isDraggable && handleRightColumnDragOver(e, configColIndex)}
onDragEnd={handleRightColumnDragEnd} onDragEnd={handleRightColumnDragEnd}
onDrop={(e) => isDraggable && handleRightColumnDrop(e, configColIndex, "main")} onDrop={(e) => isDraggable && handleRightColumnDrop(e, configColIndex, "main")}