103 lines
2.5 KiB
TypeScript
103 lines
2.5 KiB
TypeScript
|
|
// Core EventBus using pure DOM CustomEvents
|
||
|
|
import { EventLogEntry, ListenerEntry, IEventBus } from '../types/CalendarTypes';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Central event dispatcher for calendar using DOM CustomEvents
|
||
|
|
* Provides logging and debugging capabilities
|
||
|
|
*/
|
||
|
|
export class EventBus implements IEventBus {
|
||
|
|
private eventLog: EventLogEntry[] = [];
|
||
|
|
private debug: boolean = false;
|
||
|
|
private listeners: Set<ListenerEntry> = new Set();
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Subscribe to an event via DOM addEventListener
|
||
|
|
*/
|
||
|
|
on(eventType: string, handler: EventListener, options?: AddEventListenerOptions): () => void {
|
||
|
|
document.addEventListener(eventType, handler, options);
|
||
|
|
|
||
|
|
// Track for cleanup
|
||
|
|
this.listeners.add({ eventType, handler, options });
|
||
|
|
|
||
|
|
// Return unsubscribe function
|
||
|
|
return () => this.off(eventType, handler);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Subscribe to an event once
|
||
|
|
*/
|
||
|
|
once(eventType: string, handler: EventListener): () => void {
|
||
|
|
return this.on(eventType, handler, { once: true });
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Unsubscribe from an event
|
||
|
|
*/
|
||
|
|
off(eventType: string, handler: EventListener): void {
|
||
|
|
document.removeEventListener(eventType, handler);
|
||
|
|
|
||
|
|
// Remove from tracking
|
||
|
|
for (const listener of this.listeners) {
|
||
|
|
if (listener.eventType === eventType && listener.handler === handler) {
|
||
|
|
this.listeners.delete(listener);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Emit an event via DOM CustomEvent
|
||
|
|
*/
|
||
|
|
emit(eventType: string, detail: any = {}): boolean {
|
||
|
|
const event = new CustomEvent(eventType, {
|
||
|
|
detail,
|
||
|
|
bubbles: true,
|
||
|
|
cancelable: true
|
||
|
|
});
|
||
|
|
|
||
|
|
// Log event
|
||
|
|
if (this.debug) {
|
||
|
|
console.log(`📢 Event: ${eventType}`, detail);
|
||
|
|
}
|
||
|
|
|
||
|
|
this.eventLog.push({
|
||
|
|
type: eventType,
|
||
|
|
detail,
|
||
|
|
timestamp: Date.now()
|
||
|
|
});
|
||
|
|
|
||
|
|
// Emit on document (only DOM events now)
|
||
|
|
return !document.dispatchEvent(event);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get event history
|
||
|
|
*/
|
||
|
|
getEventLog(eventType?: string): EventLogEntry[] {
|
||
|
|
if (eventType) {
|
||
|
|
return this.eventLog.filter(e => e.type === eventType);
|
||
|
|
}
|
||
|
|
return this.eventLog;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Enable/disable debug mode
|
||
|
|
*/
|
||
|
|
setDebug(enabled: boolean): void {
|
||
|
|
this.debug = enabled;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Clean up all tracked listeners
|
||
|
|
*/
|
||
|
|
destroy(): void {
|
||
|
|
for (const listener of this.listeners) {
|
||
|
|
document.removeEventListener(listener.eventType, listener.handler);
|
||
|
|
}
|
||
|
|
this.listeners.clear();
|
||
|
|
this.eventLog = [];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create singleton instance
|
||
|
|
export const eventBus = new EventBus();
|