Moves event hover handling from DragDropManager to a new DragHoverManager. This improves separation of concerns and makes the hover logic more modular and reusable. The DragHoverManager is now responsible for tracking when the mouse hovers over events, and it emits events for other parts of the application to react to. The drag:start event is used to deactivate hover tracking when a drag operation starts.
116 lines
3.5 KiB
TypeScript
116 lines
3.5 KiB
TypeScript
/**
|
|
* DragHoverManager - Handles event hover tracking
|
|
* Fully autonomous - listens to mouse events and manages hover state independently
|
|
*/
|
|
|
|
import { IEventBus } from '../types/CalendarTypes';
|
|
|
|
export class DragHoverManager {
|
|
private isHoverTrackingActive = false;
|
|
private currentHoveredEvent: HTMLElement | null = null;
|
|
private calendarContainer: HTMLElement | null = null;
|
|
|
|
constructor(private eventBus: IEventBus) {
|
|
this.init();
|
|
}
|
|
|
|
private init(): void {
|
|
// Wait for DOM to be ready
|
|
setTimeout(() => {
|
|
this.calendarContainer = document.querySelector('swp-calendar-container');
|
|
if (this.calendarContainer) {
|
|
this.setupEventListeners();
|
|
}
|
|
}, 100);
|
|
|
|
// Listen to drag start to deactivate hover tracking
|
|
this.eventBus.on('drag:start', () => {
|
|
this.deactivateTracking();
|
|
});
|
|
}
|
|
|
|
private setupEventListeners(): void {
|
|
if (!this.calendarContainer) return;
|
|
|
|
// Listen to mouseenter on events (using event delegation)
|
|
this.calendarContainer.addEventListener('mouseenter', (e) => {
|
|
const target = e.target as HTMLElement;
|
|
const eventElement = target.closest<HTMLElement>('swp-event');
|
|
|
|
if (eventElement) {
|
|
this.handleEventMouseEnter(e as MouseEvent, eventElement);
|
|
}
|
|
}, true); // Use capture phase
|
|
|
|
// Listen to mousemove globally to track when mouse leaves event bounds
|
|
document.body.addEventListener('mousemove', (e: MouseEvent) => {
|
|
if (this.isHoverTrackingActive && e.buttons === 0) {
|
|
this.checkEventHover(e);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Handle mouse enter on swp-event - activate hover tracking
|
|
*/
|
|
private handleEventMouseEnter(event: MouseEvent, eventElement: HTMLElement): void {
|
|
// Only handle hover if mouse button is up
|
|
if (event.buttons === 0) {
|
|
// Clear any previous hover first
|
|
if (this.currentHoveredEvent && this.currentHoveredEvent !== eventElement) {
|
|
this.currentHoveredEvent.classList.remove('hover');
|
|
}
|
|
|
|
this.isHoverTrackingActive = true;
|
|
this.currentHoveredEvent = eventElement;
|
|
eventElement.classList.add('hover');
|
|
|
|
this.eventBus.emit('event:hover:start', { element: eventElement });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if mouse is still over the currently hovered event
|
|
*/
|
|
private checkEventHover(event: MouseEvent): void {
|
|
// Only track hover when active and mouse button is up
|
|
if (!this.isHoverTrackingActive || !this.currentHoveredEvent) return;
|
|
|
|
const rect = this.currentHoveredEvent.getBoundingClientRect();
|
|
const mouseX = event.clientX;
|
|
const mouseY = event.clientY;
|
|
|
|
// Check if mouse is still within the current hovered event
|
|
const isStillInside = mouseX >= rect.left && mouseX <= rect.right &&
|
|
mouseY >= rect.top && mouseY <= rect.bottom;
|
|
|
|
// If mouse left the event
|
|
if (!isStillInside) {
|
|
// Only disable tracking and clear if mouse is NOT pressed (allow resize to work)
|
|
if (event.buttons === 0) {
|
|
this.isHoverTrackingActive = false;
|
|
this.clearEventHover();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear hover state
|
|
*/
|
|
private clearEventHover(): void {
|
|
if (this.currentHoveredEvent) {
|
|
this.currentHoveredEvent.classList.remove('hover');
|
|
this.eventBus.emit('event:hover:end', { element: this.currentHoveredEvent });
|
|
this.currentHoveredEvent = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deactivate hover tracking and clear any current hover
|
|
* Called via event bus when drag starts
|
|
*/
|
|
private deactivateTracking(): void {
|
|
this.isHoverTrackingActive = false;
|
|
this.clearEventHover();
|
|
}
|
|
}
|