import { eventBus } from '../core/EventBus'; import { calendarConfig } from '../core/CalendarConfig'; import { CalendarTypeFactory } from '../factories/CalendarTypeFactory'; /** * HeaderManager - Handles all header-related event logic * Separates event handling from rendering concerns */ export class HeaderManager { private headerEventListener: ((event: Event) => void) | null = null; private headerMouseLeaveListener: ((event: Event) => void) | null = null; private cachedCalendarHeader: HTMLElement | null = null; constructor() { // Bind methods for event listeners this.setupHeaderDragListeners = this.setupHeaderDragListeners.bind(this); this.destroy = this.destroy.bind(this); } /** * Get cached calendar header element */ private getCalendarHeader(): HTMLElement | null { if (!this.cachedCalendarHeader) { this.cachedCalendarHeader = document.querySelector('swp-calendar-header'); } return this.cachedCalendarHeader; } /** * Setup header drag event listeners */ public setupHeaderDragListeners(): void { const calendarHeader = this.getCalendarHeader(); if (!calendarHeader) return; // Clean up existing listeners first this.removeEventListeners(); // Throttle for better performance let lastEmitTime = 0; const throttleDelay = 16; // ~60fps this.headerEventListener = (event: Event) => { const now = Date.now(); if (now - lastEmitTime < throttleDelay) { return; // Throttle events for better performance } lastEmitTime = now; const target = event.target as HTMLElement; // Optimized element detection - only handle day headers const dayHeader = target.closest('swp-day-header'); if (dayHeader) { const hoveredElement = dayHeader as HTMLElement; const targetDate = hoveredElement.dataset.date; // Get header renderer for coordination const calendarType = calendarConfig.getCalendarMode(); const headerRenderer = CalendarTypeFactory.getHeaderRenderer(calendarType); eventBus.emit('header:mouseover', { element: hoveredElement, targetDate, headerRenderer }); } }; // Header mouseleave listener this.headerMouseLeaveListener = (event: Event) => { eventBus.emit('header:mouseleave', { element: event.target as HTMLElement }); }; // Add event listeners calendarHeader.addEventListener('mouseover', this.headerEventListener); calendarHeader.addEventListener('mouseleave', this.headerMouseLeaveListener); } /** * Remove event listeners from header */ private removeEventListeners(): void { const calendarHeader = this.getCalendarHeader(); if (!calendarHeader) return; if (this.headerEventListener) { calendarHeader.removeEventListener('mouseover', this.headerEventListener); } if (this.headerMouseLeaveListener) { calendarHeader.removeEventListener('mouseleave', this.headerMouseLeaveListener); } } /** * Clear cached header reference */ public clearCache(): void { this.cachedCalendarHeader = null; } /** * Clean up resources and event listeners */ public destroy(): void { this.removeEventListeners(); // Clear references this.headerEventListener = null; this.headerMouseLeaveListener = null; this.clearCache(); } }