From 3172f772badc53de1e337fa8cf248a521e57dc4b Mon Sep 17 00:00:00 2001 From: kjs Date: Thu, 23 Oct 2025 15:14:45 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EA=B0=80?= =?UTF-8?q?=20=ED=99=94=EB=A9=B4=20=EB=B2=97=EC=96=B4=EB=82=98=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../screen/RealtimePreviewDynamic.tsx | 2 +- frontend/components/screen/ScreenDesigner.tsx | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/frontend/components/screen/RealtimePreviewDynamic.tsx b/frontend/components/screen/RealtimePreviewDynamic.tsx index 269ad3bb..67e802f0 100644 --- a/frontend/components/screen/RealtimePreviewDynamic.tsx +++ b/frontend/components/screen/RealtimePreviewDynamic.tsx @@ -183,7 +183,7 @@ export const RealtimePreviewDynamic: React.FC = ({ const selectionStyle = isSelected ? { outline: "2px solid rgb(59, 130, 246)", - outlineOffset: "2px", + outlineOffset: "0px", // 스크롤 방지를 위해 0으로 설정 zIndex: 20, } : {}; diff --git a/frontend/components/screen/ScreenDesigner.tsx b/frontend/components/screen/ScreenDesigner.tsx index 8031088b..7fc457d5 100644 --- a/frontend/components/screen/ScreenDesigner.tsx +++ b/frontend/components/screen/ScreenDesigner.tsx @@ -2906,9 +2906,18 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD const relativeMouseX = event.clientX - rect.left; const relativeMouseY = event.clientY - rect.top; + // 컴포넌트 크기 가져오기 + const draggedComp = layout.components.find((c) => c.id === dragState.draggedComponent.id); + const componentWidth = draggedComp?.size?.width || 100; + const componentHeight = draggedComp?.size?.height || 40; + + // 경계 제한 적용 + const rawX = relativeMouseX - dragState.grabOffset.x; + const rawY = relativeMouseY - dragState.grabOffset.y; + const newPosition = { - x: relativeMouseX - dragState.grabOffset.x, - y: relativeMouseY - dragState.grabOffset.y, + x: Math.max(0, Math.min(rawX, screenResolution.width - componentWidth)), + y: Math.max(0, Math.min(rawY, screenResolution.height - componentHeight)), z: (dragState.draggedComponent.position as Position).z || 1, }; @@ -3002,6 +3011,14 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD z: originalComponent.position.z || 1, }; + // 캔버스 경계 제한 (컴포넌트가 화면 밖으로 나가지 않도록) + const componentWidth = comp.size?.width || 100; + const componentHeight = comp.size?.height || 40; + + // 최소 위치: 0, 최대 위치: 캔버스 크기 - 컴포넌트 크기 + newPosition.x = Math.max(0, Math.min(newPosition.x, screenResolution.width - componentWidth)); + newPosition.y = Math.max(0, Math.min(newPosition.y, screenResolution.height - componentHeight)); + // 그룹 내부 컴포넌트인 경우 패딩을 고려한 격자 스냅 적용 if (comp.parentId && layout.gridSettings?.snapToGrid && gridInfo) { const { columnWidth } = gridInfo; @@ -4090,7 +4107,7 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD >
{ if (e.target === e.currentTarget && !selectionDrag.wasSelecting && !isPanMode) { setSelectedComponent(null);