@e280/strata 0.2.0-0 → 0.2.0-10
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 +95 -37
- package/package.json +4 -4
- package/s/signals/core/derived.ts +65 -0
- package/s/signals/{effect.ts → core/effect.ts} +1 -1
- package/s/signals/{lazy.ts → core/lazy.ts} +34 -3
- package/s/signals/{parts → core/parts}/readable.ts +1 -1
- package/s/signals/core/signal.ts +97 -0
- package/s/signals/index.ts +11 -8
- package/s/signals/porcelain.ts +30 -0
- package/s/signals/r/map.ts +63 -0
- package/s/signals/r/set.ts +43 -0
- package/s/signals/signals.test.ts +10 -264
- package/s/signals/tests/derived.test.ts +111 -0
- package/s/signals/tests/effect.test.ts +89 -0
- package/s/signals/tests/lazy.test.ts +64 -0
- package/s/signals/tests/signal.test.ts +115 -0
- package/s/signals/types.ts +23 -4
- package/s/tests.test.ts +2 -2
- package/s/tree/parts/branch.ts +4 -4
- package/s/tree/parts/trunk.ts +5 -5
- package/s/tree/tree.test.ts +1 -1
- package/x/signals/core/derived.d.ts +10 -0
- package/x/signals/core/derived.js +52 -0
- package/x/signals/core/derived.js.map +1 -0
- package/x/signals/{effect.js → core/effect.js} +1 -1
- package/x/signals/core/effect.js.map +1 -0
- package/x/signals/{lazy.d.ts → core/lazy.d.ts} +4 -1
- package/x/signals/{lazy.js → core/lazy.js} +25 -2
- package/x/signals/core/lazy.js.map +1 -0
- package/x/signals/core/parts/reactive.js.map +1 -0
- package/x/signals/{parts → core/parts}/readable.js +1 -1
- package/x/signals/core/parts/readable.js.map +1 -0
- package/x/signals/{signal.d.ts → core/signal.d.ts} +5 -2
- package/x/signals/core/signal.js +76 -0
- package/x/signals/core/signal.js.map +1 -0
- package/x/signals/index.d.ts +9 -7
- package/x/signals/index.js +9 -7
- package/x/signals/index.js.map +1 -1
- package/x/signals/porcelain.d.ts +8 -0
- package/x/signals/porcelain.js +15 -0
- package/x/signals/porcelain.js.map +1 -0
- package/x/signals/r/map.d.ts +14 -0
- package/x/signals/r/map.js +52 -0
- package/x/signals/r/map.js.map +1 -0
- package/x/signals/r/set.d.ts +10 -0
- package/x/signals/r/set.js +36 -0
- package/x/signals/r/set.js.map +1 -0
- package/x/signals/signals.test.d.ts +42 -19
- package/x/signals/signals.test.js +9 -217
- package/x/signals/signals.test.js.map +1 -1
- package/x/signals/tests/derived.test.d.ts +12 -0
- package/x/signals/tests/derived.test.js +91 -0
- package/x/signals/tests/derived.test.js.map +1 -0
- package/x/signals/tests/effect.test.d.ts +10 -0
- package/x/signals/tests/effect.test.js +72 -0
- package/x/signals/tests/effect.test.js.map +1 -0
- package/x/signals/tests/lazy.test.d.ts +10 -0
- package/x/signals/tests/lazy.test.js +51 -0
- package/x/signals/tests/lazy.test.js.map +1 -0
- package/x/signals/tests/signal.test.d.ts +18 -0
- package/x/signals/tests/signal.test.js +94 -0
- package/x/signals/tests/signal.test.js.map +1 -0
- package/x/signals/types.d.ts +19 -4
- package/x/tests.test.js +2 -2
- package/x/tests.test.js.map +1 -1
- package/x/tree/parts/branch.js +2 -2
- package/x/tree/parts/branch.js.map +1 -1
- package/x/tree/parts/trunk.js +2 -2
- package/x/tree/parts/trunk.js.map +1 -1
- package/x/tree/tree.test.js +1 -1
- package/x/tree/tree.test.js.map +1 -1
- package/s/signals/derive.ts +0 -37
- package/s/signals/fns.ts +0 -30
- package/s/signals/signal.ts +0 -50
- package/x/signals/derive.d.ts +0 -8
- package/x/signals/derive.js +0 -31
- package/x/signals/derive.js.map +0 -1
- package/x/signals/effect.js.map +0 -1
- package/x/signals/fns.d.ts +0 -11
- package/x/signals/fns.js +0 -15
- package/x/signals/fns.js.map +0 -1
- package/x/signals/lazy.js.map +0 -1
- package/x/signals/parts/reactive.js.map +0 -1
- package/x/signals/parts/readable.js.map +0 -1
- package/x/signals/signal.js +0 -42
- package/x/signals/signal.js.map +0 -1
- /package/s/signals/{parts → core/parts}/reactive.ts +0 -0
- /package/x/signals/{effect.d.ts → core/effect.d.ts} +0 -0
- /package/x/signals/{parts → core/parts}/reactive.d.ts +0 -0
- /package/x/signals/{parts → core/parts}/reactive.js +0 -0
- /package/x/signals/{parts → core/parts}/readable.d.ts +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|

|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
<br/><br/>
|
|
5
7
|
|
|
6
8
|
# ⛏️ strata
|
|
7
9
|
|
|
@@ -9,14 +11,16 @@
|
|
|
9
11
|
📦 `npm install @e280/strata`
|
|
10
12
|
🧙♂️ probably my tenth state management library, lol
|
|
11
13
|
💁 it's all about rerendering ui when data changes
|
|
12
|
-
🦝
|
|
14
|
+
🦝 powers reactivity in our view library [@e280/sly](https://github.com/e280/sly)
|
|
13
15
|
🧑💻 a project by https://e280.org/
|
|
14
16
|
|
|
15
17
|
🚦 **signals** — ephemeral view-level state
|
|
16
18
|
🌳 **tree** — persistent app-level state
|
|
17
19
|
🪄 **tracker** — reactivity integration hub
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
<br/><br/>
|
|
20
24
|
|
|
21
25
|
## 🚦 strata signals
|
|
22
26
|
> *ephemeral view-level state*
|
|
@@ -26,75 +30,125 @@ import {signal, effect} from "@e280/strata"
|
|
|
26
30
|
```
|
|
27
31
|
|
|
28
32
|
### 🚦 each signal holds a value
|
|
29
|
-
- **
|
|
33
|
+
- **make signal**
|
|
30
34
|
```ts
|
|
31
|
-
const count = signal(0)
|
|
35
|
+
const $count = signal(0)
|
|
32
36
|
```
|
|
33
|
-
|
|
37
|
+
> *maybe you like the `$` prefix convention for signals?*
|
|
38
|
+
- **read signal**
|
|
34
39
|
```ts
|
|
35
|
-
count
|
|
40
|
+
$count() // 0
|
|
36
41
|
```
|
|
37
|
-
- **
|
|
42
|
+
- **write signal**
|
|
38
43
|
```ts
|
|
39
|
-
count
|
|
44
|
+
$count(1)
|
|
40
45
|
```
|
|
41
|
-
- **
|
|
46
|
+
- **write signal *(and await all downstream effects)***
|
|
42
47
|
```ts
|
|
43
|
-
await count
|
|
48
|
+
await $count(2)
|
|
44
49
|
```
|
|
50
|
+
> *this is supposed to impress you*
|
|
45
51
|
|
|
46
52
|
### 🚦 pick your poison
|
|
53
|
+
- **signal hipster-fn syntax**
|
|
54
|
+
```ts
|
|
55
|
+
$count() // read
|
|
56
|
+
await $count(2) // write
|
|
57
|
+
```
|
|
47
58
|
- **signal get/set syntax**
|
|
48
59
|
```ts
|
|
49
|
-
count.get()
|
|
50
|
-
await count.set(2) //
|
|
60
|
+
$count.get() // read
|
|
61
|
+
await $count.set(2) // write
|
|
51
62
|
```
|
|
52
63
|
- **signal .value accessor syntax**
|
|
53
64
|
```ts
|
|
54
|
-
count.value
|
|
55
|
-
count.value = 2 //
|
|
65
|
+
$count.value // read
|
|
66
|
+
$count.value = 2 // write
|
|
56
67
|
```
|
|
57
|
-
value pattern is nice for
|
|
68
|
+
value pattern is super nice for these vibes
|
|
58
69
|
```ts
|
|
59
|
-
count.value++
|
|
60
|
-
count.value += 1
|
|
70
|
+
$count.value++
|
|
71
|
+
$count.value += 1
|
|
61
72
|
```
|
|
62
73
|
|
|
63
74
|
### 🚦 effects
|
|
64
75
|
- **effects run when the relevant signals change**
|
|
65
76
|
```ts
|
|
66
|
-
effect(() => console.log(count
|
|
77
|
+
effect(() => console.log($count()))
|
|
67
78
|
// 1
|
|
68
|
-
// the system detects 'count' is relevant
|
|
79
|
+
// the system detects '$count' is relevant
|
|
69
80
|
|
|
70
|
-
count.value++
|
|
81
|
+
$count.value++
|
|
71
82
|
// 2
|
|
72
|
-
// when count is changed, the effect fn is run
|
|
83
|
+
// when $count is changed, the effect fn is run
|
|
73
84
|
```
|
|
74
85
|
|
|
75
|
-
### 🚦 `signal.
|
|
76
|
-
- **signal.
|
|
77
|
-
is for combining signals
|
|
86
|
+
### 🚦 `signal.derived` and `signal.lazy` are computed signals
|
|
87
|
+
- **signal.derived**
|
|
88
|
+
is for combining signals, like a formula
|
|
78
89
|
```ts
|
|
79
|
-
const a = signal(1)
|
|
80
|
-
const b = signal(10)
|
|
81
|
-
const product = signal.
|
|
90
|
+
const $a = signal(1)
|
|
91
|
+
const $b = signal(10)
|
|
92
|
+
const $product = signal.derived(() => $a() * $b())
|
|
82
93
|
|
|
83
|
-
product
|
|
94
|
+
$product() // 10
|
|
84
95
|
|
|
85
96
|
// change a dependency,
|
|
86
97
|
// and the derived signal is automatically updated
|
|
87
|
-
await a
|
|
98
|
+
await $a(2)
|
|
88
99
|
|
|
89
|
-
product
|
|
100
|
+
$product() // 20
|
|
90
101
|
```
|
|
91
102
|
- **signal.lazy**
|
|
92
103
|
is for making special optimizations.
|
|
93
|
-
it's like
|
|
94
|
-
because it's so lazy it only computes the value on read, and only when necessary.
|
|
104
|
+
it's like derived, except it cannot trigger effects,
|
|
105
|
+
because it's so damned lazy, it only computes the value on read, and only when necessary.
|
|
95
106
|
> *i repeat: lazy signals cannot trigger effects!*
|
|
96
107
|
|
|
97
|
-
|
|
108
|
+
### 🚦 core primitive classes
|
|
109
|
+
- **the hipster-fn syntax has a slight performance cost**
|
|
110
|
+
- **you can instead use the core primitive classes**
|
|
111
|
+
```ts
|
|
112
|
+
const $count = new Signal(1)
|
|
113
|
+
```
|
|
114
|
+
core signals work mostly the same
|
|
115
|
+
```ts
|
|
116
|
+
// ✅ legal
|
|
117
|
+
$count.get()
|
|
118
|
+
$count.set(2)
|
|
119
|
+
```
|
|
120
|
+
except you cannot directly invoke them
|
|
121
|
+
```ts
|
|
122
|
+
// ⛔ illegal on core primitives
|
|
123
|
+
$count()
|
|
124
|
+
$count(2)
|
|
125
|
+
```
|
|
126
|
+
- **same thing for derived/lazy**
|
|
127
|
+
```ts
|
|
128
|
+
const $product = new Derived(() => $a() * $b())
|
|
129
|
+
```
|
|
130
|
+
```ts
|
|
131
|
+
const $product = new Lazy(() => $a() * $b())
|
|
132
|
+
```
|
|
133
|
+
- **conversions**
|
|
134
|
+
- all core primitives (signal/derived/lazy) have a convert-to-hipster-fn method
|
|
135
|
+
```ts
|
|
136
|
+
new Signal(1).fn() // SignalFn<number>, hipster-fn
|
|
137
|
+
```
|
|
138
|
+
- and all hipster fns (signal/derived/lazy) have a `.core` property to get the primitive
|
|
139
|
+
```ts
|
|
140
|
+
signal(0).core // Signal<number>, primitive instance
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### 🚦 types
|
|
144
|
+
- **`Signaly<V>`** — can be `Signal<V>` or `Derived<V>` or `Lazy<V>`
|
|
145
|
+
- these are types for the core primitive classes
|
|
146
|
+
- **`SignalyFn<V>`** — can be `SignalFn<V>` or `DerivedFn<V>` or `LazyFn<V>`
|
|
147
|
+
- these `*Fn` types are for the hipster-fn-syntax enabled variants
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
<br/><br/>
|
|
98
152
|
|
|
99
153
|
## 🌳 strata trees
|
|
100
154
|
> *persistent app-level state*
|
|
@@ -229,7 +283,9 @@ import {Trunk} from "@e280/strata"
|
|
|
229
283
|
- chronobranch can have its own branches — all their mutations advance history
|
|
230
284
|
- plz pinky-swear right now, that you won't create a chronobranch under a branch under another chronobranch 💀
|
|
231
285
|
|
|
232
|
-
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
<br/><br/>
|
|
233
289
|
|
|
234
290
|
## 🪄 strata tracker
|
|
235
291
|
> *reactivity integration hub*
|
|
@@ -304,9 +360,11 @@ note, the *items* that the tracker tracks can be any object, or symbol.. the tra
|
|
|
304
360
|
}
|
|
305
361
|
```
|
|
306
362
|
|
|
307
|
-
<br/>
|
|
308
363
|
|
|
309
|
-
|
|
364
|
+
|
|
365
|
+
<br/><br/>
|
|
366
|
+
|
|
367
|
+
## 🧑💻 strata is by e280
|
|
310
368
|
free and open source by https://e280.org/
|
|
311
369
|
join us if you're cool and good at dev
|
|
312
370
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e280/strata",
|
|
3
|
-
"version": "0.2.0-
|
|
3
|
+
"version": "0.2.0-10",
|
|
4
4
|
"description": "state management",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chase Moskal <chasemoskal@gmail.com>",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"_tscw": "tsc -w"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@e280/stz": "^0.2.
|
|
32
|
+
"@e280/stz": "^0.2.2"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@e280/science": "^0.1.
|
|
36
|
-
"@types/node": "^24.3.
|
|
35
|
+
"@e280/science": "^0.1.2",
|
|
36
|
+
"@types/node": "^24.3.1",
|
|
37
37
|
"npm-run-all": "^4.1.5",
|
|
38
38
|
"typescript": "^5.9.2"
|
|
39
39
|
},
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
|
|
2
|
+
import {collectorEffect} from "./effect.js"
|
|
3
|
+
import {Reactive} from "./parts/reactive.js"
|
|
4
|
+
import {tracker} from "../../tracker/tracker.js"
|
|
5
|
+
import {DerivedFn, SignalOptions} from "../types.js"
|
|
6
|
+
import {defaultCompare} from "../utils/default-compare.js"
|
|
7
|
+
|
|
8
|
+
export class Derived<V> extends Reactive<V> {
|
|
9
|
+
#dispose: () => void
|
|
10
|
+
|
|
11
|
+
constructor(formula: () => V, options?: Partial<SignalOptions>) {
|
|
12
|
+
const compare = options?.compare ?? defaultCompare
|
|
13
|
+
const {result, dispose} = collectorEffect(formula, async() => {
|
|
14
|
+
const value = formula()
|
|
15
|
+
const isChanged = !compare(this.sneak, value)
|
|
16
|
+
if (isChanged) {
|
|
17
|
+
this.sneak = value
|
|
18
|
+
await Promise.all([
|
|
19
|
+
tracker.notifyWrite(this),
|
|
20
|
+
this.on.pub(value),
|
|
21
|
+
])
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
super(result)
|
|
25
|
+
this.#dispose = dispose
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
toString() {
|
|
29
|
+
return `(derived "${String(this.get())}")`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dispose() {
|
|
33
|
+
super.dispose()
|
|
34
|
+
this.#dispose()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get core() {
|
|
38
|
+
return this
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fn() {
|
|
42
|
+
const that = this as Derived<V>
|
|
43
|
+
|
|
44
|
+
function f(): V {
|
|
45
|
+
return that.get()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
f.core = that
|
|
49
|
+
f.get = that.get.bind(that)
|
|
50
|
+
f.on = that.on
|
|
51
|
+
f.dispose = that.dispose.bind(that)
|
|
52
|
+
f.fn = that.fn.bind(that)
|
|
53
|
+
|
|
54
|
+
Object.defineProperty(f, "value", {
|
|
55
|
+
get: () => that.value,
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
Object.defineProperty(f, "sneak", {
|
|
59
|
+
get: () => that.sneak,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return f as DerivedFn<V>
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
import {SignalOptions} from "./types.js"
|
|
3
2
|
import {collectorEffect} from "./effect.js"
|
|
4
3
|
import {Readable} from "./parts/readable.js"
|
|
5
|
-
import {tracker} from "
|
|
6
|
-
import {
|
|
4
|
+
import {tracker} from "../../tracker/tracker.js"
|
|
5
|
+
import {LazyFn, SignalOptions} from "../types.js"
|
|
6
|
+
import {defaultCompare} from "../utils/default-compare.js"
|
|
7
7
|
|
|
8
8
|
export class Lazy<V> extends Readable<V> {
|
|
9
9
|
#formula: () => V
|
|
@@ -17,6 +17,10 @@ export class Lazy<V> extends Readable<V> {
|
|
|
17
17
|
this.#compare = options?.compare ?? defaultCompare
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
toString() {
|
|
21
|
+
return `($lazy "${String(this.get())}")`
|
|
22
|
+
}
|
|
23
|
+
|
|
20
24
|
get() {
|
|
21
25
|
if (!this.#effect) {
|
|
22
26
|
const {result, dispose} = collectorEffect(
|
|
@@ -43,5 +47,32 @@ export class Lazy<V> extends Readable<V> {
|
|
|
43
47
|
if (this.#effect)
|
|
44
48
|
this.#effect()
|
|
45
49
|
}
|
|
50
|
+
|
|
51
|
+
get core() {
|
|
52
|
+
return this
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fn() {
|
|
56
|
+
const that = this as Lazy<V>
|
|
57
|
+
|
|
58
|
+
function f(): V {
|
|
59
|
+
return that.get()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
f.core = that
|
|
63
|
+
f.get = that.get.bind(that)
|
|
64
|
+
f.dispose = that.dispose.bind(that)
|
|
65
|
+
f.fn = that.fn.bind(that)
|
|
66
|
+
|
|
67
|
+
Object.defineProperty(f, "value", {
|
|
68
|
+
get: () => that.value,
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
Object.defineProperty(f, "sneak", {
|
|
72
|
+
get: () => that.sneak,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
return f as LazyFn<V>
|
|
76
|
+
}
|
|
46
77
|
}
|
|
47
78
|
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
|
|
2
|
+
import {Reactive} from "./parts/reactive.js"
|
|
3
|
+
import {tracker} from "../../tracker/tracker.js"
|
|
4
|
+
import {SignalFn, SignalOptions} from "../types.js"
|
|
5
|
+
import {defaultCompare} from "../utils/default-compare.js"
|
|
6
|
+
|
|
7
|
+
export class Signal<V> extends Reactive<V> {
|
|
8
|
+
#lock = false
|
|
9
|
+
#compare: (a: any, b: any) => boolean
|
|
10
|
+
|
|
11
|
+
constructor(value: V, options?: Partial<SignalOptions>) {
|
|
12
|
+
super(value)
|
|
13
|
+
this.#compare = options?.compare ?? defaultCompare
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
toString() {
|
|
17
|
+
return `($signal "${String(this.get())}")`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async set(v: V) {
|
|
21
|
+
const isChanged = !this.#compare(this.sneak, v)
|
|
22
|
+
if (isChanged) await this.publish(v)
|
|
23
|
+
return v
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get value() {
|
|
27
|
+
return this.get()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
set value(v: V) {
|
|
31
|
+
void this.set(v)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async publish(v = this.sneak) {
|
|
35
|
+
// only wizards are allowed beyond this point.
|
|
36
|
+
// - the implementation is subtle
|
|
37
|
+
// - it looks wrong, but it's right
|
|
38
|
+
// - tarnished alchemists, take heed: lock engages only for sync activity of the async fns (think of the value setter!)
|
|
39
|
+
|
|
40
|
+
if (this.#lock)
|
|
41
|
+
throw new Error("forbid circularity")
|
|
42
|
+
|
|
43
|
+
let promise: Promise<any> = Promise.resolve()
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
this.#lock = true
|
|
47
|
+
this.sneak = v
|
|
48
|
+
promise = Promise.all([
|
|
49
|
+
tracker.notifyWrite(this),
|
|
50
|
+
this.on.publish(v),
|
|
51
|
+
])
|
|
52
|
+
}
|
|
53
|
+
finally {
|
|
54
|
+
this.#lock = false
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
await promise
|
|
58
|
+
return v
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get core() {
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
fn() {
|
|
66
|
+
const that = this as Signal<V>
|
|
67
|
+
|
|
68
|
+
function f(): V
|
|
69
|
+
function f(v: V): Promise<V>
|
|
70
|
+
function f(_v?: V): V | Promise<V> {
|
|
71
|
+
return (arguments.length === 0)
|
|
72
|
+
? that.get()
|
|
73
|
+
: that.set(arguments[0])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
f.core = that
|
|
77
|
+
f.get = that.get.bind(that)
|
|
78
|
+
f.set = that.set.bind(that)
|
|
79
|
+
f.on = that.on
|
|
80
|
+
f.dispose = that.dispose.bind(that)
|
|
81
|
+
f.publish = that.publish.bind(that)
|
|
82
|
+
f.fn = that.fn.bind(that)
|
|
83
|
+
|
|
84
|
+
Object.defineProperty(f, "value", {
|
|
85
|
+
get: () => that.value,
|
|
86
|
+
set: (v) => that.value = v,
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
Object.defineProperty(f, "sneak", {
|
|
90
|
+
get: () => that.sneak,
|
|
91
|
+
set: (v) => that.sneak = v,
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
return f as SignalFn<V>
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
package/s/signals/index.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
|
|
2
|
-
export * from "./parts/reactive.js"
|
|
3
|
-
export * from "./parts/readable.js"
|
|
4
|
-
|
|
5
|
-
export * from "./
|
|
6
|
-
export * from "./
|
|
7
|
-
export * from "./
|
|
8
|
-
|
|
9
|
-
export * from "./
|
|
2
|
+
export * from "./core/parts/reactive.js"
|
|
3
|
+
export * from "./core/parts/readable.js"
|
|
4
|
+
export * from "./core/derived.js"
|
|
5
|
+
export * from "./core/effect.js"
|
|
6
|
+
export * from "./core/lazy.js"
|
|
7
|
+
export * from "./core/signal.js"
|
|
8
|
+
|
|
9
|
+
export * from "./r/map.js"
|
|
10
|
+
export * from "./r/set.js"
|
|
11
|
+
|
|
12
|
+
export * from "./porcelain.js"
|
|
10
13
|
export * from "./types.js"
|
|
11
14
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import {SignalOptions} from "./types.js"
|
|
3
|
+
import {Lazy} from "./core/lazy.js"
|
|
4
|
+
import {Signal} from "./core/signal.js"
|
|
5
|
+
import {Derived} from "./core/derived.js"
|
|
6
|
+
|
|
7
|
+
export function lazy<V>(
|
|
8
|
+
formula: () => V,
|
|
9
|
+
options?: Partial<SignalOptions>,
|
|
10
|
+
) {
|
|
11
|
+
return new Lazy<V>(formula, options).fn()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function derived<V>(
|
|
15
|
+
formula: () => V,
|
|
16
|
+
options?: Partial<SignalOptions>,
|
|
17
|
+
) {
|
|
18
|
+
return new Derived<V>(formula, options).fn()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function signal<V>(
|
|
22
|
+
value: V,
|
|
23
|
+
options?: Partial<SignalOptions>,
|
|
24
|
+
) {
|
|
25
|
+
return new Signal<V>(value, options).fn()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
signal.lazy = lazy
|
|
29
|
+
signal.derived = derived
|
|
30
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
|
|
2
|
+
import {MapG} from "@e280/stz"
|
|
3
|
+
import {tracker} from "../../tracker/tracker.js"
|
|
4
|
+
|
|
5
|
+
export class RMap<K, V> extends MapG<K, V> {
|
|
6
|
+
get size() {
|
|
7
|
+
tracker.notifyRead(this)
|
|
8
|
+
return super.size
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
;[Symbol.iterator]() {
|
|
12
|
+
tracker.notifyRead(this)
|
|
13
|
+
return super[Symbol.iterator]()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
keys() {
|
|
17
|
+
tracker.notifyRead(this)
|
|
18
|
+
return super.keys()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
values() {
|
|
22
|
+
tracker.notifyRead(this)
|
|
23
|
+
return super.values()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
entries() {
|
|
27
|
+
tracker.notifyRead(this)
|
|
28
|
+
return super.entries()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
forEach(callbackFn: (value: V, key: K, map: Map<K, V>) => void) {
|
|
32
|
+
tracker.notifyRead(this)
|
|
33
|
+
return super.forEach(callbackFn)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
has(key: K) {
|
|
37
|
+
tracker.notifyRead(this)
|
|
38
|
+
return super.has(key)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get(key: K) {
|
|
42
|
+
tracker.notifyRead(this)
|
|
43
|
+
return super.get(key)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
set(key: K, value: V) {
|
|
47
|
+
const r = super.set(key, value)
|
|
48
|
+
tracker.notifyWrite(this)
|
|
49
|
+
return r
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
delete(key: K) {
|
|
53
|
+
const r = super.delete(key)
|
|
54
|
+
tracker.notifyWrite(this)
|
|
55
|
+
return r
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
clear() {
|
|
59
|
+
super.clear()
|
|
60
|
+
tracker.notifyWrite(this)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
import {SetG} from "@e280/stz"
|
|
3
|
+
import {tracker} from "../../tracker/tracker.js"
|
|
4
|
+
|
|
5
|
+
export class RSet<T> extends SetG<T> {
|
|
6
|
+
get size() {
|
|
7
|
+
tracker.notifyRead(this)
|
|
8
|
+
return super.size
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
;[Symbol.iterator]() {
|
|
12
|
+
tracker.notifyRead(this)
|
|
13
|
+
return super[Symbol.iterator]()
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
values() {
|
|
17
|
+
tracker.notifyRead(this)
|
|
18
|
+
return super.values()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
has(item: T) {
|
|
22
|
+
tracker.notifyRead(this)
|
|
23
|
+
return super.has(item)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
add(item: T) {
|
|
27
|
+
super.add(item)
|
|
28
|
+
tracker.notifyWrite(this)
|
|
29
|
+
return this
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
delete(item: T) {
|
|
33
|
+
const r = super.delete(item)
|
|
34
|
+
tracker.notifyWrite(this)
|
|
35
|
+
return r
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
clear() {
|
|
39
|
+
super.clear()
|
|
40
|
+
tracker.notifyWrite(this)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|