You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
success/packages/excalidraw/emitter.ts

61 lines
1.5 KiB
TypeScript

import { UnsubscribeCallback } from "./types";
type Subscriber<T extends any[]> = (...payload: T) => void;
export class Emitter<T extends any[] = []> {
public subscribers: Subscriber<T>[] = [];
public value: T | undefined;
private updateOnChangeOnly: boolean;
constructor(opts?: { initialState?: T; updateOnChangeOnly?: boolean }) {
this.updateOnChangeOnly = opts?.updateOnChangeOnly ?? false;
this.value = opts?.initialState;
}
/**
* 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): any[] {
if (this.updateOnChangeOnly && this.value === payload) {
return [];
}
this.value = payload;
return this.subscribers.map((handler) => handler(...payload));
}
destroy() {
this.subscribers = [];
this.value = undefined;
}
}