@oscarpalmer/mora 0.32.0 → 0.33.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 (45) hide show
  1. package/dist/batch.mjs +2 -2
  2. package/dist/constants.d.mts +2 -0
  3. package/dist/constants.mjs +3 -1
  4. package/dist/effect.d.mts +1 -0
  5. package/dist/effect.mjs +8 -5
  6. package/dist/helpers/is.d.mts +6 -6
  7. package/dist/helpers/misc.d.mts +4 -0
  8. package/dist/helpers/misc.mjs +9 -0
  9. package/dist/helpers/proxy.d.mts +8 -10
  10. package/dist/helpers/proxy.mjs +71 -33
  11. package/dist/helpers/subscription.d.mts +4 -4
  12. package/dist/helpers/subscription.mjs +16 -13
  13. package/dist/helpers/value.d.mts +8 -7
  14. package/dist/helpers/value.mjs +35 -22
  15. package/dist/models.d.mts +47 -24
  16. package/dist/models.mjs +1 -0
  17. package/dist/mora.full.mjs +307 -236
  18. package/dist/value/array.d.mts +1 -0
  19. package/dist/value/array.mjs +69 -61
  20. package/dist/value/computed.d.mts +3 -1
  21. package/dist/value/computed.mjs +39 -25
  22. package/dist/value/readonly.d.mts +3 -3
  23. package/dist/value/readonly.mjs +31 -24
  24. package/dist/value/signal.d.mts +1 -0
  25. package/dist/value/signal.mjs +27 -20
  26. package/dist/value/store.d.mts +1 -0
  27. package/dist/value/store.mjs +23 -41
  28. package/package.json +1 -1
  29. package/src/batch.ts +2 -2
  30. package/src/constants.ts +4 -0
  31. package/src/effect.ts +16 -11
  32. package/src/helpers/is.ts +6 -6
  33. package/src/helpers/misc.ts +15 -0
  34. package/src/helpers/proxy.ts +116 -89
  35. package/src/helpers/subscription.ts +46 -35
  36. package/src/helpers/value.ts +61 -35
  37. package/src/models.ts +54 -28
  38. package/src/value/array.ts +103 -124
  39. package/src/value/computed.ts +70 -40
  40. package/src/value/readonly.ts +54 -41
  41. package/src/value/signal.ts +46 -35
  42. package/src/value/store.ts +36 -83
  43. package/dist/value/reactive.d.mts +0 -4
  44. package/dist/value/reactive.mjs +0 -15
  45. package/src/value/reactive.ts +0 -27
package/dist/batch.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { BATCH } from "./constants.mjs";
2
2
  import { runEffect } from "./effect.mjs";
3
- import { getFrozenValue, peekSimpleValue } from "./helpers/value.mjs";
3
+ import { getFrozenValue, peekSignalValue } from "./helpers/value.mjs";
4
4
  //#region src/batch.ts
5
5
  function flushHandlers() {
6
6
  if (BATCH.flushing) return;
@@ -13,7 +13,7 @@ function flushHandlers() {
13
13
  for (let index = 0; index < length; index += 1) {
14
14
  const [, handler] = handlers[index];
15
15
  const subscription = handler;
16
- if (typeof subscription.frozen === "boolean") subscription.callback(subscription.frozen ? getFrozenValue(subscription.state.value) : peekSimpleValue(subscription.state.value, subscription.copy));
16
+ if (typeof subscription.frozen === "boolean") subscription.callback(subscription.frozen ? getFrozenValue(subscription.state.value) : peekSignalValue.call(subscription.instance, subscription.copy));
17
17
  else runEffect(handler);
18
18
  }
19
19
  }
@@ -17,6 +17,8 @@ export declare const NAME_STORE = "store";
17
17
  export declare const NAME_SUBSCRIPTION = "subscription";
18
18
  export declare const NAME_ALL: Set<string>;
19
19
  export declare const PROPERTY_LENGTH = "length";
20
+ export declare const SYMBOL_EFFECT: unique symbol;
21
+ export declare const SYMBOL_STATE: unique symbol;
20
22
  export declare const SUBSCRIPTION_PROPERTY: {
21
23
  key: string;
22
24
  value: string;
@@ -38,6 +38,8 @@ const NAME_ALL = /* @__PURE__ */ new Set([
38
38
  NAME_STORE
39
39
  ]);
40
40
  const PROPERTY_LENGTH = "length";
41
+ const SYMBOL_EFFECT = Symbol("effect");
42
+ const SYMBOL_STATE = Symbol("state");
41
43
  const SUBSCRIPTION_PROPERTY = {
42
44
  key: NAME_MORA,
43
45
  value: NAME_SUBSCRIPTION
@@ -53,4 +55,4 @@ const SUBSCRIPTION_TYPES = /* @__PURE__ */ new Set([
53
55
  SUBSCRIPTION_TYPE_ORIGINAL
54
56
  ]);
55
57
  //#endregion
56
- 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, NAME_SUBSCRIPTION, PROPERTY_LENGTH, SUBSCRIPTION_PROPERTY, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_COPY, SUBSCRIPTION_TYPE_FROZEN, SUBSCRIPTION_TYPE_ORIGINAL, SUBSCRIPTION_TYPE_READONLY };
58
+ 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, NAME_SUBSCRIPTION, PROPERTY_LENGTH, SUBSCRIPTION_PROPERTY, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_COPY, SUBSCRIPTION_TYPE_FROZEN, SUBSCRIPTION_TYPE_ORIGINAL, SUBSCRIPTION_TYPE_READONLY, SYMBOL_EFFECT, SYMBOL_STATE };
package/dist/effect.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Effect, EffectState } from "./models.mjs";
2
2
  import { GenericCallback } from "@oscarpalmer/atoms/models";
3
3
  //#region src/effect.d.ts
4
+ declare function Effect(this: any, callback: GenericCallback): void;
4
5
  /**
5
6
  * Create an effect
6
7
  *
package/dist/effect.mjs CHANGED
@@ -1,5 +1,10 @@
1
- import { ACTIVE, NAME_EFFECT, NAME_MORA } from "./constants.mjs";
1
+ import { ACTIVE, NAME_EFFECT, NAME_MORA, SYMBOL_STATE } from "./constants.mjs";
2
2
  //#region src/effect.ts
3
+ function Effect(callback) {
4
+ this[SYMBOL_STATE] = { callback };
5
+ runEffect(this[SYMBOL_STATE]);
6
+ }
7
+ Effect.prototype[NAME_MORA] = NAME_EFFECT;
3
8
  /**
4
9
  * Create an effect
5
10
  *
@@ -11,10 +16,8 @@ function effect(callback) {
11
16
  return getEffect(callback)[0];
12
17
  }
13
18
  function getEffect(callback) {
14
- const state = { callback };
15
- const instance = Object.freeze({ [NAME_MORA]: NAME_EFFECT });
16
- runEffect(state);
17
- return [instance, state];
19
+ const instance = new Effect(callback);
20
+ return [instance, instance[SYMBOL_STATE]];
18
21
  }
19
22
  function internalEffect(callback) {
20
23
  return getEffect(callback)[1];
@@ -7,7 +7,7 @@ import { PlainObject } from "@oscarpalmer/atoms/models";
7
7
  * @param value Value to check
8
8
  * @returns True if value is a {@link Computed}
9
9
  */
10
- export declare function isComputed<Value>(value: unknown): value is Computed<Value>;
10
+ export declare function isComputed<Value = unknown>(value: unknown): value is Computed<Value>;
11
11
  /**
12
12
  * Is the value an effect?
13
13
  *
@@ -21,33 +21,33 @@ export declare function isEffect(value: unknown): value is Effect;
21
21
  * @param value Value to check
22
22
  * @returns True if value is a {@link Reactive}
23
23
  */
24
- export declare function isReactive<Value>(value: unknown): value is Reactive<Value>;
24
+ export declare function isReactive<Value = unknown>(value: unknown): value is Reactive<Value>;
25
25
  /**
26
26
  * Is the value a signal?
27
27
  *
28
28
  * @param value Value to check
29
29
  * @returns True if value is a {@link Signal}
30
30
  */
31
- export declare function isSignal<Value>(value: unknown): value is Signal<Value>;
31
+ export declare function isSignal<Value = unknown>(value: unknown): value is Signal<Value>;
32
32
  /**
33
33
  * Is the value a reactive array?
34
34
  *
35
35
  * @param value Value to check
36
36
  * @returns True if value is a {@link ReactiveArray}
37
37
  */
38
- export declare function isReactiveArray<Item>(value: unknown): value is ReactiveArray<Item>;
38
+ export declare function isReactiveArray<Item = unknown>(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
- export declare function isReactiveStore<Value extends PlainObject>(value: unknown): value is ReactiveStore<Value>;
45
+ export declare function isReactiveStore<Value extends PlainObject = PlainObject>(value: unknown): value is ReactiveStore<Value>;
46
46
  /**
47
47
  * Is the value a readonly signal?
48
48
  *
49
49
  * @param value Value to check
50
50
  * @returns True if value is a {@link ReadonlySignal}
51
51
  */
52
- export declare function isReadonlySignal<Value>(value: unknown): value is ReadonlySignal<Value>;
52
+ export declare function isReadonlySignal<Value = unknown>(value: unknown): value is ReadonlySignal<Value>;
53
53
  //#endregion
@@ -0,0 +1,4 @@
1
+ import { ReactiveOptions, ReactiveState } from "../models.mjs";
2
+ //#region src/helpers/misc.d.ts
3
+ export declare function getState(value: unknown, options?: ReactiveOptions<unknown>): ReactiveState;
4
+ //#endregion
@@ -0,0 +1,9 @@
1
+ //#region src/helpers/misc.ts
2
+ function getState(value, options) {
3
+ return {
4
+ value,
5
+ equal: typeof options === "object" && typeof options?.equal === "function" ? options.equal : void 0
6
+ };
7
+ }
8
+ //#endregion
9
+ export { getState };
@@ -1,13 +1,11 @@
1
- import { Computed, ComputedEffect, ReactiveArray, ReactiveState, ReactiveStore, Signal } from "../models.mjs";
1
+ import { Computed, InternalProxy, ReactiveArray, ReactiveStore } from "../models.mjs";
2
2
  import { Key } from "@oscarpalmer/atoms/models";
3
3
  //#region src/helpers/proxy.d.ts
4
- type SetObjectCallback<Value, Item> = (state: ReactiveState<Value, Item>, value: Value | undefined) => void;
5
- type SetPropertyCallback<Value, Item> = (state: ReactiveState<Value, Item>, property: unknown, value: Item) => void;
6
- export declare function emitProxyValues<Value, Item = Value>(state: ReactiveState<Value, Item>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>): void;
7
- export declare function getReactiveValueInProxy<Value>(reactive: ReactiveArray<Value> | ReactiveStore<Value>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>, key: Key, isArray: boolean): Computed<unknown>;
8
- export declare function getValueInProxy<Value, Item = Value>(isArray: boolean, instance: ReactiveArray<Value> | ReactiveStore<Value>, state: ReactiveState<Value, Item>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>, first?: unknown): unknown;
9
- export declare function peekValueInProxy<Value, Item = Value>(isArray: boolean, state: ReactiveState<Value, Item>, first?: unknown, second?: boolean): unknown;
10
- export declare function setProxyValue<Value, Item = Value>(isArray: boolean, state: ReactiveState<Value, Item>, setObject: SetObjectCallback<Value, Item>, setProperty: SetPropertyCallback<Value, Item>, first?: unknown, second?: unknown): void;
11
- export declare function setValueInProxy<Value, Item = Value>(isArray: boolean, state: ReactiveState<Value, Item>, target: object, property: PropertyKey, value: unknown, length?: Signal<number>): boolean;
12
- export declare function updateProxyValue<Value, Item = Value>(isArray: boolean, state: ReactiveState<Value, Item>, setObject: SetObjectCallback<Value, Item>, setProperty: SetPropertyCallback<Value, Item>, callback: unknown): void;
4
+ export declare function emitProxyValues(this: InternalProxy): void;
5
+ export declare function getReactiveValueInProxy(instance: ReactiveArray<unknown> | ReactiveStore<unknown>, key: Key): Computed<unknown>;
6
+ export declare function getValueInProxy(this: InternalProxy, first?: unknown): unknown;
7
+ export declare function peekValueInProxy(this: InternalProxy, first?: unknown, second?: boolean): unknown;
8
+ export declare function setProxyValue(this: InternalProxy, first?: unknown, second?: unknown): void;
9
+ export declare function setValueInProxy(instance: InternalProxy, target: object, property: PropertyKey, value: unknown): boolean;
10
+ export declare function updateProxyValue(this: InternalProxy, callback: unknown): void;
13
11
  //#endregion
@@ -1,47 +1,84 @@
1
- import "../constants.mjs";
2
- import { emitValue, getSimpleValue, peekSimpleValue } from "./value.mjs";
1
+ import { SYMBOL_STATE } from "../constants.mjs";
2
+ import { emitValue, getSignalValue, peekSignalValue } from "./value.mjs";
3
+ import { startBatch, stopBatch } from "../batch.mjs";
3
4
  import { internalComputed } from "../value/computed.mjs";
4
5
  import { isKey, isPlainObject } from "@oscarpalmer/atoms/is";
5
6
  //#region src/helpers/proxy.ts
6
- function emitProxyValues(state, mapped) {
7
- const values = [...mapped.values()];
7
+ function emitProxyValues() {
8
+ const state = this[SYMBOL_STATE];
9
+ state.mapped ??= /* @__PURE__ */ new Map();
10
+ const values = [...state.mapped.values()];
8
11
  const { length } = values;
9
12
  for (let index = 0; index < length; index += 1) values[index][1].dirty = true;
10
- emitValue(state);
13
+ emitValue(this);
11
14
  }
12
- function getReactiveValueInProxy(reactive, mapped, key, isArray) {
15
+ function getReactiveValueInProxy(instance, key) {
16
+ const state = instance[SYMBOL_STATE];
17
+ state.mapped ??= /* @__PURE__ */ new Map();
13
18
  const mapKey = String(key);
14
- let item = mapped.get(mapKey);
19
+ let item = state.mapped.get(mapKey);
15
20
  if (item == null) {
16
- item = internalComputed(() => isArray ? reactive.get().at(key) : reactive.get()[key]);
17
- mapped.set(mapKey, item);
21
+ item = internalComputed(() => state.isArray ? instance.get().at(key) : instance.get()[key]);
22
+ state.mapped.set(mapKey, item);
18
23
  }
19
24
  return item[0];
20
25
  }
21
- function getValueInProxy(isArray, instance, state, mapped, first) {
22
- if (isArray ? typeof first === "number" : isKey(first)) return getReactiveValueInProxy(instance, mapped, first, isArray).get();
23
- return getSimpleValue(state);
26
+ function getValueInProxy(first) {
27
+ if (this[SYMBOL_STATE].isArray ? typeof first === "number" : isKey(first)) return getReactiveValueInProxy(this, first).get();
28
+ return getSignalValue.call(this);
24
29
  }
25
30
  function isProxyObject(isArray, value) {
26
31
  return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
27
32
  }
28
- function peekValueInProxy(isArray, state, first, second) {
33
+ function peekValueInProxy(first, second) {
34
+ const state = this[SYMBOL_STATE];
29
35
  let value;
30
- if (isArray ? typeof first === "number" : isKey(first)) value = isArray ? state.value.at(first) : state.value[first];
36
+ if (state.isArray ? typeof first === "number" : isKey(first)) value = state.isArray ? state.value.at(first) : state.value[first];
31
37
  else value = state.value;
32
- return peekSimpleValue(value, first === true || second === true);
38
+ return peekSignalValue.call([this, value], first === true || second === true);
33
39
  }
34
- function setProxyValue(isArray, state, setObject, setProperty, first, second) {
35
- if (isArray && first === "length") {
40
+ function setProxyObject(state, value) {
41
+ if (state.isArray) {
42
+ state.value.splice(0, state.value.length, ...value ?? []);
43
+ return;
44
+ }
45
+ startBatch();
46
+ const actual = value ?? {};
47
+ const proxy = state.value;
48
+ const proxyKeys = Object.keys(proxy);
49
+ const actualKeys = Object.keys(actual);
50
+ let { length } = proxyKeys;
51
+ for (let index = 0; index < length; index += 1) {
52
+ const key = proxyKeys[index];
53
+ proxy[key] = actualKeys.includes(key) ? actual[key] : void 0;
54
+ }
55
+ length = actualKeys.length;
56
+ for (let index = 0; index < length; index += 1) {
57
+ const key = actualKeys[index];
58
+ if (!proxyKeys.includes(key)) proxy[key] = actual[key];
59
+ }
60
+ stopBatch();
61
+ }
62
+ function setProxyProperty(state, property, value) {
63
+ if (!state.isArray) {
64
+ state.value[property] = value;
65
+ return;
66
+ }
67
+ const actual = property < 0 ? state.value.length + property : property;
68
+ if (actual > -1) state.value[actual] = value;
69
+ }
70
+ function setProxyValue(first, second) {
71
+ const state = this[SYMBOL_STATE];
72
+ if (state.isArray && first === "length") {
36
73
  state.value.length = second;
37
74
  return;
38
75
  }
39
- if (isProxyObject(isArray, first)) {
40
- setObject(state, first);
76
+ if (isProxyObject(state.isArray, first)) {
77
+ setProxyObject(state, first);
41
78
  return;
42
79
  }
43
- const property = isArray ? typeof first === "number" : isKey(first);
44
- if (isArray && property && Number.isNaN(first)) return;
80
+ const property = state.isArray ? typeof first === "number" : isKey(first);
81
+ if (state.isArray && property && Number.isNaN(first)) return;
45
82
  let actual = property ? second : first;
46
83
  if (typeof actual === "function") try {
47
84
  actual = actual();
@@ -56,35 +93,36 @@ function setProxyValue(isArray, state, setObject, setProperty, first, second) {
56
93
  actual.then((value) => {
57
94
  if (property && state.promises.get(first) === actual) {
58
95
  state.promises.delete(first);
59
- setProperty(state, first, value);
96
+ setProxyProperty(state, first, value);
60
97
  return;
61
98
  }
62
- if (!property && isProxyObject(isArray, value) && state.promise === actual) {
99
+ if (!property && isProxyObject(state.isArray, value) && state.promise === actual) {
63
100
  state.promise = void 0;
64
- setObject(state, value);
101
+ setProxyObject(state, value);
65
102
  }
66
103
  }).catch(() => {
67
104
  if (property && state.promises.get(first) === actual) state.promises.delete(first);
68
105
  else if (!property && state.promise === actual) state.promise = void 0;
69
106
  });
70
- } else if (property) setProperty(state, first, actual);
71
- else if (isProxyObject(isArray, actual)) setObject(state, actual);
107
+ } else if (property) setProxyProperty(state, first, actual);
108
+ else if (isProxyObject(state.isArray, actual)) setProxyObject(state, actual);
72
109
  }
73
- function setValueInProxy(isArray, state, target, property, value, length) {
74
- if (isArray) {
110
+ function setValueInProxy(instance, target, property, value) {
111
+ const state = instance[SYMBOL_STATE];
112
+ if (state.isArray) {
75
113
  if (!(!Number.isNaN(Number(property)) || property === "length")) return Reflect.set(target, property, value);
76
114
  }
77
115
  const previous = Reflect.get(target, property);
78
- if (!state.equal(previous, value)) {
116
+ if (!(state.equal ?? Object.is)(previous, value)) {
79
117
  Reflect.set(target, property, value);
80
- emitValue(state);
81
- if (isArray) length?.set(target.length);
118
+ emitValue(instance);
119
+ if (state.isArray) state.length?.set(target.length);
82
120
  }
83
121
  return true;
84
122
  }
85
- function updateProxyValue(isArray, state, setObject, setProperty, callback) {
123
+ function updateProxyValue(callback) {
86
124
  if (typeof callback !== "function") throw new TypeError("Callback must be a function");
87
- setProxyValue(isArray, state, setObject, setProperty, callback(state.value));
125
+ setProxyValue.call(this, callback(this[SYMBOL_STATE].value));
88
126
  }
89
127
  //#endregion
90
128
  export { emitProxyValues, getReactiveValueInProxy, getValueInProxy, peekValueInProxy, setProxyValue, setValueInProxy, updateProxyValue };
@@ -1,8 +1,8 @@
1
- import { Computed, ComputedEffect, ReactiveArray, ReactiveState, ReactiveStore, SubscriptionType } from "../models.mjs";
1
+ import { InternalProxy, InternalReadonly, InternalSignal, Subscriber } from "../models.mjs";
2
2
  import { Subscription } from "@oscarpalmer/atoms/subscription";
3
3
  import { Key } from "@oscarpalmer/atoms/models";
4
4
  //#region src/helpers/subscription.d.ts
5
- export declare function subscribeToProxy<Value, Item = Value>(isArray: boolean, instance: ReactiveArray<Value> | ReactiveStore<Value>, state: ReactiveState<Value, Item>, mapped: Map<Key, [Computed<unknown>, ComputedEffect]>, first: Key | ((value: unknown) => unknown), second?: ((value: unknown) => unknown) | boolean, third?: boolean): Subscription;
6
- export declare function subscribeToReactive<Value, Item = Value>(type: SubscriptionType, state: ReactiveState<Value, Item>, callback: (value: unknown) => unknown): Subscription;
7
- export declare function subscribeToSignal<Value, Item = Value>(state: ReactiveState<Value, Item>, callback: (value: unknown) => unknown, copy: boolean): Subscription;
5
+ export declare function subscribeToProxy(this: InternalProxy, first: Key | Subscriber<unknown>, second?: Subscriber<unknown> | boolean, third?: boolean): Subscription;
6
+ export declare function subscribeToReadonly(this: InternalReadonly, subscriber: Subscriber<unknown>): Subscription;
7
+ export declare function subscribeToSignal(this: InternalSignal, subscriber: Subscriber<unknown>, copy?: unknown): Subscription;
8
8
  //#endregion
@@ -1,27 +1,30 @@
1
- import { SUBSCRIPTION_PROPERTY, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_COPY, SUBSCRIPTION_TYPE_ORIGINAL } from "../constants.mjs";
2
- import { getFrozenValue, peekSimpleValue } from "./value.mjs";
1
+ import { SUBSCRIPTION_PROPERTY, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_COPY, SUBSCRIPTION_TYPE_FROZEN, SUBSCRIPTION_TYPE_ORIGINAL, SUBSCRIPTION_TYPE_READONLY, SYMBOL_STATE } from "../constants.mjs";
2
+ import { getFrozenValue, peekSignalValue } from "./value.mjs";
3
3
  import { getReactiveValueInProxy } from "./proxy.mjs";
4
4
  import { isKey } from "@oscarpalmer/atoms/is";
5
5
  import { subscriptions } from "@oscarpalmer/atoms/subscription";
6
6
  //#region src/helpers/subscription.ts
7
- function subscribeToProxy(isArray, instance, state, mapped, first, second, third) {
8
- if (isKey(first)) return getReactiveValueInProxy(instance, mapped, first, isArray).subscribe(second, third);
9
- return subscribeToSignal(state, first, second === true);
7
+ function subscribeToProxy(first, second, third) {
8
+ if (isKey(first)) return getReactiveValueInProxy(this, first).subscribe(second, third);
9
+ return subscribeToSignal.call(this, first, second);
10
10
  }
11
- function subscribeToReactive(type, state, callback) {
12
- state.subscriptions ??= subscriptions({
11
+ function subscribeToReactive(type, subscriber) {
12
+ this[SYMBOL_STATE].subscriptions ??= subscriptions({
13
13
  keys: SUBSCRIPTION_TYPES,
14
14
  property: SUBSCRIPTION_PROPERTY
15
15
  });
16
- const [subscription, existing] = state.subscriptions.create({
16
+ const [subscription, existing] = this[SYMBOL_STATE].subscriptions.create({
17
17
  key: type,
18
- value: callback
18
+ value: subscriber
19
19
  });
20
- if (!existing) callback(type === "frozen" ? getFrozenValue(state.value) : peekSimpleValue(state.value, SUBSCRIPTION_TYPES_COPY.has(type)));
20
+ if (!existing) subscriber(type === "frozen" ? getFrozenValue(this[SYMBOL_STATE].value) : peekSignalValue.call(this, SUBSCRIPTION_TYPES_COPY.has(type)), subscription);
21
21
  return subscription;
22
22
  }
23
- function subscribeToSignal(state, callback, copy) {
24
- return subscribeToReactive(copy ? SUBSCRIPTION_TYPE_COPY : SUBSCRIPTION_TYPE_ORIGINAL, state, callback);
23
+ function subscribeToReadonly(subscriber) {
24
+ return subscribeToReactive.call(this, this.frozen ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_READONLY, subscriber);
25
+ }
26
+ function subscribeToSignal(subscriber, copy) {
27
+ return subscribeToReactive.call(this, copy === true ? SUBSCRIPTION_TYPE_COPY : SUBSCRIPTION_TYPE_ORIGINAL, subscriber);
25
28
  }
26
29
  //#endregion
27
- export { subscribeToProxy, subscribeToReactive, subscribeToSignal };
30
+ export { subscribeToProxy, subscribeToReadonly, subscribeToSignal };
@@ -1,10 +1,11 @@
1
- import { ReactiveState } from "../models.mjs";
1
+ import { InternalSignal, ReactiveState } from "../models.mjs";
2
2
  //#region src/helpers/value.d.ts
3
- export declare function emitValue<Value>(state: ReactiveState<Value, never>): void;
4
- export declare function equalArrays<Value>(state: ReactiveState<Value[], Value>, first: Value[], second: Value[]): boolean;
3
+ export declare function emitValue(instance: InternalSignal): void;
4
+ export declare function equalArrays(state: ReactiveState, first: unknown[], second: unknown[]): boolean;
5
5
  export declare function getFrozenValue(value: unknown): unknown;
6
- export declare function getSimpleValue<Value>(state: ReactiveState<Value, never>): Value;
7
- export declare function handleSimpleValue<Value>(state: ReactiveState<Value, Value>, origin: Value | (() => Value | Promise<Value>) | Promise<Value>, setValue: (state: ReactiveState<Value, Value>, value: Value) => void, onAfter?: () => void): void;
8
- export declare function peekSimpleValue(value: unknown, copy: boolean): unknown;
9
- export declare function updateSimpleValue<Value>(state: ReactiveState<Value, Value>, callback: (value: Value) => Value, setValue: (state: ReactiveState<Value, Value>, value: Value) => void): void;
6
+ export declare function getSignalValue(this: InternalSignal): unknown;
7
+ export declare function getStringValue(this: InternalSignal, json?: boolean): string;
8
+ export declare function handleSignalValue(instance: InternalSignal, origin: unknown, setValue: (instance: InternalSignal, value: unknown) => void, onAfter?: () => void): void;
9
+ export declare function peekSignalValue(this: InternalSignal | [InternalSignal, unknown], copy?: boolean): unknown;
10
+ export declare function updateSignalValue(instance: InternalSignal, callback: (value: unknown) => unknown, setValue: (instance: InternalSignal, value: unknown) => void): void;
10
11
  //#endregion
@@ -1,14 +1,16 @@
1
- import { ACTIVE, BATCH, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_FROZEN } from "../constants.mjs";
1
+ import { ACTIVE, BATCH, SUBSCRIPTION_TYPES, SUBSCRIPTION_TYPES_COPY, SUBSCRIPTION_TYPE_FROZEN, SYMBOL_STATE } from "../constants.mjs";
2
2
  import { flushHandlers } from "../batch.mjs";
3
3
  import { isPlainObject } from "@oscarpalmer/atoms/is";
4
4
  //#region src/helpers/value.ts
5
- function emitValue(state) {
6
- for (const computed of state.computeds) computed.dirty = true;
7
- for (const effect of state.effects) BATCH.handlers.set(effect, effect);
5
+ function emitValue(instance) {
6
+ const state = instance[SYMBOL_STATE];
7
+ if (state.computeds != null && state.computeds.size > 0) for (const computed of state.computeds) computed.dirty = true;
8
+ if (state.effects != null && state.effects.size > 0) for (const effect of state.effects) BATCH.handlers.set(effect, effect);
8
9
  for (const type of SUBSCRIPTION_TYPES) {
9
10
  const subscriptions = state.subscriptions?.values.to.keyed?.get(type);
10
- if (subscriptions != null) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
11
+ if (subscriptions != null && subscriptions.size > 0) for (const [subscription, callback] of subscriptions) BATCH.handlers.set(subscription, {
11
12
  callback,
13
+ instance,
12
14
  state,
13
15
  frozen: type === SUBSCRIPTION_TYPE_FROZEN,
14
16
  copy: SUBSCRIPTION_TYPES_COPY.has(type)
@@ -17,16 +19,17 @@ function emitValue(state) {
17
19
  if (BATCH.depth === 0) flushHandlers();
18
20
  }
19
21
  function equalArrays(state, first, second) {
20
- let { length } = first;
22
+ const { length } = first;
21
23
  if (length !== second.length) return false;
24
+ const eq = state.equal ?? Object.is;
22
25
  let offset = 0;
23
26
  if (length >= 100) {
24
27
  offset = Math.round(length / 10);
25
28
  offset = offset > 25 ? 25 : offset;
26
- for (let index = 0; index < offset; index += 1) if (!state.equal(first[index], second[index])) return false;
29
+ for (let index = 0; index < offset; index += 1) if (!(eq(first[index], second[index]) && eq(first[length - index - 1], second[length - index - 1]))) return false;
27
30
  }
28
- length -= offset;
29
- for (let index = offset; index < length; index += 1) if (!state.equal(first[index], second[index])) return false;
31
+ const end = length - offset;
32
+ for (let index = offset; index < end; index += 1) if (!eq(first[index], second[index])) return false;
30
33
  return true;
31
34
  }
32
35
  function getFrozenValue(value) {
@@ -35,12 +38,22 @@ function getFrozenValue(value) {
35
38
  else if (isPlainObject(frozen)) frozen = Object.freeze({ ...frozen });
36
39
  return frozen;
37
40
  }
38
- function getSimpleValue(state) {
39
- if (ACTIVE.computed != null) state.computeds.add(ACTIVE.computed);
40
- if (ACTIVE.effect != null) state.effects.add(ACTIVE.effect);
41
- return state.value;
41
+ function getSignalValue() {
42
+ if (ACTIVE.computed != null) {
43
+ this[SYMBOL_STATE].computeds ??= /* @__PURE__ */ new Set();
44
+ this[SYMBOL_STATE].computeds.add(ACTIVE.computed);
45
+ }
46
+ if (ACTIVE.effect != null) {
47
+ this[SYMBOL_STATE].effects ??= /* @__PURE__ */ new Set();
48
+ this[SYMBOL_STATE].effects.add(ACTIVE.effect);
49
+ }
50
+ return this[SYMBOL_STATE].value;
51
+ }
52
+ function getStringValue(json) {
53
+ return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
42
54
  }
43
- function handleSimpleValue(state, origin, setValue, onAfter) {
55
+ function handleSignalValue(instance, origin, setValue, onAfter) {
56
+ const state = instance[SYMBOL_STATE];
44
57
  try {
45
58
  let actual = typeof origin === "function" ? origin() : origin;
46
59
  if (actual instanceof Promise) {
@@ -48,26 +61,26 @@ function handleSimpleValue(state, origin, setValue, onAfter) {
48
61
  actual.then((value) => {
49
62
  if (actual === state.promise) {
50
63
  state.promise = void 0;
51
- setValue(state, value);
64
+ setValue(instance, value);
52
65
  }
53
66
  }).catch(() => {
54
67
  if (actual === state.promise) state.promise = void 0;
55
68
  });
56
- } else setValue(state, actual);
69
+ } else setValue(instance, actual);
57
70
  } catch {} finally {
58
71
  onAfter?.();
59
72
  }
60
73
  }
61
- function peekSimpleValue(value, copy) {
62
- let peeked = value;
63
- if (!copy) return peeked;
74
+ function peekSignalValue(copy) {
75
+ let peeked = Array.isArray(this) ? this[1] : this[SYMBOL_STATE].value;
76
+ if (copy !== true) return peeked;
64
77
  if (Array.isArray(peeked)) peeked = peeked.slice();
65
78
  else if (isPlainObject(peeked)) peeked = { ...peeked };
66
79
  return peeked;
67
80
  }
68
- function updateSimpleValue(state, callback, setValue) {
81
+ function updateSignalValue(instance, callback, setValue) {
69
82
  if (typeof callback !== "function") throw new TypeError("Callback must be a function");
70
- handleSimpleValue(state, callback(state.value), setValue);
83
+ handleSignalValue(instance, callback(instance[SYMBOL_STATE].value), setValue);
71
84
  }
72
85
  //#endregion
73
- export { emitValue, equalArrays, getFrozenValue, getSimpleValue, handleSimpleValue, peekSimpleValue, updateSimpleValue };
86
+ export { emitValue, equalArrays, getFrozenValue, getSignalValue, getStringValue, handleSignalValue, peekSignalValue, updateSignalValue };