feat: 탭 컨테이너로의 드롭 처리 기능 추가

- 드래그 종료 시 탭 컨테이너에 컴포넌트를 드롭할 수 있는 기능을 구현하였습니다.
- 드래그된 컴포넌트를 탭 내부 컴포넌트로 변환하여 해당 탭에 추가하는 로직을 추가하였습니다.
- 드래그 상태 초기화 및 성공적인 드롭 시 사용자에게 알림을 표시하도록 하였습니다.
This commit is contained in:
kjs
2026-01-26 11:04:39 +09:00
parent 752e16bd40
commit b1fba586cb

View File

@@ -3568,8 +3568,104 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
);
// 드래그 종료
const endDrag = useCallback(() => {
const endDrag = useCallback((mouseEvent?: MouseEvent) => {
if (dragState.isDragging && dragState.draggedComponent) {
// 🎯 탭 컨테이너로의 드롭 처리 (기존 컴포넌트 이동)
if (mouseEvent) {
const dropTarget = document.elementFromPoint(mouseEvent.clientX, mouseEvent.clientY) as HTMLElement;
const tabsContainer = dropTarget?.closest('[data-tabs-container="true"]');
if (tabsContainer) {
const containerId = tabsContainer.getAttribute("data-component-id");
const activeTabId = tabsContainer.getAttribute("data-active-tab-id");
if (containerId && activeTabId) {
const targetComponent = layout.components.find((c) => c.id === containerId);
const compType = (targetComponent as any)?.componentType;
// 자기 자신을 자신에게 드롭하는 것 방지
if (targetComponent &&
(compType === "tabs-widget" || compType === "v2-tabs-widget") &&
dragState.draggedComponent !== containerId) {
const draggedComponent = layout.components.find((c) => c.id === dragState.draggedComponent);
if (draggedComponent) {
const currentConfig = (targetComponent as any).componentConfig || {};
const tabs = currentConfig.tabs || [];
// 탭 컨텐츠 영역 기준 드롭 위치 계산
const tabContentRect = tabsContainer.getBoundingClientRect();
const dropX = (mouseEvent.clientX - tabContentRect.left) / zoomLevel;
const dropY = (mouseEvent.clientY - tabContentRect.top) / zoomLevel;
// 기존 컴포넌트를 탭 내부 컴포넌트로 변환
const newTabComponent = {
id: `tab_comp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
componentType: (draggedComponent as any).componentType || draggedComponent.type,
label: (draggedComponent as any).label || "컴포넌트",
position: { x: Math.max(0, dropX), y: Math.max(0, dropY) },
size: draggedComponent.size || { width: 200, height: 100 },
componentConfig: (draggedComponent as any).componentConfig || {},
style: (draggedComponent as any).style || {},
};
// 해당 탭에 컴포넌트 추가
const updatedTabs = tabs.map((tab: any) => {
if (tab.id === activeTabId) {
return {
...tab,
components: [...(tab.components || []), newTabComponent],
};
}
return tab;
});
// 탭 컴포넌트 업데이트 + 원래 컴포넌트 캔버스에서 제거
const newLayout = {
...layout,
components: layout.components
.filter((c) => c.id !== dragState.draggedComponent) // 캔버스에서 제거
.map((c) => {
if (c.id === containerId) {
return {
...c,
componentConfig: {
...currentConfig,
tabs: updatedTabs,
},
};
}
return c;
}),
};
setLayout(newLayout);
saveToHistory(newLayout);
setSelectedComponent(null);
toast.success("컴포넌트가 탭으로 이동되었습니다");
// 드래그 상태 초기화 후 종료
setDragState({
isDragging: false,
draggedComponent: null,
draggedComponents: [],
originalPosition: { x: 0, y: 0, z: 1 },
currentPosition: { x: 0, y: 0, z: 1 },
grabOffset: { x: 0, y: 0 },
justFinishedDrag: true,
});
setTimeout(() => {
setDragState((prev) => ({ ...prev, justFinishedDrag: false }));
}, 100);
return; // 탭으로 이동 완료, 일반 드래그 종료 로직 스킵
}
}
}
}
}
// 주 드래그 컴포넌트의 최종 위치 계산
const draggedComponent = layout.components.find((c) => c.id === dragState.draggedComponent);
let finalPosition = dragState.currentPosition;
@@ -4445,12 +4541,12 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
}
};
const handleMouseUp = () => {
const handleMouseUp = (e: MouseEvent) => {
if (dragState.isDragging) {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
endDrag();
endDrag(e);
} else if (selectionDrag.isSelecting) {
endSelectionDrag();
}