95 lines
2.6 KiB
TypeScript
95 lines
2.6 KiB
TypeScript
/**
|
|
* 캔버스 분할선 글로벌 스토어
|
|
*
|
|
* 성능 최적화: 이중 리스너 구조
|
|
* - React 리스너 (subscribe): 구조적 변경만 알림 (active, isDragging 시작/종료)
|
|
* - DOM 리스너 (subscribeDom): 드래그 중 위치 변경 알림 (React 우회, 직접 DOM 조작)
|
|
*/
|
|
|
|
export interface CanvasSplitState {
|
|
initialDividerX: number;
|
|
currentDividerX: number;
|
|
canvasWidth: number;
|
|
isDragging: boolean;
|
|
active: boolean;
|
|
scopeId: string;
|
|
}
|
|
|
|
const initialState: CanvasSplitState = {
|
|
initialDividerX: 0,
|
|
currentDividerX: 0,
|
|
canvasWidth: 0,
|
|
isDragging: false,
|
|
active: false,
|
|
scopeId: "",
|
|
};
|
|
|
|
let state: CanvasSplitState = { ...initialState };
|
|
|
|
// React 리렌더링을 트리거하는 리스너 (구조적 변경 전용)
|
|
const reactListeners = new Set<() => void>();
|
|
|
|
// DOM 직접 조작용 리스너 (드래그 중 위치 업데이트, React 우회)
|
|
const domListeners = new Set<(state: CanvasSplitState) => void>();
|
|
|
|
// React용 스냅샷 (드래그 중 위치 변경에는 갱신 안 함)
|
|
let reactSnapshot: CanvasSplitState = { ...initialState };
|
|
|
|
export function setCanvasSplit(updates: Partial<CanvasSplitState>): void {
|
|
state = { ...state, ...updates };
|
|
|
|
// 드래그 중 위치만 변경 → DOM 리스너만 호출 (React 리렌더 없음)
|
|
const isPositionOnlyDuringDrag =
|
|
state.isDragging &&
|
|
Object.keys(updates).length === 1 &&
|
|
"currentDividerX" in updates;
|
|
|
|
if (isPositionOnlyDuringDrag) {
|
|
domListeners.forEach((fn) => fn(state));
|
|
return;
|
|
}
|
|
|
|
// 구조적 변경 → React 리스너 + DOM 리스너 모두 호출
|
|
reactSnapshot = { ...state };
|
|
reactListeners.forEach((fn) => fn());
|
|
domListeners.forEach((fn) => fn(state));
|
|
}
|
|
|
|
export function resetCanvasSplit(): void {
|
|
state = { ...initialState };
|
|
reactSnapshot = { ...initialState };
|
|
reactListeners.forEach((fn) => fn());
|
|
domListeners.forEach((fn) => fn(state));
|
|
}
|
|
|
|
// React용: useSyncExternalStore에 연결
|
|
export function subscribe(callback: () => void): () => void {
|
|
reactListeners.add(callback);
|
|
return () => {
|
|
reactListeners.delete(callback);
|
|
};
|
|
}
|
|
|
|
export function getSnapshot(): CanvasSplitState {
|
|
return reactSnapshot;
|
|
}
|
|
|
|
export function getServerSnapshot(): CanvasSplitState {
|
|
return { ...initialState };
|
|
}
|
|
|
|
// DOM 직접 조작용: 드래그 중 매 프레임 위치 업데이트 수신
|
|
export function subscribeDom(
|
|
callback: (state: CanvasSplitState) => void,
|
|
): () => void {
|
|
domListeners.add(callback);
|
|
return () => {
|
|
domListeners.delete(callback);
|
|
};
|
|
}
|
|
|
|
// 현재 상태 직접 참조 (DOM 리스너 콜백 외부에서 최신 상태 필요 시)
|
|
export function getCurrentState(): CanvasSplitState {
|
|
return state;
|
|
}
|