@etsoo/toolpad
Version:
Dashboard framework extention based on Toolpad Core
82 lines (73 loc) • 2.11 kB
text/typescript
export type EventName = string | symbol;
export type EventHandlers = Record<EventName, unknown>;
export type EventHandler<
T extends EventHandlers,
K extends keyof T = keyof T
> = (event: T[K]) => void;
export type AllEventsHandler<
T extends EventHandlers,
K extends keyof T = keyof T
> = (type: K, event: T[K]) => void;
/**
* Lightweight event emitter
*/
export class Emitter<T extends EventHandlers = {}> {
private handlers = new Map<
keyof T,
Set<EventHandler<T> | AllEventsHandler<T>>
>();
/**
* Add a listener for an event
*/
on(name: "*", handler: AllEventsHandler<T>): void;
on<K extends keyof T>(name: K, handler: EventHandler<T, K>): void;
on<K extends keyof T>(
name: K | "*",
handler: EventHandler<T, K> | AllEventsHandler<T>
): void {
let eventHandlers = this.handlers.get(name);
if (!eventHandlers) {
eventHandlers = new Set();
this.handlers.set(name, eventHandlers);
}
eventHandlers.add(handler as EventHandler<T> | AllEventsHandler<T>);
}
/**
* Remove a listener from an event
*/
off<K extends keyof T>(name: K, handler: EventHandler<T, K>) {
const eventHandlers = this.handlers.get(name);
if (eventHandlers) {
eventHandlers.delete(handler as EventHandler<T> | AllEventsHandler<T>);
if (eventHandlers.size <= 0) {
this.handlers.delete(name);
}
}
}
/**
* Subscribe to an event and return an unsubscribe function.
*/
subscribe<K extends keyof T>(name: K, handler: EventHandler<T, K>) {
this.on(name, handler);
return () => {
this.off(name, handler);
};
}
/**
* Emit an event.
*/
emit<K extends keyof T>(name: K, event: T[K]) {
const eventHandlers = this.handlers.get(name);
if (eventHandlers) {
for (const eventHandler of eventHandlers) {
(eventHandler as EventHandler<T, K>)(event);
}
}
const allHandlers = this.handlers.get("*");
if (allHandlers) {
for (const eventHandler of allHandlers) {
(eventHandler as AllEventsHandler<T>)(name, event);
}
}
}
}