jotai-state-tree 1.4.0 → 1.4.2

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.
@@ -42,9 +42,12 @@ var identifierFinalizationRegistry = new FinalizationRegistry(
42
42
  (info) => {
43
43
  const typeMap = identifierRegistry.get(info.typeName);
44
44
  if (typeMap) {
45
- typeMap.delete(info.identifier);
46
- if (typeMap.size === 0) {
47
- identifierRegistry.delete(info.typeName);
45
+ const ref = typeMap.get(info.identifier);
46
+ if (!ref || ref.deref() === void 0) {
47
+ typeMap.delete(info.identifier);
48
+ if (typeMap.size === 0) {
49
+ identifierRegistry.delete(info.typeName);
50
+ }
48
51
  }
49
52
  }
50
53
  }
@@ -71,6 +74,35 @@ function notifyLifecycleChange(node, isAlive2) {
71
74
  listeners.forEach((listener) => listener(isAlive2));
72
75
  }
73
76
  }
77
+ function cloneAndSerialize(value) {
78
+ if (value === null || value === void 0) {
79
+ return value;
80
+ }
81
+ if (hasStateTreeNode(value)) {
82
+ return getSnapshotFromNode(getStateTreeNode(value));
83
+ }
84
+ if (Array.isArray(value)) {
85
+ return value.map(cloneAndSerialize);
86
+ }
87
+ if (typeof value === "object") {
88
+ if (value instanceof Map) {
89
+ const res = {};
90
+ for (const [k, v] of value.entries()) {
91
+ res[k] = cloneAndSerialize(v);
92
+ }
93
+ return res;
94
+ }
95
+ const proto = Object.getPrototypeOf(value);
96
+ if (proto === null || proto === Object.prototype) {
97
+ const res = {};
98
+ for (const [k, v] of Object.entries(value)) {
99
+ res[k] = cloneAndSerialize(v);
100
+ }
101
+ return res;
102
+ }
103
+ }
104
+ return value;
105
+ }
74
106
  var StateTreeNode = class {
75
107
  constructor(type, initialValue, env, parent, pathSegment) {
76
108
  this.$parent = null;
@@ -88,6 +120,8 @@ var StateTreeNode = class {
88
120
  /** Cached snapshot for structural sharing optimization */
89
121
  this.cachedSnapshot = void 0;
90
122
  this.isSnapshotDirty = true;
123
+ /** Strong reference to the instance proxy to prevent GC of active nodes */
124
+ this.instance = null;
91
125
  this.$id = generateNodeId();
92
126
  this.$type = type;
93
127
  this.$env = env ?? parent?.$env;
@@ -108,6 +142,7 @@ var StateTreeNode = class {
108
142
  }
109
143
  /** Set the instance reference */
110
144
  setInstance(instance) {
145
+ this.instance = instance;
111
146
  const entry = nodeRegistry.get(this.$id);
112
147
  if (entry && instance && typeof instance === "object") {
113
148
  entry.instance = new WeakRef(instance);
@@ -115,8 +150,7 @@ var StateTreeNode = class {
115
150
  }
116
151
  /** Get the instance */
117
152
  getInstance() {
118
- const entry = nodeRegistry.get(this.$id);
119
- return entry?.instance?.deref() ?? null;
153
+ return this.instance;
120
154
  }
121
155
  /** Get current value from atom */
122
156
  getValue() {
@@ -222,9 +256,27 @@ var StateTreeNode = class {
222
256
  }
223
257
  /** Notify patch listeners */
224
258
  notifyPatch(patch, reversePatch) {
225
- this.patchListeners.forEach((listener) => listener(patch, reversePatch));
259
+ const serializedPatch = {
260
+ ...patch,
261
+ value: "value" in patch ? cloneAndSerialize(patch.value) : void 0
262
+ };
263
+ if (!("value" in patch)) {
264
+ delete serializedPatch.value;
265
+ }
266
+ const serializedReversePatch = {
267
+ ...reversePatch,
268
+ value: "value" in reversePatch ? cloneAndSerialize(reversePatch.value) : void 0,
269
+ oldValue: "oldValue" in reversePatch ? cloneAndSerialize(reversePatch.oldValue) : void 0
270
+ };
271
+ if (!("value" in reversePatch)) {
272
+ delete serializedReversePatch.value;
273
+ }
274
+ if (!("oldValue" in reversePatch)) {
275
+ delete serializedReversePatch.oldValue;
276
+ }
277
+ this.patchListeners.forEach((listener) => listener(serializedPatch, serializedReversePatch));
226
278
  if (this.$parent) {
227
- this.$parent.notifyPatch(patch, reversePatch);
279
+ this.$parent.notifyPatch(serializedPatch, serializedReversePatch);
228
280
  }
229
281
  }
230
282
  /** Notify snapshot listeners */
@@ -261,6 +313,7 @@ var StateTreeNode = class {
261
313
  /** Destroy this node and all children */
262
314
  destroy() {
263
315
  if (!this.$isAlive) return;
316
+ this.instance = null;
264
317
  lifecycleHookHandlers.runBeforeDestroy?.(this);
265
318
  this.children.forEach((child) => child.destroy());
266
319
  this.children.clear();
@@ -900,6 +953,8 @@ function unfreeze(target) {
900
953
  }
901
954
 
902
955
  // src/undo.ts
956
+ var undoManagersRegistry = /* @__PURE__ */ new WeakMap();
957
+ var timeTravelManagersRegistry = /* @__PURE__ */ new WeakMap();
903
958
  var UndoManager = class {
904
959
  constructor(target, options = {}) {
905
960
  this.historyEntries = [];
@@ -920,6 +975,7 @@ var UndoManager = class {
920
975
  groupByTime: options.groupByTime ?? false,
921
976
  groupingWindow: options.groupingWindow ?? 200
922
977
  };
978
+ undoManagersRegistry.set(target, this);
923
979
  this.disposer = onPatch(target, (patch, reversePatch) => {
924
980
  this.recordPatch(patch, reversePatch);
925
981
  });
@@ -1013,6 +1069,13 @@ var UndoManager = class {
1013
1069
  applyPatch(this.target, entry.patches[i]);
1014
1070
  }
1015
1071
  this.currentIndex--;
1072
+ const tt = timeTravelManagersRegistry.get(this.target);
1073
+ if (tt) {
1074
+ const N = tt.snapshots.length;
1075
+ const M = this.historyEntries.length;
1076
+ const ttIndex = this.currentIndex + 1 + (N - 1 - M);
1077
+ tt.index = Math.max(0, Math.min(N - 1, ttIndex));
1078
+ }
1016
1079
  } finally {
1017
1080
  this.isUndoing = false;
1018
1081
  rootNode.$isApplyingHistory = wasApplying;
@@ -1033,6 +1096,13 @@ var UndoManager = class {
1033
1096
  for (const patch of entry.inversePatches) {
1034
1097
  applyPatch(this.target, patch);
1035
1098
  }
1099
+ const tt = timeTravelManagersRegistry.get(this.target);
1100
+ if (tt) {
1101
+ const N = tt.snapshots.length;
1102
+ const M = this.historyEntries.length;
1103
+ const ttIndex = this.currentIndex + 1 + (N - 1 - M);
1104
+ tt.index = Math.max(0, Math.min(N - 1, ttIndex));
1105
+ }
1036
1106
  } finally {
1037
1107
  this.isRedoing = false;
1038
1108
  rootNode.$isApplyingHistory = wasApplying;
@@ -1086,6 +1156,7 @@ var UndoManager = class {
1086
1156
  }
1087
1157
  }
1088
1158
  dispose() {
1159
+ undoManagersRegistry.delete(this.target);
1089
1160
  if (this.disposer) {
1090
1161
  this.disposer();
1091
1162
  this.disposer = null;
@@ -1112,6 +1183,7 @@ var TimeTravelManager = class {
1112
1183
  this.target = target;
1113
1184
  this.maxSnapshots = options.maxSnapshots ?? 50;
1114
1185
  this.autoRecord = options.autoRecord ?? false;
1186
+ timeTravelManagersRegistry.set(target, this);
1115
1187
  this.record();
1116
1188
  if (this.autoRecord) {
1117
1189
  this.disposer = onPatch(target, () => {
@@ -1193,6 +1265,13 @@ var TimeTravelManager = class {
1193
1265
  try {
1194
1266
  this.index = index;
1195
1267
  applySnapshot(this.target, this.snapshots[index]);
1268
+ const undo = undoManagersRegistry.get(this.target);
1269
+ if (undo) {
1270
+ const N = this.snapshots.length;
1271
+ const M = undo.historyEntries.length;
1272
+ const undoIndex = this.index - 1 - (N - 1 - M);
1273
+ undo.currentIndex = Math.max(-1, Math.min(M - 1, undoIndex));
1274
+ }
1196
1275
  } finally {
1197
1276
  this.isApplying = false;
1198
1277
  rootNode.$isApplyingHistory = wasApplying;
@@ -1210,6 +1289,7 @@ var TimeTravelManager = class {
1210
1289
  this.record();
1211
1290
  }
1212
1291
  dispose() {
1292
+ timeTravelManagersRegistry.delete(this.target);
1213
1293
  if (this.disposer) {
1214
1294
  this.disposer();
1215
1295
  this.disposer = null;
@@ -1302,6 +1382,7 @@ function createActionRecorder(target) {
1302
1382
  export {
1303
1383
  setLifecycleHookHandlers,
1304
1384
  getIsApplyingSnapshotOrPatch,
1385
+ setIsApplyingSnapshotOrPatch,
1305
1386
  getGlobalStore,
1306
1387
  setGlobalStore,
1307
1388
  resetGlobalStore,
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as ISimpleType, a as IType, b as IIdentifierType, c as IIdentifierNumberType, d as ILiteralType, e as IEnumerationType, f as IFrozenType, M as ModelProperties, g as IModelType, h as MixinConfig, i as IMixin, j as IAnyType, k as IArrayType, l as IMapType, m as IOptionalType, n as IMaybeType, o as IMaybeNullType, p as IUnionType, U as UnionOptions, q as ILateType, r as IAnyModelType, R as ReferenceOptions, s as IReferenceType, t as ISafeReferenceType, u as IRefinementType, v as IDisposer, S as SnapshotIn, w as Instance } from './undo-BcBI_BQM.mjs';
2
- export { L as CustomTypeOptions, aG as IActionRecorder, aH as IActionRecording, C as IAnyComplexType, D as IAnyMixin, aE as IHistoryEntry, F as IJsonPatch, y as IMSTArray, z as IMSTMap, G as IReversibleJsonPatch, x as IStateTreeNode, aF as ITimeTravelManager, aC as IUndoManager, aD as IUndoManagerOptions, H as IValidationContext, K as IValidationError, J as IValidationResult, A as ModelInstance, E as ModelSelf, B as SnapshotOut, T as applyPatch, O as applySnapshot, aw as cleanupStaleEntries, ax as clearAllRegistries, aa as clone, aq as cloneDeep, aB as createActionRecorder, aA as createTimeTravelManager, az as createUndoManager, a8 as destroy, a9 as detach, am as findAll, an as findFirst, as as freeze, a2 as getEnv, ag as getGlobalStore, a4 as getIdentifier, af as getMembers, ar as getOrCreatePath, Y as getParent, $ as getParentOfType, a0 as getPath, a1 as getPathParts, av as getRegistryStats, aj as getRelativePath, X as getRoot, N as getSnapshot, ap as getTreeStats, a3 as getType, _ as hasParent, al as haveSameRoot, a5 as isAlive, ak as isAncestor, at as isFrozen, a6 as isRoot, a7 as isStateTreeNode, ao as isValidReference, W as onAction, ay as onLifecycleChange, Q as onPatch, P as onSnapshot, V as recordPatches, ai as resetGlobalStore, ae as resolveIdentifier, ac as resolvePath, ah as setGlobalStore, Z as tryGetParent, ad as tryResolve, au as unfreeze, ab as walk } from './undo-BcBI_BQM.mjs';
1
+ import { I as ISimpleType, a as IType, b as IIdentifierType, c as IIdentifierNumberType, d as ILiteralType, e as IEnumerationType, f as IFrozenType, M as ModelProperties, g as IModelType, h as MixinConfig, i as IMixin, j as IAnyType, k as IArrayType, l as IMapType, m as IOptionalType, n as IMaybeType, o as IMaybeNullType, p as IUnionType, U as UnionOptions, q as ILateType, r as IAnyModelType, R as ReferenceOptions, s as IReferenceType, t as ISafeReferenceType, u as IRefinementType, v as IDisposer, S as SnapshotIn, w as Instance } from './undo-DL1pyOkT.mjs';
2
+ export { L as CustomTypeOptions, aG as IActionRecorder, aH as IActionRecording, C as IAnyComplexType, D as IAnyMixin, aE as IHistoryEntry, F as IJsonPatch, y as IMSTArray, z as IMSTMap, G as IReversibleJsonPatch, x as IStateTreeNode, aF as ITimeTravelManager, aC as IUndoManager, aD as IUndoManagerOptions, H as IValidationContext, K as IValidationError, J as IValidationResult, A as ModelInstance, E as ModelSelf, B as SnapshotOut, T as applyPatch, O as applySnapshot, aw as cleanupStaleEntries, ax as clearAllRegistries, aa as clone, aq as cloneDeep, aB as createActionRecorder, aA as createTimeTravelManager, az as createUndoManager, a8 as destroy, a9 as detach, am as findAll, an as findFirst, as as freeze, a2 as getEnv, ag as getGlobalStore, a4 as getIdentifier, af as getMembers, ar as getOrCreatePath, Y as getParent, $ as getParentOfType, a0 as getPath, a1 as getPathParts, av as getRegistryStats, aj as getRelativePath, X as getRoot, N as getSnapshot, ap as getTreeStats, a3 as getType, _ as hasParent, al as haveSameRoot, a5 as isAlive, ak as isAncestor, at as isFrozen, a6 as isRoot, a7 as isStateTreeNode, ao as isValidReference, W as onAction, ay as onLifecycleChange, Q as onPatch, P as onSnapshot, V as recordPatches, ai as resetGlobalStore, ae as resolveIdentifier, ac as resolvePath, ah as setGlobalStore, Z as tryGetParent, ad as tryResolve, au as unfreeze, ab as walk } from './undo-DL1pyOkT.mjs';
3
3
  import 'jotai/vanilla/internals';
4
4
  import 'jotai';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { I as ISimpleType, a as IType, b as IIdentifierType, c as IIdentifierNumberType, d as ILiteralType, e as IEnumerationType, f as IFrozenType, M as ModelProperties, g as IModelType, h as MixinConfig, i as IMixin, j as IAnyType, k as IArrayType, l as IMapType, m as IOptionalType, n as IMaybeType, o as IMaybeNullType, p as IUnionType, U as UnionOptions, q as ILateType, r as IAnyModelType, R as ReferenceOptions, s as IReferenceType, t as ISafeReferenceType, u as IRefinementType, v as IDisposer, S as SnapshotIn, w as Instance } from './undo-BcBI_BQM.js';
2
- export { L as CustomTypeOptions, aG as IActionRecorder, aH as IActionRecording, C as IAnyComplexType, D as IAnyMixin, aE as IHistoryEntry, F as IJsonPatch, y as IMSTArray, z as IMSTMap, G as IReversibleJsonPatch, x as IStateTreeNode, aF as ITimeTravelManager, aC as IUndoManager, aD as IUndoManagerOptions, H as IValidationContext, K as IValidationError, J as IValidationResult, A as ModelInstance, E as ModelSelf, B as SnapshotOut, T as applyPatch, O as applySnapshot, aw as cleanupStaleEntries, ax as clearAllRegistries, aa as clone, aq as cloneDeep, aB as createActionRecorder, aA as createTimeTravelManager, az as createUndoManager, a8 as destroy, a9 as detach, am as findAll, an as findFirst, as as freeze, a2 as getEnv, ag as getGlobalStore, a4 as getIdentifier, af as getMembers, ar as getOrCreatePath, Y as getParent, $ as getParentOfType, a0 as getPath, a1 as getPathParts, av as getRegistryStats, aj as getRelativePath, X as getRoot, N as getSnapshot, ap as getTreeStats, a3 as getType, _ as hasParent, al as haveSameRoot, a5 as isAlive, ak as isAncestor, at as isFrozen, a6 as isRoot, a7 as isStateTreeNode, ao as isValidReference, W as onAction, ay as onLifecycleChange, Q as onPatch, P as onSnapshot, V as recordPatches, ai as resetGlobalStore, ae as resolveIdentifier, ac as resolvePath, ah as setGlobalStore, Z as tryGetParent, ad as tryResolve, au as unfreeze, ab as walk } from './undo-BcBI_BQM.js';
1
+ import { I as ISimpleType, a as IType, b as IIdentifierType, c as IIdentifierNumberType, d as ILiteralType, e as IEnumerationType, f as IFrozenType, M as ModelProperties, g as IModelType, h as MixinConfig, i as IMixin, j as IAnyType, k as IArrayType, l as IMapType, m as IOptionalType, n as IMaybeType, o as IMaybeNullType, p as IUnionType, U as UnionOptions, q as ILateType, r as IAnyModelType, R as ReferenceOptions, s as IReferenceType, t as ISafeReferenceType, u as IRefinementType, v as IDisposer, S as SnapshotIn, w as Instance } from './undo-DL1pyOkT.js';
2
+ export { L as CustomTypeOptions, aG as IActionRecorder, aH as IActionRecording, C as IAnyComplexType, D as IAnyMixin, aE as IHistoryEntry, F as IJsonPatch, y as IMSTArray, z as IMSTMap, G as IReversibleJsonPatch, x as IStateTreeNode, aF as ITimeTravelManager, aC as IUndoManager, aD as IUndoManagerOptions, H as IValidationContext, K as IValidationError, J as IValidationResult, A as ModelInstance, E as ModelSelf, B as SnapshotOut, T as applyPatch, O as applySnapshot, aw as cleanupStaleEntries, ax as clearAllRegistries, aa as clone, aq as cloneDeep, aB as createActionRecorder, aA as createTimeTravelManager, az as createUndoManager, a8 as destroy, a9 as detach, am as findAll, an as findFirst, as as freeze, a2 as getEnv, ag as getGlobalStore, a4 as getIdentifier, af as getMembers, ar as getOrCreatePath, Y as getParent, $ as getParentOfType, a0 as getPath, a1 as getPathParts, av as getRegistryStats, aj as getRelativePath, X as getRoot, N as getSnapshot, ap as getTreeStats, a3 as getType, _ as hasParent, al as haveSameRoot, a5 as isAlive, ak as isAncestor, at as isFrozen, a6 as isRoot, a7 as isStateTreeNode, ao as isValidReference, W as onAction, ay as onLifecycleChange, Q as onPatch, P as onSnapshot, V as recordPatches, ai as resetGlobalStore, ae as resolveIdentifier, ac as resolvePath, ah as setGlobalStore, Z as tryGetParent, ad as tryResolve, au as unfreeze, ab as walk } from './undo-DL1pyOkT.js';
3
3
  import 'jotai/vanilla/internals';
4
4
  import 'jotai';
5
5
 
package/dist/index.js CHANGED
@@ -473,9 +473,12 @@ var identifierFinalizationRegistry = new FinalizationRegistry(
473
473
  (info) => {
474
474
  const typeMap = identifierRegistry.get(info.typeName);
475
475
  if (typeMap) {
476
- typeMap.delete(info.identifier);
477
- if (typeMap.size === 0) {
478
- identifierRegistry.delete(info.typeName);
476
+ const ref = typeMap.get(info.identifier);
477
+ if (!ref || ref.deref() === void 0) {
478
+ typeMap.delete(info.identifier);
479
+ if (typeMap.size === 0) {
480
+ identifierRegistry.delete(info.typeName);
481
+ }
479
482
  }
480
483
  }
481
484
  }
@@ -502,6 +505,35 @@ function notifyLifecycleChange(node, isAlive2) {
502
505
  listeners.forEach((listener) => listener(isAlive2));
503
506
  }
504
507
  }
508
+ function cloneAndSerialize(value) {
509
+ if (value === null || value === void 0) {
510
+ return value;
511
+ }
512
+ if (hasStateTreeNode(value)) {
513
+ return getSnapshotFromNode(getStateTreeNode(value));
514
+ }
515
+ if (Array.isArray(value)) {
516
+ return value.map(cloneAndSerialize);
517
+ }
518
+ if (typeof value === "object") {
519
+ if (value instanceof Map) {
520
+ const res = {};
521
+ for (const [k, v] of value.entries()) {
522
+ res[k] = cloneAndSerialize(v);
523
+ }
524
+ return res;
525
+ }
526
+ const proto = Object.getPrototypeOf(value);
527
+ if (proto === null || proto === Object.prototype) {
528
+ const res = {};
529
+ for (const [k, v] of Object.entries(value)) {
530
+ res[k] = cloneAndSerialize(v);
531
+ }
532
+ return res;
533
+ }
534
+ }
535
+ return value;
536
+ }
505
537
  var StateTreeNode = class {
506
538
  constructor(type, initialValue, env, parent, pathSegment) {
507
539
  this.$parent = null;
@@ -519,6 +551,8 @@ var StateTreeNode = class {
519
551
  /** Cached snapshot for structural sharing optimization */
520
552
  this.cachedSnapshot = void 0;
521
553
  this.isSnapshotDirty = true;
554
+ /** Strong reference to the instance proxy to prevent GC of active nodes */
555
+ this.instance = null;
522
556
  this.$id = generateNodeId();
523
557
  this.$type = type;
524
558
  this.$env = env ?? parent?.$env;
@@ -539,6 +573,7 @@ var StateTreeNode = class {
539
573
  }
540
574
  /** Set the instance reference */
541
575
  setInstance(instance) {
576
+ this.instance = instance;
542
577
  const entry = nodeRegistry.get(this.$id);
543
578
  if (entry && instance && typeof instance === "object") {
544
579
  entry.instance = new WeakRef(instance);
@@ -546,8 +581,7 @@ var StateTreeNode = class {
546
581
  }
547
582
  /** Get the instance */
548
583
  getInstance() {
549
- const entry = nodeRegistry.get(this.$id);
550
- return entry?.instance?.deref() ?? null;
584
+ return this.instance;
551
585
  }
552
586
  /** Get current value from atom */
553
587
  getValue() {
@@ -653,9 +687,27 @@ var StateTreeNode = class {
653
687
  }
654
688
  /** Notify patch listeners */
655
689
  notifyPatch(patch, reversePatch) {
656
- this.patchListeners.forEach((listener) => listener(patch, reversePatch));
690
+ const serializedPatch = {
691
+ ...patch,
692
+ value: "value" in patch ? cloneAndSerialize(patch.value) : void 0
693
+ };
694
+ if (!("value" in patch)) {
695
+ delete serializedPatch.value;
696
+ }
697
+ const serializedReversePatch = {
698
+ ...reversePatch,
699
+ value: "value" in reversePatch ? cloneAndSerialize(reversePatch.value) : void 0,
700
+ oldValue: "oldValue" in reversePatch ? cloneAndSerialize(reversePatch.oldValue) : void 0
701
+ };
702
+ if (!("value" in reversePatch)) {
703
+ delete serializedReversePatch.value;
704
+ }
705
+ if (!("oldValue" in reversePatch)) {
706
+ delete serializedReversePatch.oldValue;
707
+ }
708
+ this.patchListeners.forEach((listener) => listener(serializedPatch, serializedReversePatch));
657
709
  if (this.$parent) {
658
- this.$parent.notifyPatch(patch, reversePatch);
710
+ this.$parent.notifyPatch(serializedPatch, serializedReversePatch);
659
711
  }
660
712
  }
661
713
  /** Notify snapshot listeners */
@@ -692,6 +744,7 @@ var StateTreeNode = class {
692
744
  /** Destroy this node and all children */
693
745
  destroy() {
694
746
  if (!this.$isAlive) return;
747
+ this.instance = null;
695
748
  lifecycleHookHandlers.runBeforeDestroy?.(this);
696
749
  this.children.forEach((child) => child.destroy());
697
750
  this.children.clear();
@@ -1883,6 +1936,9 @@ var ModelType = class _ModelType {
1883
1936
  }
1884
1937
  return descriptor.value;
1885
1938
  }
1939
+ if (propStr === "toggle") {
1940
+ console.log("PROXY GET toggle:", propStr, "in allActions:", propStr in allActions, "keys:", Object.keys(allActions), "node alive:", node.$isAlive);
1941
+ }
1886
1942
  if (propStr in allActions) {
1887
1943
  return allActions[propStr];
1888
1944
  }
@@ -3713,6 +3769,8 @@ function createWithDefaults(type, snapshot = {}, env) {
3713
3769
  }
3714
3770
 
3715
3771
  // src/undo.ts
3772
+ var undoManagersRegistry = /* @__PURE__ */ new WeakMap();
3773
+ var timeTravelManagersRegistry = /* @__PURE__ */ new WeakMap();
3716
3774
  var UndoManager = class {
3717
3775
  constructor(target, options = {}) {
3718
3776
  this.historyEntries = [];
@@ -3733,6 +3791,7 @@ var UndoManager = class {
3733
3791
  groupByTime: options.groupByTime ?? false,
3734
3792
  groupingWindow: options.groupingWindow ?? 200
3735
3793
  };
3794
+ undoManagersRegistry.set(target, this);
3736
3795
  this.disposer = onPatch(target, (patch, reversePatch) => {
3737
3796
  this.recordPatch(patch, reversePatch);
3738
3797
  });
@@ -3826,6 +3885,13 @@ var UndoManager = class {
3826
3885
  applyPatch(this.target, entry.patches[i]);
3827
3886
  }
3828
3887
  this.currentIndex--;
3888
+ const tt = timeTravelManagersRegistry.get(this.target);
3889
+ if (tt) {
3890
+ const N = tt.snapshots.length;
3891
+ const M = this.historyEntries.length;
3892
+ const ttIndex = this.currentIndex + 1 + (N - 1 - M);
3893
+ tt.index = Math.max(0, Math.min(N - 1, ttIndex));
3894
+ }
3829
3895
  } finally {
3830
3896
  this.isUndoing = false;
3831
3897
  rootNode.$isApplyingHistory = wasApplying;
@@ -3846,6 +3912,13 @@ var UndoManager = class {
3846
3912
  for (const patch of entry.inversePatches) {
3847
3913
  applyPatch(this.target, patch);
3848
3914
  }
3915
+ const tt = timeTravelManagersRegistry.get(this.target);
3916
+ if (tt) {
3917
+ const N = tt.snapshots.length;
3918
+ const M = this.historyEntries.length;
3919
+ const ttIndex = this.currentIndex + 1 + (N - 1 - M);
3920
+ tt.index = Math.max(0, Math.min(N - 1, ttIndex));
3921
+ }
3849
3922
  } finally {
3850
3923
  this.isRedoing = false;
3851
3924
  rootNode.$isApplyingHistory = wasApplying;
@@ -3899,6 +3972,7 @@ var UndoManager = class {
3899
3972
  }
3900
3973
  }
3901
3974
  dispose() {
3975
+ undoManagersRegistry.delete(this.target);
3902
3976
  if (this.disposer) {
3903
3977
  this.disposer();
3904
3978
  this.disposer = null;
@@ -3925,6 +3999,7 @@ var TimeTravelManager = class {
3925
3999
  this.target = target;
3926
4000
  this.maxSnapshots = options.maxSnapshots ?? 50;
3927
4001
  this.autoRecord = options.autoRecord ?? false;
4002
+ timeTravelManagersRegistry.set(target, this);
3928
4003
  this.record();
3929
4004
  if (this.autoRecord) {
3930
4005
  this.disposer = onPatch(target, () => {
@@ -4006,6 +4081,13 @@ var TimeTravelManager = class {
4006
4081
  try {
4007
4082
  this.index = index;
4008
4083
  applySnapshot(this.target, this.snapshots[index]);
4084
+ const undo = undoManagersRegistry.get(this.target);
4085
+ if (undo) {
4086
+ const N = this.snapshots.length;
4087
+ const M = undo.historyEntries.length;
4088
+ const undoIndex = this.index - 1 - (N - 1 - M);
4089
+ undo.currentIndex = Math.max(-1, Math.min(M - 1, undoIndex));
4090
+ }
4009
4091
  } finally {
4010
4092
  this.isApplying = false;
4011
4093
  rootNode.$isApplyingHistory = wasApplying;
@@ -4023,6 +4105,7 @@ var TimeTravelManager = class {
4023
4105
  this.record();
4024
4106
  }
4025
4107
  dispose() {
4108
+ timeTravelManagersRegistry.delete(this.target);
4026
4109
  if (this.disposer) {
4027
4110
  this.disposer();
4028
4111
  this.disposer = null;
package/dist/index.mjs CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  tryResolve,
63
63
  unfreeze,
64
64
  walk
65
- } from "./chunk-MSLAD5CJ.mjs";
65
+ } from "./chunk-Q6QPBXHH.mjs";
66
66
 
67
67
  // src/primitives.ts
68
68
  function createSimpleType(name, validator, defaultValue) {
@@ -895,6 +895,9 @@ var ModelType = class _ModelType {
895
895
  }
896
896
  return descriptor.value;
897
897
  }
898
+ if (propStr === "toggle") {
899
+ console.log("PROXY GET toggle:", propStr, "in allActions:", propStr in allActions, "keys:", Object.keys(allActions), "node alive:", node.$isAlive);
900
+ }
898
901
  if (propStr in allActions) {
899
902
  return allActions[propStr];
900
903
  }
package/dist/react.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React, { ComponentType, FC, ReactNode } from 'react';
2
- import { ag as getGlobalStore, aD as IUndoManagerOptions, aC as IUndoManager, aF as ITimeTravelManager } from './undo-BcBI_BQM.mjs';
3
- export { aI as hasStateTreeNode } from './undo-BcBI_BQM.mjs';
2
+ import { ag as getGlobalStore, aD as IUndoManagerOptions, aC as IUndoManager, aF as ITimeTravelManager } from './undo-DL1pyOkT.mjs';
3
+ export { aI as hasStateTreeNode } from './undo-DL1pyOkT.mjs';
4
4
  import 'jotai/vanilla/internals';
5
5
  import 'jotai';
6
6
 
package/dist/react.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React, { ComponentType, FC, ReactNode } from 'react';
2
- import { ag as getGlobalStore, aD as IUndoManagerOptions, aC as IUndoManager, aF as ITimeTravelManager } from './undo-BcBI_BQM.js';
3
- export { aI as hasStateTreeNode } from './undo-BcBI_BQM.js';
2
+ import { ag as getGlobalStore, aD as IUndoManagerOptions, aC as IUndoManager, aF as ITimeTravelManager } from './undo-DL1pyOkT.js';
3
+ export { aI as hasStateTreeNode } from './undo-DL1pyOkT.js';
4
4
  import 'jotai/vanilla/internals';
5
5
  import 'jotai';
6
6