@oscarpalmer/mora 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/batch.mjs +15 -6
  2. package/dist/constants.d.mts +2 -2
  3. package/dist/constants.mjs +7 -4
  4. package/dist/effect.d.mts +5 -18
  5. package/dist/effect.mjs +23 -19
  6. package/dist/helpers/is.d.mts +17 -16
  7. package/dist/helpers/is.mjs +20 -11
  8. package/dist/helpers/proxy.d.mts +5 -9
  9. package/dist/helpers/proxy.mjs +4 -4
  10. package/dist/helpers/value.d.mts +3 -3
  11. package/dist/helpers/value.mjs +22 -5
  12. package/dist/index.d.mts +8 -9
  13. package/dist/index.mjs +2 -2
  14. package/dist/models.d.mts +423 -19
  15. package/dist/mora.full.mjs +532 -424
  16. package/dist/subscription.d.mts +1 -9
  17. package/dist/subscription.mjs +14 -15
  18. package/dist/value/array.d.mts +5 -133
  19. package/dist/value/array.mjs +108 -138
  20. package/dist/value/computed.d.mts +4 -12
  21. package/dist/value/computed.mjs +54 -50
  22. package/dist/value/reactive.d.mts +3 -49
  23. package/dist/value/reactive.mjs +10 -54
  24. package/dist/value/readonly.d.mts +7 -0
  25. package/dist/value/readonly.mjs +37 -0
  26. package/dist/value/signal.d.mts +5 -21
  27. package/dist/value/signal.mjs +33 -49
  28. package/dist/value/store.d.mts +9 -92
  29. package/dist/value/store.mjs +58 -49
  30. package/package.json +7 -8
  31. package/src/batch.ts +22 -9
  32. package/src/constants.ts +12 -5
  33. package/src/effect.ts +35 -40
  34. package/src/helpers/is.ts +36 -20
  35. package/src/helpers/proxy.ts +23 -18
  36. package/src/helpers/value.ts +39 -5
  37. package/src/index.ts +23 -8
  38. package/src/models.ts +520 -17
  39. package/src/subscription.ts +20 -20
  40. package/src/value/array.ts +220 -266
  41. package/src/value/computed.ts +80 -74
  42. package/src/value/reactive.ts +16 -77
  43. package/src/value/readonly.ts +71 -0
  44. package/src/value/signal.ts +43 -71
  45. package/src/value/store.ts +130 -177
  46. package/types/constants.d.ts +1 -1
  47. package/types/index.d.ts +1 -1
  48. package/types/value/array.d.ts +1 -1
  49. package/types/value/computed.d.ts +3 -0
  50. package/types/value/signal.d.ts +1 -1
  51. package/types/value/store.d.ts +1 -1
package/dist/models.d.mts CHANGED
@@ -1,32 +1,229 @@
1
- import { Effect } from "./effect.mjs";
2
- import { Subscription } from "./subscription.mjs";
3
- import { Computed } from "./value/computed.mjs";
4
- import { Signal } from "./value/signal.mjs";
5
- import { GenericCallback, Key } from "@oscarpalmer/atoms/models";
6
-
1
+ import { PROPERTY_LENGTH } from "./constants.mjs";
2
+ import { GenericCallback, Key, PlainObject } from "@oscarpalmer/atoms/models";
7
3
  //#region src/models.d.ts
8
4
  type Active = {
9
- computed?: Computed<unknown>;
10
- effect?: Effect;
5
+ computed?: ComputedEffect;
6
+ effect?: EffectState;
11
7
  };
12
8
  type Batch = {
13
9
  depth: number;
14
- handlers: Set<Effect | Subscription>;
10
+ flushing: boolean;
11
+ handlers: Set<EffectState | Subscription>;
15
12
  };
13
+ type Computed<Value> = Reactive<Value> & SimpleReactive<Value>;
16
14
  type ComputedEffect = {
17
15
  dirty: boolean;
18
- instance: Effect;
16
+ instance: EffectState;
19
17
  };
18
+ type Effect = {};
20
19
  type EffectState = {
21
20
  callback: GenericCallback;
22
21
  };
23
- type InternalComputed = {
24
- readonly effect: ComputedEffect;
25
- readonly state: ReactiveState<unknown, unknown>;
26
- };
27
- type InternalEffect = {
28
- state: EffectState;
22
+ type Reactive<Value> = {
23
+ /**
24
+ * JSON representation of the value
25
+ *
26
+ * @returns JSON value
27
+ */
28
+ toJSON(): Value;
29
+ /**
30
+ * String representation of the value
31
+ *
32
+ * @returns Value as string
33
+ */
34
+ toString(): string;
29
35
  };
36
+ type ReactiveArray<Item> = {
37
+ /**
38
+ * The length of the array
39
+ */
40
+ get length(): number;
41
+ /**
42
+ * Set the length of the array
43
+ */
44
+ set length(value: number);
45
+ /**
46
+ * Get a readonly version of the reactive array
47
+ *
48
+ * @param frozen Freeze the array? _(defaults to `false`)_
49
+ * @returns Readonly reactive array
50
+ */
51
+ asReadonly(frozen: true): ReadonlyFrozenSignal<Item[]>;
52
+ /**
53
+ * Get a readonly version of the reactive array
54
+ *
55
+ * @param frozen Freeze the array? _(defaults to `false`)_
56
+ * @returns Readonly reactive array
57
+ */
58
+ asReadonly(frozen?: boolean): typeof frozen extends true ? ReadonlyFrozenSignal<Item[]> : ReadonlySignal<Item[]>;
59
+ /**
60
+ * Get the value at an index
61
+ *
62
+ * @param index Index of item to get _(if negative, starts from the end)_
63
+ * @returns Item at index, or `undefined` if it doesn't exist
64
+ */
65
+ at(index: number): Item | undefined;
66
+ /**
67
+ * Clear the array
68
+ */
69
+ clear(): void;
70
+ /**
71
+ * Create a computed, filtered array
72
+ *
73
+ * @param callback Callback to evaluate each item
74
+ * @returns Computed array of filtered items
75
+ */
76
+ filter(callback: (item: Item, index: number, array: Item[]) => boolean): Computed<Item[]>;
77
+ /**
78
+ * Get the array
79
+ *
80
+ * @returns Array of items
81
+ */
82
+ get(): Item[];
83
+ /**
84
+ * Get the value at an index
85
+ *
86
+ * @param index Index of item to get _(if negative, starts from the end)_
87
+ * @returns Item at index, or `undefined` if it doesn't exist
88
+ */
89
+ get(index: number): Item | undefined;
90
+ /**
91
+ * Get the length of the array
92
+ *
93
+ * @returns Length of the array
94
+ */
95
+ get(property: typeof PROPERTY_LENGTH): number;
96
+ /**
97
+ * Create a computed, mapped array
98
+ *
99
+ * @param callback Callback to transform each item
100
+ * @returns Computed array of mapped items
101
+ */
102
+ map<Mapped>(callback: (item: Item, index: number, array: Item[]) => Mapped): Computed<Mapped[]>;
103
+ /**
104
+ * Notify dependents of changes
105
+ *
106
+ * _This bypasses equality checks and will immediately notify dependents.
107
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
108
+ */
109
+ notify(): void;
110
+ /**
111
+ * Get the array _(without reactivity)_
112
+ *
113
+ * @param copy Copy the array? _(defaults to `false`)_
114
+ * @returns Array of items
115
+ */
116
+ peek(copy?: boolean): Item[];
117
+ /**
118
+ * Get the value at an index _(without reactivity)_
119
+ *
120
+ * @param index Index of item to get _(if negative, starts from the end)_
121
+ * @param copy If the item is an array or record, should it be copied? _(defaults to `false`)_
122
+ * @returns Item at index, or `undefined` if it doesn't exist
123
+ */
124
+ peek(index: number, copy?: boolean): Item | undefined;
125
+ /**
126
+ * Get the length of the array _(without reactivity)_
127
+ *
128
+ * @returns Length of the array
129
+ */
130
+ peek(property: typeof PROPERTY_LENGTH): number;
131
+ /**
132
+ * Remove and return the last item of the array
133
+ *
134
+ * @returns Removed item, or `undefined` if the array is empty
135
+ */
136
+ pop(): Item | undefined;
137
+ /**
138
+ * Add items to the end of the array
139
+ *
140
+ * @param items Items to add
141
+ * @returns New array length
142
+ */
143
+ push(...items: Item[]): number;
144
+ /**
145
+ * Create a computed, filtered, and mapped array
146
+ *
147
+ * @param filter Callback to evaluate each item
148
+ * @param map Callback to transform each item
149
+ * @returns Computed array of mapped items
150
+ */
151
+ select<Mapped>(filter: (item: Item, index: number, array: Item[]) => boolean, map: (item: Item, index: number, array: Item[]) => Mapped): Computed<Mapped[]>;
152
+ /**
153
+ * Set the value
154
+ *
155
+ * @param value New array of items _(defaults to an empty array)_
156
+ */
157
+ set(value?: Item[] | (() => null | undefined | Item[] | Promise<null | undefined | Item[]>) | Promise<null | undefined | Item[]>): void;
158
+ /**
159
+ * Set the value at an index
160
+ *
161
+ * @param index Index of item to set _(if negative, starts from the end)_
162
+ * @param value New item
163
+ */
164
+ set(index: number, value: Item | (() => Item | Promise<Item>) | Promise<Item>): void;
165
+ /**
166
+ * Set the length of the array
167
+ *
168
+ * @param value New array length
169
+ */
170
+ set(property: typeof PROPERTY_LENGTH, value: number): void;
171
+ /**
172
+ * Remove and return the first item of the array
173
+ *
174
+ * @returns Removed item, or `undefined` if the array is empty
175
+ */
176
+ shift(): Item | undefined;
177
+ /**
178
+ * Remove and return items from the array _(and optionally add new items)_
179
+ *
180
+ * @param from Index to start removing items from
181
+ * @param to Index to stop removing items at _(defaults to the end of the array)_
182
+ * @param items Optional items to add
183
+ * @returns Removed items
184
+ */
185
+ splice(from: number, to?: number, ...items: Item[]): Item[];
186
+ /**
187
+ * Subscribe to changes
188
+ *
189
+ * @param callback Callback for changes
190
+ * @returns Unsubscribe callback
191
+ */
192
+ subscribe(callback: (value: Item[]) => void): Unsubscribe;
193
+ /**
194
+ * Subscribe to changes at a specific index
195
+ *
196
+ * @param index Index of item to subscribe to
197
+ * @param callback Callback for changes
198
+ * @returns Unsubscribe callback
199
+ */
200
+ subscribe(index: number, callback: (value: Item | undefined) => void): Unsubscribe;
201
+ /**
202
+ * Add items to the beginning of the array
203
+ * @param items Items to add
204
+ * @returns New array length
205
+ */
206
+ unshift(...items: Item[]): number;
207
+ /**
208
+ * Unsubscribe from changes for a specific index
209
+ *
210
+ * @param index Index of the value to unsubscribe from
211
+ * @param callback Callback to unsubscribe
212
+ */
213
+ unsubscribe(index: number, callback: (item: Item | undefined) => void): void;
214
+ /**
215
+ * Unsubscribe from changes
216
+ *
217
+ * @param callback Callback to unsubscribe
218
+ */
219
+ unsubscribe(callback: (array: Item[]) => void): void;
220
+ /**
221
+ * Update the value _(based on the current value)_
222
+ *
223
+ * @param callback Callback to update the value
224
+ */
225
+ update(callback: (value: Item[]) => Item[]): void;
226
+ } & Reactive<Item[]>;
30
227
  type ReactiveOptions<Value> = {
31
228
  /**
32
229
  * Method for comparing values for equality
@@ -38,14 +235,161 @@ type ReactiveOptions<Value> = {
38
235
  equal?: (first: Value, second: Value) => boolean;
39
236
  };
40
237
  type ReactiveState<Value, Equal> = {
41
- computeds: Set<Computed<unknown>>;
42
- effects: Set<Effect>;
238
+ computeds: Set<ComputedEffect>;
239
+ effects: Set<EffectState>;
43
240
  equal: (first: Equal, second: Equal) => boolean;
44
241
  promise?: Promise<Value>;
45
242
  promises?: Map<Key, Promise<never>>;
46
243
  subscriptions: Map<GenericCallback, Subscription>;
47
244
  value: Value;
48
245
  };
246
+ type ReactiveStore<Store> = {
247
+ /**
248
+ * Get a readonly version of the reactive store
249
+ *
250
+ * @param frozen Freeze the store? _(defaults to `false`)_
251
+ * @returns Readonly reactive store
252
+ */
253
+ asReadonly(frozen: true): ReadonlyFrozenSignal<Store>;
254
+ /**
255
+ * Get a readonly version of the reactive store
256
+ *
257
+ * @param frozen Freeze the store? _(defaults to `false`)_
258
+ * @returns Readonly reactive store
259
+ */
260
+ asReadonly(frozen?: boolean): typeof frozen extends true ? ReadonlyFrozenSignal<Store> : ReadonlySignal<Store>;
261
+ /**
262
+ * Get the value
263
+ *
264
+ * @returns Current value
265
+ */
266
+ get(): Store;
267
+ /**
268
+ * Get a value by key
269
+ *
270
+ * @param key Key of the value to get
271
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
272
+ */
273
+ get<Key extends keyof Store>(key: Key): Store[Key];
274
+ /**
275
+ * Get a value by key
276
+ *
277
+ * @param key Key of the value to get
278
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
279
+ */
280
+ get(key: Key): unknown;
281
+ /**
282
+ * Notify dependents of changes
283
+ *
284
+ * _This bypasses equality checks and will immediately notify dependents.
285
+ * Use this only if you're modifying nested data that would be ignored by equality checks._
286
+ */
287
+ notify(): void;
288
+ /**
289
+ * Get the value _(without reactivity)_
290
+ *
291
+ * @param copy Copy the store? _(defaults to `false`)_
292
+ * @returns Current value
293
+ */
294
+ peek(copy?: boolean): Store;
295
+ /**
296
+ * Get a value by key _(without reactivity)_
297
+ *
298
+ * @param key Key of the value to get
299
+ * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
300
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
301
+ */
302
+ peek<Key extends keyof Store>(key: Key, copy?: boolean): Store[Key];
303
+ /**
304
+ * Get a value by key _(without reactivity)_
305
+ *
306
+ * @param key Key of the value to get
307
+ * @param copy If the value is an array or record, should it be copied? _(defaults to `false`)_
308
+ * @returns Value for the specified key, or `undefined` if it doesn't exist
309
+ */
310
+ peek(key: Key, copy?: boolean): unknown;
311
+ /**
312
+ * Set the value
313
+ *
314
+ * @param value New value _(defaults to an empty object)_
315
+ */
316
+ set(value?: Store | (() => null | undefined | Store | Promise<null | undefined | Store>) | Promise<null | undefined | Store>): void;
317
+ /**
318
+ * Set a value by key
319
+ *
320
+ * @param key Key of the value to set
321
+ * @param value New value
322
+ */
323
+ set<Key extends keyof Store>(key: Key, value: Store[Key] | (() => Store[Key] | Promise<Store[Key]>) | Promise<Store[Key]>): void;
324
+ /**
325
+ * Set a value by key
326
+ *
327
+ * @param key Key of the value to set
328
+ * @param value New value
329
+ */
330
+ set(key: Key, value: unknown): void;
331
+ /**
332
+ * Subscribe to changes
333
+ *
334
+ * @param callback Callback for changes
335
+ * @returns Unsubscribe callback
336
+ */
337
+ subscribe(callback: (value: Store) => void): Unsubscribe;
338
+ /**
339
+ * Subscribe to changes for a specific key
340
+ *
341
+ * @param key Key of the value to subscribe to
342
+ * @param callback Callback for changes
343
+ * @returns Unsubscribe callback
344
+ */
345
+ subscribe<Key extends keyof Store>(key: Key, callback: (value: Store[Key] | undefined) => void): Unsubscribe;
346
+ /**
347
+ * Subscribe to changes for a specific key
348
+ *
349
+ * @param key Key of the value to subscribe to
350
+ * @param callback Callback for changes
351
+ * @returns Unsubscribe callback
352
+ */
353
+ subscribe(key: Key, callback: (value: unknown) => void): Unsubscribe;
354
+ /**
355
+ * Unsubscribe from changes for a specific key
356
+ *
357
+ * @param key Key of the value to unsubscribe from
358
+ * @param callback Callback to unsubscribe
359
+ */
360
+ unsubscribe<Key extends keyof Store>(key: Key, callback: (value: Store[Key] | undefined) => void): void;
361
+ /**
362
+ * Unsubscribe from changes for a specific key
363
+ *
364
+ * @param key Key of the value to unsubscribe from
365
+ * @param callback Callback to unsubscribe
366
+ */
367
+ unsubscribe(key: Key, callback: (value: unknown | undefined) => void): void;
368
+ /**
369
+ * Unsubscribe from changes
370
+ *
371
+ * @param callback Callback to unsubscribe
372
+ */
373
+ unsubscribe(callback: (value: Store) => void): void;
374
+ /**
375
+ * Update the value _(based on the current value)_
376
+ *
377
+ * @param callback Callback to update the value
378
+ */
379
+ update(callback: (value: Store) => Store): void;
380
+ } & Reactive<Store>;
381
+ type ReadonlyInstances<Value> = {
382
+ frozen?: ReadonlyFrozenSignal<Value>;
383
+ original?: ReadonlySignal<Value>;
384
+ };
385
+ type ReadonlyFrozenSignal<Value> = ReadonlySignal<ReadonlySignalValue<Value>>;
386
+ type ReadonlySignal<Value> = {
387
+ /**
388
+ * Is the signal frozen?
389
+ */
390
+ get frozen(): boolean;
391
+ } & Reactive<Value> & SimpleReactive<Value>;
392
+ type ReadonlySignalValue<Value> = Value extends unknown[] ? Readonly<Value> : Value extends PlainObject ? Readonly<Value> : Value;
49
393
  type SetValueInProxyParameters<Value, Equal> = {
50
394
  target: Value;
51
395
  property: PropertyKey;
@@ -54,9 +398,69 @@ type SetValueInProxyParameters<Value, Equal> = {
54
398
  isArray: boolean;
55
399
  length?: Signal<number>;
56
400
  };
401
+ type Signal<Value> = {
402
+ /**
403
+ * Get a readonly version of the signal
404
+ *
405
+ * @param frozen Freeze the signal? _(defaults to `false`)_
406
+ * @returns Readonly signal
407
+ */
408
+ asReadonly(frozen: true): ReadonlyFrozenSignal<Value>;
409
+ /**
410
+ * Get a readonly version of the signal
411
+ *
412
+ * @param frozen Freeze the signal? _(defaults to `false`)_
413
+ * @returns Readonly signal
414
+ */
415
+ asReadonly(frozen?: boolean): typeof frozen extends true ? ReadonlyFrozenSignal<Value> : ReadonlySignal<Value>;
416
+ /**
417
+ * Set the value
418
+ *
419
+ * @param value New value
420
+ */
421
+ set(value: Value | (() => Value | Promise<Value>) | Promise<Value>): void;
422
+ /**
423
+ * Update the value _(based on the current value)_
424
+ *
425
+ * @param callback Callback to update the value
426
+ */
427
+ update(callback: (value: Value) => Value): void;
428
+ } & Reactive<Value> & SimpleReactive<Value>;
429
+ type SimpleReactive<Value> = {
430
+ /**
431
+ * Get the value
432
+ *
433
+ * @returns Current value
434
+ */
435
+ get(): Value;
436
+ /**
437
+ * Get the value _(without reactivity)_
438
+ *
439
+ * @returns Current value
440
+ */
441
+ peek(): Value;
442
+ /**
443
+ * Subscribe to changes
444
+ *
445
+ * @param callback Callback for changes
446
+ * @returns Unsubscribe callback
447
+ */
448
+ subscribe(callback: (value: Value) => void): Unsubscribe;
449
+ /**
450
+ * Unsubscribe from changes
451
+ *
452
+ * @param callback Callback to unsubscribe
453
+ */
454
+ unsubscribe(callback: (value: Value) => void): void;
455
+ };
456
+ type Subscription = {
457
+ callback: GenericCallback;
458
+ state: ReactiveState<unknown, never>;
459
+ destroy(): void;
460
+ };
57
461
  /**
58
462
  * Unsubscribe from changes
59
463
  */
60
464
  type Unsubscribe = () => void;
61
465
  //#endregion
62
- export { Active, Batch, ComputedEffect, EffectState, InternalComputed, InternalEffect, ReactiveOptions, ReactiveState, SetValueInProxyParameters, Unsubscribe };
466
+ export { Active, Batch, Computed, ComputedEffect, Effect, EffectState, Reactive, ReactiveArray, ReactiveOptions, ReactiveState, ReactiveStore, ReadonlyFrozenSignal, ReadonlyInstances, ReadonlySignal, ReadonlySignalValue, SetValueInProxyParameters, Signal, Subscription, Unsubscribe };