@oscarpalmer/mora 0.19.0 → 0.20.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.
@@ -12,7 +12,7 @@ function getReactiveValueInProxy(reactive, mapped, key, isArray) {
12
12
  });
13
13
  mapped.set(key, item);
14
14
  }
15
- return item.get();
15
+ return item;
16
16
  }
17
17
  function setProxyValue(proxy, value) {
18
18
  batch.startBatch();
@@ -10,7 +10,7 @@ function getReactiveValueInProxy(reactive, mapped, key, isArray) {
10
10
  });
11
11
  mapped.set(key, item);
12
12
  }
13
- return item.get();
13
+ return item;
14
14
  }
15
15
  function setProxyValue(proxy, value) {
16
16
  startBatch();
package/dist/mora.full.js CHANGED
@@ -289,7 +289,7 @@ function getReactiveValueInProxy(reactive, mapped, key, isArray) {
289
289
  });
290
290
  mapped.set(key, item);
291
291
  }
292
- return item.get();
292
+ return item;
293
293
  }
294
294
  function setProxyValue(proxy, value) {
295
295
  startBatch();
@@ -351,7 +351,7 @@ class Signal extends Reactive {
351
351
  }
352
352
  }
353
353
  /**
354
- * Update the value
354
+ * Update the value _(based on the current value)_
355
355
  */
356
356
  update(callback) {
357
357
  this.set(callback(this.state.value));
@@ -400,7 +400,7 @@ class ReactiveArray extends Reactive {
400
400
  }
401
401
  get(first) {
402
402
  if (typeof first === 'number') {
403
- return getReactiveValueInProxy(this, this.#indiced, first, true);
403
+ return getReactiveValueInProxy(this, this.#indiced, first, true).get();
404
404
  }
405
405
  if (first === 'length') {
406
406
  return this.length;
@@ -435,8 +435,8 @@ class ReactiveArray extends Reactive {
435
435
  return this.state.value.push(...items);
436
436
  }
437
437
  set(first, second) {
438
- if (Array.isArray(first)) {
439
- this.state.value.splice(0, this.state.value.length, ...first);
438
+ if (first == null || Array.isArray(first)) {
439
+ this.state.value.splice(0, this.state.value.length, ...(first ?? []));
440
440
  }
441
441
  else if (first === 'length') {
442
442
  this.length = second;
@@ -457,12 +457,27 @@ class ReactiveArray extends Reactive {
457
457
  splice(from, to, ...items) {
458
458
  return this.state.value.splice(from, to ?? this.state.value.length, ...items);
459
459
  }
460
+ subscribe(first, second) {
461
+ if (typeof first === 'number' && typeof second === 'function') {
462
+ return getReactiveValueInProxy(this, this.#indiced, first, true).subscribe(second);
463
+ }
464
+ return typeof first === 'function' ? subscribe(this.state, first) : noop;
465
+ }
460
466
  /**
461
467
  * Add items to the beginning of the array
462
468
  */
463
469
  unshift(...items) {
464
470
  return this.state.value.unshift(...items);
465
471
  }
472
+ /**
473
+ * Update the value _(based on the current value)_
474
+ */
475
+ update(callback) {
476
+ const updated = callback(this.state.value);
477
+ if (updated == null || Array.isArray(updated)) {
478
+ this.set(updated);
479
+ }
480
+ }
466
481
  }
467
482
  /**
468
483
  * Create a reactive array
@@ -523,7 +538,7 @@ class Store extends Reactive {
523
538
  }
524
539
  get(key) {
525
540
  return isKey(key)
526
- ? getReactiveValueInProxy(this, this.#keyed, key, false)
541
+ ? getReactiveValueInProxy(this, this.#keyed, key, false).get()
527
542
  : getValue(this.state);
528
543
  }
529
544
  peek(key) {
@@ -537,6 +552,21 @@ class Store extends Reactive {
537
552
  setProxyValue(this.state.value, first ?? {});
538
553
  }
539
554
  }
555
+ subscribe(first, second) {
556
+ if (isKey(first) && typeof second === 'function') {
557
+ return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
558
+ }
559
+ return typeof first === 'function' ? subscribe(this.state, first) : noop;
560
+ }
561
+ /**
562
+ * Update the value _(based on the current value)_
563
+ */
564
+ update(callback) {
565
+ const updated = callback({ ...this.state.value });
566
+ if (updated == null || isPlainObject(updated)) {
567
+ setProxyValue(this.state.value, updated ?? {});
568
+ }
569
+ }
540
570
  }
541
571
  /**
542
572
  * Create a reactive store
@@ -10,6 +10,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
10
10
  const helpers_is = require("../helpers/is.cjs");
11
11
  const helpers_proxy = require("../helpers/proxy.cjs");
12
12
  const helpers_value = require("../helpers/value.cjs");
13
+ const subscription = require("../subscription.cjs");
13
14
  const value_computed = require("./computed.cjs");
14
15
  const value_reactive = require("./reactive.cjs");
15
16
  const value_signal = require("./signal.cjs");
@@ -56,7 +57,7 @@ class ReactiveArray extends value_reactive.Reactive {
56
57
  }
57
58
  get(first) {
58
59
  if (typeof first === "number") {
59
- return helpers_proxy.getReactiveValueInProxy(this, __privateGet(this, _indiced), first, true);
60
+ return helpers_proxy.getReactiveValueInProxy(this, __privateGet(this, _indiced), first, true).get();
60
61
  }
61
62
  if (first === "length") {
62
63
  return this.length;
@@ -91,8 +92,8 @@ class ReactiveArray extends value_reactive.Reactive {
91
92
  return this.state.value.push(...items);
92
93
  }
93
94
  set(first, second) {
94
- if (Array.isArray(first)) {
95
- this.state.value.splice(0, this.state.value.length, ...first);
95
+ if (first == null || Array.isArray(first)) {
96
+ this.state.value.splice(0, this.state.value.length, ...first ?? []);
96
97
  } else if (first === "length") {
97
98
  this.length = second;
98
99
  } else if (typeof first === "number") {
@@ -115,12 +116,32 @@ class ReactiveArray extends value_reactive.Reactive {
115
116
  ...items
116
117
  );
117
118
  }
119
+ subscribe(first, second) {
120
+ if (typeof first === "number" && typeof second === "function") {
121
+ return helpers_proxy.getReactiveValueInProxy(
122
+ this,
123
+ __privateGet(this, _indiced),
124
+ first,
125
+ true
126
+ ).subscribe(second);
127
+ }
128
+ return typeof first === "function" ? subscription.subscribe(this.state, first) : subscription.noop;
129
+ }
118
130
  /**
119
131
  * Add items to the beginning of the array
120
132
  */
121
133
  unshift(...items) {
122
134
  return this.state.value.unshift(...items);
123
135
  }
136
+ /**
137
+ * Update the value _(based on the current value)_
138
+ */
139
+ update(callback) {
140
+ const updated = callback(this.state.value);
141
+ if (updated == null || Array.isArray(updated)) {
142
+ this.set(updated);
143
+ }
144
+ }
124
145
  }
125
146
  _indiced = new WeakMap();
126
147
  _size = new WeakMap();
@@ -8,6 +8,7 @@ var _indiced, _size;
8
8
  import { arrayName } from "../helpers/is.js";
9
9
  import { setValueInProxy, getReactiveValueInProxy } from "../helpers/proxy.js";
10
10
  import { getValue, equalArrays, emitValue } from "../helpers/value.js";
11
+ import { subscribe, noop } from "../subscription.js";
11
12
  import { computed } from "./computed.js";
12
13
  import { Reactive } from "./reactive.js";
13
14
  import { signal } from "./signal.js";
@@ -54,7 +55,7 @@ class ReactiveArray extends Reactive {
54
55
  }
55
56
  get(first) {
56
57
  if (typeof first === "number") {
57
- return getReactiveValueInProxy(this, __privateGet(this, _indiced), first, true);
58
+ return getReactiveValueInProxy(this, __privateGet(this, _indiced), first, true).get();
58
59
  }
59
60
  if (first === "length") {
60
61
  return this.length;
@@ -89,8 +90,8 @@ class ReactiveArray extends Reactive {
89
90
  return this.state.value.push(...items);
90
91
  }
91
92
  set(first, second) {
92
- if (Array.isArray(first)) {
93
- this.state.value.splice(0, this.state.value.length, ...first);
93
+ if (first == null || Array.isArray(first)) {
94
+ this.state.value.splice(0, this.state.value.length, ...first ?? []);
94
95
  } else if (first === "length") {
95
96
  this.length = second;
96
97
  } else if (typeof first === "number") {
@@ -113,12 +114,32 @@ class ReactiveArray extends Reactive {
113
114
  ...items
114
115
  );
115
116
  }
117
+ subscribe(first, second) {
118
+ if (typeof first === "number" && typeof second === "function") {
119
+ return getReactiveValueInProxy(
120
+ this,
121
+ __privateGet(this, _indiced),
122
+ first,
123
+ true
124
+ ).subscribe(second);
125
+ }
126
+ return typeof first === "function" ? subscribe(this.state, first) : noop;
127
+ }
116
128
  /**
117
129
  * Add items to the beginning of the array
118
130
  */
119
131
  unshift(...items) {
120
132
  return this.state.value.unshift(...items);
121
133
  }
134
+ /**
135
+ * Update the value _(based on the current value)_
136
+ */
137
+ update(callback) {
138
+ const updated = callback(this.state.value);
139
+ if (updated == null || Array.isArray(updated)) {
140
+ this.set(updated);
141
+ }
142
+ }
122
143
  }
123
144
  _indiced = new WeakMap();
124
145
  _size = new WeakMap();
@@ -23,7 +23,7 @@ class Signal extends value_reactive.Reactive {
23
23
  }
24
24
  }
25
25
  /**
26
- * Update the value
26
+ * Update the value _(based on the current value)_
27
27
  */
28
28
  update(callback) {
29
29
  this.set(callback(this.state.value));
@@ -21,7 +21,7 @@ class Signal extends Reactive {
21
21
  }
22
22
  }
23
23
  /**
24
- * Update the value
24
+ * Update the value _(based on the current value)_
25
25
  */
26
26
  update(callback) {
27
27
  this.set(callback(this.state.value));
@@ -11,6 +11,7 @@ const is = require("../node_modules/@oscarpalmer/atoms/dist/internal/is.cjs");
11
11
  const helpers_is = require("../helpers/is.cjs");
12
12
  const helpers_proxy = require("../helpers/proxy.cjs");
13
13
  const helpers_value = require("../helpers/value.cjs");
14
+ const subscription = require("../subscription.cjs");
14
15
  const value_reactive = require("./reactive.cjs");
15
16
  class Store extends value_reactive.Reactive {
16
17
  constructor(value, options) {
@@ -24,7 +25,7 @@ class Store extends value_reactive.Reactive {
24
25
  __privateAdd(this, _keyed, /* @__PURE__ */ new Map());
25
26
  }
26
27
  get(key) {
27
- return is.isKey(key) ? helpers_proxy.getReactiveValueInProxy(this, __privateGet(this, _keyed), key, false) : helpers_value.getValue(this.state);
28
+ return is.isKey(key) ? helpers_proxy.getReactiveValueInProxy(this, __privateGet(this, _keyed), key, false).get() : helpers_value.getValue(this.state);
28
29
  }
29
30
  peek(key) {
30
31
  return is.isKey(key) ? this.state.value[key] : { ...this.state.value };
@@ -36,6 +37,23 @@ class Store extends value_reactive.Reactive {
36
37
  helpers_proxy.setProxyValue(this.state.value, first ?? {});
37
38
  }
38
39
  }
40
+ subscribe(first, second) {
41
+ if (is.isKey(first) && typeof second === "function") {
42
+ return helpers_proxy.getReactiveValueInProxy(this, __privateGet(this, _keyed), first, false).subscribe(
43
+ second
44
+ );
45
+ }
46
+ return typeof first === "function" ? subscription.subscribe(this.state, first) : subscription.noop;
47
+ }
48
+ /**
49
+ * Update the value _(based on the current value)_
50
+ */
51
+ update(callback) {
52
+ const updated = callback({ ...this.state.value });
53
+ if (updated == null || is.isPlainObject(updated)) {
54
+ helpers_proxy.setProxyValue(this.state.value, updated ?? {});
55
+ }
56
+ }
39
57
  }
40
58
  _keyed = new WeakMap();
41
59
  function store(value, options) {
@@ -9,6 +9,7 @@ import { isPlainObject, isKey } from "../node_modules/@oscarpalmer/atoms/dist/in
9
9
  import { storeName } from "../helpers/is.js";
10
10
  import { setValueInProxy, getReactiveValueInProxy, setProxyValue } from "../helpers/proxy.js";
11
11
  import { getValue } from "../helpers/value.js";
12
+ import { subscribe, noop } from "../subscription.js";
12
13
  import { Reactive } from "./reactive.js";
13
14
  class Store extends Reactive {
14
15
  constructor(value, options) {
@@ -22,7 +23,7 @@ class Store extends Reactive {
22
23
  __privateAdd(this, _keyed, /* @__PURE__ */ new Map());
23
24
  }
24
25
  get(key) {
25
- return isKey(key) ? getReactiveValueInProxy(this, __privateGet(this, _keyed), key, false) : getValue(this.state);
26
+ return isKey(key) ? getReactiveValueInProxy(this, __privateGet(this, _keyed), key, false).get() : getValue(this.state);
26
27
  }
27
28
  peek(key) {
28
29
  return isKey(key) ? this.state.value[key] : { ...this.state.value };
@@ -34,6 +35,23 @@ class Store extends Reactive {
34
35
  setProxyValue(this.state.value, first ?? {});
35
36
  }
36
37
  }
38
+ subscribe(first, second) {
39
+ if (isKey(first) && typeof second === "function") {
40
+ return getReactiveValueInProxy(this, __privateGet(this, _keyed), first, false).subscribe(
41
+ second
42
+ );
43
+ }
44
+ return typeof first === "function" ? subscribe(this.state, first) : noop;
45
+ }
46
+ /**
47
+ * Update the value _(based on the current value)_
48
+ */
49
+ update(callback) {
50
+ const updated = callback({ ...this.state.value });
51
+ if (updated == null || isPlainObject(updated)) {
52
+ setProxyValue(this.state.value, updated ?? {});
53
+ }
54
+ }
37
55
  }
38
56
  _keyed = new WeakMap();
39
57
  function store(value, options) {
package/package.json CHANGED
@@ -4,14 +4,14 @@
4
4
  "url": "https://oscarpalmer.se"
5
5
  },
6
6
  "dependencies": {
7
- "@oscarpalmer/atoms": "^0.100"
7
+ "@oscarpalmer/atoms": "^0.102"
8
8
  },
9
9
  "description": "Signals and stuff…",
10
10
  "devDependencies": {
11
11
  "@biomejs/biome": "^1.9",
12
12
  "@rollup/plugin-node-resolve": "^16",
13
13
  "@rollup/plugin-typescript": "^12.1",
14
- "@types/node": "^22.15",
14
+ "@types/node": "^24",
15
15
  "@vitest/coverage-istanbul": "^3.2",
16
16
  "dts-bundle-generator": "^9.5",
17
17
  "glob": "^11",
@@ -54,5 +54,5 @@
54
54
  },
55
55
  "type": "module",
56
56
  "types": "./types/index.d.ts",
57
- "version": "0.19.0"
57
+ "version": "0.20.0"
58
58
  }
package/src/batch.ts CHANGED
@@ -36,6 +36,6 @@ export function stopBatch(): void {
36
36
  flushHandlers();
37
37
  }
38
38
 
39
- export const batchedHandlers = new Set<Effect | Subscription<unknown>>();
39
+ export const batchedHandlers = new Set<Effect | Subscription>();
40
40
 
41
41
  export let batchDepth = 0;
@@ -12,42 +12,42 @@ import type {Store} from '../value/store';
12
12
  import {emitValue} from './value';
13
13
 
14
14
  export function getReactiveValueInProxy<Value>(
15
- array: ReactiveArray<Value>,
16
- mapped: Map<Key, Computed<unknown>>,
17
- index: number,
18
- isArray: true,
19
- ): unknown;
15
+ array: ReactiveArray<Value>,
16
+ mapped: Map<Key, Computed<unknown>>,
17
+ index: number,
18
+ isArray: true,
19
+ ): Computed<unknown>;
20
20
 
21
21
  export function getReactiveValueInProxy<Value extends PlainObject>(
22
- store: Store<Value>,
23
- mapped: Map<Key, Computed<unknown>>,
24
- key: Key,
25
- isArray: false,
26
- ): unknown;
22
+ store: Store<Value>,
23
+ mapped: Map<Key, Computed<unknown>>,
24
+ key: Key,
25
+ isArray: false,
26
+ ): Computed<unknown>;
27
27
 
28
28
  export function getReactiveValueInProxy(
29
- reactive: ReactiveArray<unknown> | Store<PlainObject>,
30
- mapped: Map<Key, Computed<unknown>>,
31
- key: Key,
32
- isArray: boolean,
33
- ): unknown {
34
- let item = mapped.get(key);
35
-
36
- if (item == null) {
37
- item = computed(() => {
38
- const value = reactive.get();
39
-
40
- return isArray
41
- ? (value as unknown[]).at(key as number)
42
- : (value as PlainObject)[key];
43
- }) as Computed<unknown>;
29
+ reactive: ReactiveArray<unknown> | Store<PlainObject>,
30
+ mapped: Map<Key, Computed<unknown>>,
31
+ key: Key,
32
+ isArray: boolean,
33
+ ): Computed<unknown> {
34
+ let item = mapped.get(key);
35
+
36
+ if (item == null) {
37
+ item = computed(() => {
38
+ const value = reactive.get();
39
+
40
+ return isArray
41
+ ? (value as unknown[]).at(key as number)
42
+ : (value as PlainObject)[key];
43
+ }) as Computed<unknown>;
44
+
45
+ mapped.set(key, item);
46
+ }
44
47
 
45
- mapped.set(key, item);
48
+ return item;
46
49
  }
47
50
 
48
- return item.get();
49
- }
50
-
51
51
  export function setProxyValue(
52
52
  proxy: ArrayOrPlainObject,
53
53
  value: ArrayOrPlainObject,
@@ -1,9 +1,9 @@
1
1
  import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
2
  import type {ReactiveState} from './value/reactive';
3
3
 
4
- export class Subscription<Value> {
4
+ export class Subscription {
5
5
  constructor(
6
- public state: ReactiveState<Value, never>,
6
+ public state: ReactiveState<unknown, never>,
7
7
  public callback: GenericCallback,
8
8
  ) {
9
9
  callback(state.value);
@@ -1,6 +1,8 @@
1
+ import type {GenericCallback} from '@oscarpalmer/atoms';
1
2
  import {arrayName} from '../helpers/is';
2
3
  import {getReactiveValueInProxy, setValueInProxy} from '../helpers/proxy';
3
4
  import {emitValue, equalArrays, getValue} from '../helpers/value';
5
+ import {type Unsubscribe, noop, subscribe} from '../subscription';
4
6
  import {type Computed, computed} from './computed';
5
7
  import {Reactive, type ReactiveOptions, type ReactiveState} from './reactive';
6
8
  import {type Signal, signal} from './signal';
@@ -65,13 +67,19 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
65
67
  */
66
68
  get(): Item[];
67
69
 
70
+ /**
71
+ * Get the value at an index
72
+ */
68
73
  get(index: number): Item | undefined;
69
74
 
75
+ /**
76
+ * Get the length of the array
77
+ */
70
78
  get(property: 'length'): number;
71
79
 
72
80
  get(first?: unknown): unknown {
73
81
  if (typeof first === 'number') {
74
- return getReactiveValueInProxy(this, this.#indiced, first, true);
82
+ return getReactiveValueInProxy(this, this.#indiced, first, true).get();
75
83
  }
76
84
 
77
85
  if (first === 'length') {
@@ -130,7 +138,7 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
130
138
  /**
131
139
  * Set the value
132
140
  */
133
- set(value: Item[]): void;
141
+ set(value?: Item[]): void;
134
142
 
135
143
  /**
136
144
  * Set the value at an index
@@ -142,9 +150,9 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
142
150
  */
143
151
  set(property: 'length', value: number): void;
144
152
 
145
- set(first: number | 'length' | Item[], second?: number | Item): void {
146
- if (Array.isArray(first)) {
147
- this.state.value.splice(0, this.state.value.length, ...first);
153
+ set(first?: number | 'length' | Item[], second?: number | Item): void {
154
+ if (first == null || Array.isArray(first)) {
155
+ this.state.value.splice(0, this.state.value.length, ...(first ?? []));
148
156
  } else if (first === 'length') {
149
157
  this.length = second as number;
150
158
  } else if (typeof first === 'number') {
@@ -170,12 +178,52 @@ export class ReactiveArray<Item> extends Reactive<Item[], Item> {
170
178
  );
171
179
  }
172
180
 
181
+ /**
182
+ * @inheritdoc
183
+ */
184
+ subscribe(callback: (value: Item[]) => void): Unsubscribe;
185
+
186
+ /**
187
+ * Subscribe to changes at a specific index
188
+ */
189
+ subscribe(
190
+ index: number,
191
+ callback: (value: Item | undefined) => void,
192
+ ): Unsubscribe;
193
+
194
+ subscribe(
195
+ first: number | GenericCallback,
196
+ second?: GenericCallback,
197
+ ): Unsubscribe {
198
+ if (typeof first === 'number' && typeof second === 'function') {
199
+ return getReactiveValueInProxy(
200
+ this,
201
+ this.#indiced,
202
+ first,
203
+ true,
204
+ ).subscribe(second);
205
+ }
206
+
207
+ return typeof first === 'function' ? subscribe(this.state, first) : noop;
208
+ }
209
+
173
210
  /**
174
211
  * Add items to the beginning of the array
175
212
  */
176
213
  unshift(...items: Item[]): number {
177
214
  return this.state.value.unshift(...items);
178
215
  }
216
+
217
+ /**
218
+ * Update the value _(based on the current value)_
219
+ */
220
+ update(callback: (value: Item[]) => Item[]): void {
221
+ const updated = callback(this.state.value);
222
+
223
+ if (updated == null || Array.isArray(updated)) {
224
+ this.set(updated);
225
+ }
226
+ }
179
227
  }
180
228
 
181
229
  /**
@@ -1,3 +1,4 @@
1
+ import type {GenericCallback} from '@oscarpalmer/atoms/models';
1
2
  import type {Effect} from '../effect';
2
3
  import {
3
4
  type Subscription,
@@ -80,6 +81,6 @@ export type ReactiveState<Value, Equal> = {
80
81
  computeds: Set<Computed<unknown>>;
81
82
  effects: Set<Effect>;
82
83
  equal: (first: Equal, second: Equal) => boolean;
83
- subscriptions: Map<(value: Value) => void, Subscription<Value>>;
84
+ subscriptions: Map<GenericCallback, Subscription>;
84
85
  value: Value;
85
86
  };
@@ -26,7 +26,7 @@ export class Signal<Value> extends Reactive<Value> {
26
26
  }
27
27
 
28
28
  /**
29
- * Update the value
29
+ * Update the value _(based on the current value)_
30
30
  */
31
31
  update(callback: (value: Value) => Value): void {
32
32
  this.set(callback(this.state.value));
@@ -1,5 +1,9 @@
1
1
  import {isKey, isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {Key, PlainObject} from '@oscarpalmer/atoms/models';
2
+ import type {
3
+ GenericCallback,
4
+ Key,
5
+ PlainObject,
6
+ } from '@oscarpalmer/atoms/models';
3
7
  import {storeName} from '../helpers/is';
4
8
  import {
5
9
  getReactiveValueInProxy,
@@ -7,6 +11,7 @@ import {
7
11
  setValueInProxy,
8
12
  } from '../helpers/proxy';
9
13
  import {getValue} from '../helpers/value';
14
+ import {type Unsubscribe, noop, subscribe} from '../subscription';
10
15
  import type {Computed} from './computed';
11
16
  import {Reactive, type ReactiveOptions} from './reactive';
12
17
 
@@ -41,7 +46,7 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
41
46
 
42
47
  get(key?: unknown): unknown {
43
48
  return isKey(key)
44
- ? getReactiveValueInProxy(this, this.#keyed, key, false)
49
+ ? getReactiveValueInProxy(this, this.#keyed, key, false).get()
45
50
  : getValue(this.state);
46
51
  }
47
52
 
@@ -86,6 +91,48 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
86
91
  setProxyValue(this.state.value, first ?? {});
87
92
  }
88
93
  }
94
+
95
+ /**
96
+ * @inheritdoc
97
+ */
98
+ subscribe(callback: (value: Value) => void): Unsubscribe;
99
+
100
+ /**
101
+ * Subscribe to changes for a specific key
102
+ */
103
+ subscribe<Key extends keyof Value>(
104
+ key: Key,
105
+ callback: (value: Value[Key] | undefined) => void,
106
+ ): Unsubscribe;
107
+
108
+ /**
109
+ * Subscribe to changes for a specific key
110
+ */
111
+ subscribe(key: Key, callback: (value: unknown) => void): Unsubscribe;
112
+
113
+ subscribe(
114
+ first: Key | GenericCallback,
115
+ second?: GenericCallback,
116
+ ): Unsubscribe {
117
+ if (isKey(first) && typeof second === 'function') {
118
+ return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(
119
+ second,
120
+ );
121
+ }
122
+
123
+ return typeof first === 'function' ? subscribe(this.state, first) : noop;
124
+ }
125
+
126
+ /**
127
+ * Update the value _(based on the current value)_
128
+ */
129
+ update(callback: (value: Value) => Value): void {
130
+ const updated = callback({...this.state.value});
131
+
132
+ if (updated == null || isPlainObject(updated)) {
133
+ setProxyValue(this.state.value, updated ?? {});
134
+ }
135
+ }
89
136
  }
90
137
 
91
138
  /**