import { IEventBus } from '../../types/CalendarTypes'; import { IGridConfig } from '../../core/IGridConfig'; import { CoreEvents } from '../../constants/CoreEvents'; import { HeaderDrawerManager } from '../../core/HeaderDrawerManager'; import { IDragEnterHeaderPayload, IDragMoveHeaderPayload, IDragLeaveHeaderPayload } from '../../types/DragTypes'; /** * HeaderDrawerRenderer - Handles rendering of items in the header drawer * * Listens to drag events from DragDropManager and creates/manages * swp-header-item elements in the header drawer. * * Uses subgrid for column alignment with parent swp-calendar-header. * Position items via gridArea for explicit row/column placement. */ export class HeaderDrawerRenderer { private currentItem: HTMLElement | null = null; private container: HTMLElement | null = null; private sourceElement: HTMLElement | null = null; private wasExpandedBeforeDrag = false; constructor( private eventBus: IEventBus, private gridConfig: IGridConfig, private headerDrawerManager: HeaderDrawerManager ) { this.setupListeners(); } /** * Setup event listeners for drag events */ private setupListeners(): void { this.eventBus.on(CoreEvents.EVENT_DRAG_ENTER_HEADER, (e) => { const payload = (e as CustomEvent).detail; this.handleDragEnter(payload); }); this.eventBus.on(CoreEvents.EVENT_DRAG_MOVE_HEADER, (e) => { const payload = (e as CustomEvent).detail; this.handleDragMove(payload); }); this.eventBus.on(CoreEvents.EVENT_DRAG_LEAVE_HEADER, (e) => { const payload = (e as CustomEvent).detail; this.handleDragLeave(payload); }); this.eventBus.on(CoreEvents.EVENT_DRAG_END, () => { this.handleDragEnd(); }); this.eventBus.on(CoreEvents.EVENT_DRAG_CANCEL, () => { this.cleanup(); }); } /** * Handle drag entering header zone - create preview item */ private handleDragEnter(payload: IDragEnterHeaderPayload): void { this.container = document.querySelector('swp-header-drawer'); if (!this.container) return; // Remember if drawer was already expanded this.wasExpandedBeforeDrag = this.headerDrawerManager.isExpanded(); // Expand drawer with animation this.headerDrawerManager.expand(); // Store reference to source element this.sourceElement = payload.element; // Create header item const item = document.createElement('swp-header-item'); item.dataset.id = payload.eventId; item.dataset.itemType = payload.itemType; item.dataset.date = payload.sourceDate; item.dataset.duration = String(payload.duration); item.textContent = payload.title; // Apply color class if present if (payload.colorClass) { item.classList.add(payload.colorClass); } // Add dragging state item.classList.add('dragging'); // Initial placement (duration determines column span) // gridArea format: "row / col-start / row+1 / col-end" const col = payload.sourceColumnIndex + 1; const endCol = col + payload.duration; item.style.gridArea = `1 / ${col} / 2 / ${endCol}`; this.container.appendChild(item); this.currentItem = item; // Hide original element while in header payload.element.style.visibility = 'hidden'; } /** * Handle drag moving within header - update column position */ private handleDragMove(payload: IDragMoveHeaderPayload): void { if (!this.currentItem) return; // Update column position (duration=1 for now) const col = payload.columnIndex + 1; const duration = parseInt(this.currentItem.dataset.duration || '1', 10); const endCol = col + duration; this.currentItem.style.gridArea = `1 / ${col} / 2 / ${endCol}`; this.currentItem.dataset.date = payload.dateKey; } /** * Handle drag leaving header - remove preview and restore source */ private handleDragLeave(_payload: IDragLeaveHeaderPayload): void { this.cleanup(); } /** * Handle drag end - finalize the item (it stays in header) */ private handleDragEnd(): void { if (!this.currentItem) return; // Remove dragging state this.currentItem.classList.remove('dragging'); // Item stays - it's now permanent // TODO: Emit event to persist allDay=true change // Clear references but leave item in DOM this.currentItem = null; this.sourceElement = null; } /** * Cleanup preview item and restore source visibility */ private cleanup(): void { // Remove preview item this.currentItem?.remove(); this.currentItem = null; // Restore source element visibility if (this.sourceElement) { this.sourceElement.style.visibility = ''; this.sourceElement = null; } // Collapse drawer if it wasn't expanded before drag if (!this.wasExpandedBeforeDrag) { this.headerDrawerManager.collapse(); } } }