@valentin30/signal 0.0.2 → 0.0.4

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.d.mts CHANGED
@@ -1,203 +1,203 @@
1
- type Maybe<T> = T | null | undefined
1
+ type Function = (...args: any[]) => any;
2
2
 
3
- type Factory<Fn extends FactoryFunction> = Fn & {
4
- factory(factory: Maybe<Fn>): void
5
- default(factory: Maybe<Fn>): void
6
- configured(): boolean
7
- }
8
- type FactoryFunction = (...args: any[]) => any
3
+ type Maybe<T> = T | null | undefined;
4
+
5
+ type Factory<Fn extends Function> = Fn & {
6
+ factory(factory: Maybe<Fn>): void;
7
+ default(factory: Maybe<Fn>): void;
8
+ configured(): boolean;
9
+ };
10
+ declare function factory<Fn extends Function>(name: string): Factory<Fn>;
9
11
 
10
12
  interface Collector$1<T> {
11
- add(value: T): void
12
- collect(callback: () => void): Readonly<Set<T>>
13
+ add(value: T): void;
14
+ collecting(): boolean;
15
+ collect(callback: () => void): Readonly<Set<T>>;
16
+ ignore(callback: () => void): void;
13
17
  }
14
- interface CollectorFactoryFunction {
15
- <T>(): Collector$1<T>
18
+ type CollectorFactory = <T>() => Collector$1<T>;
19
+ declare const collector$1: Factory<CollectorFactory>;
20
+
21
+ type Callback = () => void;
22
+
23
+ declare function batch$1(callback: Callback): void;
24
+ declare function batch$1(callback: Callback, collector: Collector$1<Callback>): void;
25
+ declare function batch$1(callback: Callback, collector?: Collector$1<Callback>): void;
26
+ declare namespace batch$1 {
27
+ var collector: Factory<BatchCollectorFactory>;
28
+ }
29
+ type BatchCollectorFactory = () => Collector$1<Callback>;
30
+
31
+ declare function collector<T>(): Collector$1<T>;
32
+ declare class Collector<T> implements Collector$1<T> {
33
+ private values;
34
+ constructor(values: Set<T> | null);
35
+ collecting(): boolean;
36
+ add(value: T): void;
37
+ collect(callback: () => void): Set<T>;
38
+ ignore(callback: () => void): void;
16
39
  }
17
- type collector_type = typeof collector$1
18
- interface collector$1 extends collector_type {}
19
- declare const collector$1: Factory<CollectorFactoryFunction>
20
40
 
21
- type Equals<T> = (value: T, other: T) => boolean
41
+ type Equals<T> = (value: T, other: T) => boolean;
22
42
  interface Comparable<T> {
23
- equals(other: T): boolean
43
+ equals(other: T): boolean;
24
44
  }
25
45
 
26
46
  interface Reader<T> {
27
- read(): T
47
+ read(): T;
28
48
  }
29
49
 
30
- type Callback = () => void
31
-
32
50
  interface Subscription {
33
- subscribe(callback: Callback): Callback
34
- unsubscribe(callback: Callback): void
51
+ subscribe(callback: Callback): Callback;
52
+ unsubscribe(callback: Callback): void;
35
53
  }
36
54
 
37
55
  interface Writer<T> {
38
- write(value: T): void
56
+ write(value: T): void;
39
57
  }
40
58
 
41
- interface Signal$1<T> extends Reader<T>, Writer<T>, Comparable<T>, Subscription {}
42
- interface ReadonlySignal<T> extends Reader<T>, Comparable<T>, Subscription {}
43
- interface SignalFactoryFunction {
44
- <T>(value: T, equals?: Equals<T>): Signal$1<T>
59
+ interface Signal$1<T> extends Reader<T>, Writer<T>, Comparable<T>, Subscription {
45
60
  }
46
- declare const signal$1: Factory<SignalFactoryFunction>
47
-
48
- interface ComposedFactoryFunction {
49
- <T>(compute: () => T, write: (value: T) => void, equals?: Equals<T>): Signal$1<T>
61
+ interface ReadonlySignal<T> extends Reader<T>, Comparable<T>, Subscription {
50
62
  }
51
- declare const composed$1: Factory<ComposedFactoryFunction>
63
+ type SignalFactory = <T>(value: T, equals?: Equals<T>) => Signal$1<T>;
64
+ declare const signal$1: Factory<SignalFactory>;
52
65
 
53
- interface ComputedFactoryFunction {
54
- <T>(compute: () => T, equals?: Equals<T>): ReadonlySignal<T>
66
+ declare function computed$1<T>(compute: () => T, equals?: Equals<T>): Computed<T>;
67
+ declare namespace computed$1 {
68
+ var collector: Factory<ComputedCollectorFactory>;
55
69
  }
56
- declare const computed$1: Factory<ComputedFactoryFunction>
57
-
58
- declare function collector<T>(): Collector$1<T>
59
- declare class Collector<T> implements Collector$1<T> {
60
- private values
61
- constructor(values: Set<T> | null)
62
- add(value: T): void
63
- collect(callback: () => void): Set<T>
70
+ type ComputedCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
71
+ declare class Computed<T> implements ReadonlySignal<T> {
72
+ private empty;
73
+ private value;
74
+ private values;
75
+ private dependencies;
76
+ private readonly compute;
77
+ private readonly equalsFn;
78
+ private readonly listeners;
79
+ private readonly collector;
80
+ constructor(empty: boolean, value: T | undefined, values: [ReadonlySignal<unknown>, unknown][], dependencies: Set<ReadonlySignal<unknown>>, listeners: Set<Callback>, collector: Collector$1<ReadonlySignal<unknown>>, compute: () => T, equals: Maybe<Equals<T>>);
81
+ private dirty;
82
+ read(): T;
83
+ equals(other: T): boolean;
84
+ subscribe(callback: Callback): Callback;
85
+ unsubscribe(callback: Callback): void;
86
+ }
87
+
88
+ type ComposedBatcherFactory = () => Collector$1<Callback>;
89
+ type ComposedCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
90
+ declare function composed$1<T>(compute: () => T, write: (value: T) => void, equals?: Equals<T>): Composed<T>;
91
+ declare namespace composed$1 {
92
+ var batcher: Factory<ComposedBatcherFactory>;
93
+ var collector: Factory<ComposedCollectorFactory>;
94
+ }
95
+ declare class Composed<T> extends Computed<T> implements Signal$1<T> {
96
+ private readonly batcher;
97
+ private readonly writeFn;
98
+ constructor(empty: boolean, value: T | undefined, values: [ReadonlySignal<unknown>, unknown][], dependencies: Set<ReadonlySignal<unknown>>, listeners: Set<Callback>, batcher: Collector$1<Callback>, collector: Collector$1<ReadonlySignal<unknown>>, compute: () => T, write: (value: T) => void, equals: Maybe<Equals<T>>);
99
+ write(value: T): void;
64
100
  }
65
101
 
66
- declare function computed<T>(compute: () => T, equals?: Equals<T>): Computed<T>
67
- declare namespace computed {
68
- var collector: Factory<ComputedCollectorFactoryFunction>
102
+ type Effect = (callback: EffectCallback) => Callback;
103
+ type EffectCallback = (init: boolean) => EffectCleanup | void;
104
+ type EffectCleanup = (destroy: boolean) => void;
105
+ declare const effect$1: Factory<Effect>;
106
+
107
+ declare function effect(cb: EffectCallback): Callback;
108
+ declare namespace effect {
109
+ var collector: Factory<EffectCollectorFactory>;
69
110
  }
70
- interface ComputedCollectorFactoryFunction {
71
- (): Maybe<Collector$1<ReadonlySignal<unknown>>>
111
+ type EffectCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
112
+
113
+ interface Ignore$1 {
114
+ <Value>(value: ReadonlySignal<Value>): Value;
115
+ <Value>(callback: () => Value): Value;
116
+ <Value, Args extends any[]>(callback: (...args: Args) => Value, ...args: Args): Value;
72
117
  }
73
- declare class Computed<T> implements ReadonlySignal<T> {
74
- private empty
75
- private value
76
- private values
77
- private dependencies
78
- private readonly compute
79
- private readonly equalsFn
80
- private readonly listeners
81
- private readonly collector
82
- constructor(
83
- empty: boolean,
84
- value: T | undefined,
85
- values: unknown[],
86
- dependencies: Set<ReadonlySignal<unknown>>,
87
- listeners: Set<Callback>,
88
- collector: Collector$1<ReadonlySignal<unknown>>,
89
- compute: () => T,
90
- equals: Maybe<Equals<T>>,
91
- )
92
- private dirty
93
- read(): T
94
- equals(other: T): boolean
95
- subscribe(callback: Callback): Callback
96
- unsubscribe(callback: Callback): void
97
- }
98
-
99
- declare function composed<T>(compute: () => T, write: (value: T) => void, equals?: Equals<T>): Composed<T>
100
- declare namespace composed {
101
- var collector: Factory<ComposedCollectorFactoryFunction>
102
- }
103
- interface ComposedCollectorFactoryFunction {
104
- (): Maybe<Collector$1<ReadonlySignal<unknown>>>
118
+ declare function ignore$1<Value>(value: ReadonlySignal<Value>): Value;
119
+ declare function ignore$1<Value>(callback: () => Value): Value;
120
+ declare function ignore$1<Value, Args extends any[]>(callback: (...args: Args) => Value, ...args: Args): Value;
121
+ declare namespace ignore$1 {
122
+ var collector: Factory<IgnoreCollectorFactory>;
105
123
  }
106
- declare class Composed<T> extends Computed<T> implements Signal$1<T> {
107
- private readonly writeFn
108
- constructor(
109
- empty: boolean,
110
- value: T | undefined,
111
- values: unknown[],
112
- dependencies: Set<ReadonlySignal<unknown>>,
113
- listeners: Set<Callback>,
114
- collector: Collector$1<ReadonlySignal<unknown>>,
115
- compute: () => T,
116
- write: (value: T) => void,
117
- equals: Maybe<Equals<T>>,
118
- )
119
- write(value: T): void
120
- }
121
-
122
- declare function signal<T>(value: T, equals?: Equals<T>): Signal$1<T>
124
+ type IgnoreCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
125
+
126
+ type SignalBatcherFactory = () => Collector$1<Callback>;
127
+ type SignalCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
128
+ declare function signal<T>(value: T, equals?: Equals<T>): Signal$1<T>;
123
129
  declare namespace signal {
124
- var collector: Factory<SignalCollectorFactoryFunction>
125
- }
126
- interface SignalCollectorFactoryFunction {
127
- (): Maybe<Collector$1<ReadonlySignal<unknown>>>
130
+ var batcher: Factory<SignalBatcherFactory>;
131
+ var collector: Factory<SignalCollectorFactory>;
128
132
  }
129
133
  declare class Signal<T> implements Signal$1<T> {
130
- private value
131
- private equalsFn
132
- private listeners
133
- private collector
134
- constructor(value: T, equals: Maybe<Equals<T>>, listeners: Set<Callback>, collector: Maybe<Collector$1<ReadonlySignal<unknown>>>)
135
- read(): T
136
- write(value: T): void
137
- equals(other: T): boolean
138
- subscribe(callback: Callback): Callback
139
- unsubscribe(callback: Callback): void
140
- }
141
-
142
- type index_Collector<T> = Collector<T>
143
- declare const index_Collector: typeof Collector
144
- type index_Composed<T> = Composed<T>
145
- declare const index_Composed: typeof Composed
146
- type index_ComposedCollectorFactoryFunction = ComposedCollectorFactoryFunction
147
- type index_Computed<T> = Computed<T>
148
- declare const index_Computed: typeof Computed
149
- type index_ComputedCollectorFactoryFunction = ComputedCollectorFactoryFunction
150
- type index_Signal<T> = Signal<T>
151
- declare const index_Signal: typeof Signal
152
- type index_SignalCollectorFactoryFunction = SignalCollectorFactoryFunction
153
- declare const index_collector: typeof collector
154
- declare const index_composed: typeof composed
155
- declare const index_computed: typeof computed
156
- declare const index_signal: typeof signal
134
+ private value;
135
+ private readonly equalsFn;
136
+ private readonly listeners;
137
+ private readonly batcher;
138
+ private readonly collector;
139
+ constructor(value: T, equals: Maybe<Equals<T>>, listeners: Set<Callback>, batcher: Collector$1<Callback>, collector: Collector$1<ReadonlySignal<unknown>>);
140
+ read(): T;
141
+ write(value: T): void;
142
+ equals(other: T): boolean;
143
+ subscribe(callback: Callback): Callback;
144
+ unsubscribe(callback: Callback): void;
145
+ }
146
+
147
+ type index_BatchCollectorFactory = BatchCollectorFactory;
148
+ type index_Collector<T> = Collector<T>;
149
+ declare const index_Collector: typeof Collector;
150
+ type index_Composed<T> = Composed<T>;
151
+ declare const index_Composed: typeof Composed;
152
+ type index_ComposedBatcherFactory = ComposedBatcherFactory;
153
+ type index_ComposedCollectorFactory = ComposedCollectorFactory;
154
+ type index_Computed<T> = Computed<T>;
155
+ declare const index_Computed: typeof Computed;
156
+ type index_ComputedCollectorFactory = ComputedCollectorFactory;
157
+ type index_EffectCollectorFactory = EffectCollectorFactory;
158
+ type index_IgnoreCollectorFactory = IgnoreCollectorFactory;
159
+ type index_Signal<T> = Signal<T>;
160
+ declare const index_Signal: typeof Signal;
161
+ type index_SignalBatcherFactory = SignalBatcherFactory;
162
+ type index_SignalCollectorFactory = SignalCollectorFactory;
163
+ declare const index_collector: typeof collector;
164
+ declare const index_effect: typeof effect;
165
+ declare const index_signal: typeof signal;
157
166
  declare namespace index {
158
- export {
159
- index_Collector as Collector,
160
- index_Composed as Composed,
161
- type index_ComposedCollectorFactoryFunction as ComposedCollectorFactoryFunction,
162
- index_Computed as Computed,
163
- type index_ComputedCollectorFactoryFunction as ComputedCollectorFactoryFunction,
164
- index_Signal as Signal,
165
- type index_SignalCollectorFactoryFunction as SignalCollectorFactoryFunction,
166
- index_collector as collector,
167
- index_composed as composed,
168
- index_computed as computed,
169
- index_signal as signal,
170
- }
167
+ export { type index_BatchCollectorFactory as BatchCollectorFactory, index_Collector as Collector, index_Composed as Composed, type index_ComposedBatcherFactory as ComposedBatcherFactory, type index_ComposedCollectorFactory as ComposedCollectorFactory, index_Computed as Computed, type index_ComputedCollectorFactory as ComputedCollectorFactory, type index_EffectCollectorFactory as EffectCollectorFactory, type Ignore$1 as Ignore, type index_IgnoreCollectorFactory as IgnoreCollectorFactory, index_Signal as Signal, type index_SignalBatcherFactory as SignalBatcherFactory, type index_SignalCollectorFactory as SignalCollectorFactory, batch$1 as batch, index_collector as collector, composed$1 as composed, computed$1 as computed, index_effect as effect, ignore$1 as ignore, index_signal as signal };
168
+ }
169
+
170
+ type Arguments<T> = T extends (...args: infer A) => any ? A : never;
171
+
172
+ interface Batch {
173
+ (callback: Callback): void;
174
+ (callback: Callback, collector: Collector$1<Callback>): void;
175
+ (callback: Callback, collector?: Collector$1<Callback>): void;
171
176
  }
177
+ declare const batch: Factory<Batch>;
178
+
179
+ type ComposedFactory = <T>(read: () => T, write: (value: T) => void, equals?: Equals<T>) => Signal$1<T>;
180
+ declare const composed: Factory<ComposedFactory>;
181
+
182
+ type ComputedFactory = <T>(read: () => T, equals?: Equals<T>) => ReadonlySignal<T>;
183
+ declare const computed: Factory<ComputedFactory>;
184
+
185
+ interface Ignore {
186
+ <Value>(value: ReadonlySignal<Value>): Value;
187
+ <Value>(callback: () => Value): Value;
188
+ <Value, Args extends any[]>(callback: (...args: Args) => Value, ...args: Args): Value;
189
+ }
190
+ declare const ignore: Factory<Ignore>;
172
191
 
173
192
  interface Config {
174
- collector?: Maybe<CollectorFactoryFunction>
175
- signal?: Maybe<SignalFactoryFunction>
176
- computed?: Maybe<ComputedFactoryFunction>
177
- composed?: Maybe<ComposedFactoryFunction>
178
- }
179
- declare function config(config?: Config): void
180
-
181
- export {
182
- type Callback,
183
- type Collector$1 as Collector,
184
- type CollectorFactoryFunction,
185
- type Comparable,
186
- type ComposedFactoryFunction,
187
- type ComputedFactoryFunction,
188
- type Config,
189
- type Equals,
190
- type Maybe,
191
- type Reader,
192
- type ReadonlySignal,
193
- type Signal$1 as Signal,
194
- type SignalFactoryFunction,
195
- type Subscription,
196
- type Writer,
197
- collector$1 as collector,
198
- composed$1 as composed,
199
- computed$1 as computed,
200
- config,
201
- index as internal,
202
- signal$1 as signal,
193
+ collector?: Maybe<CollectorFactory>;
194
+ signal?: Maybe<SignalFactory>;
195
+ computed?: Maybe<ComputedFactory>;
196
+ composed?: Maybe<ComposedFactory>;
197
+ effect?: Maybe<Effect>;
198
+ batch?: Maybe<Batch>;
199
+ ignore?: Maybe<Ignore$1>;
203
200
  }
201
+ declare function config(config?: Config): void;
202
+
203
+ export { type Arguments, type Batch, type Callback, type Collector$1 as Collector, type CollectorFactory, type Comparable, type ComposedFactory, type ComputedFactory, type Config, type Effect, type EffectCallback, type EffectCleanup, type Equals, type Factory, type Function, type Ignore, type Maybe, type Reader, type ReadonlySignal, type Signal$1 as Signal, type SignalFactory, type Subscription, type Writer, batch, collector$1 as collector, composed, computed, config, effect$1 as effect, factory, ignore, index as internal, signal$1 as signal };
package/dist/index.d.ts CHANGED
@@ -1,23 +1,42 @@
1
+ type Function = (...args: any[]) => any;
2
+
1
3
  type Maybe<T> = T | null | undefined;
2
4
 
3
- type Factory<Fn extends FactoryFunction> = Fn & {
5
+ type Factory<Fn extends Function> = Fn & {
4
6
  factory(factory: Maybe<Fn>): void;
5
7
  default(factory: Maybe<Fn>): void;
6
8
  configured(): boolean;
7
9
  };
8
- type FactoryFunction = (...args: any[]) => any;
10
+ declare function factory<Fn extends Function>(name: string): Factory<Fn>;
9
11
 
10
12
  interface Collector$1<T> {
11
13
  add(value: T): void;
14
+ collecting(): boolean;
12
15
  collect(callback: () => void): Readonly<Set<T>>;
16
+ ignore(callback: () => void): void;
13
17
  }
14
- interface CollectorFactoryFunction {
15
- <T>(): Collector$1<T>;
18
+ type CollectorFactory = <T>() => Collector$1<T>;
19
+ declare const collector$1: Factory<CollectorFactory>;
20
+
21
+ type Callback = () => void;
22
+
23
+ declare function batch$1(callback: Callback): void;
24
+ declare function batch$1(callback: Callback, collector: Collector$1<Callback>): void;
25
+ declare function batch$1(callback: Callback, collector?: Collector$1<Callback>): void;
26
+ declare namespace batch$1 {
27
+ var collector: Factory<BatchCollectorFactory>;
16
28
  }
17
- type collector_type = typeof collector$1;
18
- interface collector$1 extends collector_type {
29
+ type BatchCollectorFactory = () => Collector$1<Callback>;
30
+
31
+ declare function collector<T>(): Collector$1<T>;
32
+ declare class Collector<T> implements Collector$1<T> {
33
+ private values;
34
+ constructor(values: Set<T> | null);
35
+ collecting(): boolean;
36
+ add(value: T): void;
37
+ collect(callback: () => void): Set<T>;
38
+ ignore(callback: () => void): void;
19
39
  }
20
- declare const collector$1: Factory<CollectorFactoryFunction>;
21
40
 
22
41
  type Equals<T> = (value: T, other: T) => boolean;
23
42
  interface Comparable<T> {
@@ -28,8 +47,6 @@ interface Reader<T> {
28
47
  read(): T;
29
48
  }
30
49
 
31
- type Callback = () => void;
32
-
33
50
  interface Subscription {
34
51
  subscribe(callback: Callback): Callback;
35
52
  unsubscribe(callback: Callback): void;
@@ -43,36 +60,14 @@ interface Signal$1<T> extends Reader<T>, Writer<T>, Comparable<T>, Subscription
43
60
  }
44
61
  interface ReadonlySignal<T> extends Reader<T>, Comparable<T>, Subscription {
45
62
  }
46
- interface SignalFactoryFunction {
47
- <T>(value: T, equals?: Equals<T>): Signal$1<T>;
48
- }
49
- declare const signal$1: Factory<SignalFactoryFunction>;
50
-
51
- interface ComposedFactoryFunction {
52
- <T>(compute: () => T, write: (value: T) => void, equals?: Equals<T>): Signal$1<T>;
53
- }
54
- declare const composed$1: Factory<ComposedFactoryFunction>;
63
+ type SignalFactory = <T>(value: T, equals?: Equals<T>) => Signal$1<T>;
64
+ declare const signal$1: Factory<SignalFactory>;
55
65
 
56
- interface ComputedFactoryFunction {
57
- <T>(compute: () => T, equals?: Equals<T>): ReadonlySignal<T>;
58
- }
59
- declare const computed$1: Factory<ComputedFactoryFunction>;
60
-
61
- declare function collector<T>(): Collector$1<T>;
62
- declare class Collector<T> implements Collector$1<T> {
63
- private values;
64
- constructor(values: Set<T> | null);
65
- add(value: T): void;
66
- collect(callback: () => void): Set<T>;
67
- }
68
-
69
- declare function computed<T>(compute: () => T, equals?: Equals<T>): Computed<T>;
70
- declare namespace computed {
71
- var collector: Factory<ComputedCollectorFactoryFunction>;
72
- }
73
- interface ComputedCollectorFactoryFunction {
74
- (): Maybe<Collector$1<ReadonlySignal<unknown>>>;
66
+ declare function computed$1<T>(compute: () => T, equals?: Equals<T>): Computed<T>;
67
+ declare namespace computed$1 {
68
+ var collector: Factory<ComputedCollectorFactory>;
75
69
  }
70
+ type ComputedCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
76
71
  declare class Computed<T> implements ReadonlySignal<T> {
77
72
  private empty;
78
73
  private value;
@@ -82,7 +77,7 @@ declare class Computed<T> implements ReadonlySignal<T> {
82
77
  private readonly equalsFn;
83
78
  private readonly listeners;
84
79
  private readonly collector;
85
- constructor(empty: boolean, value: T | undefined, values: unknown[], dependencies: Set<ReadonlySignal<unknown>>, listeners: Set<Callback>, collector: Collector$1<ReadonlySignal<unknown>>, compute: () => T, equals: Maybe<Equals<T>>);
80
+ constructor(empty: boolean, value: T | undefined, values: [ReadonlySignal<unknown>, unknown][], dependencies: Set<ReadonlySignal<unknown>>, listeners: Set<Callback>, collector: Collector$1<ReadonlySignal<unknown>>, compute: () => T, equals: Maybe<Equals<T>>);
86
81
  private dirty;
87
82
  read(): T;
88
83
  equals(other: T): boolean;
@@ -90,32 +85,58 @@ declare class Computed<T> implements ReadonlySignal<T> {
90
85
  unsubscribe(callback: Callback): void;
91
86
  }
92
87
 
93
- declare function composed<T>(compute: () => T, write: (value: T) => void, equals?: Equals<T>): Composed<T>;
94
- declare namespace composed {
95
- var collector: Factory<ComposedCollectorFactoryFunction>;
96
- }
97
- interface ComposedCollectorFactoryFunction {
98
- (): Maybe<Collector$1<ReadonlySignal<unknown>>>;
88
+ type ComposedBatcherFactory = () => Collector$1<Callback>;
89
+ type ComposedCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
90
+ declare function composed$1<T>(compute: () => T, write: (value: T) => void, equals?: Equals<T>): Composed<T>;
91
+ declare namespace composed$1 {
92
+ var batcher: Factory<ComposedBatcherFactory>;
93
+ var collector: Factory<ComposedCollectorFactory>;
99
94
  }
100
95
  declare class Composed<T> extends Computed<T> implements Signal$1<T> {
96
+ private readonly batcher;
101
97
  private readonly writeFn;
102
- constructor(empty: boolean, value: T | undefined, values: unknown[], dependencies: Set<ReadonlySignal<unknown>>, listeners: Set<Callback>, collector: Collector$1<ReadonlySignal<unknown>>, compute: () => T, write: (value: T) => void, equals: Maybe<Equals<T>>);
98
+ constructor(empty: boolean, value: T | undefined, values: [ReadonlySignal<unknown>, unknown][], dependencies: Set<ReadonlySignal<unknown>>, listeners: Set<Callback>, batcher: Collector$1<Callback>, collector: Collector$1<ReadonlySignal<unknown>>, compute: () => T, write: (value: T) => void, equals: Maybe<Equals<T>>);
103
99
  write(value: T): void;
104
100
  }
105
101
 
102
+ type Effect = (callback: EffectCallback) => Callback;
103
+ type EffectCallback = (init: boolean) => EffectCleanup | void;
104
+ type EffectCleanup = (destroy: boolean) => void;
105
+ declare const effect$1: Factory<Effect>;
106
+
107
+ declare function effect(cb: EffectCallback): Callback;
108
+ declare namespace effect {
109
+ var collector: Factory<EffectCollectorFactory>;
110
+ }
111
+ type EffectCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
112
+
113
+ interface Ignore$1 {
114
+ <Value>(value: ReadonlySignal<Value>): Value;
115
+ <Value>(callback: () => Value): Value;
116
+ <Value, Args extends any[]>(callback: (...args: Args) => Value, ...args: Args): Value;
117
+ }
118
+ declare function ignore$1<Value>(value: ReadonlySignal<Value>): Value;
119
+ declare function ignore$1<Value>(callback: () => Value): Value;
120
+ declare function ignore$1<Value, Args extends any[]>(callback: (...args: Args) => Value, ...args: Args): Value;
121
+ declare namespace ignore$1 {
122
+ var collector: Factory<IgnoreCollectorFactory>;
123
+ }
124
+ type IgnoreCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
125
+
126
+ type SignalBatcherFactory = () => Collector$1<Callback>;
127
+ type SignalCollectorFactory = () => Collector$1<ReadonlySignal<unknown>>;
106
128
  declare function signal<T>(value: T, equals?: Equals<T>): Signal$1<T>;
107
129
  declare namespace signal {
108
- var collector: Factory<SignalCollectorFactoryFunction>;
109
- }
110
- interface SignalCollectorFactoryFunction {
111
- (): Maybe<Collector$1<ReadonlySignal<unknown>>>;
130
+ var batcher: Factory<SignalBatcherFactory>;
131
+ var collector: Factory<SignalCollectorFactory>;
112
132
  }
113
133
  declare class Signal<T> implements Signal$1<T> {
114
134
  private value;
115
- private equalsFn;
116
- private listeners;
117
- private collector;
118
- constructor(value: T, equals: Maybe<Equals<T>>, listeners: Set<Callback>, collector: Maybe<Collector$1<ReadonlySignal<unknown>>>);
135
+ private readonly equalsFn;
136
+ private readonly listeners;
137
+ private readonly batcher;
138
+ private readonly collector;
139
+ constructor(value: T, equals: Maybe<Equals<T>>, listeners: Set<Callback>, batcher: Collector$1<Callback>, collector: Collector$1<ReadonlySignal<unknown>>);
119
140
  read(): T;
120
141
  write(value: T): void;
121
142
  equals(other: T): boolean;
@@ -123,31 +144,60 @@ declare class Signal<T> implements Signal$1<T> {
123
144
  unsubscribe(callback: Callback): void;
124
145
  }
125
146
 
147
+ type index_BatchCollectorFactory = BatchCollectorFactory;
126
148
  type index_Collector<T> = Collector<T>;
127
149
  declare const index_Collector: typeof Collector;
128
150
  type index_Composed<T> = Composed<T>;
129
151
  declare const index_Composed: typeof Composed;
130
- type index_ComposedCollectorFactoryFunction = ComposedCollectorFactoryFunction;
152
+ type index_ComposedBatcherFactory = ComposedBatcherFactory;
153
+ type index_ComposedCollectorFactory = ComposedCollectorFactory;
131
154
  type index_Computed<T> = Computed<T>;
132
155
  declare const index_Computed: typeof Computed;
133
- type index_ComputedCollectorFactoryFunction = ComputedCollectorFactoryFunction;
156
+ type index_ComputedCollectorFactory = ComputedCollectorFactory;
157
+ type index_EffectCollectorFactory = EffectCollectorFactory;
158
+ type index_IgnoreCollectorFactory = IgnoreCollectorFactory;
134
159
  type index_Signal<T> = Signal<T>;
135
160
  declare const index_Signal: typeof Signal;
136
- type index_SignalCollectorFactoryFunction = SignalCollectorFactoryFunction;
161
+ type index_SignalBatcherFactory = SignalBatcherFactory;
162
+ type index_SignalCollectorFactory = SignalCollectorFactory;
137
163
  declare const index_collector: typeof collector;
138
- declare const index_composed: typeof composed;
139
- declare const index_computed: typeof computed;
164
+ declare const index_effect: typeof effect;
140
165
  declare const index_signal: typeof signal;
141
166
  declare namespace index {
142
- export { index_Collector as Collector, index_Composed as Composed, type index_ComposedCollectorFactoryFunction as ComposedCollectorFactoryFunction, index_Computed as Computed, type index_ComputedCollectorFactoryFunction as ComputedCollectorFactoryFunction, index_Signal as Signal, type index_SignalCollectorFactoryFunction as SignalCollectorFactoryFunction, index_collector as collector, index_composed as composed, index_computed as computed, index_signal as signal };
167
+ export { type index_BatchCollectorFactory as BatchCollectorFactory, index_Collector as Collector, index_Composed as Composed, type index_ComposedBatcherFactory as ComposedBatcherFactory, type index_ComposedCollectorFactory as ComposedCollectorFactory, index_Computed as Computed, type index_ComputedCollectorFactory as ComputedCollectorFactory, type index_EffectCollectorFactory as EffectCollectorFactory, type Ignore$1 as Ignore, type index_IgnoreCollectorFactory as IgnoreCollectorFactory, index_Signal as Signal, type index_SignalBatcherFactory as SignalBatcherFactory, type index_SignalCollectorFactory as SignalCollectorFactory, batch$1 as batch, index_collector as collector, composed$1 as composed, computed$1 as computed, index_effect as effect, ignore$1 as ignore, index_signal as signal };
168
+ }
169
+
170
+ type Arguments<T> = T extends (...args: infer A) => any ? A : never;
171
+
172
+ interface Batch {
173
+ (callback: Callback): void;
174
+ (callback: Callback, collector: Collector$1<Callback>): void;
175
+ (callback: Callback, collector?: Collector$1<Callback>): void;
176
+ }
177
+ declare const batch: Factory<Batch>;
178
+
179
+ type ComposedFactory = <T>(read: () => T, write: (value: T) => void, equals?: Equals<T>) => Signal$1<T>;
180
+ declare const composed: Factory<ComposedFactory>;
181
+
182
+ type ComputedFactory = <T>(read: () => T, equals?: Equals<T>) => ReadonlySignal<T>;
183
+ declare const computed: Factory<ComputedFactory>;
184
+
185
+ interface Ignore {
186
+ <Value>(value: ReadonlySignal<Value>): Value;
187
+ <Value>(callback: () => Value): Value;
188
+ <Value, Args extends any[]>(callback: (...args: Args) => Value, ...args: Args): Value;
143
189
  }
190
+ declare const ignore: Factory<Ignore>;
144
191
 
145
192
  interface Config {
146
- collector?: Maybe<CollectorFactoryFunction>;
147
- signal?: Maybe<SignalFactoryFunction>;
148
- computed?: Maybe<ComputedFactoryFunction>;
149
- composed?: Maybe<ComposedFactoryFunction>;
193
+ collector?: Maybe<CollectorFactory>;
194
+ signal?: Maybe<SignalFactory>;
195
+ computed?: Maybe<ComputedFactory>;
196
+ composed?: Maybe<ComposedFactory>;
197
+ effect?: Maybe<Effect>;
198
+ batch?: Maybe<Batch>;
199
+ ignore?: Maybe<Ignore$1>;
150
200
  }
151
201
  declare function config(config?: Config): void;
152
202
 
153
- export { type Callback, type Collector$1 as Collector, type CollectorFactoryFunction, type Comparable, type ComposedFactoryFunction, type ComputedFactoryFunction, type Config, type Equals, type Maybe, type Reader, type ReadonlySignal, type Signal$1 as Signal, type SignalFactoryFunction, type Subscription, type Writer, collector$1 as collector, composed$1 as composed, computed$1 as computed, config, index as internal, signal$1 as signal };
203
+ export { type Arguments, type Batch, type Callback, type Collector$1 as Collector, type CollectorFactory, type Comparable, type ComposedFactory, type ComputedFactory, type Config, type Effect, type EffectCallback, type EffectCleanup, type Equals, type Factory, type Function, type Ignore, type Maybe, type Reader, type ReadonlySignal, type Signal$1 as Signal, type SignalFactory, type Subscription, type Writer, batch, collector$1 as collector, composed, computed, config, effect$1 as effect, factory, ignore, index as internal, signal$1 as signal };
package/dist/index.js CHANGED
@@ -20,10 +20,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ batch: () => batch,
23
24
  collector: () => collector,
24
25
  composed: () => composed,
25
26
  computed: () => computed,
26
27
  config: () => config,
28
+ effect: () => effect,
29
+ factory: () => factory,
30
+ ignore: () => ignore,
27
31
  internal: () => internal_exports,
28
32
  signal: () => signal
29
33
  });
@@ -38,16 +42,15 @@ function factory(name) {
38
42
  if (__default__) return __default__(...args);
39
43
  throw new Error(`${name}.factory() not configured!`);
40
44
  }
41
- object.default = (factory2) => {
42
- __default__ = factory2;
43
- };
44
- object.factory = (factory2) => {
45
- __factory__ = factory2;
46
- };
45
+ object.default = (factory2) => __default__ = factory2;
46
+ object.factory = (factory2) => __factory__ = factory2;
47
47
  object.configured = () => __default__ !== null || __factory__ !== null;
48
48
  return object;
49
49
  }
50
50
 
51
+ // src/core/batch.ts
52
+ var batch = factory("batch");
53
+
51
54
  // src/core/collector.ts
52
55
  var collector = factory("collector");
53
56
 
@@ -57,6 +60,12 @@ var composed = factory("composed");
57
60
  // src/core/computed.ts
58
61
  var computed = factory("computed");
59
62
 
63
+ // src/core/effect.ts
64
+ var effect = factory("effect");
65
+
66
+ // src/core/ignore.ts
67
+ var ignore = factory("ignore");
68
+
60
69
  // src/core/signal.ts
61
70
  var signal = factory("signal");
62
71
 
@@ -67,12 +76,22 @@ __export(internal_exports, {
67
76
  Composed: () => Composed,
68
77
  Computed: () => Computed,
69
78
  Signal: () => Signal,
79
+ batch: () => batch2,
70
80
  collector: () => collector2,
71
81
  composed: () => composed2,
72
82
  computed: () => computed2,
83
+ effect: () => effect2,
84
+ ignore: () => ignore2,
73
85
  signal: () => signal2
74
86
  });
75
87
 
88
+ // src/internal/batch.ts
89
+ function batch2(callback, collector3 = batch2.collector()) {
90
+ if (collector3.collecting()) return callback();
91
+ collector3.collect(callback).forEach((listener) => listener());
92
+ }
93
+ batch2.collector = factory("batch.collector");
94
+
76
95
  // src/internal/collector.ts
77
96
  function collector2() {
78
97
  return new Collector(null);
@@ -82,6 +101,9 @@ var Collector = class {
82
101
  constructor(values) {
83
102
  this.values = values;
84
103
  }
104
+ collecting() {
105
+ return this.values !== null;
106
+ }
85
107
  add(value) {
86
108
  if (!this.values) return;
87
109
  this.values.add(value);
@@ -94,13 +116,16 @@ var Collector = class {
94
116
  this.values = current;
95
117
  return collected;
96
118
  }
119
+ ignore(callback) {
120
+ const current = this.values;
121
+ this.values = null;
122
+ callback();
123
+ this.values = current;
124
+ }
97
125
  };
98
126
 
99
127
  // src/internal/computed.ts
100
128
  function computed2(compute, equals) {
101
- if (!computed2.collector()) {
102
- throw new Error("computed: collector is not configured.");
103
- }
104
129
  return new Computed(
105
130
  true,
106
131
  void 0,
@@ -134,28 +159,20 @@ var Computed = class {
134
159
  }
135
160
  dirty() {
136
161
  if (this.empty) return true;
137
- return Array.from(this.dependencies).some((dependency, index) => !dependency.equals(this.values[index]));
162
+ return this.values.some(([dep, value]) => !dep.equals(value));
138
163
  }
139
164
  read() {
140
165
  this.collector.add(this);
141
166
  if (!this.dirty()) return this.value;
142
167
  const current = this.dependencies;
143
- const next = this.collector.collect(() => {
144
- this.value = this.compute();
145
- });
168
+ const next = this.collector.collect(() => this.value = this.compute());
146
169
  this.dependencies = next;
147
- this.values = Array.from(this.dependencies).map((dependency) => dependency.read());
170
+ this.values = Array.from(next).map((dep) => [dep, dep.read()]);
148
171
  this.empty = false;
149
172
  if (!current.size && !next.size) return this.value;
150
173
  if (!this.listeners.size) return this.value;
151
- current.forEach((dependency) => {
152
- if (next.has(dependency)) return;
153
- this.listeners.forEach((listener) => dependency.unsubscribe(listener));
154
- });
155
- next.forEach((dependency) => {
156
- if (current.has(dependency)) return;
157
- this.listeners.forEach((listener) => dependency.subscribe(listener));
158
- });
174
+ current.forEach((dep) => !next.has(dep) && this.listeners.forEach((listener) => dep.unsubscribe(listener)));
175
+ next.forEach((dep) => !current.has(dep) && this.listeners.forEach((listener) => dep.subscribe(listener)));
159
176
  return this.value;
160
177
  }
161
178
  equals(other) {
@@ -164,69 +181,103 @@ var Computed = class {
164
181
  }
165
182
  subscribe(callback) {
166
183
  this.listeners.add(callback);
167
- this.dependencies.forEach((dependency) => dependency.subscribe(callback));
168
- return () => this.unsubscribe(callback);
184
+ this.dependencies.forEach((dep) => dep.subscribe(callback));
185
+ return this.unsubscribe.bind(this, callback);
169
186
  }
170
187
  unsubscribe(callback) {
171
188
  this.listeners.delete(callback);
172
- this.dependencies.forEach((dependency) => dependency.unsubscribe(callback));
189
+ this.dependencies.forEach((dep) => dep.unsubscribe(callback));
173
190
  }
174
191
  };
175
192
 
176
193
  // src/internal/composed.ts
177
194
  function composed2(compute, write, equals) {
178
- if (!composed2.collector()) {
179
- throw new Error("composed: collector is not configured.");
180
- }
181
195
  return new Composed(
182
196
  true,
183
197
  void 0,
184
198
  [],
185
199
  /* @__PURE__ */ new Set(),
186
200
  /* @__PURE__ */ new Set(),
201
+ composed2.batcher(),
187
202
  composed2.collector(),
188
203
  compute,
189
204
  write,
190
205
  equals
191
206
  );
192
207
  }
208
+ composed2.batcher = factory("composed.batcher");
193
209
  composed2.collector = factory("composed.collector");
194
210
  var Composed = class extends Computed {
211
+ batcher;
195
212
  writeFn;
196
- constructor(empty, value, values, dependencies, listeners, collector3, compute, write, equals) {
213
+ constructor(empty, value, values, dependencies, listeners, batcher, collector3, compute, write, equals) {
197
214
  super(empty, value, values, dependencies, listeners, collector3, compute, equals);
215
+ this.batcher = batcher;
198
216
  this.writeFn = write;
199
217
  }
200
218
  write(value) {
201
219
  if (this.equals(value)) return;
202
- this.writeFn(value);
220
+ batch(() => this.writeFn(value), this.batcher);
203
221
  }
204
222
  };
205
223
 
224
+ // src/internal/effect.ts
225
+ function effect2(cb) {
226
+ let cleanupFn = null;
227
+ let dependencies = effect2.collector().collect(() => cleanupFn = cb(true) ?? null);
228
+ dependencies.forEach((dependency) => dependency.subscribe(callback));
229
+ function callback() {
230
+ if (cleanupFn) cleanupFn(false);
231
+ const next = effect2.collector().collect(() => cleanupFn = cb(false) ?? null);
232
+ next.forEach((dependency) => !dependencies.has(dependency) && dependency.subscribe(callback));
233
+ dependencies.forEach((dependency) => !next.has(dependency) && dependency.unsubscribe(callback));
234
+ dependencies = next;
235
+ }
236
+ return () => {
237
+ dependencies.forEach((dependency) => dependency.unsubscribe(callback));
238
+ dependencies.clear();
239
+ if (cleanupFn) cleanupFn(true);
240
+ cleanupFn = null;
241
+ };
242
+ }
243
+ effect2.collector = factory("effect.collector");
244
+
245
+ // src/internal/ignore.ts
246
+ function ignore2(callback, ...args) {
247
+ let value;
248
+ ignore2.collector().ignore(() => value = typeof callback === "function" ? callback(...args) : callback.read());
249
+ return value;
250
+ }
251
+ ignore2.collector = factory("signal.collector");
252
+
206
253
  // src/internal/signal.ts
207
254
  function signal2(value, equals) {
208
- return new Signal(value, equals, /* @__PURE__ */ new Set(), signal2.collector());
255
+ return new Signal(value, equals, /* @__PURE__ */ new Set(), signal2.batcher(), signal2.collector());
209
256
  }
257
+ signal2.batcher = factory("signal.batcher");
210
258
  signal2.collector = factory("signal.collector");
211
259
  var Signal = class {
212
260
  value;
213
261
  equalsFn;
214
262
  listeners;
263
+ batcher;
215
264
  collector;
216
- constructor(value, equals, listeners, collector3) {
265
+ constructor(value, equals, listeners, batcher, collector3) {
217
266
  this.value = value;
218
267
  this.equalsFn = equals;
219
268
  this.listeners = listeners;
269
+ this.batcher = batcher;
220
270
  this.collector = collector3;
221
271
  }
222
272
  read() {
223
- if (this.collector) this.collector.add(this);
273
+ this.collector.add(this);
224
274
  return this.value;
225
275
  }
226
276
  write(value) {
227
277
  if (this.equals(value)) return;
228
278
  this.value = value;
229
- this.listeners.forEach((listener) => listener());
279
+ if (this.batcher.collecting()) this.listeners.forEach((listener) => this.batcher.add(listener));
280
+ else this.listeners.forEach((listener) => listener());
230
281
  }
231
282
  equals(other) {
232
283
  if (this.equalsFn) return this.equalsFn(this.value, other);
@@ -234,38 +285,60 @@ var Signal = class {
234
285
  }
235
286
  subscribe(callback) {
236
287
  this.listeners.add(callback);
237
- return () => this.unsubscribe(callback);
288
+ return this.unsubscribe.bind(this, callback);
238
289
  }
239
290
  unsubscribe(callback) {
240
291
  this.listeners.delete(callback);
241
292
  }
242
293
  };
243
294
 
244
- // src/index.ts
295
+ // src/core/config.ts
245
296
  function config(config2 = {}) {
246
- signal.factory(config2.signal);
247
297
  collector.factory(config2.collector);
298
+ signal.factory(config2.signal);
248
299
  computed.factory(config2.computed);
249
300
  composed.factory(config2.composed);
301
+ effect.factory(config2.effect);
302
+ batch.factory(config2.batch);
303
+ ignore.factory(config2.ignore);
250
304
  }
251
- var __shared__ = null;
252
- function shared() {
253
- if (!__shared__) __shared__ = collector();
254
- return __shared__;
305
+
306
+ // src/index.ts
307
+ var __collector__ = null;
308
+ function shared_collector() {
309
+ if (!__collector__) __collector__ = collector();
310
+ return __collector__;
255
311
  }
256
- signal2.collector.default(shared);
257
- computed2.collector.default(shared);
258
- composed2.collector.default(shared);
259
- signal.default(signal2);
312
+ signal2.collector.default(shared_collector);
313
+ computed2.collector.default(shared_collector);
314
+ composed2.collector.default(shared_collector);
315
+ effect2.collector.default(shared_collector);
316
+ ignore2.collector.default(shared_collector);
317
+ var __batcher__ = null;
318
+ function shared_batcher() {
319
+ if (!__batcher__) __batcher__ = collector();
320
+ return __batcher__;
321
+ }
322
+ signal2.batcher.default(shared_batcher);
323
+ composed2.batcher.default(shared_batcher);
324
+ batch2.collector.default(shared_batcher);
260
325
  collector.default(collector2);
326
+ signal.default(signal2);
261
327
  computed.default(computed2);
262
328
  composed.default(composed2);
329
+ effect.default(effect2);
330
+ batch.default(batch2);
331
+ ignore.default(ignore2);
263
332
  // Annotate the CommonJS export names for ESM import in node:
264
333
  0 && (module.exports = {
334
+ batch,
265
335
  collector,
266
336
  composed,
267
337
  computed,
268
338
  config,
339
+ effect,
340
+ factory,
341
+ ignore,
269
342
  internal,
270
343
  signal
271
344
  });
package/dist/index.mjs CHANGED
@@ -13,16 +13,15 @@ function factory(name) {
13
13
  if (__default__) return __default__(...args);
14
14
  throw new Error(`${name}.factory() not configured!`);
15
15
  }
16
- object.default = (factory2) => {
17
- __default__ = factory2;
18
- };
19
- object.factory = (factory2) => {
20
- __factory__ = factory2;
21
- };
16
+ object.default = (factory2) => __default__ = factory2;
17
+ object.factory = (factory2) => __factory__ = factory2;
22
18
  object.configured = () => __default__ !== null || __factory__ !== null;
23
19
  return object;
24
20
  }
25
21
 
22
+ // src/core/batch.ts
23
+ var batch = factory("batch");
24
+
26
25
  // src/core/collector.ts
27
26
  var collector = factory("collector");
28
27
 
@@ -32,6 +31,12 @@ var composed = factory("composed");
32
31
  // src/core/computed.ts
33
32
  var computed = factory("computed");
34
33
 
34
+ // src/core/effect.ts
35
+ var effect = factory("effect");
36
+
37
+ // src/core/ignore.ts
38
+ var ignore = factory("ignore");
39
+
35
40
  // src/core/signal.ts
36
41
  var signal = factory("signal");
37
42
 
@@ -42,12 +47,22 @@ __export(internal_exports, {
42
47
  Composed: () => Composed,
43
48
  Computed: () => Computed,
44
49
  Signal: () => Signal,
50
+ batch: () => batch2,
45
51
  collector: () => collector2,
46
52
  composed: () => composed2,
47
53
  computed: () => computed2,
54
+ effect: () => effect2,
55
+ ignore: () => ignore2,
48
56
  signal: () => signal2
49
57
  });
50
58
 
59
+ // src/internal/batch.ts
60
+ function batch2(callback, collector3 = batch2.collector()) {
61
+ if (collector3.collecting()) return callback();
62
+ collector3.collect(callback).forEach((listener) => listener());
63
+ }
64
+ batch2.collector = factory("batch.collector");
65
+
51
66
  // src/internal/collector.ts
52
67
  function collector2() {
53
68
  return new Collector(null);
@@ -57,6 +72,9 @@ var Collector = class {
57
72
  constructor(values) {
58
73
  this.values = values;
59
74
  }
75
+ collecting() {
76
+ return this.values !== null;
77
+ }
60
78
  add(value) {
61
79
  if (!this.values) return;
62
80
  this.values.add(value);
@@ -69,13 +87,16 @@ var Collector = class {
69
87
  this.values = current;
70
88
  return collected;
71
89
  }
90
+ ignore(callback) {
91
+ const current = this.values;
92
+ this.values = null;
93
+ callback();
94
+ this.values = current;
95
+ }
72
96
  };
73
97
 
74
98
  // src/internal/computed.ts
75
99
  function computed2(compute, equals) {
76
- if (!computed2.collector()) {
77
- throw new Error("computed: collector is not configured.");
78
- }
79
100
  return new Computed(
80
101
  true,
81
102
  void 0,
@@ -109,28 +130,20 @@ var Computed = class {
109
130
  }
110
131
  dirty() {
111
132
  if (this.empty) return true;
112
- return Array.from(this.dependencies).some((dependency, index) => !dependency.equals(this.values[index]));
133
+ return this.values.some(([dep, value]) => !dep.equals(value));
113
134
  }
114
135
  read() {
115
136
  this.collector.add(this);
116
137
  if (!this.dirty()) return this.value;
117
138
  const current = this.dependencies;
118
- const next = this.collector.collect(() => {
119
- this.value = this.compute();
120
- });
139
+ const next = this.collector.collect(() => this.value = this.compute());
121
140
  this.dependencies = next;
122
- this.values = Array.from(this.dependencies).map((dependency) => dependency.read());
141
+ this.values = Array.from(next).map((dep) => [dep, dep.read()]);
123
142
  this.empty = false;
124
143
  if (!current.size && !next.size) return this.value;
125
144
  if (!this.listeners.size) return this.value;
126
- current.forEach((dependency) => {
127
- if (next.has(dependency)) return;
128
- this.listeners.forEach((listener) => dependency.unsubscribe(listener));
129
- });
130
- next.forEach((dependency) => {
131
- if (current.has(dependency)) return;
132
- this.listeners.forEach((listener) => dependency.subscribe(listener));
133
- });
145
+ current.forEach((dep) => !next.has(dep) && this.listeners.forEach((listener) => dep.unsubscribe(listener)));
146
+ next.forEach((dep) => !current.has(dep) && this.listeners.forEach((listener) => dep.subscribe(listener)));
134
147
  return this.value;
135
148
  }
136
149
  equals(other) {
@@ -139,69 +152,103 @@ var Computed = class {
139
152
  }
140
153
  subscribe(callback) {
141
154
  this.listeners.add(callback);
142
- this.dependencies.forEach((dependency) => dependency.subscribe(callback));
143
- return () => this.unsubscribe(callback);
155
+ this.dependencies.forEach((dep) => dep.subscribe(callback));
156
+ return this.unsubscribe.bind(this, callback);
144
157
  }
145
158
  unsubscribe(callback) {
146
159
  this.listeners.delete(callback);
147
- this.dependencies.forEach((dependency) => dependency.unsubscribe(callback));
160
+ this.dependencies.forEach((dep) => dep.unsubscribe(callback));
148
161
  }
149
162
  };
150
163
 
151
164
  // src/internal/composed.ts
152
165
  function composed2(compute, write, equals) {
153
- if (!composed2.collector()) {
154
- throw new Error("composed: collector is not configured.");
155
- }
156
166
  return new Composed(
157
167
  true,
158
168
  void 0,
159
169
  [],
160
170
  /* @__PURE__ */ new Set(),
161
171
  /* @__PURE__ */ new Set(),
172
+ composed2.batcher(),
162
173
  composed2.collector(),
163
174
  compute,
164
175
  write,
165
176
  equals
166
177
  );
167
178
  }
179
+ composed2.batcher = factory("composed.batcher");
168
180
  composed2.collector = factory("composed.collector");
169
181
  var Composed = class extends Computed {
182
+ batcher;
170
183
  writeFn;
171
- constructor(empty, value, values, dependencies, listeners, collector3, compute, write, equals) {
184
+ constructor(empty, value, values, dependencies, listeners, batcher, collector3, compute, write, equals) {
172
185
  super(empty, value, values, dependencies, listeners, collector3, compute, equals);
186
+ this.batcher = batcher;
173
187
  this.writeFn = write;
174
188
  }
175
189
  write(value) {
176
190
  if (this.equals(value)) return;
177
- this.writeFn(value);
191
+ batch(() => this.writeFn(value), this.batcher);
178
192
  }
179
193
  };
180
194
 
195
+ // src/internal/effect.ts
196
+ function effect2(cb) {
197
+ let cleanupFn = null;
198
+ let dependencies = effect2.collector().collect(() => cleanupFn = cb(true) ?? null);
199
+ dependencies.forEach((dependency) => dependency.subscribe(callback));
200
+ function callback() {
201
+ if (cleanupFn) cleanupFn(false);
202
+ const next = effect2.collector().collect(() => cleanupFn = cb(false) ?? null);
203
+ next.forEach((dependency) => !dependencies.has(dependency) && dependency.subscribe(callback));
204
+ dependencies.forEach((dependency) => !next.has(dependency) && dependency.unsubscribe(callback));
205
+ dependencies = next;
206
+ }
207
+ return () => {
208
+ dependencies.forEach((dependency) => dependency.unsubscribe(callback));
209
+ dependencies.clear();
210
+ if (cleanupFn) cleanupFn(true);
211
+ cleanupFn = null;
212
+ };
213
+ }
214
+ effect2.collector = factory("effect.collector");
215
+
216
+ // src/internal/ignore.ts
217
+ function ignore2(callback, ...args) {
218
+ let value;
219
+ ignore2.collector().ignore(() => value = typeof callback === "function" ? callback(...args) : callback.read());
220
+ return value;
221
+ }
222
+ ignore2.collector = factory("signal.collector");
223
+
181
224
  // src/internal/signal.ts
182
225
  function signal2(value, equals) {
183
- return new Signal(value, equals, /* @__PURE__ */ new Set(), signal2.collector());
226
+ return new Signal(value, equals, /* @__PURE__ */ new Set(), signal2.batcher(), signal2.collector());
184
227
  }
228
+ signal2.batcher = factory("signal.batcher");
185
229
  signal2.collector = factory("signal.collector");
186
230
  var Signal = class {
187
231
  value;
188
232
  equalsFn;
189
233
  listeners;
234
+ batcher;
190
235
  collector;
191
- constructor(value, equals, listeners, collector3) {
236
+ constructor(value, equals, listeners, batcher, collector3) {
192
237
  this.value = value;
193
238
  this.equalsFn = equals;
194
239
  this.listeners = listeners;
240
+ this.batcher = batcher;
195
241
  this.collector = collector3;
196
242
  }
197
243
  read() {
198
- if (this.collector) this.collector.add(this);
244
+ this.collector.add(this);
199
245
  return this.value;
200
246
  }
201
247
  write(value) {
202
248
  if (this.equals(value)) return;
203
249
  this.value = value;
204
- this.listeners.forEach((listener) => listener());
250
+ if (this.batcher.collecting()) this.listeners.forEach((listener) => this.batcher.add(listener));
251
+ else this.listeners.forEach((listener) => listener());
205
252
  }
206
253
  equals(other) {
207
254
  if (this.equalsFn) return this.equalsFn(this.value, other);
@@ -209,37 +256,59 @@ var Signal = class {
209
256
  }
210
257
  subscribe(callback) {
211
258
  this.listeners.add(callback);
212
- return () => this.unsubscribe(callback);
259
+ return this.unsubscribe.bind(this, callback);
213
260
  }
214
261
  unsubscribe(callback) {
215
262
  this.listeners.delete(callback);
216
263
  }
217
264
  };
218
265
 
219
- // src/index.ts
266
+ // src/core/config.ts
220
267
  function config(config2 = {}) {
221
- signal.factory(config2.signal);
222
268
  collector.factory(config2.collector);
269
+ signal.factory(config2.signal);
223
270
  computed.factory(config2.computed);
224
271
  composed.factory(config2.composed);
272
+ effect.factory(config2.effect);
273
+ batch.factory(config2.batch);
274
+ ignore.factory(config2.ignore);
225
275
  }
226
- var __shared__ = null;
227
- function shared() {
228
- if (!__shared__) __shared__ = collector();
229
- return __shared__;
276
+
277
+ // src/index.ts
278
+ var __collector__ = null;
279
+ function shared_collector() {
280
+ if (!__collector__) __collector__ = collector();
281
+ return __collector__;
230
282
  }
231
- signal2.collector.default(shared);
232
- computed2.collector.default(shared);
233
- composed2.collector.default(shared);
234
- signal.default(signal2);
283
+ signal2.collector.default(shared_collector);
284
+ computed2.collector.default(shared_collector);
285
+ composed2.collector.default(shared_collector);
286
+ effect2.collector.default(shared_collector);
287
+ ignore2.collector.default(shared_collector);
288
+ var __batcher__ = null;
289
+ function shared_batcher() {
290
+ if (!__batcher__) __batcher__ = collector();
291
+ return __batcher__;
292
+ }
293
+ signal2.batcher.default(shared_batcher);
294
+ composed2.batcher.default(shared_batcher);
295
+ batch2.collector.default(shared_batcher);
235
296
  collector.default(collector2);
297
+ signal.default(signal2);
236
298
  computed.default(computed2);
237
299
  composed.default(composed2);
300
+ effect.default(effect2);
301
+ batch.default(batch2);
302
+ ignore.default(ignore2);
238
303
  export {
304
+ batch,
239
305
  collector,
240
306
  composed,
241
307
  computed,
242
308
  config,
309
+ effect,
310
+ factory,
311
+ ignore,
243
312
  internal_exports as internal,
244
313
  signal
245
314
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@valentin30/signal",
3
- "version": "0.0.2",
4
- "description": "",
3
+ "version": "0.0.4",
4
+ "description": "My take on signals - lightweight reactive primitives inspired by Preact Signals, written in TypeScript.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -11,6 +11,7 @@
11
11
  "scripts": {
12
12
  "clean": "rimraf dist",
13
13
  "build": "npm run clean && tsup",
14
+ "publish": "npm run build && npm publish --access public",
14
15
  "dev": "tsup --watch",
15
16
  "test": "vitest run",
16
17
  "test:watch": "vitest"