@oscarpalmer/mora 0.31.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 (58) hide show
  1. package/dist/batch.d.mts +4 -5
  2. package/dist/batch.mjs +4 -2
  3. package/dist/constants.d.mts +31 -19
  4. package/dist/constants.mjs +19 -2
  5. package/dist/effect.d.mts +5 -5
  6. package/dist/effect.mjs +8 -5
  7. package/dist/helpers/is.d.mts +14 -9
  8. package/dist/helpers/is.mjs +6 -0
  9. package/dist/helpers/misc.d.mts +4 -0
  10. package/dist/helpers/misc.mjs +9 -0
  11. package/dist/helpers/proxy.d.mts +10 -10
  12. package/dist/helpers/proxy.mjs +83 -27
  13. package/dist/helpers/subscription.d.mts +8 -0
  14. package/dist/helpers/subscription.mjs +30 -0
  15. package/dist/helpers/value.d.mts +10 -7
  16. package/dist/helpers/value.mjs +56 -17
  17. package/dist/index.d.mts +3 -2
  18. package/dist/models.d.mts +82 -101
  19. package/dist/models.mjs +1 -0
  20. package/dist/mora.full.mjs +659 -412
  21. package/dist/value/array.d.mts +5 -5
  22. package/dist/value/array.mjs +70 -109
  23. package/dist/value/computed.d.mts +5 -4
  24. package/dist/value/computed.mjs +45 -31
  25. package/dist/value/readonly.d.mts +4 -6
  26. package/dist/value/readonly.mjs +34 -31
  27. package/dist/value/signal.d.mts +5 -5
  28. package/dist/value/signal.mjs +28 -34
  29. package/dist/value/store.d.mts +5 -5
  30. package/dist/value/store.mjs +25 -83
  31. package/package.json +6 -6
  32. package/src/batch.ts +15 -5
  33. package/src/constants.ts +36 -2
  34. package/src/effect.ts +20 -11
  35. package/src/helpers/is.ts +16 -6
  36. package/src/helpers/misc.ts +15 -0
  37. package/src/helpers/proxy.ts +151 -74
  38. package/src/helpers/subscription.ts +89 -0
  39. package/src/helpers/value.ts +121 -30
  40. package/src/index.ts +1 -1
  41. package/src/models.ts +81 -98
  42. package/src/value/array.ts +116 -226
  43. package/src/value/computed.ts +96 -43
  44. package/src/value/readonly.ts +68 -54
  45. package/src/value/signal.ts +54 -46
  46. package/src/value/store.ts +42 -168
  47. package/types/constants.d.ts +1 -1
  48. package/types/index.d.ts +1 -1
  49. package/types/value/array.d.ts +1 -1
  50. package/types/value/computed.d.ts +0 -3
  51. package/types/value/signal.d.ts +1 -1
  52. package/types/value/store.d.ts +1 -1
  53. package/dist/subscription.d.mts +0 -7
  54. package/dist/subscription.mjs +0 -27
  55. package/dist/value/reactive.d.mts +0 -5
  56. package/dist/value/reactive.mjs +0 -16
  57. package/src/subscription.ts +0 -45
  58. package/src/value/reactive.ts +0 -24
@@ -1,71 +1,85 @@
1
- import {isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {GenericCallback} from '@oscarpalmer/atoms/models';
3
- import {NAME_MORA, NAME_READONLY} from '../constants';
4
- import {getSimpleValue} from '../helpers/value';
5
- import type {
6
- ReactiveState,
7
- ReadonlyFrozenSignal,
8
- ReadonlyInstances,
9
- ReadonlySignal,
10
- ReadonlySignalValue,
11
- } from '../models';
1
+ import {
2
+ NAME_MORA,
3
+ NAME_READONLY,
4
+ SUBSCRIPTION_TYPE_FROZEN,
5
+ SUBSCRIPTION_TYPE_ORIGINAL,
6
+ SYMBOL_STATE,
7
+ } from '../constants';
8
+ import {subscribeToReadonly} from '../helpers/subscription';
9
+ import {getFrozenValue, getSignalValue, getStringValue, peekSignalValue} from '../helpers/value';
10
+ import type {ReadonlyFrozenSignal, ReadonlySignal, SignalState, InternalSignal} from '../models';
11
+
12
+ // #region Instance
13
+
14
+ function Readonly(this: any, state: SignalState, frozen: boolean) {
15
+ this[SYMBOL_STATE] = state;
16
+
17
+ Object.defineProperty(this, SUBSCRIPTION_TYPE_FROZEN, {
18
+ enumerable: true,
19
+ value: frozen,
20
+ });
21
+ }
22
+
23
+ Readonly.prototype[NAME_MORA] = NAME_READONLY;
24
+
25
+ Readonly.prototype.subscribe = subscribeToReadonly;
26
+ Readonly.prototype.toString = getStringValue;
27
+
28
+ Readonly.prototype.get = function () {
29
+ return getReadonlyValue(this, false, this[SUBSCRIPTION_TYPE_FROZEN]);
30
+ };
31
+
32
+ Readonly.prototype.peek = function (copy?: boolean) {
33
+ return getReadonlyValue(this, true, this[SUBSCRIPTION_TYPE_FROZEN], copy);
34
+ };
35
+
36
+ Readonly.prototype.toJSON = function () {
37
+ return this[SYMBOL_STATE].value;
38
+ };
39
+
40
+ // #endregion
41
+
42
+ // #region Functions
12
43
 
13
44
  export function getReadonlyInstance<Value>(
14
- state: ReactiveState<Value, never>,
15
- instances: ReadonlyInstances<Value>,
16
- handlers: Record<string, GenericCallback>,
17
- frozen: boolean,
45
+ this: InternalSignal,
46
+ frozen?: never,
18
47
  ): ReadonlySignal<Value> {
19
- const key = frozen ? 'frozen' : 'original';
48
+ const key = (frozen === true ? SUBSCRIPTION_TYPE_FROZEN : SUBSCRIPTION_TYPE_ORIGINAL) as never;
20
49
 
21
- instances[key] ??= getReadonlySignal(state, handlers, frozen) as never;
50
+ this[SYMBOL_STATE].readonlies ??= {};
22
51
 
23
- return instances[key] as ReadonlySignal<Value>;
52
+ this[SYMBOL_STATE].readonlies[key] ??= getReadonlySignal(
53
+ this[SYMBOL_STATE],
54
+ frozen === true,
55
+ ) as never;
56
+
57
+ return this[SYMBOL_STATE].readonlies[key] as never;
24
58
  }
25
59
 
26
- export function getReadonlySignal<Value>(
27
- state: ReactiveState<Value, never>,
28
- handlers: Record<string, GenericCallback>,
60
+ export function getReadonlySignal(
61
+ state: SignalState,
29
62
  frozen: boolean,
30
- ): ReadonlySignal<Value> | ReadonlyFrozenSignal<Value> {
31
- const instance = {
32
- ...handlers,
33
- get: () => getReadonlyValue(state, false, frozen),
34
- peek: () => getReadonlyValue(state, true, frozen),
35
- };
36
-
37
- Object.defineProperties(instance, {
38
- [NAME_MORA]: {
39
- enumerable: false,
40
- value: NAME_READONLY,
41
- },
42
- frozen: {
43
- enumerable: true,
44
- value: frozen,
45
- },
46
- });
47
-
48
- return Object.freeze(instance) as ReadonlySignal<Value>;
63
+ ): ReadonlySignal<unknown> | ReadonlyFrozenSignal<unknown> {
64
+ // @ts-expect-error All good, no worries :-)
65
+ return new Readonly(state, frozen);
49
66
  }
50
67
 
51
- function getReadonlyValue<Value>(
52
- state: ReactiveState<Value, never>,
68
+ function getReadonlyValue(
69
+ instance: InternalSignal,
53
70
  peek: boolean,
54
71
  frozen: boolean,
55
- ): Value | ReadonlySignalValue<Value> {
56
- let value = peek ? state.value : getSimpleValue(state);
57
-
58
- if (!frozen) {
59
- return value;
60
- }
72
+ copy?: boolean,
73
+ ): unknown {
74
+ let value: unknown;
61
75
 
62
- if (Array.isArray(state.value)) {
63
- value = [...state.value] as Value;
64
- } else if (isPlainObject(state.value)) {
65
- value = {...state.value} as Value;
76
+ if (peek) {
77
+ value = peekSignalValue.call(instance, copy === true);
66
78
  } else {
67
- value = state.value;
79
+ value = getSignalValue.call(instance);
68
80
  }
69
81
 
70
- return Object.freeze(value);
82
+ return frozen ? getFrozenValue(value) : value;
71
83
  }
84
+
85
+ // #endregion
@@ -1,15 +1,56 @@
1
- import {NAME_MORA, NAME_SIGNAL} from '../constants';
2
- import {emitValue, getSimpleValue, handleSimpleValue} from '../helpers/value';
3
- import type {ReactiveOptions, ReactiveState, ReadonlyInstances, Signal} from '../models';
4
- import {subscribe} from '../subscription';
5
- import {reactive} from './reactive';
1
+ import {NAME_MORA, NAME_SIGNAL, SYMBOL_STATE} from '../constants';
2
+ import {getState} from '../helpers/misc';
3
+ import {subscribeToSignal} from '../helpers/subscription';
4
+ import {
5
+ emitValue,
6
+ getSignalValue,
7
+ getStringValue,
8
+ handleSignalValue,
9
+ peekSignalValue,
10
+ updateSignalValue,
11
+ } from '../helpers/value';
12
+ import type {ReactiveOptions, Signal, InternalSignal} from '../models';
6
13
  import {getReadonlyInstance} from './readonly';
7
14
 
8
- function setAndEmit<Value>(state: ReactiveState<Value, Value>, value: Value): void {
9
- if (!state.equal(state.value, value)) {
15
+ // #region Instance
16
+
17
+ function Signal(this: any, value: unknown, options?: ReactiveOptions<unknown>) {
18
+ this[SYMBOL_STATE] = getState(undefined, options);
19
+
20
+ handleSignalValue(this, value, setAndEmit);
21
+ }
22
+
23
+ Signal.prototype[NAME_MORA] = NAME_SIGNAL;
24
+
25
+ Signal.prototype.asReadonly = getReadonlyInstance;
26
+ Signal.prototype.get = getSignalValue;
27
+ Signal.prototype.peek = peekSignalValue;
28
+ Signal.prototype.subscribe = subscribeToSignal;
29
+ Signal.prototype.toString = getStringValue;
30
+
31
+ Signal.prototype.set = function (value: never) {
32
+ return handleSignalValue(this, value, setAndEmit);
33
+ };
34
+
35
+ Signal.prototype.toJSON = function () {
36
+ return this[SYMBOL_STATE].value;
37
+ };
38
+
39
+ Signal.prototype.update = function (callback: never) {
40
+ return updateSignalValue(this, callback, setAndEmit);
41
+ };
42
+
43
+ // #endregion
44
+
45
+ // #region Functions
46
+
47
+ function setAndEmit(instance: InternalSignal, value: unknown): void {
48
+ const state = instance[SYMBOL_STATE];
49
+
50
+ if (!(state.equal ?? Object.is)(state.value as never, value as never)) {
10
51
  state.value = value;
11
52
 
12
- emitValue(state);
53
+ emitValue(instance);
13
54
  }
14
55
  }
15
56
 
@@ -46,42 +87,9 @@ export function signal<Value>(
46
87
  */
47
88
  export function signal<Value>(value: Value, options?: ReactiveOptions<Value>): Signal<Value>;
48
89
 
49
- export function signal<Value>(
50
- value: Value | (() => Value | Promise<Value>) | Promise<Value>,
51
- options?: ReactiveOptions<Value>,
52
- ): Signal<Value> {
53
- const [rx, state] = reactive<Value>(undefined as unknown as Value, options);
54
-
55
- const readonlies: ReadonlyInstances<Value> = {};
56
-
57
- const handlers = {
58
- ...rx,
59
- subscribe: (callback: (value: Value) => void) => subscribe(state, callback),
60
- unsubscribe: (callback: (value: Value) => void) => {
61
- state.subscriptions.delete(callback);
62
- },
63
- };
64
-
65
- const instance = {
66
- ...handlers,
67
- asReadonly: (frozen?: unknown) =>
68
- getReadonlyInstance(state, readonlies, handlers, frozen === true),
69
- get: () => getSimpleValue(state),
70
- peek: () => state.value,
71
- set: (value: Value | (() => Value | Promise<Value>) | Promise<Value>) => {
72
- handleSimpleValue(state, value, setAndEmit);
73
- },
74
- update: (callback: (value: Value) => Value) => {
75
- handleSimpleValue(state, callback(state.value), setAndEmit);
76
- },
77
- };
78
-
79
- Object.defineProperty(instance, NAME_MORA, {
80
- enumerable: false,
81
- value: NAME_SIGNAL,
82
- });
83
-
84
- handleSimpleValue(state, value, setAndEmit);
85
-
86
- return Object.freeze(instance) as Signal<Value>;
90
+ export function signal(value: unknown, options?: ReactiveOptions<unknown>): Signal<unknown> {
91
+ // @ts-expect-error All good, no worries :-)
92
+ return new Signal(value, options);
87
93
  }
94
+
95
+ // #endregion
@@ -1,98 +1,55 @@
1
- import {isKey, isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {GenericCallback, Key, PlainObject} from '@oscarpalmer/atoms/models';
3
- import {startBatch, stopBatch} from '../batch';
4
- import {NAME_MORA, NAME_STORE} from '../constants';
1
+ import type {PlainObject} from '@oscarpalmer/atoms/models';
2
+ import {NAME_MORA, NAME_STORE, SYMBOL_STATE} from '../constants';
3
+ import {getState} from '../helpers/misc';
5
4
  import {
6
- emityProxyValues,
7
- getReactiveValueInProxy,
5
+ emitProxyValues,
6
+ getValueInProxy,
7
+ peekValueInProxy,
8
8
  setProxyValue,
9
9
  setValueInProxy,
10
+ updateProxyValue,
10
11
  } from '../helpers/proxy';
11
- import {getSimpleValue} from '../helpers/value';
12
- import type {
13
- Computed,
14
- ComputedEffect,
15
- ReactiveOptions,
16
- ReactiveState,
17
- ReactiveStore,
18
- ReadonlyInstances,
19
- Unsubscribe,
20
- } from '../models';
21
- import {noop, subscribe, unsubscribe} from '../subscription';
22
- import {reactive} from './reactive';
12
+ import {subscribeToProxy} from '../helpers/subscription';
13
+ import {getStringValue} from '../helpers/value';
14
+ import type {ReactiveOptions, ReactiveStore} from '../models';
23
15
  import {getReadonlyInstance} from './readonly';
24
16
 
25
- function isStoreObject<Value extends PlainObject>(value: unknown): value is Value | undefined {
26
- return value == null || isPlainObject(value);
27
- }
28
-
29
- function setObject(state: ReactiveState<PlainObject, never>, value: PlainObject | undefined): void {
30
- startBatch();
31
-
32
- const actual = value ?? {};
33
- const proxy = state.value as PlainObject;
34
-
35
- const proxyKeys = Object.keys(proxy);
36
- const actualKeys = Object.keys(actual);
37
-
38
- let {length} = proxyKeys;
39
-
40
- for (let index = 0; index < length; index += 1) {
41
- const key = proxyKeys[index];
42
-
43
- proxy[key] = actualKeys.includes(key) ? actual[key] : undefined;
44
- }
45
-
46
- length = actualKeys.length;
47
-
48
- for (let index = 0; index < length; index += 1) {
49
- const key = actualKeys[index];
17
+ // #region Instance
50
18
 
51
- if (!proxyKeys.includes(key)) {
52
- const keyedValue = actual[key];
19
+ function ReactiveStore(this: any, value: never, options?: ReactiveOptions<unknown>) {
20
+ this[SYMBOL_STATE] = {
21
+ ...getState(undefined, options),
22
+ isArray: false,
23
+ };
53
24
 
54
- proxy[key] = keyedValue;
55
- }
56
- }
25
+ this[SYMBOL_STATE].value = new Proxy(
26
+ {},
27
+ {
28
+ set: (target, property, value) => setValueInProxy(this, target, property, value),
29
+ },
30
+ );
57
31
 
58
- stopBatch();
32
+ setProxyValue.call(this, value);
59
33
  }
60
34
 
61
- function peekStoreValue<Value extends PlainObject>(
62
- state: ReactiveState<Value, Value>,
63
- first?: unknown,
64
- second?: boolean,
65
- ): unknown {
66
- let value: unknown;
35
+ ReactiveStore.prototype[NAME_MORA] = NAME_STORE;
67
36
 
68
- if (isKey(first)) {
69
- value = state.value[first];
70
- } else {
71
- value = state.value;
72
- }
37
+ ReactiveStore.prototype.asReadonly = getReadonlyInstance;
38
+ ReactiveStore.prototype.get = getValueInProxy;
39
+ ReactiveStore.prototype.notify = emitProxyValues;
40
+ ReactiveStore.prototype.peek = peekValueInProxy;
41
+ ReactiveStore.prototype.set = setProxyValue;
42
+ ReactiveStore.prototype.subscribe = subscribeToProxy;
43
+ ReactiveStore.prototype.toString = getStringValue;
44
+ ReactiveStore.prototype.update = updateProxyValue;
73
45
 
74
- if (!(first === true || second === true)) {
75
- return value;
76
- }
46
+ ReactiveStore.prototype.toJSON = function () {
47
+ return this[SYMBOL_STATE].value;
48
+ };
77
49
 
78
- if (Array.isArray(value)) {
79
- return value.slice();
80
- }
50
+ // #endregion
81
51
 
82
- if (isPlainObject(value)) {
83
- return {...value};
84
- }
85
-
86
- return value;
87
- }
88
-
89
- function setProperty<Value extends PlainObject>(
90
- state: ReactiveState<Value, Value>,
91
- key: unknown,
92
- value: unknown,
93
- ): void {
94
- (state.value as PlainObject)[key as Key] = value;
95
- }
52
+ // #region Functions
96
53
 
97
54
  /**
98
55
  * Create a reactive store from a function result
@@ -130,92 +87,9 @@ export function store<Value extends PlainObject>(
130
87
  options?: ReactiveOptions<Value>,
131
88
  ): ReactiveStore<Value>;
132
89
 
133
- export function store<Value extends PlainObject>(
134
- value: Value | (() => Value | Promise<Value>) | Promise<Value>,
135
- options?: ReactiveOptions<Value>,
136
- ): ReactiveStore<Value> {
137
- const [rx, state] = reactive<Value>(undefined as never, options);
138
-
139
- const keyed = new Map<Key, [Computed<unknown>, ComputedEffect]>();
140
- const readonlies: ReadonlyInstances<Value> = {};
141
-
142
- let instance: Record<string, GenericCallback> = {};
143
-
144
- state.value = new Proxy({} as Value, {
145
- set: (target: Value, property: PropertyKey, value: unknown) =>
146
- setValueInProxy({
147
- target,
148
- property,
149
- state,
150
- value,
151
- isArray: false,
152
- }),
153
- });
154
-
155
- const handlers = {
156
- ...rx,
157
- get: (value?: unknown): unknown =>
158
- isKey(value)
159
- ? getReactiveValueInProxy(instance as ReactiveStore<Value>, keyed, value, false).get()
160
- : getSimpleValue(state),
161
- peek: (first?: unknown, second?: boolean): unknown => peekStoreValue(state, first, second),
162
- subscribe: (first: Key | GenericCallback, second?: GenericCallback): Unsubscribe => {
163
- if (isKey(first) && typeof second === 'function') {
164
- return getReactiveValueInProxy(
165
- instance as ReactiveStore<Value>,
166
- keyed,
167
- first,
168
- false,
169
- ).subscribe(second);
170
- }
171
-
172
- return typeof first === 'function' ? subscribe(state, first) : noop;
173
- },
174
- unsubscribe: (first: Key | GenericCallback, second?: GenericCallback) => {
175
- if (isKey(first) && typeof second === 'function') {
176
- getReactiveValueInProxy(instance as ReactiveStore<Value>, keyed, first, false)?.unsubscribe(
177
- second,
178
- );
179
- } else if (typeof first === 'function') {
180
- unsubscribe(state, first);
181
- }
182
- },
183
- };
184
-
185
- instance = {
186
- ...handlers,
187
- asReadonly: (frozen?: unknown) =>
188
- getReadonlyInstance(state, readonlies, handlers, frozen === true),
189
- notify(): void {
190
- emityProxyValues(state, keyed);
191
- },
192
- set: (first?: unknown, second?: unknown) => {
193
- setProxyValue<Value>(
194
- false,
195
- state,
196
- isStoreObject,
197
- isKey,
198
- setObject,
199
- setProperty,
200
- first,
201
- second,
202
- );
203
- },
204
- update: (callback: (value: Value) => Value) => {
205
- const updated = callback(state.value);
206
-
207
- if (updated == null || isPlainObject(updated)) {
208
- setObject(state, updated);
209
- }
210
- },
211
- };
212
-
213
- Object.defineProperty(instance, NAME_MORA, {
214
- enumerable: false,
215
- value: NAME_STORE,
216
- });
217
-
218
- instance.set(value);
219
-
220
- return Object.freeze(instance) as ReactiveStore<Value>;
90
+ export function store(value: unknown, options?: ReactiveOptions<unknown>): ReactiveStore<unknown> {
91
+ // @ts-expect-error All good, no worries :-)
92
+ return new ReactiveStore(value, options);
221
93
  }
94
+
95
+ // #endregion
@@ -12,5 +12,5 @@ export declare const NAME_EFFECT = "effect";
12
12
  export declare const NAME_MORA = "$mora";
13
13
  export declare const NAME_SIGNAL = "signal";
14
14
  export declare const NAME_STORE = "store";
15
- export declare const NAME_ALL: Set<string>;
15
+ export declare const NAMES: Set<string>;
16
16
  export declare const PROPERTY_LENGTH = "length";
package/types/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { startBatch, stopBatch } from './batch';
2
2
  export { effect, type Effect } from './effect';
3
- export { isArray, isComputed, isEffect, isReactive, isSignal } from './helpers/is';
3
+ export { isArray, isComputed, isEffect, isReactive, isSignal, } from './helpers/is';
4
4
  export type { Unsubscribe } from './models';
5
5
  export { array, type ReactiveArray } from './value/array';
6
6
  export { computed, type Computed } from './value/computed';
@@ -131,7 +131,7 @@ export declare class ReactiveArray<Item> extends Reactive<Item[], Item> {
131
131
  /**
132
132
  * Create a reactive array
133
133
  * @param value Initial array of items
134
- * @param options Reactivity options
134
+ * @param options Optional reactivity options
135
135
  * @returns Reactive array
136
136
  */
137
137
  export declare function array<Item>(value: Item[], options?: ReactiveOptions<Item>): ReactiveArray<Item>;
@@ -10,8 +10,5 @@ export declare class Computed<Value> extends Reactive<Value> {
10
10
  }
11
11
  /**
12
12
  * Create a computed value
13
- * @param callback Callback to compute the value
14
- * @param options Reactivity options
15
- * @returns Computed value
16
13
  */
17
14
  export declare function computed<Value>(callback: () => Value, options?: ReactiveOptions<Value>): Computed<Value>;
@@ -20,7 +20,7 @@ export declare class Signal<Value> extends Reactive<Value> {
20
20
  /**
21
21
  * Create a reactive value
22
22
  * @param value Initial value
23
- * @param options Reactivity options
23
+ * @param options Optional reactivity options
24
24
  * @returns Reactive value
25
25
  */
26
26
  export declare function signal<Value>(value: Value, options?: ReactiveOptions<Value>): Signal<Value>;
@@ -88,7 +88,7 @@ export declare class Store<Value extends PlainObject> extends Reactive<Value, Va
88
88
  /**
89
89
  * Create a reactive store
90
90
  * @param value Initial object value
91
- * @param options Reactivity options
91
+ * @param options Optional reactivity options
92
92
  * @returns Reactive store
93
93
  */
94
94
  export declare function store<Value extends PlainObject>(value: Value, options?: ReactiveOptions<Value>): Store<Value>;
@@ -1,7 +0,0 @@
1
- import { ReactiveState, Unsubscribe } from "./models.mjs";
2
- //#region src/subscription.d.ts
3
- declare function noop(): void;
4
- declare function subscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): Unsubscribe;
5
- declare function unsubscribe<Value>(state: ReactiveState<Value, never>, callback: (value: Value) => void): void;
6
- //#endregion
7
- export { noop, subscribe, unsubscribe };
@@ -1,27 +0,0 @@
1
- //#region src/subscription.ts
2
- function noop() {}
3
- function subscribe(state, callback) {
4
- if (typeof callback !== "function" || state.subscriptions.has(callback)) return noop;
5
- state.subscriptions.set(callback, subscription(state, callback));
6
- return () => {
7
- unsubscribe(state, callback);
8
- };
9
- }
10
- function subscription(state, callback) {
11
- const instance = {
12
- callback,
13
- state,
14
- destroy: () => {
15
- instance.callback = noop;
16
- instance.state = void 0;
17
- }
18
- };
19
- callback(state.value);
20
- return instance;
21
- }
22
- function unsubscribe(state, callback) {
23
- state.subscriptions.get(callback)?.destroy();
24
- state.subscriptions.delete(callback);
25
- }
26
- //#endregion
27
- export { noop, subscribe, unsubscribe };
@@ -1,5 +0,0 @@
1
- import { Reactive, ReactiveOptions, ReactiveState } from "../models.mjs";
2
- //#region src/value/reactive.d.ts
3
- declare function reactive<Value, Equal = Value>(value: Value, options?: ReactiveOptions<Equal>): [Reactive<Value>, ReactiveState<Value, Equal>];
4
- //#endregion
5
- export { reactive };
@@ -1,16 +0,0 @@
1
- //#region src/value/reactive.ts
2
- function reactive(value, options) {
3
- const state = {
4
- computeds: /* @__PURE__ */ new Set(),
5
- effects: /* @__PURE__ */ new Set(),
6
- equal: typeof options === "object" && typeof options?.equal === "function" ? options.equal : Object.is,
7
- subscriptions: /* @__PURE__ */ new Map(),
8
- value
9
- };
10
- return [{
11
- toJSON: () => state.value,
12
- toString: () => String(state.value)
13
- }, state];
14
- }
15
- //#endregion
16
- export { reactive };
@@ -1,45 +0,0 @@
1
- import type {ReactiveState, Subscription, Unsubscribe} from './models';
2
-
3
- export function noop(): void {}
4
-
5
- export function subscribe<Value>(
6
- state: ReactiveState<Value, never>,
7
- callback: (value: Value) => void,
8
- ): Unsubscribe {
9
- if (typeof callback !== 'function' || state.subscriptions.has(callback)) {
10
- return noop;
11
- }
12
-
13
- state.subscriptions.set(callback, subscription(state, callback));
14
-
15
- return () => {
16
- unsubscribe(state, callback);
17
- };
18
- }
19
-
20
- function subscription<Value>(
21
- state: ReactiveState<Value, never>,
22
- callback: (value: Value) => void,
23
- ): Subscription {
24
- const instance: Subscription = {
25
- callback,
26
- state,
27
- destroy: () => {
28
- instance.callback = noop;
29
- instance.state = undefined as never;
30
- },
31
- };
32
-
33
- callback(state.value);
34
-
35
- return instance;
36
- }
37
-
38
- export function unsubscribe<Value>(
39
- state: ReactiveState<Value, never>,
40
- callback: (value: Value) => void,
41
- ): void {
42
- state.subscriptions.get(callback)?.destroy();
43
-
44
- state.subscriptions.delete(callback);
45
- }
@@ -1,24 +0,0 @@
1
- import type {Reactive, ReactiveOptions, ReactiveState} from '../models';
2
-
3
- export function reactive<Value, Equal = Value>(
4
- value: Value,
5
- options?: ReactiveOptions<Equal>,
6
- ): [Reactive<Value>, ReactiveState<Value, Equal>] {
7
- const state: ReactiveState<Value, Equal> = {
8
- computeds: new Set(),
9
- effects: new Set(),
10
- equal:
11
- typeof options === 'object' && typeof options?.equal === 'function'
12
- ? options.equal
13
- : Object.is,
14
- subscriptions: new Map(),
15
- value: value as Value,
16
- };
17
-
18
- const instance = {
19
- toJSON: () => state.value,
20
- toString: () => String(state.value),
21
- };
22
-
23
- return [instance, state];
24
- }