@ereo/state 0.1.28 → 0.1.30
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/dist/index.js +78 -13
- package/dist/react.d.ts.map +1 -1
- package/dist/signals.d.ts +10 -1
- package/dist/signals.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
class Signal {
|
|
4
4
|
_value;
|
|
5
5
|
_subscribers = new Set;
|
|
6
|
+
_boundFire;
|
|
7
|
+
_disposers = [];
|
|
6
8
|
constructor(initialValue) {
|
|
7
9
|
this._value = initialValue;
|
|
10
|
+
this._boundFire = this._fireSubscribers.bind(this);
|
|
8
11
|
}
|
|
9
12
|
get() {
|
|
10
13
|
return this._value;
|
|
@@ -23,11 +26,25 @@ class Signal {
|
|
|
23
26
|
return () => this._subscribers.delete(subscriber);
|
|
24
27
|
}
|
|
25
28
|
map(fn) {
|
|
26
|
-
const
|
|
27
|
-
this.subscribe((v) =>
|
|
28
|
-
|
|
29
|
+
const mapped = new Signal(fn(this._value));
|
|
30
|
+
const unsub = this.subscribe((v) => mapped.set(fn(v)));
|
|
31
|
+
mapped._disposers.push(unsub);
|
|
32
|
+
return mapped;
|
|
33
|
+
}
|
|
34
|
+
dispose() {
|
|
35
|
+
for (const disposer of this._disposers) {
|
|
36
|
+
disposer();
|
|
37
|
+
}
|
|
38
|
+
this._disposers = [];
|
|
39
|
+
this._subscribers.clear();
|
|
29
40
|
}
|
|
30
41
|
_notify() {
|
|
42
|
+
const deferred = _scheduleBatchNotification(this._boundFire);
|
|
43
|
+
if (!deferred) {
|
|
44
|
+
this._fireSubscribers();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
_fireSubscribers() {
|
|
31
48
|
for (const subscriber of this._subscribers) {
|
|
32
49
|
try {
|
|
33
50
|
subscriber(this._value);
|
|
@@ -41,20 +58,52 @@ function signal(initialValue) {
|
|
|
41
58
|
return new Signal(initialValue);
|
|
42
59
|
}
|
|
43
60
|
function computed(fn, deps) {
|
|
44
|
-
const
|
|
61
|
+
const c = new Signal(fn());
|
|
45
62
|
const update = () => {
|
|
46
|
-
|
|
63
|
+
c.set(fn());
|
|
47
64
|
};
|
|
48
|
-
|
|
49
|
-
|
|
65
|
+
const uniqueDeps = [...new Set(deps)];
|
|
66
|
+
for (const dep of uniqueDeps) {
|
|
67
|
+
const unsub = dep.subscribe(update);
|
|
68
|
+
c._disposers.push(unsub);
|
|
50
69
|
}
|
|
51
|
-
return
|
|
70
|
+
return c;
|
|
52
71
|
}
|
|
53
72
|
function atom(initialValue) {
|
|
54
73
|
return signal(initialValue);
|
|
55
74
|
}
|
|
75
|
+
var batchDepth = 0;
|
|
76
|
+
var batchQueue = null;
|
|
77
|
+
function _scheduleBatchNotification(notifier) {
|
|
78
|
+
if (batchDepth > 0) {
|
|
79
|
+
if (!batchQueue)
|
|
80
|
+
batchQueue = new Set;
|
|
81
|
+
batchQueue.add(notifier);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
56
86
|
function batch(fn) {
|
|
57
|
-
|
|
87
|
+
batchDepth++;
|
|
88
|
+
try {
|
|
89
|
+
return fn();
|
|
90
|
+
} finally {
|
|
91
|
+
batchDepth--;
|
|
92
|
+
if (batchDepth === 0 && batchQueue) {
|
|
93
|
+
const queue = batchQueue;
|
|
94
|
+
batchQueue = null;
|
|
95
|
+
let firstError;
|
|
96
|
+
for (const notifier of queue) {
|
|
97
|
+
try {
|
|
98
|
+
notifier();
|
|
99
|
+
} catch (e) {
|
|
100
|
+
firstError ??= e;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (firstError)
|
|
104
|
+
throw firstError;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
58
107
|
}
|
|
59
108
|
|
|
60
109
|
class Store {
|
|
@@ -90,7 +139,7 @@ function createStore(initialState) {
|
|
|
90
139
|
return new Store(initialState);
|
|
91
140
|
}
|
|
92
141
|
// src/react.ts
|
|
93
|
-
import { useSyncExternalStore, useCallback } from "react";
|
|
142
|
+
import { useSyncExternalStore, useCallback, useRef } from "react";
|
|
94
143
|
function useSignal(signal2) {
|
|
95
144
|
return useSyncExternalStore(useCallback((callback) => signal2.subscribe(callback), [signal2]), () => signal2.get(), () => signal2.get());
|
|
96
145
|
}
|
|
@@ -99,13 +148,29 @@ function useStoreKey(store, key) {
|
|
|
99
148
|
return useSignal(signal2);
|
|
100
149
|
}
|
|
101
150
|
function useStore(store) {
|
|
151
|
+
const cachedSnapshot = useRef(null);
|
|
152
|
+
const versionRef = useRef(0);
|
|
102
153
|
return useSyncExternalStore(useCallback((callback) => {
|
|
103
154
|
const unsubscribers = [];
|
|
104
|
-
for (const [
|
|
105
|
-
unsubscribers.push(sig.subscribe(
|
|
155
|
+
for (const [, sig] of store.entries()) {
|
|
156
|
+
unsubscribers.push(sig.subscribe(() => {
|
|
157
|
+
versionRef.current++;
|
|
158
|
+
cachedSnapshot.current = null;
|
|
159
|
+
callback();
|
|
160
|
+
}));
|
|
106
161
|
}
|
|
107
162
|
return () => unsubscribers.forEach((unsub) => unsub());
|
|
108
|
-
}, [store]), () =>
|
|
163
|
+
}, [store]), () => {
|
|
164
|
+
if (cachedSnapshot.current === null) {
|
|
165
|
+
cachedSnapshot.current = store.getSnapshot();
|
|
166
|
+
}
|
|
167
|
+
return cachedSnapshot.current;
|
|
168
|
+
}, () => {
|
|
169
|
+
if (cachedSnapshot.current === null) {
|
|
170
|
+
cachedSnapshot.current = store.getSnapshot();
|
|
171
|
+
}
|
|
172
|
+
return cachedSnapshot.current;
|
|
173
|
+
});
|
|
109
174
|
}
|
|
110
175
|
export {
|
|
111
176
|
useStoreKey,
|
package/dist/react.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAMjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAC9E,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,GAAG,EAAE,CAAC,GACL,CAAC,CAAC,CAAC,CAAC,CAGN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE/C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAMjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,EAC9E,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,GAAG,EAAE,CAAC,GACL,CAAC,CAAC,CAAC,CAAC,CAGN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CA6B9E"}
|
package/dist/signals.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ type Subscriber<T> = (value: T) => void;
|
|
|
9
9
|
export declare class Signal<T> {
|
|
10
10
|
private _value;
|
|
11
11
|
private _subscribers;
|
|
12
|
+
/** Stable reference for batch deduplication */
|
|
13
|
+
private readonly _boundFire;
|
|
14
|
+
/** Cleanup functions for upstream subscriptions (from map/computed) */
|
|
15
|
+
_disposers: (() => void)[];
|
|
12
16
|
constructor(initialValue: T);
|
|
13
17
|
/** Get current value (subscribes in reactive context) */
|
|
14
18
|
get(): T;
|
|
@@ -20,7 +24,10 @@ export declare class Signal<T> {
|
|
|
20
24
|
subscribe(subscriber: Subscriber<T>): () => void;
|
|
21
25
|
/** Create computed signal from this signal */
|
|
22
26
|
map<U>(fn: (value: T) => U): Signal<U>;
|
|
27
|
+
/** Dispose this signal: unsubscribe from upstream sources and clear subscribers */
|
|
28
|
+
dispose(): void;
|
|
23
29
|
private _notify;
|
|
30
|
+
private _fireSubscribers;
|
|
24
31
|
}
|
|
25
32
|
/** Create a new signal */
|
|
26
33
|
export declare function signal<T>(initialValue: T): Signal<T>;
|
|
@@ -28,7 +35,9 @@ export declare function signal<T>(initialValue: T): Signal<T>;
|
|
|
28
35
|
export declare function computed<T>(fn: () => T, deps: Signal<unknown>[]): Signal<T>;
|
|
29
36
|
/** Atom (alias for signal) */
|
|
30
37
|
export declare function atom<T>(initialValue: T): Signal<T>;
|
|
31
|
-
/**
|
|
38
|
+
/** Schedule a notification (called from Signal._notify) */
|
|
39
|
+
export declare function _scheduleBatchNotification(notifier: () => void): boolean;
|
|
40
|
+
/** Batch multiple updates — notifications are deferred until the batch completes */
|
|
32
41
|
export declare function batch<T>(fn: () => T): T;
|
|
33
42
|
/** Store for global state */
|
|
34
43
|
export declare class Store<T extends Record<string, unknown>> {
|
package/dist/signals.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,0BAA0B;AAC1B,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAExC,iCAAiC;AACjC,qBAAa,MAAM,CAAC,CAAC;IACnB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,YAAY,CAAiC;
|
|
1
|
+
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../src/signals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,0BAA0B;AAC1B,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;AAExC,iCAAiC;AACjC,qBAAa,MAAM,CAAC,CAAC;IACnB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,YAAY,CAAiC;IACrD,+CAA+C;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,uEAAuE;IACvE,UAAU,EAAE,CAAC,MAAM,IAAI,CAAC,EAAE,CAAM;gBAEpB,YAAY,EAAE,CAAC;IAK3B,yDAAyD;IACzD,GAAG,IAAI,CAAC;IAIR,2CAA2C;IAC3C,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI;IAOnB,iCAAiC;IACjC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IAItC,2BAA2B;IAC3B,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAKhD,8CAA8C;IAC9C,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IAOtC,mFAAmF;IACnF,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,gBAAgB;CAUzB;AAED,0BAA0B;AAC1B,wBAAgB,MAAM,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAEpD;AAED,+BAA+B;AAC/B,wBAAgB,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAc3E;AAED,8BAA8B;AAC9B,wBAAgB,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAElD;AAOD,2DAA2D;AAC3D,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAOxE;AAED,oFAAoF;AACpF,wBAAgB,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAoBvC;AAED,6BAA6B;AAC7B,qBAAa,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAElD,OAAO,CAAC,MAAM,CAAuC;gBAEzC,YAAY,EAAE,CAAC;IAM3B,yBAAyB;IACzB,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAI5C,wBAAwB;IACxB,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI;IASjD,sCAAsC;IACtC,OAAO,IAAI,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAItD,yCAAyC;IACzC,WAAW,IAAI,CAAC;CAOjB;AAED,qBAAqB;AACrB,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAExF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ereo/state",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Ereo Team",
|
|
6
6
|
"homepage": "https://ereo.dev",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"typecheck": "tsc --noEmit"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ereo/core": "
|
|
36
|
+
"@ereo/core": "workspace:*"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": "^18.0.0"
|