@tldraw/state 4.0.3 → 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.
Files changed (56) hide show
  1. package/dist-cjs/index.d.ts +358 -43
  2. package/dist-cjs/index.js +3 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/ArraySet.js +90 -6
  5. package/dist-cjs/lib/ArraySet.js.map +2 -2
  6. package/dist-cjs/lib/Atom.js +70 -0
  7. package/dist-cjs/lib/Atom.js.map +2 -2
  8. package/dist-cjs/lib/Computed.js +1 -1
  9. package/dist-cjs/lib/Computed.js.map +2 -2
  10. package/dist-cjs/lib/HistoryBuffer.js +57 -9
  11. package/dist-cjs/lib/HistoryBuffer.js.map +2 -2
  12. package/dist-cjs/lib/capture.js.map +2 -2
  13. package/dist-cjs/lib/constants.js.map +2 -2
  14. package/dist-cjs/lib/helpers.js.map +2 -2
  15. package/dist-cjs/lib/isSignal.js.map +2 -2
  16. package/dist-cjs/lib/localStorageAtom.js +60 -0
  17. package/dist-cjs/lib/localStorageAtom.js.map +7 -0
  18. package/dist-cjs/lib/transactions.js.map +2 -2
  19. package/dist-cjs/lib/types.js.map +2 -2
  20. package/dist-cjs/lib/warnings.js.map +2 -2
  21. package/dist-esm/index.d.mts +358 -43
  22. package/dist-esm/index.mjs +3 -1
  23. package/dist-esm/index.mjs.map +2 -2
  24. package/dist-esm/lib/ArraySet.mjs +90 -6
  25. package/dist-esm/lib/ArraySet.mjs.map +2 -2
  26. package/dist-esm/lib/Atom.mjs +70 -0
  27. package/dist-esm/lib/Atom.mjs.map +2 -2
  28. package/dist-esm/lib/Computed.mjs +1 -1
  29. package/dist-esm/lib/Computed.mjs.map +2 -2
  30. package/dist-esm/lib/HistoryBuffer.mjs +57 -9
  31. package/dist-esm/lib/HistoryBuffer.mjs.map +2 -2
  32. package/dist-esm/lib/capture.mjs.map +2 -2
  33. package/dist-esm/lib/constants.mjs.map +2 -2
  34. package/dist-esm/lib/helpers.mjs.map +2 -2
  35. package/dist-esm/lib/isSignal.mjs.map +2 -2
  36. package/dist-esm/lib/localStorageAtom.mjs +40 -0
  37. package/dist-esm/lib/localStorageAtom.mjs.map +7 -0
  38. package/dist-esm/lib/transactions.mjs.map +2 -2
  39. package/dist-esm/lib/types.mjs.map +2 -2
  40. package/dist-esm/lib/warnings.mjs.map +2 -2
  41. package/package.json +2 -2
  42. package/src/index.ts +1 -0
  43. package/src/lib/ArraySet.ts +101 -8
  44. package/src/lib/Atom.ts +92 -0
  45. package/src/lib/Computed.ts +169 -19
  46. package/src/lib/HistoryBuffer.ts +76 -10
  47. package/src/lib/__tests__/helpers.test.ts +168 -0
  48. package/src/lib/__tests__/localStorageAtom.test.ts +183 -0
  49. package/src/lib/capture.ts +56 -1
  50. package/src/lib/constants.ts +25 -1
  51. package/src/lib/helpers.ts +137 -13
  52. package/src/lib/isSignal.ts +24 -0
  53. package/src/lib/localStorageAtom.ts +87 -0
  54. package/src/lib/transactions.ts +79 -10
  55. package/src/lib/types.ts +173 -19
  56. package/src/lib/warnings.ts +36 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/capture.ts"],
4
- "sourcesContent": ["import { isComputed } from './Computed'\nimport { attach, detach, singleton } from './helpers'\nimport type { Child, Signal } from './types'\n\nclass CaptureStackFrame {\n\toffset = 0\n\n\tmaybeRemoved?: Signal<any>[]\n\n\tconstructor(\n\t\tpublic readonly below: CaptureStackFrame | null,\n\t\tpublic readonly child: Child\n\t) {}\n}\n\nconst inst = singleton('capture', () => ({ stack: null as null | CaptureStackFrame }))\n\n/**\n * Executes the given function without capturing any parents in the current capture context.\n *\n * This is mainly useful if you want to run an effect only when certain signals change while also\n * dereferencing other signals which should not cause the effect to rerun on their own.\n *\n * @example\n * ```ts\n * const name = atom('name', 'Sam')\n * const time = atom('time', () => new Date().getTime())\n *\n * setInterval(() => {\n * time.set(new Date().getTime())\n * })\n *\n * react('log name changes', () => {\n * \t print(name.get(), 'was changed at', unsafe__withoutCapture(() => time.get()))\n * })\n *\n * ```\n *\n * @public\n */\nexport function unsafe__withoutCapture<T>(fn: () => T): T {\n\tconst oldStack = inst.stack\n\tinst.stack = null\n\ttry {\n\t\treturn fn()\n\t} finally {\n\t\tinst.stack = oldStack\n\t}\n}\n\nexport function startCapturingParents(child: Child) {\n\tinst.stack = new CaptureStackFrame(inst.stack, child)\n\tif (child.__debug_ancestor_epochs__) {\n\t\tconst previousAncestorEpochs = child.__debug_ancestor_epochs__\n\t\tchild.__debug_ancestor_epochs__ = null\n\t\tfor (const p of child.parents) {\n\t\t\tp.__unsafe__getWithoutCapture(true)\n\t\t}\n\t\tlogChangedAncestors(child, previousAncestorEpochs)\n\t}\n\tchild.parentSet.clear()\n}\n\nexport function stopCapturingParents() {\n\tconst frame = inst.stack!\n\tinst.stack = frame.below\n\n\tif (frame.offset < frame.child.parents.length) {\n\t\tfor (let i = frame.offset; i < frame.child.parents.length; i++) {\n\t\t\tconst maybeRemovedParent = frame.child.parents[i]\n\t\t\tif (!frame.child.parentSet.has(maybeRemovedParent)) {\n\t\t\t\tdetach(maybeRemovedParent, frame.child)\n\t\t\t}\n\t\t}\n\n\t\tframe.child.parents.length = frame.offset\n\t\tframe.child.parentEpochs.length = frame.offset\n\t}\n\n\tif (frame.maybeRemoved) {\n\t\tfor (let i = 0; i < frame.maybeRemoved.length; i++) {\n\t\t\tconst maybeRemovedParent = frame.maybeRemoved[i]\n\t\t\tif (!frame.child.parentSet.has(maybeRemovedParent)) {\n\t\t\t\tdetach(maybeRemovedParent, frame.child)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (frame.child.__debug_ancestor_epochs__) {\n\t\tcaptureAncestorEpochs(frame.child, frame.child.__debug_ancestor_epochs__)\n\t}\n}\n\n// this must be called after the parent is up to date\nexport function maybeCaptureParent(p: Signal<any, any>) {\n\tif (inst.stack) {\n\t\tconst wasCapturedAlready = inst.stack.child.parentSet.has(p)\n\t\t// if the child didn't deref this parent last time it executed, then idx will be -1\n\t\t// if the child did deref this parent last time but in a different order relative to other parents, then idx will be greater than stack.offset\n\t\t// if the child did deref this parent last time in the same order, then idx will be the same as stack.offset\n\t\t// if the child did deref this parent already during this capture session then 0 <= idx < stack.offset\n\n\t\tif (wasCapturedAlready) {\n\t\t\treturn\n\t\t}\n\n\t\tinst.stack.child.parentSet.add(p)\n\t\tif (inst.stack.child.isActivelyListening) {\n\t\t\tattach(p, inst.stack.child)\n\t\t}\n\n\t\tif (inst.stack.offset < inst.stack.child.parents.length) {\n\t\t\tconst maybeRemovedParent = inst.stack.child.parents[inst.stack.offset]\n\t\t\tif (maybeRemovedParent !== p) {\n\t\t\t\tif (!inst.stack.maybeRemoved) {\n\t\t\t\t\tinst.stack.maybeRemoved = [maybeRemovedParent]\n\t\t\t\t} else {\n\t\t\t\t\tinst.stack.maybeRemoved.push(maybeRemovedParent)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tinst.stack.child.parents[inst.stack.offset] = p\n\t\tinst.stack.child.parentEpochs[inst.stack.offset] = p.lastChangedEpoch\n\t\tinst.stack.offset++\n\t}\n}\n\n/**\n * A debugging tool that tells you why a computed signal or effect is running.\n * Call in the body of a computed signal or effect function.\n *\n * @example\n * ```ts\n * const name = atom('name', 'Bob')\n * react('greeting', () => {\n * \twhyAmIRunning()\n *\tprint('Hello', name.get())\n * })\n *\n * name.set('Alice')\n *\n * // 'greeting' is running because:\n * // 'name' changed => 'Alice'\n * ```\n *\n * @public\n */\nexport function whyAmIRunning() {\n\tconst child = inst.stack?.child\n\tif (!child) {\n\t\tthrow new Error('whyAmIRunning() called outside of a reactive context')\n\t}\n\tchild.__debug_ancestor_epochs__ = new Map()\n}\n\nfunction captureAncestorEpochs(child: Child, ancestorEpochs: Map<Signal<any>, number>) {\n\tfor (let i = 0; i < child.parents.length; i++) {\n\t\tconst parent = child.parents[i]\n\t\tconst epoch = child.parentEpochs[i]\n\t\tancestorEpochs.set(parent, epoch)\n\t\tif (isComputed(parent)) {\n\t\t\tcaptureAncestorEpochs(parent as any, ancestorEpochs)\n\t\t}\n\t}\n\treturn ancestorEpochs\n}\n\ntype ChangeTree = { [signalName: string]: ChangeTree } | null\nfunction collectChangedAncestors(\n\tchild: Child,\n\tancestorEpochs: Map<Signal<any>, number>\n): NonNullable<ChangeTree> {\n\tconst changeTree: ChangeTree = {}\n\tfor (let i = 0; i < child.parents.length; i++) {\n\t\tconst parent = child.parents[i]\n\t\tif (!ancestorEpochs.has(parent)) {\n\t\t\tcontinue\n\t\t}\n\t\tconst prevEpoch = ancestorEpochs.get(parent)\n\t\tconst currentEpoch = parent.lastChangedEpoch\n\t\tif (currentEpoch !== prevEpoch) {\n\t\t\tif (isComputed(parent)) {\n\t\t\t\tchangeTree[parent.name] = collectChangedAncestors(parent as any, ancestorEpochs)\n\t\t\t} else {\n\t\t\t\tchangeTree[parent.name] = null\n\t\t\t}\n\t\t}\n\t}\n\treturn changeTree\n}\n\nfunction logChangedAncestors(child: Child, ancestorEpochs: Map<Signal<any>, number>) {\n\tconst changeTree = collectChangedAncestors(child, ancestorEpochs)\n\tif (Object.keys(changeTree).length === 0) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(`Effect(${child.name}) was executed manually.`)\n\t\treturn\n\t}\n\n\tlet str = isComputed(child)\n\t\t? `Computed(${child.name}) is recomputing because:`\n\t\t: `Effect(${child.name}) is executing because:`\n\n\tfunction logParent(tree: NonNullable<ChangeTree>, indent: number) {\n\t\tconst indentStr = '\\n' + ' '.repeat(indent) + '\u21B3 '\n\t\tfor (const [name, val] of Object.entries(tree)) {\n\t\t\tif (val) {\n\t\t\t\tstr += `${indentStr}Computed(${name}) changed`\n\t\t\t\tlogParent(val, indent + 2)\n\t\t\t} else {\n\t\t\t\tstr += `${indentStr}Atom(${name}) changed`\n\t\t\t}\n\t\t}\n\t}\n\n\tlogParent(changeTree, 1)\n\n\t// eslint-disable-next-line no-console\n\tconsole.log(str)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { isComputed } from './Computed'\nimport { attach, detach, singleton } from './helpers'\nimport type { Child, Signal } from './types'\n\nclass CaptureStackFrame {\n\toffset = 0\n\n\tmaybeRemoved?: Signal<any>[]\n\n\tconstructor(\n\t\tpublic readonly below: CaptureStackFrame | null,\n\t\tpublic readonly child: Child\n\t) {}\n}\n\nconst inst = singleton('capture', () => ({ stack: null as null | CaptureStackFrame }))\n\n/**\n * Executes the given function without capturing any parents in the current capture context.\n *\n * This is mainly useful if you want to run an effect only when certain signals change while also\n * dereferencing other signals which should not cause the effect to rerun on their own.\n *\n * @example\n * ```ts\n * const name = atom('name', 'Sam')\n * const time = atom('time', () => new Date().getTime())\n *\n * setInterval(() => {\n * time.set(new Date().getTime())\n * })\n *\n * react('log name changes', () => {\n * \t print(name.get(), 'was changed at', unsafe__withoutCapture(() => time.get()))\n * })\n *\n * ```\n *\n * @public\n */\nexport function unsafe__withoutCapture<T>(fn: () => T): T {\n\tconst oldStack = inst.stack\n\tinst.stack = null\n\ttry {\n\t\treturn fn()\n\t} finally {\n\t\tinst.stack = oldStack\n\t}\n}\n\n/**\n * Begins capturing parent signal dependencies for the given child signal.\n *\n * This function initiates a capture session where any signal accessed via `.get()`\n * will be automatically registered as a dependency of the child signal. It sets up\n * the capture stack frame and clears the existing parent set to prepare for fresh\n * dependency tracking.\n *\n * @param child - The child signal (computed or effect) that will capture dependencies\n *\n * @example\n * ```ts\n * const effect = createEffect('myEffect', () => { /* ... *\\/ })\n * startCapturingParents(effect)\n * // Now any signal.get() calls will be captured as dependencies\n * ```\n *\n * @internal\n */\nexport function startCapturingParents(child: Child) {\n\tinst.stack = new CaptureStackFrame(inst.stack, child)\n\tif (child.__debug_ancestor_epochs__) {\n\t\tconst previousAncestorEpochs = child.__debug_ancestor_epochs__\n\t\tchild.__debug_ancestor_epochs__ = null\n\t\tfor (const p of child.parents) {\n\t\t\tp.__unsafe__getWithoutCapture(true)\n\t\t}\n\t\tlogChangedAncestors(child, previousAncestorEpochs)\n\t}\n\tchild.parentSet.clear()\n}\n\n/**\n * Completes the parent dependency capture session and finalizes the dependency graph.\n *\n * This function cleans up the capture session by removing dependencies that are no\n * longer needed, detaching signals that should no longer be parents, and updating\n * the dependency arrays to reflect the current set of captured parents. It must be\n * called after `startCapturingParents` to complete the capture cycle.\n *\n * @example\n * ```ts\n * startCapturingParents(effect)\n * // ... signal.get() calls happen here ...\n * stopCapturingParents() // Finalizes the dependency graph\n * ```\n *\n * @internal\n */\nexport function stopCapturingParents() {\n\tconst frame = inst.stack!\n\tinst.stack = frame.below\n\n\tif (frame.offset < frame.child.parents.length) {\n\t\tfor (let i = frame.offset; i < frame.child.parents.length; i++) {\n\t\t\tconst maybeRemovedParent = frame.child.parents[i]\n\t\t\tif (!frame.child.parentSet.has(maybeRemovedParent)) {\n\t\t\t\tdetach(maybeRemovedParent, frame.child)\n\t\t\t}\n\t\t}\n\n\t\tframe.child.parents.length = frame.offset\n\t\tframe.child.parentEpochs.length = frame.offset\n\t}\n\n\tif (frame.maybeRemoved) {\n\t\tfor (let i = 0; i < frame.maybeRemoved.length; i++) {\n\t\t\tconst maybeRemovedParent = frame.maybeRemoved[i]\n\t\t\tif (!frame.child.parentSet.has(maybeRemovedParent)) {\n\t\t\t\tdetach(maybeRemovedParent, frame.child)\n\t\t\t}\n\t\t}\n\t}\n\n\tif (frame.child.__debug_ancestor_epochs__) {\n\t\tcaptureAncestorEpochs(frame.child, frame.child.__debug_ancestor_epochs__)\n\t}\n}\n\n/**\n * Conditionally captures a signal as a parent dependency during an active capture session.\n *\n * This function is called whenever a signal's `.get()` method is invoked during a\n * capture session. It checks if the signal should be added as a dependency and manages\n * the parent-child relationship in the reactive graph. The function handles deduplication,\n * attachment/detachment, and tracks changes in dependency order.\n *\n * Note: This must be called after the parent signal is up to date.\n *\n * @param p - The signal that might be captured as a parent dependency\n *\n * @example\n * ```ts\n * // This is called internally when you do:\n * const value = someAtom.get() // maybeCaptureParent(someAtom) is called\n * ```\n *\n * @internal\n */\nexport function maybeCaptureParent(p: Signal<any, any>) {\n\tif (inst.stack) {\n\t\tconst wasCapturedAlready = inst.stack.child.parentSet.has(p)\n\t\t// if the child didn't deref this parent last time it executed, then idx will be -1\n\t\t// if the child did deref this parent last time but in a different order relative to other parents, then idx will be greater than stack.offset\n\t\t// if the child did deref this parent last time in the same order, then idx will be the same as stack.offset\n\t\t// if the child did deref this parent already during this capture session then 0 <= idx < stack.offset\n\n\t\tif (wasCapturedAlready) {\n\t\t\treturn\n\t\t}\n\n\t\tinst.stack.child.parentSet.add(p)\n\t\tif (inst.stack.child.isActivelyListening) {\n\t\t\tattach(p, inst.stack.child)\n\t\t}\n\n\t\tif (inst.stack.offset < inst.stack.child.parents.length) {\n\t\t\tconst maybeRemovedParent = inst.stack.child.parents[inst.stack.offset]\n\t\t\tif (maybeRemovedParent !== p) {\n\t\t\t\tif (!inst.stack.maybeRemoved) {\n\t\t\t\t\tinst.stack.maybeRemoved = [maybeRemovedParent]\n\t\t\t\t} else {\n\t\t\t\t\tinst.stack.maybeRemoved.push(maybeRemovedParent)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tinst.stack.child.parents[inst.stack.offset] = p\n\t\tinst.stack.child.parentEpochs[inst.stack.offset] = p.lastChangedEpoch\n\t\tinst.stack.offset++\n\t}\n}\n\n/**\n * A debugging tool that tells you why a computed signal or effect is running.\n * Call in the body of a computed signal or effect function.\n *\n * @example\n * ```ts\n * const name = atom('name', 'Bob')\n * react('greeting', () => {\n * \twhyAmIRunning()\n *\tprint('Hello', name.get())\n * })\n *\n * name.set('Alice')\n *\n * // 'greeting' is running because:\n * // 'name' changed => 'Alice'\n * ```\n *\n * @public\n */\nexport function whyAmIRunning() {\n\tconst child = inst.stack?.child\n\tif (!child) {\n\t\tthrow new Error('whyAmIRunning() called outside of a reactive context')\n\t}\n\tchild.__debug_ancestor_epochs__ = new Map()\n}\n\nfunction captureAncestorEpochs(child: Child, ancestorEpochs: Map<Signal<any>, number>) {\n\tfor (let i = 0; i < child.parents.length; i++) {\n\t\tconst parent = child.parents[i]\n\t\tconst epoch = child.parentEpochs[i]\n\t\tancestorEpochs.set(parent, epoch)\n\t\tif (isComputed(parent)) {\n\t\t\tcaptureAncestorEpochs(parent as any, ancestorEpochs)\n\t\t}\n\t}\n\treturn ancestorEpochs\n}\n\ntype ChangeTree = { [signalName: string]: ChangeTree } | null\nfunction collectChangedAncestors(\n\tchild: Child,\n\tancestorEpochs: Map<Signal<any>, number>\n): NonNullable<ChangeTree> {\n\tconst changeTree: ChangeTree = {}\n\tfor (let i = 0; i < child.parents.length; i++) {\n\t\tconst parent = child.parents[i]\n\t\tif (!ancestorEpochs.has(parent)) {\n\t\t\tcontinue\n\t\t}\n\t\tconst prevEpoch = ancestorEpochs.get(parent)\n\t\tconst currentEpoch = parent.lastChangedEpoch\n\t\tif (currentEpoch !== prevEpoch) {\n\t\t\tif (isComputed(parent)) {\n\t\t\t\tchangeTree[parent.name] = collectChangedAncestors(parent as any, ancestorEpochs)\n\t\t\t} else {\n\t\t\t\tchangeTree[parent.name] = null\n\t\t\t}\n\t\t}\n\t}\n\treturn changeTree\n}\n\nfunction logChangedAncestors(child: Child, ancestorEpochs: Map<Signal<any>, number>) {\n\tconst changeTree = collectChangedAncestors(child, ancestorEpochs)\n\tif (Object.keys(changeTree).length === 0) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(`Effect(${child.name}) was executed manually.`)\n\t\treturn\n\t}\n\n\tlet str = isComputed(child)\n\t\t? `Computed(${child.name}) is recomputing because:`\n\t\t: `Effect(${child.name}) is executing because:`\n\n\tfunction logParent(tree: NonNullable<ChangeTree>, indent: number) {\n\t\tconst indentStr = '\\n' + ' '.repeat(indent) + '\u21B3 '\n\t\tfor (const [name, val] of Object.entries(tree)) {\n\t\t\tif (val) {\n\t\t\t\tstr += `${indentStr}Computed(${name}) changed`\n\t\t\t\tlogParent(val, indent + 2)\n\t\t\t} else {\n\t\t\t\tstr += `${indentStr}Atom(${name}) changed`\n\t\t\t}\n\t\t}\n\t}\n\n\tlogParent(changeTree, 1)\n\n\t// eslint-disable-next-line no-console\n\tconsole.log(str)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/constants.ts"],
4
- "sourcesContent": ["// Derivations start on GLOBAL_START_EPOCH so they are dirty before having been computed\nexport const GLOBAL_START_EPOCH = -1\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACO,MAAM,qBAAqB;",
4
+ "sourcesContent": ["/**\n * The initial epoch value used to mark derivations (computed signals and effects) as dirty before their first computation.\n *\n * This constant ensures that all computed signals and effects start in a \"dirty\" state, guaranteeing they will\n * be computed/executed at least once when first accessed or started. The value -1 is used because:\n * - Global epoch starts at 0 (GLOBAL_START_EPOCH + 1)\n * - Any derived signal initialized with GLOBAL_START_EPOCH (-1) will be considered dirty when compared to any positive epoch\n * - This forces initial computation/execution without requiring special initialization logic\n *\n * Used by:\n * - Computed signals to track when they were last changed\n * - Effect schedulers to track when they were last executed\n * - Transaction system for initial global and reaction epoch values\n *\n * @example\n * ```ts\n * // In Computed class constructor\n * lastChangedEpoch = GLOBAL_START_EPOCH // -1, marking as dirty\n *\n * // When global epoch is 5, this computed will be dirty since -1 < 5\n * const needsComputation = this.lastChangedEpoch < globalEpoch\n * ```\n *\n * @public\n */\nexport const GLOBAL_START_EPOCH = -1\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBO,MAAM,qBAAqB;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/helpers.ts"],
4
- "sourcesContent": ["import { Child, Signal } from './types'\n\n/**\n * Get whether the given value is a child.\n *\n * @param x The value to check.\n * @returns True if the value is a child, false otherwise.\n */\nfunction isChild(x: any): x is Child {\n\treturn x && typeof x === 'object' && 'parents' in x\n}\n\n/**\n * Get whether a child's parents have changed.\n *\n * @param child The child to check.\n * @returns True if the child's parents have changed, false otherwise.\n */\nexport function haveParentsChanged(child: Child): boolean {\n\tfor (let i = 0, n = child.parents.length; i < n; i++) {\n\t\t// Get the parent's value without capturing it.\n\t\tchild.parents[i].__unsafe__getWithoutCapture(true)\n\n\t\t// If the parent's epoch does not match the child's view of the parent's epoch, then the parent has changed.\n\t\tif (child.parents[i].lastChangedEpoch !== child.parentEpochs[i]) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n/**\n * Detach a child from a parent.\n *\n * @param parent The parent to detach from.\n * @param child The child to detach.\n */\nexport function detach(parent: Signal<any>, child: Child) {\n\t// If the child is not attached to the parent, do nothing.\n\tif (!parent.children.remove(child)) {\n\t\treturn\n\t}\n\n\t// If the parent has no more children, then detach the parent from its parents.\n\tif (parent.children.isEmpty && isChild(parent)) {\n\t\tfor (let i = 0, n = parent.parents.length; i < n; i++) {\n\t\t\tdetach(parent.parents[i], parent)\n\t\t}\n\t}\n}\n\n/**\n * Attach a child to a parent.\n *\n * @param parent The parent to attach to.\n * @param child The child to attach.\n */\nexport function attach(parent: Signal<any>, child: Child) {\n\t// If the child is already attached to the parent, do nothing.\n\tif (!parent.children.add(child)) {\n\t\treturn\n\t}\n\n\t// If the parent itself is a child, add the parent to the parent's parents.\n\tif (isChild(parent)) {\n\t\tfor (let i = 0, n = parent.parents.length; i < n; i++) {\n\t\t\tattach(parent.parents[i], parent)\n\t\t}\n\t}\n}\n\n/**\n * Get whether two values are equal (insofar as @tldraw/state is concerned).\n *\n * @param a The first value.\n * @param b The second value.\n */\nexport function equals(a: any, b: any): boolean {\n\tconst shallowEquals =\n\t\ta === b || Object.is(a, b) || Boolean(a && b && typeof a.equals === 'function' && a.equals(b))\n\treturn shallowEquals\n}\n\nexport declare function assertNever(x: never): never\n\nexport function singleton<T>(key: string, init: () => T): T {\n\tconst symbol = Symbol.for(`com.tldraw.state/${key}`)\n\tconst global = globalThis as any\n\tglobal[symbol] ??= init()\n\treturn global[symbol]\n}\n\n/**\n * @public\n */\nexport const EMPTY_ARRAY: [] = singleton('empty_array', () => Object.freeze([]) as any)\n\n/**\n * Does this signal have any active reactors attached to it? When it changes, will it cause anything to run?\n * @public\n */\nexport function hasReactors(signal: Signal<any>) {\n\tfor (const child of signal.children) {\n\t\tif (child.isActivelyListening) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,SAAS,QAAQ,GAAoB;AACpC,SAAO,KAAK,OAAO,MAAM,YAAY,aAAa;AACnD;AAQO,SAAS,mBAAmB,OAAuB;AACzD,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,QAAQ,IAAI,GAAG,KAAK;AAErD,UAAM,QAAQ,CAAC,EAAE,4BAA4B,IAAI;AAGjD,QAAI,MAAM,QAAQ,CAAC,EAAE,qBAAqB,MAAM,aAAa,CAAC,GAAG;AAChE,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAQO,SAAS,OAAO,QAAqB,OAAc;AAEzD,MAAI,CAAC,OAAO,SAAS,OAAO,KAAK,GAAG;AACnC;AAAA,EACD;AAGA,MAAI,OAAO,SAAS,WAAW,QAAQ,MAAM,GAAG;AAC/C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IAAI,GAAG,KAAK;AACtD,aAAO,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAA,IACjC;AAAA,EACD;AACD;AAQO,SAAS,OAAO,QAAqB,OAAc;AAEzD,MAAI,CAAC,OAAO,SAAS,IAAI,KAAK,GAAG;AAChC;AAAA,EACD;AAGA,MAAI,QAAQ,MAAM,GAAG;AACpB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IAAI,GAAG,KAAK;AACtD,aAAO,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAA,IACjC;AAAA,EACD;AACD;AAQO,SAAS,OAAO,GAAQ,GAAiB;AAC/C,QAAM,gBACL,MAAM,KAAK,OAAO,GAAG,GAAG,CAAC,KAAK,QAAQ,KAAK,KAAK,OAAO,EAAE,WAAW,cAAc,EAAE,OAAO,CAAC,CAAC;AAC9F,SAAO;AACR;AAIO,SAAS,UAAa,KAAa,MAAkB;AAC3D,QAAM,SAAS,OAAO,IAAI,oBAAoB,GAAG,EAAE;AACnD,QAAM,SAAS;AACf,SAAO,MAAM,MAAM,KAAK;AACxB,SAAO,OAAO,MAAM;AACrB;AAKO,MAAM,cAAkB,UAAU,eAAe,MAAM,OAAO,OAAO,CAAC,CAAC,CAAQ;AAM/E,SAAS,YAAY,QAAqB;AAChD,aAAW,SAAS,OAAO,UAAU;AACpC,QAAI,MAAM,qBAAqB;AAC9B,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;",
4
+ "sourcesContent": ["import { Child, Signal } from './types'\n\n/**\n * Get whether the given value is a child.\n *\n * @param x The value to check.\n * @returns True if the value is a child, false otherwise.\n * @internal\n */\nfunction isChild(x: any): x is Child {\n\treturn x && typeof x === 'object' && 'parents' in x\n}\n\n/**\n * Checks if any of a child's parent signals have changed by comparing their current epochs\n * with the child's cached view of those epochs.\n *\n * This function is used internally to determine if a computed signal or effect needs to\n * be re-evaluated because one of its dependencies has changed.\n *\n * @param child - The child (computed signal or effect) to check for parent changes\n * @returns `true` if any parent signal has changed since the child last observed it, `false` otherwise\n * @example\n * ```ts\n * const childSignal = computed('child', () => parentAtom.get())\n * // Check if the child needs to recompute\n * if (haveParentsChanged(childSignal)) {\n * // Recompute the child's value\n * }\n * ```\n * @internal\n */\nexport function haveParentsChanged(child: Child): boolean {\n\tfor (let i = 0, n = child.parents.length; i < n; i++) {\n\t\t// Get the parent's value without capturing it.\n\t\tchild.parents[i].__unsafe__getWithoutCapture(true)\n\n\t\t// If the parent's epoch does not match the child's view of the parent's epoch, then the parent has changed.\n\t\tif (child.parents[i].lastChangedEpoch !== child.parentEpochs[i]) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\n/**\n * Detaches a child signal from its parent signal, removing the parent-child relationship\n * in the reactive dependency graph. If the parent has no remaining children and is itself\n * a child, it will recursively detach from its own parents.\n *\n * This function is used internally to clean up the dependency graph when signals are no\n * longer needed or when dependencies change.\n *\n * @param parent - The parent signal to detach from\n * @param child - The child signal to detach\n * @example\n * ```ts\n * // When a computed signal's dependencies change\n * const oldParent = atom('old', 1)\n * const child = computed('child', () => oldParent.get())\n * // Later, detach the child from the old parent\n * detach(oldParent, child)\n * ```\n * @internal\n */\nexport function detach(parent: Signal<any>, child: Child) {\n\t// If the child is not attached to the parent, do nothing.\n\tif (!parent.children.remove(child)) {\n\t\treturn\n\t}\n\n\t// If the parent has no more children, then detach the parent from its parents.\n\tif (parent.children.isEmpty && isChild(parent)) {\n\t\tfor (let i = 0, n = parent.parents.length; i < n; i++) {\n\t\t\tdetach(parent.parents[i], parent)\n\t\t}\n\t}\n}\n\n/**\n * Attaches a child signal to its parent signal, establishing a parent-child relationship\n * in the reactive dependency graph. If the parent is itself a child, it will recursively\n * attach to its own parents to maintain the dependency chain.\n *\n * This function is used internally when dependencies are captured during computed signal\n * evaluation or effect execution.\n *\n * @param parent - The parent signal to attach to\n * @param child - The child signal to attach\n * @example\n * ```ts\n * // When a computed signal captures a new dependency\n * const parentAtom = atom('parent', 1)\n * const child = computed('child', () => parentAtom.get())\n * // Internally, attach is called to establish the dependency\n * attach(parentAtom, child)\n * ```\n * @internal\n */\nexport function attach(parent: Signal<any>, child: Child) {\n\t// If the child is already attached to the parent, do nothing.\n\tif (!parent.children.add(child)) {\n\t\treturn\n\t}\n\n\t// If the parent itself is a child, add the parent to the parent's parents.\n\tif (isChild(parent)) {\n\t\tfor (let i = 0, n = parent.parents.length; i < n; i++) {\n\t\t\tattach(parent.parents[i], parent)\n\t\t}\n\t}\n}\n\n/**\n * Checks if two values are equal using the equality semantics of @tldraw/state.\n *\n * This function performs equality checks in the following order:\n * 1. Reference equality (`===`)\n * 2. `Object.is()` equality (handles NaN and -0/+0 cases)\n * 3. Custom `.equals()` method when the left-hand value provides one\n *\n * This is used internally to determine if a signal's value has actually changed\n * when setting new values, preventing unnecessary updates and re-computations.\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are considered equal, `false` otherwise\n * @example\n * ```ts\n * equals(1, 1) // true\n * equals(NaN, NaN) // true (unlike === which returns false)\n * equals({ equals: (other: any) => other.id === 1 }, { id: 1 }) // Uses custom equals method\n * ```\n * @internal\n */\nexport function equals(a: any, b: any): boolean {\n\tconst shallowEquals =\n\t\ta === b || Object.is(a, b) || Boolean(a && b && typeof a.equals === 'function' && a.equals(b))\n\treturn shallowEquals\n}\n\n/**\n * A TypeScript utility function for exhaustiveness checking in switch statements and\n * conditional branches. This function should never be called at runtime\u2014it exists\n * purely for compile-time type checking and is `undefined` in emitted JavaScript.\n *\n * @param x - A value that should be of type `never`\n * @throws Always at runtime because the identifier is undefined\n * @example\n * ```ts\n * type Color = 'red' | 'blue'\n *\n * function handleColor(color: Color) {\n * switch (color) {\n * case 'red':\n * return 'Stop'\n * case 'blue':\n * return 'Go'\n * default:\n * return assertNever(color) // TypeScript error if not all cases handled\n * }\n * }\n * ```\n * @public\n */\nexport declare function assertNever(x: never): never\n\n/**\n * Creates or retrieves a singleton instance using a global symbol registry.\n * This ensures that the same instance is shared across all code that uses\n * the same key, even across different module boundaries.\n *\n * The singleton is stored on `globalThis` using a symbol created with\n * `Symbol.for()`, which ensures global uniqueness across realms.\n *\n * @param key - A unique string identifier for the singleton\n * @param init - A function that creates the initial value if it doesn't exist\n * @returns The singleton instance\n * @example\n * ```ts\n * // Create a singleton logger\n * const logger = singleton('logger', () => new Logger())\n *\n * // Elsewhere in the codebase, get the same logger instance\n * const sameLogger = singleton('logger', () => new Logger())\n * // logger === sameLogger\n * ```\n * @internal\n */\nexport function singleton<T>(key: string, init: () => T): T {\n\tconst symbol = Symbol.for(`com.tldraw.state/${key}`)\n\tconst global = globalThis as any\n\tglobal[symbol] ??= init()\n\treturn global[symbol]\n}\n\n/**\n * @public\n */\nexport const EMPTY_ARRAY: [] = singleton('empty_array', () => Object.freeze([]) as any)\n\n/**\n * Checks if a signal has any active reactors (effects or computed signals) that are\n * currently listening to it. This determines whether changes to the signal will\n * cause any side effects or recomputations to occur.\n *\n * A signal is considered to have active reactors if any of its child dependencies\n * are actively listening for changes.\n *\n * @param signal - The signal to check for active reactors\n * @returns `true` if the signal has active reactors, `false` otherwise\n * @example\n * ```ts\n * const count = atom('count', 0)\n *\n * console.log(hasReactors(count)) // false - no effects listening\n *\n * const stop = react('logger', () => console.log(count.get()))\n * console.log(hasReactors(count)) // true - effect is listening\n *\n * stop()\n * console.log(hasReactors(count)) // false - effect stopped\n * ```\n * @public\n */\nexport function hasReactors(signal: Signal<any>) {\n\tfor (const child of signal.children) {\n\t\tif (child.isActivelyListening) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,SAAS,QAAQ,GAAoB;AACpC,SAAO,KAAK,OAAO,MAAM,YAAY,aAAa;AACnD;AAqBO,SAAS,mBAAmB,OAAuB;AACzD,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,QAAQ,IAAI,GAAG,KAAK;AAErD,UAAM,QAAQ,CAAC,EAAE,4BAA4B,IAAI;AAGjD,QAAI,MAAM,QAAQ,CAAC,EAAE,qBAAqB,MAAM,aAAa,CAAC,GAAG;AAChE,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;AAsBO,SAAS,OAAO,QAAqB,OAAc;AAEzD,MAAI,CAAC,OAAO,SAAS,OAAO,KAAK,GAAG;AACnC;AAAA,EACD;AAGA,MAAI,OAAO,SAAS,WAAW,QAAQ,MAAM,GAAG;AAC/C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IAAI,GAAG,KAAK;AACtD,aAAO,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAA,IACjC;AAAA,EACD;AACD;AAsBO,SAAS,OAAO,QAAqB,OAAc;AAEzD,MAAI,CAAC,OAAO,SAAS,IAAI,KAAK,GAAG;AAChC;AAAA,EACD;AAGA,MAAI,QAAQ,MAAM,GAAG;AACpB,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,QAAQ,IAAI,GAAG,KAAK;AACtD,aAAO,OAAO,QAAQ,CAAC,GAAG,MAAM;AAAA,IACjC;AAAA,EACD;AACD;AAwBO,SAAS,OAAO,GAAQ,GAAiB;AAC/C,QAAM,gBACL,MAAM,KAAK,OAAO,GAAG,GAAG,CAAC,KAAK,QAAQ,KAAK,KAAK,OAAO,EAAE,WAAW,cAAc,EAAE,OAAO,CAAC,CAAC;AAC9F,SAAO;AACR;AAkDO,SAAS,UAAa,KAAa,MAAkB;AAC3D,QAAM,SAAS,OAAO,IAAI,oBAAoB,GAAG,EAAE;AACnD,QAAM,SAAS;AACf,SAAO,MAAM,MAAM,KAAK;AACxB,SAAO,OAAO,MAAM;AACrB;AAKO,MAAM,cAAkB,UAAU,eAAe,MAAM,OAAO,OAAO,CAAC,CAAC,CAAQ;AA0B/E,SAAS,YAAY,QAAqB;AAChD,aAAW,SAAS,OAAO,UAAU;AACpC,QAAI,MAAM,qBAAqB;AAC9B,aAAO;AAAA,IACR;AAAA,EACD;AAEA,SAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/isSignal.ts"],
4
- "sourcesContent": ["import { _Atom } from './Atom'\nimport { _Computed } from './Computed'\nimport { Signal } from './types'\n\n/**\n * @public\n */\nexport function isSignal(value: any): value is Signal<any> {\n\treturn value instanceof _Atom || value instanceof _Computed\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsB;AACtB,sBAA0B;AAMnB,SAAS,SAAS,OAAkC;AAC1D,SAAO,iBAAiB,qBAAS,iBAAiB;AACnD;",
4
+ "sourcesContent": ["import { _Atom } from './Atom'\nimport { _Computed } from './Computed'\nimport { Signal } from './types'\n\n/**\n * Type guard function that determines whether a value is a signal (either an Atom or Computed).\n *\n * This utility function is helpful when working with mixed data types and you need to\n * differentiate between regular values and reactive signal containers. It returns `true`\n * if the provided value is either an atomic signal created with `atom()` or a computed\n * signal created with `computed()`.\n *\n * @param value - The value to check, can be of any type\n * @returns `true` if the value is a Signal (Atom or Computed), `false` otherwise\n *\n * @example\n * ```ts\n * import { atom, computed, isSignal } from '@tldraw/state'\n *\n * const count = atom('count', 5)\n * const doubled = computed('doubled', () => count.get() * 2)\n * const regularValue = 'hello'\n *\n * console.log(isSignal(count)) // true\n * console.log(isSignal(doubled)) // true\n * console.log(isSignal(regularValue)) // false\n * console.log(isSignal(null)) // false\n * ```\n *\n * @public\n */\nexport function isSignal(value: any): value is Signal<any> {\n\treturn value instanceof _Atom || value instanceof _Computed\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAsB;AACtB,sBAA0B;AA8BnB,SAAS,SAAS,OAAkC;AAC1D,SAAO,iBAAiB,qBAAS,iBAAiB;AACnD;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var localStorageAtom_exports = {};
20
+ __export(localStorageAtom_exports, {
21
+ localStorageAtom: () => localStorageAtom
22
+ });
23
+ module.exports = __toCommonJS(localStorageAtom_exports);
24
+ var import_utils = require("@tldraw/utils");
25
+ var import_Atom = require("./Atom");
26
+ var import_EffectScheduler = require("./EffectScheduler");
27
+ function localStorageAtom(name, initialValue, options) {
28
+ let _initialValue = initialValue;
29
+ try {
30
+ const value = (0, import_utils.getFromLocalStorage)(name);
31
+ if (value) {
32
+ _initialValue = JSON.parse(value);
33
+ }
34
+ } catch {
35
+ (0, import_utils.deleteFromLocalStorage)(name);
36
+ }
37
+ const outAtom = (0, import_Atom.atom)(name, _initialValue, options);
38
+ const reactCleanup = (0, import_EffectScheduler.react)(`save ${name} to localStorage`, () => {
39
+ (0, import_utils.setInLocalStorage)(name, JSON.stringify(outAtom.get()));
40
+ });
41
+ const handleStorageEvent = (event) => {
42
+ if (event.key !== name) return;
43
+ if (event.newValue === null) {
44
+ outAtom.set(initialValue);
45
+ return;
46
+ }
47
+ try {
48
+ const newValue = JSON.parse(event.newValue);
49
+ outAtom.set(newValue);
50
+ } catch {
51
+ }
52
+ };
53
+ window.addEventListener("storage", handleStorageEvent);
54
+ const cleanup = () => {
55
+ reactCleanup();
56
+ window.removeEventListener("storage", handleStorageEvent);
57
+ };
58
+ return [outAtom, cleanup];
59
+ }
60
+ //# sourceMappingURL=localStorageAtom.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/lib/localStorageAtom.ts"],
4
+ "sourcesContent": ["import { deleteFromLocalStorage, getFromLocalStorage, setInLocalStorage } from '@tldraw/utils'\nimport { Atom, atom, AtomOptions } from './Atom'\nimport { react } from './EffectScheduler'\n\n/**\n * Creates a new {@link Atom} that persists its value to localStorage.\n *\n * The atom is automatically synced with localStorage - changes to the atom are saved to localStorage,\n * and the initial value is read from localStorage if it exists. Returns both the atom and a cleanup\n * function that should be called to stop syncing when the atom is no longer needed. If you need to delete\n * the atom, you should do it manually after all cleanup functions have been called.\n *\n * @example\n * ```ts\n * const [theme, cleanup] = localStorageAtom('theme', 'light')\n *\n * theme.get() // 'light' or value from localStorage if it exists\n *\n * theme.set('dark') // updates atom and saves to localStorage\n *\n * // When done:\n * cleanup() // stops syncing to localStorage\n * ```\n *\n * @param name - The localStorage key and atom name. This is used for both localStorage persistence\n * and debugging/profiling purposes.\n * @param initialValue - The initial value of the atom, used if no value exists in localStorage.\n * @param options - Optional atom configuration. See {@link AtomOptions}.\n * @returns A tuple containing the atom and a cleanup function to stop localStorage syncing.\n * @public\n */\nexport function localStorageAtom<Value, Diff = unknown>(\n\tname: string,\n\tinitialValue: Value,\n\toptions?: AtomOptions<Value, Diff>\n): [Atom<Value, Diff>, () => void] {\n\t// Try to restore the initial value from localStorage\n\tlet _initialValue = initialValue\n\n\ttry {\n\t\tconst value = getFromLocalStorage(name)\n\t\tif (value) {\n\t\t\t_initialValue = JSON.parse(value) as Value\n\t\t}\n\t} catch {\n\t\t// If parsing fails, the stored value is corrupted - delete it and use the provided initial value\n\t\tdeleteFromLocalStorage(name)\n\t}\n\n\t// Create the atom with the restored or initial value\n\tconst outAtom = atom(name, _initialValue, options)\n\n\t// Set up automatic syncing: whenever the atom changes, save it to localStorage\n\tconst reactCleanup = react(`save ${name} to localStorage`, () => {\n\t\tsetInLocalStorage(name, JSON.stringify(outAtom.get()))\n\t})\n\n\t// Set up cross-tab sync: listen for storage events from other tabs\n\tconst handleStorageEvent = (event: StorageEvent) => {\n\t\t// Only handle events for this specific key\n\t\tif (event.key !== name) return\n\n\t\t// If the value was deleted in another tab\n\t\tif (event.newValue === null) {\n\t\t\toutAtom.set(initialValue)\n\t\t\treturn\n\t\t}\n\n\t\t// If the value was changed in another tab, update the atom\n\t\ttry {\n\t\t\tconst newValue = JSON.parse(event.newValue) as Value\n\t\t\toutAtom.set(newValue)\n\t\t} catch {\n\t\t\t// If parsing fails, the stored value is corrupted; preserve the existing value\n\t\t}\n\t}\n\n\twindow.addEventListener('storage', handleStorageEvent)\n\n\t// Combined cleanup function\n\tconst cleanup = () => {\n\t\treactCleanup()\n\t\twindow.removeEventListener('storage', handleStorageEvent)\n\t}\n\n\treturn [outAtom, cleanup]\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+E;AAC/E,kBAAwC;AACxC,6BAAsB;AA6Bf,SAAS,iBACf,MACA,cACA,SACkC;AAElC,MAAI,gBAAgB;AAEpB,MAAI;AACH,UAAM,YAAQ,kCAAoB,IAAI;AACtC,QAAI,OAAO;AACV,sBAAgB,KAAK,MAAM,KAAK;AAAA,IACjC;AAAA,EACD,QAAQ;AAEP,6CAAuB,IAAI;AAAA,EAC5B;AAGA,QAAM,cAAU,kBAAK,MAAM,eAAe,OAAO;AAGjD,QAAM,mBAAe,8BAAM,QAAQ,IAAI,oBAAoB,MAAM;AAChE,wCAAkB,MAAM,KAAK,UAAU,QAAQ,IAAI,CAAC,CAAC;AAAA,EACtD,CAAC;AAGD,QAAM,qBAAqB,CAAC,UAAwB;AAEnD,QAAI,MAAM,QAAQ,KAAM;AAGxB,QAAI,MAAM,aAAa,MAAM;AAC5B,cAAQ,IAAI,YAAY;AACxB;AAAA,IACD;AAGA,QAAI;AACH,YAAM,WAAW,KAAK,MAAM,MAAM,QAAQ;AAC1C,cAAQ,IAAI,QAAQ;AAAA,IACrB,QAAQ;AAAA,IAER;AAAA,EACD;AAEA,SAAO,iBAAiB,WAAW,kBAAkB;AAGrD,QAAM,UAAU,MAAM;AACrB,iBAAa;AACb,WAAO,oBAAoB,WAAW,kBAAkB;AAAA,EACzD;AAEA,SAAO,CAAC,SAAS,OAAO;AACzB;",
6
+ "names": []
7
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/transactions.ts"],
4
- "sourcesContent": ["import { _Atom } from './Atom'\nimport { EffectScheduler } from './EffectScheduler'\nimport { GLOBAL_START_EPOCH } from './constants'\nimport { singleton } from './helpers'\nimport { Child, Signal } from './types'\n\nclass Transaction {\n\tasyncProcessCount = 0\n\tconstructor(\n\t\tpublic readonly parent: Transaction | null,\n\t\tpublic readonly isSync: boolean\n\t) {}\n\n\tinitialAtomValues = new Map<_Atom, any>()\n\n\t/**\n\t * Get whether this transaction is a root (no parents).\n\t *\n\t * @public\n\t */\n\t// eslint-disable-next-line no-restricted-syntax\n\tget isRoot() {\n\t\treturn this.parent === null\n\t}\n\n\t/**\n\t * Commit the transaction's changes.\n\t *\n\t * @public\n\t */\n\tcommit() {\n\t\tif (inst.globalIsReacting) {\n\t\t\t// if we're committing during a reaction we actually need to\n\t\t\t// use the 'cleanup' reactors set to ensure we re-run effects if necessary\n\t\t\tfor (const atom of this.initialAtomValues.keys()) {\n\t\t\t\ttraverseAtomForCleanup(atom)\n\t\t\t}\n\t\t} else if (this.isRoot) {\n\t\t\t// For root transactions, flush changed atoms\n\t\t\tflushChanges(this.initialAtomValues.keys())\n\t\t} else {\n\t\t\t// For transactions with parents, add the transaction's initial values to the parent's.\n\t\t\tthis.initialAtomValues.forEach((value, atom) => {\n\t\t\t\tif (!this.parent!.initialAtomValues.has(atom)) {\n\t\t\t\t\tthis.parent!.initialAtomValues.set(atom, value)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Abort the transaction.\n\t *\n\t * @public\n\t */\n\tabort() {\n\t\tinst.globalEpoch++\n\n\t\t// Reset each of the transaction's atoms to its initial value.\n\t\tthis.initialAtomValues.forEach((value, atom) => {\n\t\t\tatom.set(value)\n\t\t\tatom.historyBuffer?.clear()\n\t\t})\n\n\t\t// Commit the changes.\n\t\tthis.commit()\n\t}\n}\n\nconst inst = singleton('transactions', () => ({\n\t// The current epoch (global to all atoms).\n\tglobalEpoch: GLOBAL_START_EPOCH + 1,\n\t// Whether any transaction is reacting.\n\tglobalIsReacting: false,\n\tcurrentTransaction: null as Transaction | null,\n\n\tcleanupReactors: null as null | Set<EffectScheduler<unknown>>,\n\treactionEpoch: GLOBAL_START_EPOCH + 1,\n}))\n\nexport function getReactionEpoch() {\n\treturn inst.reactionEpoch\n}\n\nexport function getGlobalEpoch() {\n\treturn inst.globalEpoch\n}\n\nexport function getIsReacting() {\n\treturn inst.globalIsReacting\n}\n\nfunction traverse(reactors: Set<EffectScheduler<unknown>>, child: Child) {\n\tif (child.lastTraversedEpoch === inst.globalEpoch) {\n\t\treturn\n\t}\n\n\tchild.lastTraversedEpoch = inst.globalEpoch\n\n\tif (child instanceof EffectScheduler) {\n\t\treactors.add(child)\n\t} else {\n\t\t;(child as any as Signal<any>).children.visit((c) => traverse(reactors, c))\n\t}\n}\n\n/**\n * Collect all of the reactors that need to run for an atom and run them.\n *\n * @param atoms - The atoms to flush changes for.\n */\nfunction flushChanges(atoms: Iterable<_Atom>) {\n\tif (inst.globalIsReacting) {\n\t\tthrow new Error('flushChanges cannot be called during a reaction')\n\t}\n\n\tconst outerTxn = inst.currentTransaction\n\ttry {\n\t\t// clear the transaction stack\n\t\tinst.currentTransaction = null\n\t\tinst.globalIsReacting = true\n\t\tinst.reactionEpoch = inst.globalEpoch\n\n\t\t// Collect all of the visited reactors.\n\t\tconst reactors = new Set<EffectScheduler<unknown>>()\n\n\t\tfor (const atom of atoms) {\n\t\t\tatom.children.visit((child) => traverse(reactors, child))\n\t\t}\n\n\t\t// Run each reactor.\n\t\tfor (const r of reactors) {\n\t\t\tr.maybeScheduleEffect()\n\t\t}\n\n\t\tlet updateDepth = 0\n\t\twhile (inst.cleanupReactors?.size) {\n\t\t\tif (updateDepth++ > 1000) {\n\t\t\t\tthrow new Error('Reaction update depth limit exceeded')\n\t\t\t}\n\t\t\tconst reactors = inst.cleanupReactors\n\t\t\tinst.cleanupReactors = null\n\t\t\tfor (const r of reactors) {\n\t\t\t\tr.maybeScheduleEffect()\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tinst.cleanupReactors = null\n\t\tinst.globalIsReacting = false\n\t\tinst.currentTransaction = outerTxn\n\t}\n}\n\n/**\n * Handle a change to an atom.\n *\n * @param atom The atom that changed.\n * @param previousValue The atom's previous value.\n *\n * @internal\n */\nexport function atomDidChange(atom: _Atom, previousValue: any) {\n\tif (inst.currentTransaction) {\n\t\t// If we are in a transaction, then all we have to do is preserve\n\t\t// the value of the atom at the start of the transaction in case\n\t\t// we need to roll back.\n\t\tif (!inst.currentTransaction.initialAtomValues.has(atom)) {\n\t\t\tinst.currentTransaction.initialAtomValues.set(atom, previousValue)\n\t\t}\n\t} else if (inst.globalIsReacting) {\n\t\t// If the atom changed during the reaction phase of flushChanges\n\t\t// (and there are no transactions started inside the reaction phase)\n\t\t// then we are past the point where a transaction can be aborted\n\t\t// so we don't need to note down the previousValue.\n\t\ttraverseAtomForCleanup(atom)\n\t} else {\n\t\t// If there is no transaction, flush the changes immediately.\n\t\tflushChanges([atom])\n\t}\n}\n\nfunction traverseAtomForCleanup(atom: _Atom) {\n\tconst rs = (inst.cleanupReactors ??= new Set())\n\tatom.children.visit((child) => traverse(rs, child))\n}\n\nexport function advanceGlobalEpoch() {\n\tinst.globalEpoch++\n}\n\n/**\n * Batches state updates, deferring side effects until after the transaction completes.\n *\n * @example\n * ```ts\n * const firstName = atom('John')\n * const lastName = atom('Doe')\n *\n * react('greet', () => {\n * print(`Hello, ${firstName.get()} ${lastName.get()}!`)\n * })\n *\n * // Logs \"Hello, John Doe!\"\n *\n * transaction(() => {\n * firstName.set('Jane')\n * lastName.set('Smith')\n * })\n *\n * // Logs \"Hello, Jane Smith!\"\n * ```\n *\n * 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.\n *\n * @example\n * ```ts\n * const firstName = atom('John')\n * const lastName = atom('Doe')\n *\n * react('greet', () => {\n * print(`Hello, ${firstName.get()} ${lastName.get()}!`)\n * })\n *\n * // Logs \"Hello, John Doe!\"\n *\n * transaction(() => {\n * firstName.set('Jane')\n * throw new Error('oops')\n * })\n *\n * // Does not log\n * // firstName.get() === 'John'\n * ```\n *\n * A `rollback` callback is passed into the function.\n * Calling this will prevent the transaction from committing and will revert any signals that were updated during the transaction to their state before the transaction began.\n *\n * @example\n * ```ts\n * const firstName = atom('John')\n * const lastName = atom('Doe')\n *\n * react('greet', () => {\n * print(`Hello, ${firstName.get()} ${lastName.get()}!`)\n * })\n *\n * // Logs \"Hello, John Doe!\"\n *\n * transaction((rollback) => {\n * firstName.set('Jane')\n * lastName.set('Smith')\n * rollback()\n * })\n *\n * // Does not log\n * // firstName.get() === 'John'\n * // lastName.get() === 'Doe'\n * ```\n *\n * @param fn - The function to run in a transaction, called with a function to roll back the change.\n * @public\n */\nexport function transaction<T>(fn: (rollback: () => void) => T) {\n\tconst txn = new Transaction(inst.currentTransaction, true)\n\n\t// Set the current transaction to the transaction\n\tinst.currentTransaction = txn\n\n\ttry {\n\t\tlet result = undefined as T | undefined\n\t\tlet rollback = false\n\n\t\ttry {\n\t\t\t// Run the function.\n\t\t\tresult = fn(() => (rollback = true))\n\t\t} catch (e) {\n\t\t\t// Abort the transaction if the function throws.\n\t\t\ttxn.abort()\n\t\t\tthrow e\n\t\t}\n\n\t\tif (inst.currentTransaction !== txn) {\n\t\t\tthrow new Error('Transaction boundaries overlap')\n\t\t}\n\n\t\tif (rollback) {\n\t\t\t// If the rollback was triggered, abort the transaction.\n\t\t\ttxn.abort()\n\t\t} else {\n\t\t\ttxn.commit()\n\t\t}\n\n\t\treturn result\n\t} finally {\n\t\t// Set the current transaction to the transaction's parent.\n\t\tinst.currentTransaction = txn.parent\n\t}\n}\n\n/**\n * Like {@link transaction}, but does not create a new transaction if there is already one in progress.\n *\n * @param fn - The function to run in a transaction.\n * @public\n */\nexport function transact<T>(fn: () => T): T {\n\tif (inst.currentTransaction) {\n\t\treturn fn()\n\t}\n\treturn transaction(fn)\n}\n\n/**\n * @internal\n */\nexport async function deferAsyncEffects<T>(fn: () => Promise<T>) {\n\t// Can't kick off async transactions during a sync transaction because\n\t// the async transaction won't finish until after the sync transaction\n\t// is done.\n\tif (inst.currentTransaction?.isSync) {\n\t\tthrow new Error('deferAsyncEffects cannot be called during a sync transaction')\n\t}\n\n\t// Can't kick off async transactions during a reaction phase at the moment,\n\t// because the transaction stack is cleared after the reaction phase.\n\t// So wait until the path ahead is clear\n\twhile (inst.globalIsReacting) {\n\t\tawait new Promise((r) => queueMicrotask(() => r(null)))\n\t}\n\n\tconst txn = inst.currentTransaction ?? new Transaction(null, false)\n\n\t// don't think this can happen, but just in case\n\tif (txn.isSync) throw new Error('deferAsyncEffects cannot be called during a sync transaction')\n\n\tinst.currentTransaction = txn\n\ttxn.asyncProcessCount++\n\n\tlet result = undefined as T | undefined\n\n\tlet error = undefined as any\n\ttry {\n\t\t// Run the function.\n\t\tresult = await fn()\n\t} catch (e) {\n\t\t// Abort the transaction if the function throws.\n\t\terror = e ?? null\n\t}\n\n\tif (--txn.asyncProcessCount > 0) {\n\t\tif (typeof error !== 'undefined') {\n\t\t\t// If the rollback was triggered, abort the transaction.\n\t\t\tthrow error\n\t\t} else {\n\t\t\treturn result\n\t\t}\n\t}\n\n\tinst.currentTransaction = null\n\n\tif (typeof error !== 'undefined') {\n\t\t// If the rollback was triggered, abort the transaction.\n\t\ttxn.abort()\n\t\tthrow error\n\t} else {\n\t\ttxn.commit()\n\t\treturn result\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { _Atom } from './Atom'\nimport { EffectScheduler } from './EffectScheduler'\nimport { GLOBAL_START_EPOCH } from './constants'\nimport { singleton } from './helpers'\nimport { Child, Signal } from './types'\n\nclass Transaction {\n\tasyncProcessCount = 0\n\tconstructor(\n\t\tpublic readonly parent: Transaction | null,\n\t\tpublic readonly isSync: boolean\n\t) {}\n\n\tinitialAtomValues = new Map<_Atom, any>()\n\n\t/**\n\t * Get whether this transaction is a root (no parents).\n\t *\n\t * @public\n\t */\n\t// eslint-disable-next-line no-restricted-syntax\n\tget isRoot() {\n\t\treturn this.parent === null\n\t}\n\n\t/**\n\t * Commit the transaction's changes.\n\t *\n\t * @public\n\t */\n\tcommit() {\n\t\tif (inst.globalIsReacting) {\n\t\t\t// if we're committing during a reaction we actually need to\n\t\t\t// use the 'cleanup' reactors set to ensure we re-run effects if necessary\n\t\t\tfor (const atom of this.initialAtomValues.keys()) {\n\t\t\t\ttraverseAtomForCleanup(atom)\n\t\t\t}\n\t\t} else if (this.isRoot) {\n\t\t\t// For root transactions, flush changed atoms\n\t\t\tflushChanges(this.initialAtomValues.keys())\n\t\t} else {\n\t\t\t// For transactions with parents, add the transaction's initial values to the parent's.\n\t\t\tthis.initialAtomValues.forEach((value, atom) => {\n\t\t\t\tif (!this.parent!.initialAtomValues.has(atom)) {\n\t\t\t\t\tthis.parent!.initialAtomValues.set(atom, value)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Abort the transaction.\n\t *\n\t * @public\n\t */\n\tabort() {\n\t\tinst.globalEpoch++\n\n\t\t// Reset each of the transaction's atoms to its initial value.\n\t\tthis.initialAtomValues.forEach((value, atom) => {\n\t\t\tatom.set(value)\n\t\t\tatom.historyBuffer?.clear()\n\t\t})\n\n\t\t// Commit the changes.\n\t\tthis.commit()\n\t}\n}\n\nconst inst = singleton('transactions', () => ({\n\t// The current epoch (global to all atoms).\n\tglobalEpoch: GLOBAL_START_EPOCH + 1,\n\t// Whether any transaction is reacting.\n\tglobalIsReacting: false,\n\tcurrentTransaction: null as Transaction | null,\n\n\tcleanupReactors: null as null | Set<EffectScheduler<unknown>>,\n\treactionEpoch: GLOBAL_START_EPOCH + 1,\n}))\n\n/**\n * Gets the current reaction epoch, which is used to track when reactions are running.\n * The reaction epoch is updated at the start of each reaction cycle.\n *\n * @returns The current reaction epoch number\n * @public\n */\nexport function getReactionEpoch() {\n\treturn inst.reactionEpoch\n}\n\n/**\n * Gets the current global epoch, which is incremented every time any atom changes.\n * This is used to track changes across the entire reactive system.\n *\n * @returns The current global epoch number\n * @public\n */\nexport function getGlobalEpoch() {\n\treturn inst.globalEpoch\n}\n\n/**\n * Checks whether any reactions are currently executing.\n * When true, the system is in the middle of processing effects and side effects.\n *\n * @returns True if reactions are currently running, false otherwise\n * @public\n */\nexport function getIsReacting() {\n\treturn inst.globalIsReacting\n}\n\nfunction traverse(reactors: Set<EffectScheduler<unknown>>, child: Child) {\n\tif (child.lastTraversedEpoch === inst.globalEpoch) {\n\t\treturn\n\t}\n\n\tchild.lastTraversedEpoch = inst.globalEpoch\n\n\tif (child instanceof EffectScheduler) {\n\t\treactors.add(child)\n\t} else {\n\t\t;(child as any as Signal<any>).children.visit((c) => traverse(reactors, c))\n\t}\n}\n\n/**\n * Collect all of the reactors that need to run for an atom and run them.\n *\n * @param atoms - The atoms to flush changes for.\n */\nfunction flushChanges(atoms: Iterable<_Atom>) {\n\tif (inst.globalIsReacting) {\n\t\tthrow new Error('flushChanges cannot be called during a reaction')\n\t}\n\n\tconst outerTxn = inst.currentTransaction\n\ttry {\n\t\t// clear the transaction stack\n\t\tinst.currentTransaction = null\n\t\tinst.globalIsReacting = true\n\t\tinst.reactionEpoch = inst.globalEpoch\n\n\t\t// Collect all of the visited reactors.\n\t\tconst reactors = new Set<EffectScheduler<unknown>>()\n\n\t\tfor (const atom of atoms) {\n\t\t\tatom.children.visit((child) => traverse(reactors, child))\n\t\t}\n\n\t\t// Run each reactor.\n\t\tfor (const r of reactors) {\n\t\t\tr.maybeScheduleEffect()\n\t\t}\n\n\t\tlet updateDepth = 0\n\t\twhile (inst.cleanupReactors?.size) {\n\t\t\tif (updateDepth++ > 1000) {\n\t\t\t\tthrow new Error('Reaction update depth limit exceeded')\n\t\t\t}\n\t\t\tconst reactors = inst.cleanupReactors\n\t\t\tinst.cleanupReactors = null\n\t\t\tfor (const r of reactors) {\n\t\t\t\tr.maybeScheduleEffect()\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tinst.cleanupReactors = null\n\t\tinst.globalIsReacting = false\n\t\tinst.currentTransaction = outerTxn\n\t}\n}\n\n/**\n * Handle a change to an atom.\n *\n * @param atom The atom that changed.\n * @param previousValue The atom's previous value.\n *\n * @internal\n */\nexport function atomDidChange(atom: _Atom, previousValue: any) {\n\tif (inst.currentTransaction) {\n\t\t// If we are in a transaction, then all we have to do is preserve\n\t\t// the value of the atom at the start of the transaction in case\n\t\t// we need to roll back.\n\t\tif (!inst.currentTransaction.initialAtomValues.has(atom)) {\n\t\t\tinst.currentTransaction.initialAtomValues.set(atom, previousValue)\n\t\t}\n\t} else if (inst.globalIsReacting) {\n\t\t// If the atom changed during the reaction phase of flushChanges\n\t\t// (and there are no transactions started inside the reaction phase)\n\t\t// then we are past the point where a transaction can be aborted\n\t\t// so we don't need to note down the previousValue.\n\t\ttraverseAtomForCleanup(atom)\n\t} else {\n\t\t// If there is no transaction, flush the changes immediately.\n\t\tflushChanges([atom])\n\t}\n}\n\nfunction traverseAtomForCleanup(atom: _Atom) {\n\tconst rs = (inst.cleanupReactors ??= new Set())\n\tatom.children.visit((child) => traverse(rs, child))\n}\n\n/**\n * Advances the global epoch counter by one.\n * This is used internally to track when changes occur across the reactive system.\n *\n * @internal\n */\nexport function advanceGlobalEpoch() {\n\tinst.globalEpoch++\n}\n\n/**\n * Batches state updates, deferring side effects until after the transaction completes.\n * Unlike {@link transact}, this function always creates a new transaction, allowing for nested transactions.\n *\n * @example\n * ```ts\n * const firstName = atom('firstName', 'John')\n * const lastName = atom('lastName', 'Doe')\n *\n * react('greet', () => {\n * console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)\n * })\n *\n * // Logs \"Hello, John Doe!\"\n *\n * transaction(() => {\n * firstName.set('Jane')\n * lastName.set('Smith')\n * })\n *\n * // Logs \"Hello, Jane Smith!\"\n * ```\n *\n * 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.\n *\n * @example\n * ```ts\n * const firstName = atom('firstName', 'John')\n * const lastName = atom('lastName', 'Doe')\n *\n * react('greet', () => {\n * console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)\n * })\n *\n * // Logs \"Hello, John Doe!\"\n *\n * transaction(() => {\n * firstName.set('Jane')\n * throw new Error('oops')\n * })\n *\n * // Does not log\n * // firstName.get() === 'John'\n * ```\n *\n * A `rollback` callback is passed into the function.\n * Calling this will prevent the transaction from committing and will revert any signals that were updated during the transaction to their state before the transaction began.\n *\n * @example\n * ```ts\n * const firstName = atom('firstName', 'John')\n * const lastName = atom('lastName', 'Doe')\n *\n * react('greet', () => {\n * console.log(`Hello, ${firstName.get()} ${lastName.get()}!`)\n * })\n *\n * // Logs \"Hello, John Doe!\"\n *\n * transaction((rollback) => {\n * firstName.set('Jane')\n * lastName.set('Smith')\n * rollback()\n * })\n *\n * // Does not log\n * // firstName.get() === 'John'\n * // lastName.get() === 'Doe'\n * ```\n *\n * @param fn - The function to run in a transaction, called with a function to roll back the change.\n * @returns The return value of the function\n * @public\n */\nexport function transaction<T>(fn: (rollback: () => void) => T) {\n\tconst txn = new Transaction(inst.currentTransaction, true)\n\n\t// Set the current transaction to the transaction\n\tinst.currentTransaction = txn\n\n\ttry {\n\t\tlet result = undefined as T | undefined\n\t\tlet rollback = false\n\n\t\ttry {\n\t\t\t// Run the function.\n\t\t\tresult = fn(() => (rollback = true))\n\t\t} catch (e) {\n\t\t\t// Abort the transaction if the function throws.\n\t\t\ttxn.abort()\n\t\t\tthrow e\n\t\t}\n\n\t\tif (inst.currentTransaction !== txn) {\n\t\t\tthrow new Error('Transaction boundaries overlap')\n\t\t}\n\n\t\tif (rollback) {\n\t\t\t// If the rollback was triggered, abort the transaction.\n\t\t\ttxn.abort()\n\t\t} else {\n\t\t\ttxn.commit()\n\t\t}\n\n\t\treturn result\n\t} finally {\n\t\t// Set the current transaction to the transaction's parent.\n\t\tinst.currentTransaction = txn.parent\n\t}\n}\n\n/**\n * Like {@link transaction}, but does not create a new transaction if there is already one in progress.\n * This is the preferred way to batch state updates when you don't need the rollback functionality.\n *\n * @example\n * ```ts\n * const count = atom('count', 0)\n * const doubled = atom('doubled', 0)\n *\n * react('update doubled', () => {\n * console.log(`Count: ${count.get()}, Doubled: ${doubled.get()}`)\n * })\n *\n * // This batches both updates into a single reaction\n * transact(() => {\n * count.set(5)\n * doubled.set(count.get() * 2)\n * })\n * // Logs: \"Count: 5, Doubled: 10\"\n * ```\n *\n * @param fn - The function to run in a transaction\n * @returns The return value of the function\n * @public\n */\nexport function transact<T>(fn: () => T): T {\n\tif (inst.currentTransaction) {\n\t\treturn fn()\n\t}\n\treturn transaction(fn)\n}\n\n/**\n * Defers the execution of asynchronous effects until they can be properly handled.\n * This function creates an asynchronous transaction context that batches state updates\n * across async operations while preventing conflicts with synchronous transactions.\n *\n * @example\n * ```ts\n * const data = atom('data', null)\n * const loading = atom('loading', false)\n *\n * await deferAsyncEffects(async () => {\n * loading.set(true)\n * const result = await fetch('/api/data')\n * const json = await result.json()\n * data.set(json)\n * loading.set(false)\n * })\n * ```\n *\n * @param fn - The async function to execute within the deferred context\n * @returns A promise that resolves to the return value of the function\n * @throws Will throw if called during a synchronous transaction\n * @internal\n */\nexport async function deferAsyncEffects<T>(fn: () => Promise<T>) {\n\t// Can't kick off async transactions during a sync transaction because\n\t// the async transaction won't finish until after the sync transaction\n\t// is done.\n\tif (inst.currentTransaction?.isSync) {\n\t\tthrow new Error('deferAsyncEffects cannot be called during a sync transaction')\n\t}\n\n\t// Can't kick off async transactions during a reaction phase at the moment,\n\t// because the transaction stack is cleared after the reaction phase.\n\t// So wait until the path ahead is clear\n\twhile (inst.globalIsReacting) {\n\t\tawait new Promise((r) => queueMicrotask(() => r(null)))\n\t}\n\n\tconst txn = inst.currentTransaction ?? new Transaction(null, false)\n\n\t// don't think this can happen, but just in case\n\tif (txn.isSync) throw new Error('deferAsyncEffects cannot be called during a sync transaction')\n\n\tinst.currentTransaction = txn\n\ttxn.asyncProcessCount++\n\n\tlet result = undefined as T | undefined\n\n\tlet error = undefined as any\n\ttry {\n\t\t// Run the function.\n\t\tresult = await fn()\n\t} catch (e) {\n\t\t// Abort the transaction if the function throws.\n\t\terror = e ?? null\n\t}\n\n\tif (--txn.asyncProcessCount > 0) {\n\t\tif (typeof error !== 'undefined') {\n\t\t\t// If the rollback was triggered, abort the transaction.\n\t\t\tthrow error\n\t\t} else {\n\t\t\treturn result\n\t\t}\n\t}\n\n\tinst.currentTransaction = null\n\n\tif (typeof error !== 'undefined') {\n\t\t// If the rollback was triggered, abort the transaction.\n\t\ttxn.abort()\n\t\tthrow error\n\t} else {\n\t\ttxn.commit()\n\t\treturn result\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["reactors"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/types.ts"],
4
- "sourcesContent": ["import { ArraySet } from './ArraySet'\n\n/** @public */\nexport const RESET_VALUE: unique symbol = Symbol.for('com.tldraw.state/RESET_VALUE')\n\n/** @public */\nexport type RESET_VALUE = typeof RESET_VALUE\n\n/**\n * A Signal is a reactive value container. The value may change over time, and it may keep track of the diffs between sequential values.\n *\n * There are two types of signal:\n *\n * - Atomic signals, created using {@link atom}. These are mutable references to values that can be changed using {@link Atom.set}.\n * - Computed signals, created using `computed`. These are values that are computed from other signals. They are recomputed lazily if their dependencies change.\n *\n * @public\n */\nexport interface Signal<Value, Diff = unknown> {\n\t/**\n\t * The name of the signal. This is used at runtime for debugging and perf profiling only. It does not need to be globally unique.\n\t */\n\tname: string\n\t/**\n\t * The current value of the signal. This is a reactive value, and will update when the signal changes.\n\t * Any computed signal that depends on this signal will be lazily recomputed if this signal changes.\n\t * Any effect that depends on this signal will be rescheduled if this signal changes.\n\t */\n\tget(): Value\n\n\t/**\n\t * The epoch when this signal's value last changed. Note that this is not the same as when the value was last computed.\n\t * A signal may recompute it's value without changing it.\n\t */\n\tlastChangedEpoch: number\n\t/**\n\t * Returns the sequence of diffs between the the value at the given epoch and the current value.\n\t * Returns the `RESET_VALUE` constant if there is not enough information to compute the diff sequence.\n\t * @param epoch - The epoch to get diffs since.\n\t */\n\tgetDiffSince(epoch: number): RESET_VALUE | Diff[]\n\t/**\n\t * Returns the current value of the signal without capturing it as a dependency.\n\t * Use this if you need to retrieve the signal's value in a hot loop where the performance overhead of dependency tracking is too high.\n\t */\n\t__unsafe__getWithoutCapture(ignoreErrors?: boolean): Value\n\t/** @internal */\n\tchildren: ArraySet<Child>\n}\n\n/** @internal */\nexport interface Child {\n\tlastTraversedEpoch: number\n\treadonly parentSet: ArraySet<Signal<any, any>>\n\treadonly parents: Signal<any, any>[]\n\treadonly parentEpochs: number[]\n\treadonly name: string\n\tisActivelyListening: boolean\n\t__debug_ancestor_epochs__: Map<Signal<any, any>, number> | null\n}\n\n/**\n * Computes the diff between the previous and current value.\n *\n * If the diff cannot be computed for whatever reason, it should return {@link state#RESET_VALUE}.\n *\n * @public\n */\nexport type ComputeDiff<Value, Diff> = (\n\tpreviousValue: Value,\n\tcurrentValue: Value,\n\tlastComputedEpoch: number,\n\tcurrentEpoch: number\n) => Diff | RESET_VALUE\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,cAA6B,OAAO,IAAI,8BAA8B;",
4
+ "sourcesContent": ["import { ArraySet } from './ArraySet'\n\n/**\n * A unique symbol used to indicate that a signal's value should be reset or that\n * there is insufficient history to compute diffs between epochs.\n *\n * This value is returned by {@link Signal.getDiffSince} when the requested epoch\n * is too far in the past and the diff sequence cannot be reconstructed.\n *\n * @example\n * ```ts\n * import { atom, getGlobalEpoch, RESET_VALUE } from '@tldraw/state'\n *\n * const count = atom('count', 0, { historyLength: 3 })\n * const oldEpoch = getGlobalEpoch()\n *\n * // Make many changes that exceed history length\n * count.set(1)\n * count.set(2)\n * count.set(3)\n * count.set(4)\n *\n * const diffs = count.getDiffSince(oldEpoch)\n * if (diffs === RESET_VALUE) {\n * console.log('Too many changes, need to reset state')\n * }\n * ```\n *\n * @public\n */\nexport const RESET_VALUE: unique symbol = Symbol.for('com.tldraw.state/RESET_VALUE')\n\n/**\n * Type representing the the unique symbol RESET_VALUE symbol, used in type annotations\n * to indicate when a signal value should be reset or when diff computation\n * cannot proceed due to insufficient history.\n *\n * @public\n */\nexport type RESET_VALUE = typeof RESET_VALUE\n\n/**\n * A reactive value container that can change over time and track diffs between sequential values.\n *\n * Signals are the foundation of the \\@tldraw/state reactive system. They automatically manage\n * dependencies and trigger updates when their values change. Any computed signal or effect\n * that reads from this signal will be automatically recomputed when the signal's value changes.\n *\n * There are two types of signal:\n * - **Atomic signals** - Created using `atom()`. These are mutable containers that can be\n * directly updated using `set()` or `update()` methods.\n * - **Computed signals** - Created using `computed()`. These derive their values from other\n * signals and are automatically recomputed when dependencies change.\n *\n * @example\n * ```ts\n * import { atom, computed } from '@tldraw/state'\n *\n * // Create an atomic signal\n * const count = atom('count', 0)\n *\n * // Create a computed signal that derives from the atom\n * const doubled = computed('doubled', () => count.get() * 2)\n *\n * console.log(doubled.get()) // 0\n * count.set(5)\n * console.log(doubled.get()) // 10\n * ```\n *\n * @public\n */\nexport interface Signal<Value, Diff = unknown> {\n\t/**\n\t * A human-readable identifier for this signal, used primarily for debugging and performance profiling.\n\t *\n\t * The name is displayed in debug output from {@link whyAmIRunning} and other diagnostic tools.\n\t * It does not need to be globally unique within your application.\n\t */\n\tname: string\n\t/**\n\t * Gets the current value of the signal and establishes a dependency relationship.\n\t *\n\t * When called from within a computed signal or effect, this signal will be automatically\n\t * tracked as a dependency. If this signal's value changes, any dependent computations\n\t * or effects will be marked for re-execution.\n\t *\n\t * @returns The current value stored in the signal\n\t */\n\tget(): Value\n\n\t/**\n\t * The global epoch number when this signal's value last changed.\n\t *\n\t * Note that this represents when the value actually changed, not when it was last computed.\n\t * A computed signal may recalculate and produce the same value without changing its epoch.\n\t * This is used internally for dependency tracking and history management.\n\t */\n\tlastChangedEpoch: number\n\t/**\n\t * Gets the sequence of diffs that occurred between a specific epoch and the current state.\n\t *\n\t * This method enables incremental synchronization by providing a list of changes that\n\t * have occurred since a specific point in time. If the requested epoch is too far in\n\t * the past or the signal doesn't have enough history, it returns the unique symbol RESET_VALUE\n\t * to indicate that a full state reset is required.\n\t *\n\t * @param epoch - The epoch timestamp to get diffs since\n\t * @returns An array of diff objects representing changes since the epoch, or the unique symbol RESET_VALUE if insufficient history is available\n\t */\n\tgetDiffSince(epoch: number): RESET_VALUE | Diff[]\n\t/**\n\t * Gets the current value of the signal without establishing a dependency relationship.\n\t *\n\t * This method bypasses the automatic dependency tracking system, making it useful for\n\t * performance-critical code paths where the overhead of dependency capture would be\n\t * problematic. Use with caution as it breaks the reactive guarantees of the system.\n\t *\n\t * **Warning**: This method should only be used when you're certain that you don't need\n\t * the calling context to react to changes in this signal.\n\t *\n\t * @param ignoreErrors - Whether to suppress errors during value retrieval (optional)\n\t * @returns The current value without establishing dependencies\n\t */\n\t__unsafe__getWithoutCapture(ignoreErrors?: boolean): Value\n\t/** @internal */\n\tchildren: ArraySet<Child>\n}\n\n/**\n * Internal interface representing a child node in the signal dependency graph.\n *\n * This interface is used internally by the reactive system to manage dependencies\n * between signals, computed values, and effects. Each child tracks its parent\n * signals and maintains state needed for efficient dependency graph traversal\n * and change propagation.\n *\n * @internal\n */\nexport interface Child {\n\t/**\n\t * The epoch when this child was last traversed during dependency graph updates.\n\t * Used to prevent redundant traversals during change propagation.\n\t */\n\tlastTraversedEpoch: number\n\n\t/**\n\t * Set of parent signals that this child depends on.\n\t * Used for efficient lookup and cleanup operations.\n\t */\n\treadonly parentSet: ArraySet<Signal<any, any>>\n\n\t/**\n\t * Array of parent signals that this child depends on.\n\t * Maintained in parallel with parentSet for ordered access.\n\t */\n\treadonly parents: Signal<any, any>[]\n\n\t/**\n\t * Array of epochs corresponding to each parent signal.\n\t * Used to detect which parents have changed since last computation.\n\t */\n\treadonly parentEpochs: number[]\n\n\t/**\n\t * Human-readable name for this child, used in debugging output.\n\t */\n\treadonly name: string\n\n\t/**\n\t * Whether this child is currently subscribed to change notifications.\n\t * Used to optimize resource usage by unsubscribing inactive dependencies.\n\t */\n\tisActivelyListening: boolean\n\n\t/**\n\t * Debug information tracking ancestor epochs in the dependency graph.\n\t * Only populated in debug builds for diagnostic purposes.\n\t */\n\t__debug_ancestor_epochs__: Map<Signal<any, any>, number> | null\n}\n\n/**\n * A function type that computes the difference between two values of a signal.\n *\n * This function is used to generate incremental diffs that can be applied to\n * reconstruct state changes over time. It's particularly useful for features\n * like undo/redo, synchronization, and change tracking.\n *\n * The function should analyze the previous and current values and return a\n * diff object that represents the change. If the diff cannot be computed\n * (e.g., the values are too different or incompatible), it should return\n * the unique symbol RESET_VALUE to indicate that a full state reset is required.\n *\n * @param previousValue - The previous value of the signal\n * @param currentValue - The current value of the signal\n * @param lastComputedEpoch - The epoch when the previous value was set\n * @param currentEpoch - The epoch when the current value was set\n * @returns A diff object representing the change, or the unique symbol RESET_VALUE if no diff can be computed\n *\n * @example\n * ```ts\n * import { atom, RESET_VALUE } from '@tldraw/state'\n *\n * // Simple numeric diff\n * const numberDiff: ComputeDiff<number, number> = (prev, curr) => curr - prev\n *\n * // Array diff with reset fallback\n * const arrayDiff: ComputeDiff<string[], { added: string[], removed: string[] }> = (prev, curr) => {\n * if (prev.length > 1000 || curr.length > 1000) {\n * return RESET_VALUE // Too complex, force reset\n * }\n * return {\n * added: curr.filter(item => !prev.includes(item)),\n * removed: prev.filter(item => !curr.includes(item))\n * }\n * }\n *\n * const count = atom('count', 0, { computeDiff: numberDiff })\n * ```\n *\n * @public\n */\nexport type ComputeDiff<Value, Diff> = (\n\tpreviousValue: Value,\n\tcurrentValue: Value,\n\tlastComputedEpoch: number,\n\tcurrentEpoch: number\n) => Diff | RESET_VALUE\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BO,MAAM,cAA6B,OAAO,IAAI,8BAA8B;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/warnings.ts"],
4
- "sourcesContent": ["let didWarnComputedGetter = false\n\nexport function logComputedGetterWarning() {\n\tif (didWarnComputedGetter) return\n\tdidWarnComputedGetter = true\n\tconsole.warn(\n\t\t`Using \\`@computed\\` as a decorator for getters is deprecated and will be removed in the near future. Please refactor to use \\`@computed\\` as a decorator for methods.\n\n// Before\n@computed\nget foo() {\n\treturn 'foo'\n}\n\n// After\n@computed\ngetFoo() {\n\treturn 'foo'\n}\n`\n\t)\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAI,wBAAwB;AAErB,SAAS,2BAA2B;AAC1C,MAAI,sBAAuB;AAC3B,0BAAwB;AACxB,UAAQ;AAAA,IACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcD;AACD;",
4
+ "sourcesContent": ["/**\n * Flag to track whether the computed getter deprecation warning has already been shown.\n * Prevents the same warning from being logged multiple times during application runtime.\n *\n * @internal\n */\nlet didWarnComputedGetter = false\n\n/**\n * Logs a deprecation warning for the deprecated `@computed` getter decorator syntax.\n * This function is called internally when the library detects usage of `@computed`\n * on a getter method instead of the recommended method syntax.\n *\n * The warning is only shown once per application session to avoid spam in the console.\n * It provides clear guidance on how to migrate from the deprecated getter syntax\n * to the current method-based approach.\n *\n * @example\n * ```ts\n * // Deprecated pattern that triggers this warning:\n * class MyClass {\n * @computed\n * get value() {\n * return this.someAtom.get()\n * }\n * }\n *\n * // Recommended pattern:\n * class MyClass {\n * @computed\n * getValue() {\n * return this.someAtom.get()\n * }\n * }\n * ```\n *\n * @internal\n */\nexport function logComputedGetterWarning() {\n\tif (didWarnComputedGetter) return\n\tdidWarnComputedGetter = true\n\tconsole.warn(\n\t\t`Using \\`@computed\\` as a decorator for getters is deprecated and will be removed in the near future. Please refactor to use \\`@computed\\` as a decorator for methods.\n\n// Before\n@computed\nget foo() {\n\treturn 'foo'\n}\n\n// After\n@computed\ngetFoo() {\n\treturn 'foo'\n}\n`\n\t)\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,IAAI,wBAAwB;AAgCrB,SAAS,2BAA2B;AAC1C,MAAI,sBAAuB;AAC3B,0BAAwB;AACxB,UAAQ;AAAA,IACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcD;AACD;",
6
6
  "names": []
7
7
  }