@oscarpalmer/mora 0.34.0 → 0.36.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.
@@ -5,8 +5,8 @@ export declare const ARRAY_THRESHOLD = 100;
5
5
  export declare const ARRAY_OFFSET = 25;
6
6
  export declare const ARRAY_PEEK = 10;
7
7
  export declare const BATCH: Batch;
8
- export declare const METHODS_AFFECTING_LENGTH: Set<string>;
9
- export declare const METHODS_UPDATE: Set<string>;
8
+ export declare const METHODS_AFFECTING_LENGTH: Set<string | symbol>;
9
+ export declare const METHODS_UPDATE: Set<string | symbol>;
10
10
  export declare const NAME_ARRAY = "array";
11
11
  export declare const NAME_COMPUTED = "computed";
12
12
  export declare const NAME_EFFECT = "effect";
@@ -1,11 +1,11 @@
1
- import { Computed, InternalProxy, ReactiveArray, ReactiveStore } from "../models.mjs";
1
+ import { InternalArray, InternalComputed, InternalStore } from "../models.mjs";
2
2
  import { Key } from "@oscarpalmer/atoms/models";
3
3
  //#region src/helpers/proxy.d.ts
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;
4
+ export declare function emitProxyValues(this: InternalArray | InternalStore): void;
5
+ export declare function getReactiveValueInProxy(instance: InternalArray | InternalStore, key: Key): InternalComputed;
6
+ export declare function getValueInProxy(this: InternalArray | InternalStore, first?: unknown): unknown;
7
+ export declare function peekValueInProxy(this: InternalArray | InternalStore, first?: unknown, second?: boolean): unknown;
8
+ export declare function setProxyValue(this: InternalArray | InternalStore, first?: unknown, second?: unknown): void;
9
+ export declare function setValueInProxy(instance: InternalArray | InternalStore, target: object, property: PropertyKey, value: unknown): boolean;
10
+ export declare function updateProxyValue(this: InternalArray | InternalStore, callback: unknown): void;
11
11
  //#endregion
@@ -24,8 +24,12 @@ function getReactiveValueInProxy(instance, key) {
24
24
  return item[0];
25
25
  }
26
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);
27
+ let signal;
28
+ if (this[SYMBOL_STATE].isArray ? typeof first === "number" : isKey(first)) signal = getReactiveValueInProxy(this, first);
29
+ return getSignalValue.call(signal ?? this);
30
+ }
31
+ function isProxyKey(isArray, value) {
32
+ return isArray ? typeof value === "number" : isKey(value);
29
33
  }
30
34
  function isProxyObject(isArray, value) {
31
35
  return value == null || (isArray ? Array.isArray(value) : isPlainObject(value));
@@ -39,23 +43,24 @@ function peekValueInProxy(first, second) {
39
43
  }
40
44
  function setProxyObject(state, value) {
41
45
  if (state.isArray) {
42
- state.value.splice(0, state.value.length, ...value ?? []);
46
+ const values = state.value;
47
+ values.splice(0, values.length, ...value ?? []);
43
48
  return;
44
49
  }
45
50
  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
+ const current = state.value;
52
+ const next = value ?? {};
53
+ const currentKeys = Object.keys(current);
54
+ const nextKeys = Object.keys(next);
55
+ let { length } = currentKeys;
51
56
  for (let index = 0; index < length; index += 1) {
52
- const key = proxyKeys[index];
53
- proxy[key] = actualKeys.includes(key) ? actual[key] : void 0;
57
+ const key = currentKeys[index];
58
+ current[key] = nextKeys.includes(key) ? next[key] : void 0;
54
59
  }
55
- length = actualKeys.length;
60
+ length = nextKeys.length;
56
61
  for (let index = 0; index < length; index += 1) {
57
- const key = actualKeys[index];
58
- if (!proxyKeys.includes(key)) proxy[key] = actual[key];
62
+ const key = nextKeys[index];
63
+ if (!currentKeys.includes(key)) current[key] = next[key];
59
64
  }
60
65
  stopBatch();
61
66
  }
@@ -64,8 +69,10 @@ function setProxyProperty(state, property, value) {
64
69
  state.value[property] = value;
65
70
  return;
66
71
  }
67
- const actual = property < 0 ? state.value.length + property : property;
68
- if (actual > -1) state.value[actual] = value;
72
+ const array = state.value;
73
+ const index = property;
74
+ const actual = index < 0 ? array.length + index : index;
75
+ if (actual > -1) array[actual] = value;
69
76
  }
70
77
  function setProxyValue(first, second) {
71
78
  const state = this[SYMBOL_STATE];
@@ -77,34 +84,34 @@ function setProxyValue(first, second) {
77
84
  setProxyObject(state, first);
78
85
  return;
79
86
  }
80
- const property = state.isArray ? typeof first === "number" : isKey(first);
81
- if (state.isArray && property && Number.isNaN(first)) return;
82
- let actual = property ? second : first;
87
+ const keyed = isProxyKey(state.isArray, first);
88
+ if (state.isArray && keyed && Number.isNaN(first)) return;
89
+ let actual = keyed ? second : first;
83
90
  if (typeof actual === "function") try {
84
91
  actual = actual();
85
92
  } catch {
86
93
  return;
87
94
  }
88
95
  if (actual instanceof Promise) {
89
- if (property) {
96
+ if (keyed) {
90
97
  state.promises ??= /* @__PURE__ */ new Map();
91
98
  state.promises.set(first, actual);
92
99
  } else state.promise = actual;
93
100
  actual.then((value) => {
94
- if (property && state.promises.get(first) === actual) {
95
- state.promises.delete(first);
101
+ if (keyed && state.promises?.get(first) === actual) {
102
+ state.promises?.delete(first);
96
103
  setProxyProperty(state, first, value);
97
104
  return;
98
105
  }
99
- if (!property && isProxyObject(state.isArray, value) && state.promise === actual) {
106
+ if (!keyed && isProxyObject(state.isArray, value) && state.promise === actual) {
100
107
  state.promise = void 0;
101
108
  setProxyObject(state, value);
102
109
  }
103
110
  }).catch(() => {
104
- if (property && state.promises.get(first) === actual) state.promises.delete(first);
105
- else if (!property && state.promise === actual) state.promise = void 0;
111
+ if (keyed && state.promises?.get(first) === actual) state.promises?.delete(first);
112
+ else if (!keyed && state.promise === actual) state.promise = void 0;
106
113
  });
107
- } else if (property) setProxyProperty(state, first, actual);
114
+ } else if (keyed) setProxyProperty(state, first, actual);
108
115
  else if (isProxyObject(state.isArray, actual)) setProxyObject(state, actual);
109
116
  }
110
117
  function setValueInProxy(instance, target, property, value) {
@@ -1,8 +1,8 @@
1
- import { InternalProxy, InternalReadonly, InternalSignal, Subscriber } from "../models.mjs";
1
+ import { InternalArray, InternalReadonly, InternalStateful, InternalStore, 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(this: InternalProxy, first: Key | Subscriber<unknown>, second?: Subscriber<unknown> | boolean, third?: boolean): Subscription;
5
+ export declare function subscribeToProxy(this: InternalArray | InternalStore, first: Key | Subscriber<unknown>, second?: Subscriber<unknown> | boolean, third?: boolean): Subscription;
6
6
  export declare function subscribeToReadonly(this: InternalReadonly, subscriber: Subscriber<unknown>): Subscription;
7
- export declare function subscribeToSignal(this: InternalSignal, subscriber: Subscriber<unknown>, copy?: unknown): Subscription;
7
+ export declare function subscribeToSignal(this: InternalStateful, subscriber: Subscriber<unknown>, copy?: unknown): Subscription;
8
8
  //#endregion
@@ -1,11 +1,12 @@
1
- import { InternalSignal, ReactiveState } from "../models.mjs";
1
+ import { InternalStateful } from "../models.mjs";
2
2
  //#region src/helpers/value.d.ts
3
- export declare function emitValue(instance: InternalSignal): void;
4
- export declare function equalArrays(state: ReactiveState, first: unknown[], second: unknown[]): boolean;
3
+ export declare function emitValue(instance: InternalStateful): void;
4
+ export declare function equalArrays(first: unknown[], second: unknown[], equal?: (first: unknown, second: unknown) => boolean): boolean;
5
5
  export declare function getFrozenValue(value: unknown): unknown;
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;
6
+ export declare function getJsonValue(this: InternalStateful): unknown;
7
+ export declare function getSignalValue(this: InternalStateful): unknown;
8
+ export declare function getStringValue(this: InternalStateful, json?: boolean): string;
9
+ export declare function handleSignal(instance: InternalStateful, origin: unknown, setValue: (instance: InternalStateful, value: unknown) => void, onAfter?: () => void): void;
10
+ export declare function peekSignalValue(this: InternalStateful | [InternalStateful, unknown], copy?: boolean): unknown;
11
+ export declare function updateSignal(instance: InternalStateful, callback: (value: unknown) => unknown, setValue: (instance: InternalStateful, value: unknown) => void): void;
11
12
  //#endregion
@@ -18,10 +18,10 @@ function emitValue(instance) {
18
18
  }
19
19
  if (BATCH.depth === 0) flushHandlers();
20
20
  }
21
- function equalArrays(state, first, second) {
21
+ function equalArrays(first, second, equal) {
22
22
  const { length } = first;
23
23
  if (length !== second.length) return false;
24
- const eq = state.equal ?? Object.is;
24
+ const eq = equal ?? Object.is;
25
25
  let offset = 0;
26
26
  if (length >= 100) {
27
27
  offset = Math.round(length / 10);
@@ -38,21 +38,25 @@ function getFrozenValue(value) {
38
38
  else if (isPlainObject(frozen)) frozen = Object.freeze({ ...frozen });
39
39
  return frozen;
40
40
  }
41
+ function getJsonValue() {
42
+ return this[SYMBOL_STATE].value;
43
+ }
41
44
  function getSignalValue() {
45
+ const state = this[SYMBOL_STATE];
42
46
  if (ACTIVE.computed != null) {
43
- this[SYMBOL_STATE].computeds ??= /* @__PURE__ */ new Set();
44
- this[SYMBOL_STATE].computeds.add(ACTIVE.computed);
47
+ state.computeds ??= /* @__PURE__ */ new Set();
48
+ state.computeds.add(ACTIVE.computed);
45
49
  }
46
50
  if (ACTIVE.effect != null) {
47
- this[SYMBOL_STATE].effects ??= /* @__PURE__ */ new Set();
48
- this[SYMBOL_STATE].effects.add(ACTIVE.effect);
51
+ state.effects ??= /* @__PURE__ */ new Set();
52
+ state.effects.add(ACTIVE.effect);
49
53
  }
50
- return this[SYMBOL_STATE].value;
54
+ return state.value;
51
55
  }
52
56
  function getStringValue(json) {
53
57
  return json === true ? JSON.stringify(this[SYMBOL_STATE].value) : String(this[SYMBOL_STATE].value);
54
58
  }
55
- function handleSignalValue(instance, origin, setValue, onAfter) {
59
+ function handleSignal(instance, origin, setValue, onAfter) {
56
60
  const state = instance[SYMBOL_STATE];
57
61
  try {
58
62
  let actual = typeof origin === "function" ? origin() : origin;
@@ -78,9 +82,9 @@ function peekSignalValue(copy) {
78
82
  else if (isPlainObject(peeked)) peeked = { ...peeked };
79
83
  return peeked;
80
84
  }
81
- function updateSignalValue(instance, callback, setValue) {
85
+ function updateSignal(instance, callback, setValue) {
82
86
  if (typeof callback !== "function") throw new TypeError("Callback must be a function");
83
- handleSignalValue(instance, callback(instance[SYMBOL_STATE].value), setValue);
87
+ handleSignal(instance, callback(instance[SYMBOL_STATE].value), setValue);
84
88
  }
85
89
  //#endregion
86
- export { emitValue, equalArrays, getFrozenValue, getSignalValue, getStringValue, handleSignalValue, peekSignalValue, updateSignalValue };
90
+ export { emitValue, equalArrays, getFrozenValue, getJsonValue, getSignalValue, getStringValue, handleSignal, peekSignalValue, updateSignal };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { startBatch, stopBatch } from "./batch.mjs";
2
- import { Computed, Effect, ReactiveArray, ReactiveStore, ReadonlySignal, Signal } from "./models.mjs";
2
+ import { Computed, Effect, Reactive, ReactiveArray, ReactiveStore, ReadonlySignal, Signal } from "./models.mjs";
3
3
  import { effect } from "./effect.mjs";
4
4
  import { isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal } from "./helpers/is.mjs";
5
5
  import { array } from "./value/array.mjs";
@@ -7,4 +7,4 @@ import { computed } from "./value/computed.mjs";
7
7
  import { signal } from "./value/signal.mjs";
8
8
  import { store } from "./value/store.mjs";
9
9
  import { Subscription } from "@oscarpalmer/atoms/subscription";
10
- export { type Computed, type Effect, type ReactiveArray, type ReactiveStore, type ReadonlySignal, type Signal, type Subscription, array, computed, effect, isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal, signal, startBatch, stopBatch, store };
10
+ export { type Computed, type Effect, type Reactive, type ReactiveArray, type ReactiveStore, type ReadonlySignal, type Signal, type Subscription, array, computed, effect, isComputed, isEffect, isReactive, isReactiveArray, isReactiveStore, isReadonlySignal, isSignal, signal, startBatch, stopBatch, store };
package/dist/models.d.mts CHANGED
@@ -11,7 +11,7 @@ export type Batch = {
11
11
  flushing: boolean;
12
12
  handlers: Map<EffectState | Subscription, EffectState | StoredSubscription>;
13
13
  };
14
- export type Computed<Value> = Reactive<Value> & SimpleReactive<Value>;
14
+ export type Computed<Value> = Reactive<Value>;
15
15
  export type ComputedEffect = {
16
16
  dirty: boolean;
17
17
  instance: EffectState;
@@ -20,19 +20,37 @@ export type Effect = {};
20
20
  export type EffectState = {
21
21
  callback: GenericCallback;
22
22
  };
23
+ export type InternalArray = {
24
+ [SYMBOL_STATE]: ReactiveProxyState;
25
+ } & ReactiveArray<unknown>;
23
26
  export type InternalComputed = {
24
27
  [SYMBOL_EFFECT]: ComputedEffect;
25
- } & InternalSignal;
26
- export type InternalProxy = {
27
- [SYMBOL_STATE]: ReactiveProxyState;
28
- };
28
+ [SYMBOL_STATE]: SignalState;
29
+ } & Computed<unknown>;
29
30
  export type InternalReadonly = {
30
31
  frozen: boolean;
31
- } & InternalSignal;
32
- export type InternalSignal = {
32
+ } & InternalStateful & ReadonlySignal<unknown>;
33
+ export type InternalSignal = InternalStateful & Signal<unknown>;
34
+ export type InternalStateful = {
33
35
  [SYMBOL_STATE]: SignalState;
34
36
  };
37
+ export type InternalStore = {
38
+ [SYMBOL_STATE]: ReactiveProxyState;
39
+ } & ReactiveStore<PlainObject>;
35
40
  export type Reactive<Value> = {
41
+ /**
42
+ * Get the value
43
+ *
44
+ * @returns Current value
45
+ */
46
+ get(): Value;
47
+ /**
48
+ * Get the value _(without reactivity)_
49
+ *
50
+ * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
51
+ * @returns Current value
52
+ */
53
+ peek(copy?: boolean): Value;
36
54
  /**
37
55
  * _JSON_ representation of the value
38
56
  *
@@ -46,6 +64,14 @@ export type Reactive<Value> = {
46
64
  * @returns Value as string
47
65
  */
48
66
  toString(json?: boolean): string;
67
+ /**
68
+ * Subscribe to changes
69
+ *
70
+ * @param subscriber Callback for changes
71
+ * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
72
+ * @returns Subscription
73
+ */
74
+ subscribe(subscriber: Subscriber<Value>, copy?: boolean): Subscription;
49
75
  };
50
76
  export type ReactiveArray<Item> = {
51
77
  /**
@@ -240,16 +266,16 @@ export type ReactiveOptions<Value> = {
240
266
  export type ReactiveProxyState = {
241
267
  isArray: boolean;
242
268
  length?: Signal<number>;
243
- mapped?: Map<string, [Computed<unknown>, ComputedEffect]>;
269
+ mapped?: Map<string, [InternalComputed, ComputedEffect]>;
244
270
  } & SignalState;
245
- export type ReactiveState = {
271
+ export type ReactiveState<Value = unknown, Item = Value> = {
246
272
  computeds?: Set<ComputedEffect>;
247
273
  effects?: Set<EffectState>;
248
- equal?: (first: unknown, second: unknown) => boolean;
274
+ equal?: (first: Item, second: Item) => boolean;
249
275
  promise?: Promise<unknown>;
250
276
  promises?: Map<Key, Promise<never>>;
251
277
  subscriptions?: Subscriptions<GenericCallback>;
252
- value: unknown;
278
+ value: Value;
253
279
  };
254
280
  export type ReactiveStore<Store> = {
255
281
  /**
@@ -379,7 +405,7 @@ export type ReadonlySignal<Value> = {
379
405
  * Is the signal frozen?
380
406
  */
381
407
  get frozen(): boolean;
382
- } & Reactive<Value> & SimpleReactive<Value>;
408
+ } & Reactive<Value>;
383
409
  export type ReadonlySignalValue<Value> = Value extends unknown[] ? Readonly<Value> : Value extends PlainObject ? Readonly<Value> : Value;
384
410
  export type Signal<Value> = {
385
411
  /**
@@ -408,38 +434,15 @@ export type Signal<Value> = {
408
434
  * @param callback Callback to update the value
409
435
  */
410
436
  update(callback: (value: Value) => Value): void;
411
- } & Reactive<Value> & SimpleReactive<Value>;
437
+ } & Reactive<Value>;
412
438
  export type SignalState = {
413
439
  readonlies?: ReadonlyInstances<unknown>;
414
440
  } & ReactiveState;
415
- type SimpleReactive<Value> = {
416
- /**
417
- * Get the value
418
- *
419
- * @returns Current value
420
- */
421
- get(): Value;
422
- /**
423
- * Get the value _(without reactivity)_
424
- *
425
- * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
426
- * @returns Current value
427
- */
428
- peek(copy?: boolean): Value;
429
- /**
430
- * Subscribe to changes
431
- *
432
- * @param subscriber Callback for changes
433
- * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
434
- * @returns Subscription
435
- */
436
- subscribe(subscriber: Subscriber<Value>, copy?: boolean): Subscription;
437
- };
438
441
  export type StoredSubscription = {
439
442
  callback: GenericCallback;
440
443
  copy: boolean;
441
444
  frozen: boolean;
442
- instance: InternalSignal;
445
+ instance: InternalStateful;
443
446
  state: SignalState;
444
447
  };
445
448
  export type Subscriber<Value> = (value: Value, subscription: Subscription) => void;