From b4d758b6d9bc44aa4749157ef665e1843230ce74 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Wed, 3 Sep 2025 20:13:56 +0200 Subject: [PATCH] Improves drag and drop autoscroll behavior. Refines the drag and drop autoscroll functionality to correctly update the position of the dragged element relative to the scrolling container. Calculates the snapped position based on the column's bounding rectangle and scroll movement, ensuring accurate placement during autoscroll. This provides a smoother and more responsive user experience when dragging elements near the edges of the scrollable area. --- src/managers/DragDropManager.ts | 24 +++++++++++++++++------- src/renderers/EventRenderer.ts | 12 ++++++++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/managers/DragDropManager.ts b/src/managers/DragDropManager.ts index 91631cb..5e25058 100644 --- a/src/managers/DragDropManager.ts +++ b/src/managers/DragDropManager.ts @@ -364,14 +364,24 @@ export class DragDropManager { const scrollAmount = direction === 'up' ? -this.scrollSpeed : this.scrollSpeed; this.cachedElements.scrollContainer.scrollTop += scrollAmount; - // Emit updated position during scroll + // Emit updated position during scroll - adjust for scroll movement if (this.draggedEventId) { - const snappedY = this.calculateSnapPosition(this.currentMouseY); - this.eventBus.emit('drag:auto-scroll', { - eventId: this.draggedEventId, - snappedY, - scrollTop: this.cachedElements.scrollContainer.scrollTop - }); + // During autoscroll, we need to calculate position relative to the scrolled content + // The mouse hasn't moved, but the content has scrolled + const columnElement = this.getCachedColumnElement(this.currentColumn); + if (columnElement) { + const columnRect = columnElement.getBoundingClientRect(); + // Calculate position relative to column, accounting for scroll movement + const relativeY = this.currentMouseY - columnRect.top - this.mouseOffset.y; + const snappedY = Math.round(relativeY / this.snapDistancePx) * this.snapDistancePx; + const finalSnappedY = Math.max(0, snappedY); + + this.eventBus.emit('drag:auto-scroll', { + eventId: this.draggedEventId, + snappedY: finalSnappedY, + scrollTop: this.cachedElements.scrollContainer.scrollTop + }); + } } this.autoScrollAnimationId = requestAnimationFrame(scroll); diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 6d70709..494082b 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -48,6 +48,18 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { this.handleDragMove(eventId, snappedY, column, mouseOffset); }); + // Handle drag auto-scroll (when dragging near edges triggers scroll) + eventBus.on('drag:auto-scroll', (event) => { + const { eventId, snappedY } = (event as CustomEvent).detail; + if (!this.draggedClone) return; + + // Update position directly using the calculated snapped position + this.draggedClone.style.top = snappedY + 'px'; + + // Update timestamp display + this.updateCloneTimestamp(this.draggedClone, snappedY); + }); + // Handle drag end eventBus.on('drag:end', (event) => { const { eventId, originalElement, finalColumn, finalY } = (event as CustomEvent).detail;