jrx 0.0.1 → 0.1.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/README.md +46 -4
- package/computed.d.ts +3 -0
- package/computed.js +17 -0
- package/index.d.ts +1 -0
- package/index.js +8 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,6 +17,19 @@ npm install jrx
|
|
|
17
17
|
- Composable reactive utilities
|
|
18
18
|
- Browser and Node.js compatible
|
|
19
19
|
|
|
20
|
+
## API Overview
|
|
21
|
+
|
|
22
|
+
- [`makeRenderLoop()`](#makerenderloop) - Render loops with automatic cleanup
|
|
23
|
+
- [`addInterval(cb, ms)`](#addintervalcb-ms) - Repeating intervals with cleanup
|
|
24
|
+
- [`addIntervalAsync(cb, ms)`](#addintervalasynccb-ms) - Async intervals with cancellation
|
|
25
|
+
- [`addRequestAnimationFrame(cb)`](#addrequestanimationframecb) - Single animation frame with cleanup
|
|
26
|
+
- [`addRequestAnimationFrameLoop(cb)`](#addrequestanimationframeloopcb) - Animation frame loops
|
|
27
|
+
- [`addSubs(subs, cb, options?)`](#addsubssubs-cb-options) - Multiple subscription management
|
|
28
|
+
- [`addTimeout(cb, ms)`](#addtimeoutcb-ms) - Timeouts with cleanup
|
|
29
|
+
- [`addTransition(cb, durationMs)`](#addtransitioncb-durationms) - Progress-based animations
|
|
30
|
+
- [`computed(fn, getDeps?)`](#computedfn-getdeps) - Memoized computed values
|
|
31
|
+
- [`retry(cb, options?)`](#retrycb-options) - Async retry with exponential backoff
|
|
32
|
+
|
|
20
33
|
## API
|
|
21
34
|
|
|
22
35
|
### `makeRenderLoop()`
|
|
@@ -49,11 +62,13 @@ dispose()
|
|
|
49
62
|
|
|
50
63
|
Creates a repeating interval with cleanup. The callback can optionally return a cleanup function that runs before the next invocation.
|
|
51
64
|
|
|
65
|
+
**Note:** The callback fires **immediately** on first call, then waits `ms` milliseconds **after** the previous callback completes. This is not a fixed-rate timer.
|
|
66
|
+
|
|
52
67
|
```typescript
|
|
53
68
|
import { addInterval } from 'jrx'
|
|
54
69
|
|
|
55
70
|
const dispose = addInterval(() => {
|
|
56
|
-
console.log('Tick')
|
|
71
|
+
console.log('Tick') // Called immediately, then every 1000ms after completion
|
|
57
72
|
|
|
58
73
|
// Optional: return cleanup function
|
|
59
74
|
return () => {
|
|
@@ -69,10 +84,13 @@ dispose()
|
|
|
69
84
|
|
|
70
85
|
Async version of `addInterval`. Waits for the callback to complete before scheduling the next invocation.
|
|
71
86
|
|
|
87
|
+
**Note:** The callback fires **immediately** on first call, then waits `ms` milliseconds **after** the previous async callback completes.
|
|
88
|
+
|
|
72
89
|
```typescript
|
|
73
90
|
import { addIntervalAsync } from 'jrx'
|
|
74
91
|
|
|
75
92
|
const dispose = addIntervalAsync(async (disposer) => {
|
|
93
|
+
// Called immediately, then 5000ms after each completion
|
|
76
94
|
await fetchData()
|
|
77
95
|
|
|
78
96
|
// Check if disposed during async operation
|
|
@@ -86,7 +104,7 @@ dispose()
|
|
|
86
104
|
|
|
87
105
|
### `addRequestAnimationFrame(cb)`
|
|
88
106
|
|
|
89
|
-
|
|
107
|
+
Executes a callback on the next animation frame with cleanup.
|
|
90
108
|
|
|
91
109
|
```typescript
|
|
92
110
|
import { addRequestAnimationFrame } from 'jrx'
|
|
@@ -100,6 +118,27 @@ const dispose = addRequestAnimationFrame((now) => {
|
|
|
100
118
|
}
|
|
101
119
|
})
|
|
102
120
|
|
|
121
|
+
// Cancel if needed before the frame fires
|
|
122
|
+
dispose()
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `addRequestAnimationFrameLoop(cb)`
|
|
126
|
+
|
|
127
|
+
Creates a continuous `requestAnimationFrame` loop with cleanup.
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { addRequestAnimationFrameLoop } from 'jrx'
|
|
131
|
+
|
|
132
|
+
const dispose = addRequestAnimationFrameLoop((now) => {
|
|
133
|
+
updateAnimation(now)
|
|
134
|
+
|
|
135
|
+
// Optional: return cleanup function
|
|
136
|
+
return () => {
|
|
137
|
+
cleanupAnimation()
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// Stop the loop
|
|
103
142
|
dispose()
|
|
104
143
|
```
|
|
105
144
|
|
|
@@ -196,6 +235,8 @@ console.log(value2.value) // Recomputed: 12
|
|
|
196
235
|
|
|
197
236
|
Retries an async operation with exponential backoff on failure.
|
|
198
237
|
|
|
238
|
+
**Default backoff:** `[5, 5, 10, 10, 20, 20, 40, 40, 60, -1]` seconds (where `-1` means retry forever with 60s delay)
|
|
239
|
+
|
|
199
240
|
```typescript
|
|
200
241
|
import retry from 'jrx/retry'
|
|
201
242
|
|
|
@@ -249,7 +290,8 @@ console.log(data) // T | undefined
|
|
|
249
290
|
```
|
|
250
291
|
|
|
251
292
|
**Options:**
|
|
252
|
-
- `backoffSec`: Array of retry delays in seconds. Use `-1` for infinite retries with the last delay.
|
|
293
|
+
- `backoffSec`: Array of retry delays in seconds. Use `-1` for infinite retries with the last delay.
|
|
294
|
+
- Default: `[5, 5, 10, 10, 20, 20, 40, 40, 60, -1]`
|
|
253
295
|
- `disposer`: Optional disposer for cancellation. When provided, the return type is `T | undefined`. Otherwise, the return type is `T`.
|
|
254
296
|
|
|
255
297
|
**Callback parameters:**
|
|
@@ -269,7 +311,7 @@ const disposer = makeDisposer()
|
|
|
269
311
|
// Collect disposers
|
|
270
312
|
disposer.add(addInterval(() => console.log('tick'), 1000))
|
|
271
313
|
disposer.add(addTimeout(() => console.log('timeout'), 5000))
|
|
272
|
-
disposer.add(
|
|
314
|
+
disposer.add(addRequestAnimationFrameLoop((now) => render(now)))
|
|
273
315
|
|
|
274
316
|
// Cleanup all at once
|
|
275
317
|
disposer.dispose()
|
package/computed.d.ts
ADDED
package/computed.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default function computed(fn, getDeps) {
|
|
2
|
+
let cached;
|
|
3
|
+
let lastDeps;
|
|
4
|
+
let first = true;
|
|
5
|
+
return {
|
|
6
|
+
get value() {
|
|
7
|
+
if (!getDeps)
|
|
8
|
+
return fn();
|
|
9
|
+
const deps = getDeps();
|
|
10
|
+
if (!first && deps.length === lastDeps.length && deps.every((dep, idx) => Object.is(dep, lastDeps[idx])))
|
|
11
|
+
return cached;
|
|
12
|
+
first = false;
|
|
13
|
+
lastDeps = deps;
|
|
14
|
+
return (cached = fn());
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export declare function makeRenderLoop(): {
|
|
|
6
6
|
export declare function addInterval(cb: () => void | (() => any), ms: number): () => void;
|
|
7
7
|
export declare function addIntervalAsync(cb: (disposer: Disposer) => void | (() => any) | Promise<void> | Promise<() => any>, ms: number): () => void;
|
|
8
8
|
export declare function addRequestAnimationFrame(cb: (now: DOMHighResTimeStamp) => void | (() => any)): () => void;
|
|
9
|
+
export declare function addRequestAnimationFrameLoop(cb: (now: DOMHighResTimeStamp) => void | (() => any)): () => void;
|
|
9
10
|
export declare function addSubs<Subs extends any[]>(subs: Subs, cb: () => void | (() => void), { now }?: {
|
|
10
11
|
now?: boolean;
|
|
11
12
|
}): (this: void) => void;
|
package/index.js
CHANGED
|
@@ -44,6 +44,14 @@ export function addIntervalAsync(cb, ms) {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
export function addRequestAnimationFrame(cb) {
|
|
47
|
+
const disposer = makeDisposer();
|
|
48
|
+
const raf = requestAnimationFrame(now => disposer.add(cb(now)));
|
|
49
|
+
return () => {
|
|
50
|
+
disposer.dispose();
|
|
51
|
+
cancelAnimationFrame(raf);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function addRequestAnimationFrameLoop(cb) {
|
|
47
55
|
const reset = makeReset();
|
|
48
56
|
let raf = requestAnimationFrame(wrapper);
|
|
49
57
|
return () => {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jrx",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"prepublishOnly": "npx tsc index.ts retry.ts --target esnext --declaration --moduleResolution node",
|
|
6
|
+
"prepublishOnly": "npx tsc index.ts retry.ts computed.ts --target esnext --declaration --moduleResolution node",
|
|
7
7
|
"test": "node --test tests/*.test.ts",
|
|
8
8
|
"test:coverage": "node --test --experimental-test-coverage tests/*.test.ts"
|
|
9
9
|
},
|