From 660f81edbc869553f1d0003bbf46985bd2c9a96b Mon Sep 17 00:00:00 2001 From: SeongHyun Kim Date: Mon, 17 Nov 2025 10:01:09 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20table-list=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=ED=81=AC=EA=B8=B0=20=EC=A1=B0=EC=A0=88=20=EB=B0=8F?= =?UTF-8?q?=20=EB=8F=99=EA=B8=B0=ED=99=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기본 너비 120px → 1000px 변경 - 선택 영역과 컴포넌트 영역 크기 동기화 - 편집 패널에서 너비/높이 조절 시 즉시 반영되도록 개선 --- .../screen/RealtimePreviewDynamic.tsx | 32 +++++++++++-------- frontend/components/screen/ScreenDesigner.tsx | 31 +++++++++++++++++- .../lib/registry/DynamicComponentRenderer.tsx | 18 +++++------ .../CustomerItemMappingComponent.tsx | 6 ++-- .../table-list/SingleTableWithSticky.tsx | 5 ++- .../table-list/TableListComponent.tsx | 32 ++++++++++++------- .../registry/components/table-list/index.ts | 2 +- 7 files changed, 84 insertions(+), 42 deletions(-) diff --git a/frontend/components/screen/RealtimePreviewDynamic.tsx b/frontend/components/screen/RealtimePreviewDynamic.tsx index 9ae2db82..b3263275 100644 --- a/frontend/components/screen/RealtimePreviewDynamic.tsx +++ b/frontend/components/screen/RealtimePreviewDynamic.tsx @@ -212,14 +212,7 @@ export const RealtimePreviewDynamic: React.FC = ({ // 컴포넌트 기본 스타일 - 레이아웃은 항상 맨 아래 // 🔥 모든 컴포넌트를 픽셀 기준으로 통일 (스케일로만 조정) const getWidth = () => { - // table-list는 화면 너비 전체 사용 - if (component.componentConfig?.type === "table-list") { - // 디자인 해상도 기준으로 픽셀 반환 - const screenWidth = 1920; // 기본 디자인 해상도 - return `${screenWidth}px`; - } - - // 모든 컴포넌트는 size.width 픽셀 사용 + // 모든 컴포넌트는 size.width 픽셀 사용 (table-list 포함) const width = `${size?.width || 100}px`; return width; }; @@ -259,19 +252,30 @@ export const RealtimePreviewDynamic: React.FC = ({ } : component; - // componentStyle에서 width, height 제거 (size.width, size.height만 사용) - const { width: _styleWidth, height: _styleHeight, ...restComponentStyle } = componentStyle || {}; - const baseStyle = { left: `${position.x}px`, top: `${position.y}px`, - ...restComponentStyle, // width/height 제외한 스타일 먼저 적용 - width: getWidth(), // size.width로 덮어쓰기 - height: getHeight(), // size.height로 덮어쓰기 + ...componentStyle, // componentStyle 전체 적용 (DynamicComponentRenderer에서 이미 size가 변환됨) + width: getWidth(), // getWidth() 우선 (table-list 등 특수 케이스) + height: getHeight(), // getHeight() 우선 (flow-widget 등 특수 케이스) zIndex: component.type === "layout" ? 1 : position.z || 2, right: undefined, }; + // 디버깅: 크기 정보 로그 + if (component.id && isSelected) { + console.log("📐 RealtimePreview baseStyle:", { + componentId: component.id, + componentType: (component as any).componentType || component.type, + sizeWidth: size?.width, + sizeHeight: size?.height, + styleWidth: componentStyle?.width, + styleHeight: componentStyle?.height, + baseStyleWidth: baseStyle.width, + baseStyleHeight: baseStyle.height, + }); + } + // 🔍 DOM 렌더링 후 실제 크기 측정 const innerDivRef = React.useRef(null); const outerDivRef = React.useRef(null); diff --git a/frontend/components/screen/ScreenDesigner.tsx b/frontend/components/screen/ScreenDesigner.tsx index cafd3c41..dcd80a62 100644 --- a/frontend/components/screen/ScreenDesigner.tsx +++ b/frontend/components/screen/ScreenDesigner.tsx @@ -525,6 +525,34 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD const finalKey = pathParts[pathParts.length - 1]; current[finalKey] = value; + // 🆕 size 변경 시 style도 함께 업데이트 (파란 테두리와 실제 크기 동기화) + if (path === "size.width" || path === "size.height" || path === "size") { + if (!newComp.style) { + newComp.style = {}; + } + + if (path === "size.width") { + newComp.style.width = `${value}px`; + } else if (path === "size.height") { + newComp.style.height = `${value}px`; + } else if (path === "size") { + // size 객체 전체가 변경된 경우 + if (value.width !== undefined) { + newComp.style.width = `${value.width}px`; + } + if (value.height !== undefined) { + newComp.style.height = `${value.height}px`; + } + } + + console.log("🔄 size 변경 → style 동기화:", { + componentId: newComp.id, + path, + value, + updatedStyle: newComp.style, + }); + } + // gridColumns 변경 시 크기 자동 업데이트 제거 (격자 시스템 제거됨) // if (path === "gridColumns" && prevLayout.gridSettings) { // const updatedSize = updateSizeFromGridColumns(newComp, prevLayout.gridSettings as GridUtilSettings); @@ -2217,7 +2245,8 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD labelColor: "#212121", labelFontWeight: "500", labelMarginBottom: "4px", - width: `${widthPercent}%`, // gridColumns에 맞춘 퍼센트 너비 + width: `${componentSize.width}px`, // size와 동기화 (픽셀 단위) + height: `${componentSize.height}px`, // size와 동기화 (픽셀 단위) }, }; diff --git a/frontend/lib/registry/DynamicComponentRenderer.tsx b/frontend/lib/registry/DynamicComponentRenderer.tsx index 1791e9b0..144b1f1a 100644 --- a/frontend/lib/registry/DynamicComponentRenderer.tsx +++ b/frontend/lib/registry/DynamicComponentRenderer.tsx @@ -287,18 +287,16 @@ export const DynamicComponentRenderer: React.FC = }; // 렌더러 props 구성 - // component.style에서 height 제거 (RealtimePreviewDynamic에서 size.height로 처리) - // 단, layout 타입 컴포넌트(split-panel-layout 등)는 height 유지 - const isLayoutComponent = - component.type === "layout" || - componentType === "split-panel-layout" || - componentType?.includes("layout"); - - const { height: _height, ...styleWithoutHeight } = component.style || {}; - // 숨김 값 추출 const hiddenValue = component.hidden || component.componentConfig?.hidden; + // size.width와 size.height를 style.width와 style.height로 변환 + const finalStyle: React.CSSProperties = { + ...component.style, + width: component.size?.width ? `${component.size.width}px` : component.style?.width, + height: component.size?.height ? `${component.size.height}px` : component.style?.height, + }; + const rendererProps = { component, isSelected, @@ -307,7 +305,7 @@ export const DynamicComponentRenderer: React.FC = onDragEnd, size: component.size || newComponent.defaultSize, position: component.position, - style: isLayoutComponent ? component.style : styleWithoutHeight, // 레이아웃은 height 유지 + style: finalStyle, // size를 포함한 최종 style config: component.componentConfig, componentConfig: component.componentConfig, value: currentValue, // formData에서 추출한 현재 값 전달 diff --git a/frontend/lib/registry/components/customer-item-mapping/CustomerItemMappingComponent.tsx b/frontend/lib/registry/components/customer-item-mapping/CustomerItemMappingComponent.tsx index a1cd73e5..178f8a4a 100644 --- a/frontend/lib/registry/components/customer-item-mapping/CustomerItemMappingComponent.tsx +++ b/frontend/lib/registry/components/customer-item-mapping/CustomerItemMappingComponent.tsx @@ -75,13 +75,15 @@ export const CustomerItemMappingComponent: React.FC = ({ className="relative flex h-full flex-col overflow-hidden bg-background shadow-sm" style={{ width: "100%", - maxWidth: "100%", + height: "100%", boxSizing: "border-box", }} > -
+
= ({ } const componentStyle: React.CSSProperties = { - width: calculatedWidth, - height: isDesignMode ? "auto" : "100%", - minHeight: isDesignMode ? "300px" : "100%", + position: "relative", display: "flex", flexDirection: "column", backgroundColor: "hsl(var(--background))", overflow: "hidden", - ...style, - // width는 항상 100%로 고정 (부모 컨테이너가 gridColumns로 크기 제어) + boxSizing: "border-box", width: "100%", + height: "100%", + minHeight: isDesignMode ? "300px" : "100%", + ...style, // style prop이 위의 기본값들을 덮어씀 }; // ======================================== @@ -1875,7 +1875,7 @@ export const TableListComponent: React.FC = ({ onDragStart: isDesignMode ? onDragStart : undefined, onDragEnd: isDesignMode ? onDragEnd : undefined, draggable: isDesignMode, - className: cn(className, isDesignMode && "cursor-move"), + className: cn("w-full h-full", className, isDesignMode && "cursor-move"), // customer-item-mapping과 동일 style: componentStyle, }; @@ -1992,17 +1992,27 @@ export const TableListComponent: React.FC = ({ {/* 테이블 컨테이너 */}
{/* 스크롤 영역 */}
{/* 테이블 */}