Implements auto-scroll for drag and drop

Adds auto-scrolling functionality to the column detector when dragging elements near the edges of the scrollable container.

This enhances the drag and drop experience by automatically scrolling the content when the user drags an element close to the top or bottom of the visible area.

The auto-scroll is triggered when the mouse cursor is within a defined threshold of the container's edges and stops when the mouse moves outside of the threshold.

A check is also added to ensure auto-scroll stops when the user releases the mouse button.
This commit is contained in:
Janus Knudsen 2025-08-24 23:41:32 +02:00
parent eb08a28495
commit fc354ad618

View file

@ -14,6 +14,12 @@ export class ColumnDetector {
private originalEvent: HTMLElement | null = null; private originalEvent: HTMLElement | null = null;
private mouseOffset = { x: 0, y: 0 }; private mouseOffset = { x: 0, y: 0 };
// Auto-scroll properties
private scrollContainer: HTMLElement | null = null;
private autoScrollAnimationId: number | null = null;
private scrollSpeed = 10; // pixels per frame
private scrollThreshold = 30; // pixels from edge
// Konfiguration for snap interval // Konfiguration for snap interval
private snapIntervalMinutes = 15; // 15 minutter private snapIntervalMinutes = 15; // 15 minutter
private hourHeightPx = 60; // Fra CSS --hour-height private hourHeightPx = 60; // Fra CSS --hour-height
@ -103,6 +109,12 @@ export class ColumnDetector {
this.draggedClone.style.top = relativeY + 'px'; this.draggedClone.style.top = relativeY + 'px';
} }
} }
// Auto-scroll detection når der er en aktiv clone
if (this.draggedClone) {
console.log('ColumnDetector: Checking auto-scroll, mouse at:', event.clientY);
this.checkAutoScroll(event);
}
} }
// Find hvilket element musen er over (altid) // Find hvilket element musen er over (altid)
@ -270,6 +282,9 @@ export class ColumnDetector {
this.isMouseDown = false; this.isMouseDown = false;
console.log('Mouse up at:', { x: event.clientX, y: event.clientY }); console.log('Mouse up at:', { x: event.clientX, y: event.clientY });
// Stop auto-scroll
this.stopAutoScroll();
// Drop operationen: fade out original og remove clone suffix // Drop operationen: fade out original og remove clone suffix
if (this.originalEvent && this.draggedClone) { if (this.originalEvent && this.draggedClone) {
// Fade out og fjern originalen // Fade out og fjern originalen
@ -281,6 +296,7 @@ export class ColumnDetector {
// Ryd op // Ryd op
this.originalEvent = null; this.originalEvent = null;
this.draggedClone = null; this.draggedClone = null;
this.scrollContainer = null;
console.log('Drop completed: original faded out and removed, clone became permanent'); console.log('Drop completed: original faded out and removed, clone became permanent');
} }
@ -306,7 +322,89 @@ export class ColumnDetector {
} }
} }
/**
* Check if auto-scroll should be triggered based on mouse position
*/
private checkAutoScroll(event: MouseEvent): void {
// Find scrollable content if not cached
if (!this.scrollContainer) {
this.scrollContainer = document.querySelector('swp-scrollable-content') as HTMLElement;
if (!this.scrollContainer) {
console.warn('ColumnDetector: Could not find swp-scrollable-content for auto-scroll');
return;
}
console.log('ColumnDetector: Found scroll container:', this.scrollContainer);
}
const containerRect = this.scrollContainer.getBoundingClientRect();
const mouseY = event.clientY;
// Calculate distances from edges
const distanceFromTop = mouseY - containerRect.top;
const distanceFromBottom = containerRect.bottom - mouseY;
console.log('ColumnDetector: Auto-scroll check:', {
mouseY,
containerTop: containerRect.top,
containerBottom: containerRect.bottom,
distanceFromTop: Math.round(distanceFromTop),
distanceFromBottom: Math.round(distanceFromBottom),
threshold: this.scrollThreshold
});
// Check if we need to scroll up
if (distanceFromTop <= this.scrollThreshold && distanceFromTop > 0) {
this.startAutoScroll('up');
console.log(`Auto-scroll up triggered: ${Math.round(distanceFromTop)}px from top edge`);
}
// Check if we need to scroll down
else if (distanceFromBottom <= this.scrollThreshold && distanceFromBottom > 0) {
this.startAutoScroll('down');
console.log(`Auto-scroll down triggered: ${Math.round(distanceFromBottom)}px from bottom edge`);
}
// Stop scrolling if not in threshold zone
else {
this.stopAutoScroll();
}
}
/**
* Start auto-scroll animation in specified direction
*/
private startAutoScroll(direction: 'up' | 'down'): void {
// Don't start if already scrolling in same direction
if (this.autoScrollAnimationId !== null) {
return;
}
const scroll = () => {
if (!this.scrollContainer || !this.isMouseDown || !this.draggedClone) {
this.stopAutoScroll();
return;
}
const scrollAmount = direction === 'up' ? -this.scrollSpeed : this.scrollSpeed;
this.scrollContainer.scrollTop += scrollAmount;
// Continue animation
this.autoScrollAnimationId = requestAnimationFrame(scroll);
};
this.autoScrollAnimationId = requestAnimationFrame(scroll);
}
/**
* Stop auto-scroll animation
*/
private stopAutoScroll(): void {
if (this.autoScrollAnimationId !== null) {
cancelAnimationFrame(this.autoScrollAnimationId);
this.autoScrollAnimationId = null;
}
}
public destroy(): void { public destroy(): void {
this.stopAutoScroll();
document.body.removeEventListener('mousemove', this.handleMouseMove.bind(this)); document.body.removeEventListener('mousemove', this.handleMouseMove.bind(this));
document.body.removeEventListener('click', this.handleClick.bind(this)); document.body.removeEventListener('click', this.handleClick.bind(this));
document.body.removeEventListener('mousedown', this.handleMouseDown.bind(this)); document.body.removeEventListener('mousedown', this.handleMouseDown.bind(this));