|
| 1 | +/** |
| 2 | + * This event emitter is a minimal reimplementation of `mitt` with the support of stoppable event propagation |
| 3 | + */ |
| 4 | + |
| 5 | +export type EventType = string | symbol; |
| 6 | + |
| 7 | +// An event handler can take an optional event argument |
| 8 | +// and should return a boolean indicating whether or not to stop event propagation |
| 9 | +export type Handler<T = unknown> = (event: T) => boolean; |
| 10 | + |
| 11 | +// An array of all currently registered event handlers for a type |
| 12 | +export type EventHandlerList<T = unknown> = Array<Handler<T>>; |
| 13 | + |
| 14 | +// A map of event types and their corresponding event handlers. |
| 15 | +export type EventHandlerMap<Events extends Record<EventType, unknown>> = Map< |
| 16 | + keyof Events, |
| 17 | + EventHandlerList<Events[keyof Events]> |
| 18 | +>; |
| 19 | + |
| 20 | +export default class CustomEventEmitter<Events extends Record<EventType, unknown>> { |
| 21 | + private handlers: EventHandlerMap<Events> = new Map(); |
| 22 | + |
| 23 | + on = <Key extends keyof Events>(eventType: Key, handler: Handler<Events[keyof Events]>) => { |
| 24 | + const eventTypeHandlers = this.handlers.get(eventType); |
| 25 | + if (!Array.isArray(eventTypeHandlers)) this.handlers.set(eventType, [handler]); |
| 26 | + else eventTypeHandlers.push(handler); |
| 27 | + }; |
| 28 | + |
| 29 | + off = <Key extends keyof Events>(eventType: Key, handler?: Handler<Events[keyof Events]>) => { |
| 30 | + this.handlers.set( |
| 31 | + eventType, |
| 32 | + this.handlers.get(eventType).filter((h) => h !== handler), |
| 33 | + ); |
| 34 | + }; |
| 35 | + |
| 36 | + emit = <Key extends keyof Events>(eventType: Key, evt?: Events[Key]) => { |
| 37 | + const eventTypeHandlers = this.handlers.get(eventType); |
| 38 | + for (let index = eventTypeHandlers.length - 1; index >= 0; index--) { |
| 39 | + const handler = eventTypeHandlers[index]; |
| 40 | + if (handler(evt)) { |
| 41 | + return; |
| 42 | + } |
| 43 | + } |
| 44 | + }; |
| 45 | +} |
0 commit comments