From 727a6ec53a3f8b03586fe1664b584f9d9788f238 Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Thu, 4 Sep 2025 23:56:22 +0200 Subject: [PATCH] Fixes event stacking order during drag and drop Ensures existing events maintain their base positions when a new event is dragged and dropped into an overlapping time slot. The fix prioritizes existing events in the stack, placing the newly dropped event on top. This ensures correct visual representation and expected behavior during event manipulation. --- src/renderers/EventRenderer.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/renderers/EventRenderer.ts b/src/renderers/EventRenderer.ts index 7870e92..45b935f 100644 --- a/src/renderers/EventRenderer.ts +++ b/src/renderers/EventRenderer.ts @@ -574,13 +574,24 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { eventsLayer.appendChild(groupContainer); } else if (overlapType === OverlapType.STACKING) { - // Handle stacking - sort by duration and stack shorter events on top - const sortedEvents = [...overlappingEvents].sort((a, b) => { + // CRITICAL FIX: Respect existing event position - they stay as base + + // Separate existing events from the dropped event + const existingInOverlap = overlappingEvents.filter(e => e.id !== droppedEvent.id); + const droppedIsInList = overlappingEvents.find(e => e.id === droppedEvent.id); + + // Sort ONLY existing events by duration (among themselves) + const sortedExisting = [...existingInOverlap].sort((a, b) => { const durationA = new Date(a.end).getTime() - new Date(a.start).getTime(); const durationB = new Date(b.end).getTime() - new Date(b.start).getTime(); - return durationB - durationA; // Longer duration first (background) + return durationB - durationA; // Longer existing first }); + // FINAL ORDER: Existing events first (base), dropped event LAST (stacked on top) + const finalEventOrder = droppedIsInList + ? [...sortedExisting, droppedEvent] + : sortedExisting; + // Remove overlapping events from DOM const overlappingEventIds = new Set(overlappingEvents.map(e => e.id)); existingEvents @@ -590,16 +601,16 @@ export abstract class BaseEventRenderer implements EventRendererStrategy { let underlyingElement: HTMLElement | null = null; - sortedEvents.forEach((event, index) => { + finalEventOrder.forEach((event, index) => { const eventElement = this.createEventElement(event); this.positionEvent(eventElement, event); if (index === 0) { - // First (longest duration) event renders normally at full width + // First event (existing) - always remains base position eventsLayer.appendChild(eventElement); underlyingElement = eventElement; } else { - // Shorter events are stacked with margin-left offset and higher z-index + // Subsequent events (including dropped) - stacked on top if (underlyingElement) { this.overlapManager.createStackedEvent(eventElement, underlyingElement, index); }