diff --git a/src/managers/DragDropManager.ts b/src/managers/DragDropManager.ts index 63d332e..7ea7496 100644 --- a/src/managers/DragDropManager.ts +++ b/src/managers/DragDropManager.ts @@ -226,6 +226,7 @@ export class DragDropManager { // Continue drag if started if (this.isDragStarted && this.draggedElement && this.draggedClone) { + console.log("Continue drag if started", this.draggedClone); this.continueDrag(currentPosition); this.detectAndEmitColumnChange(currentPosition); } @@ -280,9 +281,10 @@ export class DragDropManager { * Continue drag movement - update position and auto-scroll */ private continueDrag(currentPosition: MousePosition): void { - if (!this.draggedElement!.hasAttribute("data-allday")) { + if (!this.draggedClone!.hasAttribute("data-allday")) { // Calculate raw position from mouse (no snapping) const column = ColumnDetectionUtils.getColumnBounds(currentPosition); + console.log("continueDrag"); if (column) { // Calculate raw Y position relative to column (accounting for mouse offset) @@ -296,11 +298,26 @@ export class DragDropManager { this.currentY = parseFloat(this.draggedClone!.style.top) || 0; this.animateDrag(); } + + // Emit drag:move event with current draggedClone reference + if (this.draggedClone) { + const dragMovePayload: DragMoveEventPayload = { + draggedElement: this.draggedElement!, + draggedClone: this.draggedClone, + mousePosition: currentPosition, + snappedY: this.currentY, + columnBounds: column, + mouseOffset: this.mouseOffset + }; + this.eventBus.emit('drag:move', dragMovePayload); + } } // Check for auto-scroll this.checkAutoScroll(currentPosition); } + else + console.log("hasAttribute(data-allday)"); } /** @@ -461,6 +478,7 @@ export class DragDropManager { /** * Smooth drag animation using requestAnimationFrame + * Only interpolates currentY - events are emitted from continueDrag() */ private animateDrag(): void { if (!this.isDragStarted || !this.draggedClone || !this.targetColumn) { @@ -475,33 +493,10 @@ export class DragDropManager { // Update if difference is significant if (Math.abs(diff) > 0.5) { this.currentY += step; - - // Emit drag move event with interpolated position - const dragMovePayload: DragMoveEventPayload = { - draggedElement: this.draggedElement!, - draggedClone: this.draggedClone, - mousePosition: this.lastMousePosition, - snappedY: this.currentY, - columnBounds: this.targetColumn, - mouseOffset: this.mouseOffset - }; - this.eventBus.emit('drag:move', dragMovePayload); - this.dragAnimationId = requestAnimationFrame(() => this.animateDrag()); } else { // Close enough - snap to target this.currentY = this.targetY; - - const dragMovePayload: DragMoveEventPayload = { - draggedElement: this.draggedElement!, - draggedClone: this.draggedClone, - mousePosition: this.lastMousePosition, - snappedY: this.currentY, - columnBounds: this.targetColumn, - mouseOffset: this.mouseOffset - }; - this.eventBus.emit('drag:move', dragMovePayload); - this.dragAnimationId = null; } } @@ -649,6 +644,7 @@ export class DragDropManager { // Delegate pattern - allows AllDayManager to replace the clone replaceClone: (newClone: HTMLElement) => { this.draggedClone = newClone; + this.dragAnimationId === null; } }; this.eventBus.emit('drag:mouseenter-header', dragMouseEnterPayload); @@ -690,6 +686,9 @@ export class DragDropManager { // Delegate pattern - allows EventRenderer to replace the clone replaceClone: (newClone: HTMLElement) => { this.draggedClone = newClone; + this.dragAnimationId === null; + this.stopDragAnimation(); + console.log("replacing clone with", newClone) } }; this.eventBus.emit('drag:mouseenter-column', dragMouseEnterPayload); diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 5a01e2b..0581ace 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -43,7 +43,7 @@ export class DateEventRenderer implements EventRendererStrategy { this.stackManager = new EventStackManager(); this.layoutCoordinator = new EventLayoutCoordinator(); } - + private applyDragStyling(element: HTMLElement): void { element.classList.add('dragging'); element.style.removeProperty("margin-left"); @@ -90,11 +90,10 @@ export class DateEventRenderer implements EventRendererStrategy { * Handle drag move event */ public handleDragMove(payload: DragMoveEventPayload): void { - if (!this.draggedClone || !payload.columnBounds) return; // Delegate to SwpEventElement to update position and timestamps - const swpEvent = this.draggedClone as SwpEventElement; - const columnDate = this.dateService.parseISO(payload.columnBounds.date); + const swpEvent = payload.draggedClone as SwpEventElement; + const columnDate = this.dateService.parseISO(payload.columnBounds!!.date); swpEvent.updatePosition(columnDate, payload.snappedY); } @@ -133,27 +132,18 @@ export class DateEventRenderer implements EventRendererStrategy { * Handle conversion of all-day event to timed event */ public handleConvertAllDayToTimed(payload: DragMouseEnterColumnEventPayload): void { - const { calendarEvent, targetColumn, snappedY, replaceClone } = payload; console.log('🎯 DateEventRenderer: Converting all-day to timed event', { - eventId: calendarEvent.id, - targetColumn: targetColumn.date, - snappedY + eventId: payload.calendarEvent.id, + targetColumn: payload.targetColumn.date, + snappedY: payload.snappedY }); - // Create timed event element from CalendarEvent - const timedClone = SwpEventElement.fromCalendarEvent(calendarEvent); - - // Calculate proper height from event duration - const position = this.calculateEventPosition(calendarEvent); - - // Calculate actual duration in minutes from CalendarEvent (important for all-day conversions) - const durationMinutes = (calendarEvent.end.getTime() - calendarEvent.start.getTime()) / (1000 * 60); - timedClone.dataset.duration = durationMinutes.toString(); - timedClone.dataset.originalDuration = durationMinutes.toString(); + let timedClone = SwpEventElement.fromCalendarEvent(payload.calendarEvent); + let position = this.calculateEventPosition(payload.calendarEvent); // Set position at snapped Y - timedClone.style.top = `${snappedY}px`; + //timedClone.style.top = `${snappedY}px`; // Set complete styling for dragged clone (matching normal event rendering) timedClone.style.height = `${position.height - 3}px`; @@ -166,25 +156,16 @@ export class DateEventRenderer implements EventRendererStrategy { this.applyDragStyling(timedClone); // Find the events layer in the target column - const eventsLayer = targetColumn.element.querySelector('swp-events-layer'); - if (!eventsLayer) { - console.warn('DateEventRenderer: Events layer not found in column'); - return; - } + let eventsLayer = payload.targetColumn.element.querySelector('swp-events-layer'); - // Append new timed clone to events layer - eventsLayer.appendChild(timedClone); + // Add "clone-" prefix to match clone ID pattern + timedClone.dataset.eventId = payload.calendarEvent.id; - // Update instance state - this.draggedClone = timedClone; + // Remove old all-day clone and replace with new timed clone + payload.draggedClone.remove(); + payload.replaceClone(timedClone); + eventsLayer!!.appendChild(timedClone); - // Update DragDropManager's reference to the new clone - replaceClone(timedClone); - - console.log('✅ DateEventRenderer: Converted all-day to timed event', { - eventId: calendarEvent.id, - position: snappedY - }); } /** diff --git a/src/renderers/EventRendererManager.ts b/src/renderers/EventRendererManager.ts index 19c1e4a..7fc41d7 100644 --- a/src/renderers/EventRendererManager.ts +++ b/src/renderers/EventRendererManager.ts @@ -153,7 +153,7 @@ export class EventRenderingService { this.eventBus.on('drag:move', (event: Event) => { let dragEvent = (event as CustomEvent).detail; - if (dragEvent.draggedElement.hasAttribute('data-allday')) { + if (dragEvent.draggedClone.hasAttribute('data-allday')) { return; } if (this.strategy.handleDragMove) { @@ -266,9 +266,6 @@ export class EventRenderingService { calendarEvent: payload.calendarEvent }); - // Remove the old all-day clone from header - payload.draggedClone.remove(); - // Delegate to strategy for conversion if (this.strategy.handleConvertAllDayToTimed) { this.strategy.handleConvertAllDayToTimed(payload);