@tldraw/state 5.3.2 → 5.4.0-canary.02cd0bd3b597

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 (71) hide show
  1. package/DOCS.md +64 -63
  2. package/README.md +35 -36
  3. package/dist-cjs/index.d.ts +26 -27
  4. package/dist-cjs/index.js +1 -1
  5. package/dist-cjs/lib/ArraySet.js +47 -144
  6. package/dist-cjs/lib/ArraySet.js.map +2 -2
  7. package/dist-cjs/lib/Atom.js +12 -26
  8. package/dist-cjs/lib/Atom.js.map +2 -2
  9. package/dist-cjs/lib/Computed.js +36 -64
  10. package/dist-cjs/lib/Computed.js.map +2 -2
  11. package/dist-cjs/lib/EffectScheduler.js +1 -1
  12. package/dist-cjs/lib/EffectScheduler.js.map +2 -2
  13. package/dist-cjs/lib/HistoryBuffer.js +8 -8
  14. package/dist-cjs/lib/HistoryBuffer.js.map +2 -2
  15. package/dist-cjs/lib/capture.js +1 -3
  16. package/dist-cjs/lib/capture.js.map +2 -2
  17. package/dist-cjs/lib/constants.js.map +2 -2
  18. package/dist-cjs/lib/helpers.js +3 -11
  19. package/dist-cjs/lib/helpers.js.map +2 -2
  20. package/dist-cjs/lib/localStorageAtom.js +7 -2
  21. package/dist-cjs/lib/localStorageAtom.js.map +2 -2
  22. package/dist-cjs/lib/transactions.js +11 -19
  23. package/dist-cjs/lib/transactions.js.map +2 -2
  24. package/dist-cjs/lib/types.js.map +1 -1
  25. package/dist-cjs/lib/warnings.js +2 -4
  26. package/dist-cjs/lib/warnings.js.map +2 -2
  27. package/dist-esm/index.d.mts +26 -27
  28. package/dist-esm/index.mjs +1 -1
  29. package/dist-esm/lib/ArraySet.mjs +47 -144
  30. package/dist-esm/lib/ArraySet.mjs.map +2 -2
  31. package/dist-esm/lib/Atom.mjs +12 -26
  32. package/dist-esm/lib/Atom.mjs.map +2 -2
  33. package/dist-esm/lib/Computed.mjs +36 -64
  34. package/dist-esm/lib/Computed.mjs.map +2 -2
  35. package/dist-esm/lib/EffectScheduler.mjs +1 -1
  36. package/dist-esm/lib/EffectScheduler.mjs.map +2 -2
  37. package/dist-esm/lib/HistoryBuffer.mjs +8 -8
  38. package/dist-esm/lib/HistoryBuffer.mjs.map +2 -2
  39. package/dist-esm/lib/capture.mjs +1 -3
  40. package/dist-esm/lib/capture.mjs.map +2 -2
  41. package/dist-esm/lib/constants.mjs.map +2 -2
  42. package/dist-esm/lib/helpers.mjs +3 -11
  43. package/dist-esm/lib/helpers.mjs.map +2 -2
  44. package/dist-esm/lib/localStorageAtom.mjs +7 -2
  45. package/dist-esm/lib/localStorageAtom.mjs.map +2 -2
  46. package/dist-esm/lib/transactions.mjs +11 -19
  47. package/dist-esm/lib/transactions.mjs.map +2 -2
  48. package/dist-esm/lib/types.mjs.map +1 -1
  49. package/dist-esm/lib/warnings.mjs +2 -4
  50. package/dist-esm/lib/warnings.mjs.map +2 -2
  51. package/package.json +2 -2
  52. package/src/lib/ArraySet.ts +68 -176
  53. package/src/lib/Atom.ts +27 -31
  54. package/src/lib/Computed.ts +68 -96
  55. package/src/lib/EffectScheduler.ts +9 -8
  56. package/src/lib/HistoryBuffer.ts +12 -10
  57. package/src/lib/__tests__/ArraySet.test.ts +39 -13
  58. package/src/lib/__tests__/EffectScheduler.test.ts +18 -0
  59. package/src/lib/__tests__/HistoryBuffer.test.ts +6 -3
  60. package/src/lib/__tests__/computed.test.ts +75 -0
  61. package/src/lib/__tests__/errors.test.ts +24 -0
  62. package/src/lib/__tests__/helpers.test.ts +7 -11
  63. package/src/lib/__tests__/history.test.ts +32 -2
  64. package/src/lib/__tests__/localStorageAtom.test.ts +15 -0
  65. package/src/lib/capture.ts +13 -13
  66. package/src/lib/constants.ts +3 -22
  67. package/src/lib/helpers.ts +15 -140
  68. package/src/lib/localStorageAtom.ts +9 -2
  69. package/src/lib/transactions.ts +23 -47
  70. package/src/lib/types.ts +7 -7
  71. package/src/lib/warnings.ts +2 -10
@@ -70,7 +70,7 @@ export declare interface AtomOptions<Value, Diff> {
70
70
  /**
71
71
  * The maximum number of diffs to keep in the history buffer.
72
72
  *
73
- * If you don't need to compute diffs, or if you will supply diffs manually via {@link Atom.set}, you can leave this as `undefined` and no history buffer will be created.
73
+ * If you don't need diffs, leave this as `undefined` and no history buffer will be created. Diffs passed to {@link Atom.set} or produced by {@link AtomOptions.computeDiff} are only recorded when this is set.
74
74
  *
75
75
  * If you expect the value to be part of an active effect subscription all the time, and to not change multiple times inside of a single transaction, you can set this to a relatively low number (e.g. 10).
76
76
  *
@@ -142,7 +142,7 @@ export declare interface Computed<Value, Diff = unknown> extends Signal<Value, D
142
142
  * ```ts
143
143
  * class Counter {
144
144
  * max = 100
145
- * count = atom<number>(0)
145
+ * count = atom('count', 0)
146
146
  *
147
147
  * @computed getRemaining() {
148
148
  * return this.max - this.count.get()
@@ -156,7 +156,7 @@ export declare interface Computed<Value, Diff = unknown> extends Signal<Value, D
156
156
  * ```ts
157
157
  * class Counter {
158
158
  * max = 100
159
- * count = atom<number>(0)
159
+ * count = atom('count', 0)
160
160
  *
161
161
  * @computed({isEqual: (a, b) => a === b})
162
162
  * getRemaining() {
@@ -243,8 +243,8 @@ export declare function computed<Value, Diff = unknown>(options?: ComputedOption
243
243
  * A function type that computes the difference between two values of a signal.
244
244
  *
245
245
  * This function is used to generate incremental diffs that can be applied to
246
- * reconstruct state changes over time. It's particularly useful for features
247
- * like undo/redo, synchronization, and change tracking.
246
+ * reconstruct state changes over time, so that downstream computeds and effects can
247
+ * update incrementally instead of recomputing from scratch.
248
248
  *
249
249
  * The function should analyze the previous and current values and return a
250
250
  * diff object that represents the change. If the diff cannot be computed
@@ -253,7 +253,7 @@ export declare function computed<Value, Diff = unknown>(options?: ComputedOption
253
253
  *
254
254
  * @param previousValue - The previous value of the signal
255
255
  * @param currentValue - The current value of the signal
256
- * @param lastComputedEpoch - The epoch when the previous value was set
256
+ * @param lastComputedEpoch - For an atom, the epoch when the previous value was set. For a computed, the epoch at which it was last checked (the same value its compute function receives), so that `other.getDiffSince(lastComputedEpoch)` yields exactly the changes not yet accounted for.
257
257
  * @param currentEpoch - The epoch when the current value was set
258
258
  * @returns A diff object representing the change, or the unique symbol RESET_VALUE if no diff can be computed
259
259
  *
@@ -300,7 +300,7 @@ export declare interface ComputedOptions<Value, Diff> {
300
300
  /**
301
301
  * The maximum number of diffs to keep in the history buffer.
302
302
  *
303
- * If you don't need to compute diffs, or if you will supply diffs manually via {@link Atom.set}, you can leave this as `undefined` and no history buffer will be created.
303
+ * If you don't need diffs, leave this as `undefined` and no history buffer will be created. Diffs supplied via {@link withDiff} or {@link ComputedOptions.computeDiff} are only recorded when this is set.
304
304
  *
305
305
  * If you expect the value to be part of an active effect subscription all the time, and to not change multiple times inside of a single transaction, you can set this to a relatively low number (e.g. 10).
306
306
  *
@@ -341,7 +341,7 @@ export declare interface ComputedOptions<Value, Diff> {
341
341
  *
342
342
  * @public
343
343
  */
344
- export declare const EffectScheduler: new <Result>(name: string, runEffect: (lastReactedEpoch: number) => Result, options?: EffectSchedulerOptions | undefined) => EffectScheduler<Result>;
344
+ export declare const EffectScheduler: new <Result>(name: string, runEffect: (lastReactedEpoch: number) => Result, options?: EffectSchedulerOptions) => EffectScheduler<Result>;
345
345
 
346
346
  /** @public */
347
347
  export declare interface EffectScheduler<Result> {
@@ -410,12 +410,9 @@ export declare interface EffectSchedulerOptions {
410
410
  * }
411
411
  * }
412
412
  * const stop = react('set page title', () => {
413
- * document.title = doc.title,
414
- * }, scheduleEffect)
413
+ * document.title = doc.title
414
+ * }, { scheduleEffect })
415
415
  * ```
416
- *
417
- * @param execute - A function that will execute the effect.
418
- * @returns void
419
416
  */
420
417
  scheduleEffect?: (execute: () => void) => void;
421
418
  }
@@ -433,7 +430,7 @@ export declare const EMPTY_ARRAY: [];
433
430
  * ```ts
434
431
  * class Counter {
435
432
  * max = 100
436
- * count = atom(0)
433
+ * count = atom('count', 0)
437
434
  *
438
435
  * @computed getRemaining() {
439
436
  * return this.max - this.count.get()
@@ -451,7 +448,7 @@ export declare const EMPTY_ARRAY: [];
451
448
  * @param propertyName - The property name
452
449
  * @public
453
450
  */
454
- export declare function getComputedInstance<Obj extends object, Prop extends keyof Obj>(obj: Obj, propertyName: Prop): Computed<Obj[Prop]>;
451
+ export declare function getComputedInstance<Obj extends object, Prop extends keyof Obj>(obj: Obj, propertyName: Prop): Computed<Obj[Prop] extends () => infer Value ? Value : Obj[Prop]>;
455
452
 
456
453
  /**
457
454
  * Returns true if the given value is an {@link Atom}.
@@ -631,12 +628,12 @@ export declare function reactor<Result>(name: string, fn: (lastReactedEpoch: num
631
628
  *
632
629
  * @example
633
630
  * ```ts
634
- * import { atom, getGlobalEpoch, RESET_VALUE } from '@tldraw/state'
631
+ * import { atom, RESET_VALUE } from '@tldraw/state'
635
632
  *
636
- * const count = atom('count', 0, { historyLength: 3 })
637
- * const oldEpoch = getGlobalEpoch()
633
+ * const count = atom('count', 0, { historyLength: 3, computeDiff: (prev, next) => next - prev })
634
+ * const oldEpoch = count.lastChangedEpoch
638
635
  *
639
- * // Make many changes that exceed history length
636
+ * // Make more changes than the history length can hold
640
637
  * count.set(1)
641
638
  * count.set(2)
642
639
  * count.set(3)
@@ -796,7 +793,7 @@ export declare function transact<T>(fn: () => T): T;
796
793
  * // Logs "Hello, Jane Smith!"
797
794
  * ```
798
795
  *
799
- * If the function throws, the transaction is aborted and any signals that were updated during the transaction revert to their state before the transaction began.
796
+ * If the function throws, the transaction is aborted and any signals that were updated during the transaction revert to their state before the transaction began. An aborted transaction still flushes effects: effects whose parents went through a change-and-restore round trip are checked again and, if a parent's value differs from what they last saw (an atom they read directly always will), run once more with the restored values.
800
797
  *
801
798
  * @example
802
799
  * ```ts
@@ -814,8 +811,9 @@ export declare function transact<T>(fn: () => T): T;
814
811
  * throw new Error('oops')
815
812
  * })
816
813
  *
817
- * // Does not log
818
814
  * // firstName.get() === 'John'
815
+ * // Logs "Hello, John Doe!" again: effects whose parents were changed and restored still run,
816
+ * // and observe the restored values.
819
817
  * ```
820
818
  *
821
819
  * A `rollback` callback is passed into the function.
@@ -838,9 +836,9 @@ export declare function transact<T>(fn: () => T): T;
838
836
  * rollback()
839
837
  * })
840
838
  *
841
- * // Does not log
842
839
  * // firstName.get() === 'John'
843
840
  * // lastName.get() === 'Doe'
841
+ * // Logs "Hello, John Doe!" again, as above.
844
842
  * ```
845
843
  *
846
844
  * @param fn - The function to run in a transaction, called with a function to roll back the change.
@@ -886,10 +884,10 @@ export declare type UNINITIALIZED = typeof UNINITIALIZED;
886
884
  * @example
887
885
  * ```ts
888
886
  * const name = atom('name', 'Sam')
889
- * const time = atom('time', () => new Date().getTime())
887
+ * const time = atom('time', Date.now())
890
888
  *
891
889
  * setInterval(() => {
892
- * time.set(new Date().getTime())
890
+ * time.set(Date.now())
893
891
  * })
894
892
  *
895
893
  * react('log name changes', () => {
@@ -904,7 +902,8 @@ export declare function unsafe__withoutCapture<T>(fn: () => T): T;
904
902
 
905
903
  /**
906
904
  * A debugging tool that tells you why a computed signal or effect is running.
907
- * Call in the body of a computed signal or effect function.
905
+ * Call in the body of a computed signal or effect function. Nothing is logged for the run that
906
+ * calls it; from the next run on, each run logs the ancestors that changed.
908
907
  *
909
908
  * @example
910
909
  * ```ts
@@ -916,8 +915,8 @@ export declare function unsafe__withoutCapture<T>(fn: () => T): T;
916
915
  *
917
916
  * name.set('Alice')
918
917
  *
919
- * // 'greeting' is running because:
920
- * // 'name' changed => 'Alice'
918
+ * // Effect(greeting) is executing because:
919
+ * // ↳ Atom(name) changed
921
920
  * ```
922
921
  *
923
922
  * @public
package/dist-cjs/index.js CHANGED
@@ -61,7 +61,7 @@ if (actualApiVersion !== currentApiVersion) {
61
61
  }
62
62
  (0, import_utils.registerTldrawLibraryVersion)(
63
63
  "@tldraw/state",
64
- "5.3.2",
64
+ "5.4.0-canary.02cd0bd3b597",
65
65
  "cjs"
66
66
  );
67
67
  //# sourceMappingURL=index.js.map
@@ -24,54 +24,27 @@ __export(ArraySet_exports, {
24
24
  module.exports = __toCommonJS(ArraySet_exports);
25
25
  const ARRAY_SIZE_THRESHOLD = 8;
26
26
  class ArraySet {
27
- arraySize = 0;
28
- array = Array(ARRAY_SIZE_THRESHOLD);
29
27
  set = null;
28
+ // Slots [0, arraySize) hold the items; slots beyond are undefined. `add`/`has` scan the whole
29
+ // array with indexOf, which is why `clear` and `remove` must blank vacated slots.
30
+ array = null;
31
+ arraySize = 0;
30
32
  /**
31
33
  * Get whether this ArraySet has any elements.
32
- *
33
- * @returns True if this ArraySet has any elements, false otherwise.
34
34
  */
35
35
  // eslint-disable-next-line tldraw/no-setter-getter
36
36
  get isEmpty() {
37
- if (this.array) {
38
- return this.arraySize === 0;
39
- }
40
37
  if (this.set) {
41
38
  return this.set.size === 0;
42
39
  }
43
- throw new Error("no set or array");
40
+ return this.arraySize === 0;
44
41
  }
45
42
  /**
46
43
  * Add an element to the ArraySet if it is not already present.
47
44
  *
48
- * @param elem - The element to add to the set
49
45
  * @returns `true` if the element was added, `false` if it was already present
50
- * @example
51
- * ```ts
52
- * const arraySet = new ArraySet<string>()
53
- *
54
- * console.log(arraySet.add('hello')) // true
55
- * console.log(arraySet.add('hello')) // false (already exists)
56
- * ```
57
46
  */
58
47
  add(elem) {
59
- if (this.array) {
60
- const idx = this.array.indexOf(elem);
61
- if (idx !== -1) {
62
- return false;
63
- }
64
- if (this.arraySize < ARRAY_SIZE_THRESHOLD) {
65
- this.array[this.arraySize] = elem;
66
- this.arraySize++;
67
- return true;
68
- } else {
69
- this.set = new Set(this.array);
70
- this.array = null;
71
- this.set.add(elem);
72
- return true;
73
- }
74
- }
75
48
  if (this.set) {
76
49
  if (this.set.has(elem)) {
77
50
  return false;
@@ -79,168 +52,98 @@ class ArraySet {
79
52
  this.set.add(elem);
80
53
  return true;
81
54
  }
82
- throw new Error("no set or array");
55
+ if (!this.array) {
56
+ this.array = Array(ARRAY_SIZE_THRESHOLD);
57
+ } else if (this.array.indexOf(elem) !== -1) {
58
+ return false;
59
+ }
60
+ if (this.arraySize < ARRAY_SIZE_THRESHOLD) {
61
+ this.array[this.arraySize] = elem;
62
+ this.arraySize++;
63
+ return true;
64
+ }
65
+ this.set = new Set(this.array);
66
+ this.set.add(elem);
67
+ this.array = null;
68
+ this.arraySize = 0;
69
+ return true;
83
70
  }
84
71
  /**
85
72
  * Remove an element from the ArraySet if it is present.
86
73
  *
87
- * @param elem - The element to remove from the set
88
74
  * @returns `true` if the element was removed, `false` if it was not present
89
- * @example
90
- * ```ts
91
- * const arraySet = new ArraySet<string>()
92
- * arraySet.add('hello')
93
- *
94
- * console.log(arraySet.remove('hello')) // true
95
- * console.log(arraySet.remove('hello')) // false (not present)
96
- * ```
97
75
  */
98
76
  remove(elem) {
99
- if (this.array) {
100
- const idx = this.array.indexOf(elem);
101
- if (idx === -1) {
102
- return false;
103
- }
104
- this.array[idx] = void 0;
105
- this.arraySize--;
106
- if (idx !== this.arraySize) {
107
- this.array[idx] = this.array[this.arraySize];
108
- this.array[this.arraySize] = void 0;
109
- }
110
- return true;
111
- }
112
77
  if (this.set) {
113
- if (!this.set.has(elem)) {
114
- return false;
115
- }
116
- this.set.delete(elem);
117
- return true;
78
+ return this.set.delete(elem);
79
+ }
80
+ if (!this.array) {
81
+ return false;
82
+ }
83
+ const idx = this.array.indexOf(elem);
84
+ if (idx === -1) {
85
+ return false;
118
86
  }
119
- throw new Error("no set or array");
87
+ this.arraySize--;
88
+ this.array[idx] = this.array[this.arraySize];
89
+ this.array[this.arraySize] = void 0;
90
+ return true;
120
91
  }
121
92
  /**
122
93
  * Execute a callback function for each element in the ArraySet.
123
- *
124
- * @param visitor - A function to call for each element in the set
125
- * @example
126
- * ```ts
127
- * const arraySet = new ArraySet<string>()
128
- * arraySet.add('hello')
129
- * arraySet.add('world')
130
- *
131
- * arraySet.visit((item) => {
132
- * console.log(item) // 'hello', 'world'
133
- * })
134
- * ```
135
94
  */
136
95
  visit(visitor) {
137
- if (this.array) {
138
- for (let i = 0; i < this.arraySize; i++) {
139
- const elem = this.array[i];
140
- if (typeof elem !== "undefined") {
141
- visitor(elem);
142
- }
143
- }
144
- return;
145
- }
146
96
  if (this.set) {
147
97
  this.set.forEach(visitor);
148
98
  return;
149
99
  }
150
- throw new Error("no set or array");
100
+ if (!this.array) {
101
+ return;
102
+ }
103
+ for (let i = 0; i < this.arraySize; i++) {
104
+ visitor(this.array[i]);
105
+ }
151
106
  }
152
107
  /**
153
108
  * Make the ArraySet iterable, allowing it to be used in for...of loops and with spread syntax.
154
- *
155
- * @returns An iterator that yields each element in the set
156
- * @example
157
- * ```ts
158
- * const arraySet = new ArraySet<number>()
159
- * arraySet.add(1)
160
- * arraySet.add(2)
161
- *
162
- * for (const item of arraySet) {
163
- * console.log(item) // 1, 2
164
- * }
165
- *
166
- * const items = [...arraySet] // [1, 2]
167
- * ```
168
109
  */
169
110
  *[Symbol.iterator]() {
170
- if (this.array) {
111
+ if (this.set) {
112
+ yield* this.set;
113
+ } else if (this.array) {
171
114
  for (let i = 0; i < this.arraySize; i++) {
172
- const elem = this.array[i];
173
- if (typeof elem !== "undefined") {
174
- yield elem;
175
- }
115
+ yield this.array[i];
176
116
  }
177
- } else if (this.set) {
178
- yield* this.set;
179
- } else {
180
- throw new Error("no set or array");
181
117
  }
182
118
  }
183
119
  /**
184
120
  * Check whether an element is present in the ArraySet.
185
- *
186
- * @param elem - The element to check for
187
- * @returns `true` if the element is present, `false` otherwise
188
- * @example
189
- * ```ts
190
- * const arraySet = new ArraySet<string>()
191
- * arraySet.add('hello')
192
- *
193
- * console.log(arraySet.has('hello')) // true
194
- * console.log(arraySet.has('world')) // false
195
- * ```
196
121
  */
197
122
  has(elem) {
198
- if (this.array) {
199
- return this.array.indexOf(elem) !== -1;
200
- } else {
123
+ if (this.set) {
201
124
  return this.set.has(elem);
202
125
  }
126
+ return this.array ? this.array.indexOf(elem) !== -1 : false;
203
127
  }
204
128
  /**
205
129
  * Remove all elements from the ArraySet.
206
- *
207
- * @example
208
- * ```ts
209
- * const arraySet = new ArraySet<string>()
210
- * arraySet.add('hello')
211
- * arraySet.add('world')
212
- *
213
- * arraySet.clear()
214
- * console.log(arraySet.size()) // 0
215
- * ```
216
130
  */
217
131
  clear() {
218
132
  if (this.set) {
219
133
  this.set.clear();
220
- } else {
134
+ } else if (this.array) {
135
+ this.array.fill(void 0, 0, this.arraySize);
221
136
  this.arraySize = 0;
222
- this.array = [];
223
137
  }
224
138
  }
225
139
  /**
226
140
  * Get the number of elements in the ArraySet.
227
- *
228
- * @returns The number of elements in the set
229
- * @example
230
- * ```ts
231
- * const arraySet = new ArraySet<string>()
232
- * console.log(arraySet.size()) // 0
233
- *
234
- * arraySet.add('hello')
235
- * console.log(arraySet.size()) // 1
236
- * ```
237
141
  */
238
142
  size() {
239
143
  if (this.set) {
240
144
  return this.set.size;
241
- } else {
242
- return this.arraySize;
243
145
  }
146
+ return this.arraySize;
244
147
  }
245
148
  }
246
149
  //# sourceMappingURL=ArraySet.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/ArraySet.ts"],
4
- "sourcesContent": ["/**\n * The maximum number of items that can be stored in an ArraySet in array mode before switching to Set mode.\n *\n * @public\n * @example\n * ```ts\n * import { ARRAY_SIZE_THRESHOLD } from '@tldraw/state'\n *\n * console.log(ARRAY_SIZE_THRESHOLD) // 8\n * ```\n */\nexport const ARRAY_SIZE_THRESHOLD = 8\n\n/**\n * An ArraySet operates as an array until it reaches a certain size, after which a Set is used\n * instead. In either case, the same methods are used to get, set, remove, and visit the items.\n * @internal\n */\nexport class ArraySet<T> {\n\tprivate arraySize = 0\n\n\tprivate array: (T | undefined)[] | null = Array(ARRAY_SIZE_THRESHOLD)\n\n\tprivate set: Set<T> | null = null\n\n\t/**\n\t * Get whether this ArraySet has any elements.\n\t *\n\t * @returns True if this ArraySet has any elements, false otherwise.\n\t */\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget isEmpty() {\n\t\tif (this.array) {\n\t\t\treturn this.arraySize === 0\n\t\t}\n\n\t\tif (this.set) {\n\t\t\treturn this.set.size === 0\n\t\t}\n\n\t\tthrow new Error('no set or array')\n\t}\n\n\t/**\n\t * Add an element to the ArraySet if it is not already present.\n\t *\n\t * @param elem - The element to add to the set\n\t * @returns `true` if the element was added, `false` if it was already present\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<string>()\n\t *\n\t * console.log(arraySet.add('hello')) // true\n\t * console.log(arraySet.add('hello')) // false (already exists)\n\t * ```\n\t */\n\tadd(elem: T) {\n\t\tif (this.array) {\n\t\t\tconst idx = this.array.indexOf(elem)\n\n\t\t\t// Return false if the element is already in the array.\n\t\t\tif (idx !== -1) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tif (this.arraySize < ARRAY_SIZE_THRESHOLD) {\n\t\t\t\t// If the array is below the size threshold, push items into the array.\n\n\t\t\t\t// Insert the element into the array's next available slot.\n\t\t\t\tthis.array[this.arraySize] = elem\n\t\t\t\tthis.arraySize++\n\n\t\t\t\treturn true\n\t\t\t} else {\n\t\t\t\t// If the array is full, convert it to a set and remove the array.\n\t\t\t\tthis.set = new Set(this.array as any)\n\t\t\t\tthis.array = null\n\t\t\t\tthis.set.add(elem)\n\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\tif (this.set) {\n\t\t\t// Return false if the element is already in the set.\n\t\t\tif (this.set.has(elem)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tthis.set.add(elem)\n\t\t\treturn true\n\t\t}\n\n\t\tthrow new Error('no set or array')\n\t}\n\n\t/**\n\t * Remove an element from the ArraySet if it is present.\n\t *\n\t * @param elem - The element to remove from the set\n\t * @returns `true` if the element was removed, `false` if it was not present\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<string>()\n\t * arraySet.add('hello')\n\t *\n\t * console.log(arraySet.remove('hello')) // true\n\t * console.log(arraySet.remove('hello')) // false (not present)\n\t * ```\n\t */\n\tremove(elem: T) {\n\t\tif (this.array) {\n\t\t\tconst idx = this.array.indexOf(elem)\n\n\t\t\t// If the item is not in the array, return false.\n\t\t\tif (idx === -1) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tthis.array[idx] = undefined\n\t\t\tthis.arraySize--\n\n\t\t\tif (idx !== this.arraySize) {\n\t\t\t\t// If the item is not the last item in the array, move the last item into the\n\t\t\t\t// removed item's slot.\n\t\t\t\tthis.array[idx] = this.array[this.arraySize]\n\t\t\t\tthis.array[this.arraySize] = undefined\n\t\t\t}\n\n\t\t\treturn true\n\t\t}\n\n\t\tif (this.set) {\n\t\t\t// If the item is not in the set, return false.\n\t\t\tif (!this.set.has(elem)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tthis.set.delete(elem)\n\n\t\t\treturn true\n\t\t}\n\n\t\tthrow new Error('no set or array')\n\t}\n\n\t/**\n\t * Execute a callback function for each element in the ArraySet.\n\t *\n\t * @param visitor - A function to call for each element in the set\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<string>()\n\t * arraySet.add('hello')\n\t * arraySet.add('world')\n\t *\n\t * arraySet.visit((item) => {\n\t * console.log(item) // 'hello', 'world'\n\t * })\n\t * ```\n\t */\n\tvisit(visitor: (item: T) => void) {\n\t\tif (this.array) {\n\t\t\tfor (let i = 0; i < this.arraySize; i++) {\n\t\t\t\tconst elem = this.array[i]\n\n\t\t\t\tif (typeof elem !== 'undefined') {\n\t\t\t\t\tvisitor(elem)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn\n\t\t}\n\n\t\tif (this.set) {\n\t\t\tthis.set.forEach(visitor)\n\n\t\t\treturn\n\t\t}\n\n\t\tthrow new Error('no set or array')\n\t}\n\n\t/**\n\t * Make the ArraySet iterable, allowing it to be used in for...of loops and with spread syntax.\n\t *\n\t * @returns An iterator that yields each element in the set\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<number>()\n\t * arraySet.add(1)\n\t * arraySet.add(2)\n\t *\n\t * for (const item of arraySet) {\n\t * console.log(item) // 1, 2\n\t * }\n\t *\n\t * const items = [...arraySet] // [1, 2]\n\t * ```\n\t */\n\t*[Symbol.iterator]() {\n\t\tif (this.array) {\n\t\t\tfor (let i = 0; i < this.arraySize; i++) {\n\t\t\t\tconst elem = this.array[i]\n\n\t\t\t\tif (typeof elem !== 'undefined') {\n\t\t\t\t\tyield elem\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.set) {\n\t\t\tyield* this.set\n\t\t} else {\n\t\t\tthrow new Error('no set or array')\n\t\t}\n\t}\n\n\t/**\n\t * Check whether an element is present in the ArraySet.\n\t *\n\t * @param elem - The element to check for\n\t * @returns `true` if the element is present, `false` otherwise\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<string>()\n\t * arraySet.add('hello')\n\t *\n\t * console.log(arraySet.has('hello')) // true\n\t * console.log(arraySet.has('world')) // false\n\t * ```\n\t */\n\thas(elem: T) {\n\t\tif (this.array) {\n\t\t\treturn this.array.indexOf(elem) !== -1\n\t\t} else {\n\t\t\treturn this.set!.has(elem)\n\t\t}\n\t}\n\n\t/**\n\t * Remove all elements from the ArraySet.\n\t *\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<string>()\n\t * arraySet.add('hello')\n\t * arraySet.add('world')\n\t *\n\t * arraySet.clear()\n\t * console.log(arraySet.size()) // 0\n\t * ```\n\t */\n\tclear() {\n\t\tif (this.set) {\n\t\t\tthis.set.clear()\n\t\t} else {\n\t\t\tthis.arraySize = 0\n\t\t\tthis.array = []\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of elements in the ArraySet.\n\t *\n\t * @returns The number of elements in the set\n\t * @example\n\t * ```ts\n\t * const arraySet = new ArraySet<string>()\n\t * console.log(arraySet.size()) // 0\n\t *\n\t * arraySet.add('hello')\n\t * console.log(arraySet.size()) // 1\n\t * ```\n\t */\n\tsize() {\n\t\tif (this.set) {\n\t\t\treturn this.set.size\n\t\t} else {\n\t\t\treturn this.arraySize\n\t\t}\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * The number of items an ArraySet holds in array mode before switching to a Set.\n * Exported only for tests.\n * @internal\n */\nexport const ARRAY_SIZE_THRESHOLD = 8\n\n/**\n * An ArraySet operates as an array until it reaches a certain size, after which a Set is used\n * instead. In either case, the same methods are used to get, set, remove, and visit the items.\n *\n * `set` and `array` are never both non-null. `set` being null means array mode, but the array\n * itself is only allocated on the first `add` (most signals never get a child, and an empty\n * ArraySet is created for every atom and effect, and two for every computed), so array-mode code\n * must handle `array === null`; `arraySize` is 0 in that state. Once promoted to a set, an\n * ArraySet never goes back.\n * @internal\n */\nexport class ArraySet<T> {\n\tprivate set: Set<T> | null = null\n\n\t// Slots [0, arraySize) hold the items; slots beyond are undefined. `add`/`has` scan the whole\n\t// array with indexOf, which is why `clear` and `remove` must blank vacated slots.\n\tprivate array: (T | undefined)[] | null = null\n\n\tprivate arraySize = 0\n\n\t/**\n\t * Get whether this ArraySet has any elements.\n\t */\n\t// eslint-disable-next-line tldraw/no-setter-getter\n\tget isEmpty() {\n\t\tif (this.set) {\n\t\t\treturn this.set.size === 0\n\t\t}\n\n\t\treturn this.arraySize === 0\n\t}\n\n\t/**\n\t * Add an element to the ArraySet if it is not already present.\n\t *\n\t * @returns `true` if the element was added, `false` if it was already present\n\t */\n\tadd(elem: T) {\n\t\tif (this.set) {\n\t\t\tif (this.set.has(elem)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tthis.set.add(elem)\n\t\t\treturn true\n\t\t}\n\n\t\tif (!this.array) {\n\t\t\tthis.array = Array(ARRAY_SIZE_THRESHOLD)\n\t\t} else if (this.array.indexOf(elem) !== -1) {\n\t\t\treturn false\n\t\t}\n\n\t\tif (this.arraySize < ARRAY_SIZE_THRESHOLD) {\n\t\t\tthis.array[this.arraySize] = elem\n\t\t\tthis.arraySize++\n\n\t\t\treturn true\n\t\t}\n\n\t\t// The array is full: promote to a set.\n\t\tthis.set = new Set(this.array as T[])\n\t\tthis.set.add(elem)\n\t\tthis.array = null\n\t\tthis.arraySize = 0\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Remove an element from the ArraySet if it is present.\n\t *\n\t * @returns `true` if the element was removed, `false` if it was not present\n\t */\n\tremove(elem: T) {\n\t\tif (this.set) {\n\t\t\treturn this.set.delete(elem)\n\t\t}\n\n\t\tif (!this.array) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst idx = this.array.indexOf(elem)\n\n\t\tif (idx === -1) {\n\t\t\treturn false\n\t\t}\n\n\t\tthis.arraySize--\n\n\t\t// Move the last item into the vacated slot so the items stay dense.\n\t\tthis.array[idx] = this.array[this.arraySize]\n\t\tthis.array[this.arraySize] = undefined\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Execute a callback function for each element in the ArraySet.\n\t */\n\tvisit(visitor: (item: T) => void) {\n\t\tif (this.set) {\n\t\t\tthis.set.forEach(visitor)\n\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.array) {\n\t\t\treturn\n\t\t}\n\n\t\tfor (let i = 0; i < this.arraySize; i++) {\n\t\t\tvisitor(this.array[i]!)\n\t\t}\n\t}\n\n\t/**\n\t * Make the ArraySet iterable, allowing it to be used in for...of loops and with spread syntax.\n\t */\n\t*[Symbol.iterator]() {\n\t\tif (this.set) {\n\t\t\tyield* this.set\n\t\t} else if (this.array) {\n\t\t\tfor (let i = 0; i < this.arraySize; i++) {\n\t\t\t\tyield this.array[i]!\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Check whether an element is present in the ArraySet.\n\t */\n\thas(elem: T) {\n\t\tif (this.set) {\n\t\t\treturn this.set.has(elem)\n\t\t}\n\n\t\treturn this.array ? this.array.indexOf(elem) !== -1 : false\n\t}\n\n\t/**\n\t * Remove all elements from the ArraySet.\n\t */\n\tclear() {\n\t\tif (this.set) {\n\t\t\tthis.set.clear()\n\t\t} else if (this.array) {\n\t\t\t// Blank the used slots in place rather than allocating a new array: this runs on every\n\t\t\t// computed derive and effect run.\n\t\t\tthis.array.fill(undefined, 0, this.arraySize)\n\t\t\tthis.arraySize = 0\n\t\t}\n\t}\n\n\t/**\n\t * Get the number of elements in the ArraySet.\n\t */\n\tsize() {\n\t\tif (this.set) {\n\t\t\treturn this.set.size\n\t\t}\n\n\t\treturn this.arraySize\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKO,MAAM,uBAAuB;AAa7B,MAAM,SAAY;AAAA,EAChB,MAAqB;AAAA;AAAA;AAAA,EAIrB,QAAkC;AAAA,EAElC,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAMpB,IAAI,UAAU;AACb,QAAI,KAAK,KAAK;AACb,aAAO,KAAK,IAAI,SAAS;AAAA,IAC1B;AAEA,WAAO,KAAK,cAAc;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,MAAS;AACZ,QAAI,KAAK,KAAK;AACb,UAAI,KAAK,IAAI,IAAI,IAAI,GAAG;AACvB,eAAO;AAAA,MACR;AAEA,WAAK,IAAI,IAAI,IAAI;AACjB,aAAO;AAAA,IACR;AAEA,QAAI,CAAC,KAAK,OAAO;AAChB,WAAK,QAAQ,MAAM,oBAAoB;AAAA,IACxC,WAAW,KAAK,MAAM,QAAQ,IAAI,MAAM,IAAI;AAC3C,aAAO;AAAA,IACR;AAEA,QAAI,KAAK,YAAY,sBAAsB;AAC1C,WAAK,MAAM,KAAK,SAAS,IAAI;AAC7B,WAAK;AAEL,aAAO;AAAA,IACR;AAGA,SAAK,MAAM,IAAI,IAAI,KAAK,KAAY;AACpC,SAAK,IAAI,IAAI,IAAI;AACjB,SAAK,QAAQ;AACb,SAAK,YAAY;AAEjB,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,MAAS;AACf,QAAI,KAAK,KAAK;AACb,aAAO,KAAK,IAAI,OAAO,IAAI;AAAA,IAC5B;AAEA,QAAI,CAAC,KAAK,OAAO;AAChB,aAAO;AAAA,IACR;AAEA,UAAM,MAAM,KAAK,MAAM,QAAQ,IAAI;AAEnC,QAAI,QAAQ,IAAI;AACf,aAAO;AAAA,IACR;AAEA,SAAK;AAGL,SAAK,MAAM,GAAG,IAAI,KAAK,MAAM,KAAK,SAAS;AAC3C,SAAK,MAAM,KAAK,SAAS,IAAI;AAE7B,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAA4B;AACjC,QAAI,KAAK,KAAK;AACb,WAAK,IAAI,QAAQ,OAAO;AAExB;AAAA,IACD;AAEA,QAAI,CAAC,KAAK,OAAO;AAChB;AAAA,IACD;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,KAAK;AACxC,cAAQ,KAAK,MAAM,CAAC,CAAE;AAAA,IACvB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,EAAE,OAAO,QAAQ,IAAI;AACpB,QAAI,KAAK,KAAK;AACb,aAAO,KAAK;AAAA,IACb,WAAW,KAAK,OAAO;AACtB,eAAS,IAAI,GAAG,IAAI,KAAK,WAAW,KAAK;AACxC,cAAM,KAAK,MAAM,CAAC;AAAA,MACnB;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAS;AACZ,QAAI,KAAK,KAAK;AACb,aAAO,KAAK,IAAI,IAAI,IAAI;AAAA,IACzB;AAEA,WAAO,KAAK,QAAQ,KAAK,MAAM,QAAQ,IAAI,MAAM,KAAK;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACP,QAAI,KAAK,KAAK;AACb,WAAK,IAAI,MAAM;AAAA,IAChB,WAAW,KAAK,OAAO;AAGtB,WAAK,MAAM,KAAK,QAAW,GAAG,KAAK,SAAS;AAC5C,WAAK,YAAY;AAAA,IAClB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO;AACN,QAAI,KAAK,KAAK;AACb,aAAO,KAAK,IAAI;AAAA,IACjB;AAEA,WAAO,KAAK;AAAA,EACb;AACD;",
6
6
  "names": []
7
7
  }
@@ -42,30 +42,15 @@ class __Atom__ {
42
42
  }
43
43
  name;
44
44
  current;
45
- /**
46
- * Custom equality function for comparing values, or null to use default equality.
47
- * @internal
48
- */
45
+ /** @internal */
49
46
  isEqual;
50
- /**
51
- * Optional function to compute diffs between old and new values.
52
- * @internal
53
- */
47
+ /** @internal */
54
48
  computeDiff;
55
- /**
56
- * The global epoch when this atom was last changed.
57
- * @internal
58
- */
49
+ /** @internal */
59
50
  lastChangedEpoch = (0, import_transactions.getGlobalEpoch)();
60
- /**
61
- * Set of child signals that depend on this atom.
62
- * @internal
63
- */
51
+ /** @internal */
64
52
  children = new import_ArraySet.ArraySet();
65
- /**
66
- * Optional history buffer for tracking changes over time.
67
- * @internal
68
- */
53
+ /** @internal */
69
54
  historyBuffer;
70
55
  /**
71
56
  * Gets the current value without capturing it as a dependency in the current reactive context.
@@ -109,15 +94,16 @@ class __Atom__ {
109
94
  if (this.isEqual?.(this.current, value) ?? (0, import_helpers.equals)(this.current, value)) {
110
95
  return this.current;
111
96
  }
97
+ let historyDiff;
98
+ if (this.historyBuffer) {
99
+ historyDiff = diff !== void 0 ? diff : this.computeDiff ? this.computeDiff(this.current, value, this.lastChangedEpoch, (0, import_transactions.getGlobalEpoch)() + 1) : import_types.RESET_VALUE;
100
+ }
112
101
  (0, import_transactions.advanceGlobalEpoch)();
102
+ const epoch = (0, import_transactions.getGlobalEpoch)();
113
103
  if (this.historyBuffer) {
114
- this.historyBuffer.pushEntry(
115
- this.lastChangedEpoch,
116
- (0, import_transactions.getGlobalEpoch)(),
117
- diff ?? this.computeDiff?.(this.current, value, this.lastChangedEpoch, (0, import_transactions.getGlobalEpoch)()) ?? import_types.RESET_VALUE
118
- );
104
+ this.historyBuffer.pushEntry(this.lastChangedEpoch, epoch, historyDiff);
119
105
  }
120
- this.lastChangedEpoch = (0, import_transactions.getGlobalEpoch)();
106
+ this.lastChangedEpoch = epoch;
121
107
  const oldValue = this.current;
122
108
  this.current = value;
123
109
  (0, import_transactions.atomDidChange)(this, oldValue);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/Atom.ts"],
4
- "sourcesContent": ["import { ArraySet } from './ArraySet'\nimport { maybeCaptureParent } from './capture'\nimport { EMPTY_ARRAY, equals, singleton } from './helpers'\nimport { HistoryBuffer } from './HistoryBuffer'\nimport { advanceGlobalEpoch, atomDidChange, getGlobalEpoch } from './transactions'\nimport { Child, ComputeDiff, RESET_VALUE, Signal } from './types'\n\n/**\n * The options to configure an atom, passed into the {@link atom} function.\n * @public\n */\nexport interface AtomOptions<Value, Diff> {\n\t/**\n\t * The maximum number of diffs to keep in the history buffer.\n\t *\n\t * If you don't need to compute diffs, or if you will supply diffs manually via {@link Atom.set}, you can leave this as `undefined` and no history buffer will be created.\n\t *\n\t * If you expect the value to be part of an active effect subscription all the time, and to not change multiple times inside of a single transaction, you can set this to a relatively low number (e.g. 10).\n\t *\n\t * Otherwise, set this to a higher number based on your usage pattern and memory constraints.\n\t *\n\t */\n\thistoryLength?: number\n\t/**\n\t * A method used to compute a diff between the atom's old and new values. If provided, it will not be used unless you also specify {@link AtomOptions.historyLength}.\n\t */\n\tcomputeDiff?: ComputeDiff<Value, Diff>\n\t/**\n\t * If provided, this will be used to compare the old and new values of the atom to determine if the value has changed.\n\t * By default, values are compared using first using strict equality (`===`), then `Object.is`, and finally any `.equals` method present in the object's prototype chain.\n\t * @param a - The old value\n\t * @param b - The new value\n\t * @returns True if the values are equal, false otherwise.\n\t */\n\tisEqual?(a: any, b: any): boolean\n}\n\n/**\n * An Atom is a signal that can be updated directly by calling {@link Atom.set} or {@link Atom.update}.\n *\n * Atoms are created using the {@link atom} function.\n *\n * @example\n * ```ts\n * const name = atom('name', 'John')\n *\n * print(name.get()) // 'John'\n * ```\n *\n * @public\n */\nexport interface Atom<Value, Diff = unknown> extends Signal<Value, Diff> {\n\t/**\n\t * Sets the value of this atom to the given value. If the value is the same as the current value, this is a no-op.\n\t *\n\t * @param value - The new value to set.\n\t * @param diff - The diff to use for the update. If not provided, the diff will be computed using {@link AtomOptions.computeDiff}.\n\t */\n\tset(value: Value, diff?: Diff): Value\n\t/**\n\t * Updates the value of this atom using the given updater function. If the returned value is the same as the current value, this is a no-op.\n\t *\n\t * @param updater - A function that takes the current value and returns the new value.\n\t */\n\tupdate(updater: (value: Value) => Value): Value\n}\n\n/**\n * Internal implementation of the Atom interface. This class should not be used directly - use the {@link atom} function instead.\n *\n * @internal\n */\nclass __Atom__<Value, Diff = unknown> implements Atom<Value, Diff> {\n\tconstructor(\n\t\tpublic readonly name: string,\n\t\tprivate current: Value,\n\t\toptions?: AtomOptions<Value, Diff>\n\t) {\n\t\tthis.isEqual = options?.isEqual ?? null\n\n\t\tif (!options) return\n\n\t\tif (options.historyLength) {\n\t\t\tthis.historyBuffer = new HistoryBuffer(options.historyLength)\n\t\t}\n\n\t\tthis.computeDiff = options.computeDiff\n\t}\n\n\t/**\n\t * Custom equality function for comparing values, or null to use default equality.\n\t * @internal\n\t */\n\treadonly isEqual: null | ((a: any, b: any) => boolean)\n\n\t/**\n\t * Optional function to compute diffs between old and new values.\n\t * @internal\n\t */\n\tcomputeDiff?: ComputeDiff<Value, Diff>\n\n\t/**\n\t * The global epoch when this atom was last changed.\n\t * @internal\n\t */\n\tlastChangedEpoch = getGlobalEpoch()\n\n\t/**\n\t * Set of child signals that depend on this atom.\n\t * @internal\n\t */\n\tchildren = new ArraySet<Child>()\n\n\t/**\n\t * Optional history buffer for tracking changes over time.\n\t * @internal\n\t */\n\thistoryBuffer?: HistoryBuffer<Diff>\n\n\t/**\n\t * Gets the current value without capturing it as a dependency in the current reactive context.\n\t * This is unsafe because it breaks the reactivity chain - use with caution.\n\t *\n\t * @param _ignoreErrors - Unused parameter for API compatibility\n\t * @returns The current value\n\t * @internal\n\t */\n\t__unsafe__getWithoutCapture(_ignoreErrors?: boolean): Value {\n\t\treturn this.current\n\t}\n\n\t/**\n\t * Gets the current value of this atom. When called within a computed signal or reaction,\n\t * this atom will be automatically captured as a dependency.\n\t *\n\t * @returns The current value\n\t * @example\n\t * ```ts\n\t * const count = atom('count', 5)\n\t * console.log(count.get()) // 5\n\t * ```\n\t */\n\tget() {\n\t\tmaybeCaptureParent(this)\n\t\treturn this.current\n\t}\n\n\t/**\n\t * Sets the value of this atom to the given value. If the value is the same as the current value, this is a no-op.\n\t *\n\t * @param value - The new value to set\n\t * @param diff - The diff to use for the update. If not provided, the diff will be computed using {@link AtomOptions.computeDiff}\n\t * @returns The new value\n\t * @example\n\t * ```ts\n\t * const count = atom('count', 0)\n\t * count.set(5) // count.get() is now 5\n\t * ```\n\t */\n\tset(value: Value, diff?: Diff): Value {\n\t\t// If the value has not changed, do nothing.\n\t\tif (this.isEqual?.(this.current, value) ?? equals(this.current, value)) {\n\t\t\treturn this.current\n\t\t}\n\n\t\t// Tick forward the global epoch\n\t\tadvanceGlobalEpoch()\n\n\t\t// Add the diff to the history buffer.\n\t\tif (this.historyBuffer) {\n\t\t\tthis.historyBuffer.pushEntry(\n\t\t\t\tthis.lastChangedEpoch,\n\t\t\t\tgetGlobalEpoch(),\n\t\t\t\tdiff ??\n\t\t\t\t\tthis.computeDiff?.(this.current, value, this.lastChangedEpoch, getGlobalEpoch()) ??\n\t\t\t\t\tRESET_VALUE\n\t\t\t)\n\t\t}\n\n\t\t// Update the atom's record of the epoch when last changed.\n\t\tthis.lastChangedEpoch = getGlobalEpoch()\n\n\t\tconst oldValue = this.current\n\t\tthis.current = value\n\n\t\t// Notify all children that this atom has changed.\n\t\tatomDidChange(this as any, oldValue)\n\n\t\treturn value\n\t}\n\n\t/**\n\t * Updates the value of this atom using the given updater function. If the returned value is the same as the current value, this is a no-op.\n\t *\n\t * @param updater - A function that takes the current value and returns the new value\n\t * @returns The new value\n\t * @example\n\t * ```ts\n\t * const count = atom('count', 5)\n\t * count.update(n => n + 1) // count.get() is now 6\n\t * ```\n\t */\n\tupdate(updater: (value: Value) => Value): Value {\n\t\treturn this.set(updater(this.current))\n\t}\n\n\t/**\n\t * Gets all the diffs that have occurred since the given epoch. When called within a computed\n\t * signal or reaction, this atom will be automatically captured as a dependency.\n\t *\n\t * @param epoch - The epoch to get changes since\n\t * @returns An array of diffs, or RESET_VALUE if history is insufficient\n\t * @internal\n\t */\n\tgetDiffSince(epoch: number): RESET_VALUE | Diff[] {\n\t\tmaybeCaptureParent(this)\n\n\t\t// If no changes have occurred since the given epoch, return an empty array.\n\t\tif (epoch >= this.lastChangedEpoch) {\n\t\t\treturn EMPTY_ARRAY\n\t\t}\n\n\t\treturn this.historyBuffer?.getChangesSince(epoch) ?? RESET_VALUE\n\t}\n}\n\n/**\n * Singleton reference to the Atom constructor. Used internally to create atom instances.\n * @internal\n */\nexport const _Atom = singleton('Atom', () => __Atom__)\n\n/**\n * Type alias for instances of the internal Atom class.\n * @internal\n */\nexport type _Atom = InstanceType<typeof _Atom>\n\n/**\n * Creates a new {@link Atom}.\n *\n * An Atom is a signal that can be updated directly by calling {@link Atom.set} or {@link Atom.update}.\n *\n * @example\n * ```ts\n * const name = atom('name', 'John')\n *\n * name.get() // 'John'\n *\n * name.set('Jane')\n *\n * name.get() // 'Jane'\n * ```\n *\n * @public\n */\nexport function atom<Value, Diff = unknown>(\n\t/**\n\t * A name for the signal. This is used for debugging and profiling purposes, it does not need to be unique.\n\t */\n\tname: string,\n\t/**\n\t * The initial value of the signal.\n\t */\n\tinitialValue: Value,\n\t/**\n\t * The options to configure the atom. See {@link AtomOptions}.\n\t */\n\toptions?: AtomOptions<Value, Diff>\n): Atom<Value, Diff> {\n\treturn new _Atom(name, initialValue, options)\n}\n\n/**\n * Returns true if the given value is an {@link Atom}.\n *\n * @param value - The value to check\n * @returns True if the value is an Atom, false otherwise\n * @example\n * ```ts\n * const myAtom = atom('test', 42)\n * const notAtom = 'hello'\n *\n * console.log(isAtom(myAtom)) // true\n * console.log(isAtom(notAtom)) // false\n * ```\n * @public\n */\nexport function isAtom(value: unknown): value is Atom<unknown> {\n\treturn value instanceof _Atom\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyB;AACzB,qBAAmC;AACnC,qBAA+C;AAC/C,2BAA8B;AAC9B,0BAAkE;AAClE,mBAAwD;AAmExD,MAAM,SAA6D;AAAA,EAClE,YACiB,MACR,SACR,SACC;AAHe;AACR;AAGR,SAAK,UAAU,SAAS,WAAW;AAEnC,QAAI,CAAC,QAAS;AAEd,QAAI,QAAQ,eAAe;AAC1B,WAAK,gBAAgB,IAAI,mCAAc,QAAQ,aAAa;AAAA,IAC7D;AAEA,SAAK,cAAc,QAAQ;AAAA,EAC5B;AAAA,EAbiB;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAmB,oCAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlC,WAAW,IAAI,yBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,4BAA4B,eAAgC;AAC3D,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM;AACL,2CAAmB,IAAI;AACvB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,IAAI,OAAc,MAAoB;AAErC,QAAI,KAAK,UAAU,KAAK,SAAS,KAAK,SAAK,uBAAO,KAAK,SAAS,KAAK,GAAG;AACvE,aAAO,KAAK;AAAA,IACb;AAGA,gDAAmB;AAGnB,QAAI,KAAK,eAAe;AACvB,WAAK,cAAc;AAAA,QAClB,KAAK;AAAA,YACL,oCAAe;AAAA,QACf,QACC,KAAK,cAAc,KAAK,SAAS,OAAO,KAAK,sBAAkB,oCAAe,CAAC,KAC/E;AAAA,MACF;AAAA,IACD;AAGA,SAAK,uBAAmB,oCAAe;AAEvC,UAAM,WAAW,KAAK;AACtB,SAAK,UAAU;AAGf,2CAAc,MAAa,QAAQ;AAEnC,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,SAAyC;AAC/C,WAAO,KAAK,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,OAAqC;AACjD,2CAAmB,IAAI;AAGvB,QAAI,SAAS,KAAK,kBAAkB;AACnC,aAAO;AAAA,IACR;AAEA,WAAO,KAAK,eAAe,gBAAgB,KAAK,KAAK;AAAA,EACtD;AACD;AAMO,MAAM,YAAQ,0BAAU,QAAQ,MAAM,QAAQ;AA0B9C,SAAS,KAIf,MAIA,cAIA,SACoB;AACpB,SAAO,IAAI,MAAM,MAAM,cAAc,OAAO;AAC7C;AAiBO,SAAS,OAAO,OAAwC;AAC9D,SAAO,iBAAiB;AACzB;",
4
+ "sourcesContent": ["import { ArraySet } from './ArraySet'\nimport { maybeCaptureParent } from './capture'\nimport { EMPTY_ARRAY, equals, singleton } from './helpers'\nimport { HistoryBuffer } from './HistoryBuffer'\nimport { advanceGlobalEpoch, atomDidChange, getGlobalEpoch } from './transactions'\nimport { Child, ComputeDiff, RESET_VALUE, Signal } from './types'\n\n/**\n * The options to configure an atom, passed into the {@link atom} function.\n * @public\n */\nexport interface AtomOptions<Value, Diff> {\n\t/**\n\t * The maximum number of diffs to keep in the history buffer.\n\t *\n\t * If you don't need diffs, leave this as `undefined` and no history buffer will be created. Diffs passed to {@link Atom.set} or produced by {@link AtomOptions.computeDiff} are only recorded when this is set.\n\t *\n\t * If you expect the value to be part of an active effect subscription all the time, and to not change multiple times inside of a single transaction, you can set this to a relatively low number (e.g. 10).\n\t *\n\t * Otherwise, set this to a higher number based on your usage pattern and memory constraints.\n\t *\n\t */\n\thistoryLength?: number\n\t/**\n\t * A method used to compute a diff between the atom's old and new values. If provided, it will not be used unless you also specify {@link AtomOptions.historyLength}.\n\t */\n\tcomputeDiff?: ComputeDiff<Value, Diff>\n\t/**\n\t * If provided, this will be used to compare the old and new values of the atom to determine if the value has changed.\n\t * By default, values are compared using first using strict equality (`===`), then `Object.is`, and finally any `.equals` method present in the object's prototype chain.\n\t * @param a - The old value\n\t * @param b - The new value\n\t * @returns True if the values are equal, false otherwise.\n\t */\n\tisEqual?(a: any, b: any): boolean\n}\n\n/**\n * An Atom is a signal that can be updated directly by calling {@link Atom.set} or {@link Atom.update}.\n *\n * Atoms are created using the {@link atom} function.\n *\n * @example\n * ```ts\n * const name = atom('name', 'John')\n *\n * print(name.get()) // 'John'\n * ```\n *\n * @public\n */\nexport interface Atom<Value, Diff = unknown> extends Signal<Value, Diff> {\n\t/**\n\t * Sets the value of this atom to the given value. If the value is the same as the current value, this is a no-op.\n\t *\n\t * @param value - The new value to set.\n\t * @param diff - The diff to use for the update. If not provided, the diff will be computed using {@link AtomOptions.computeDiff}.\n\t */\n\tset(value: Value, diff?: Diff): Value\n\t/**\n\t * Updates the value of this atom using the given updater function. If the returned value is the same as the current value, this is a no-op.\n\t *\n\t * @param updater - A function that takes the current value and returns the new value.\n\t */\n\tupdate(updater: (value: Value) => Value): Value\n}\n\n/**\n * Internal implementation of the Atom interface. This class should not be used directly - use the {@link atom} function instead.\n *\n * @internal\n */\nclass __Atom__<Value, Diff = unknown> implements Atom<Value, Diff> {\n\tconstructor(\n\t\tpublic readonly name: string,\n\t\tprivate current: Value,\n\t\toptions?: AtomOptions<Value, Diff>\n\t) {\n\t\tthis.isEqual = options?.isEqual ?? null\n\n\t\tif (!options) return\n\n\t\tif (options.historyLength) {\n\t\t\tthis.historyBuffer = new HistoryBuffer(options.historyLength)\n\t\t}\n\n\t\tthis.computeDiff = options.computeDiff\n\t}\n\n\t/** @internal */\n\treadonly isEqual: null | ((a: any, b: any) => boolean)\n\n\t/** @internal */\n\tcomputeDiff?: ComputeDiff<Value, Diff>\n\n\t/** @internal */\n\tlastChangedEpoch = getGlobalEpoch()\n\n\t/** @internal */\n\tchildren = new ArraySet<Child>()\n\n\t/** @internal */\n\thistoryBuffer?: HistoryBuffer<Diff>\n\n\t/**\n\t * Gets the current value without capturing it as a dependency in the current reactive context.\n\t * This is unsafe because it breaks the reactivity chain - use with caution.\n\t *\n\t * @param _ignoreErrors - Unused parameter for API compatibility\n\t * @returns The current value\n\t * @internal\n\t */\n\t__unsafe__getWithoutCapture(_ignoreErrors?: boolean): Value {\n\t\treturn this.current\n\t}\n\n\t/**\n\t * Gets the current value of this atom. When called within a computed signal or reaction,\n\t * this atom will be automatically captured as a dependency.\n\t *\n\t * @returns The current value\n\t * @example\n\t * ```ts\n\t * const count = atom('count', 5)\n\t * console.log(count.get()) // 5\n\t * ```\n\t */\n\tget() {\n\t\tmaybeCaptureParent(this)\n\t\treturn this.current\n\t}\n\n\t/**\n\t * Sets the value of this atom to the given value. If the value is the same as the current value, this is a no-op.\n\t *\n\t * @param value - The new value to set\n\t * @param diff - The diff to use for the update. If not provided, the diff will be computed using {@link AtomOptions.computeDiff}\n\t * @returns The new value\n\t * @example\n\t * ```ts\n\t * const count = atom('count', 0)\n\t * count.set(5) // count.get() is now 5\n\t * ```\n\t */\n\tset(value: Value, diff?: Diff): Value {\n\t\t// If the value has not changed, do nothing.\n\t\tif (this.isEqual?.(this.current, value) ?? equals(this.current, value)) {\n\t\t\treturn this.current\n\t\t}\n\n\t\t// `computeDiff` is user code: run it before ticking the epoch, so that any signal it reads is\n\t\t// checked against the epoch this write has not yet happened in. Reading a dependent computed\n\t\t// after the tick would stamp it as checked at the new epoch while the atom was still being\n\t\t// written, and it would then never see the change. Only `undefined` means \"no diff\n\t\t// supplied\"; `null` can be a legitimate diff.\n\t\tlet historyDiff: Diff | RESET_VALUE | undefined\n\t\tif (this.historyBuffer) {\n\t\t\thistoryDiff =\n\t\t\t\tdiff !== undefined\n\t\t\t\t\t? diff\n\t\t\t\t\t: this.computeDiff\n\t\t\t\t\t\t? this.computeDiff(this.current, value, this.lastChangedEpoch, getGlobalEpoch() + 1)\n\t\t\t\t\t\t: RESET_VALUE\n\t\t}\n\n\t\t// Tick forward the global epoch. This write belongs to that one epoch, so read it once and\n\t\t// use it everywhere below \u2014 otherwise a `computeDiff` that touches other atoms could leave\n\t\t// the history entry and `lastChangedEpoch` disagreeing.\n\t\tadvanceGlobalEpoch()\n\t\tconst epoch = getGlobalEpoch()\n\n\t\t// Add the diff to the history buffer.\n\t\tif (this.historyBuffer) {\n\t\t\tthis.historyBuffer.pushEntry(this.lastChangedEpoch, epoch, historyDiff)\n\t\t}\n\n\t\t// Update the atom's record of the epoch when last changed.\n\t\tthis.lastChangedEpoch = epoch\n\n\t\tconst oldValue = this.current\n\t\tthis.current = value\n\n\t\t// Notify all children that this atom has changed.\n\t\tatomDidChange(this as any, oldValue)\n\n\t\treturn value\n\t}\n\n\t/**\n\t * Updates the value of this atom using the given updater function. If the returned value is the same as the current value, this is a no-op.\n\t *\n\t * @param updater - A function that takes the current value and returns the new value\n\t * @returns The new value\n\t * @example\n\t * ```ts\n\t * const count = atom('count', 5)\n\t * count.update(n => n + 1) // count.get() is now 6\n\t * ```\n\t */\n\tupdate(updater: (value: Value) => Value): Value {\n\t\treturn this.set(updater(this.current))\n\t}\n\n\t/**\n\t * Gets all the diffs that have occurred since the given epoch. When called within a computed\n\t * signal or reaction, this atom will be automatically captured as a dependency.\n\t *\n\t * @param epoch - The epoch to get changes since\n\t * @returns An array of diffs, or RESET_VALUE if history is insufficient\n\t * @internal\n\t */\n\tgetDiffSince(epoch: number): RESET_VALUE | Diff[] {\n\t\tmaybeCaptureParent(this)\n\n\t\tif (epoch >= this.lastChangedEpoch) {\n\t\t\treturn EMPTY_ARRAY\n\t\t}\n\n\t\treturn this.historyBuffer?.getChangesSince(epoch) ?? RESET_VALUE\n\t}\n}\n\n/**\n * Singleton reference to the Atom constructor. Used internally to create atom instances.\n * @internal\n */\nexport const _Atom = singleton('Atom', () => __Atom__)\n\n/**\n * Type alias for instances of the internal Atom class.\n * @internal\n */\nexport type _Atom = InstanceType<typeof _Atom>\n\n/**\n * Creates a new {@link Atom}.\n *\n * An Atom is a signal that can be updated directly by calling {@link Atom.set} or {@link Atom.update}.\n *\n * @example\n * ```ts\n * const name = atom('name', 'John')\n *\n * name.get() // 'John'\n *\n * name.set('Jane')\n *\n * name.get() // 'Jane'\n * ```\n *\n * @public\n */\nexport function atom<Value, Diff = unknown>(\n\t/**\n\t * A name for the signal. This is used for debugging and profiling purposes, it does not need to be unique.\n\t */\n\tname: string,\n\t/**\n\t * The initial value of the signal.\n\t */\n\tinitialValue: Value,\n\t/**\n\t * The options to configure the atom. See {@link AtomOptions}.\n\t */\n\toptions?: AtomOptions<Value, Diff>\n): Atom<Value, Diff> {\n\treturn new _Atom(name, initialValue, options)\n}\n\n/**\n * Returns true if the given value is an {@link Atom}.\n *\n * @param value - The value to check\n * @returns True if the value is an Atom, false otherwise\n * @example\n * ```ts\n * const myAtom = atom('test', 42)\n * const notAtom = 'hello'\n *\n * console.log(isAtom(myAtom)) // true\n * console.log(isAtom(notAtom)) // false\n * ```\n * @public\n */\nexport function isAtom(value: unknown): value is Atom<unknown> {\n\treturn value instanceof _Atom\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAyB;AACzB,qBAAmC;AACnC,qBAA+C;AAC/C,2BAA8B;AAC9B,0BAAkE;AAClE,mBAAwD;AAmExD,MAAM,SAA6D;AAAA,EAClE,YACiB,MACR,SACR,SACC;AAHe;AACR;AAGR,SAAK,UAAU,SAAS,WAAW;AAEnC,QAAI,CAAC,QAAS;AAEd,QAAI,QAAQ,eAAe;AAC1B,WAAK,gBAAgB,IAAI,mCAAc,QAAQ,aAAa;AAAA,IAC7D;AAEA,SAAK,cAAc,QAAQ;AAAA,EAC5B;AAAA,EAbiB;AAAA,EACR;AAAA;AAAA,EAeA;AAAA;AAAA,EAGT;AAAA;AAAA,EAGA,uBAAmB,oCAAe;AAAA;AAAA,EAGlC,WAAW,IAAI,yBAAgB;AAAA;AAAA,EAG/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,4BAA4B,eAAgC;AAC3D,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM;AACL,2CAAmB,IAAI;AACvB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,IAAI,OAAc,MAAoB;AAErC,QAAI,KAAK,UAAU,KAAK,SAAS,KAAK,SAAK,uBAAO,KAAK,SAAS,KAAK,GAAG;AACvE,aAAO,KAAK;AAAA,IACb;AAOA,QAAI;AACJ,QAAI,KAAK,eAAe;AACvB,oBACC,SAAS,SACN,OACA,KAAK,cACJ,KAAK,YAAY,KAAK,SAAS,OAAO,KAAK,sBAAkB,oCAAe,IAAI,CAAC,IACjF;AAAA,IACN;AAKA,gDAAmB;AACnB,UAAM,YAAQ,oCAAe;AAG7B,QAAI,KAAK,eAAe;AACvB,WAAK,cAAc,UAAU,KAAK,kBAAkB,OAAO,WAAW;AAAA,IACvE;AAGA,SAAK,mBAAmB;AAExB,UAAM,WAAW,KAAK;AACtB,SAAK,UAAU;AAGf,2CAAc,MAAa,QAAQ;AAEnC,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,SAAyC;AAC/C,WAAO,KAAK,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,OAAqC;AACjD,2CAAmB,IAAI;AAEvB,QAAI,SAAS,KAAK,kBAAkB;AACnC,aAAO;AAAA,IACR;AAEA,WAAO,KAAK,eAAe,gBAAgB,KAAK,KAAK;AAAA,EACtD;AACD;AAMO,MAAM,YAAQ,0BAAU,QAAQ,MAAM,QAAQ;AA0B9C,SAAS,KAIf,MAIA,cAIA,SACoB;AACpB,SAAO,IAAI,MAAM,MAAM,cAAc,OAAO;AAC7C;AAiBO,SAAS,OAAO,OAAwC;AAC9D,SAAO,iBAAiB;AACzB;",
6
6
  "names": []
7
7
  }