@zerolith/state 0.0.0-stage → 1.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/LICENSE +201 -0
- package/README.md +31 -2
- package/dist/history.d.ts +38 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +68 -0
- package/dist/history.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/production/history.js +2 -0
- package/dist/production/history.js.map +1 -0
- package/dist/production/index.js +2 -0
- package/dist/production/index.js.map +1 -0
- package/dist/production/selector.js +2 -0
- package/dist/production/selector.js.map +1 -0
- package/dist/production/stored.js +2 -0
- package/dist/production/stored.js.map +1 -0
- package/dist/production/timing.js +2 -0
- package/dist/production/timing.js.map +1 -0
- package/dist/selector.d.ts +18 -0
- package/dist/selector.d.ts.map +1 -0
- package/dist/selector.js +48 -0
- package/dist/selector.js.map +1 -0
- package/dist/stored.d.ts +32 -0
- package/dist/stored.d.ts.map +1 -0
- package/dist/stored.js +130 -0
- package/dist/stored.js.map +1 -0
- package/dist/timing.d.ts +21 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +70 -0
- package/dist/timing.js.map +1 -0
- package/package.json +51 -5
- package/src/history.ts +105 -0
- package/src/index.ts +16 -0
- package/src/selector.ts +57 -0
- package/src/stored.ts +173 -0
- package/src/timing.ts +82 -0
package/src/timing.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signals that follow another in their own time: after a quiet spell, or
|
|
3
|
+
* at most so often.
|
|
4
|
+
*/
|
|
5
|
+
import { type ReadableSignal, effect, hasOwner, onDispose, signal, untracked } from "zerolith";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A signal that follows `source` once it has been quiet for `ms`
|
|
9
|
+
* milliseconds, starting at its current value, so a search runs for the
|
|
10
|
+
* text a reader stopped typing rather than for every keystroke. The
|
|
11
|
+
* pending change is dropped with the enclosing owner when there is one.
|
|
12
|
+
*/
|
|
13
|
+
export function debounced<T>(source: ReadableSignal<T>, ms: number): ReadableSignal<T>
|
|
14
|
+
{
|
|
15
|
+
const value = signal(untracked(() => source.get()));
|
|
16
|
+
let first = true;
|
|
17
|
+
effect(() =>
|
|
18
|
+
{
|
|
19
|
+
const next = source.get();
|
|
20
|
+
if (first)
|
|
21
|
+
{
|
|
22
|
+
first = false;
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const timer = setTimeout(() => value.set(next), ms);
|
|
26
|
+
return () => clearTimeout(timer);
|
|
27
|
+
});
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A signal that follows `source` at most once per `ms` milliseconds: the
|
|
33
|
+
* first change in a window shows at once, and the last one in it shows
|
|
34
|
+
* when the window ends, so a scroll position drives work at a steady rate.
|
|
35
|
+
* A change still pending is dropped when a newer one shows after the
|
|
36
|
+
* window, and with the enclosing owner when there is one.
|
|
37
|
+
*/
|
|
38
|
+
export function throttled<T>(source: ReadableSignal<T>, ms: number): ReadableSignal<T>
|
|
39
|
+
{
|
|
40
|
+
const value = signal(untracked(() => source.get()));
|
|
41
|
+
let last = Number.NEGATIVE_INFINITY;
|
|
42
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
43
|
+
let pending: T;
|
|
44
|
+
let first = true;
|
|
45
|
+
const clear = (): void =>
|
|
46
|
+
{
|
|
47
|
+
if (timer !== undefined)
|
|
48
|
+
{
|
|
49
|
+
clearTimeout(timer);
|
|
50
|
+
timer = undefined;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
effect(() =>
|
|
54
|
+
{
|
|
55
|
+
const next = source.get();
|
|
56
|
+
if (first)
|
|
57
|
+
{
|
|
58
|
+
first = false;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
if (now - last >= ms)
|
|
63
|
+
{
|
|
64
|
+
clear();
|
|
65
|
+
last = now;
|
|
66
|
+
value.set(next);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
pending = next;
|
|
70
|
+
timer ??= setTimeout(() =>
|
|
71
|
+
{
|
|
72
|
+
timer = undefined;
|
|
73
|
+
last = Date.now();
|
|
74
|
+
value.set(pending);
|
|
75
|
+
}, ms - (now - last));
|
|
76
|
+
});
|
|
77
|
+
if (hasOwner())
|
|
78
|
+
{
|
|
79
|
+
onDispose(clear);
|
|
80
|
+
}
|
|
81
|
+
return value;
|
|
82
|
+
}
|