refactor(web): extract drag position helpers

This commit is contained in:
2026-04-01 11:18:31 +02:00
parent 3fe3a5fb2a
commit 5402189158
5 changed files with 250 additions and 56 deletions
@@ -0,0 +1,74 @@
import { computeDragDates, pixelsToDays } from "~/components/timeline/dragMath.js";
type DragPositionLike = {
originalStartDate: Date | null;
originalEndDate: Date | null;
currentStartDate: Date | null;
currentEndDate: Date | null;
startMouseX: number;
pointerDeltaX: number;
daysDelta: number;
};
type DragMode = "move" | "resize-start" | "resize-end";
export type TimelineDragPositionResult<State> =
| { handled: false }
| { handled: true; nextState: State; pointerDeltaX: number; daysDelta: number; shouldSyncState: boolean };
function resolveDragPosition<State extends DragPositionLike>(
state: State,
clientX: number,
cellWidth: number,
mode: DragMode,
): TimelineDragPositionResult<State> {
const pointerDeltaX = clientX - state.startMouseX;
const daysDelta = pixelsToDays(pointerDeltaX, cellWidth);
if (daysDelta === state.daysDelta) {
return {
handled: true,
nextState: pointerDeltaX === state.pointerDeltaX ? state : { ...state, pointerDeltaX },
pointerDeltaX,
daysDelta,
shouldSyncState: false,
};
}
const { start, end } = computeDragDates(mode, state.originalStartDate!, state.originalEndDate!, daysDelta);
return {
handled: true,
nextState: {
...state,
currentStartDate: start,
currentEndDate: end,
pointerDeltaX,
daysDelta,
},
pointerDeltaX,
daysDelta,
shouldSyncState: true,
};
}
export function resolveProjectDragPosition<State extends DragPositionLike & { isDragging: boolean }>(
drag: State,
clientX: number,
cellWidth: number,
): TimelineDragPositionResult<State> {
if (!drag.isDragging || !drag.originalStartDate || !drag.originalEndDate) {
return { handled: false };
}
return resolveDragPosition(drag, clientX, cellWidth, "move");
}
export function resolveAllocationDragPosition<
State extends DragPositionLike & { isActive: boolean; mode: DragMode },
>(alloc: State, clientX: number, cellWidth: number): TimelineDragPositionResult<State> {
if (!alloc.isActive || !alloc.originalStartDate || !alloc.originalEndDate) {
return { handled: false };
}
return resolveDragPosition(alloc, clientX, cellWidth, alloc.mode);
}