분할패널 버튼 이동 가능하게 수정

This commit is contained in:
kjs
2025-12-11 18:40:39 +09:00
parent 88024b4e60
commit 016b8f707b
8 changed files with 1021 additions and 162 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import React, { useState, useCallback, useEffect, useMemo } from "react";
import React, { useState, useCallback, useEffect, useMemo, useRef } from "react";
import { ComponentRendererProps } from "../../types";
import { SplitPanelLayoutConfig } from "./types";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
@@ -36,6 +36,7 @@ import { Label } from "@/components/ui/label";
import { useTableOptions } from "@/contexts/TableOptionsContext";
import { TableFilter, ColumnVisibility, GroupSumConfig } from "@/types/table-options";
import { useAuth } from "@/hooks/useAuth";
import { useSplitPanel } from "./SplitPanelContext";
export interface SplitPanelLayoutComponentProps extends ComponentRendererProps {
// 추가 props
@@ -182,6 +183,120 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
const [leftWidth, setLeftWidth] = useState(splitRatio);
const containerRef = React.useRef<HTMLDivElement>(null);
// 🆕 SplitPanel Resize Context 연동 (버튼 등 외부 컴포넌트와 드래그 리사이즈 상태 공유)
const splitPanelContext = useSplitPanel();
const {
registerSplitPanel: ctxRegisterSplitPanel,
unregisterSplitPanel: ctxUnregisterSplitPanel,
updateSplitPanel: ctxUpdateSplitPanel,
} = splitPanelContext;
const splitPanelId = `split-panel-${component.id}`;
// 디버깅: Context 연결 상태 확인
console.log("🔗 [SplitPanelLayout] Context 연결 상태:", {
componentId: component.id,
splitPanelId,
hasRegisterFunc: typeof ctxRegisterSplitPanel === "function",
splitPanelsSize: splitPanelContext.splitPanels?.size ?? "없음",
});
// Context에 분할 패널 등록 (좌표 정보 포함) - 마운트 시 1회만 실행
const ctxRegisterRef = useRef(ctxRegisterSplitPanel);
const ctxUnregisterRef = useRef(ctxUnregisterSplitPanel);
ctxRegisterRef.current = ctxRegisterSplitPanel;
ctxUnregisterRef.current = ctxUnregisterSplitPanel;
useEffect(() => {
// 컴포넌트의 위치와 크기 정보
const panelX = component.position?.x || 0;
const panelY = component.position?.y || 0;
const panelWidth = component.size?.width || component.style?.width || 800;
const panelHeight = component.size?.height || component.style?.height || 600;
const panelInfo = {
x: panelX,
y: panelY,
width: typeof panelWidth === "number" ? panelWidth : parseInt(String(panelWidth)) || 800,
height: typeof panelHeight === "number" ? panelHeight : parseInt(String(panelHeight)) || 600,
leftWidthPercent: splitRatio, // 초기값은 splitRatio 사용
initialLeftWidthPercent: splitRatio,
isDragging: false,
};
console.log("📦 [SplitPanelLayout] Context에 분할 패널 등록:", {
splitPanelId,
panelInfo,
});
ctxRegisterRef.current(splitPanelId, panelInfo);
return () => {
console.log("📦 [SplitPanelLayout] Context에서 분할 패널 해제:", splitPanelId);
ctxUnregisterRef.current(splitPanelId);
};
// 마운트/언마운트 시에만 실행, 위치/크기 변경은 별도 업데이트로 처리
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [splitPanelId]);
// 위치/크기 변경 시 Context 업데이트 (등록 후)
const ctxUpdateRef = useRef(ctxUpdateSplitPanel);
ctxUpdateRef.current = ctxUpdateSplitPanel;
useEffect(() => {
const panelX = component.position?.x || 0;
const panelY = component.position?.y || 0;
const panelWidth = component.size?.width || component.style?.width || 800;
const panelHeight = component.size?.height || component.style?.height || 600;
ctxUpdateRef.current(splitPanelId, {
x: panelX,
y: panelY,
width: typeof panelWidth === "number" ? panelWidth : parseInt(String(panelWidth)) || 800,
height: typeof panelHeight === "number" ? panelHeight : parseInt(String(panelHeight)) || 600,
});
}, [
splitPanelId,
component.position?.x,
component.position?.y,
component.size?.width,
component.size?.height,
component.style?.width,
component.style?.height,
]);
// leftWidth 변경 시 Context 업데이트
useEffect(() => {
ctxUpdateRef.current(splitPanelId, { leftWidthPercent: leftWidth });
}, [leftWidth, splitPanelId]);
// 드래그 상태 변경 시 Context 업데이트
// 이전 드래그 상태를 추적하여 드래그 종료 시점을 감지
const prevIsDraggingRef = useRef(false);
useEffect(() => {
const wasJustDragging = prevIsDraggingRef.current && !isDragging;
if (isDragging) {
// 드래그 시작 시: 현재 비율을 초기 비율로 저장
ctxUpdateRef.current(splitPanelId, {
isDragging: true,
initialLeftWidthPercent: leftWidth,
});
} else if (wasJustDragging) {
// 드래그 종료 시: 최종 비율을 초기 비율로 업데이트 (버튼 위치 고정)
ctxUpdateRef.current(splitPanelId, {
isDragging: false,
initialLeftWidthPercent: leftWidth,
});
console.log("🛑 [SplitPanelLayout] 드래그 종료 - 버튼 위치 고정:", {
splitPanelId,
finalLeftWidthPercent: leftWidth,
});
}
prevIsDraggingRef.current = isDragging;
}, [isDragging, splitPanelId, leftWidth]);
// 🆕 그룹별 합산된 데이터 계산
const summedLeftData = useMemo(() => {
console.log("🔍 [그룹합산] leftGroupSumConfig:", leftGroupSumConfig);