refactor(web): extract allocation multi-drag session
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
type MutableCurrent<T> = {
|
||||
current: T;
|
||||
};
|
||||
|
||||
type AttachDocumentMouseDrag = (
|
||||
documentTarget: Document,
|
||||
onMove: (event: MouseEvent) => void,
|
||||
onUp: (event: MouseEvent) => void,
|
||||
) => () => void;
|
||||
|
||||
type MultiDragStateLike<TMode extends string = string> = {
|
||||
selectedAllocationIds: string[];
|
||||
multiDragDaysDelta: number;
|
||||
isMultiDragging: boolean;
|
||||
multiDragMode: TMode;
|
||||
};
|
||||
|
||||
type BeginAllocationMultiDragSessionParams<TState extends MultiDragStateLike, TMode extends string> = {
|
||||
startMouseX: number;
|
||||
dragMode: TMode;
|
||||
documentTarget: Document;
|
||||
cleanupRef: MutableCurrent<(() => void) | null>;
|
||||
stateRef: MutableCurrent<TState>;
|
||||
setState: (state: TState) => void;
|
||||
startState: (state: TState, dragMode: TMode) => TState;
|
||||
updateState: (state: TState, daysDelta: number) => TState | null;
|
||||
finalizeState: (state: TState) => TState;
|
||||
toDaysDelta: (deltaX: number) => number;
|
||||
onComplete: (daysDelta: number, finalState: TState) => void;
|
||||
attachDrag: AttachDocumentMouseDrag;
|
||||
};
|
||||
|
||||
export function beginAllocationMultiDragSession<TState extends MultiDragStateLike, TMode extends string>({
|
||||
startMouseX,
|
||||
dragMode,
|
||||
documentTarget,
|
||||
cleanupRef,
|
||||
stateRef,
|
||||
setState,
|
||||
startState,
|
||||
updateState,
|
||||
finalizeState,
|
||||
toDaysDelta,
|
||||
onComplete,
|
||||
attachDrag,
|
||||
}: BeginAllocationMultiDragSessionParams<TState, TMode>) {
|
||||
const initialState = startState(stateRef.current, dragMode);
|
||||
stateRef.current = initialState;
|
||||
setState(initialState);
|
||||
cleanupRef.current?.();
|
||||
|
||||
function handleMove(event: MouseEvent) {
|
||||
const updated = updateState(stateRef.current, toDaysDelta(event.clientX - startMouseX));
|
||||
if (!updated) return;
|
||||
|
||||
stateRef.current = updated;
|
||||
setState(updated);
|
||||
}
|
||||
|
||||
function handleUp(event: MouseEvent) {
|
||||
cleanupRef.current?.();
|
||||
cleanupRef.current = null;
|
||||
|
||||
const finalState = finalizeState(stateRef.current);
|
||||
stateRef.current = finalState;
|
||||
setState(finalState);
|
||||
|
||||
const finalDelta = toDaysDelta(event.clientX - startMouseX);
|
||||
if (finalDelta !== 0) {
|
||||
onComplete(finalDelta, finalState);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupRef.current = attachDrag(documentTarget, handleMove, handleUp);
|
||||
}
|
||||
Reference in New Issue
Block a user