@tldraw/state 4.0.2 → 4.1.0-canary.0259516ffb8c
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.
- package/dist-cjs/index.d.ts +358 -43
- package/dist-cjs/index.js +3 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/ArraySet.js +90 -6
- package/dist-cjs/lib/ArraySet.js.map +2 -2
- package/dist-cjs/lib/Atom.js +70 -0
- package/dist-cjs/lib/Atom.js.map +2 -2
- package/dist-cjs/lib/Computed.js +1 -1
- package/dist-cjs/lib/Computed.js.map +2 -2
- package/dist-cjs/lib/HistoryBuffer.js +57 -9
- package/dist-cjs/lib/HistoryBuffer.js.map +2 -2
- package/dist-cjs/lib/capture.js.map +2 -2
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/helpers.js.map +2 -2
- package/dist-cjs/lib/isSignal.js.map +2 -2
- package/dist-cjs/lib/localStorageAtom.js +60 -0
- package/dist-cjs/lib/localStorageAtom.js.map +7 -0
- package/dist-cjs/lib/transactions.js.map +2 -2
- package/dist-cjs/lib/types.js.map +2 -2
- package/dist-cjs/lib/warnings.js.map +2 -2
- package/dist-esm/index.d.mts +358 -43
- package/dist-esm/index.mjs +3 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/ArraySet.mjs +90 -6
- package/dist-esm/lib/ArraySet.mjs.map +2 -2
- package/dist-esm/lib/Atom.mjs +70 -0
- package/dist-esm/lib/Atom.mjs.map +2 -2
- package/dist-esm/lib/Computed.mjs +1 -1
- package/dist-esm/lib/Computed.mjs.map +2 -2
- package/dist-esm/lib/HistoryBuffer.mjs +57 -9
- package/dist-esm/lib/HistoryBuffer.mjs.map +2 -2
- package/dist-esm/lib/capture.mjs.map +2 -2
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/helpers.mjs.map +2 -2
- package/dist-esm/lib/isSignal.mjs.map +2 -2
- package/dist-esm/lib/localStorageAtom.mjs +40 -0
- package/dist-esm/lib/localStorageAtom.mjs.map +7 -0
- package/dist-esm/lib/transactions.mjs.map +2 -2
- package/dist-esm/lib/types.mjs.map +2 -2
- package/dist-esm/lib/warnings.mjs.map +2 -2
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/lib/ArraySet.ts +101 -8
- package/src/lib/Atom.ts +92 -0
- package/src/lib/Computed.ts +169 -19
- package/src/lib/HistoryBuffer.ts +76 -10
- package/src/lib/__tests__/helpers.test.ts +168 -0
- package/src/lib/__tests__/localStorageAtom.test.ts +183 -0
- package/src/lib/capture.ts +56 -1
- package/src/lib/constants.ts +25 -1
- package/src/lib/helpers.ts +137 -13
- package/src/lib/isSignal.ts +24 -0
- package/src/lib/localStorageAtom.ts +87 -0
- package/src/lib/transactions.ts +79 -10
- package/src/lib/types.ts +173 -19
- package/src/lib/warnings.ts +36 -0
package/dist-cjs/index.d.ts
CHANGED
|
@@ -95,13 +95,27 @@ export declare interface AtomOptions<Value, Diff> {
|
|
|
95
95
|
/* Excluded from this release type: Child */
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
* A computed signal created via `computed
|
|
98
|
+
* A computed signal created via the `computed` function or `@computed` decorator.
|
|
99
|
+
* Computed signals derive their values from other signals and automatically update when their dependencies change.
|
|
100
|
+
* They use lazy evaluation, only recalculating when accessed and dependencies have changed.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const firstName = atom('firstName', 'John')
|
|
105
|
+
* const lastName = atom('lastName', 'Doe')
|
|
106
|
+
* const fullName = computed('fullName', () => `${firstName.get()} ${lastName.get()}`)
|
|
107
|
+
*
|
|
108
|
+
* console.log(fullName.get()) // "John Doe"
|
|
109
|
+
* firstName.set('Jane')
|
|
110
|
+
* console.log(fullName.get()) // "Jane Doe"
|
|
111
|
+
* ```
|
|
99
112
|
*
|
|
100
113
|
* @public
|
|
101
114
|
*/
|
|
102
115
|
export declare interface Computed<Value, Diff = unknown> extends Signal<Value, Diff> {
|
|
103
116
|
/**
|
|
104
|
-
* Whether this computed
|
|
117
|
+
* Whether this computed signal is involved in an actively-running effect graph.
|
|
118
|
+
* Returns true if there are any reactions or other computed signals depending on this one.
|
|
105
119
|
* @public
|
|
106
120
|
*/
|
|
107
121
|
readonly isActivelyListening: boolean;
|
|
@@ -111,7 +125,9 @@ export declare interface Computed<Value, Diff = unknown> extends Signal<Value, D
|
|
|
111
125
|
}
|
|
112
126
|
|
|
113
127
|
/**
|
|
114
|
-
* Creates a computed signal.
|
|
128
|
+
* Creates a computed signal that derives its value from other signals.
|
|
129
|
+
* Computed signals automatically update when their dependencies change and use lazy evaluation
|
|
130
|
+
* for optimal performance.
|
|
115
131
|
*
|
|
116
132
|
* @example
|
|
117
133
|
* ```ts
|
|
@@ -149,43 +165,135 @@ export declare interface Computed<Value, Diff = unknown> extends Signal<Value, D
|
|
|
149
165
|
* }
|
|
150
166
|
* ```
|
|
151
167
|
*
|
|
152
|
-
* @param name - The name of the signal
|
|
153
|
-
* @param compute - The function that computes the value of the signal.
|
|
154
|
-
* @param options -
|
|
155
|
-
*
|
|
168
|
+
* @param name - The name of the signal for debugging purposes
|
|
169
|
+
* @param compute - The function that computes the value of the signal. Receives the previous value and last computed epoch
|
|
170
|
+
* @param options - Optional configuration for the computed signal
|
|
171
|
+
* @returns A new computed signal
|
|
156
172
|
* @public
|
|
157
173
|
*/
|
|
158
174
|
export declare function computed<Value, Diff = unknown>(name: string, compute: (previousValue: typeof UNINITIALIZED | Value, lastComputedEpoch: number) => Value | WithDiff<Value, Diff>, options?: ComputedOptions<Value, Diff>): Computed<Value, Diff>;
|
|
159
175
|
|
|
160
176
|
/**
|
|
161
|
-
*
|
|
177
|
+
* TC39 decorator for creating computed methods in classes.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* class MyClass {
|
|
182
|
+
* value = atom('value', 10)
|
|
183
|
+
*
|
|
184
|
+
* @computed
|
|
185
|
+
* doubled() {
|
|
186
|
+
* return this.value.get() * 2
|
|
187
|
+
* }
|
|
188
|
+
* }
|
|
189
|
+
* ```
|
|
190
|
+
*
|
|
191
|
+
* @param compute - The method to be decorated
|
|
192
|
+
* @param context - The decorator context provided by TypeScript
|
|
193
|
+
* @returns The decorated method
|
|
162
194
|
* @public
|
|
163
195
|
*/
|
|
164
196
|
export declare function computed<This extends object, Value>(compute: () => Value, context: ClassMethodDecoratorContext<This, () => Value>): () => Value;
|
|
165
197
|
|
|
166
198
|
/**
|
|
167
|
-
*
|
|
199
|
+
* Legacy TypeScript decorator for creating computed methods in classes.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```ts
|
|
203
|
+
* class MyClass {
|
|
204
|
+
* value = atom('value', 10)
|
|
205
|
+
*
|
|
206
|
+
* @computed
|
|
207
|
+
* doubled() {
|
|
208
|
+
* return this.value.get() * 2
|
|
209
|
+
* }
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
168
212
|
*
|
|
169
|
-
* @
|
|
213
|
+
* @param target - The class prototype
|
|
214
|
+
* @param key - The property key
|
|
215
|
+
* @param descriptor - The property descriptor
|
|
216
|
+
* @returns The modified property descriptor
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
170
219
|
export declare function computed(target: any, key: string, descriptor: PropertyDescriptor): PropertyDescriptor;
|
|
171
220
|
|
|
172
221
|
/**
|
|
173
|
-
*
|
|
222
|
+
* Decorator factory for creating computed methods with options.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```ts
|
|
226
|
+
* class MyClass {
|
|
227
|
+
* items = atom('items', [1, 2, 3])
|
|
228
|
+
*
|
|
229
|
+
* @computed({ historyLength: 10 })
|
|
230
|
+
* sum() {
|
|
231
|
+
* return this.items.get().reduce((a, b) => a + b, 0)
|
|
232
|
+
* }
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*
|
|
236
|
+
* @param options - Configuration options for the computed signal
|
|
237
|
+
* @returns A decorator function that can be applied to methods
|
|
174
238
|
* @public
|
|
175
239
|
*/
|
|
176
240
|
export declare function computed<Value, Diff = unknown>(options?: ComputedOptions<Value, Diff>): ((target: any, key: string, descriptor: PropertyDescriptor) => PropertyDescriptor) & (<This>(compute: () => Value, context: ClassMethodDecoratorContext<This, () => Value>) => () => Value);
|
|
177
241
|
|
|
178
242
|
/**
|
|
179
|
-
*
|
|
243
|
+
* A function type that computes the difference between two values of a signal.
|
|
244
|
+
*
|
|
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.
|
|
248
|
+
*
|
|
249
|
+
* The function should analyze the previous and current values and return a
|
|
250
|
+
* diff object that represents the change. If the diff cannot be computed
|
|
251
|
+
* (e.g., the values are too different or incompatible), it should return
|
|
252
|
+
* the unique symbol RESET_VALUE to indicate that a full state reset is required.
|
|
253
|
+
*
|
|
254
|
+
* @param previousValue - The previous value of the signal
|
|
255
|
+
* @param currentValue - The current value of the signal
|
|
256
|
+
* @param lastComputedEpoch - The epoch when the previous value was set
|
|
257
|
+
* @param currentEpoch - The epoch when the current value was set
|
|
258
|
+
* @returns A diff object representing the change, or the unique symbol RESET_VALUE if no diff can be computed
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* import { atom, RESET_VALUE } from '@tldraw/state'
|
|
180
263
|
*
|
|
181
|
-
*
|
|
264
|
+
* // Simple numeric diff
|
|
265
|
+
* const numberDiff: ComputeDiff<number, number> = (prev, curr) => curr - prev
|
|
266
|
+
*
|
|
267
|
+
* // Array diff with reset fallback
|
|
268
|
+
* const arrayDiff: ComputeDiff<string[], { added: string[], removed: string[] }> = (prev, curr) => {
|
|
269
|
+
* if (prev.length > 1000 || curr.length > 1000) {
|
|
270
|
+
* return RESET_VALUE // Too complex, force reset
|
|
271
|
+
* }
|
|
272
|
+
* return {
|
|
273
|
+
* added: curr.filter(item => !prev.includes(item)),
|
|
274
|
+
* removed: prev.filter(item => !curr.includes(item))
|
|
275
|
+
* }
|
|
276
|
+
* }
|
|
277
|
+
*
|
|
278
|
+
* const count = atom('count', 0, { computeDiff: numberDiff })
|
|
279
|
+
* ```
|
|
182
280
|
*
|
|
183
281
|
* @public
|
|
184
282
|
*/
|
|
185
283
|
export declare type ComputeDiff<Value, Diff> = (previousValue: Value, currentValue: Value, lastComputedEpoch: number, currentEpoch: number) => Diff | RESET_VALUE;
|
|
186
284
|
|
|
187
285
|
/**
|
|
188
|
-
* Options for
|
|
286
|
+
* Options for configuring computed signals. Used when calling `computed` or using the `@computed` decorator.
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```ts
|
|
290
|
+
* const greeting = computed('greeting', () => `Hello ${name.get()}!`, {
|
|
291
|
+
* historyLength: 10,
|
|
292
|
+
* isEqual: (a, b) => a === b,
|
|
293
|
+
* computeDiff: (oldVal, newVal) => ({ type: 'change', from: oldVal, to: newVal })
|
|
294
|
+
* })
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
189
297
|
* @public
|
|
190
298
|
*/
|
|
191
299
|
export declare interface ComputedOptions<Value, Diff> {
|
|
@@ -347,11 +455,46 @@ export declare function getComputedInstance<Obj extends object, Prop extends key
|
|
|
347
455
|
|
|
348
456
|
/**
|
|
349
457
|
* Returns true if the given value is an {@link Atom}.
|
|
458
|
+
*
|
|
459
|
+
* @param value - The value to check
|
|
460
|
+
* @returns True if the value is an Atom, false otherwise
|
|
461
|
+
* @example
|
|
462
|
+
* ```ts
|
|
463
|
+
* const myAtom = atom('test', 42)
|
|
464
|
+
* const notAtom = 'hello'
|
|
465
|
+
*
|
|
466
|
+
* console.log(isAtom(myAtom)) // true
|
|
467
|
+
* console.log(isAtom(notAtom)) // false
|
|
468
|
+
* ```
|
|
350
469
|
* @public
|
|
351
470
|
*/
|
|
352
471
|
export declare function isAtom(value: unknown): value is Atom<unknown>;
|
|
353
472
|
|
|
354
473
|
/**
|
|
474
|
+
* Type guard function that determines whether a value is a signal (either an Atom or Computed).
|
|
475
|
+
*
|
|
476
|
+
* This utility function is helpful when working with mixed data types and you need to
|
|
477
|
+
* differentiate between regular values and reactive signal containers. It returns `true`
|
|
478
|
+
* if the provided value is either an atomic signal created with `atom()` or a computed
|
|
479
|
+
* signal created with `computed()`.
|
|
480
|
+
*
|
|
481
|
+
* @param value - The value to check, can be of any type
|
|
482
|
+
* @returns `true` if the value is a Signal (Atom or Computed), `false` otherwise
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```ts
|
|
486
|
+
* import { atom, computed, isSignal } from '@tldraw/state'
|
|
487
|
+
*
|
|
488
|
+
* const count = atom('count', 5)
|
|
489
|
+
* const doubled = computed('doubled', () => count.get() * 2)
|
|
490
|
+
* const regularValue = 'hello'
|
|
491
|
+
*
|
|
492
|
+
* console.log(isSignal(count)) // true
|
|
493
|
+
* console.log(isSignal(doubled)) // true
|
|
494
|
+
* console.log(isSignal(regularValue)) // false
|
|
495
|
+
* console.log(isSignal(null)) // false
|
|
496
|
+
* ```
|
|
497
|
+
*
|
|
355
498
|
* @public
|
|
356
499
|
*/
|
|
357
500
|
export declare function isSignal(value: any): value is Signal<any>;
|
|
@@ -377,6 +520,35 @@ export declare function isSignal(value: any): value is Signal<any>;
|
|
|
377
520
|
*/
|
|
378
521
|
export declare function isUninitialized(value: any): value is UNINITIALIZED;
|
|
379
522
|
|
|
523
|
+
/**
|
|
524
|
+
* Creates a new {@link Atom} that persists its value to localStorage.
|
|
525
|
+
*
|
|
526
|
+
* The atom is automatically synced with localStorage - changes to the atom are saved to localStorage,
|
|
527
|
+
* and the initial value is read from localStorage if it exists. Returns both the atom and a cleanup
|
|
528
|
+
* function that should be called to stop syncing when the atom is no longer needed. If you need to delete
|
|
529
|
+
* the atom, you should do it manually after all cleanup functions have been called.
|
|
530
|
+
*
|
|
531
|
+
* @example
|
|
532
|
+
* ```ts
|
|
533
|
+
* const [theme, cleanup] = localStorageAtom('theme', 'light')
|
|
534
|
+
*
|
|
535
|
+
* theme.get() // 'light' or value from localStorage if it exists
|
|
536
|
+
*
|
|
537
|
+
* theme.set('dark') // updates atom and saves to localStorage
|
|
538
|
+
*
|
|
539
|
+
* // When done:
|
|
540
|
+
* cleanup() // stops syncing to localStorage
|
|
541
|
+
* ```
|
|
542
|
+
*
|
|
543
|
+
* @param name - The localStorage key and atom name. This is used for both localStorage persistence
|
|
544
|
+
* and debugging/profiling purposes.
|
|
545
|
+
* @param initialValue - The initial value of the atom, used if no value exists in localStorage.
|
|
546
|
+
* @param options - Optional atom configuration. See {@link AtomOptions}.
|
|
547
|
+
* @returns A tuple containing the atom and a cleanup function to stop localStorage syncing.
|
|
548
|
+
* @public
|
|
549
|
+
*/
|
|
550
|
+
export declare function localStorageAtom<Value, Diff = unknown>(name: string, initialValue: Value, options?: AtomOptions<Value, Diff>): [Atom<Value, Diff>, () => void];
|
|
551
|
+
|
|
380
552
|
/**
|
|
381
553
|
* Starts a new effect scheduler, scheduling the effect immediately.
|
|
382
554
|
*
|
|
@@ -450,47 +622,125 @@ export declare interface Reactor<T = unknown> {
|
|
|
450
622
|
*/
|
|
451
623
|
export declare function reactor<Result>(name: string, fn: (lastReactedEpoch: number) => Result, options?: EffectSchedulerOptions): Reactor<Result>;
|
|
452
624
|
|
|
453
|
-
/**
|
|
625
|
+
/**
|
|
626
|
+
* A unique symbol used to indicate that a signal's value should be reset or that
|
|
627
|
+
* there is insufficient history to compute diffs between epochs.
|
|
628
|
+
*
|
|
629
|
+
* This value is returned by {@link Signal.getDiffSince} when the requested epoch
|
|
630
|
+
* is too far in the past and the diff sequence cannot be reconstructed.
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* ```ts
|
|
634
|
+
* import { atom, getGlobalEpoch, RESET_VALUE } from '@tldraw/state'
|
|
635
|
+
*
|
|
636
|
+
* const count = atom('count', 0, { historyLength: 3 })
|
|
637
|
+
* const oldEpoch = getGlobalEpoch()
|
|
638
|
+
*
|
|
639
|
+
* // Make many changes that exceed history length
|
|
640
|
+
* count.set(1)
|
|
641
|
+
* count.set(2)
|
|
642
|
+
* count.set(3)
|
|
643
|
+
* count.set(4)
|
|
644
|
+
*
|
|
645
|
+
* const diffs = count.getDiffSince(oldEpoch)
|
|
646
|
+
* if (diffs === RESET_VALUE) {
|
|
647
|
+
* console.log('Too many changes, need to reset state')
|
|
648
|
+
* }
|
|
649
|
+
* ```
|
|
650
|
+
*
|
|
651
|
+
* @public
|
|
652
|
+
*/
|
|
454
653
|
export declare const RESET_VALUE: unique symbol;
|
|
455
654
|
|
|
456
|
-
/**
|
|
655
|
+
/**
|
|
656
|
+
* Type representing the the unique symbol RESET_VALUE symbol, used in type annotations
|
|
657
|
+
* to indicate when a signal value should be reset or when diff computation
|
|
658
|
+
* cannot proceed due to insufficient history.
|
|
659
|
+
*
|
|
660
|
+
* @public
|
|
661
|
+
*/
|
|
457
662
|
export declare type RESET_VALUE = typeof RESET_VALUE;
|
|
458
663
|
|
|
459
664
|
/**
|
|
460
|
-
* A
|
|
665
|
+
* A reactive value container that can change over time and track diffs between sequential values.
|
|
666
|
+
*
|
|
667
|
+
* Signals are the foundation of the \@tldraw/state reactive system. They automatically manage
|
|
668
|
+
* dependencies and trigger updates when their values change. Any computed signal or effect
|
|
669
|
+
* that reads from this signal will be automatically recomputed when the signal's value changes.
|
|
461
670
|
*
|
|
462
671
|
* There are two types of signal:
|
|
672
|
+
* - **Atomic signals** - Created using `atom()`. These are mutable containers that can be
|
|
673
|
+
* directly updated using `set()` or `update()` methods.
|
|
674
|
+
* - **Computed signals** - Created using `computed()`. These derive their values from other
|
|
675
|
+
* signals and are automatically recomputed when dependencies change.
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* ```ts
|
|
679
|
+
* import { atom, computed } from '@tldraw/state'
|
|
463
680
|
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
681
|
+
* // Create an atomic signal
|
|
682
|
+
* const count = atom('count', 0)
|
|
683
|
+
*
|
|
684
|
+
* // Create a computed signal that derives from the atom
|
|
685
|
+
* const doubled = computed('doubled', () => count.get() * 2)
|
|
686
|
+
*
|
|
687
|
+
* console.log(doubled.get()) // 0
|
|
688
|
+
* count.set(5)
|
|
689
|
+
* console.log(doubled.get()) // 10
|
|
690
|
+
* ```
|
|
466
691
|
*
|
|
467
692
|
* @public
|
|
468
693
|
*/
|
|
469
694
|
export declare interface Signal<Value, Diff = unknown> {
|
|
470
695
|
/**
|
|
471
|
-
*
|
|
696
|
+
* A human-readable identifier for this signal, used primarily for debugging and performance profiling.
|
|
697
|
+
*
|
|
698
|
+
* The name is displayed in debug output from {@link whyAmIRunning} and other diagnostic tools.
|
|
699
|
+
* It does not need to be globally unique within your application.
|
|
472
700
|
*/
|
|
473
701
|
name: string;
|
|
474
702
|
/**
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
*
|
|
703
|
+
* Gets the current value of the signal and establishes a dependency relationship.
|
|
704
|
+
*
|
|
705
|
+
* When called from within a computed signal or effect, this signal will be automatically
|
|
706
|
+
* tracked as a dependency. If this signal's value changes, any dependent computations
|
|
707
|
+
* or effects will be marked for re-execution.
|
|
708
|
+
*
|
|
709
|
+
* @returns The current value stored in the signal
|
|
478
710
|
*/
|
|
479
711
|
get(): Value;
|
|
480
712
|
/**
|
|
481
|
-
* The epoch when this signal's value last changed.
|
|
482
|
-
*
|
|
713
|
+
* The global epoch number when this signal's value last changed.
|
|
714
|
+
*
|
|
715
|
+
* Note that this represents when the value actually changed, not when it was last computed.
|
|
716
|
+
* A computed signal may recalculate and produce the same value without changing its epoch.
|
|
717
|
+
* This is used internally for dependency tracking and history management.
|
|
483
718
|
*/
|
|
484
719
|
lastChangedEpoch: number;
|
|
485
720
|
/**
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
*
|
|
721
|
+
* Gets the sequence of diffs that occurred between a specific epoch and the current state.
|
|
722
|
+
*
|
|
723
|
+
* This method enables incremental synchronization by providing a list of changes that
|
|
724
|
+
* have occurred since a specific point in time. If the requested epoch is too far in
|
|
725
|
+
* the past or the signal doesn't have enough history, it returns the unique symbol RESET_VALUE
|
|
726
|
+
* to indicate that a full state reset is required.
|
|
727
|
+
*
|
|
728
|
+
* @param epoch - The epoch timestamp to get diffs since
|
|
729
|
+
* @returns An array of diff objects representing changes since the epoch, or the unique symbol RESET_VALUE if insufficient history is available
|
|
489
730
|
*/
|
|
490
731
|
getDiffSince(epoch: number): Diff[] | RESET_VALUE;
|
|
491
732
|
/**
|
|
492
|
-
*
|
|
493
|
-
*
|
|
733
|
+
* Gets the current value of the signal without establishing a dependency relationship.
|
|
734
|
+
*
|
|
735
|
+
* This method bypasses the automatic dependency tracking system, making it useful for
|
|
736
|
+
* performance-critical code paths where the overhead of dependency capture would be
|
|
737
|
+
* problematic. Use with caution as it breaks the reactive guarantees of the system.
|
|
738
|
+
*
|
|
739
|
+
* **Warning**: This method should only be used when you're certain that you don't need
|
|
740
|
+
* the calling context to react to changes in this signal.
|
|
741
|
+
*
|
|
742
|
+
* @param ignoreErrors - Whether to suppress errors during value retrieval (optional)
|
|
743
|
+
* @returns The current value without establishing dependencies
|
|
494
744
|
*/
|
|
495
745
|
__unsafe__getWithoutCapture(ignoreErrors?: boolean): Value;
|
|
496
746
|
/* Excluded from this release type: children */
|
|
@@ -498,22 +748,42 @@ export declare interface Signal<Value, Diff = unknown> {
|
|
|
498
748
|
|
|
499
749
|
/**
|
|
500
750
|
* Like {@link transaction}, but does not create a new transaction if there is already one in progress.
|
|
751
|
+
* This is the preferred way to batch state updates when you don't need the rollback functionality.
|
|
752
|
+
*
|
|
753
|
+
* @example
|
|
754
|
+
* ```ts
|
|
755
|
+
* const count = atom('count', 0)
|
|
756
|
+
* const doubled = atom('doubled', 0)
|
|
501
757
|
*
|
|
502
|
-
*
|
|
758
|
+
* react('update doubled', () => {
|
|
759
|
+
* console.log(`Count: ${count.get()}, Doubled: ${doubled.get()}`)
|
|
760
|
+
* })
|
|
761
|
+
*
|
|
762
|
+
* // This batches both updates into a single reaction
|
|
763
|
+
* transact(() => {
|
|
764
|
+
* count.set(5)
|
|
765
|
+
* doubled.set(count.get() * 2)
|
|
766
|
+
* })
|
|
767
|
+
* // Logs: "Count: 5, Doubled: 10"
|
|
768
|
+
* ```
|
|
769
|
+
*
|
|
770
|
+
* @param fn - The function to run in a transaction
|
|
771
|
+
* @returns The return value of the function
|
|
503
772
|
* @public
|
|
504
773
|
*/
|
|
505
774
|
export declare function transact<T>(fn: () => T): T;
|
|
506
775
|
|
|
507
776
|
/**
|
|
508
777
|
* Batches state updates, deferring side effects until after the transaction completes.
|
|
778
|
+
* Unlike {@link transact}, this function always creates a new transaction, allowing for nested transactions.
|
|
509
779
|
*
|
|
510
780
|
* @example
|
|
511
781
|
* ```ts
|
|
512
|
-
* const firstName = atom('John')
|
|
513
|
-
* const lastName = atom('Doe')
|
|
782
|
+
* const firstName = atom('firstName', 'John')
|
|
783
|
+
* const lastName = atom('lastName', 'Doe')
|
|
514
784
|
*
|
|
515
785
|
* react('greet', () => {
|
|
516
|
-
*
|
|
786
|
+
* console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)
|
|
517
787
|
* })
|
|
518
788
|
*
|
|
519
789
|
* // Logs "Hello, John Doe!"
|
|
@@ -530,11 +800,11 @@ export declare function transact<T>(fn: () => T): T;
|
|
|
530
800
|
*
|
|
531
801
|
* @example
|
|
532
802
|
* ```ts
|
|
533
|
-
* const firstName = atom('John')
|
|
534
|
-
* const lastName = atom('Doe')
|
|
803
|
+
* const firstName = atom('firstName', 'John')
|
|
804
|
+
* const lastName = atom('lastName', 'Doe')
|
|
535
805
|
*
|
|
536
806
|
* react('greet', () => {
|
|
537
|
-
*
|
|
807
|
+
* console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)
|
|
538
808
|
* })
|
|
539
809
|
*
|
|
540
810
|
* // Logs "Hello, John Doe!"
|
|
@@ -553,11 +823,11 @@ export declare function transact<T>(fn: () => T): T;
|
|
|
553
823
|
*
|
|
554
824
|
* @example
|
|
555
825
|
* ```ts
|
|
556
|
-
* const firstName = atom('John')
|
|
557
|
-
* const lastName = atom('Doe')
|
|
826
|
+
* const firstName = atom('firstName', 'John')
|
|
827
|
+
* const lastName = atom('lastName', 'Doe')
|
|
558
828
|
*
|
|
559
829
|
* react('greet', () => {
|
|
560
|
-
*
|
|
830
|
+
* console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)
|
|
561
831
|
* })
|
|
562
832
|
*
|
|
563
833
|
* // Logs "Hello, John Doe!"
|
|
@@ -574,19 +844,35 @@ export declare function transact<T>(fn: () => T): T;
|
|
|
574
844
|
* ```
|
|
575
845
|
*
|
|
576
846
|
* @param fn - The function to run in a transaction, called with a function to roll back the change.
|
|
847
|
+
* @returns The return value of the function
|
|
577
848
|
* @public
|
|
578
849
|
*/
|
|
579
850
|
export declare function transaction<T>(fn: (rollback: () => void) => T): T;
|
|
580
851
|
|
|
581
852
|
/**
|
|
853
|
+
* A special symbol used to indicate that a computed signal has not been initialized yet.
|
|
854
|
+
* This is passed as the `previousValue` parameter to a computed signal function on its first run.
|
|
855
|
+
*
|
|
856
|
+
* @example
|
|
857
|
+
* ```ts
|
|
858
|
+
* const count = atom('count', 0)
|
|
859
|
+
* const double = computed('double', (prevValue) => {
|
|
860
|
+
* if (isUninitialized(prevValue)) {
|
|
861
|
+
* console.log('First computation!')
|
|
862
|
+
* }
|
|
863
|
+
* return count.get() * 2
|
|
864
|
+
* })
|
|
865
|
+
* ```
|
|
866
|
+
*
|
|
582
867
|
* @public
|
|
583
868
|
*/
|
|
584
869
|
export declare const UNINITIALIZED: unique symbol;
|
|
585
870
|
|
|
586
871
|
/**
|
|
587
872
|
* The type of the first value passed to a computed signal function as the 'prevValue' parameter.
|
|
873
|
+
* This type represents the uninitialized state of a computed signal before its first calculation.
|
|
588
874
|
*
|
|
589
|
-
* @see {@link isUninitialized}
|
|
875
|
+
* @see {@link isUninitialized}
|
|
590
876
|
* @public
|
|
591
877
|
*/
|
|
592
878
|
export declare type UNINITIALIZED = typeof UNINITIALIZED;
|
|
@@ -638,7 +924,25 @@ export declare function unsafe__withoutCapture<T>(fn: () => T): T;
|
|
|
638
924
|
*/
|
|
639
925
|
export declare function whyAmIRunning(): void;
|
|
640
926
|
|
|
641
|
-
/**
|
|
927
|
+
/**
|
|
928
|
+
* A singleton class used to wrap computed signal values along with their diffs.
|
|
929
|
+
* This class is used internally by the {@link withDiff} function to provide both
|
|
930
|
+
* the computed value and its diff to the signal system.
|
|
931
|
+
*
|
|
932
|
+
* @example
|
|
933
|
+
* ```ts
|
|
934
|
+
* const count = atom('count', 0)
|
|
935
|
+
* const double = computed('double', (prevValue) => {
|
|
936
|
+
* const nextValue = count.get() * 2
|
|
937
|
+
* if (isUninitialized(prevValue)) {
|
|
938
|
+
* return nextValue
|
|
939
|
+
* }
|
|
940
|
+
* return withDiff(nextValue, nextValue - prevValue)
|
|
941
|
+
* })
|
|
942
|
+
* ```
|
|
943
|
+
*
|
|
944
|
+
* @public
|
|
945
|
+
*/
|
|
642
946
|
export declare const WithDiff: {
|
|
643
947
|
new <Value, Diff>(value: Value, diff: Diff): {
|
|
644
948
|
diff: Diff;
|
|
@@ -646,9 +950,20 @@ export declare const WithDiff: {
|
|
|
646
950
|
};
|
|
647
951
|
};
|
|
648
952
|
|
|
649
|
-
/**
|
|
953
|
+
/**
|
|
954
|
+
* Interface representing a value wrapped with its corresponding diff.
|
|
955
|
+
* Used in incremental computation to provide both the new value and the diff from the previous value.
|
|
956
|
+
*
|
|
957
|
+
* @public
|
|
958
|
+
*/
|
|
650
959
|
export declare interface WithDiff<Value, Diff> {
|
|
960
|
+
/**
|
|
961
|
+
* The computed value.
|
|
962
|
+
*/
|
|
651
963
|
value: Value;
|
|
964
|
+
/**
|
|
965
|
+
* The diff between the previous and current value.
|
|
966
|
+
*/
|
|
652
967
|
diff: Diff;
|
|
653
968
|
}
|
|
654
969
|
|
package/dist-cjs/index.js
CHANGED
|
@@ -30,6 +30,7 @@ __export(index_exports, {
|
|
|
30
30
|
isAtom: () => import_Atom.isAtom,
|
|
31
31
|
isSignal: () => import_isSignal.isSignal,
|
|
32
32
|
isUninitialized: () => import_Computed.isUninitialized,
|
|
33
|
+
localStorageAtom: () => import_localStorageAtom.localStorageAtom,
|
|
33
34
|
react: () => import_EffectScheduler.react,
|
|
34
35
|
reactor: () => import_EffectScheduler.reactor,
|
|
35
36
|
transact: () => import_transactions.transact,
|
|
@@ -48,6 +49,7 @@ var import_Computed = require("./lib/Computed");
|
|
|
48
49
|
var import_EffectScheduler = require("./lib/EffectScheduler");
|
|
49
50
|
var import_helpers2 = require("./lib/helpers");
|
|
50
51
|
var import_isSignal = require("./lib/isSignal");
|
|
52
|
+
var import_localStorageAtom = require("./lib/localStorageAtom");
|
|
51
53
|
var import_transactions = require("./lib/transactions");
|
|
52
54
|
var import_types = require("./lib/types");
|
|
53
55
|
const currentApiVersion = 1;
|
|
@@ -59,7 +61,7 @@ if (actualApiVersion !== currentApiVersion) {
|
|
|
59
61
|
}
|
|
60
62
|
(0, import_utils.registerTldrawLibraryVersion)(
|
|
61
63
|
"@tldraw/state",
|
|
62
|
-
"4.0.
|
|
64
|
+
"4.1.0-canary.0259516ffb8c",
|
|
63
65
|
"cjs"
|
|
64
66
|
);
|
|
65
67
|
//# sourceMappingURL=index.js.map
|
package/dist-cjs/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerTldrawLibraryVersion } from '@tldraw/utils'\nimport { singleton } from './lib/helpers'\n\nexport { ArraySet } from './lib/ArraySet'\nexport { atom, isAtom } from './lib/Atom'\nexport type { Atom, AtomOptions } from './lib/Atom'\nexport { unsafe__withoutCapture, whyAmIRunning } from './lib/capture'\nexport {\n\tcomputed,\n\tgetComputedInstance,\n\tisUninitialized,\n\tUNINITIALIZED,\n\twithDiff,\n} from './lib/Computed'\nexport type { Computed, ComputedOptions, WithDiff } from './lib/Computed'\nexport { EffectScheduler, react, reactor } from './lib/EffectScheduler'\nexport type { EffectSchedulerOptions, Reactor } from './lib/EffectScheduler'\nexport { EMPTY_ARRAY } from './lib/helpers'\nexport { isSignal } from './lib/isSignal'\nexport { deferAsyncEffects, transact, transaction } from './lib/transactions'\nexport { RESET_VALUE } from './lib/types'\nexport type { Child, ComputeDiff, Signal } from './lib/types'\n\n// This should be incremented any time an API change is made. i.e. for additions or removals.\n// Bugfixes need not increment this.\nconst currentApiVersion = 1\n\nconst actualApiVersion = singleton('apiVersion', () => currentApiVersion)\n\nif (actualApiVersion !== currentApiVersion) {\n\tthrow new Error(\n\t\t`You have multiple incompatible versions of @tldraw/state in your app. Please deduplicate the package.`\n\t)\n}\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAC7C,qBAA0B;AAE1B,sBAAyB;AACzB,kBAA6B;AAE7B,qBAAsD;AACtD,sBAMO;AAEP,6BAAgD;AAEhD,IAAAA,kBAA4B;AAC5B,sBAAyB;AACzB,0BAAyD;AACzD,mBAA4B;AAK5B,MAAM,oBAAoB;AAE1B,MAAM,uBAAmB,0BAAU,cAAc,MAAM,iBAAiB;AAExE,IAAI,qBAAqB,mBAAmB;AAC3C,QAAM,IAAI;AAAA,IACT;AAAA,EACD;AACD;AAAA,IAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
|
|
4
|
+
"sourcesContent": ["import { registerTldrawLibraryVersion } from '@tldraw/utils'\nimport { singleton } from './lib/helpers'\n\nexport { ArraySet } from './lib/ArraySet'\nexport { atom, isAtom } from './lib/Atom'\nexport type { Atom, AtomOptions } from './lib/Atom'\nexport { unsafe__withoutCapture, whyAmIRunning } from './lib/capture'\nexport {\n\tcomputed,\n\tgetComputedInstance,\n\tisUninitialized,\n\tUNINITIALIZED,\n\twithDiff,\n} from './lib/Computed'\nexport type { Computed, ComputedOptions, WithDiff } from './lib/Computed'\nexport { EffectScheduler, react, reactor } from './lib/EffectScheduler'\nexport type { EffectSchedulerOptions, Reactor } from './lib/EffectScheduler'\nexport { EMPTY_ARRAY } from './lib/helpers'\nexport { isSignal } from './lib/isSignal'\nexport { localStorageAtom } from './lib/localStorageAtom'\nexport { deferAsyncEffects, transact, transaction } from './lib/transactions'\nexport { RESET_VALUE } from './lib/types'\nexport type { Child, ComputeDiff, Signal } from './lib/types'\n\n// This should be incremented any time an API change is made. i.e. for additions or removals.\n// Bugfixes need not increment this.\nconst currentApiVersion = 1\n\nconst actualApiVersion = singleton('apiVersion', () => currentApiVersion)\n\nif (actualApiVersion !== currentApiVersion) {\n\tthrow new Error(\n\t\t`You have multiple incompatible versions of @tldraw/state in your app. Please deduplicate the package.`\n\t)\n}\n\nregisterTldrawLibraryVersion(\n\t(globalThis as any).TLDRAW_LIBRARY_NAME,\n\t(globalThis as any).TLDRAW_LIBRARY_VERSION,\n\t(globalThis as any).TLDRAW_LIBRARY_MODULES\n)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA6C;AAC7C,qBAA0B;AAE1B,sBAAyB;AACzB,kBAA6B;AAE7B,qBAAsD;AACtD,sBAMO;AAEP,6BAAgD;AAEhD,IAAAA,kBAA4B;AAC5B,sBAAyB;AACzB,8BAAiC;AACjC,0BAAyD;AACzD,mBAA4B;AAK5B,MAAM,oBAAoB;AAE1B,MAAM,uBAAmB,0BAAU,cAAc,MAAM,iBAAiB;AAExE,IAAI,qBAAqB,mBAAmB;AAC3C,QAAM,IAAI;AAAA,IACT;AAAA,EACD;AACD;AAAA,IAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": ["import_helpers"]
|
|
7
7
|
}
|