refactor(web): extract range selection bootstrap

This commit is contained in:
2026-04-01 10:17:39 +02:00
parent c941b1e5cf
commit 84c5760392
5 changed files with 47 additions and 11 deletions
@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { finalizeRangeSelection, updateRangeSelectionDraft } from "./timelineRangeSelection.js";
import { createRangeSelectionState, finalizeRangeSelection, updateRangeSelectionDraft } from "./timelineRangeSelection.js";
type TestRangeState = {
isSelecting: boolean;
@@ -11,6 +11,23 @@ type TestRangeState = {
};
describe("timelineRangeSelection", () => {
it("creates a selection draft with currentDate anchored to the start date", () => {
expect(
createRangeSelectionState<TestRangeState>(
"res-1",
new Date("2025-01-15T12:00:00.000Z"),
100,
),
).toEqual({
isSelecting: true,
resourceId: "res-1",
startDate: new Date("2025-01-15T12:00:00.000Z"),
currentDate: new Date("2025-01-15T12:00:00.000Z"),
suggestedProjectId: null,
startClientX: 100,
});
});
it("ignores updates when no full day boundary was crossed", () => {
const state: TestRangeState = {
isSelecting: true,
@@ -18,6 +18,22 @@ export type RangeSelectionResult = {
anchorY: number;
};
export function createRangeSelectionState<TState extends RangeStateLike>(
resourceId: string,
startDate: Date,
startClientX: number,
suggestedProjectId?: string | null,
): TState {
return {
isSelecting: true,
resourceId,
startDate,
currentDate: startDate,
suggestedProjectId: suggestedProjectId ?? null,
startClientX,
} as TState;
}
export function updateRangeSelectionDraft<TState extends RangeStateLike>(
state: TState,
currentClientX: number,
+7 -9
View File
@@ -31,7 +31,7 @@ import {
updateMultiSelectDraft,
} from "./timelineMultiSelect.js";
import { reconcileOptimisticEntries } from "./timelineOptimisticAllocations.js";
import { finalizeRangeSelection, updateRangeSelectionDraft } from "./timelineRangeSelection.js";
import { createRangeSelectionState, finalizeRangeSelection, updateRangeSelectionDraft } from "./timelineRangeSelection.js";
import { getTouchPoint, resolveTouchDragDecision } from "./timelineTouch.js";
const DRAG_CLICK_THRESHOLD_PX = 5;
@@ -826,14 +826,12 @@ export function useTimelineDrag({
if (dragStateRef.current.isDragging || allocDragRef.current.isActive) return;
if (e.button !== 0) return;
e.preventDefault();
const state: RangeState = {
isSelecting: true,
resourceId: opts.resourceId,
startDate: opts.startDate,
currentDate: opts.startDate,
suggestedProjectId: opts.suggestedProjectId ?? null,
startClientX: e.clientX,
};
const state = createRangeSelectionState<RangeState>(
opts.resourceId,
opts.startDate,
e.clientX,
opts.suggestedProjectId,
);
rangeStateRef.current = state;
setRangeState(state);
},