@oscarpalmer/mora 0.30.0 → 0.31.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.
@@ -11,9 +11,10 @@ declare const NAME_ARRAY = "array";
11
11
  declare const NAME_COMPUTED = "computed";
12
12
  declare const NAME_EFFECT = "effect";
13
13
  declare const NAME_MORA = "$mora";
14
+ declare const NAME_READONLY = "readonly";
14
15
  declare const NAME_SIGNAL = "signal";
15
16
  declare const NAME_STORE = "store";
16
17
  declare const NAME_ALL: Set<string>;
17
18
  declare const PROPERTY_LENGTH = "length";
18
19
  //#endregion
19
- export { ACTIVE, ARRAY_OFFSET, ARRAY_PEEK, ARRAY_THRESHOLD, BATCH, METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_MORA, NAME_SIGNAL, NAME_STORE, PROPERTY_LENGTH };
20
+ export { ACTIVE, ARRAY_OFFSET, ARRAY_PEEK, ARRAY_THRESHOLD, BATCH, METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_MORA, NAME_READONLY, NAME_SIGNAL, NAME_STORE, PROPERTY_LENGTH };
@@ -26,14 +26,16 @@ const NAME_ARRAY = "array";
26
26
  const NAME_COMPUTED = "computed";
27
27
  const NAME_EFFECT = "effect";
28
28
  const NAME_MORA = "$mora";
29
+ const NAME_READONLY = "readonly";
29
30
  const NAME_SIGNAL = "signal";
30
31
  const NAME_STORE = "store";
31
32
  const NAME_ALL = /* @__PURE__ */ new Set([
32
33
  NAME_ARRAY,
33
34
  NAME_COMPUTED,
35
+ NAME_READONLY,
34
36
  NAME_SIGNAL,
35
37
  NAME_STORE
36
38
  ]);
37
39
  const PROPERTY_LENGTH = "length";
38
40
  //#endregion
39
- export { ACTIVE, ARRAY_OFFSET, ARRAY_PEEK, ARRAY_THRESHOLD, BATCH, METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_MORA, NAME_SIGNAL, NAME_STORE, PROPERTY_LENGTH };
41
+ export { ACTIVE, ARRAY_OFFSET, ARRAY_PEEK, ARRAY_THRESHOLD, BATCH, METHODS_AFFECTING_LENGTH, METHODS_UPDATE, NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_MORA, NAME_READONLY, NAME_SIGNAL, NAME_STORE, PROPERTY_LENGTH };
@@ -1,13 +1,6 @@
1
- import { Computed, Effect, Reactive, ReactiveArray, ReactiveStore, Signal } from "../models.mjs";
1
+ import { Computed, Effect, Reactive, ReactiveArray, ReactiveStore, ReadonlySignal, Signal } from "../models.mjs";
2
2
  import { PlainObject } from "@oscarpalmer/atoms/models";
3
3
  //#region src/helpers/is.d.ts
4
- /**
5
- * Is the value a reactive array?
6
- *
7
- * @param value Value to check
8
- * @returns True if value is a {@link ReactiveArray}
9
- */
10
- declare function isArray<Item>(value: unknown): value is ReactiveArray<Item>;
11
4
  /**
12
5
  * Is the value a computed signal?
13
6
  *
@@ -36,12 +29,20 @@ declare function isReactive<Value>(value: unknown): value is Reactive<Value>;
36
29
  * @returns True if value is a {@link Signal}
37
30
  */
38
31
  declare function isSignal<Value>(value: unknown): value is Signal<Value>;
32
+ /**
33
+ * Is the value a reactive array?
34
+ *
35
+ * @param value Value to check
36
+ * @returns True if value is a {@link ReactiveArray}
37
+ */
38
+ declare function isReactiveArray<Item>(value: unknown): value is ReactiveArray<Item>;
39
39
  /**
40
40
  * Is the value a reactive store?
41
41
  *
42
42
  * @param value Value to check
43
43
  * @returns True if value is a {@link Store}
44
44
  */
45
- declare function isStore<Value extends PlainObject>(value: unknown): value is ReactiveStore<Value>;
45
+ declare function isReactiveStore<Value extends PlainObject>(value: unknown): value is ReactiveStore<Value>;
46
+ declare function isReadonlySignal<Value>(value: unknown): value is ReadonlySignal<Value>;
46
47
  //#endregion
47
- export { isArray, isComputed, isEffect, isReactive, isSignal, isStore };
48
+ export { isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal };
@@ -1,15 +1,6 @@
1
- import { NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_SIGNAL, NAME_STORE } from "../constants.mjs";
1
+ import { NAME_ALL, NAME_ARRAY, NAME_COMPUTED, NAME_EFFECT, NAME_READONLY, NAME_SIGNAL, NAME_STORE } from "../constants.mjs";
2
2
  //#region src/helpers/is.ts
3
3
  /**
4
- * Is the value a reactive array?
5
- *
6
- * @param value Value to check
7
- * @returns True if value is a {@link ReactiveArray}
8
- */
9
- function isArray(value) {
10
- return isMora(value, NAME_ARRAY);
11
- }
12
- /**
13
4
  * Is the value a computed signal?
14
5
  *
15
6
  * @param value Value to check
@@ -49,13 +40,25 @@ function isSignal(value) {
49
40
  return isMora(value, NAME_SIGNAL);
50
41
  }
51
42
  /**
43
+ * Is the value a reactive array?
44
+ *
45
+ * @param value Value to check
46
+ * @returns True if value is a {@link ReactiveArray}
47
+ */
48
+ function isReactiveArray(value) {
49
+ return isMora(value, NAME_ARRAY);
50
+ }
51
+ /**
52
52
  * Is the value a reactive store?
53
53
  *
54
54
  * @param value Value to check
55
55
  * @returns True if value is a {@link Store}
56
56
  */
57
- function isStore(value) {
57
+ function isReactiveStore(value) {
58
58
  return isMora(value, NAME_STORE);
59
59
  }
60
+ function isReadonlySignal(value) {
61
+ return isMora(value, NAME_READONLY);
62
+ }
60
63
  //#endregion
61
- export { isArray, isComputed, isEffect, isReactive, isSignal, isStore };
64
+ export { isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal };
package/dist/index.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { startBatch, stopBatch } from "./batch.mjs";
2
- import { Computed, Effect, ReactiveArray, ReactiveStore, Signal, Unsubscribe } from "./models.mjs";
2
+ import { Computed, Effect, ReactiveArray, ReactiveStore, ReadonlySignal, Signal, Unsubscribe } from "./models.mjs";
3
3
  import { effect } from "./effect.mjs";
4
- import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.mjs";
4
+ import { isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal } from "./helpers/is.mjs";
5
5
  import { array } from "./value/array.mjs";
6
6
  import { computed } from "./value/computed.mjs";
7
7
  import { signal } from "./value/signal.mjs";
8
8
  import { store } from "./value/store.mjs";
9
- export { type Computed, type Effect, type ReactiveArray, type ReactiveStore, type Signal, type Unsubscribe, array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
9
+ export { type Computed, type Effect, type ReactiveArray, type ReactiveStore, type ReadonlySignal, type Signal, type Unsubscribe, array, computed, effect, isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal, signal, startBatch, stopBatch, store };
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { effect } from "./effect.mjs";
2
2
  import { startBatch, stopBatch } from "./batch.mjs";
3
- import { isArray, isComputed, isEffect, isReactive, isSignal } from "./helpers/is.mjs";
3
+ import { isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal } from "./helpers/is.mjs";
4
4
  import { computed } from "./value/computed.mjs";
5
5
  import { signal } from "./value/signal.mjs";
6
6
  import { array } from "./value/array.mjs";
7
7
  import { store } from "./value/store.mjs";
8
- export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
8
+ export { array, computed, effect, isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal, signal, startBatch, stopBatch, store };
package/dist/models.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PROPERTY_LENGTH } from "./constants.mjs";
2
- import { GenericCallback, Key } from "@oscarpalmer/atoms/models";
2
+ import { GenericCallback, Key, PlainObject } from "@oscarpalmer/atoms/models";
3
3
  //#region src/models.d.ts
4
4
  type Active = {
5
5
  computed?: ComputedEffect;
@@ -42,6 +42,20 @@ type ReactiveArray<Item> = {
42
42
  * Set the length of the array
43
43
  */
44
44
  set length(value: number);
45
+ /**
46
+ * Get a readonly version of the reactive array
47
+ *
48
+ * @param frozen Freeze the array? _(defaults to `false`)_
49
+ * @returns Readonly reactive array
50
+ */
51
+ asReadonly(frozen: true): ReadonlyFrozenSignal<Item[]>;
52
+ /**
53
+ * Get a readonly version of the reactive array
54
+ *
55
+ * @param frozen Freeze the array? _(defaults to `false`)_
56
+ * @returns Readonly reactive array
57
+ */
58
+ asReadonly(frozen?: boolean): typeof frozen extends true ? ReadonlyFrozenSignal<Item[]> : ReadonlySignal<Item[]>;
45
59
  /**
46
60
  * Get the value at an index
47
61
  *
@@ -96,16 +110,18 @@ type ReactiveArray<Item> = {
96
110
  /**
97
111
  * Get the array _(without reactivity)_
98
112
  *
113
+ * @param copy Copy the array? _(defaults to `false`)_
99
114
  * @returns Array of items
100
115
  */
101
- peek(): Item[];
116
+ peek(copy?: boolean): Item[];
102
117
  /**
103
118
  * Get the value at an index _(without reactivity)_
104
119
  *
105
120
  * @param index Index of item to get _(if negative, starts from the end)_
121
+ * @param copy If the item is an array or record, should it be copied? _(defaults to `false`)_
106
122
  * @returns Item at index, or `undefined` if it doesn't exist
107
123
  */
108
- peek(index: number): Item | undefined;
124
+ peek(index: number, copy?: boolean): Item | undefined;
109
125
  /**
110
126
  * Get the length of the array _(without reactivity)_
111
127
  *
@@ -227,20 +243,34 @@ type ReactiveState<Value, Equal> = {
227
243
  subscriptions: Map<GenericCallback, Subscription>;
228
244
  value: Value;
229
245
  };
230
- type ReactiveStore<Value> = {
246
+ type ReactiveStore<Store> = {
247
+ /**
248
+ * Get a readonly version of the reactive store
249
+ *
250
+ * @param frozen Freeze the store? _(defaults to `false`)_
251
+ * @returns Readonly reactive store
252
+ */
253
+ asReadonly(frozen: true): ReadonlyFrozenSignal<Store>;
254
+ /**
255
+ * Get a readonly version of the reactive store
256
+ *
257
+ * @param frozen Freeze the store? _(defaults to `false`)_
258
+ * @returns Readonly reactive store
259
+ */
260
+ asReadonly(frozen?: boolean): typeof frozen extends true ? ReadonlyFrozenSignal<Store> : ReadonlySignal<Store>;
231
261
  /**
232
262
  * Get the value
233
263
  *
234
264
  * @returns Current value
235
265
  */
236
- get(): Value;
266
+ get(): Store;
237
267
  /**
238
268
  * Get a value by key
239
269
  *
240
270
  * @param key Key of the value to get
241
271
  * @returns Value for the specified key, or `undefined` if it doesn't exist
242
272
  */
243
- get<Key extends keyof Value>(key: Key): Value[Key];
273
+ get<Key extends keyof Store>(key: Key): Store[Key];
244
274
  /**
245
275
  * Get a value by key
246
276
  *
@@ -258,36 +288,39 @@ type ReactiveStore<Value> = {
258
288
  /**
259
289
  * Get the value _(without reactivity)_
260
290
  *
291
+ * @param copy Copy the store? _(defaults to `false`)_
261
292
  * @returns Current value
262
293
  */
263
- peek(): Value;
294
+ peek(copy?: boolean): Store;
264
295
  /**
265
296
  * Get a value by key _(without reactivity)_
266
297
  *
267
298
  * @param key Key of the value to get
299
+ * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
268
300
  * @returns Value for the specified key, or `undefined` if it doesn't exist
269
301
  */
270
- peek<Key extends keyof Value>(key: Key): Value[Key];
302
+ peek<Key extends keyof Store>(key: Key, copy?: boolean): Store[Key];
271
303
  /**
272
304
  * Get a value by key _(without reactivity)_
273
305
  *
274
306
  * @param key Key of the value to get
307
+ * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
275
308
  * @returns Value for the specified key, or `undefined` if it doesn't exist
276
309
  */
277
- peek(key: Key): unknown;
310
+ peek(key: Key, copy?: boolean): unknown;
278
311
  /**
279
312
  * Set the value
280
313
  *
281
314
  * @param value New value _(defaults to an empty object)_
282
315
  */
283
- set(value?: Value | (() => null | undefined | Value | Promise<null | undefined | Value>) | Promise<null | undefined | Value>): void;
316
+ set(value?: Store | (() => null | undefined | Store | Promise<null | undefined | Store>) | Promise<null | undefined | Store>): void;
284
317
  /**
285
318
  * Set a value by key
286
319
  *
287
320
  * @param key Key of the value to set
288
321
  * @param value New value
289
322
  */
290
- set<Key extends keyof Value>(key: Key, value: Value[Key] | (() => Value[Key] | Promise<Value[Key]>) | Promise<Value[Key]>): void;
323
+ set<Key extends keyof Store>(key: Key, value: Store[Key] | (() => Store[Key] | Promise<Store[Key]>) | Promise<Store[Key]>): void;
291
324
  /**
292
325
  * Set a value by key
293
326
  *
@@ -301,7 +334,7 @@ type ReactiveStore<Value> = {
301
334
  * @param callback Callback for changes
302
335
  * @returns Unsubscribe callback
303
336
  */
304
- subscribe(callback: (value: Value) => void): Unsubscribe;
337
+ subscribe(callback: (value: Store) => void): Unsubscribe;
305
338
  /**
306
339
  * Subscribe to changes for a specific key
307
340
  *
@@ -309,7 +342,7 @@ type ReactiveStore<Value> = {
309
342
  * @param callback Callback for changes
310
343
  * @returns Unsubscribe callback
311
344
  */
312
- subscribe<Key extends keyof Value>(key: Key, callback: (value: Value[Key] | undefined) => void): Unsubscribe;
345
+ subscribe<Key extends keyof Store>(key: Key, callback: (value: Store[Key] | undefined) => void): Unsubscribe;
313
346
  /**
314
347
  * Subscribe to changes for a specific key
315
348
  *
@@ -324,20 +357,39 @@ type ReactiveStore<Value> = {
324
357
  * @param key Key of the value to unsubscribe from
325
358
  * @param callback Callback to unsubscribe
326
359
  */
327
- unsubscribe<Key extends keyof Value>(key: Key, callback: (value: Value[Key] | undefined) => void): void;
360
+ unsubscribe<Key extends keyof Store>(key: Key, callback: (value: Store[Key] | undefined) => void): void;
361
+ /**
362
+ * Unsubscribe from changes for a specific key
363
+ *
364
+ * @param key Key of the value to unsubscribe from
365
+ * @param callback Callback to unsubscribe
366
+ */
367
+ unsubscribe(key: Key, callback: (value: unknown | undefined) => void): void;
328
368
  /**
329
369
  * Unsubscribe from changes
330
370
  *
331
371
  * @param callback Callback to unsubscribe
332
372
  */
333
- unsubscribe(callback: (value: Value) => void): void;
373
+ unsubscribe(callback: (value: Store) => void): void;
334
374
  /**
335
375
  * Update the value _(based on the current value)_
336
376
  *
337
377
  * @param callback Callback to update the value
338
378
  */
339
- update(callback: (value: Value) => Value): void;
340
- } & Reactive<Value>;
379
+ update(callback: (value: Store) => Store): void;
380
+ } & Reactive<Store>;
381
+ type ReadonlyInstances<Value> = {
382
+ frozen?: ReadonlyFrozenSignal<Value>;
383
+ original?: ReadonlySignal<Value>;
384
+ };
385
+ type ReadonlyFrozenSignal<Value> = ReadonlySignal<ReadonlySignalValue<Value>>;
386
+ type ReadonlySignal<Value> = {
387
+ /**
388
+ * Is the signal frozen?
389
+ */
390
+ get frozen(): boolean;
391
+ } & Reactive<Value> & SimpleReactive<Value>;
392
+ type ReadonlySignalValue<Value> = Value extends unknown[] ? Readonly<Value> : Value extends PlainObject ? Readonly<Value> : Value;
341
393
  type SetValueInProxyParameters<Value, Equal> = {
342
394
  target: Value;
343
395
  property: PropertyKey;
@@ -347,6 +399,20 @@ type SetValueInProxyParameters<Value, Equal> = {
347
399
  length?: Signal<number>;
348
400
  };
349
401
  type Signal<Value> = {
402
+ /**
403
+ * Get a readonly version of the signal
404
+ *
405
+ * @param frozen Freeze the signal? _(defaults to `false`)_
406
+ * @returns Readonly signal
407
+ */
408
+ asReadonly(frozen: true): ReadonlyFrozenSignal<Value>;
409
+ /**
410
+ * Get a readonly version of the signal
411
+ *
412
+ * @param frozen Freeze the signal? _(defaults to `false`)_
413
+ * @returns Readonly signal
414
+ */
415
+ asReadonly(frozen?: boolean): typeof frozen extends true ? ReadonlyFrozenSignal<Value> : ReadonlySignal<Value>;
350
416
  /**
351
417
  * Set the value
352
418
  *
@@ -397,4 +463,4 @@ type Subscription = {
397
463
  */
398
464
  type Unsubscribe = () => void;
399
465
  //#endregion
400
- export { Active, Batch, Computed, ComputedEffect, Effect, EffectState, Reactive, ReactiveArray, ReactiveOptions, ReactiveState, ReactiveStore, SetValueInProxyParameters, Signal, Subscription, Unsubscribe };
466
+ export { Active, Batch, Computed, ComputedEffect, Effect, EffectState, Reactive, ReactiveArray, ReactiveOptions, ReactiveState, ReactiveStore, ReadonlyFrozenSignal, ReadonlyInstances, ReadonlySignal, ReadonlySignalValue, SetValueInProxyParameters, Signal, Subscription, Unsubscribe };
@@ -23,11 +23,13 @@ const NAME_ARRAY = "array";
23
23
  const NAME_COMPUTED = "computed";
24
24
  const NAME_EFFECT = "effect";
25
25
  const NAME_MORA = "$mora";
26
+ const NAME_READONLY = "readonly";
26
27
  const NAME_SIGNAL = "signal";
27
28
  const NAME_STORE = "store";
28
29
  const NAME_ALL = /* @__PURE__ */ new Set([
29
30
  NAME_ARRAY,
30
31
  NAME_COMPUTED,
32
+ NAME_READONLY,
31
33
  NAME_SIGNAL,
32
34
  NAME_STORE
33
35
  ]);
@@ -99,15 +101,6 @@ function stopBatch() {
99
101
  //#endregion
100
102
  //#region src/helpers/is.ts
101
103
  /**
102
- * Is the value a reactive array?
103
- *
104
- * @param value Value to check
105
- * @returns True if value is a {@link ReactiveArray}
106
- */
107
- function isArray(value) {
108
- return isMora(value, NAME_ARRAY);
109
- }
110
- /**
111
104
  * Is the value a computed signal?
112
105
  *
113
106
  * @param value Value to check
@@ -146,6 +139,27 @@ function isReactive(value) {
146
139
  function isSignal(value) {
147
140
  return isMora(value, NAME_SIGNAL);
148
141
  }
142
+ /**
143
+ * Is the value a reactive array?
144
+ *
145
+ * @param value Value to check
146
+ * @returns True if value is a {@link ReactiveArray}
147
+ */
148
+ function isReactiveArray(value) {
149
+ return isMora(value, NAME_ARRAY);
150
+ }
151
+ /**
152
+ * Is the value a reactive store?
153
+ *
154
+ * @param value Value to check
155
+ * @returns True if value is a {@link Store}
156
+ */
157
+ function isReactiveStore(value) {
158
+ return isMora(value, NAME_STORE);
159
+ }
160
+ function isReadonlySignal(value) {
161
+ return isMora(value, NAME_READONLY);
162
+ }
149
163
  //#endregion
150
164
  //#region node_modules/@oscarpalmer/atoms/dist/internal/array/callbacks.mjs
151
165
  function getArrayCallback(value) {
@@ -512,6 +526,39 @@ function setValueInProxy(parameters) {
512
526
  return true;
513
527
  }
514
528
  //#endregion
529
+ //#region src/value/readonly.ts
530
+ function getReadonlyInstance(state, instances, handlers, frozen) {
531
+ const key = frozen ? "frozen" : "original";
532
+ instances[key] ??= getReadonlySignal(state, handlers, frozen);
533
+ return instances[key];
534
+ }
535
+ function getReadonlySignal(state, handlers, frozen) {
536
+ const instance = {
537
+ ...handlers,
538
+ get: () => getReadonlyValue(state, false, frozen),
539
+ peek: () => getReadonlyValue(state, true, frozen)
540
+ };
541
+ Object.defineProperties(instance, {
542
+ [NAME_MORA]: {
543
+ enumerable: false,
544
+ value: NAME_READONLY
545
+ },
546
+ frozen: {
547
+ enumerable: true,
548
+ value: frozen
549
+ }
550
+ });
551
+ return Object.freeze(instance);
552
+ }
553
+ function getReadonlyValue(state, peek, frozen) {
554
+ let value = peek ? state.value : getSimpleValue(state);
555
+ if (!frozen) return value;
556
+ if (Array.isArray(state.value)) value = [...state.value];
557
+ else if (isPlainObject(state.value)) value = { ...state.value };
558
+ else value = state.value;
559
+ return Object.freeze(value);
560
+ }
561
+ //#endregion
515
562
  //#region src/value/signal.ts
516
563
  function setAndEmit(state, value) {
517
564
  if (!state.equal(state.value, value)) {
@@ -521,8 +568,17 @@ function setAndEmit(state, value) {
521
568
  }
522
569
  function signal(value, options) {
523
570
  const [rx, state] = reactive(void 0, options);
524
- const instance = {
571
+ const readonlies = {};
572
+ const handlers = {
525
573
  ...rx,
574
+ subscribe: (callback) => subscribe(state, callback),
575
+ unsubscribe: (callback) => {
576
+ state.subscriptions.delete(callback);
577
+ }
578
+ };
579
+ const instance = {
580
+ ...handlers,
581
+ asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
526
582
  get: () => getSimpleValue(state),
527
583
  peek: () => state.value,
528
584
  set: (value) => {
@@ -530,10 +586,6 @@ function signal(value, options) {
530
586
  },
531
587
  update: (callback) => {
532
588
  handleSimpleValue(state, callback(state.value), setAndEmit);
533
- },
534
- subscribe: (callback) => subscribe(state, callback),
535
- unsubscribe: (callback) => {
536
- state.subscriptions.delete(callback);
537
589
  }
538
590
  };
539
591
  Object.defineProperty(instance, NAME_MORA, {
@@ -549,6 +601,8 @@ function array(value, options) {
549
601
  const [rx, state] = reactive([], options);
550
602
  const indiced = /* @__PURE__ */ new Map();
551
603
  const length = signal(0);
604
+ const readonlies = {};
605
+ let instance = {};
552
606
  state.value = new Proxy([], {
553
607
  get: (target, property) => METHODS_UPDATE.has(property) ? updateArray(property, target, state, length) : Reflect.get(target, property),
554
608
  set: (target, property, value) => setValueInProxy({
@@ -563,37 +617,43 @@ function array(value, options) {
563
617
  function get(value) {
564
618
  return getArrayValue(instance, indiced, state, length, value);
565
619
  }
566
- const instance = {
620
+ function set(first, second) {
621
+ setProxyValue(true, state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
622
+ }
623
+ const handlers = {
567
624
  ...rx,
568
- length: state.value.length,
625
+ get: (value) => get(value),
626
+ peek: (first, second) => peekArrayValue(state, length, first, second),
627
+ subscribe: (first, second) => {
628
+ if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(instance, indiced, first, true).subscribe(second);
629
+ return typeof first === "function" ? subscribe(state, first) : noop$1;
630
+ },
631
+ unsubscribe: (first, second) => {
632
+ if (typeof first === "number" && typeof second === "function") getReactiveValueInProxy(instance, indiced, first, true)?.unsubscribe(second);
633
+ else if (typeof first === "function") unsubscribe(state, first);
634
+ }
635
+ };
636
+ instance = {
637
+ ...handlers,
638
+ asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
569
639
  at: (index) => get(index),
570
640
  clear: () => {
571
641
  state.value.length = 0;
572
642
  },
573
643
  filter: (callback) => computed(() => filter(get(), callback)),
574
- get: (value) => get(value),
575
644
  map: (callback) => computed(() => get().map(callback)),
576
645
  notify: () => {
577
646
  emityProxyValues(state, indiced);
578
647
  },
579
- peek: (value) => peekArrayValue(state, length, value),
580
648
  pop: () => state.value.pop(),
581
649
  push: (...items) => state.value.push(...items),
582
650
  select: (filter, map) => computed(() => select(get(), filter, map)),
583
651
  set: (first, second) => {
584
- setProxyValue(true, state, isArrayValue, isArrayIndex, setArray, setAtIndex, first, second);
652
+ set(first, second);
585
653
  },
586
654
  shift: () => state.value.shift(),
587
655
  splice: (from, to, ...items) => state.value.splice(from, to ?? state.value.length, ...items),
588
- subscribe: (first, second) => {
589
- if (typeof first === "number" && typeof second === "function") return getReactiveValueInProxy(instance, indiced, first, true).subscribe(second);
590
- return typeof first === "function" ? subscribe(state, first) : noop$1;
591
- },
592
656
  unshift: (...items) => state.value.unshift(...items),
593
- unsubscribe: (first, second) => {
594
- if (typeof first === "number" && typeof second === "function") getReactiveValueInProxy(instance, indiced, first, true)?.unsubscribe(second);
595
- else if (typeof first === "function") unsubscribe(state, first);
596
- },
597
657
  update: (callback) => updateArrayValue(instance, state, callback)
598
658
  };
599
659
  Object.defineProperties(instance, {
@@ -607,7 +667,7 @@ function array(value, options) {
607
667
  set: (value) => setArrayLength(state, value)
608
668
  }
609
669
  });
610
- instance.set(value);
670
+ set(value);
611
671
  return Object.freeze(instance);
612
672
  }
613
673
  function getArrayValue(instance, indiced, state, length, first) {
@@ -620,9 +680,15 @@ function isArrayIndex(value) {
620
680
  function isArrayValue(value) {
621
681
  return value == null || Array.isArray(value);
622
682
  }
623
- function peekArrayValue(state, length, value) {
624
- if (value === "length") return length.peek();
625
- return typeof value === "number" ? state.value.at(value) : state.value.slice();
683
+ function peekArrayValue(state, length, first, second) {
684
+ if (first === "length") return length.peek();
685
+ let value;
686
+ if (typeof first === "number") value = state.value.at(first);
687
+ else value = state.value;
688
+ if (!(first === true || second === true)) return value;
689
+ if (Array.isArray(value)) return value.slice();
690
+ if (isPlainObject(value)) return { ...value };
691
+ return value;
626
692
  }
627
693
  function setArray(state, value) {
628
694
  state.value.splice(0, state.value.length, ...value ?? []);
@@ -674,12 +740,23 @@ function setObject(state, value) {
674
740
  }
675
741
  stopBatch();
676
742
  }
743
+ function peekStoreValue(state, first, second) {
744
+ let value;
745
+ if (isKey(first)) value = state.value[first];
746
+ else value = state.value;
747
+ if (!(first === true || second === true)) return value;
748
+ if (Array.isArray(value)) return value.slice();
749
+ if (isPlainObject(value)) return { ...value };
750
+ return value;
751
+ }
677
752
  function setProperty(state, key, value) {
678
753
  state.value[key] = value;
679
754
  }
680
755
  function store(value, options) {
681
756
  const [rx, state] = reactive(void 0, options);
682
757
  const keyed = /* @__PURE__ */ new Map();
758
+ const readonlies = {};
759
+ let instance = {};
683
760
  state.value = new Proxy({}, { set: (target, property, value) => setValueInProxy({
684
761
  target,
685
762
  property,
@@ -687,16 +764,10 @@ function store(value, options) {
687
764
  value,
688
765
  isArray: false
689
766
  }) });
690
- const instance = {
767
+ const handlers = {
691
768
  ...rx,
692
769
  get: (value) => isKey(value) ? getReactiveValueInProxy(instance, keyed, value, false).get() : getSimpleValue(state),
693
- notify() {
694
- emityProxyValues(state, keyed);
695
- },
696
- peek: (value) => isKey(value) ? state.value[value] : { ...state.value },
697
- set: (first, second) => {
698
- setProxyValue(false, state, isStoreObject, isKey, setObject, setProperty, first, second);
699
- },
770
+ peek: (first, second) => peekStoreValue(state, first, second),
700
771
  subscribe: (first, second) => {
701
772
  if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(instance, keyed, first, false).subscribe(second);
702
773
  return typeof first === "function" ? subscribe(state, first) : noop;
@@ -704,6 +775,16 @@ function store(value, options) {
704
775
  unsubscribe: (first, second) => {
705
776
  if (isKey(first) && typeof second === "function") getReactiveValueInProxy(instance, keyed, first, false)?.unsubscribe(second);
706
777
  else if (typeof first === "function") unsubscribe(state, first);
778
+ }
779
+ };
780
+ instance = {
781
+ ...handlers,
782
+ asReadonly: (frozen) => getReadonlyInstance(state, readonlies, handlers, frozen === true),
783
+ notify() {
784
+ emityProxyValues(state, keyed);
785
+ },
786
+ set: (first, second) => {
787
+ setProxyValue(false, state, isStoreObject, isKey, setObject, setProperty, first, second);
707
788
  },
708
789
  update: (callback) => {
709
790
  const updated = callback(state.value);
@@ -718,4 +799,4 @@ function store(value, options) {
718
799
  return Object.freeze(instance);
719
800
  }
720
801
  //#endregion
721
- export { array, computed, effect, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
802
+ export { array, computed, effect, isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal, signal, startBatch, stopBatch, store };