diff --git a/core/signal/src/event-listener.ts b/core/signal/src/event-listener.ts new file mode 100644 index 000000000..ea8b005bf --- /dev/null +++ b/core/signal/src/event-listener.ts @@ -0,0 +1,131 @@ +import {Stringifyable, OmitFirstParam} from '@alwatr/type'; + +import {signalManager} from './signal-manager.js'; + +/** + * Event signal listener/subscriber interface. + */ +export const eventListener = { + /** + * Get last event dispatched detail. + * + * Return undefined if signal not dispatched before or expired. + * + * Example: + * + * ```ts + * const currentSize = eventTrigger.getLastDetail('window-resize'); + * if (currentSize === undefined) { + * // event-signal not dispatched yet + * } + * ``` + */ + getLastDetail: signalManager.getDetail, + + /** + * Wait until new event. + * + * Example: + * + * ```ts + * const newSize = await eventTrigger.untilNext('window-resize'); + * ``` + */ + untilNext: signalManager.untilNext, + + /** + * Subscribe new listener to an event, work like addEventListener. + * + * Example: + * + * ```ts + * const listener = eventTrigger.subscribe('window-resize', (size) => console.log(size)); + * ... + * eventTrigger.unsubscribe(listener); + * ``` + */ + subscribe: signalManager.subscribe, + + /** + * Unsubscribe listener from event, work like removeEventListener. + * + * Example: + * + * ```ts + * const listener = eventTrigger.subscribe('window-resize', (size) => console.log(size)); + * ... + * eventTrigger.unsubscribe(listener); + * ``` + */ + unsubscribe: signalManager.unsubscribe, + + /** + * Bind this interface to special event. + * + * Example: + * + * ```ts + * const resizeEvent = eventTrigger.bind('window-resize'); + * ``` + */ + bind: (eventId: string) => ({ + /** + * Event signal Id. + */ + id: eventId, + + /** + * Get last event dispatched detail. + * + * Return undefined if signal not dispatched before or expired. + * + * Example: + * + * ```ts + * const currentSize = resizeEvent.getLastDetail(); + * if (currentSize === undefined) { + * // signal not dispatched yet + * } + * ``` + */ + getLastDetail: signalManager.getDetail.bind(null, eventId) as OmitFirstParam>, + + /** + * Wait until new event. + * + * Example: + * + * ```ts + * const newSize = await resizeEvent.untilNext(); + * ``` + */ + untilNext: signalManager.untilNext.bind(null, eventId) as OmitFirstParam>, + + /** + * Subscribe new listener to an event, work like addEventListener. + * + * Example: + * + * ```ts + * const listener = resizeEvent.subscribe((size) => console.log(size)); + * ... + * resizeEvent.unsubscribe(listener); + * ``` + */ + subscribe: signalManager.subscribe.bind(null, eventId) as unknown as + OmitFirstParam>, + + /** + * Unsubscribe listener from event, work like removeEventListener. + * + * Example: + * + * ```ts + * const listener = resizeEvent.subscribe((size) => console.log(size)); + * ... + * resizeEvent.unsubscribe(listener); + * ``` + */ + unsubscribe: signalManager.unsubscribe, + }), +} as const;