@oscarpalmer/mora 0.22.0 → 0.23.0

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 (43) hide show
  1. package/dist/batch.js +8 -9
  2. package/dist/constants.js +34 -0
  3. package/dist/effect.js +7 -8
  4. package/dist/helpers/is.js +8 -18
  5. package/dist/helpers/proxy.js +3 -2
  6. package/dist/helpers/value.js +7 -8
  7. package/dist/index.js +1 -1
  8. package/dist/models.js +0 -0
  9. package/dist/mora.full.js +218 -130
  10. package/dist/subscription.js +7 -5
  11. package/dist/value/array.js +24 -24
  12. package/dist/value/computed.js +18 -21
  13. package/dist/value/signal.js +2 -2
  14. package/dist/value/store.js +8 -2
  15. package/package.json +9 -10
  16. package/src/batch.ts +11 -13
  17. package/src/constants.ts +49 -0
  18. package/src/effect.ts +11 -16
  19. package/src/helpers/is.ts +41 -19
  20. package/src/helpers/proxy.ts +34 -38
  21. package/src/helpers/value.ts +19 -14
  22. package/src/index.ts +1 -0
  23. package/src/models.ts +66 -0
  24. package/src/subscription.ts +14 -16
  25. package/src/value/array.ts +86 -44
  26. package/src/value/computed.ts +29 -39
  27. package/src/value/reactive.ts +9 -24
  28. package/src/value/signal.ts +9 -3
  29. package/src/value/store.ts +40 -9
  30. package/types/batch.d.ts +3 -5
  31. package/types/constants.d.ts +14 -0
  32. package/types/effect.d.ts +2 -1
  33. package/types/helpers/is.d.ts +23 -10
  34. package/types/helpers/proxy.d.ts +2 -3
  35. package/types/helpers/value.d.ts +1 -1
  36. package/types/index.d.ts +1 -0
  37. package/types/models.d.ts +56 -0
  38. package/types/subscription.d.ts +3 -6
  39. package/types/value/array.d.ts +48 -7
  40. package/types/value/computed.d.ts +2 -11
  41. package/types/value/reactive.d.ts +8 -17
  42. package/types/value/signal.d.ts +7 -1
  43. package/types/value/store.d.ts +28 -4
package/src/models.ts ADDED
@@ -0,0 +1,66 @@
1
+ import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
+ import type {Effect} from './effect';
3
+ import type {Subscription} from './subscription';
4
+ import type {Computed} from './value/computed';
5
+ import type {Signal} from './value/signal';
6
+
7
+ export type Active = {
8
+ computed?: Computed<unknown>;
9
+ effect?: Effect;
10
+ };
11
+
12
+ export type Batch = {
13
+ depth: number;
14
+ handlers: Set<Effect | Subscription>;
15
+ };
16
+
17
+ export type ComputedEffect = {
18
+ dirty: boolean;
19
+ instance: Effect;
20
+ };
21
+
22
+ export type EffectState = {
23
+ callback: GenericCallback;
24
+ };
25
+
26
+ export type InternalComputed = {
27
+ readonly effect: ComputedEffect;
28
+ readonly state: ReactiveState<unknown, unknown>;
29
+ };
30
+
31
+ export type InternalEffect = {
32
+ state: EffectState;
33
+ };
34
+
35
+ export type ReactiveOptions<Value> = {
36
+ /**
37
+ * Method for comparing values for equality
38
+ * @param first First value
39
+ * @param second Second value
40
+ * @returns Are the values equal?
41
+ * @default Object.is
42
+ */
43
+ equal?: (first: Value, second: Value) => boolean;
44
+ };
45
+
46
+ export type ReactiveState<Value, Equal> = {
47
+ computeds: Set<Computed<unknown>>;
48
+ effects: Set<Effect>;
49
+ equal: (first: Equal, second: Equal) => boolean;
50
+ subscriptions: Map<GenericCallback, Subscription>;
51
+ value: Value;
52
+ };
53
+
54
+ export type SetValueInProxyParameters<Value, Equal> = {
55
+ target: Value;
56
+ property: PropertyKey;
57
+ value: unknown;
58
+ state: ReactiveState<Value, Equal>;
59
+ isArray: boolean;
60
+ length?: Signal<number>;
61
+ };
62
+
63
+ /**
64
+ * Unsubscribe from changes
65
+ */
66
+ export type Unsubscribe = () => void;
@@ -1,19 +1,22 @@
1
1
  import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
- import type {ReactiveState} from './value/reactive';
2
+ import type {ReactiveState, Unsubscribe} from './models';
3
3
 
4
4
  export class Subscription {
5
- constructor(
6
- public state: ReactiveState<unknown, never>,
7
- public callback: GenericCallback,
8
- ) {
5
+ callback: GenericCallback;
6
+ state: ReactiveState<unknown, never>;
7
+
8
+ constructor(state: ReactiveState<unknown, never>, callback: GenericCallback) {
9
+ this.state = state;
10
+ this.callback = callback;
11
+
9
12
  callback(state.value);
10
13
  }
11
- }
12
14
 
13
- /**
14
- * Unsubscribe from changes
15
- */
16
- export type Unsubscribe = () => void;
15
+ destroy(): void {
16
+ this.callback = noop;
17
+ this.state = undefined as never;
18
+ }
19
+ }
17
20
 
18
21
  export function noop(): void {}
19
22
 
@@ -36,12 +39,7 @@ export function unsubscribe<Value>(
36
39
  state: ReactiveState<Value, never>,
37
40
  callback: (value: Value) => void,
38
41
  ): void {
39
- const subscription = state.subscriptions.get(callback);
42
+ state.subscriptions.get(callback)?.destroy();
40
43
 
41
44
  state.subscriptions.delete(callback);
42
-
43
- if (subscription != null) {
44
- subscription.callback = noop;
45
- subscription.state = undefined as never;
46
- }
47
45
  }
@@ -1,15 +1,21 @@
1
1
  import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
- import {arrayName} from '../helpers/is';
2
+ import {
3
+ METHODS_AFFECTING_LENGTH,
4
+ METHODS_UPDATE,
5
+ NAME_ARRAY,
6
+ } from '../constants';
3
7
  import {getReactiveValueInProxy, setValueInProxy} from '../helpers/proxy';
4
8
  import {emitValue, equalArrays, getValue} from '../helpers/value';
5
- import {type Unsubscribe, noop, subscribe} from '../subscription';
9
+ import type {ReactiveOptions, ReactiveState, Unsubscribe} from '../models';
10
+ import {noop, subscribe} from '../subscription';
6
11
  import {type Computed, computed} from './computed';
7
- import {Reactive, type ReactiveOptions, type ReactiveState} from './reactive';
12
+ import {Reactive} from './reactive';
8
13
  import {type Signal, signal} from './signal';
9
14
 
10
15
  export class ReactiveArray<Item> extends Reactive<Item[], Item> {
11
- #indiced = new Map<number, Computed<unknown>>();
12
- #size = signal(0);
16
+ readonly #indiced = new Map<number, Computed<unknown>>();
17
+
18
+ readonly #size = signal(0);
13
19
 
14
20
  /**
15
21
  * The length of the array
@@ -33,21 +39,21 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
33
39
 
34
40
  constructor(value: Item[], options?: ReactiveOptions<Item>) {
35
41
  super(
36
- arrayName,
42
+ NAME_ARRAY,
37
43
  new Proxy(value, {
38
- get: (target, property) =>
39
- updateMethods.has(property as string)
44
+ get: (target: Item[], property: PropertyKey) =>
45
+ METHODS_UPDATE.has(property as string)
40
46
  ? updateArray(property as string, target, this.state, this.#size)
41
47
  : Reflect.get(target, property),
42
- set: (target, property, value) =>
43
- setValueInProxy(
44
- target,
48
+ set: (target: Item[], property: PropertyKey, value: Item) =>
49
+ setValueInProxy({
45
50
  property,
51
+ target,
46
52
  value,
47
- this.state,
48
- true,
49
- this.#size,
50
- ),
53
+ isArray: true,
54
+ state: this.state,
55
+ length: this.#size,
56
+ }),
51
57
  }),
52
58
  options,
53
59
  );
@@ -62,6 +68,17 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
62
68
  this.length = 0;
63
69
  }
64
70
 
71
+ /**
72
+ * Create a computed, filtered array
73
+ * @param callback Callback to evaluate each item
74
+ * @return Computed array of filtered items
75
+ */
76
+ filter(
77
+ callback: (item: Item, index: number, array: Item[]) => boolean,
78
+ ): Computed<Item[]> {
79
+ return computed(() => this.get().filter(callback));
80
+ }
81
+
65
82
  /**
66
83
  * @inheritdoc
67
84
  */
@@ -69,11 +86,14 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
69
86
 
70
87
  /**
71
88
  * Get the value at an index
89
+ * @param index Index of item to get _(if negative, starts from the end)_
90
+ * @returns Item at index, or `undefined` if it doesn't exist
72
91
  */
73
92
  get(index: number): Item | undefined;
74
93
 
75
94
  /**
76
95
  * Get the length of the array
96
+ * @returns Length of the array
77
97
  */
78
98
  get(property: 'length'): number;
79
99
 
@@ -89,17 +109,10 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
89
109
  return getValue(this.state);
90
110
  }
91
111
 
92
- /**
93
- * Create a computed, filtered array
94
- */
95
- filter(
96
- callback: (item: Item, index: number, array: Item[]) => boolean,
97
- ): Computed<Item[]> {
98
- return computed(() => this.get().filter(callback));
99
- }
100
-
101
112
  /**
102
113
  * Create a computed, mapped array
114
+ * @param callback Callback to transform each item
115
+ * @return Computed array of mapped items
103
116
  */
104
117
  map<Mapped>(
105
118
  callback: (item: Item, index: number, array: Item[]) => Mapped,
@@ -107,20 +120,36 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
107
120
  return computed(() => this.get().map(callback));
108
121
  }
109
122
 
123
+ /**
124
+ * Notify dependents of changes
125
+ *
126
+ * _This bypasses equality checks and will immediately notify dependents.
127
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
128
+ */
129
+ notify(): void {
130
+ emitValue(this.state);
131
+ }
132
+
110
133
  /**
111
134
  * @inheritdoc
112
135
  */
113
136
  peek(): Item[];
114
137
 
138
+ /**
139
+ * Get the value at an index _(without reactivity)_
140
+ * @param index Index of item to get _(if negative, starts from the end)_
141
+ * @returns Item at index, or `undefined` if it doesn't exist
142
+ */
115
143
  peek(index: number): Item | undefined;
116
144
 
117
145
  /**
118
146
  * Get the length of the array _(without reactivity)_
147
+ * @returns Length of the array
119
148
  */
120
- peek(length: true): number;
149
+ peek(property: 'length'): number;
121
150
 
122
151
  peek(value?: unknown): unknown {
123
- if (value === true) {
152
+ if (value === 'length') {
124
153
  return this.#size.peek();
125
154
  }
126
155
 
@@ -133,6 +162,7 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
133
162
 
134
163
  /**
135
164
  * Remove and return the last item of the array
165
+ * @returns Removed item, or `undefined` if the array is empty
136
166
  */
137
167
  pop(): Item | undefined {
138
168
  return this.state.value.pop();
@@ -140,6 +170,8 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
140
170
 
141
171
  /**
142
172
  * Add items to the end of the array
173
+ * @param items Items to add
174
+ * @returns New array length
143
175
  */
144
176
  push(...items: Item[]): number {
145
177
  return this.state.value.push(...items);
@@ -147,16 +179,20 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
147
179
 
148
180
  /**
149
181
  * Set the value
182
+ * @param value New array of items _(defaults to an empty array)_
150
183
  */
151
184
  set(value?: Item[]): void;
152
185
 
153
186
  /**
154
187
  * Set the value at an index
188
+ * @param index Index of item to set __(if negative, starts from the end)_
189
+ * @param value New item
155
190
  */
156
191
  set(index: number, value: Item): void;
157
192
 
158
193
  /**
159
194
  * Set the length of the array
195
+ * @param value New array length
160
196
  */
161
197
  set(property: 'length', value: number): void;
162
198
 
@@ -165,13 +201,14 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
165
201
  this.state.value.splice(0, this.state.value.length, ...(first ?? []));
166
202
  } else if (first === 'length') {
167
203
  this.length = second as number;
168
- } else if (typeof first === 'number') {
169
- this.state.value[first] = second as Item;
204
+ } else if (typeof first === 'number' && !Number.isNaN(first)) {
205
+ setAtIndex(this.state.value, first, second as Item);
170
206
  }
171
207
  }
172
208
 
173
209
  /**
174
210
  * Remove and return the first item of the array
211
+ * @returns Removed item, or `undefined` if the array is empty
175
212
  */
176
213
  shift(): Item | undefined {
177
214
  return this.state.value.shift();
@@ -179,6 +216,10 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
179
216
 
180
217
  /**
181
218
  * Remove and return items from the array _(and optionally add new items)_
219
+ * @param from Index to start removing items from
220
+ * @param to Index to stop removing items at _(defaults to the end of the array)_
221
+ * @param items Optional items to add
222
+ * @returns Removed items
182
223
  */
183
224
  splice(from: number, to?: number, ...items: Item[]): Item[] {
184
225
  return this.state.value.splice(
@@ -195,6 +236,9 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
195
236
 
196
237
  /**
197
238
  * Subscribe to changes at a specific index
239
+ * @param index Index of item to subscribe to
240
+ * @param callback Callback for changes
241
+ * @returns Unsubscribe callback
198
242
  */
199
243
  subscribe(
200
244
  index: number,
@@ -219,6 +263,8 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
219
263
 
220
264
  /**
221
265
  * Add items to the beginning of the array
266
+ * @param items Items to add
267
+ * @returns New array length
222
268
  */
223
269
  unshift(...items: Item[]): number {
224
270
  return this.state.value.unshift(...items);
@@ -226,6 +272,7 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
226
272
 
227
273
  /**
228
274
  * Update the value _(based on the current value)_
275
+ * @param callback Callback to update the value
229
276
  */
230
277
  update(callback: (value: Item[]) => Item[]): void {
231
278
  const updated = callback(this.state.value);
@@ -238,6 +285,9 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
238
285
 
239
286
  /**
240
287
  * Create a reactive array
288
+ * @param value Initial array of items
289
+ * @param options Optional reactivity options
290
+ * @returns Reactive array
241
291
  */
242
292
  export function array<Item>(
243
293
  value: Item[],
@@ -252,7 +302,7 @@ function updateArray<Item>(
252
302
  state: ReactiveState<Item[], Item>,
253
303
  length: Signal<number>,
254
304
  ): unknown {
255
- const affectsLength = lengthAffectingMethods.has(type);
305
+ const affectsLength = METHODS_AFFECTING_LENGTH.has(type);
256
306
  const previousArray = affectsLength ? [] : [...array];
257
307
  const previousLength = array.length;
258
308
 
@@ -275,18 +325,10 @@ function updateArray<Item>(
275
325
  };
276
326
  }
277
327
 
278
- const lengthAffectingMethods = new Set<string>([
279
- 'pop',
280
- 'push',
281
- 'shift',
282
- 'unshift',
283
- ]);
284
-
285
- const updateMethods = new Set<string>([
286
- ...lengthAffectingMethods,
287
- 'copyWithin',
288
- 'fill',
289
- 'reverse',
290
- 'sort',
291
- 'splice',
292
- ]);
328
+ function setAtIndex<Item>(array: Item[], index: number, value: Item): void {
329
+ const actual = index < 0 ? array.length + index : index;
330
+
331
+ if (actual > -1) {
332
+ array[actual] = value;
333
+ }
334
+ }
@@ -1,19 +1,7 @@
1
- import {batchDepth, batchedHandlers} from '../batch';
2
- import {type Effect, activeEffect, effect, runEffect} from '../effect';
3
- import {computedName} from '../helpers/is';
4
- import {Reactive, type ReactiveOptions, type ReactiveState} from './reactive';
5
-
6
- export type ComputedEffect = {
7
- dirty: boolean;
8
- instance: Effect;
9
- };
10
-
11
- export type InternalComputed = {
12
- readonly effect: ComputedEffect;
13
- readonly state: ReactiveState<unknown, unknown>;
14
- };
15
-
16
- export let activeComputed: Computed<unknown> | undefined;
1
+ import {ACTIVE, BATCH, NAME_COMPUTED} from '../constants';
2
+ import {effect, runEffect} from '../effect';
3
+ import type {ComputedEffect, ReactiveOptions} from '../models';
4
+ import {Reactive} from './reactive';
17
5
 
18
6
  export class Computed<Value> extends Reactive<Value> {
19
7
  private readonly effect: ComputedEffect = {
@@ -22,36 +10,38 @@ export class Computed<Value> extends Reactive<Value> {
22
10
  };
23
11
 
24
12
  constructor(callback: () => Value, options?: ReactiveOptions<Value>) {
25
- super(computedName, undefined as never, options);
13
+ super(NAME_COMPUTED, undefined as never, options);
26
14
 
27
15
  this.effect.instance = effect(() => {
28
- if (this.effect.dirty) {
29
- const previousComputed = activeComputed;
16
+ if (!this.effect.dirty) {
17
+ return;
18
+ }
30
19
 
31
- activeComputed = this as never;
20
+ const previousComputed = ACTIVE.computed;
32
21
 
33
- const value = callback();
22
+ ACTIVE.computed = this as never;
34
23
 
35
- activeComputed = previousComputed;
24
+ const value = callback();
36
25
 
37
- if (!this.state.equal(this.state.value, value)) {
38
- this.state.value = value;
26
+ ACTIVE.computed = previousComputed;
39
27
 
40
- for (const computed of this.state.computeds) {
41
- computed.effect.dirty = true;
42
- }
28
+ if (!this.state.equal(this.state.value, value)) {
29
+ this.state.value = value;
43
30
 
44
- for (const effect of this.state.effects) {
45
- batchedHandlers.add(effect);
46
- }
31
+ for (const computed of this.state.computeds) {
32
+ computed.effect.dirty = true;
33
+ }
47
34
 
48
- for (const [, subscription] of this.state.subscriptions) {
49
- subscription.callback(value);
50
- }
35
+ for (const effect of this.state.effects) {
36
+ BATCH.handlers.add(effect);
51
37
  }
52
38
 
53
- this.effect.dirty = false;
39
+ for (const [, subscription] of this.state.subscriptions) {
40
+ subscription.callback(value);
41
+ }
54
42
  }
43
+
44
+ this.effect.dirty = false;
55
45
  });
56
46
  }
57
47
 
@@ -59,15 +49,15 @@ export class Computed<Value> extends Reactive<Value> {
59
49
  * @inheritdoc
60
50
  */
61
51
  get(): Value {
62
- if (activeComputed != null && this !== activeComputed) {
63
- this.state.computeds.add(activeComputed);
52
+ if (ACTIVE.computed != null && this !== ACTIVE.computed) {
53
+ this.state.computeds.add(ACTIVE.computed);
64
54
  }
65
55
 
66
- if (activeEffect != null && activeEffect !== this.effect.instance) {
67
- this.state.effects.add(activeEffect);
56
+ if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) {
57
+ this.state.effects.add(ACTIVE.effect);
68
58
  }
69
59
 
70
- if (this.effect.dirty && batchDepth === 0) {
60
+ if (this.effect.dirty && BATCH.depth === 0) {
71
61
  runEffect(this.effect.instance);
72
62
  }
73
63
 
@@ -1,12 +1,5 @@
1
- import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
- import type {Effect} from '../effect';
3
- import {
4
- type Subscription,
5
- type Unsubscribe,
6
- subscribe,
7
- unsubscribe,
8
- } from '../subscription';
9
- import type {Computed} from './computed';
1
+ import type {ReactiveOptions, ReactiveState, Unsubscribe} from '../models';
2
+ import {subscribe, unsubscribe} from '../subscription';
10
3
 
11
4
  export abstract class Reactive<Value, Equal = Value> {
12
5
  protected readonly state: ReactiveState<Value, Equal> = {
@@ -31,11 +24,13 @@ export abstract class Reactive<Value, Equal = Value> {
31
24
 
32
25
  /**
33
26
  * Get the value
27
+ * @return Current value
34
28
  */
35
29
  abstract get(): Value;
36
30
 
37
31
  /**
38
32
  * Get the value _(without reactivity)_
33
+ * @return Current value
39
34
  */
40
35
  peek(): Value {
41
36
  return this.state.value;
@@ -43,6 +38,8 @@ export abstract class Reactive<Value, Equal = Value> {
43
38
 
44
39
  /**
45
40
  * Subscribe to changes
41
+ * @param callback Callback for changes
42
+ * @return Unsubscribe callback
46
43
  */
47
44
  subscribe(callback: (value: Value) => void): Unsubscribe {
48
45
  return subscribe(this.state, callback);
@@ -50,6 +47,7 @@ export abstract class Reactive<Value, Equal = Value> {
50
47
 
51
48
  /**
52
49
  * JSON representation of the value
50
+ * @return JSON value
53
51
  */
54
52
  toJSON(): Value {
55
53
  return this.get();
@@ -57,6 +55,7 @@ export abstract class Reactive<Value, Equal = Value> {
57
55
 
58
56
  /**
59
57
  * String representation of the value
58
+ * @return Value as string
60
59
  */
61
60
  toString(): string {
62
61
  return String(this.get());
@@ -64,23 +63,9 @@ export abstract class Reactive<Value, Equal = Value> {
64
63
 
65
64
  /**
66
65
  * Unsubscribe from changes
66
+ * @param callback Callback to unsubscribe
67
67
  */
68
68
  unsubscribe(callback: (value: Value) => void): void {
69
69
  unsubscribe(this.state, callback);
70
70
  }
71
71
  }
72
-
73
- export type ReactiveOptions<Value> = {
74
- /**
75
- * Method to compare values for equality
76
- */
77
- equal?: (first: Value, second: Value) => boolean;
78
- };
79
-
80
- export type ReactiveState<Value, Equal> = {
81
- computeds: Set<Computed<unknown>>;
82
- effects: Set<Effect>;
83
- equal: (first: Equal, second: Equal) => boolean;
84
- subscriptions: Map<GenericCallback, Subscription>;
85
- value: Value;
86
- };
@@ -1,10 +1,11 @@
1
- import {signalName} from '../helpers/is';
1
+ import {NAME_SIGNAL} from '../constants';
2
2
  import {emitValue, getValue} from '../helpers/value';
3
- import {Reactive, type ReactiveOptions} from './reactive';
3
+ import type {ReactiveOptions} from '../models';
4
+ import {Reactive} from './reactive';
4
5
 
5
6
  export class Signal<Value> extends Reactive<Value> {
6
7
  constructor(value: Value, options?: ReactiveOptions<Value>) {
7
- super(signalName, value, options);
8
+ super(NAME_SIGNAL, value, options);
8
9
  }
9
10
 
10
11
  /**
@@ -16,6 +17,7 @@ export class Signal<Value> extends Reactive<Value> {
16
17
 
17
18
  /**
18
19
  * Set the value
20
+ * @param value New value
19
21
  */
20
22
  set(value: Value): void {
21
23
  if (!this.state.equal(this.state.value, value)) {
@@ -27,6 +29,7 @@ export class Signal<Value> extends Reactive<Value> {
27
29
 
28
30
  /**
29
31
  * Update the value _(based on the current value)_
32
+ * @param callback Callback to update the value
30
33
  */
31
34
  update(callback: (value: Value) => Value): void {
32
35
  this.set(callback(this.state.value));
@@ -35,6 +38,9 @@ export class Signal<Value> extends Reactive<Value> {
35
38
 
36
39
  /**
37
40
  * Create a reactive value
41
+ * @param value Initial value
42
+ * @param options Optional reactivity options
43
+ * @returns Reactive value
38
44
  */
39
45
  export function signal<Value>(
40
46
  value: Value,