import type { EVENTS } from "./constants" import { hasProp, isFunction } from "./utils" import type { ToastOptionsAndRequiredContent, ToastID, ToastContent, ToastOptions, PluginOptions, } from "../types/index" type EventData = { [EVENTS.ADD]: ToastOptionsAndRequiredContent & { id: ToastID } [EVENTS.CLEAR]: undefined [EVENTS.DISMISS]: ToastID [EVENTS.UPDATE]: | { id: ToastID options: Partial & { content?: ToastContent } create: false } | { id: ToastID options: Partial & { content: ToastContent } create: true } [EVENTS.UPDATE_DEFAULTS]: PluginOptions } type Handler = (event: EventData[E]) => void export interface EventBusInterface { on(eventType: E, handler: Handler): void off(eventType: E, handler: Handler): void emit(eventType: E, event: EventData[E]): void } type HandlerList = Handler[] type HandlerMap = { [E in EVENTS]?: HandlerList } export class EventBus implements EventBusInterface { protected allHandlers: HandlerMap = {} protected getHandlers(eventType: E) { return (this.allHandlers[eventType] as HandlerList | undefined) || [] } public on(eventType: E, handler: Handler) { const handlers = this.getHandlers(eventType) handlers.push(handler) this.allHandlers[eventType] = handlers as EventBus["allHandlers"][E] } public off(eventType: E, handler: Handler) { const handlers = this.getHandlers(eventType) handlers.splice(handlers.indexOf(handler) >>> 0, 1) } public emit(eventType: E, event: EventData[E]) { const handlers = this.getHandlers(eventType) handlers.forEach(handler => handler(event)) } } export const isEventBusInterface = (e: unknown): e is EventBusInterface => ["on", "off", "emit"].every(f => hasProp(e, f) && isFunction(e[f]))