@oscarpalmer/mora 0.22.0 → 0.24.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 (44) hide show
  1. package/dist/batch.js +8 -9
  2. package/dist/constants.js +36 -0
  3. package/dist/effect.js +7 -8
  4. package/dist/helpers/is.js +9 -19
  5. package/dist/helpers/proxy.js +12 -7
  6. package/dist/helpers/value.js +7 -8
  7. package/dist/index.js +1 -1
  8. package/dist/models.js +0 -0
  9. package/dist/mora.full.js +248 -148
  10. package/dist/subscription.js +7 -5
  11. package/dist/value/array.js +27 -29
  12. package/dist/value/computed.js +18 -21
  13. package/dist/value/reactive.js +2 -1
  14. package/dist/value/signal.js +2 -2
  15. package/dist/value/store.js +12 -3
  16. package/package.json +9 -11
  17. package/src/batch.ts +11 -13
  18. package/src/constants.ts +53 -0
  19. package/src/effect.ts +12 -17
  20. package/src/helpers/is.ts +45 -22
  21. package/src/helpers/proxy.ts +62 -39
  22. package/src/helpers/value.ts +19 -14
  23. package/src/index.ts +1 -0
  24. package/src/models.ts +66 -0
  25. package/src/subscription.ts +14 -16
  26. package/src/value/array.ts +92 -55
  27. package/src/value/computed.ts +29 -39
  28. package/src/value/reactive.ts +11 -25
  29. package/src/value/signal.ts +9 -3
  30. package/src/value/store.ts +55 -13
  31. package/types/batch.d.ts +3 -5
  32. package/types/constants.d.ts +16 -0
  33. package/types/effect.d.ts +2 -1
  34. package/types/helpers/is.d.ts +23 -10
  35. package/types/helpers/proxy.d.ts +4 -3
  36. package/types/helpers/value.d.ts +1 -1
  37. package/types/index.d.ts +1 -0
  38. package/types/models.d.ts +56 -0
  39. package/types/subscription.d.ts +3 -6
  40. package/types/value/array.d.ts +48 -7
  41. package/types/value/computed.d.ts +2 -11
  42. package/types/value/reactive.d.ts +8 -17
  43. package/types/value/signal.d.ts +7 -1
  44. package/types/value/store.d.ts +38 -7
@@ -1,19 +1,7 @@
1
- import {batchDepth, batchedHandlers} from '../batch';
2
- import {type Effect, activeEffect, effect, runEffect} from '../effect';
3
- import {computedName} from '../helpers/is';
4
- import {Reactive, type ReactiveOptions, type ReactiveState} from './reactive';
5
-
6
- export type ComputedEffect = {
7
- dirty: boolean;
8
- instance: Effect;
9
- };
10
-
11
- export type InternalComputed = {
12
- readonly effect: ComputedEffect;
13
- readonly state: ReactiveState<unknown, unknown>;
14
- };
15
-
16
- export let activeComputed: Computed<unknown> | undefined;
1
+ import {ACTIVE, BATCH, NAME_COMPUTED} from '../constants';
2
+ import {effect, runEffect} from '../effect';
3
+ import type {ComputedEffect, ReactiveOptions} from '../models';
4
+ import {Reactive} from './reactive';
17
5
 
18
6
  export class Computed<Value> extends Reactive<Value> {
19
7
  private readonly effect: ComputedEffect = {
@@ -22,36 +10,38 @@ export class Computed<Value> extends Reactive<Value> {
22
10
  };
23
11
 
24
12
  constructor(callback: () => Value, options?: ReactiveOptions<Value>) {
25
- super(computedName, undefined as never, options);
13
+ super(NAME_COMPUTED, undefined as never, options);
26
14
 
27
15
  this.effect.instance = effect(() => {
28
- if (this.effect.dirty) {
29
- const previousComputed = activeComputed;
16
+ if (!this.effect.dirty) {
17
+ return;
18
+ }
30
19
 
31
- activeComputed = this as never;
20
+ const previousComputed = ACTIVE.computed;
32
21
 
33
- const value = callback();
22
+ ACTIVE.computed = this as never;
34
23
 
35
- activeComputed = previousComputed;
24
+ const value = callback();
36
25
 
37
- if (!this.state.equal(this.state.value, value)) {
38
- this.state.value = value;
26
+ ACTIVE.computed = previousComputed;
39
27
 
40
- for (const computed of this.state.computeds) {
41
- computed.effect.dirty = true;
42
- }
28
+ if (!this.state.equal(this.state.value, value)) {
29
+ this.state.value = value;
43
30
 
44
- for (const effect of this.state.effects) {
45
- batchedHandlers.add(effect);
46
- }
31
+ for (const computed of this.state.computeds) {
32
+ computed.effect.dirty = true;
33
+ }
47
34
 
48
- for (const [, subscription] of this.state.subscriptions) {
49
- subscription.callback(value);
50
- }
35
+ for (const effect of this.state.effects) {
36
+ BATCH.handlers.add(effect);
51
37
  }
52
38
 
53
- this.effect.dirty = false;
39
+ for (const [, subscription] of this.state.subscriptions) {
40
+ subscription.callback(value);
41
+ }
54
42
  }
43
+
44
+ this.effect.dirty = false;
55
45
  });
56
46
  }
57
47
 
@@ -59,15 +49,15 @@ export class Computed<Value> extends Reactive<Value> {
59
49
  * @inheritdoc
60
50
  */
61
51
  get(): Value {
62
- if (activeComputed != null && this !== activeComputed) {
63
- this.state.computeds.add(activeComputed);
52
+ if (ACTIVE.computed != null && this !== ACTIVE.computed) {
53
+ this.state.computeds.add(ACTIVE.computed);
64
54
  }
65
55
 
66
- if (activeEffect != null && activeEffect !== this.effect.instance) {
67
- this.state.effects.add(activeEffect);
56
+ if (ACTIVE.effect != null && ACTIVE.effect !== this.effect.instance) {
57
+ this.state.effects.add(ACTIVE.effect);
68
58
  }
69
59
 
70
- if (this.effect.dirty && batchDepth === 0) {
60
+ if (this.effect.dirty && BATCH.depth === 0) {
71
61
  runEffect(this.effect.instance);
72
62
  }
73
63
 
@@ -1,12 +1,6 @@
1
- import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
- import type {Effect} from '../effect';
3
- import {
4
- type Subscription,
5
- type Unsubscribe,
6
- subscribe,
7
- unsubscribe,
8
- } from '../subscription';
9
- import type {Computed} from './computed';
1
+ import {NAME_MORA} from '../constants';
2
+ import type {ReactiveOptions, ReactiveState, Unsubscribe} from '../models';
3
+ import {subscribe, unsubscribe} from '../subscription';
10
4
 
11
5
  export abstract class Reactive<Value, Equal = Value> {
12
6
  protected readonly state: ReactiveState<Value, Equal> = {
@@ -24,18 +18,20 @@ export abstract class Reactive<Value, Equal = Value> {
24
18
  this.state.equal = options.equal;
25
19
  }
26
20
 
27
- Object.defineProperty(this, '$mora', {
21
+ Object.defineProperty(this, NAME_MORA, {
28
22
  value: name,
29
23
  });
30
24
  }
31
25
 
32
26
  /**
33
27
  * Get the value
28
+ * @return Current value
34
29
  */
35
30
  abstract get(): Value;
36
31
 
37
32
  /**
38
33
  * Get the value _(without reactivity)_
34
+ * @return Current value
39
35
  */
40
36
  peek(): Value {
41
37
  return this.state.value;
@@ -43,6 +39,8 @@ export abstract class Reactive<Value, Equal = Value> {
43
39
 
44
40
  /**
45
41
  * Subscribe to changes
42
+ * @param callback Callback for changes
43
+ * @return Unsubscribe callback
46
44
  */
47
45
  subscribe(callback: (value: Value) => void): Unsubscribe {
48
46
  return subscribe(this.state, callback);
@@ -50,6 +48,7 @@ export abstract class Reactive<Value, Equal = Value> {
50
48
 
51
49
  /**
52
50
  * JSON representation of the value
51
+ * @return JSON value
53
52
  */
54
53
  toJSON(): Value {
55
54
  return this.get();
@@ -57,6 +56,7 @@ export abstract class Reactive<Value, Equal = Value> {
57
56
 
58
57
  /**
59
58
  * String representation of the value
59
+ * @return Value as string
60
60
  */
61
61
  toString(): string {
62
62
  return String(this.get());
@@ -64,23 +64,9 @@ export abstract class Reactive<Value, Equal = Value> {
64
64
 
65
65
  /**
66
66
  * Unsubscribe from changes
67
+ * @param callback Callback to unsubscribe
67
68
  */
68
69
  unsubscribe(callback: (value: Value) => void): void {
69
70
  unsubscribe(this.state, callback);
70
71
  }
71
72
  }
72
-
73
- export type ReactiveOptions<Value> = {
74
- /**
75
- * Method to compare values for equality
76
- */
77
- equal?: (first: Value, second: Value) => boolean;
78
- };
79
-
80
- export type ReactiveState<Value, Equal> = {
81
- computeds: Set<Computed<unknown>>;
82
- effects: Set<Effect>;
83
- equal: (first: Equal, second: Equal) => boolean;
84
- subscriptions: Map<GenericCallback, Subscription>;
85
- value: Value;
86
- };
@@ -1,10 +1,11 @@
1
- import {signalName} from '../helpers/is';
1
+ import {NAME_SIGNAL} from '../constants';
2
2
  import {emitValue, getValue} from '../helpers/value';
3
- import {Reactive, type ReactiveOptions} from './reactive';
3
+ import type {ReactiveOptions} from '../models';
4
+ import {Reactive} from './reactive';
4
5
 
5
6
  export class Signal<Value> extends Reactive<Value> {
6
7
  constructor(value: Value, options?: ReactiveOptions<Value>) {
7
- super(signalName, value, options);
8
+ super(NAME_SIGNAL, value, options);
8
9
  }
9
10
 
10
11
  /**
@@ -16,6 +17,7 @@ export class Signal<Value> extends Reactive<Value> {
16
17
 
17
18
  /**
18
19
  * Set the value
20
+ * @param value New value
19
21
  */
20
22
  set(value: Value): void {
21
23
  if (!this.state.equal(this.state.value, value)) {
@@ -27,6 +29,7 @@ export class Signal<Value> extends Reactive<Value> {
27
29
 
28
30
  /**
29
31
  * Update the value _(based on the current value)_
32
+ * @param callback Callback to update the value
30
33
  */
31
34
  update(callback: (value: Value) => Value): void {
32
35
  this.set(callback(this.state.value));
@@ -35,6 +38,9 @@ export class Signal<Value> extends Reactive<Value> {
35
38
 
36
39
  /**
37
40
  * Create a reactive value
41
+ * @param value Initial value
42
+ * @param options Optional reactivity options
43
+ * @returns Reactive value
38
44
  */
39
45
  export function signal<Value>(
40
46
  value: Value,
@@ -4,26 +4,34 @@ import type {
4
4
  Key,
5
5
  PlainObject,
6
6
  } from '@oscarpalmer/atoms/models';
7
- import {storeName} from '../helpers/is';
7
+ import {NAME_STORE} from '../constants';
8
8
  import {
9
9
  getReactiveValueInProxy,
10
+ emityProxyValues,
10
11
  setProxyValue,
11
12
  setValueInProxy,
12
13
  } from '../helpers/proxy';
13
- import {getValue} from '../helpers/value';
14
- import {type Unsubscribe, noop, subscribe} from '../subscription';
14
+ import {emitValue, getValue} from '../helpers/value';
15
+ import type {InternalComputed, ReactiveOptions, Unsubscribe} from '../models';
16
+ import {noop, subscribe} from '../subscription';
15
17
  import type {Computed} from './computed';
16
- import {Reactive, type ReactiveOptions} from './reactive';
18
+ import {Reactive} from './reactive';
17
19
 
18
20
  export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
19
- #keyed = new Map<Key, Computed<unknown>>();
21
+ readonly #keyed = new Map<Key, Computed<unknown>>();
20
22
 
21
23
  constructor(value: Value, options?: ReactiveOptions<Value>) {
22
24
  super(
23
- storeName,
25
+ NAME_STORE,
24
26
  new Proxy(value, {
25
- set: (target, property, value) =>
26
- setValueInProxy(target, property, value, this.state, false),
27
+ set: (target: Value, property: PropertyKey, value: unknown) =>
28
+ setValueInProxy({
29
+ target,
30
+ property,
31
+ value,
32
+ isArray: false,
33
+ state: this.state,
34
+ }),
27
35
  }),
28
36
  options,
29
37
  );
@@ -35,12 +43,16 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
35
43
  get(): Value;
36
44
 
37
45
  /**
38
- * Get a value by key _(without reactivity)_
46
+ * Get a value by key
47
+ * @param key Key of the value to get
48
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
39
49
  */
40
- get(key: keyof Value): Value[keyof Value];
50
+ get<Key extends keyof Value>(key: Key): Value[Key];
41
51
 
42
52
  /**
43
- * Get a value by key _(without reactivity)_
53
+ * Get a value by key
54
+ * @param key Key of the value to get
55
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
44
56
  */
45
57
  get(key: Key): unknown;
46
58
 
@@ -50,18 +62,33 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
50
62
  : getValue(this.state);
51
63
  }
52
64
 
65
+ /**
66
+ * Notify dependents of changes
67
+ *
68
+ * _This bypasses equality checks and will immediately notify dependents.
69
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
70
+ */
71
+ notify(): void {
72
+ emityProxyValues(this.state, this.#keyed);
73
+ }
74
+
53
75
  /**
54
76
  * Get the value _(without reactivity)_
77
+ * @returns The current value
55
78
  */
56
79
  peek(): Value;
57
80
 
58
81
  /**
59
82
  * Get a value by key _(without reactivity)_
83
+ * @param key Key of the value to get
84
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
60
85
  */
61
- peek(key: keyof Value): Value[keyof Value];
86
+ peek<Key extends keyof Value>(key: Key): Value[Key];
62
87
 
63
88
  /**
64
89
  * Get a value by key _(without reactivity)_
90
+ * @param key Key of the value to get
91
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
65
92
  */
66
93
  peek(key: Key): unknown;
67
94
 
@@ -71,16 +98,21 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
71
98
 
72
99
  /**
73
100
  * Set the value
101
+ * @param value New value _(defaults to an empty object)_
74
102
  */
75
103
  set(value?: Value): void;
76
104
 
77
105
  /**
78
106
  * Set a value by key
107
+ * @param key Key of the value to set
108
+ * @param value New value
79
109
  */
80
- set(key: keyof Value, value: Value[keyof Value]): void;
110
+ set<Key extends keyof Value>(key: Key, value: Value[Key]): void;
81
111
 
82
112
  /**
83
113
  * Set a value by key
114
+ * @param key Key of the value to set
115
+ * @param value New value
84
116
  */
85
117
  set(key: Key, value: unknown): void;
86
118
 
@@ -99,6 +131,9 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
99
131
 
100
132
  /**
101
133
  * Subscribe to changes for a specific key
134
+ * @param key Key of the value to subscribe to
135
+ * @param callback Callback for changes
136
+ * @returns Unsubscribe callback
102
137
  */
103
138
  subscribe<Key extends keyof Value>(
104
139
  key: Key,
@@ -107,6 +142,9 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
107
142
 
108
143
  /**
109
144
  * Subscribe to changes for a specific key
145
+ * @param key Key of the value to subscribe to
146
+ * @param callback Callback for changes
147
+ * @returns Unsubscribe callback
110
148
  */
111
149
  subscribe(key: Key, callback: (value: unknown) => void): Unsubscribe;
112
150
 
@@ -125,6 +163,7 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
125
163
 
126
164
  /**
127
165
  * Update the value _(based on the current value)_
166
+ * @param callback Callback to update the value
128
167
  */
129
168
  update(callback: (value: Value) => Value): void {
130
169
  const updated = callback({...this.state.value});
@@ -137,6 +176,9 @@ export class Store<Value extends PlainObject> extends Reactive<Value, Value> {
137
176
 
138
177
  /**
139
178
  * Create a reactive store
179
+ * @param value Initial object value
180
+ * @param options Optional reactivity options
181
+ * @returns Reactive store
140
182
  */
141
183
  export function store<Value extends PlainObject>(
142
184
  value: Value,
package/types/batch.d.ts CHANGED
@@ -1,13 +1,11 @@
1
- import { type Effect } from './effect';
2
- import type { Subscription } from './subscription';
3
1
  export declare function flushHandlers(): void;
4
2
  /**
5
- * Start batching effects _(use `stopBatch` to flush and run batched effects)_
3
+ * Start batching effects
4
+ *
5
+ * _(Use {@link stopBatch} to flush and run batched effects)_
6
6
  */
7
7
  export declare function startBatch(): void;
8
8
  /**
9
9
  * Stop batching effects and flush _(run)_ them
10
10
  */
11
11
  export declare function stopBatch(): void;
12
- export declare const batchedHandlers: Set<Subscription | Effect>;
13
- export declare let batchDepth: number;
@@ -0,0 +1,16 @@
1
+ import type { Active, Batch } from './models';
2
+ export declare const ACTIVE: Active;
3
+ export declare const ARRAY_THRESHOLD = 100;
4
+ export declare const ARRAY_OFFSET = 25;
5
+ export declare const ARRAY_PEEK = 10;
6
+ export declare const BATCH: Batch;
7
+ export declare const METHODS_AFFECTING_LENGTH: Set<string>;
8
+ export declare const METHODS_UPDATE: Set<string>;
9
+ export declare const NAME_ARRAY = "array";
10
+ export declare const NAME_COMPUTED = "computed";
11
+ export declare const NAME_EFFECT = "effect";
12
+ export declare const NAME_MORA = "$mora";
13
+ export declare const NAME_SIGNAL = "signal";
14
+ export declare const NAME_STORE = "store";
15
+ export declare const NAMES: Set<string>;
16
+ export declare const PROPERTY_LENGTH = "length";
package/types/effect.d.ts CHANGED
@@ -7,6 +7,7 @@ export declare class Effect {
7
7
  export declare function runEffect(effect: Effect): void;
8
8
  /**
9
9
  * Create an effect
10
+ * @param callback Callback for handling signal effects
11
+ * @returns Effect
10
12
  */
11
13
  export declare function effect(callback: GenericCallback): Effect;
12
- export declare let activeEffect: Effect | undefined;
@@ -7,24 +7,37 @@ import type { Signal } from '../value/signal';
7
7
  import type { Store } from '../value/store';
8
8
  /**
9
9
  * Is the value a reactive array?
10
+ * @param value Value to check
11
+ * @returns True if value is a {@link ReactiveArray}
10
12
  */
11
- export declare function isArray(value: unknown): value is ReactiveArray<unknown>;
13
+ export declare function isArray<Item>(value: unknown): value is ReactiveArray<Item>;
12
14
  /**
13
15
  * Is the value a computed signal?
16
+ * @param value Value to check
17
+ * @returns True if value is a {@link Computed}
14
18
  */
15
- export declare function isComputed(value: unknown): value is Computed<unknown>;
19
+ export declare function isComputed<Value>(value: unknown): value is Computed<Value>;
16
20
  /**
17
21
  * Is the value an effect?
22
+ * @param value Value to check
23
+ * @returns True if value is an {@link Effect}
18
24
  */
19
25
  export declare function isEffect(value: unknown): value is Effect;
20
- export declare function isReactive(value: unknown): value is Reactive<unknown>;
26
+ /**
27
+ * Is the value reactive?
28
+ * @param value Value to check
29
+ * @returns True if value is a {@link Reactive}
30
+ */
31
+ export declare function isReactive<Value, Equal = Value>(value: unknown): value is Reactive<Value, Equal>;
21
32
  /**
22
33
  * Is the value a signal?
34
+ * @param value Value to check
35
+ * @returns True if value is a {@link Signal}
36
+ */
37
+ export declare function isSignal<Value>(value: unknown): value is Signal<Value>;
38
+ /**
39
+ * Is the value a reactive store?
40
+ * @param value Value to check
41
+ * @returns True if value is a {@link Store}
23
42
  */
24
- export declare function isSignal(value: unknown): value is Signal<unknown>;
25
- export declare function isStore(value: unknown): value is Store<PlainObject>;
26
- export declare const arrayName = "array";
27
- export declare const computedName = "computed";
28
- export declare const effectName = "effect";
29
- export declare const signalName = "signal";
30
- export declare const storeName = "store";
43
+ export declare function isStore<Value extends PlainObject>(value: unknown): value is Store<Value>;
@@ -1,10 +1,11 @@
1
1
  import type { ArrayOrPlainObject, Key, PlainObject } from '@oscarpalmer/atoms/models';
2
+ import type { ReactiveState, SetValueInProxyParameters } from '../models';
2
3
  import type { ReactiveArray } from '../value/array';
3
4
  import { type Computed } from '../value/computed';
4
- import type { ReactiveState } from '../value/reactive';
5
- import type { Signal } from '../value/signal';
6
5
  import type { Store } from '../value/store';
6
+ export declare function emityProxyValues<Value>(state: ReactiveState<Value, Value>, mapped: Map<Key, Computed<unknown>>): void;
7
+ export declare function emityProxyValues<Value>(state: ReactiveState<Value[], Value>, mapped: Map<Key, Computed<unknown>>): void;
7
8
  export declare function getReactiveValueInProxy<Value>(array: ReactiveArray<Value>, mapped: Map<Key, Computed<unknown>>, index: number, isArray: true): Computed<unknown>;
8
9
  export declare function getReactiveValueInProxy<Value extends PlainObject>(store: Store<Value>, mapped: Map<Key, Computed<unknown>>, key: Key, isArray: false): Computed<unknown>;
9
10
  export declare function setProxyValue(proxy: ArrayOrPlainObject, value: ArrayOrPlainObject): void;
10
- export declare function setValueInProxy<Value extends ArrayOrPlainObject, Equal>(target: Value, property: PropertyKey, value: unknown, state: ReactiveState<Value, Equal>, isArray: boolean, length?: Signal<number>): boolean;
11
+ export declare function setValueInProxy<Value extends ArrayOrPlainObject, Equal>(parameters: SetValueInProxyParameters<Value, Equal>): boolean;
@@ -1,4 +1,4 @@
1
- import type { ReactiveState } from '../value/reactive';
1
+ import type { ReactiveState } from '../models';
2
2
  export declare function emitValue<Value>(state: ReactiveState<Value, never>): void;
3
3
  export declare function equalArrays<Value>(state: ReactiveState<Value[], Value>, first: Value[], second: Value[]): boolean;
4
4
  export declare function getValue<Value>(state: ReactiveState<Value, never>): Value;
package/types/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { startBatch, stopBatch } from './batch';
2
2
  export { effect, type Effect } from './effect';
3
3
  export { isArray, isComputed, isEffect, isReactive, isSignal, } from './helpers/is';
4
+ export type { Unsubscribe } from './models';
4
5
  export { array, type ReactiveArray } from './value/array';
5
6
  export { computed, type Computed } from './value/computed';
6
7
  export type { Reactive } from './value/reactive';
@@ -0,0 +1,56 @@
1
+ import type { GenericCallback } from '@oscarpalmer/atoms/models';
2
+ import type { Effect } from './effect';
3
+ import type { Subscription } from './subscription';
4
+ import type { Computed } from './value/computed';
5
+ import type { Signal } from './value/signal';
6
+ export type Active = {
7
+ computed?: Computed<unknown>;
8
+ effect?: Effect;
9
+ };
10
+ export type Batch = {
11
+ depth: number;
12
+ handlers: Set<Effect | Subscription>;
13
+ };
14
+ export type ComputedEffect = {
15
+ dirty: boolean;
16
+ instance: Effect;
17
+ };
18
+ export type EffectState = {
19
+ callback: GenericCallback;
20
+ };
21
+ export type InternalComputed = {
22
+ readonly effect: ComputedEffect;
23
+ readonly state: ReactiveState<unknown, unknown>;
24
+ };
25
+ export type InternalEffect = {
26
+ state: EffectState;
27
+ };
28
+ export type ReactiveOptions<Value> = {
29
+ /**
30
+ * Method for comparing values for equality
31
+ * @param first First value
32
+ * @param second Second value
33
+ * @returns Are the values equal?
34
+ * @default Object.is
35
+ */
36
+ equal?: (first: Value, second: Value) => boolean;
37
+ };
38
+ export type ReactiveState<Value, Equal> = {
39
+ computeds: Set<Computed<unknown>>;
40
+ effects: Set<Effect>;
41
+ equal: (first: Equal, second: Equal) => boolean;
42
+ subscriptions: Map<GenericCallback, Subscription>;
43
+ value: Value;
44
+ };
45
+ export type SetValueInProxyParameters<Value, Equal> = {
46
+ target: Value;
47
+ property: PropertyKey;
48
+ value: unknown;
49
+ state: ReactiveState<Value, Equal>;
50
+ isArray: boolean;
51
+ length?: Signal<number>;
52
+ };
53
+ /**
54
+ * Unsubscribe from changes
55
+ */
56
+ export type Unsubscribe = () => void;
@@ -1,14 +1,11 @@
1
1
  import type { GenericCallback } from '@oscarpalmer/atoms/models';
2
- import type { ReactiveState } from './value/reactive';
2
+ import type { ReactiveState, Unsubscribe } from './models';
3
3
  export declare class Subscription {
4
- state: ReactiveState<unknown, never>;
5
4
  callback: GenericCallback;
5
+ state: ReactiveState<unknown, never>;
6
6
  constructor(state: ReactiveState<unknown, never>, callback: GenericCallback);
7
+ destroy(): void;
7
8
  }
8
- /**
9
- * Unsubscribe from changes
10
- */
11
- export type Unsubscribe = () => void;
12
9
  export declare function noop(): void;
13
10
  export declare function subscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): Unsubscribe;
14
11
  export declare function unsubscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): void;