evnty 1.3.4 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.cjs +9 -0
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +82 -27
- package/build/index.js +9 -0
- package/build/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +92 -28
package/build/index.cjs
CHANGED
|
@@ -150,6 +150,15 @@ class Event extends FunctionExt {
|
|
|
150
150
|
const reducedEvent = new Event(dispose);
|
|
151
151
|
return reducedEvent;
|
|
152
152
|
}
|
|
153
|
+
debounce(interval) {
|
|
154
|
+
let timer;
|
|
155
|
+
const dispose = this.on((...args)=>{
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
timer = setTimeout(()=>debouncedEvent(...args), interval);
|
|
158
|
+
});
|
|
159
|
+
const debouncedEvent = new Event(dispose);
|
|
160
|
+
return debouncedEvent;
|
|
161
|
+
}
|
|
153
162
|
}
|
|
154
163
|
const once = (event)=>{
|
|
155
164
|
return new Promise((resolve)=>event.once((...args)=>resolve(args)));
|
package/build/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R = unknown> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R = unknown> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R = unknown> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of FunctionExt is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport interface Task {\n (): MaybePromise<unknown>;\n}\n\nexport class Dismiss extends FunctionExt {\n constructor(callback: Unsubscribe) {\n super(callback);\n }\n\n async after(task: Task) {\n await task();\n this();\n }\n\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\n\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\n\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\n\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n * @example\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n *\n * @template T - The tuple of arguments that the event takes.\n * @template R - The return type of the event.\n */\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n /**\n * Merges multiple events into a single event.\n * @param events - The events to merge.\n * @returns The merged event.\n */\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n /**\n * Creates an event that triggers at a specified interval.\n * @param interval - The interval at which to trigger the event.\n * @returns The interval event.\n */\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: NodeJS.Timeout = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n /**\n * The array of listeners for the event.\n */\n private listeners: Listeners<T, R>;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Dispose;\n\n /**\n * Creates a new event.\n * @param dispose - A function to dispose of the event and its listeners.\n */\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if a listener is not registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is not registered, `false` otherwise.\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if a listener is registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is registered, `false` otherwise.\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a listener from the event.\n * @param listener - The listener to remove.\n */\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n /**\n * Adds a listener to the event.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n /**\n * Adds a listener to the event that will only be called once.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event.\n */\n clear() {\n this.listeners.splice(0);\n }\n\n /**\n * Converts the event to a promise that resolves with the event arguments.\n * @returns A promise that resolves with the event arguments.\n */\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n /**\n * Creates a new event that only triggers if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that only triggers once if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n first(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n dispose();\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that maps the event arguments to a new value.\n * @param mapper - The mapper function.\n * @returns The mapped event.\n */\n map<M, MR = unknown>(mapper: Mapper<T, M>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event<[M], MR>(dispose);\n return mappedEvent;\n }\n\n /**\n * Creates a new event that reduces the event arguments to a single value.\n * @param reducer - The reducer function.\n * @param init - The initial value for the reducer.\n * @returns The reduced event.\n */\n reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event<[A], AR>(dispose);\n return reducedEvent;\n }\n}\n\n/**\n * Returns a promise that resolves with the arguments passed to the first invocation of the given event.\n * @param event The event to listen for.\n * @returns A promise that resolves with the arguments passed to the first invocation of the given event.\n */\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\n/**\n * Creates a new instance of the Event class.\n * @returns {Event<T, R>} A new instance of the Event class.\n * @template T The type of the arguments passed to the event.\n * @template R The return type of the event.\n */\nexport const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {\n return new Event<T, R>();\n};\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @template E - The event object type.\n * @template T - The event type extracted from the event object.\n * @template R - The result type returned by the event handler function.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n"],"names":["FunctionExt","Dismiss","Event","once","createEvent","Function","constructor","func","Object","setPrototypeOf","prototype","callback","after","task","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","oneTimeListener","toPromise","resolve","filter","filteredEvent","first","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R = unknown> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R = unknown> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R = unknown> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of FunctionExt is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport interface Task {\n (): MaybePromise<unknown>;\n}\n\n/**\n * @internal\n */\nexport class Dismiss extends FunctionExt {\n constructor(callback: Unsubscribe) {\n super(callback);\n }\n\n async after(task: Task) {\n await task();\n this();\n }\n\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\n\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\n\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\n\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n *\n * @typeParam T - The tuple of arguments that the event takes.\n * @typeParam R - The return type of the event.\n */\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n /**\n * Merges multiple events into a single event.\n * @example\n * const inputEvent = Event.merge(mouseEvent, keyboardEvent);\n *\n * @param events - The events to merge.\n * @returns The merged event.\n */\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n /**\n * Creates an event that triggers at a specified interval.\n * @example\n * const tickEvent = Event.interval(1000);\n * tickEvent.on((tickNumber) => console.log(tickNumber));\n *\n * @param interval - The interval at which to trigger the event.\n * @returns The interval event.\n */\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: ReturnType<typeof setInterval> = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n /**\n * The array of listeners for the event.\n */\n private listeners: Listeners<T, R>;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Dispose;\n\n /**\n * Creates a new event.\n * @example\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n * clickEvent.on((x, y) => console.log(`Clicked at ${x}, ${y}`));\n *\n * @param dispose - A function to call on the event disposal.\n */\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if a listener is not registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is not registered, `false` otherwise.\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if a listener is registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is registered, `false` otherwise.\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a listener from the event.\n * @param listener - The listener to remove.\n */\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n /**\n * Adds a listener to the event.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n /**\n * Adds a listener to the event that will only be called once.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event.\n */\n clear() {\n this.listeners.splice(0);\n }\n\n /**\n * Returns a Promise that resolves with the first emitted by the event arguments.\n * @returns A Promise that resolves with the first emitted by the event.\n */\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n /**\n * Returns a new event that only triggers when the provided filter function returns `true`.\n * @example\n * const spacePressEvent = keyboardEvent.filter((key) => key === 'Space');\n *\n * @param filter The filter function to apply to the event.\n * @returns A new event that only triggers when the provided filter function returns `true`.\n */\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Returns a new event that will only be triggered once the provided filter function returns `true`.\n * @example\n * const escPressEvent = keyboardEvent.first((key) => key === 'Esc');\n * await escPressEvent.toPromise();\n *\n * @param filter - The filter function.\n * @returns A new event that will only be triggered once the provided filter function returns `true`.\n */\n first(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n dispose();\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Returns a new event that maps the values of this event using the provided mapper function.\n * @example\n * const keyPressEvent = keyboardEvent.map((key) => key.toUpperCase()); // ['a'] -> ['A']\n *\n * @param mapper A function that maps the values of this event to a new value.\n * @returns A new event that emits the mapped values.\n */\n map<M, MR = unknown>(mapper: Mapper<T, M>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event<[M], MR>(dispose);\n return mappedEvent;\n }\n\n /**\n * Returns a new event that reduces the emitted values using the provided reducer function.\n * @example\n * const sumEvent = numberEvent.reduce((a, b) => a + b, 0);\n * sumEvent.on((sum) => console.log(sum)); // 1, 3, 6\n * sumEvent(1);\n * sumEvent(2);\n * sumEvent(3);\n *\n * @typeParam A The type of the accumulator value.\n * @typeParam AR The type of the reduced value.\n * @param {Reducer<T, A>} reducer The reducer function that reduces the emitted values.\n * @param {A} init The initial value of the accumulator.\n * @returns {Event<[A], AR>} A new event that reduces the emitted values using the provided reducer function.\n */\n reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event<[A], AR>(dispose);\n return reducedEvent;\n }\n\n /**\n * Returns a new debounced event that will not fire until a certain amount of time has passed\n * since the last time it was triggered.\n * @example\n * const debouncedEvent = textInputEvent.debounce(100);\n * debouncedEvent.on((str) => console.log(str)); // 'test'\n * event('t');\n * event('te');\n * event('tes');\n * event('test');\n *\n * @param interval - The amount of time to wait before firing the debounced event, in milliseconds.\n * @returns A new debounced event.\n */\n debounce(interval: number) {\n let timer: ReturnType<typeof setTimeout>;\n const dispose = this.on((...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => debouncedEvent(...args), interval);\n });\n const debouncedEvent = new Event<T, R>(dispose);\n return debouncedEvent;\n }\n}\n\n/**\n * Returns a promise that resolves with the arguments passed to the first invocation of the given event.\n * @example\n * const [x, y] = await once(mouseEvent);\n *\n * @param event The event to listen for.\n * @returns A promise that resolves with the arguments passed to the first invocation of the given event.\n */\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\n/**\n * Creates a new event instance.\n *\n * @typeParam T - An array of argument types that the event will accept.\n * @typeParam R - The return type of the event handler function.\n * @returns A new instance of the `Event` class.\n *\n * @example\n * const myEvent = createEvent<[string], number>();\n * myEvent.on((str: string) => str.length);\n * await myEvent('hello'); // [5]\n */\nexport const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {\n return new Event<T, R>();\n};\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @typeParam E - The event object type.\n * @typeParam T - The event type extracted from the event object.\n * @typeParam R - The result type returned by the event handler function.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n"],"names":["FunctionExt","Dismiss","Event","once","createEvent","Function","constructor","func","Object","setPrototypeOf","prototype","callback","after","task","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","oneTimeListener","toPromise","resolve","filter","filteredEvent","first","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent","debounce","timer","clearTimeout","setTimeout","debouncedEvent"],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -33,6 +33,9 @@ export interface Dismiss {
|
|
|
33
33
|
export interface Task {
|
|
34
34
|
(): MaybePromise<unknown>;
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
36
39
|
export declare class Dismiss extends FunctionExt {
|
|
37
40
|
constructor(callback: Unsubscribe);
|
|
38
41
|
after(task: Task): Promise<void>;
|
|
@@ -51,22 +54,26 @@ type UnpackAllReturn<T extends Event<unknown[], unknown>[]> = {
|
|
|
51
54
|
}[number];
|
|
52
55
|
/**
|
|
53
56
|
* A class representing an anonymous event that can be listened to or triggered.
|
|
54
|
-
* @example
|
|
55
|
-
* // Create a click event.
|
|
56
|
-
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
57
57
|
*
|
|
58
|
-
* @
|
|
59
|
-
* @
|
|
58
|
+
* @typeParam T - The tuple of arguments that the event takes.
|
|
59
|
+
* @typeParam R - The return type of the event.
|
|
60
60
|
*/
|
|
61
61
|
export declare class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
62
62
|
/**
|
|
63
63
|
* Merges multiple events into a single event.
|
|
64
|
+
* @example
|
|
65
|
+
* const inputEvent = Event.merge(mouseEvent, keyboardEvent);
|
|
66
|
+
*
|
|
64
67
|
* @param events - The events to merge.
|
|
65
68
|
* @returns The merged event.
|
|
66
69
|
*/
|
|
67
70
|
static merge<Events extends Event<any[], any>[]>(...events: Events): Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>;
|
|
68
71
|
/**
|
|
69
72
|
* Creates an event that triggers at a specified interval.
|
|
73
|
+
* @example
|
|
74
|
+
* const tickEvent = Event.interval(1000);
|
|
75
|
+
* tickEvent.on((tickNumber) => console.log(tickNumber));
|
|
76
|
+
*
|
|
70
77
|
* @param interval - The interval at which to trigger the event.
|
|
71
78
|
* @returns The interval event.
|
|
72
79
|
*/
|
|
@@ -81,7 +88,12 @@ export declare class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
81
88
|
readonly dispose: Dispose;
|
|
82
89
|
/**
|
|
83
90
|
* Creates a new event.
|
|
84
|
-
* @
|
|
91
|
+
* @example
|
|
92
|
+
* // Create a click event.
|
|
93
|
+
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
94
|
+
* clickEvent.on((x, y) => console.log(`Clicked at ${x}, ${y}`));
|
|
95
|
+
*
|
|
96
|
+
* @param dispose - A function to call on the event disposal.
|
|
85
97
|
*/
|
|
86
98
|
constructor(dispose?: Dispose);
|
|
87
99
|
/**
|
|
@@ -122,55 +134,98 @@ export declare class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
122
134
|
*/
|
|
123
135
|
clear(): void;
|
|
124
136
|
/**
|
|
125
|
-
*
|
|
126
|
-
* @returns A
|
|
137
|
+
* Returns a Promise that resolves with the first emitted by the event arguments.
|
|
138
|
+
* @returns A Promise that resolves with the first emitted by the event.
|
|
127
139
|
*/
|
|
128
140
|
toPromise(): Promise<T>;
|
|
129
141
|
/**
|
|
130
|
-
*
|
|
131
|
-
* @
|
|
132
|
-
*
|
|
142
|
+
* Returns a new event that only triggers when the provided filter function returns `true`.
|
|
143
|
+
* @example
|
|
144
|
+
* const spacePressEvent = keyboardEvent.filter((key) => key === 'Space');
|
|
145
|
+
*
|
|
146
|
+
* @param filter The filter function to apply to the event.
|
|
147
|
+
* @returns A new event that only triggers when the provided filter function returns `true`.
|
|
133
148
|
*/
|
|
134
149
|
filter(filter: Filter<T>): Event<T, R>;
|
|
135
150
|
/**
|
|
136
|
-
*
|
|
151
|
+
* Returns a new event that will only be triggered once the provided filter function returns `true`.
|
|
152
|
+
* @example
|
|
153
|
+
* const escPressEvent = keyboardEvent.first((key) => key === 'Esc');
|
|
154
|
+
* await escPressEvent.toPromise();
|
|
155
|
+
*
|
|
137
156
|
* @param filter - The filter function.
|
|
138
|
-
* @returns
|
|
157
|
+
* @returns A new event that will only be triggered once the provided filter function returns `true`.
|
|
139
158
|
*/
|
|
140
159
|
first(filter: Filter<T>): Event<T, R>;
|
|
141
160
|
/**
|
|
142
|
-
*
|
|
143
|
-
* @
|
|
144
|
-
*
|
|
161
|
+
* Returns a new event that maps the values of this event using the provided mapper function.
|
|
162
|
+
* @example
|
|
163
|
+
* const keyPressEvent = keyboardEvent.map((key) => key.toUpperCase()); // ['a'] -> ['A']
|
|
164
|
+
*
|
|
165
|
+
* @param mapper A function that maps the values of this event to a new value.
|
|
166
|
+
* @returns A new event that emits the mapped values.
|
|
145
167
|
*/
|
|
146
168
|
map<M, MR = unknown>(mapper: Mapper<T, M>): Event<[M], MR>;
|
|
147
169
|
/**
|
|
148
|
-
*
|
|
149
|
-
* @
|
|
150
|
-
*
|
|
151
|
-
*
|
|
170
|
+
* Returns a new event that reduces the emitted values using the provided reducer function.
|
|
171
|
+
* @example
|
|
172
|
+
* const sumEvent = numberEvent.reduce((a, b) => a + b, 0);
|
|
173
|
+
* sumEvent.on((sum) => console.log(sum)); // 1, 3, 6
|
|
174
|
+
* sumEvent(1);
|
|
175
|
+
* sumEvent(2);
|
|
176
|
+
* sumEvent(3);
|
|
177
|
+
*
|
|
178
|
+
* @typeParam A The type of the accumulator value.
|
|
179
|
+
* @typeParam AR The type of the reduced value.
|
|
180
|
+
* @param {Reducer<T, A>} reducer The reducer function that reduces the emitted values.
|
|
181
|
+
* @param {A} init The initial value of the accumulator.
|
|
182
|
+
* @returns {Event<[A], AR>} A new event that reduces the emitted values using the provided reducer function.
|
|
152
183
|
*/
|
|
153
184
|
reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A): Event<[A], AR>;
|
|
185
|
+
/**
|
|
186
|
+
* Returns a new debounced event that will not fire until a certain amount of time has passed
|
|
187
|
+
* since the last time it was triggered.
|
|
188
|
+
* @example
|
|
189
|
+
* const debouncedEvent = textInputEvent.debounce(100);
|
|
190
|
+
* debouncedEvent.on((str) => console.log(str)); // 'test'
|
|
191
|
+
* event('t');
|
|
192
|
+
* event('te');
|
|
193
|
+
* event('tes');
|
|
194
|
+
* event('test');
|
|
195
|
+
*
|
|
196
|
+
* @param interval - The amount of time to wait before firing the debounced event, in milliseconds.
|
|
197
|
+
* @returns A new debounced event.
|
|
198
|
+
*/
|
|
199
|
+
debounce(interval: number): Event<T, R>;
|
|
154
200
|
}
|
|
155
201
|
/**
|
|
156
202
|
* Returns a promise that resolves with the arguments passed to the first invocation of the given event.
|
|
203
|
+
* @example
|
|
204
|
+
* const [x, y] = await once(mouseEvent);
|
|
205
|
+
*
|
|
157
206
|
* @param event The event to listen for.
|
|
158
207
|
* @returns A promise that resolves with the arguments passed to the first invocation of the given event.
|
|
159
208
|
*/
|
|
160
209
|
export declare const once: <T extends unknown[], R = void>(event: Event<T, R>) => Promise<T>;
|
|
161
210
|
/**
|
|
162
|
-
* Creates a new instance
|
|
163
|
-
*
|
|
164
|
-
* @
|
|
165
|
-
* @
|
|
211
|
+
* Creates a new event instance.
|
|
212
|
+
*
|
|
213
|
+
* @typeParam T - An array of argument types that the event will accept.
|
|
214
|
+
* @typeParam R - The return type of the event handler function.
|
|
215
|
+
* @returns A new instance of the `Event` class.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* const myEvent = createEvent<[string], number>();
|
|
219
|
+
* myEvent.on((str: string) => str.length);
|
|
220
|
+
* await myEvent('hello'); // [5]
|
|
166
221
|
*/
|
|
167
222
|
export declare const createEvent: <T extends unknown[], R = void>() => Event<T, R>;
|
|
168
223
|
export default createEvent;
|
|
169
224
|
/**
|
|
170
225
|
* A type helper that extracts the event listener type
|
|
171
226
|
*
|
|
172
|
-
* @
|
|
173
|
-
* @
|
|
174
|
-
* @
|
|
227
|
+
* @typeParam E - The event object type.
|
|
228
|
+
* @typeParam T - The event type extracted from the event object.
|
|
229
|
+
* @typeParam R - The result type returned by the event handler function.
|
|
175
230
|
*/
|
|
176
231
|
export type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;
|
package/build/index.js
CHANGED
|
@@ -120,6 +120,15 @@ export class Event extends FunctionExt {
|
|
|
120
120
|
const reducedEvent = new Event(dispose);
|
|
121
121
|
return reducedEvent;
|
|
122
122
|
}
|
|
123
|
+
debounce(interval) {
|
|
124
|
+
let timer;
|
|
125
|
+
const dispose = this.on((...args)=>{
|
|
126
|
+
clearTimeout(timer);
|
|
127
|
+
timer = setTimeout(()=>debouncedEvent(...args), interval);
|
|
128
|
+
});
|
|
129
|
+
const debouncedEvent = new Event(dispose);
|
|
130
|
+
return debouncedEvent;
|
|
131
|
+
}
|
|
123
132
|
}
|
|
124
133
|
export const once = (event)=>{
|
|
125
134
|
return new Promise((resolve)=>event.once((...args)=>resolve(args)));
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R = unknown> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R = unknown> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R = unknown> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of FunctionExt is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport interface Task {\n (): MaybePromise<unknown>;\n}\n\nexport class Dismiss extends FunctionExt {\n constructor(callback: Unsubscribe) {\n super(callback);\n }\n\n async after(task: Task) {\n await task();\n this();\n }\n\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\n\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\n\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\n\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n * @example\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n *\n * @template T - The tuple of arguments that the event takes.\n * @template R - The return type of the event.\n */\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n /**\n * Merges multiple events into a single event.\n * @param events - The events to merge.\n * @returns The merged event.\n */\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n /**\n * Creates an event that triggers at a specified interval.\n * @param interval - The interval at which to trigger the event.\n * @returns The interval event.\n */\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: NodeJS.Timeout = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n /**\n * The array of listeners for the event.\n */\n private listeners: Listeners<T, R>;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Dispose;\n\n /**\n * Creates a new event.\n * @param dispose - A function to dispose of the event and its listeners.\n */\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if a listener is not registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is not registered, `false` otherwise.\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if a listener is registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is registered, `false` otherwise.\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a listener from the event.\n * @param listener - The listener to remove.\n */\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n /**\n * Adds a listener to the event.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n /**\n * Adds a listener to the event that will only be called once.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event.\n */\n clear() {\n this.listeners.splice(0);\n }\n\n /**\n * Converts the event to a promise that resolves with the event arguments.\n * @returns A promise that resolves with the event arguments.\n */\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n /**\n * Creates a new event that only triggers if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that only triggers once if the filter function returns `true`.\n * @param filter - The filter function.\n * @returns The filtered event.\n */\n first(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n dispose();\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Creates a new event that maps the event arguments to a new value.\n * @param mapper - The mapper function.\n * @returns The mapped event.\n */\n map<M, MR = unknown>(mapper: Mapper<T, M>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event<[M], MR>(dispose);\n return mappedEvent;\n }\n\n /**\n * Creates a new event that reduces the event arguments to a single value.\n * @param reducer - The reducer function.\n * @param init - The initial value for the reducer.\n * @returns The reduced event.\n */\n reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event<[A], AR>(dispose);\n return reducedEvent;\n }\n}\n\n/**\n * Returns a promise that resolves with the arguments passed to the first invocation of the given event.\n * @param event The event to listen for.\n * @returns A promise that resolves with the arguments passed to the first invocation of the given event.\n */\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\n/**\n * Creates a new instance of the Event class.\n * @returns {Event<T, R>} A new instance of the Event class.\n * @template T The type of the arguments passed to the event.\n * @template R The return type of the event.\n */\nexport const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {\n return new Event<T, R>();\n};\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @template E - The event object type.\n * @template T - The event type extracted from the event object.\n * @template R - The result type returned by the event handler function.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n"],"names":["FunctionExt","Function","constructor","func","Object","setPrototypeOf","prototype","Dismiss","callback","after","task","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","Event","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","once","oneTimeListener","toPromise","resolve","filter","filteredEvent","first","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent","createEvent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type MaybePromise<T> = Promise<T> | PromiseLike<T> | T;\n\nexport interface Unsubscribe {\n (): void;\n}\n\nexport interface Listener<T extends unknown[], R = unknown> {\n (...args: T): MaybePromise<R | void>;\n}\n\nexport interface Dispose {\n (): void;\n}\n\nexport interface Filter<T extends unknown[]> {\n (...args: T): MaybePromise<boolean>;\n}\n\nexport interface Mapper<T extends unknown[], R = unknown> {\n (...args: T): R;\n}\n\nexport interface Reducer<T extends unknown[], R = unknown> {\n (value: R, ...args: T): R;\n}\n\nexport type Listeners<T extends unknown[], R = unknown> = Listener<T, R>[];\n\n/**\n * An abstract class that extends the built-in Function class. It allows instances of the class\n * to be called as functions. When an instance of FunctionExt is called as a function, it will\n * call the function passed to its constructor with the same arguments.\n * @internal\n */\nexport abstract class FunctionExt extends Function {\n constructor(func: Function) {\n super();\n return Object.setPrototypeOf(func, new.target.prototype);\n }\n}\n\nexport interface Dismiss {\n (): Promise<void> | void;\n}\n\nexport interface Task {\n (): MaybePromise<unknown>;\n}\n\n/**\n * @internal\n */\nexport class Dismiss extends FunctionExt {\n constructor(callback: Unsubscribe) {\n super(callback);\n }\n\n async after(task: Task) {\n await task();\n this();\n }\n\n afterTimes(count: number) {\n return () => {\n if (!--count) {\n this();\n }\n };\n }\n}\n\nconst eventEmitter = async <A extends unknown[], R>(listeners: Listeners<A, R>, ...args: A) => {\n return Promise.all(listeners.map((listener) => listener(...args)));\n};\n\nexport interface Event<T extends unknown[], R> {\n (...args: T): Promise<(R | undefined)[]>;\n}\n\ntype UnpackParameters<T> = T extends Event<infer P, unknown> ? P : never;\n\ntype UnpackReturn<T> = T extends Event<unknown[], infer R> ? R : never;\n\ntype UnpackAllParameters<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackParameters<T[K]> }[number];\n\ntype UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]: UnpackReturn<T[K]> }[number];\n\n/**\n * A class representing an anonymous event that can be listened to or triggered.\n *\n * @typeParam T - The tuple of arguments that the event takes.\n * @typeParam R - The return type of the event.\n */\nexport class Event<T extends unknown[], R = void> extends FunctionExt {\n /**\n * Merges multiple events into a single event.\n * @example\n * const inputEvent = Event.merge(mouseEvent, keyboardEvent);\n *\n * @param events - The events to merge.\n * @returns The merged event.\n */\n static merge<Events extends Event<any[], any>[]>(...events: Events) {\n const mergedEvent = new Event<UnpackAllParameters<Events>, UnpackAllReturn<Events>>();\n events.forEach((event) => event.on(mergedEvent));\n return mergedEvent;\n }\n\n /**\n * Creates an event that triggers at a specified interval.\n * @example\n * const tickEvent = Event.interval(1000);\n * tickEvent.on((tickNumber) => console.log(tickNumber));\n *\n * @param interval - The interval at which to trigger the event.\n * @returns The interval event.\n */\n static interval(interval: number) {\n let counter = 0;\n const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));\n const timerId: ReturnType<typeof setInterval> = setInterval(() => intervalEvent(counter++), interval);\n return intervalEvent;\n }\n\n /**\n * The array of listeners for the event.\n */\n private listeners: Listeners<T, R>;\n\n /**\n * A function that disposes of the event and its listeners.\n */\n readonly dispose: Dispose;\n\n /**\n * Creates a new event.\n * @example\n * // Create a click event.\n * const clickEvent = new Event<[x: number, y: number], void>();\n * clickEvent.on((x, y) => console.log(`Clicked at ${x}, ${y}`));\n *\n * @param dispose - A function to call on the event disposal.\n */\n constructor(dispose?: Dispose) {\n const listeners: Listeners<T, R> = [];\n const fn = (...args: T) => eventEmitter(listeners, ...args);\n\n super(fn);\n this.listeners = listeners;\n this.dispose = () => {\n this.clear();\n dispose?.();\n };\n }\n\n /**\n * The number of listeners for the event.\n */\n get size(): number {\n return this.listeners.length;\n }\n\n /**\n * Checks if a listener is not registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is not registered, `false` otherwise.\n */\n lacks(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) === -1;\n }\n\n /**\n * Checks if a listener is registered for the event.\n * @param listener - The listener to check.\n * @returns `true` if the listener is registered, `false` otherwise.\n */\n has(listener: Listener<T, R>): boolean {\n return this.listeners.indexOf(listener) !== -1;\n }\n\n /**\n * Removes a listener from the event.\n * @param listener - The listener to remove.\n */\n off(listener: Listener<T, R>): void {\n let index = this.listeners.indexOf(listener);\n while (~index) {\n this.listeners.splice(index, 1);\n index = this.listeners.indexOf(listener);\n }\n }\n\n /**\n * Adds a listener to the event.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n on(listener: Listener<T, R>): Dismiss {\n this.listeners.push(listener);\n return new Dismiss(() => this.off(listener));\n }\n\n /**\n * Adds a listener to the event that will only be called once.\n * @param listener - The listener to add.\n * @returns An object that can be used to remove the listener.\n */\n once(listener: Listener<T, R>): Dismiss {\n const oneTimeListener = (...args: T) => {\n this.off(oneTimeListener);\n return listener(...args);\n };\n return this.on(oneTimeListener);\n }\n\n /**\n * Removes all listeners from the event.\n */\n clear() {\n this.listeners.splice(0);\n }\n\n /**\n * Returns a Promise that resolves with the first emitted by the event arguments.\n * @returns A Promise that resolves with the first emitted by the event.\n */\n toPromise(): Promise<T> {\n return new Promise((resolve) => this.once((...args) => resolve(args)));\n }\n\n /**\n * Returns a new event that only triggers when the provided filter function returns `true`.\n * @example\n * const spacePressEvent = keyboardEvent.filter((key) => key === 'Space');\n *\n * @param filter The filter function to apply to the event.\n * @returns A new event that only triggers when the provided filter function returns `true`.\n */\n filter(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Returns a new event that will only be triggered once the provided filter function returns `true`.\n * @example\n * const escPressEvent = keyboardEvent.first((key) => key === 'Esc');\n * await escPressEvent.toPromise();\n *\n * @param filter - The filter function.\n * @returns A new event that will only be triggered once the provided filter function returns `true`.\n */\n first(filter: Filter<T>) {\n const dispose = this.on(async (...args) => {\n if (filteredEvent.size > 0 && (await filter(...args))) {\n dispose();\n await filteredEvent(...args);\n }\n });\n const filteredEvent = new Event<T, R>(dispose);\n return filteredEvent;\n }\n\n /**\n * Returns a new event that maps the values of this event using the provided mapper function.\n * @example\n * const keyPressEvent = keyboardEvent.map((key) => key.toUpperCase()); // ['a'] -> ['A']\n *\n * @param mapper A function that maps the values of this event to a new value.\n * @returns A new event that emits the mapped values.\n */\n map<M, MR = unknown>(mapper: Mapper<T, M>) {\n const dispose = this.on(async (...args) => {\n if (mappedEvent.size > 0) {\n const value = await mapper(...args);\n mappedEvent(value);\n }\n });\n const mappedEvent = new Event<[M], MR>(dispose);\n return mappedEvent;\n }\n\n /**\n * Returns a new event that reduces the emitted values using the provided reducer function.\n * @example\n * const sumEvent = numberEvent.reduce((a, b) => a + b, 0);\n * sumEvent.on((sum) => console.log(sum)); // 1, 3, 6\n * sumEvent(1);\n * sumEvent(2);\n * sumEvent(3);\n *\n * @typeParam A The type of the accumulator value.\n * @typeParam AR The type of the reduced value.\n * @param {Reducer<T, A>} reducer The reducer function that reduces the emitted values.\n * @param {A} init The initial value of the accumulator.\n * @returns {Event<[A], AR>} A new event that reduces the emitted values using the provided reducer function.\n */\n reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {\n let value = init;\n const dispose = this.on(async (...args) => {\n if (reducedEvent.size > 0) {\n value = await reducer(value, ...args);\n reducedEvent(value);\n }\n });\n const reducedEvent = new Event<[A], AR>(dispose);\n return reducedEvent;\n }\n\n /**\n * Returns a new debounced event that will not fire until a certain amount of time has passed\n * since the last time it was triggered.\n * @example\n * const debouncedEvent = textInputEvent.debounce(100);\n * debouncedEvent.on((str) => console.log(str)); // 'test'\n * event('t');\n * event('te');\n * event('tes');\n * event('test');\n *\n * @param interval - The amount of time to wait before firing the debounced event, in milliseconds.\n * @returns A new debounced event.\n */\n debounce(interval: number) {\n let timer: ReturnType<typeof setTimeout>;\n const dispose = this.on((...args) => {\n clearTimeout(timer);\n timer = setTimeout(() => debouncedEvent(...args), interval);\n });\n const debouncedEvent = new Event<T, R>(dispose);\n return debouncedEvent;\n }\n}\n\n/**\n * Returns a promise that resolves with the arguments passed to the first invocation of the given event.\n * @example\n * const [x, y] = await once(mouseEvent);\n *\n * @param event The event to listen for.\n * @returns A promise that resolves with the arguments passed to the first invocation of the given event.\n */\nexport const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise<T> => {\n return new Promise((resolve) => event.once((...args) => resolve(args)));\n};\n\n/**\n * Creates a new event instance.\n *\n * @typeParam T - An array of argument types that the event will accept.\n * @typeParam R - The return type of the event handler function.\n * @returns A new instance of the `Event` class.\n *\n * @example\n * const myEvent = createEvent<[string], number>();\n * myEvent.on((str: string) => str.length);\n * await myEvent('hello'); // [5]\n */\nexport const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {\n return new Event<T, R>();\n};\n\nexport default createEvent;\n\n/**\n * A type helper that extracts the event listener type\n *\n * @typeParam E - The event object type.\n * @typeParam T - The event type extracted from the event object.\n * @typeParam R - The result type returned by the event handler function.\n */\nexport type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;\n"],"names":["FunctionExt","Function","constructor","func","Object","setPrototypeOf","prototype","Dismiss","callback","after","task","afterTimes","count","eventEmitter","listeners","args","Promise","all","map","listener","Event","merge","events","mergedEvent","forEach","event","on","interval","counter","intervalEvent","clearInterval","timerId","setInterval","dispose","fn","clear","size","length","lacks","indexOf","has","off","index","splice","push","once","oneTimeListener","toPromise","resolve","filter","filteredEvent","first","mapper","mappedEvent","value","reduce","reducer","init","reducedEvent","debounce","timer","clearTimeout","setTimeout","debouncedEvent","createEvent"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "evnty",
|
|
3
3
|
"description": "0-Deps, simple, fast, for browser and node js anonymous event library",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
7
7
|
"main": "build/index.cjs",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"eslint-plugin-import": "^2.27.5",
|
|
60
60
|
"eslint-plugin-prettier": "^5.0.0",
|
|
61
61
|
"husky": "^8.0.3",
|
|
62
|
-
"inop": "^0.
|
|
62
|
+
"inop": "^0.4.2",
|
|
63
63
|
"jest": "^29.5.0",
|
|
64
64
|
"prettier": "^3.0.1",
|
|
65
65
|
"typescript": "^5.0.3"
|
package/src/index.ts
CHANGED
|
@@ -47,6 +47,9 @@ export interface Task {
|
|
|
47
47
|
(): MaybePromise<unknown>;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
50
53
|
export class Dismiss extends FunctionExt {
|
|
51
54
|
constructor(callback: Unsubscribe) {
|
|
52
55
|
super(callback);
|
|
@@ -84,16 +87,16 @@ type UnpackAllReturn<T extends Event<unknown[], unknown>[]> = { [K in keyof T]:
|
|
|
84
87
|
|
|
85
88
|
/**
|
|
86
89
|
* A class representing an anonymous event that can be listened to or triggered.
|
|
87
|
-
* @example
|
|
88
|
-
* // Create a click event.
|
|
89
|
-
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
90
90
|
*
|
|
91
|
-
* @
|
|
92
|
-
* @
|
|
91
|
+
* @typeParam T - The tuple of arguments that the event takes.
|
|
92
|
+
* @typeParam R - The return type of the event.
|
|
93
93
|
*/
|
|
94
94
|
export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
95
95
|
/**
|
|
96
96
|
* Merges multiple events into a single event.
|
|
97
|
+
* @example
|
|
98
|
+
* const inputEvent = Event.merge(mouseEvent, keyboardEvent);
|
|
99
|
+
*
|
|
97
100
|
* @param events - The events to merge.
|
|
98
101
|
* @returns The merged event.
|
|
99
102
|
*/
|
|
@@ -105,13 +108,17 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
105
108
|
|
|
106
109
|
/**
|
|
107
110
|
* Creates an event that triggers at a specified interval.
|
|
111
|
+
* @example
|
|
112
|
+
* const tickEvent = Event.interval(1000);
|
|
113
|
+
* tickEvent.on((tickNumber) => console.log(tickNumber));
|
|
114
|
+
*
|
|
108
115
|
* @param interval - The interval at which to trigger the event.
|
|
109
116
|
* @returns The interval event.
|
|
110
117
|
*/
|
|
111
118
|
static interval(interval: number) {
|
|
112
119
|
let counter = 0;
|
|
113
120
|
const intervalEvent = new Event<[number], void>(() => clearInterval(timerId));
|
|
114
|
-
const timerId:
|
|
121
|
+
const timerId: ReturnType<typeof setInterval> = setInterval(() => intervalEvent(counter++), interval);
|
|
115
122
|
return intervalEvent;
|
|
116
123
|
}
|
|
117
124
|
|
|
@@ -127,7 +134,12 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
127
134
|
|
|
128
135
|
/**
|
|
129
136
|
* Creates a new event.
|
|
130
|
-
* @
|
|
137
|
+
* @example
|
|
138
|
+
* // Create a click event.
|
|
139
|
+
* const clickEvent = new Event<[x: number, y: number], void>();
|
|
140
|
+
* clickEvent.on((x, y) => console.log(`Clicked at ${x}, ${y}`));
|
|
141
|
+
*
|
|
142
|
+
* @param dispose - A function to call on the event disposal.
|
|
131
143
|
*/
|
|
132
144
|
constructor(dispose?: Dispose) {
|
|
133
145
|
const listeners: Listeners<T, R> = [];
|
|
@@ -209,17 +221,20 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
209
221
|
}
|
|
210
222
|
|
|
211
223
|
/**
|
|
212
|
-
*
|
|
213
|
-
* @returns A
|
|
224
|
+
* Returns a Promise that resolves with the first emitted by the event arguments.
|
|
225
|
+
* @returns A Promise that resolves with the first emitted by the event.
|
|
214
226
|
*/
|
|
215
227
|
toPromise(): Promise<T> {
|
|
216
228
|
return new Promise((resolve) => this.once((...args) => resolve(args)));
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
/**
|
|
220
|
-
*
|
|
221
|
-
* @
|
|
222
|
-
*
|
|
232
|
+
* Returns a new event that only triggers when the provided filter function returns `true`.
|
|
233
|
+
* @example
|
|
234
|
+
* const spacePressEvent = keyboardEvent.filter((key) => key === 'Space');
|
|
235
|
+
*
|
|
236
|
+
* @param filter The filter function to apply to the event.
|
|
237
|
+
* @returns A new event that only triggers when the provided filter function returns `true`.
|
|
223
238
|
*/
|
|
224
239
|
filter(filter: Filter<T>) {
|
|
225
240
|
const dispose = this.on(async (...args) => {
|
|
@@ -232,9 +247,13 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
232
247
|
}
|
|
233
248
|
|
|
234
249
|
/**
|
|
235
|
-
*
|
|
250
|
+
* Returns a new event that will only be triggered once the provided filter function returns `true`.
|
|
251
|
+
* @example
|
|
252
|
+
* const escPressEvent = keyboardEvent.first((key) => key === 'Esc');
|
|
253
|
+
* await escPressEvent.toPromise();
|
|
254
|
+
*
|
|
236
255
|
* @param filter - The filter function.
|
|
237
|
-
* @returns
|
|
256
|
+
* @returns A new event that will only be triggered once the provided filter function returns `true`.
|
|
238
257
|
*/
|
|
239
258
|
first(filter: Filter<T>) {
|
|
240
259
|
const dispose = this.on(async (...args) => {
|
|
@@ -248,9 +267,12 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
248
267
|
}
|
|
249
268
|
|
|
250
269
|
/**
|
|
251
|
-
*
|
|
252
|
-
* @
|
|
253
|
-
*
|
|
270
|
+
* Returns a new event that maps the values of this event using the provided mapper function.
|
|
271
|
+
* @example
|
|
272
|
+
* const keyPressEvent = keyboardEvent.map((key) => key.toUpperCase()); // ['a'] -> ['A']
|
|
273
|
+
*
|
|
274
|
+
* @param mapper A function that maps the values of this event to a new value.
|
|
275
|
+
* @returns A new event that emits the mapped values.
|
|
254
276
|
*/
|
|
255
277
|
map<M, MR = unknown>(mapper: Mapper<T, M>) {
|
|
256
278
|
const dispose = this.on(async (...args) => {
|
|
@@ -264,10 +286,19 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
264
286
|
}
|
|
265
287
|
|
|
266
288
|
/**
|
|
267
|
-
*
|
|
268
|
-
* @
|
|
269
|
-
*
|
|
270
|
-
*
|
|
289
|
+
* Returns a new event that reduces the emitted values using the provided reducer function.
|
|
290
|
+
* @example
|
|
291
|
+
* const sumEvent = numberEvent.reduce((a, b) => a + b, 0);
|
|
292
|
+
* sumEvent.on((sum) => console.log(sum)); // 1, 3, 6
|
|
293
|
+
* sumEvent(1);
|
|
294
|
+
* sumEvent(2);
|
|
295
|
+
* sumEvent(3);
|
|
296
|
+
*
|
|
297
|
+
* @typeParam A The type of the accumulator value.
|
|
298
|
+
* @typeParam AR The type of the reduced value.
|
|
299
|
+
* @param {Reducer<T, A>} reducer The reducer function that reduces the emitted values.
|
|
300
|
+
* @param {A} init The initial value of the accumulator.
|
|
301
|
+
* @returns {Event<[A], AR>} A new event that reduces the emitted values using the provided reducer function.
|
|
271
302
|
*/
|
|
272
303
|
reduce<A, AR = unknown>(reducer: Reducer<T, A>, init: A) {
|
|
273
304
|
let value = init;
|
|
@@ -280,10 +311,37 @@ export class Event<T extends unknown[], R = void> extends FunctionExt {
|
|
|
280
311
|
const reducedEvent = new Event<[A], AR>(dispose);
|
|
281
312
|
return reducedEvent;
|
|
282
313
|
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Returns a new debounced event that will not fire until a certain amount of time has passed
|
|
317
|
+
* since the last time it was triggered.
|
|
318
|
+
* @example
|
|
319
|
+
* const debouncedEvent = textInputEvent.debounce(100);
|
|
320
|
+
* debouncedEvent.on((str) => console.log(str)); // 'test'
|
|
321
|
+
* event('t');
|
|
322
|
+
* event('te');
|
|
323
|
+
* event('tes');
|
|
324
|
+
* event('test');
|
|
325
|
+
*
|
|
326
|
+
* @param interval - The amount of time to wait before firing the debounced event, in milliseconds.
|
|
327
|
+
* @returns A new debounced event.
|
|
328
|
+
*/
|
|
329
|
+
debounce(interval: number) {
|
|
330
|
+
let timer: ReturnType<typeof setTimeout>;
|
|
331
|
+
const dispose = this.on((...args) => {
|
|
332
|
+
clearTimeout(timer);
|
|
333
|
+
timer = setTimeout(() => debouncedEvent(...args), interval);
|
|
334
|
+
});
|
|
335
|
+
const debouncedEvent = new Event<T, R>(dispose);
|
|
336
|
+
return debouncedEvent;
|
|
337
|
+
}
|
|
283
338
|
}
|
|
284
339
|
|
|
285
340
|
/**
|
|
286
341
|
* Returns a promise that resolves with the arguments passed to the first invocation of the given event.
|
|
342
|
+
* @example
|
|
343
|
+
* const [x, y] = await once(mouseEvent);
|
|
344
|
+
*
|
|
287
345
|
* @param event The event to listen for.
|
|
288
346
|
* @returns A promise that resolves with the arguments passed to the first invocation of the given event.
|
|
289
347
|
*/
|
|
@@ -292,10 +350,16 @@ export const once = <T extends unknown[], R = void>(event: Event<T, R>): Promise
|
|
|
292
350
|
};
|
|
293
351
|
|
|
294
352
|
/**
|
|
295
|
-
* Creates a new instance
|
|
296
|
-
*
|
|
297
|
-
* @
|
|
298
|
-
* @
|
|
353
|
+
* Creates a new event instance.
|
|
354
|
+
*
|
|
355
|
+
* @typeParam T - An array of argument types that the event will accept.
|
|
356
|
+
* @typeParam R - The return type of the event handler function.
|
|
357
|
+
* @returns A new instance of the `Event` class.
|
|
358
|
+
*
|
|
359
|
+
* @example
|
|
360
|
+
* const myEvent = createEvent<[string], number>();
|
|
361
|
+
* myEvent.on((str: string) => str.length);
|
|
362
|
+
* await myEvent('hello'); // [5]
|
|
299
363
|
*/
|
|
300
364
|
export const createEvent = <T extends unknown[], R = void>(): Event<T, R> => {
|
|
301
365
|
return new Event<T, R>();
|
|
@@ -306,8 +370,8 @@ export default createEvent;
|
|
|
306
370
|
/**
|
|
307
371
|
* A type helper that extracts the event listener type
|
|
308
372
|
*
|
|
309
|
-
* @
|
|
310
|
-
* @
|
|
311
|
-
* @
|
|
373
|
+
* @typeParam E - The event object type.
|
|
374
|
+
* @typeParam T - The event type extracted from the event object.
|
|
375
|
+
* @typeParam R - The result type returned by the event handler function.
|
|
312
376
|
*/
|
|
313
377
|
export type EventHandler<E> = E extends Event<infer T, infer R> ? Listener<T, R> : never;
|