분할패널 버튼 이동 가능하게 수정
This commit is contained in:
@@ -0,0 +1,400 @@
|
||||
"use client";
|
||||
|
||||
import React, { createContext, useContext, useState, useCallback, useRef, useMemo } from "react";
|
||||
|
||||
/**
|
||||
* SplitPanelResize Context 타입 정의
|
||||
* 분할 패널의 드래그 리사이즈 상태를 외부 컴포넌트(버튼 등)와 공유하기 위한 Context
|
||||
*
|
||||
* 주의: contexts/SplitPanelContext.tsx는 데이터 전달용 Context이고,
|
||||
* 이 Context는 드래그 리사이즈 시 버튼 위치 조정을 위한 별도 Context입니다.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 분할 패널 정보 (컴포넌트 좌표 기준)
|
||||
*/
|
||||
export interface SplitPanelInfo {
|
||||
id: string;
|
||||
// 분할 패널의 좌표 (스크린 캔버스 기준, px)
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
// 좌측 패널 비율 (0-100)
|
||||
leftWidthPercent: number;
|
||||
// 초기 좌측 패널 비율 (드래그 시작 시점)
|
||||
initialLeftWidthPercent: number;
|
||||
// 드래그 중 여부
|
||||
isDragging: boolean;
|
||||
}
|
||||
|
||||
export interface SplitPanelResizeContextValue {
|
||||
// 등록된 분할 패널들
|
||||
splitPanels: Map<string, SplitPanelInfo>;
|
||||
|
||||
// 분할 패널 등록/해제/업데이트
|
||||
registerSplitPanel: (id: string, info: Omit<SplitPanelInfo, "id">) => void;
|
||||
unregisterSplitPanel: (id: string) => void;
|
||||
updateSplitPanel: (id: string, updates: Partial<SplitPanelInfo>) => void;
|
||||
|
||||
// 컴포넌트가 어떤 분할 패널의 좌측 영역 위에 있는지 확인
|
||||
// 반환값: { panelId, offsetX } 또는 null
|
||||
getOverlappingSplitPanel: (
|
||||
componentX: number,
|
||||
componentY: number,
|
||||
componentWidth: number,
|
||||
componentHeight: number,
|
||||
) => { panelId: string; panel: SplitPanelInfo; isInLeftPanel: boolean } | null;
|
||||
|
||||
// 컴포넌트의 조정된 X 좌표 계산
|
||||
// 분할 패널 좌측 영역 위에 있으면, 드래그에 따라 조정된 X 좌표 반환
|
||||
getAdjustedX: (componentX: number, componentY: number, componentWidth: number, componentHeight: number) => number;
|
||||
|
||||
// 레거시 호환 (단일 분할 패널용)
|
||||
leftWidthPercent: number;
|
||||
containerRect: DOMRect | null;
|
||||
dividerX: number;
|
||||
isDragging: boolean;
|
||||
splitPanelId: string | null;
|
||||
updateLeftWidth: (percent: number) => void;
|
||||
updateContainerRect: (rect: DOMRect | null) => void;
|
||||
updateDragging: (dragging: boolean) => void;
|
||||
}
|
||||
|
||||
// Context 생성
|
||||
const SplitPanelResizeContext = createContext<SplitPanelResizeContextValue | null>(null);
|
||||
|
||||
/**
|
||||
* SplitPanelResize Context Provider
|
||||
* 스크린 빌더 레벨에서 감싸서 사용
|
||||
*/
|
||||
export const SplitPanelProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
// 등록된 분할 패널들
|
||||
const splitPanelsRef = useRef<Map<string, SplitPanelInfo>>(new Map());
|
||||
const [, forceUpdate] = useState(0);
|
||||
|
||||
// 레거시 호환용 상태
|
||||
const [legacyLeftWidthPercent, setLegacyLeftWidthPercent] = useState(30);
|
||||
const [legacyContainerRect, setLegacyContainerRect] = useState<DOMRect | null>(null);
|
||||
const [legacyIsDragging, setLegacyIsDragging] = useState(false);
|
||||
const [legacySplitPanelId, setLegacySplitPanelId] = useState<string | null>(null);
|
||||
|
||||
// 분할 패널 등록
|
||||
const registerSplitPanel = useCallback((id: string, info: Omit<SplitPanelInfo, "id">) => {
|
||||
splitPanelsRef.current.set(id, { id, ...info });
|
||||
setLegacySplitPanelId(id);
|
||||
setLegacyLeftWidthPercent(info.leftWidthPercent);
|
||||
forceUpdate((n) => n + 1);
|
||||
}, []);
|
||||
|
||||
// 분할 패널 해제
|
||||
const unregisterSplitPanel = useCallback(
|
||||
(id: string) => {
|
||||
splitPanelsRef.current.delete(id);
|
||||
if (legacySplitPanelId === id) {
|
||||
setLegacySplitPanelId(null);
|
||||
}
|
||||
forceUpdate((n) => n + 1);
|
||||
},
|
||||
[legacySplitPanelId],
|
||||
);
|
||||
|
||||
// 분할 패널 업데이트
|
||||
const updateSplitPanel = useCallback((id: string, updates: Partial<SplitPanelInfo>) => {
|
||||
const panel = splitPanelsRef.current.get(id);
|
||||
if (panel) {
|
||||
const updatedPanel = { ...panel, ...updates };
|
||||
splitPanelsRef.current.set(id, updatedPanel);
|
||||
|
||||
// 레거시 호환 상태 업데이트
|
||||
if (updates.leftWidthPercent !== undefined) {
|
||||
setLegacyLeftWidthPercent(updates.leftWidthPercent);
|
||||
}
|
||||
if (updates.isDragging !== undefined) {
|
||||
setLegacyIsDragging(updates.isDragging);
|
||||
}
|
||||
|
||||
forceUpdate((n) => n + 1);
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* 컴포넌트가 어떤 분할 패널의 좌측 영역 위에 있는지 확인
|
||||
*/
|
||||
const getOverlappingSplitPanel = useCallback(
|
||||
(
|
||||
componentX: number,
|
||||
componentY: number,
|
||||
componentWidth: number,
|
||||
componentHeight: number,
|
||||
): { panelId: string; panel: SplitPanelInfo; isInLeftPanel: boolean } | null => {
|
||||
for (const [panelId, panel] of splitPanelsRef.current) {
|
||||
// 컴포넌트의 중심점
|
||||
const componentCenterX = componentX + componentWidth / 2;
|
||||
const componentCenterY = componentY + componentHeight / 2;
|
||||
|
||||
// 컴포넌트가 분할 패널 영역 내에 있는지 확인
|
||||
const isInPanelX = componentCenterX >= panel.x && componentCenterX <= panel.x + panel.width;
|
||||
const isInPanelY = componentCenterY >= panel.y && componentCenterY <= panel.y + panel.height;
|
||||
|
||||
if (isInPanelX && isInPanelY) {
|
||||
// 좌측 패널의 현재 너비 (px)
|
||||
const leftPanelWidth = (panel.width * panel.leftWidthPercent) / 100;
|
||||
// 좌측 패널 경계 (분할 패널 기준 상대 좌표)
|
||||
const dividerX = panel.x + leftPanelWidth;
|
||||
|
||||
// 컴포넌트 중심이 좌측 패널 내에 있는지 확인
|
||||
const isInLeftPanel = componentCenterX < dividerX;
|
||||
|
||||
return { panelId, panel, isInLeftPanel };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
/**
|
||||
* 컴포넌트의 조정된 X 좌표 계산
|
||||
* 분할 패널 좌측 영역 위에 있으면, 드래그에 따라 조정된 X 좌표 반환
|
||||
*
|
||||
* 핵심 로직:
|
||||
* - 버튼의 원래 X 좌표가 초기 좌측 패널 너비 내에서 어느 비율에 있는지 계산
|
||||
* - 드래그로 좌측 패널 너비가 바뀌면, 같은 비율을 유지하도록 X 좌표 조정
|
||||
*/
|
||||
const getAdjustedX = useCallback(
|
||||
(componentX: number, componentY: number, componentWidth: number, componentHeight: number): number => {
|
||||
const overlap = getOverlappingSplitPanel(componentX, componentY, componentWidth, componentHeight);
|
||||
|
||||
if (!overlap || !overlap.isInLeftPanel) {
|
||||
// 분할 패널 위에 없거나, 우측 패널 위에 있으면 원래 위치 유지
|
||||
return componentX;
|
||||
}
|
||||
|
||||
const { panel } = overlap;
|
||||
|
||||
// 초기 좌측 패널 너비 (설정된 splitRatio 기준)
|
||||
const initialLeftPanelWidth = (panel.width * panel.initialLeftWidthPercent) / 100;
|
||||
// 현재 좌측 패널 너비 (드래그로 변경된 값)
|
||||
const currentLeftPanelWidth = (panel.width * panel.leftWidthPercent) / 100;
|
||||
|
||||
// 변화가 없으면 원래 위치 반환
|
||||
if (Math.abs(initialLeftPanelWidth - currentLeftPanelWidth) < 1) {
|
||||
return componentX;
|
||||
}
|
||||
|
||||
// 컴포넌트의 분할 패널 내 상대 X 좌표
|
||||
const relativeX = componentX - panel.x;
|
||||
|
||||
// 좌측 패널 내에서의 비율 (0~1)
|
||||
const ratioInLeftPanel = relativeX / initialLeftPanelWidth;
|
||||
|
||||
// 조정된 상대 X 좌표 = 원래 비율 * 현재 좌측 패널 너비
|
||||
const adjustedRelativeX = ratioInLeftPanel * currentLeftPanelWidth;
|
||||
|
||||
// 절대 X 좌표로 변환
|
||||
const adjustedX = panel.x + adjustedRelativeX;
|
||||
|
||||
console.log("📍 [SplitPanel] 버튼 위치 조정:", {
|
||||
componentX,
|
||||
panelX: panel.x,
|
||||
relativeX,
|
||||
initialLeftPanelWidth,
|
||||
currentLeftPanelWidth,
|
||||
ratioInLeftPanel,
|
||||
adjustedX,
|
||||
delta: adjustedX - componentX,
|
||||
});
|
||||
|
||||
return adjustedX;
|
||||
},
|
||||
[getOverlappingSplitPanel],
|
||||
);
|
||||
|
||||
// 레거시 호환 - dividerX 계산
|
||||
const legacyDividerX = legacyContainerRect ? (legacyContainerRect.width * legacyLeftWidthPercent) / 100 : 0;
|
||||
|
||||
// 레거시 호환 함수들
|
||||
const updateLeftWidth = useCallback((percent: number) => {
|
||||
setLegacyLeftWidthPercent(percent);
|
||||
// 첫 번째 분할 패널 업데이트
|
||||
const firstPanelId = splitPanelsRef.current.keys().next().value;
|
||||
if (firstPanelId) {
|
||||
const panel = splitPanelsRef.current.get(firstPanelId);
|
||||
if (panel) {
|
||||
splitPanelsRef.current.set(firstPanelId, { ...panel, leftWidthPercent: percent });
|
||||
}
|
||||
}
|
||||
forceUpdate((n) => n + 1);
|
||||
}, []);
|
||||
|
||||
const updateContainerRect = useCallback((rect: DOMRect | null) => {
|
||||
setLegacyContainerRect(rect);
|
||||
}, []);
|
||||
|
||||
const updateDragging = useCallback((dragging: boolean) => {
|
||||
setLegacyIsDragging(dragging);
|
||||
// 첫 번째 분할 패널 업데이트
|
||||
const firstPanelId = splitPanelsRef.current.keys().next().value;
|
||||
if (firstPanelId) {
|
||||
const panel = splitPanelsRef.current.get(firstPanelId);
|
||||
if (panel) {
|
||||
// 드래그 시작 시 초기 비율 저장
|
||||
const updates: Partial<SplitPanelInfo> = { isDragging: dragging };
|
||||
if (dragging) {
|
||||
updates.initialLeftWidthPercent = panel.leftWidthPercent;
|
||||
}
|
||||
splitPanelsRef.current.set(firstPanelId, { ...panel, ...updates });
|
||||
}
|
||||
}
|
||||
forceUpdate((n) => n + 1);
|
||||
}, []);
|
||||
|
||||
const value = useMemo<SplitPanelResizeContextValue>(
|
||||
() => ({
|
||||
splitPanels: splitPanelsRef.current,
|
||||
registerSplitPanel,
|
||||
unregisterSplitPanel,
|
||||
updateSplitPanel,
|
||||
getOverlappingSplitPanel,
|
||||
getAdjustedX,
|
||||
// 레거시 호환
|
||||
leftWidthPercent: legacyLeftWidthPercent,
|
||||
containerRect: legacyContainerRect,
|
||||
dividerX: legacyDividerX,
|
||||
isDragging: legacyIsDragging,
|
||||
splitPanelId: legacySplitPanelId,
|
||||
updateLeftWidth,
|
||||
updateContainerRect,
|
||||
updateDragging,
|
||||
}),
|
||||
[
|
||||
registerSplitPanel,
|
||||
unregisterSplitPanel,
|
||||
updateSplitPanel,
|
||||
getOverlappingSplitPanel,
|
||||
getAdjustedX,
|
||||
legacyLeftWidthPercent,
|
||||
legacyContainerRect,
|
||||
legacyDividerX,
|
||||
legacyIsDragging,
|
||||
legacySplitPanelId,
|
||||
updateLeftWidth,
|
||||
updateContainerRect,
|
||||
updateDragging,
|
||||
],
|
||||
);
|
||||
|
||||
return <SplitPanelResizeContext.Provider value={value}>{children}</SplitPanelResizeContext.Provider>;
|
||||
};
|
||||
|
||||
/**
|
||||
* SplitPanelResize Context 사용 훅
|
||||
* 분할 패널의 드래그 리사이즈 상태를 구독합니다.
|
||||
*/
|
||||
export const useSplitPanel = (): SplitPanelResizeContextValue => {
|
||||
const context = useContext(SplitPanelResizeContext);
|
||||
|
||||
// Context가 없으면 기본값 반환 (Provider 외부에서 사용 시)
|
||||
if (!context) {
|
||||
return {
|
||||
splitPanels: new Map(),
|
||||
registerSplitPanel: () => {},
|
||||
unregisterSplitPanel: () => {},
|
||||
updateSplitPanel: () => {},
|
||||
getOverlappingSplitPanel: () => null,
|
||||
getAdjustedX: (x) => x,
|
||||
leftWidthPercent: 30,
|
||||
containerRect: null,
|
||||
dividerX: 0,
|
||||
isDragging: false,
|
||||
splitPanelId: null,
|
||||
updateLeftWidth: () => {},
|
||||
updateContainerRect: () => {},
|
||||
updateDragging: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
|
||||
/**
|
||||
* 컴포넌트의 조정된 위치를 계산하는 훅
|
||||
* 분할 패널 좌측 영역 위에 있으면, 드래그에 따라 X 좌표가 조정됨
|
||||
*
|
||||
* @param componentX - 컴포넌트의 X 좌표 (px)
|
||||
* @param componentY - 컴포넌트의 Y 좌표 (px)
|
||||
* @param componentWidth - 컴포넌트 너비 (px)
|
||||
* @param componentHeight - 컴포넌트 높이 (px)
|
||||
* @returns 조정된 X 좌표와 관련 정보
|
||||
*/
|
||||
export const useAdjustedComponentPosition = (
|
||||
componentX: number,
|
||||
componentY: number,
|
||||
componentWidth: number,
|
||||
componentHeight: number,
|
||||
) => {
|
||||
const context = useSplitPanel();
|
||||
|
||||
const adjustedX = context.getAdjustedX(componentX, componentY, componentWidth, componentHeight);
|
||||
const overlap = context.getOverlappingSplitPanel(componentX, componentY, componentWidth, componentHeight);
|
||||
|
||||
return {
|
||||
adjustedX,
|
||||
isInSplitPanel: !!overlap,
|
||||
isInLeftPanel: overlap?.isInLeftPanel ?? false,
|
||||
isDragging: overlap?.panel.isDragging ?? false,
|
||||
panelId: overlap?.panelId ?? null,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 버튼 등 외부 컴포넌트에서 분할 패널 좌측 영역 내 위치를 계산하는 훅 (레거시 호환)
|
||||
*/
|
||||
export const useAdjustedPosition = (originalXPercent: number) => {
|
||||
const { leftWidthPercent, containerRect, dividerX, isDragging } = useSplitPanel();
|
||||
|
||||
const isInLeftPanel = originalXPercent <= leftWidthPercent;
|
||||
const adjustedXPercent = isInLeftPanel ? (originalXPercent / 100) * leftWidthPercent : originalXPercent;
|
||||
const adjustedXPx = containerRect ? (containerRect.width * adjustedXPercent) / 100 : 0;
|
||||
|
||||
return {
|
||||
adjustedXPercent,
|
||||
adjustedXPx,
|
||||
isInLeftPanel,
|
||||
isDragging,
|
||||
dividerX,
|
||||
containerRect,
|
||||
leftWidthPercent,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 버튼이 좌측 패널 위에 배치되었을 때, 드래그에 따라 위치가 조정되는 스타일을 반환하는 훅 (레거시 호환)
|
||||
*/
|
||||
export const useSplitPanelAwarePosition = (
|
||||
initialLeftPercent: number,
|
||||
options?: {
|
||||
followDivider?: boolean;
|
||||
offset?: number;
|
||||
},
|
||||
) => {
|
||||
const { leftWidthPercent, containerRect, dividerX, isDragging } = useSplitPanel();
|
||||
const { followDivider = false, offset = 0 } = options || {};
|
||||
|
||||
if (followDivider) {
|
||||
return {
|
||||
left: containerRect ? `${dividerX + offset}px` : `${leftWidthPercent}%`,
|
||||
transition: isDragging ? "none" : "left 0.15s ease-out",
|
||||
};
|
||||
}
|
||||
|
||||
const adjustedLeft = (initialLeftPercent / 100) * leftWidthPercent;
|
||||
|
||||
return {
|
||||
left: `${adjustedLeft}%`,
|
||||
transition: isDragging ? "none" : "left 0.15s ease-out",
|
||||
};
|
||||
};
|
||||
|
||||
export default SplitPanelResizeContext;
|
||||
@@ -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);
|
||||
|
||||
@@ -58,3 +58,13 @@ export type { SplitPanelLayoutConfig } from "./types";
|
||||
// 컴포넌트 내보내기
|
||||
export { SplitPanelLayoutComponent } from "./SplitPanelLayoutComponent";
|
||||
export { SplitPanelLayoutRenderer } from "./SplitPanelLayoutRenderer";
|
||||
|
||||
// Resize Context 내보내기 (버튼 등 외부 컴포넌트에서 분할 패널 드래그 리사이즈 상태 활용)
|
||||
export {
|
||||
SplitPanelProvider,
|
||||
useSplitPanel,
|
||||
useAdjustedPosition,
|
||||
useSplitPanelAwarePosition,
|
||||
useAdjustedComponentPosition,
|
||||
} from "./SplitPanelContext";
|
||||
export type { SplitPanelResizeContextValue, SplitPanelInfo } from "./SplitPanelContext";
|
||||
|
||||
Reference in New Issue
Block a user