@e280/strata 0.1.0 → 0.2.0-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.
Files changed (87) hide show
  1. package/README.md +28 -14
  2. package/package.json +3 -3
  3. package/s/signals/derive.ts +33 -0
  4. package/s/signals/effect.ts +10 -2
  5. package/s/signals/fns.ts +31 -0
  6. package/s/signals/index.ts +6 -2
  7. package/s/signals/lazy.ts +47 -0
  8. package/s/signals/parts/reactive.ts +12 -0
  9. package/s/signals/parts/readable.ts +16 -0
  10. package/s/signals/signal.ts +48 -37
  11. package/s/signals/signals.test.ts +11 -280
  12. package/s/signals/tests/derive.test.ts +89 -0
  13. package/s/signals/tests/effect.test.ts +89 -0
  14. package/s/signals/tests/lazy.test.ts +49 -0
  15. package/s/signals/tests/signal-fn.test.ts +28 -0
  16. package/s/signals/tests/signal.test.ts +63 -0
  17. package/s/signals/types.ts +11 -3
  18. package/s/signals/utils/default-compare.ts +5 -0
  19. package/s/signals/utils/hipster.ts +40 -0
  20. package/s/tests.test.ts +2 -2
  21. package/s/tree/parts/branch.ts +4 -4
  22. package/s/tree/parts/trunk.ts +7 -5
  23. package/x/signals/derive.d.ts +7 -0
  24. package/x/signals/derive.js +28 -0
  25. package/x/signals/derive.js.map +1 -0
  26. package/x/signals/effect.js.map +1 -1
  27. package/x/signals/fns.d.ts +12 -0
  28. package/x/signals/fns.js +16 -0
  29. package/x/signals/fns.js.map +1 -0
  30. package/x/signals/index.d.ts +5 -2
  31. package/x/signals/index.js +5 -2
  32. package/x/signals/index.js.map +1 -1
  33. package/x/signals/lazy.d.ts +8 -0
  34. package/x/signals/lazy.js +37 -0
  35. package/x/signals/lazy.js.map +1 -0
  36. package/x/signals/parts/reactive.d.ts +5 -0
  37. package/x/signals/parts/reactive.js +9 -0
  38. package/x/signals/parts/reactive.js.map +1 -0
  39. package/x/signals/parts/readable.d.ts +6 -0
  40. package/x/signals/parts/readable.js +15 -0
  41. package/x/signals/parts/readable.js.map +1 -0
  42. package/x/signals/signal.d.ts +7 -17
  43. package/x/signals/signal.js +43 -15
  44. package/x/signals/signal.js.map +1 -1
  45. package/x/signals/signals.test.d.ts +33 -20
  46. package/x/signals/signals.test.js +11 -227
  47. package/x/signals/signals.test.js.map +1 -1
  48. package/x/signals/tests/derive.test.d.ts +8 -0
  49. package/x/signals/tests/derive.test.js +73 -0
  50. package/x/signals/tests/derive.test.js.map +1 -0
  51. package/x/signals/tests/effect.test.d.ts +10 -0
  52. package/x/signals/tests/effect.test.js +72 -0
  53. package/x/signals/tests/effect.test.js.map +1 -0
  54. package/x/signals/tests/lazy.test.d.ts +7 -0
  55. package/x/signals/tests/lazy.test.js +39 -0
  56. package/x/signals/tests/lazy.test.js.map +1 -0
  57. package/x/signals/tests/signal-fn.test.d.ts +6 -0
  58. package/x/signals/tests/signal-fn.test.js +22 -0
  59. package/x/signals/tests/signal-fn.test.js.map +1 -0
  60. package/x/signals/tests/signal.test.d.ts +12 -0
  61. package/x/signals/tests/signal.test.js +54 -0
  62. package/x/signals/tests/signal.test.js.map +1 -0
  63. package/x/signals/types.d.ts +9 -3
  64. package/x/signals/utils/default-compare.d.ts +1 -0
  65. package/x/signals/utils/default-compare.js +4 -0
  66. package/x/signals/utils/default-compare.js.map +1 -0
  67. package/x/signals/utils/hipster.d.ts +3 -0
  68. package/x/signals/utils/hipster.js +28 -0
  69. package/x/signals/utils/hipster.js.map +1 -0
  70. package/x/tests.test.js +2 -2
  71. package/x/tests.test.js.map +1 -1
  72. package/x/tree/parts/branch.js +2 -2
  73. package/x/tree/parts/branch.js.map +1 -1
  74. package/x/tree/parts/trunk.js +4 -3
  75. package/x/tree/parts/trunk.js.map +1 -1
  76. package/s/signals/parts/derive.ts +0 -29
  77. package/s/signals/parts/lazy.ts +0 -27
  78. package/s/signals/parts/units.ts +0 -152
  79. package/x/signals/parts/derive.d.ts +0 -12
  80. package/x/signals/parts/derive.js +0 -12
  81. package/x/signals/parts/derive.js.map +0 -1
  82. package/x/signals/parts/lazy.d.ts +0 -10
  83. package/x/signals/parts/lazy.js +0 -12
  84. package/x/signals/parts/lazy.js.map +0 -1
  85. package/x/signals/parts/units.d.ts +0 -43
  86. package/x/signals/parts/units.js +0 -133
  87. package/x/signals/parts/units.js.map +0 -1
@@ -0,0 +1,89 @@
1
+
2
+ import {Science, test, expect, spy} from "@e280/science"
3
+ import {effect} from "../effect.js"
4
+ import {derive, signal} from "../fns.js"
5
+
6
+ export default Science.suite({
7
+ "effect reacts to derived changes": test(async() => {
8
+ const a = signal(1)
9
+ const b = signal(10)
10
+ const product = derive(() => a.value * b.value)
11
+
12
+ let mutations = 0
13
+ effect(() => {
14
+ void product.get()
15
+ mutations++
16
+ })
17
+ expect(product.value).is(10)
18
+ expect(mutations).is(1)
19
+
20
+ await a.set(2)
21
+ expect(product.value).is(20)
22
+ expect(mutations).is(2)
23
+
24
+ await a.set(3)
25
+ expect(product.value).is(30)
26
+ expect(mutations).is(3)
27
+ }),
28
+
29
+ "effect doesn't overreact to derived": test(async() => {
30
+ const a = signal(1)
31
+ const b = signal(10)
32
+ const product = signal.derive(() => a.value * b.value)
33
+
34
+ const derivedSpy = spy(() => {})
35
+ product.on(derivedSpy)
36
+
37
+ let mutations = 0
38
+ effect(() => {
39
+ a.get()
40
+ product.get()
41
+ mutations++
42
+ })
43
+ expect(product.value).is(10)
44
+ expect(mutations).is(1)
45
+ expect(derivedSpy.spy.calls.length).is(0)
46
+
47
+ await a.set(2)
48
+ expect(product.value).is(20)
49
+ expect(mutations).is(2)
50
+ expect(derivedSpy.spy.calls.length).is(1)
51
+ }),
52
+
53
+ "derived.on": test(async() => {
54
+ const a = signal(1)
55
+ const b = signal(10)
56
+ const product = signal.derive(() => a.value * b.value)
57
+ expect(product.value).is(10)
58
+
59
+ const mole = spy((_v: number) => {})
60
+ product.on(mole)
61
+ expect(mole.spy.calls.length).is(0)
62
+
63
+ await a.set(2)
64
+ expect(product.value).is(20)
65
+ expect(mole.spy.calls.length).is(1)
66
+ expect(mole.spy.calls[0].args[0]).is(20)
67
+ }),
68
+
69
+ "derived.on not called if result doesn't change": test(async() => {
70
+ const a = signal(1)
71
+ const b = signal(10)
72
+ const product = signal.derive(() => a.value * b.value)
73
+ expect(product.value).is(10)
74
+
75
+ const mole = spy((_v: number) => {})
76
+ product.on(mole)
77
+ expect(mole.spy.calls.length).is(0)
78
+
79
+ await a.set(2)
80
+ expect(product.value).is(20)
81
+ expect(mole.spy.calls.length).is(1)
82
+ expect(mole.spy.calls[0].args[0]).is(20)
83
+
84
+ await a.set(2)
85
+ expect(product.value).is(20)
86
+ expect(mole.spy.calls.length).is(1)
87
+ }),
88
+ })
89
+
@@ -0,0 +1,89 @@
1
+
2
+ import {Science, test, expect} from "@e280/science"
3
+ import {signal} from "../fns.js"
4
+ import {effect} from "../effect.js"
5
+
6
+ export default Science.suite({
7
+ "tracks signal changes": test(async() => {
8
+ const count = signal(1)
9
+ let doubled = 0
10
+
11
+ effect(() => doubled = count.value * 2)
12
+ expect(doubled).is(2)
13
+
14
+ await count.set(3)
15
+ expect(doubled).is(6)
16
+ }),
17
+
18
+ "is only called when signal actually changes": test(async() => {
19
+ const count = signal(1)
20
+ let runs = 0
21
+ effect(() => {
22
+ count.get()
23
+ runs++
24
+ })
25
+ expect(runs).is(1)
26
+ await count.set(999)
27
+ expect(runs).is(2)
28
+ await count.set(999)
29
+ expect(runs).is(2)
30
+ }),
31
+
32
+ "debounced": test(async() => {
33
+ const count = signal(1)
34
+ let runs = 0
35
+ effect(() => {
36
+ count.get()
37
+ runs++
38
+ })
39
+ expect(runs).is(1)
40
+ count.value++
41
+ count.value++
42
+ await count.set(count.get() + 1)
43
+ expect(runs).is(2)
44
+ }),
45
+
46
+ "can be disposed": test(async() => {
47
+ const count = signal(1)
48
+ let doubled = 0
49
+
50
+ const dispose = effect(() => doubled = count.value * 2)
51
+ expect(doubled).is(2)
52
+
53
+ await count.set(3)
54
+ expect(doubled).is(6)
55
+
56
+ dispose()
57
+ await count.set(4)
58
+ expect(doubled).is(6) // old value
59
+ }),
60
+
61
+ "signal set promise waits for effects": test(async() => {
62
+ const count = signal(1)
63
+ let doubled = 0
64
+
65
+ effect(() => doubled = count.value * 2)
66
+ expect(doubled).is(2)
67
+
68
+ await count.set(3)
69
+ expect(doubled).is(6)
70
+ }),
71
+
72
+ "only runs on change": test(async() => {
73
+ const sig = signal("a")
74
+ let runs = 0
75
+
76
+ effect(() => {
77
+ sig.value
78
+ runs++
79
+ })
80
+ expect(runs).is(1)
81
+
82
+ await sig.set("a")
83
+ expect(runs).is(1)
84
+
85
+ await sig.set("b")
86
+ expect(runs).is(2)
87
+ }),
88
+ })
89
+
@@ -0,0 +1,49 @@
1
+
2
+ import {Science, test, expect} from "@e280/science"
3
+ import {lazy, signal} from "../fns.js"
4
+
5
+ export default Science.suite({
6
+ "lazy values": test(async() => {
7
+ const a = signal(2)
8
+ const b = signal(3)
9
+ const sum = lazy(() => a.value + b.value)
10
+ expect(sum.value).is(5)
11
+
12
+ await a.set(5)
13
+ expect(sum.value).is(8)
14
+
15
+ await b.set(7)
16
+ expect(sum.value).is(12)
17
+ }),
18
+
19
+ "lazy is lazy": test(async() => {
20
+ const a = signal(1)
21
+ let runs = 0
22
+
23
+ const comp = lazy(() => {
24
+ runs++
25
+ return a.value * 10
26
+ })
27
+
28
+ expect(runs).is(0)
29
+ expect(comp.value).is(10)
30
+ expect(runs).is(1)
31
+
32
+ await a.set(2)
33
+ expect(runs).is(1)
34
+ expect(comp.value).is(20)
35
+ expect(runs).is(2)
36
+ }),
37
+
38
+ "lazy syntax": test(async() => {
39
+ const a = signal(2)
40
+ const b = signal(3)
41
+ const sum = lazy(() => a.value + b.value)
42
+ expect(sum.value).is(5)
43
+
44
+ await a.set(5)
45
+ expect(sum.value).is(8)
46
+ expect(sum.get()).is(8)
47
+ }),
48
+ })
49
+
@@ -0,0 +1,28 @@
1
+
2
+ import {Science, test, expect} from "@e280/science"
3
+ import {signal} from "../fns.js"
4
+
5
+ export default Science.suite({
6
+ "get/set": test(async() => {
7
+ const count = signal.fn(0)
8
+ expect(count()).is(0)
9
+
10
+ count.value++
11
+ expect(count()).is(1)
12
+ }),
13
+ ".on 'this' interrogation": test(async() => {
14
+ const count = signal.fn(0)
15
+ expect(count()).is(0)
16
+
17
+ let reported = count()
18
+ count.on(x => {reported = x})
19
+
20
+ count(1)
21
+ expect(reported).is(1)
22
+
23
+ count.on.clear()
24
+ count(2)
25
+ expect(reported).is(1)
26
+ }),
27
+ })
28
+
@@ -0,0 +1,63 @@
1
+
2
+ import {Science, test, expect} from "@e280/science"
3
+ import {signal} from "../fns.js"
4
+
5
+ export default Science.suite({
6
+ "get/set value": test(async() => {
7
+ const count = signal(0)
8
+ expect(count.value).is(0)
9
+
10
+ count.value++
11
+ expect(count.value).is(1)
12
+
13
+ count.value = 5
14
+ expect(count.value).is(5)
15
+ }),
16
+
17
+ "set and publish returns value": test(async() => {
18
+ const count = signal(0)
19
+ expect(count.value).is(0)
20
+ expect(await count.set(1)).is(1)
21
+ expect(await count.publish(2)).is(2)
22
+ }),
23
+
24
+ "syntax interop": test(async() => {
25
+ const count = signal(0)
26
+ count.value = 1
27
+ expect(count.get()).is(1)
28
+ }),
29
+
30
+ "on": Science.suite({
31
+ "on is not debounced": test(async() => {
32
+ const count = signal(1)
33
+ let runs = 0
34
+ count.on(() => void runs++)
35
+ await count.set(2)
36
+ await count.set(3)
37
+ expect(runs).is(2)
38
+ }),
39
+
40
+ "on only fires on change": test(async() => {
41
+ const count = signal(1)
42
+ let runs = 0
43
+ count.on(() => void runs++)
44
+ await count.set(2)
45
+ await count.set(2)
46
+ expect(runs).is(1)
47
+ }),
48
+
49
+ "on circularity forbidden": test(async() => {
50
+ const count = signal(1)
51
+ let runs = 0
52
+ count.on(async() => {
53
+ await count.set(99)
54
+ runs++
55
+ })
56
+ expect(async() => {
57
+ await count.set(2)
58
+ }).throwsAsync()
59
+ expect(runs).is(0)
60
+ }),
61
+ }),
62
+ })
63
+
@@ -1,11 +1,19 @@
1
1
 
2
+ import {Lazy} from "./lazy.js"
2
3
  import {Signal} from "./signal.js"
3
- import {LazySignal} from "./parts/lazy.js"
4
- import {DerivedSignal} from "./parts/derive.js"
4
+ import {Derive} from "./derive.js"
5
5
 
6
- export type Signaloid<V> = Signal<V> | DerivedSignal<V> | LazySignal<V>
6
+ export type Signaly<V> = Signal<V> | Derive<V> | Lazy<V>
7
7
 
8
8
  export type SignalOptions = {
9
9
  compare: (a: any, b: any) => boolean
10
10
  }
11
11
 
12
+ export type SignalFn<V> = {
13
+ (): V
14
+ (v: V): Promise<V>
15
+ (v?: V): V | Promise<V>
16
+
17
+ signal: Signal<V>
18
+ } & Signal<V>
19
+
@@ -0,0 +1,5 @@
1
+
2
+ export function defaultCompare(a: any, b: any) {
3
+ return a === b
4
+ }
5
+
@@ -0,0 +1,40 @@
1
+
2
+ import {Signal} from "../signal.js"
3
+ import {SignalFn} from "../types.js"
4
+
5
+ export function hipster<V>(sig: Signal<V>) {
6
+ function f(): V
7
+ function f(v: V): Promise<V>
8
+ function f(_v?: V): V | Promise<V> {
9
+ return (arguments.length === 0)
10
+ ? sig.get()
11
+ : sig.set(arguments[0])
12
+ }
13
+
14
+ f.signal = sig
15
+
16
+ f.get = sig.get.bind(sig)
17
+ f.set = sig.set.bind(sig)
18
+ f.on = sig.on
19
+ f.dispose = sig.dispose.bind(sig)
20
+ f.publish = sig.publish.bind(sig)
21
+ f.fn = sig.fn.bind(sig)
22
+
23
+ Object.setPrototypeOf(f, {
24
+ set: sig.set.bind(sig),
25
+ publish: sig.publish.bind(sig),
26
+ })
27
+
28
+ Object.defineProperty(f, "value", {
29
+ get: () => sig.value,
30
+ set: (v) => sig.value = v,
31
+ })
32
+
33
+ Object.defineProperty(f, "sneak", {
34
+ get: () => sig.sneak,
35
+ set: (v) => sig.sneak = v,
36
+ })
37
+
38
+ return f as SignalFn<V>
39
+ }
40
+
package/s/tests.test.ts CHANGED
@@ -5,9 +5,9 @@ import tree from "./tree/tree.test.js"
5
5
  import signals from "./signals/signals.test.js"
6
6
  import tracker from "./tracker/tracker.test.js"
7
7
 
8
- import {Trunk} from "./tree/parts/trunk.js"
8
+ import {signal} from "./signals/fns.js"
9
9
  import {effect} from "./signals/effect.js"
10
- import {signal} from "./signals/signal.js"
10
+ import {Trunk} from "./tree/parts/trunk.js"
11
11
 
12
12
  await Science.run({
13
13
  tree,
@@ -1,11 +1,11 @@
1
1
 
2
2
  import {deep} from "@e280/stz"
3
- import {signal} from "../../signals/signal.js"
4
- import {DerivedSignal} from "../../signals/parts/derive.js"
3
+ import {derive} from "../../signals/fns.js"
4
+ import {Derive} from "../../signals/derive.js"
5
5
  import {Branchstate, Immutable, Mutator, Options, Selector, Tree} from "./types.js"
6
6
 
7
7
  export class Branch<S extends Branchstate, ParentState extends Branchstate = any> implements Tree<S> {
8
- #immutable: DerivedSignal<Immutable<S>>
8
+ #immutable: Derive<Immutable<S>>
9
9
 
10
10
  constructor(
11
11
  private parent: Tree<ParentState>,
@@ -13,7 +13,7 @@ export class Branch<S extends Branchstate, ParentState extends Branchstate = any
13
13
  private options: Options,
14
14
  ) {
15
15
 
16
- this.#immutable = signal.derive(() => {
16
+ this.#immutable = derive(() => {
17
17
  const state = selector(parent.state as any)
18
18
  return deep.freeze(options.clone(state)) as Immutable<S>
19
19
  }, {compare: deep.equal})
@@ -1,11 +1,12 @@
1
1
 
2
2
  import {deep} from "@e280/stz"
3
3
  import {Branch} from "./branch.js"
4
+ import {signal} from "../../signals/fns.js"
4
5
  import {trunkSetup} from "./utils/setup.js"
6
+ import {Derive} from "../../signals/derive.js"
7
+ import {Signal} from "../../signals/signal.js"
5
8
  import {Chronobranch} from "./chronobranch.js"
6
9
  import {processOptions} from "./utils/process-options.js"
7
- import {DerivedSignal} from "../../signals/parts/derive.js"
8
- import {signal, Signal} from "../../signals/signal.js"
9
10
  import {Branchstate, Chronicle, Immutable, Mutator, Options, Selector, Tree, Trunkstate} from "./types.js"
10
11
 
11
12
  export class Trunk<S extends Trunkstate> implements Tree<S> {
@@ -18,7 +19,7 @@ export class Trunk<S extends Trunkstate> implements Tree<S> {
18
19
 
19
20
  options: Options
20
21
 
21
- #immutable: DerivedSignal<Immutable<S>>
22
+ #immutable: Derive<Immutable<S>>
22
23
  #mutable: Signal<S>
23
24
  #mutationLock = 0
24
25
 
@@ -44,8 +45,9 @@ export class Trunk<S extends Trunkstate> implements Tree<S> {
44
45
  throw new Error("nested mutations are forbidden")
45
46
  try {
46
47
  this.#mutationLock++
47
- mutator(this.#mutable())
48
- const newState = this.#mutable.get()
48
+ const value = this.#mutable.get()
49
+ mutator(value)
50
+ const newState = value
49
51
  const isChanged = !deep.equal(newState, oldState)
50
52
  if (isChanged)
51
53
  await this.overwrite(newState)
@@ -0,0 +1,7 @@
1
+ import { SignalOptions } from "./types.js";
2
+ import { Reactive } from "./parts/reactive.js";
3
+ export declare class Derive<V> extends Reactive<V> {
4
+ #private;
5
+ constructor(formula: () => V, options?: Partial<SignalOptions>);
6
+ dispose(): void;
7
+ }
@@ -0,0 +1,28 @@
1
+ import { collectorEffect } from "./effect.js";
2
+ import { Reactive } from "./parts/reactive.js";
3
+ import { tracker } from "../tracker/tracker.js";
4
+ import { defaultCompare } from "./utils/default-compare.js";
5
+ export class Derive extends Reactive {
6
+ #dispose;
7
+ constructor(formula, options) {
8
+ const compare = options?.compare ?? defaultCompare;
9
+ const { result, dispose } = collectorEffect(formula, async () => {
10
+ const value = formula();
11
+ const isChanged = !compare(this.sneak, value);
12
+ if (isChanged) {
13
+ this.sneak = value;
14
+ await Promise.all([
15
+ tracker.notifyWrite(this),
16
+ this.on.pub(value),
17
+ ]);
18
+ }
19
+ });
20
+ super(result);
21
+ this.#dispose = dispose;
22
+ }
23
+ dispose() {
24
+ super.dispose();
25
+ this.#dispose();
26
+ }
27
+ }
28
+ //# sourceMappingURL=derive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive.js","sourceRoot":"","sources":["../../s/signals/derive.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAA;AAEzD,MAAM,OAAO,MAAU,SAAQ,QAAW;IACzC,QAAQ,CAAY;IAEpB,YAAY,OAAgB,EAAE,OAAgC;QAC7D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,CAAA;QAClD,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,eAAe,CAAC,OAAO,EAAE,KAAK,IAAG,EAAE;YAC5D,MAAM,KAAK,GAAG,OAAO,EAAE,CAAA;YACvB,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;YAC7C,IAAI,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;gBAClB,MAAM,OAAO,CAAC,GAAG,CAAC;oBACjB,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC;oBACzB,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;iBAClB,CAAC,CAAA;YACH,CAAC;QACF,CAAC,CAAC,CAAA;QACF,KAAK,CAAC,MAAM,CAAC,CAAA;QACb,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,OAAO;QACN,KAAK,CAAC,OAAO,EAAE,CAAA;QACf,IAAI,CAAC,QAAQ,EAAE,CAAA;IAChB,CAAC;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"effect.js","sourceRoot":"","sources":["../../s/signals/effect.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAClC,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAA;AAE7C,MAAM,UAAU,MAAM,CAAC,SAAqB,EAAE,YAAwB,SAAS;IAC9E,OAAO,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,OAAO,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAAW,SAAkB,EAAE,YAAwB,SAAS;IAC9F,MAAM,EAAC,IAAI,EAAE,MAAM,EAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjD,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;IAEjC,MAAM,SAAS,GAAmB,EAAE,CAAA;IACpC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IAEjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC1C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,EAAC,MAAM,EAAE,OAAO,EAAC,CAAA;AACzB,CAAC"}
1
+ {"version":3,"file":"effect.js","sourceRoot":"","sources":["../../s/signals/effect.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,QAAQ,EAAC,MAAM,WAAW,CAAA;AAClC,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAA;AAE7C,MAAM,UAAU,MAAM,CACpB,SAAqB,EACrB,YAAwB,SAAS;IAGlC,OAAO,eAAe,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,OAAO,CAAA;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,SAAkB,EAClB,YAAwB,SAAS;IAGlC,MAAM,EAAC,IAAI,EAAE,MAAM,EAAC,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACjD,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;IAEjC,MAAM,SAAS,GAAmB,EAAE,CAAA;IACpC,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;IAEjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC1C,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,EAAC,MAAM,EAAE,OAAO,EAAC,CAAA;AACzB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { Lazy } from "./lazy.js";
2
+ import { Signal } from "./signal.js";
3
+ import { Derive } from "./derive.js";
4
+ import { SignalOptions } from "./types.js";
5
+ export declare function lazy<V>(formula: () => V, options?: Partial<SignalOptions>): Lazy<V>;
6
+ export declare function derive<V>(formula: () => V, options?: Partial<SignalOptions>): Derive<V>;
7
+ export declare function signal<V>(value: V, options?: Partial<SignalOptions>): Signal<V>;
8
+ export declare namespace signal {
9
+ var lazy: typeof import("./fns.js").lazy;
10
+ var derive: typeof import("./fns.js").derive;
11
+ var fn: <V>(value: V) => import("./types.js").SignalFn<V>;
12
+ }
@@ -0,0 +1,16 @@
1
+ import { Lazy } from "./lazy.js";
2
+ import { Signal } from "./signal.js";
3
+ import { Derive } from "./derive.js";
4
+ export function lazy(formula, options) {
5
+ return new Lazy(formula, options);
6
+ }
7
+ export function derive(formula, options) {
8
+ return new Derive(formula, options);
9
+ }
10
+ export function signal(value, options) {
11
+ return new Signal(value, options);
12
+ }
13
+ signal.lazy = lazy;
14
+ signal.derive = derive;
15
+ signal.fn = (value) => signal(value).fn();
16
+ //# sourceMappingURL=fns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fns.js","sourceRoot":"","sources":["../../s/signals/fns.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAA;AAC9B,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAClC,OAAO,EAAC,MAAM,EAAC,MAAM,aAAa,CAAA;AAGlC,MAAM,UAAU,IAAI,CAClB,OAAgB,EAChB,OAAgC;IAEjC,OAAO,IAAI,IAAI,CAAI,OAAO,EAAE,OAAO,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,MAAM,CACpB,OAAgB,EAChB,OAAgC;IAEjC,OAAO,IAAI,MAAM,CAAI,OAAO,EAAE,OAAO,CAAC,CAAA;AACvC,CAAC;AAED,MAAM,UAAU,MAAM,CACpB,KAAQ,EACR,OAAgC;IAEjC,OAAO,IAAI,MAAM,CAAI,KAAK,EAAE,OAAO,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;AAClB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;AACtB,MAAM,CAAC,EAAE,GAAG,CAAI,KAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAA"}
@@ -1,5 +1,8 @@
1
- export * from "./parts/derive.js";
2
- export * from "./parts/lazy.js";
1
+ export * from "./parts/reactive.js";
2
+ export * from "./parts/readable.js";
3
+ export * from "./derive.js";
3
4
  export * from "./effect.js";
5
+ export * from "./fns.js";
6
+ export * from "./lazy.js";
4
7
  export * from "./signal.js";
5
8
  export * from "./types.js";
@@ -1,6 +1,9 @@
1
- export * from "./parts/derive.js";
2
- export * from "./parts/lazy.js";
1
+ export * from "./parts/reactive.js";
2
+ export * from "./parts/readable.js";
3
+ export * from "./derive.js";
3
4
  export * from "./effect.js";
5
+ export * from "./fns.js";
6
+ export * from "./lazy.js";
4
7
  export * from "./signal.js";
5
8
  export * from "./types.js";
6
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/signals/index.ts"],"names":[],"mappings":"AACA,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../s/signals/index.ts"],"names":[],"mappings":"AACA,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,UAAU,CAAA;AACxB,cAAc,WAAW,CAAA;AACzB,cAAc,aAAa,CAAA;AAC3B,cAAc,YAAY,CAAA"}
@@ -0,0 +1,8 @@
1
+ import { SignalOptions } from "./types.js";
2
+ import { Readable } from "./parts/readable.js";
3
+ export declare class Lazy<V> extends Readable<V> {
4
+ #private;
5
+ constructor(formula: () => V, options?: Partial<SignalOptions>);
6
+ get(): V;
7
+ dispose(): void;
8
+ }
@@ -0,0 +1,37 @@
1
+ import { collectorEffect } from "./effect.js";
2
+ import { Readable } from "./parts/readable.js";
3
+ import { tracker } from "../tracker/tracker.js";
4
+ import { defaultCompare } from "./utils/default-compare.js";
5
+ export class Lazy extends Readable {
6
+ #formula;
7
+ #compare;
8
+ #dirty = false;
9
+ #effect;
10
+ constructor(formula, options) {
11
+ super(undefined);
12
+ this.#formula = formula;
13
+ this.#compare = options?.compare ?? defaultCompare;
14
+ }
15
+ get() {
16
+ if (!this.#effect) {
17
+ const { result, dispose } = collectorEffect(this.#formula, () => this.#dirty = true);
18
+ this.#effect = dispose;
19
+ this.sneak = result;
20
+ }
21
+ if (this.#dirty) {
22
+ this.#dirty = false;
23
+ const v = this.#formula();
24
+ const isChanged = !this.#compare(this.sneak, v);
25
+ if (isChanged) {
26
+ this.sneak = v;
27
+ tracker.notifyWrite(this);
28
+ }
29
+ }
30
+ return super.get();
31
+ }
32
+ dispose() {
33
+ if (this.#effect)
34
+ this.#effect();
35
+ }
36
+ }
37
+ //# sourceMappingURL=lazy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../s/signals/lazy.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAC,QAAQ,EAAC,MAAM,qBAAqB,CAAA;AAC5C,OAAO,EAAC,OAAO,EAAC,MAAM,uBAAuB,CAAA;AAC7C,OAAO,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAA;AAEzD,MAAM,OAAO,IAAQ,SAAQ,QAAW;IACvC,QAAQ,CAAS;IACjB,QAAQ,CAA6B;IACrC,MAAM,GAAG,KAAK,CAAA;IACd,OAAO,CAA0B;IAEjC,YAAY,OAAgB,EAAE,OAAgC;QAC7D,KAAK,CAAC,SAAgB,CAAC,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAA;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,CAAA;IACnD,CAAC;IAED,GAAG;QACF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,eAAe,CACxC,IAAI,CAAC,QAAQ,EACb,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CACxB,CAAA;YACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;YACtB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACpB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;YAEnB,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;YACzB,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YAC/C,IAAI,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC,KAAK,GAAG,CAAC,CAAA;gBACd,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YAC1B,CAAC;QACF,CAAC;QACD,OAAO,KAAK,CAAC,GAAG,EAAE,CAAA;IACnB,CAAC;IAED,OAAO;QACN,IAAI,IAAI,CAAC,OAAO;YACf,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;CACD"}
@@ -0,0 +1,5 @@
1
+ import { Readable } from "./readable.js";
2
+ export declare class Reactive<V> extends Readable<V> {
3
+ on: import("@e280/stz").Sub<[V]>;
4
+ dispose(): void;
5
+ }
@@ -0,0 +1,9 @@
1
+ import { sub } from "@e280/stz";
2
+ import { Readable } from "./readable.js";
3
+ export class Reactive extends Readable {
4
+ on = sub();
5
+ dispose() {
6
+ this.on.clear();
7
+ }
8
+ }
9
+ //# sourceMappingURL=reactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactive.js","sourceRoot":"","sources":["../../../s/signals/parts/reactive.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,GAAG,EAAC,MAAM,WAAW,CAAA;AAC7B,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AAEtC,MAAM,OAAO,QAAY,SAAQ,QAAW;IAC3C,EAAE,GAAG,GAAG,EAAO,CAAA;IAEf,OAAO;QACN,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAA;IAChB,CAAC;CACD"}
@@ -0,0 +1,6 @@
1
+ export declare class Readable<V> {
2
+ sneak: V;
3
+ constructor(sneak: V);
4
+ get(): V;
5
+ get value(): V;
6
+ }