74 lines
1.8 KiB
TypeScript
74 lines
1.8 KiB
TypeScript
/**
|
|
* 캔버스 분할선 글로벌 스토어
|
|
*
|
|
* React Context를 우회하여 useSyncExternalStore로 직접 상태를 공유.
|
|
* SplitLineComponent가 드래그 시 이 스토어를 업데이트하고,
|
|
* RealtimePreviewDynamic이 구독하여 컴포넌트 위치를 조정.
|
|
*/
|
|
|
|
export interface CanvasSplitState {
|
|
/** 스플릿선의 초기 X 위치 (캔버스 기준 px) */
|
|
initialDividerX: number;
|
|
/** 스플릿선의 현재 X 위치 (드래그 중 변경) */
|
|
currentDividerX: number;
|
|
/** 캔버스 전체 너비 (px) */
|
|
canvasWidth: number;
|
|
/** 드래그 진행 중 여부 */
|
|
isDragging: boolean;
|
|
/** 활성 여부 (스플릿선이 등록되었는지) */
|
|
active: boolean;
|
|
/** 스코프 ID (같은 data-screen-runtime 컨테이너의 컴포넌트만 영향) */
|
|
scopeId: string;
|
|
}
|
|
|
|
let state: CanvasSplitState = {
|
|
initialDividerX: 0,
|
|
currentDividerX: 0,
|
|
canvasWidth: 0,
|
|
isDragging: false,
|
|
active: false,
|
|
scopeId: "",
|
|
};
|
|
|
|
const listeners = new Set<() => void>();
|
|
|
|
export function setCanvasSplit(updates: Partial<CanvasSplitState>): void {
|
|
state = { ...state, ...updates };
|
|
listeners.forEach((fn) => fn());
|
|
}
|
|
|
|
export function resetCanvasSplit(): void {
|
|
state = {
|
|
initialDividerX: 0,
|
|
currentDividerX: 0,
|
|
canvasWidth: 0,
|
|
isDragging: false,
|
|
active: false,
|
|
scopeId: "",
|
|
};
|
|
listeners.forEach((fn) => fn());
|
|
}
|
|
|
|
export function subscribe(callback: () => void): () => void {
|
|
listeners.add(callback);
|
|
return () => {
|
|
listeners.delete(callback);
|
|
};
|
|
}
|
|
|
|
export function getSnapshot(): CanvasSplitState {
|
|
return state;
|
|
}
|
|
|
|
// SSR 호환
|
|
export function getServerSnapshot(): CanvasSplitState {
|
|
return {
|
|
initialDividerX: 0,
|
|
currentDividerX: 0,
|
|
canvasWidth: 0,
|
|
isDragging: false,
|
|
active: false,
|
|
scopeId: "",
|
|
};
|
|
}
|