import type { UnsubscribeCallback } from "./types"; type Subscriber<T extends any[]> = (...payload: T) => void; export class Emitter<T extends any[] = []> { public subscribers: Subscriber<T>[] = []; /** * Attaches subscriber * * @returns unsubscribe function */ on(...handlers: Subscriber<T>[] | Subscriber<T>[][]): UnsubscribeCallback { const _handlers = handlers .flat() .filter((item) => typeof item === "function"); this.subscribers.push(..._handlers); return () => this.off(_handlers); } once(...handlers: Subscriber<T>[] | Subscriber<T>[][]): UnsubscribeCallback { const _handlers = handlers .flat() .filter((item) => typeof item === "function"); _handlers.push(() => detach()); const detach = this.on(..._handlers); return detach; } off(...handlers: Subscriber<T>[] | Subscriber<T>[][]) { const _handlers = handlers.flat(); this.subscribers = this.subscribers.filter( (handler) => !_handlers.includes(handler), ); } trigger(...payload: T) { for (const handler of this.subscribers) { handler(...payload); } return this; } clear() { this.subscribers = []; } }