jrx 0.2.0 → 0.3.0-alpha.1

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/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # jrx
2
2
 
3
- A lightweight TypeScript library for managing side effects, subscriptions, and animations with automatic cleanup. Built on top of [jdisposer](https://github.com/tranvansang/jdisposer) for safe resource management.
3
+ A lightweight TypeScript library for managing side effects, subscriptions, and animations with automatic cleanup using the [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) API.
4
+
5
+ ## Prerequisites
6
+
7
+ This library requires the [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) globals (`DisposableStack`, `AsyncDisposableStack`, `Symbol.dispose`, `Symbol.asyncDispose`). If your environment does not support them natively, you must load a polyfill before importing jrx (e.g. [`core-js`](https://github.com/nicolo-ribaudo/tc39-proposal-explicit-resource-management-polyfill)).
8
+
9
+ The `using` keyword is **not** required — this library only uses the API objects directly, so no transpiler support for `using` declarations is needed.
4
10
 
5
11
  ## Installation
6
12
 
@@ -11,36 +17,64 @@ npm i jrx
11
17
  ## Features
12
18
 
13
19
  - Automatic cleanup for all effects and subscriptions
14
- - Type-safe disposer pattern
20
+ - Built on the native `DisposableStack` / `AsyncDisposableStack` API
15
21
  - Retry logic with exponential backoff and cancellation
16
- - Single dependency (jdisposer)
22
+ - Zero dependencies
17
23
  - Composable reactive utilities
18
24
  - Browser and Node.js compatible
19
25
 
20
26
  ## API Overview
21
27
 
28
+ - [`makeReset()`](#makereset) - Create a resettable `DisposableStack`
29
+ - [`makeAsyncReset()`](#makeasyncreset) - Create a resettable `AsyncDisposableStack`
22
30
  - [`makeRenderLoop()`](#makerenderloop) - Render loops with automatic cleanup
23
- - [`addEvtListener(target, event, handler, option?)`](#addevtlistenertarget-event-handler-option) - Event listeners with cleanup
24
31
  - [`addInterval(cb, ms)`](#addintervalcb-ms) - Repeating intervals with cleanup
25
32
  - [`addIntervalAsync(cb, ms)`](#addintervalasynccb-ms) - Async intervals with cancellation
26
33
  - [`addRequestAnimationFrame(cb)`](#addrequestanimationframecb) - Single animation frame with cleanup
27
34
  - [`addRequestAnimationFrameLoop(cb)`](#addrequestanimationframeloopcb) - Animation frame loops
28
- - [`addSubs(subs, cb, options?)`](#addsubssubs-cb-options) - Multiple subscription management
29
35
  - [`addTimeout(cb, ms)`](#addtimeoutcb-ms) - Timeouts with cleanup
30
36
  - [`addTransition(cb, durationMs)`](#addtransitioncb-durationms) - Progress-based animations
31
37
  - [`computed(fn, getDeps?)`](#computedfn-getdeps) - Memoized computed values
32
- - [`retry(cb, options?)`](#retrycb-options) - Async retry with exponential backoff
38
+ - [`retry(cb, backoffSec?)`](#retrycb-backoffsec) - Retry with exponential backoff
33
39
 
34
40
  ## API
35
41
 
42
+ ### `makeReset()`
43
+
44
+ Creates a resettable `DisposableStack`. Each call disposes the previous stack and returns a new one.
45
+
46
+ ```typescript
47
+ import {makeReset} from 'jrx'
48
+
49
+ const reset = makeReset()
50
+ const stack = reset() // Get a fresh DisposableStack
51
+
52
+ // Add disposables
53
+ stack.use(someDisposable)
54
+
55
+ // Reset - disposes previous stack, returns new one
56
+ const newStack = reset()
57
+ ```
58
+
59
+ ### `makeAsyncReset()`
60
+
61
+ Async version of `makeReset` using `AsyncDisposableStack`.
62
+
63
+ ```typescript
64
+ import {makeAsyncReset} from 'jrx'
65
+
66
+ const reset = makeAsyncReset()
67
+ const stack = await reset() // Get a fresh AsyncDisposableStack
68
+ ```
69
+
36
70
  ### `makeRenderLoop()`
37
71
 
38
72
  Creates a render loop with automatic cleanup management.
39
73
 
40
74
  ```typescript
41
- import { makeRenderLoop } from 'jrx'
75
+ import {makeRenderLoop} from 'jrx'
42
76
 
43
- const { loop, setLoop } = makeRenderLoop()
77
+ const {loop, setLoop} = makeRenderLoop()
44
78
 
45
79
  // Set the loop function
46
80
  const dispose = setLoop((time) => {
@@ -59,28 +93,6 @@ requestAnimationFrame(loop)
59
93
  dispose()
60
94
  ```
61
95
 
62
- ### `addEvtListener(target, event, handler, option?)`
63
-
64
- Adds an event listener to a target and returns a disposer that removes it. Works with any object that implements `addEventListener`/`removeEventListener` (DOM elements, `window`, `document`, etc.).
65
-
66
- ```typescript
67
- import { addEvtListener } from 'jrx'
68
-
69
- // Basic usage
70
- const dispose = addEvtListener(window, 'resize', (e) => {
71
- console.log('Window resized', e)
72
- })
73
-
74
- // With options
75
- const dispose2 = addEvtListener(element, 'click', (e) => {
76
- console.log('Clicked', e)
77
- }, { capture: true })
78
-
79
- // Cleanup
80
- dispose()
81
- dispose2()
82
- ```
83
-
84
96
  ### `addInterval(cb, ms)`
85
97
 
86
98
  Creates a repeating interval with cleanup. The callback can optionally return a cleanup function that runs before the next invocation.
@@ -112,13 +124,9 @@ Async version of `addInterval`. Waits for the callback to complete before schedu
112
124
  ```typescript
113
125
  import { addIntervalAsync } from 'jrx'
114
126
 
115
- const dispose = addIntervalAsync(async (disposer) => {
127
+ const dispose = addIntervalAsync(async () => {
116
128
  // Called immediately, then 5000ms after each completion
117
129
  await fetchData()
118
-
119
- // Check if disposed during async operation
120
- if (disposer.signal.aborted) return
121
-
122
130
  processData()
123
131
  }, 5000)
124
132
 
@@ -165,35 +173,6 @@ const dispose = addRequestAnimationFrameLoop((now) => {
165
173
  dispose()
166
174
  ```
167
175
 
168
- ### `addSubs(subs, cb, options?)`
169
-
170
- Manages multiple subscriptions with a single callback.
171
-
172
- ```typescript
173
- import { addSubs } from 'jrx'
174
-
175
- const sub1 = (listener) => {
176
- eventEmitter.on('event1', listener)
177
- return () => eventEmitter.off('event1', listener)
178
- }
179
-
180
- const sub2 = (listener) => {
181
- eventEmitter.on('event2', listener)
182
- return () => eventEmitter.off('event2', listener)
183
- }
184
-
185
- const dispose = addSubs([sub1, sub2], () => {
186
- console.log('Any event fired')
187
-
188
- // Optional: return cleanup function
189
- return () => {
190
- console.log('Cleanup')
191
- }
192
- }, { now: true }) // Call immediately with now: true
193
-
194
- dispose()
195
- ```
196
-
197
176
  ### `addTimeout(cb, ms)`
198
177
 
199
178
  Creates a timeout with cleanup.
@@ -254,9 +233,9 @@ a = 10
254
233
  console.log(value2.value) // Recomputed: 12
255
234
  ```
256
235
 
257
- ### `retry(cb, options?)`
236
+ ### `retry(cb, backoffSec?)`
258
237
 
259
- Retries an async operation with exponential backoff on failure.
238
+ Retries an operation with exponential backoff on failure. Returns `Disposable & Promise<T>`.
260
239
 
261
240
  **Default backoff:** `[5, 5, 10, 10, 20, 20, 40, 40, 60, -1]` seconds (where `-1` means retry forever with 60s delay)
262
241
 
@@ -264,92 +243,61 @@ Retries an async operation with exponential backoff on failure.
264
243
  import {retry} from 'jrx'
265
244
 
266
245
  // Basic usage - retries with default backoff
267
- const result = await retry(async (disposer, { resetBackoff }) => {
268
- const response = await fetch('/api/data')
269
- if (!response.ok) throw new Error('Failed to fetch')
270
- return response.json()
246
+ const result = await retry(({resetBackoff}) => {
247
+ const promise = fetch('/api/data').then((r) => r.json())
248
+ return Object.assign(promise, {[Symbol.dispose]() {}})
271
249
  })
272
250
 
273
251
  // Custom backoff schedule (in seconds)
274
252
  await retry(
275
- async (disposer, { resetBackoff }) => {
276
- return await fetchData()
253
+ () => {
254
+ const promise = fetchData()
255
+ return Object.assign(promise, {[Symbol.dispose]() {}})
277
256
  },
278
- {
279
- backoffSec: [1, 2, 5, 10, -1] // -1 means retry forever with last delay
280
- }
257
+ [1, 2, 5, 10, -1], // -1 means retry forever with last delay
281
258
  )
282
259
 
283
- // With disposer for cancellation
284
- import { makeDisposer } from 'jdisposer'
285
-
286
- const disposer = makeDisposer()
287
-
288
- const data = await retry(
289
- async (loopDisposer, { resetBackoff }) => {
290
- // Check if aborted
291
- if (loopDisposer.signal.aborted) return
292
-
293
- const result = await fetchData()
294
-
295
- // Reset backoff on successful partial progress
296
- if (result.isPartialSuccess) {
297
- resetBackoff()
298
- }
299
-
300
- return result
260
+ // Cancellation via Disposable
261
+ const r = retry(
262
+ ({resetBackoff}) => {
263
+ const promise = fetchData()
264
+ return Object.assign(promise, {[Symbol.dispose]() { /* cancel */ }})
301
265
  },
302
- {
303
- disposer,
304
- backoffSec: [5, 10, 20, 40, -1]
305
- }
266
+ [5, 10, 20, 40, -1],
306
267
  )
307
268
 
308
269
  // Cancel the retry loop
309
- disposer.dispose()
270
+ r[Symbol.dispose]()
310
271
 
311
272
  // Returns undefined when disposed
312
- console.log(data) // T | undefined
273
+ const data = await r // undefined
313
274
  ```
314
275
 
315
- **Options:**
316
- - `backoffSec`: Array of retry delays in seconds. Use `-1` for infinite retries with the last delay.
317
- - Default: `[5, 5, 10, 10, 20, 20, 40, 40, 60, -1]`
318
- - `disposer`: Optional disposer for cancellation. When provided, the return type is `T | undefined`. Otherwise, the return type is `T`.
319
-
320
- **Callback parameters:**
321
- - `disposer`: A disposer for the current retry attempt. Check `disposer.signal.aborted` to handle cancellation
322
- - `info.resetBackoff()`: Call this to reset the backoff counter to the beginning (useful when making partial progress)
276
+ **Parameters:**
277
+ - `cb`: Callback that returns `Disposable & (T | Promise<T>)`. Receives `{ resetBackoff() }` to reset the backoff counter.
278
+ - `backoffSec`: Array of retry delays in seconds. Use `-1` for infinite retries with the last delay. Default: `[5, 5, 10, 10, 20, 20, 40, 40, 60, -1]`
323
279
 
324
280
  ## Cleanup Pattern
325
281
 
326
- All functions return disposer functions that clean up resources:
282
+ All effect functions return a dispose function that stops the effect and runs any pending cleanup:
327
283
 
328
284
  ```typescript
329
285
  import {addInterval, addTimeout, addRequestAnimationFrame} from 'jrx'
330
- import {makeDisposer} from 'jdisposer'
331
286
 
332
- const disposer = makeDisposer()
287
+ // Each function returns a dispose function
288
+ const disposeInterval = addInterval(() => console.log('tick'), 1000)
289
+ const disposeTimeout = addTimeout(() => console.log('timeout'), 5000)
290
+ const disposeRaf = addRequestAnimationFrame((now) => render(now))
333
291
 
334
- // Collect disposers
335
- disposer.add(addInterval(() => console.log('tick'), 1000))
336
- disposer.add(addTimeout(() => console.log('timeout'), 5000))
337
- disposer.add(addRequestAnimationFrameLoop((now) => render(now)))
338
-
339
- // Cleanup all at once
340
- disposer.dispose()
292
+ // Call the dispose function to stop the effect
293
+ disposeInterval()
294
+ disposeTimeout()
295
+ disposeRaf()
341
296
  ```
342
297
 
343
298
  ## TypeScript
344
299
 
345
- This library is written in TypeScript and includes type definitions.
346
-
347
- ```typescript
348
- import type { Disposer } from 'jdisposer'
349
-
350
- // All disposer functions follow this pattern
351
- type DisposerFunction = () => void
352
- ```
300
+ This library is written in TypeScript and uses the [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) types (`Disposable`, `DisposableStack`, `AsyncDisposableStack`).
353
301
 
354
302
  ## License
355
303
 
package/index.d.ts CHANGED
@@ -1,18 +1,15 @@
1
- import { type Disposer } from 'jdisposer';
2
1
  import retry from './retry.js';
3
2
  import computed from './computed.js';
4
- import addEvtListener from './addEvtListener.js';
5
- export { retry, computed, addEvtListener };
3
+ export { retry, computed };
4
+ export declare function makeReset(): () => DisposableStack;
5
+ export declare function makeAsyncReset(): () => Promise<AsyncDisposableStack>;
6
6
  export declare function makeRenderLoop(): {
7
7
  loop(this: void, time: DOMHighResTimeStamp): void;
8
- setLoop(this: void, loop: (time: DOMHighResTimeStamp) => void | (() => void)): () => void;
8
+ setLoop(this: void, loop: (time: DOMHighResTimeStamp) => undefined | (() => void)): () => void;
9
9
  };
10
- export declare function addInterval(cb: () => void | (() => any), ms: number): () => void;
11
- export declare function addIntervalAsync(cb: (disposer: Disposer) => void | (() => any) | Promise<void> | Promise<() => any>, ms: number): () => void;
12
- export declare function addRequestAnimationFrame(cb: (now: DOMHighResTimeStamp) => void | (() => any)): () => void;
13
- export declare function addRequestAnimationFrameLoop(cb: (now: DOMHighResTimeStamp) => void | (() => any)): () => void;
14
- export declare function addSubs<Subs extends any[]>(subs: Subs, cb: () => void | (() => void), { now }?: {
15
- now?: boolean;
16
- }): (this: void) => void;
10
+ export declare function addInterval(cb: () => undefined | (() => any), ms: number): () => void;
11
+ export declare function addIntervalAsync(cb: () => (void | Disposable) & (void | (() => any) | Promise<void> | Promise<() => any>), ms: number): () => void;
12
+ export declare function addRequestAnimationFrame(cb: (now: DOMHighResTimeStamp) => undefined | (() => any)): () => void;
13
+ export declare function addRequestAnimationFrameLoop(cb: (now: DOMHighResTimeStamp) => undefined | (() => any)): () => void;
17
14
  export declare function addTimeout(cb: () => void, ms: number): () => void;
18
- export declare function addTransition(cb: (progress: number) => void | (() => void), durationMs: number): () => void;
15
+ export declare function addTransition(cb: (progress: number) => undefined | (() => void), durationMs: number): () => void;
package/index.js CHANGED
@@ -1,14 +1,26 @@
1
- import { makeDisposer, makeReset } from 'jdisposer';
2
1
  import retry from './retry.js';
3
2
  import computed from './computed.js';
4
- import addEvtListener from './addEvtListener.js';
5
- export { retry, computed, addEvtListener };
3
+ export { retry, computed };
4
+ export function makeReset() {
5
+ let stack = new DisposableStack();
6
+ return () => {
7
+ stack.dispose();
8
+ return (stack = new DisposableStack());
9
+ };
10
+ }
11
+ export function makeAsyncReset() {
12
+ let stack = new AsyncDisposableStack();
13
+ return async () => {
14
+ await stack.disposeAsync();
15
+ return (stack = new AsyncDisposableStack());
16
+ };
17
+ }
6
18
  export function makeRenderLoop() {
7
19
  let loop_;
8
20
  const reset = makeReset();
9
21
  return {
10
22
  loop(time) {
11
- reset().add(loop_?.(time));
23
+ reset().adopt(loop_?.(time), v => v?.());
12
24
  },
13
25
  setLoop(loop) {
14
26
  loop_ = loop;
@@ -28,7 +40,7 @@ export function addInterval(cb, ms) {
28
40
  clearTimeout(timeout);
29
41
  };
30
42
  function wrapper() {
31
- reset().add(cb());
43
+ reset().adopt(cb(), v => v?.());
32
44
  timeout = setTimeout(wrapper, ms);
33
45
  }
34
46
  }
@@ -41,17 +53,21 @@ export function addIntervalAsync(cb, ms) {
41
53
  clearTimeout(timeout);
42
54
  };
43
55
  async function wrapper() {
44
- const disposer = reset();
45
- await cb(disposer);
46
- if (!disposer.signal.aborted)
56
+ const stack = reset();
57
+ await stack.adopt(cb(), v => v?.[Symbol.dispose]?.());
58
+ if (!stack.disposed)
47
59
  timeout = setTimeout(wrapper, ms);
48
60
  }
49
61
  }
50
62
  export function addRequestAnimationFrame(cb) {
51
- const disposer = makeDisposer();
52
- const raf = requestAnimationFrame(now => disposer.add(cb(now)));
63
+ const stack = new DisposableStack();
64
+ const raf = requestAnimationFrame(now => {
65
+ if (stack.disposed)
66
+ return;
67
+ stack.adopt(cb(now), v => v?.());
68
+ });
53
69
  return () => {
54
- disposer.dispose();
70
+ stack.dispose();
55
71
  cancelAnimationFrame(raf);
56
72
  };
57
73
  }
@@ -63,20 +79,10 @@ export function addRequestAnimationFrameLoop(cb) {
63
79
  cancelAnimationFrame(raf);
64
80
  };
65
81
  function wrapper(now) {
66
- reset().add(cb(now));
82
+ reset().adopt(cb(now), v => v?.());
67
83
  raf = requestAnimationFrame(wrapper);
68
84
  }
69
85
  }
70
- export function addSubs(subs, cb, { now } = {}) {
71
- const disposer = makeDisposer();
72
- const reset = makeReset();
73
- disposer.add(reset);
74
- for (const sub of subs)
75
- disposer.add(sub(() => reset().add(cb())));
76
- if (now)
77
- reset().add(cb());
78
- return disposer.dispose;
79
- }
80
86
  export function addTimeout(cb, ms) {
81
87
  const timeout = setTimeout(cb, ms);
82
88
  return () => clearTimeout(timeout);
@@ -92,15 +98,15 @@ export function addTransition(cb, durationMs) {
92
98
  function wrapper(now) {
93
99
  if (start === undefined) {
94
100
  start = now;
95
- reset().add(cb(0));
101
+ reset().adopt(cb(0), v => v?.());
96
102
  raf = requestAnimationFrame(wrapper);
97
103
  }
98
104
  else {
99
105
  const progress = (now - start) / durationMs;
100
106
  if (progress >= 1)
101
- reset().add(cb(1));
107
+ reset().adopt(cb(1), v => v?.());
102
108
  else {
103
- reset().add(cb(progress));
109
+ reset().adopt(cb(progress), v => v?.());
104
110
  raf = requestAnimationFrame(wrapper);
105
111
  }
106
112
  }
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "jrx",
3
- "version": "0.2.0",
3
+ "version": "0.3.0-alpha.1",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "prepublishOnly": "npx tsc",
7
- "test": "node --test tests/*.test.ts",
8
- "test:coverage": "node --test --experimental-test-coverage tests/*.test.ts"
7
+ "test": "npm run prepublishOnly && node --test tests/*.test.ts",
8
+ "test:coverage": "npm run prepublishOnly && node --test --experimental-test-coverage tests/*.test.ts"
9
9
  },
10
10
  "exports": {
11
11
  ".": {
@@ -23,15 +23,10 @@
23
23
  "retry.js",
24
24
  "retry.d.ts",
25
25
  "computed.js",
26
- "computed.d.ts",
27
- "addEvtListener.js",
28
- "addEvtListener.d.ts"
26
+ "computed.d.ts"
29
27
  ],
30
28
  "devDependencies": {
31
29
  "@types/node": "^25.2.1",
32
- "typescript": "^5.9.3"
33
- },
34
- "dependencies": {
35
- "jdisposer": "^0.0.1"
30
+ "typescript": "^6.0.2"
36
31
  }
37
32
  }
package/retry.d.ts CHANGED
@@ -1,12 +1,3 @@
1
- import { type Disposer } from 'jdisposer';
2
- export default function retry<T>(cb: (disposer: Disposer, info: {
1
+ export default function retry<T>(cb: (info: {
3
2
  resetBackoff(): void;
4
- }) => T | Promise<T>, options?: {
5
- backoffSec?: number[];
6
- }): Promise<T>;
7
- export default function retry<T>(cb: (disposer: Disposer, info: {
8
- resetBackoff(): void;
9
- }) => T | Promise<T>, options?: {
10
- backoffSec?: number[];
11
- disposer: Disposer;
12
- }): Promise<T | undefined>;
3
+ }) => (Disposable | undefined) & (T | Promise<T>), backoffSec?: number[]): Disposable & Promise<T | undefined>;
package/retry.js CHANGED
@@ -1,32 +1,35 @@
1
- import { makeReset } from 'jdisposer';
2
- export default async function retry(cb, { backoffSec = [5, 5, 10, 10, 20, 20, 40, 40, 60, -1], // -1: retry forever with the last backoff . first element must not be -1
3
- disposer, } = {}) {
1
+ import { makeReset } from './index.js';
2
+ export default function retry(cb, backoffSec = [5, 5, 10, 10, 20, 20, 40, 40, 60, -1]) {
3
+ const stack = new DisposableStack();
4
4
  const reset = makeReset();
5
- disposer?.add(reset);
5
+ stack.defer(reset);
6
6
  let count = 0;
7
- let loopDisposer = reset();
8
- while (true) {
9
- if (backoffSec[count] !== -1)
10
- count++;
11
- try {
12
- if (loopDisposer?.signal.aborted)
13
- return; // only happen if disposer?.signal.aborted
14
- return await cb(loopDisposer, {
15
- resetBackoff() {
16
- count = 1;
17
- },
18
- });
19
- }
20
- catch (e) {
21
- if (disposer?.signal.aborted)
22
- return;
23
- if (count > backoffSec.length) {
24
- console.error('max retries reached:', e);
25
- throw e;
7
+ let loopStack = reset();
8
+ return Object.assign((async () => {
9
+ while (true) {
10
+ if (backoffSec[count] !== -1)
11
+ count++;
12
+ try {
13
+ if (loopStack.disposed)
14
+ return;
15
+ const value = cb({
16
+ resetBackoff() {
17
+ count = 1;
18
+ },
19
+ });
20
+ return value?.[Symbol.dispose] ? loopStack.use(value) : value;
21
+ }
22
+ catch (e) {
23
+ if (stack.disposed)
24
+ return;
25
+ if (count > backoffSec.length) {
26
+ console.error('max retries reached:', e);
27
+ throw e;
28
+ }
29
+ console.warn('Retrying due to error:', e);
30
+ loopStack = reset();
31
+ await new Promise(resolve => setTimeout(resolve, backoffSec[count - 1] * 1000));
26
32
  }
27
- console.warn('Retrying due to error:', e);
28
- loopDisposer = reset();
29
- await new Promise(resolve => setTimeout(resolve, backoffSec[count - 1] * 1000));
30
33
  }
31
- }
34
+ })(), { [Symbol.dispose]: stack[Symbol.dispose].bind(stack) });
32
35
  }
@@ -1,15 +0,0 @@
1
- type IEventHandler<Target extends {
2
- addEventListener(event: string, handler: any, option?: any): any;
3
- }, EventName> = Target['addEventListener'] extends (event: EventName, handler: infer Handler, ...args: any[]) => any ? Handler extends (...params: any[]) => any ? Handler : never : never;
4
- type IEventOption<Target extends {
5
- addEventListener(event: string, handler: any, option?: any): any;
6
- }, EventName, Handler> = Target['addEventListener'] extends (event: EventName, handler: Handler, option: infer Option) => any ? Option : never;
7
- export default function addEvtListener<Target extends {
8
- addEventListener(event: string, handler: any, option?: any): any;
9
- removeEventListener(event: string, handler: any, option?: any): any;
10
- }, EventName extends Parameters<Target['addEventListener']>[0], Handler extends IEventHandler<Target, EventName>>(target: Target, event: EventName, handler: Handler, option?: IEventOption<Target, EventName, Handler>): () => void;
11
- export default function addEvtListener<Target extends {
12
- addEventListener(event: string, handler: any, option?: any): any;
13
- removeEventListener(event: string, handler: any, option?: any): any;
14
- }, EventName extends Parameters<Target['addEventListener']>[0]>(target: Target, event: EventName, handler: (...args: any[]) => any, option?: IEventOption<Target, EventName, IEventHandler<Target, EventName>>): () => void;
15
- export {};
package/addEvtListener.js DELETED
@@ -1,6 +0,0 @@
1
- export default function addEvtListener(target, event, handler, option) {
2
- target.addEventListener(event, handler, option);
3
- return function removeEvtListener() {
4
- return target.removeEventListener(event, handler, option);
5
- };
6
- }