flatsignals 0.2.0 → 0.2.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 +35 -37
- package/dist/react.d.ts +1 -1
- package/dist/react.js +9 -5
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,42 +14,42 @@
|
|
|
14
14
|
|
|
15
15
|
### 1-to-64 fanout
|
|
16
16
|
|
|
17
|
-
| Library | Operations/sec ⚡ | vs flatsignals
|
|
18
|
-
| -------------------- | ----------------- |
|
|
19
|
-
| **flatsignals** 🏆 | **449,848** | **baseline**
|
|
20
|
-
| alien-signals | 261,082 |
|
|
21
|
-
| @preact/signals | 230,899 |
|
|
22
|
-
| @reactively/core | 182,403 |
|
|
23
|
-
| @vue/reactivity | 152,709 |
|
|
24
|
-
| @maverick-js/signals | 137,712 |
|
|
25
|
-
| Angular Signals | 98,597 |
|
|
26
|
-
| @solidjs/signals | 78,849 |
|
|
17
|
+
| Library | Operations/sec ⚡ | vs flatsignals |
|
|
18
|
+
| -------------------- | ----------------- | -------------- |
|
|
19
|
+
| **flatsignals** 🏆 | **449,848** | **baseline** |
|
|
20
|
+
| alien-signals | 261,082 | 1.72x slower |
|
|
21
|
+
| @preact/signals | 230,899 | 1.95x slower |
|
|
22
|
+
| @reactively/core | 182,403 | 2.47x slower |
|
|
23
|
+
| @vue/reactivity | 152,709 | 2.95x slower |
|
|
24
|
+
| @maverick-js/signals | 137,712 | 3.27x slower |
|
|
25
|
+
| Angular Signals | 98,597 | 4.56x slower |
|
|
26
|
+
| @solidjs/signals | 78,849 | 5.71x slower |
|
|
27
27
|
|
|
28
28
|
### High-frequency updates
|
|
29
29
|
|
|
30
|
-
| Library | Operations/sec ⚡ | vs flatsignals
|
|
31
|
-
| -------------------- | ----------------- |
|
|
32
|
-
| **flatsignals** 🏆 | **976,139** | **baseline**
|
|
33
|
-
| alien-signals | 502,513 |
|
|
34
|
-
| @preact/signals | 492,543 |
|
|
35
|
-
| @reactively/core | 438,882 |
|
|
36
|
-
| @maverick-js/signals | 343,368 |
|
|
37
|
-
| Angular Signals | 241,189 |
|
|
38
|
-
| @vue/reactivity | 221,537 |
|
|
39
|
-
| @solidjs/signals | 202,492 |
|
|
30
|
+
| Library | Operations/sec ⚡ | vs flatsignals |
|
|
31
|
+
| -------------------- | ----------------- | -------------- |
|
|
32
|
+
| **flatsignals** 🏆 | **976,139** | **baseline** |
|
|
33
|
+
| alien-signals | 502,513 | 1.94x slower |
|
|
34
|
+
| @preact/signals | 492,543 | 1.98x slower |
|
|
35
|
+
| @reactively/core | 438,882 | 2.22x slower |
|
|
36
|
+
| @maverick-js/signals | 343,368 | 2.84x slower |
|
|
37
|
+
| Angular Signals | 241,189 | 4.05x slower |
|
|
38
|
+
| @vue/reactivity | 221,537 | 4.41x slower |
|
|
39
|
+
| @solidjs/signals | 202,492 | 4.82x slower |
|
|
40
40
|
|
|
41
41
|
### Diamond
|
|
42
42
|
|
|
43
|
-
| Library | Operations/sec ⚡ | vs flatsignals
|
|
44
|
-
| -------------------- | ----------------- |
|
|
45
|
-
| **flatsignals** 🏆 | **4,556,987** | **baseline**
|
|
46
|
-
| alien-signals | 3,028,320 |
|
|
47
|
-
| @preact/signals | 2,531,788 |
|
|
48
|
-
| @reactively/core | 1,688,053 |
|
|
49
|
-
| Angular Signals | 1,614,432 |
|
|
50
|
-
| @vue/reactivity | 1,563,865 |
|
|
51
|
-
| @maverick-js/signals | 1,407,975 |
|
|
52
|
-
| @solidjs/signals | 870,080 |
|
|
43
|
+
| Library | Operations/sec ⚡ | vs flatsignals |
|
|
44
|
+
| -------------------- | ----------------- | -------------- |
|
|
45
|
+
| **flatsignals** 🏆 | **4,556,987** | **baseline** |
|
|
46
|
+
| alien-signals | 3,028,320 | 1.50x slower |
|
|
47
|
+
| @preact/signals | 2,531,788 | 1.80x slower |
|
|
48
|
+
| @reactively/core | 1,688,053 | 2.70x slower |
|
|
49
|
+
| Angular Signals | 1,614,432 | 2.82x slower |
|
|
50
|
+
| @vue/reactivity | 1,563,865 | 2.91x slower |
|
|
51
|
+
| @maverick-js/signals | 1,407,975 | 3.24x slower |
|
|
52
|
+
| @solidjs/signals | 870,080 | 5.24x slower |
|
|
53
53
|
|
|
54
54
|
## Installation
|
|
55
55
|
|
|
@@ -77,19 +77,17 @@ const log = effect(() => console.log(double.val));
|
|
|
77
77
|
## With React
|
|
78
78
|
|
|
79
79
|
```tsx
|
|
80
|
-
import { useFlatSignal } from "flatsignals/react";
|
|
80
|
+
import { useFlatSignal, useFlatReader } from "flatsignals/react";
|
|
81
81
|
import { counter, double } from "./signals";
|
|
82
82
|
|
|
83
83
|
function MyCounter() {
|
|
84
|
-
const [
|
|
85
|
-
return (
|
|
86
|
-
<button onClick={() => setCounter(counter + 1)}>Count: {counter}</button>
|
|
87
|
-
);
|
|
84
|
+
const [val, setVal] = useFlatSignal(counter);
|
|
85
|
+
return <button onClick={() => setVal(val + 1)}>Count: {val}</button>;
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
function ReadDouble() {
|
|
91
|
-
const
|
|
92
|
-
return <div>{
|
|
89
|
+
const val = useFlatReader(double);
|
|
90
|
+
return <div>{val}</div>;
|
|
93
91
|
}
|
|
94
92
|
```
|
|
95
93
|
|
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as FlatRoot, r as FlatSignal, t as FlatCompute } from "./index-BUz21f61.js";
|
|
2
2
|
|
|
3
3
|
//#region src/react/index.d.ts
|
|
4
|
-
declare function useFlatReader<T>(signal: FlatSignal<T> | FlatCompute<T
|
|
4
|
+
declare function useFlatReader<T>(signal: FlatSignal<T> | FlatCompute<T>, isEqual?: (a: T, b: T) => boolean): T;
|
|
5
5
|
declare function useFlatWriter<T>(signal: FlatSignal<T>): (val: T | ((oldVal: T) => T)) => void;
|
|
6
6
|
declare function useFlatSignal<T>(signal: FlatSignal<T>): readonly [T, (val: T | ((oldVal: T) => T)) => void];
|
|
7
7
|
declare function useFlatEffect(fn: () => undefined | (() => void)): void;
|
package/dist/react.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { o as effect, s as scoped } from "./src-CJj34M6F.js";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useSyncExternalStore } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
3
3
|
|
|
4
4
|
//#region src/react/index.ts
|
|
5
|
-
function useFlatReader(signal) {
|
|
5
|
+
function useFlatReader(signal, isEqual = Object.is) {
|
|
6
|
+
const lastValueRef = useRef(signal.peek);
|
|
6
7
|
return useSyncExternalStore(useCallback((onStoreChange) => scoped(() => effect(() => {
|
|
7
|
-
signal.val;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const newValue = signal.val;
|
|
9
|
+
if (!isEqual(lastValueRef.current, newValue)) {
|
|
10
|
+
lastValueRef.current = newValue;
|
|
11
|
+
onStoreChange();
|
|
12
|
+
}
|
|
13
|
+
}), signal.root), [signal, isEqual]), () => signal.val, () => signal.peek);
|
|
10
14
|
}
|
|
11
15
|
function useFlatWriter(signal) {
|
|
12
16
|
return useCallback((val) => {
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["cleanup: undefined | (() => void)"],"sources":["../src/react/index.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"react.js","names":["cleanup: undefined | (() => void)"],"sources":["../src/react/index.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport {\n effect,\n type FlatCompute,\n type FlatRoot,\n type FlatSignal,\n scoped,\n} from \"../index.js\";\n\nexport function useFlatReader<T>(\n signal: FlatSignal<T> | FlatCompute<T>,\n isEqual: (a: T, b: T) => boolean = Object.is\n): T {\n const lastValueRef = useRef<T>(signal.peek);\n\n return useSyncExternalStore(\n useCallback(\n (onStoreChange) =>\n scoped(\n () =>\n effect(() => {\n const newValue = signal.val;\n if (!isEqual(lastValueRef.current, newValue)) {\n lastValueRef.current = newValue;\n onStoreChange();\n }\n }),\n signal.root\n ),\n [signal, isEqual]\n ),\n () => signal.val,\n () => signal.peek\n );\n}\n\nexport function useFlatWriter<T>(\n signal: FlatSignal<T>\n): (val: T | ((oldVal: T) => T)) => void {\n return useCallback(\n (val) => {\n if (typeof val === \"function\") {\n signal.val = (val as (oldVal: T) => T)(signal.peek);\n } else {\n signal.val = val;\n }\n },\n [signal]\n );\n}\n\nexport function useFlatSignal<T>(signal: FlatSignal<T>) {\n const reader = useFlatReader(signal);\n const writer = useFlatWriter(signal);\n return [reader, writer] as const;\n}\n\nexport function useFlatEffect(fn: () => undefined | (() => void)): void {\n useEffect(() => {\n let cleanup: undefined | (() => void);\n const stop = effect(() => {\n if (cleanup) cleanup();\n cleanup = fn();\n });\n\n return () => {\n if (cleanup) cleanup();\n stop();\n };\n }, [fn]);\n}\n\nexport function useFlatScope<T>(callback: () => T, scope?: FlatRoot): T {\n return useMemo(() => scoped(callback, scope), [callback, scope]);\n}\n"],"mappings":";;;;AAeA,SAAgB,cACd,QACA,UAAmC,OAAO,IACvC;CACH,MAAM,eAAe,OAAU,OAAO,KAAK;AAE3C,QAAO,qBACL,aACG,kBACC,aAEI,aAAa;EACX,MAAM,WAAW,OAAO;AACxB,MAAI,CAAC,QAAQ,aAAa,SAAS,SAAS,EAAE;AAC5C,gBAAa,UAAU;AACvB,kBAAe;;GAEjB,EACJ,OAAO,KACR,EACH,CAAC,QAAQ,QAAQ,CAClB,QACK,OAAO,WACP,OAAO,KACd;;AAGH,SAAgB,cACd,QACuC;AACvC,QAAO,aACJ,QAAQ;AACP,MAAI,OAAO,QAAQ,WACjB,QAAO,MAAO,IAAyB,OAAO,KAAK;MAEnD,QAAO,MAAM;IAGjB,CAAC,OAAO,CACT;;AAGH,SAAgB,cAAiB,QAAuB;AAGtD,QAAO,CAFQ,cAAc,OAAO,EACrB,cAAc,OAAO,CACb;;AAGzB,SAAgB,cAAc,IAA0C;AACtE,iBAAgB;EACd,IAAIA;EACJ,MAAM,OAAO,aAAa;AACxB,OAAI,QAAS,UAAS;AACtB,aAAU,IAAI;IACd;AAEF,eAAa;AACX,OAAI,QAAS,UAAS;AACtB,SAAM;;IAEP,CAAC,GAAG,CAAC;;AAGV,SAAgB,aAAgB,UAAmB,OAAqB;AACtE,QAAO,cAAc,OAAO,UAAU,MAAM,EAAE,CAAC,UAAU,MAAM,CAAC"}
|