Use nearest-grid snapping for event resize

This commit is contained in:
Gregor Vostrak
2026-03-04 19:00:30 +01:00
parent 89a4a1962a
commit 2b46e568e0
2 changed files with 14 additions and 5 deletions
@@ -441,6 +441,13 @@ function snapEndToGrid(time: Dayjs, snapMinutes: number): Dayjs {
return time.startOf('day').add(snapped, 'minute');
}
// Snap a dayjs time to the nearest snap boundary (for resize)
function snapToNearestGrid(time: Dayjs, snapMinutes: number): Dayjs {
const minutes = time.hour() * 60 + time.minute();
const snapped = Math.round(minutes / snapMinutes) * snapMinutes;
return time.startOf('day').add(snapped, 'minute');
}
// --- Visual snap (composable) ---
const {
startDragSnap: startVisualDragSnap,
@@ -503,9 +510,11 @@ async function handleEventResize(arg: EventChangeArg) {
const startChanged = !newStartLocal.isSame(origStartLocal, 'minute');
// Snap only the changed edge once, reuse for both setDates and API update
const snappedStart = startChanged ? snapStartToGrid(newStartLocal, snap) : null;
const snappedEnd = !startChanged && !ext.isRunning ? snapEndToGrid(newEndLocal, snap) : null;
// Snap only the changed edge once, reuse for both setDates and API update.
// Use Math.round (snapToNearestGrid) to match the visual snap during resize.
const snappedStart = startChanged ? snapToNearestGrid(newStartLocal, snap) : null;
const snappedEnd =
!startChanged && !ext.isRunning ? snapToNearestGrid(newEndLocal, snap) : null;
// Set FC event to snapped position immediately to avoid flash.
// Use the original event date for the edge that wasn't resized.
@@ -159,12 +159,12 @@ export function useVisualSnap({
}
if (resizeEdge === 'bottom') {
const snappedEnd = Math.ceil(endPos / snapPx) * snapPx;
const snappedEnd = Math.round(endPos / snapPx) * snapPx;
const clampedEnd = Math.max(top + snapPx, snappedEnd);
harness.style.bottom = -clampedEnd + 'px';
if (mirror) updateMirrorDurationLabel(mirror, top, clampedEnd, snapPx);
} else if (resizeEdge === 'top') {
const snappedTop = Math.floor(top / snapPx) * snapPx;
const snappedTop = Math.round(top / snapPx) * snapPx;
const clampedTop = Math.min(endPos - snapPx, snappedTop);
harness.style.top = clampedTop + 'px';
if (mirror) updateMirrorDurationLabel(mirror, clampedTop, endPos, snapPx);