ERP-node/frontend/lib/registry/components/v2-split-line/canvasSplitStore.ts

95 lines
2.6 KiB
TypeScript
Raw Normal View History

/**
*
*
* 최적화: 이중
* - 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;
}